From 240d23ec41ee51c72a69fda93148cb534a6688ec Mon Sep 17 00:00:00 2001 From: Samuel Hoffman Date: Wed, 5 Aug 2020 22:18:50 -0400 Subject: [PATCH] vectorized meta fair and removed unused code --- .../inprocessing/celisMeta/FalseDiscovery.py | 205 ++-- .../inprocessing/celisMeta/General.py | 347 ++----- .../inprocessing/celisMeta/StatisticalRate.py | 218 ++-- .../inprocessing/celisMeta/__init__.py | 1 - .../inprocessing/celisMeta/utils.py | 489 --------- .../inprocessing/meta_fair_classifier.py | 35 +- examples/demo_meta_classifier.ipynb | 928 +++++------------- tests/test_meta_classifier.py | 84 +- 8 files changed, 523 insertions(+), 1784 deletions(-) delete mode 100644 aif360/algorithms/inprocessing/celisMeta/utils.py diff --git a/aif360/algorithms/inprocessing/celisMeta/FalseDiscovery.py b/aif360/algorithms/inprocessing/celisMeta/FalseDiscovery.py index 674c3b27..252f68d1 100644 --- a/aif360/algorithms/inprocessing/celisMeta/FalseDiscovery.py +++ b/aif360/algorithms/inprocessing/celisMeta/FalseDiscovery.py @@ -1,151 +1,64 @@ -from __future__ import division - -import os,sys -from scipy.stats import multivariate_normal -import scipy.stats as st import numpy as np -import math - -import site -site.addsitedir('.') -from .General import * -from . import utils as ut +from aif360.algorithms.inprocessing.celisMeta.General import General class FalseDiscovery(General): - - def getExpectedGrad(self, dist_params, params, samples, mu, z_0, z_1, a, b): - u_1, u_2, l_1, l_2 = params[0], params[1], params[2], params[3] - a, b = a[0], b[0] - res1 = [] - res2 = [] - res3 = [] - res4 = [] - for x in samples: - temp = np.append(np.append(x, 1), 1) - prob_1_1 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, -1), 1) - prob_m1_1 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, 1), 0) - prob_1_0 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, -1), 0) - prob_m1_0 = ut.getProbability(dist_params, temp) - - - prob_y_1 = (prob_1_1 + prob_1_0) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - #print(prob_y_1) - - prob_z_0 = (prob_m1_0 + prob_1_0) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - prob_z_1 = (prob_m1_1 + prob_1_1) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - - probc_m1_0 = prob_m1_0 / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - probc_m1_1 = prob_m1_1 / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - - c_0 = prob_y_1 - 0.5 - c_1 = u_1 * (probc_m1_0 - a*prob_z_0) + u_2 * (probc_m1_1 - a*prob_z_1) - c_2 = l_1 * (- probc_m1_0 + b*prob_z_0) + l_2 * (- probc_m1_1 + b*prob_z_1) - - t = math.sqrt((c_0 + c_1 + c_2)*(c_0 + c_1 + c_2) + mu*mu) - t1 = (c_0 + c_1 + c_2) * (probc_m1_0 - a*prob_z_0)/t - t2 = (c_0 + c_1 + c_2) * (probc_m1_1 - a*prob_z_1)/t - t3 = (c_0 + c_1 + c_2) * (- probc_m1_0 + b*prob_z_0)/t - t4 = (c_0 + c_1 + c_2) * (- probc_m1_1 + b*prob_z_1)/t - #print(t1,t2) - res1.append(t1) - res2.append(t2) - res3.append(t3) - res4.append(t4) - - return [np.mean(res1), np.mean(res2), np.mean(res3), np.mean(res4)] - - def getValueForX(self, dist_params, a,b, params, samples, z_0, z_1, x, flag): - u_1, u_2, l_1, l_2 = params[0], params[1], params[2], params[3] - #print (params) - a, b = a[0], b[0] - - temp = np.append(np.append(x, 1), 1) - prob_1_1 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, -1), 1) - prob_m1_1 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, 1), 0) - prob_1_0 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, -1), 0) - prob_m1_0 = ut.getProbability(dist_params, temp) - - if (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) == 0: - print("Probability is 0.\n") - return 0 - - prob_y_1 = (prob_1_1 + prob_1_0) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - #print(prob_y_1) - - prob_z_0 = (prob_m1_0 + prob_1_0) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - prob_z_1 = (prob_m1_1 + prob_1_1) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - - - probc_m1_0 = prob_m1_0 / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - probc_m1_1 = prob_m1_1 / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - - c_0 = prob_y_1 - 0.5 - c_1 = u_1 * (probc_m1_0 - a*prob_z_0) + u_2 * (probc_m1_1 - a*prob_z_1) - c_2 = l_1 * (- probc_m1_0 + b*prob_z_0) + l_2 * (- probc_m1_1 + b*prob_z_1) - if flag==1: - print(c_0, c_1, c_2, prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - - # c_1 = prob_z_0/z_0 - # c_2 = prob_z_1/z_1 - - t = c_0 + c_1 + c_2 - return t - - def getFuncValue(self, dist_params, a,b, params, samples, z_0, z_1): - res = [] - for x in samples: - t = abs(self.getValueForX(dist_params, a,b, params, samples, z_0, z_1, x, 0)) - res.append(t) - - exp = np.mean(res) - return exp - - def getNumOfParams(self): - return 4 - - def getGamma(self, y_test, y_res, x_control_test): - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - - if result == 1 and x_control_test[j] == 0: - z1_0 += 1 - if result == 1 and x_control_test[j] == 1: - z1_1 += 1 - - actual = y_test[j] - if result == 1 and actual == -1 and x_control_test[j] == 0: - pos_0 += 1 - if result == 1 and actual == -1 and x_control_test[j] == 1: - pos_1 += 1 - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - return 0 - else: - return min(pos_0/pos_1 , pos_1/pos_0) - - -if __name__ == '__main__': - obj = FalseDiscovery() - obj.testPreprocessedData() - #obj.testSyntheticData() + def getExpectedGrad(self, dist, a, b, params, samples, mu, z_prior): + t, probc_m1_0, probc_m1_1, prob_z_0, prob_z_1 = self.getValueForX(dist, + a, b, params, z_prior, samples, return_probs=True) + res = np.vstack([probc_m1_0 - a*prob_z_0, + probc_m1_1 - a*prob_z_1, + -probc_m1_0 + b*prob_z_0, + -probc_m1_1 + b*prob_z_1]) + res *= t / np.sqrt(t**2 + mu**2) + return np.mean(res, axis=1) + + def getValueForX(self, dist, a, b, params, z_prior, x, return_probs=False): + u_1, u_2, l_1, l_2 = params + z_0, z_1 = 1-z_prior, z_prior + + pos = np.ones(len(x)) + prob_1_1 = self.prob(dist, np.c_[x, pos, pos]) + prob_m1_1 = self.prob(dist, np.c_[x, -pos, pos]) + prob_1_0 = self.prob(dist, np.c_[x, pos, np.zeros(len(x))]) + prob_m1_0 = self.prob(dist, np.c_[x, -pos, np.zeros(len(x))]) + + total = prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1 + # if total == 0: + # return 0 + + prob_y_1 = (prob_1_1 + prob_1_0) / total + prob_z_0 = (prob_m1_0 + prob_1_0) / total + prob_z_1 = (prob_m1_1 + prob_1_1) / total + + probc_m1_0 = prob_m1_0 / total + probc_m1_1 = prob_m1_1 / total + + c_0 = prob_y_1 - 0.5 + c_1 = u_1*(probc_m1_0 - a*prob_z_0) + u_2*(probc_m1_1 - a*prob_z_1) + c_2 = l_1*(-probc_m1_0 + b*prob_z_0) + l_2*(-probc_m1_1 + b*prob_z_1) + + t = c_0 + c_1 + c_2 + if return_probs: + return t, probc_m1_0, probc_m1_1, prob_z_0, prob_z_1 + return t + + def getFuncValue(self, dist, a, b, params, samples, z_prior): + return np.mean(np.abs(self.getValueForX(dist, a, b, params, z_prior, + samples))) + + @property + def num_params(self): + return 4 + + def gamma(self, y_true, y_pred, sens): + pos_0 = y_pred[sens == 0] == 1 + pos_1 = y_pred[sens == 1] == 1 + if np.sum(pos_0) == 0 or np.sum(pos_1) == 0: + return 0 + fdr_0 = np.sum(pos_0 & (y_true[sens == 0] == -1)) / np.sum(pos_0) + fdr_1 = np.sum(pos_1 & (y_true[sens == 1] == -1)) / np.sum(pos_1) + if fdr_0 == 0 or fdr_1 == 0: + return 0 + return min(fdr_0/fdr_1, fdr_1/fdr_0) diff --git a/aif360/algorithms/inprocessing/celisMeta/General.py b/aif360/algorithms/inprocessing/celisMeta/General.py index a85f6cd4..870fbfcb 100644 --- a/aif360/algorithms/inprocessing/celisMeta/General.py +++ b/aif360/algorithms/inprocessing/celisMeta/General.py @@ -1,242 +1,109 @@ -from __future__ import division +from abc import ABC, abstractmethod +from functools import partial -import os,sys -from scipy.stats import multivariate_normal -import scipy.stats as st import numpy as np -import math -from sklearn.mixture import GaussianMixture -import logging -from . import utils as ut - -# This is the class with the general functions of the algorithm. -# For different fairness metrics, the objective function of the optimization problem is different and hence needs different implementations. -# The fairness-metric specific methods need to extend this class and implement the necessary functions -class General: - - # Used in gradient descent algorithm. Returns the value of gradient at any step. - def getExpectedGrad(self, dist_params, params, samples, mu, z_0, z_1, a, b): - raise NotImplementedError("Expected gradient function not implemented") - return [] - - # Returns the threshold value at any point. - def getValueForX(self, dist_params, a,b, params, samples, z_0, z_1, x, flag): - raise NotImplementedError("GetValueForX function not implemented") - return 0 - - # Returns the value of the objective function for given parameters. - def getFuncValue(self, dist_params, a,b, params, samples, z_0, z_1): - raise NotImplementedError("Value function not implemented") - return 0 - - def getNumOfParams(self): - raise NotImplementedError("Specify number of params") - return 0 - - def getRange(self, eps, tau): - span = [] - L = math.ceil(tau/eps) - for i in range(1, int(L+1), 10): - a = (i-1) * eps - b = (i) * eps / tau - if b > 1: - b = 1.0 - - span.append(([a, -1],[b, -1])) - return span - - def getGamma(self, y_test, y_res, x_control_test): - raise NotImplementedError("Gamma function not implemented") - return 0 - - def getStartParams(self, i): - num = self.getNumOfParams() - return [i] * num - - # Gradient Descent implementation for the optimizing the objective function. - # Note that one can alternately also use packages like CVXPY here. - # Here we use decaying step size. For certain objectives, constant step size might be better. - def gradientDescent(self, dist_params, a, b, samples, z_0, z_1): - mu = 0.01 - minVal = 100000000 - size = self.getNumOfParams() - - minParam = [0] * size - - for i in range(1,10): - params = self.getStartParams(i) - for k in range(1,50): - grad = self.getExpectedGrad(dist_params, params, samples, mu, z_0, z_1, a, b) - for j in range(0, len(params)): - params[j] = params[j] - 1/k * grad[j] - funcVal = self.getFuncValue(dist_params, a,b, params, samples, z_0, z_1) - if funcVal < minVal: - minVal, minParam = funcVal, params - - return minParam - - # Returns the model given the training data and input tau. - def getModel(self, tau, x_train, y_train, x_control_train): - if tau == 0: - return self.getUnbiasedModel(x_train, y_train, x_control_train) - - dist_params, dist_params_train = ut.getDistribution(x_train, y_train, x_control_train) - eps = 0.01 - L = math.ceil(tau/eps) - z_1 = sum(x_control_train)/(float(len(x_control_train))) - z_0 = 1 - z_1 - p, q = [0,0],[0,0] - paramsOpt, samples = [], [] - maxAcc = 0 - maxGamma = 0 - - span = self.getRange(eps, tau) - for (a,b) in span: - acc, gamma = 0, 0 - #print("-----",a,b) - samples = ut.getRandomSamples(dist_params_train) - - #try : - params = self.gradientDescent(dist_params, a, b, samples, z_0, z_1) - #print(params) - y_res = [] - - for x in x_train: - t = self.getValueForX(dist_params, a,b, params, samples, z_0, z_1, x, 0) - if t > 0 : - y_res.append(1) - else: - y_res.append(-1) - - acc = ut.getAccuracy(y_train, y_res) - gamma = self.getGamma(y_train, y_res, x_control_train) - #print(acc, gamma) - - if maxAcc < acc and gamma >= tau - 0.2: - maxGamma = gamma - maxAcc = acc - p = a - q = b - paramsOpt = params - - print("Training Accuracy: ", maxAcc, ", Training gamma: ", maxGamma) - def model(x): - return self.getValueForX(dist_params, p, q, paramsOpt, samples, z_0, z_1, x, 0) - - return model - - def getUnbiasedModel(self, x_train, y_train, x_control_train): - dist_params, dist_params_train = ut.getDistribution(x_train, y_train, x_control_train) - eps = 0.01 - z_1 = sum(x_control_train)/(float(len(x_control_train))) - z_0 = 1 - z_1 - p, q = [0,0],[0,0] - params = [0]*self.getNumOfParams() - samples = ut.getRandomSamples(dist_params_train) - - def model(x): - return self.getValueForX(dist_params, p, q, params, samples, z_0, z_1, x, 0) - - return model - - def processGivenData(self, tau, x_train, y_train, x_control_train, x_test, y_test, x_control_test, dist_params, dist_params_train): - model = self.getModel(tau, x_train, y_train, x_control_train) - - y_test_res = [] - for x in x_test: - #t = self.getValueForX(dist_params, p, q, paramsOpt, samples, z_0, z_1, x, 0) - t = model(x) - if t > 0 : - y_test_res.append(1) - else: - y_test_res.append(-1) - #f.write(str(tau) + " " + str(self.getGamma(y_test, y_test_res, x_control_test)) + " " + str(ut.getAccuracy(y_test, y_test_res)) + "\n") - return y_test_res - - def test_given_data(self, x_train, y_train, x_control_train, x_test, y_test, x_control_test, sensitive_attrs, tau): - attr = sensitive_attrs[0] - x_control_train = x_control_train[attr] - x_control_test = x_control_test[attr] - - l = len(y_train) - - - #print(mean, cov) - - return self.processGivenData(tau, x_train, y_train, x_control_train, x_test, y_test, x_control_test, [], []) - - global getData - - def testPreprocessedData(self): - x_train, y_train, x_control_train, x_control_test, x_test, y_test = ut.getData() - #checkNormalFit(x_train, y_train, x_control_train) - - for i in range(1,11): - try : - tau = i/10.0 - print("Tau : ", tau) - y_res = self.processGivenData(tau, x_train, y_train, x_control_train, x_test, y_test, x_control_test, [], []) - ut.getStats(y_test, y_res, x_control_test) - print("\n") - except Exception as e: - logging.exception(str(tau) + " failed\n" + str(e)) - - def testSyntheticData(self): - #A,S,F = [],[],[] - x_train, y_train, x_control_train, x_control_test, x_test, y_test = ut.getData() - dist_params, dist_params_train = ut.getDistribution(x_train, y_train, x_control_train) - - mean, cov, meanT, covT = dist_params["mean"], dist_params["cov"], dist_params_train["mean"], dist_params_train["cov"] - #print(mean) - meanN = [0] * len(mean) - covN = np.identity(len(mean)) - - #clf = GaussianMixture(n_components=2, covariance_type='full') - means = [mean, meanN] - covariances = [cov, covN] - lw = float(sys.argv[2]) - weights = [1-lw, lw] - - #for i in range(0,4): - LR, LE = len(y_train), len(y_test) - train, test = [],[] - for i in range(0, LR): - j = np.random.choice([0,1], p=weights) - seed = np.random.randint(10) - train.append(multivariate_normal(means[j], covariances[j], allow_singular=1).rvs(size=1, random_state=seed)) - for i in range(0, LE): - j = np.random.choice([0,1], p=weights) - seed = np.random.randint(10) - test.append(multivariate_normal(means[j], covariances[j], allow_singular=1).rvs(size=1, random_state=seed)) - - x_train, y_train, x_control_train = [], [], [] - for t in train: - x_train.append(t[:-2]) - if t[len(t)-2] < 0: - y_train.append(-1) - else: - y_train.append(1) - #y_train.append(t[len(t)-2]) - if t[len(t)-1] < 0.5: - x_control_train.append(0) - else: - x_control_train.append(1) - - x_control_test, x_test, y_test = [], [], [] - for t in test: - x_test.append(t[:-2]) - if t[len(t)-2] < 0: - y_test.append(-1) - else: - y_test.append(1) - if t[len(t)-1] < 0.5: - x_control_test.append(0) - else: - x_control_test.append(1) - - #print(x_train, y_train, x_control_train) - y_res = self.processGivenData(0.9, x_train, y_train, x_control_train, x_test, y_test, x_control_test, dist_params, dist_params_train) - acc, sr, fdr = ut.getStats(y_test, y_res, x_control_test) - print("Acc: ", acc, " SR: ", sr, " FDR: ", fdr) - - #print("\n", np.mean(A), np.std(A), np.mean(S), np.std(S), np.mean(F), np.std(F)) +from scipy.stats import multivariate_normal +from sklearn.metrics import accuracy_score + + +class General(ABC): + """This is the class with the general functions of the algorithm. + + For different fairness metrics, the objective function of the optimization + problem is different and hence needs different implementations. + The fairness-metric specific methods need to extend this class and implement + the necessary functions. + """ + @abstractmethod + def getExpectedGrad(self, dist, a, b, params, samples, mu, z_prior): + """Used in gradient descent algorithm. Returns the value of gradient at + any step. + """ + raise NotImplementedError + + @abstractmethod + def getValueForX(self, dist, a, b, params, z_prior, x): + """Returns the threshold value at any point.""" + raise NotImplementedError + + @abstractmethod + def getFuncValue(self, dist, a, b, params, samples, z_prior): + """Returns the value of the objective function for given parameters.""" + raise NotImplementedError + + @property + @abstractmethod + def num_params(self): + raise NotImplementedError + + def range(self, eps, tau): + a = np.arange(np.ceil(tau/eps), step=10) * eps + b = (a + eps) / tau + b = np.minimum(b, 1) + return np.c_[a, b] + + @abstractmethod + def gamma(self, y_true, y_pred, sens): + raise NotImplementedError + + def init_params(self, i): + return [i] * self.num_params + + def gradientDescent(self, dist, a, b, samples, z_prior): + """Gradient Descent implementation for the optimizing the objective + function. + + Note that one can alternately also use packages like CVXPY here. + Here we use decaying step size. For certain objectives, constant step + size might be better. + """ + min_val = np.inf # 1e8 + min_param = None + for i in range(1, 10): + params = self.init_params(i) + for k in range(1, 50): + grad = self.getExpectedGrad(dist, a, b, params, samples, 0.01, + z_prior) + for j in range(self.num_params): + params[j] = params[j] - 1/k * grad[j] + f_val = self.getFuncValue(dist, a, b, params, samples, z_prior) + if f_val < min_val: + min_val, min_param = f_val, params + return min_param + + def prob(self, dist, x): + return dist.pdf(x) + + def getModel(self, tau, X, y, sens, random_state=None): + """Returns the model given the training data and input tau.""" + train = np.c_[X, y, sens] + mean = np.mean(train, axis=0) + cov = np.cov(train, rowvar=False) + dist = multivariate_normal(mean, cov, allow_singular=True, + seed=random_state) + n = X.shape[1] + dist_x = multivariate_normal(mean[:n], cov[:n, :n], allow_singular=True, + seed=random_state) + + eps = 0.01 + z_1 = np.mean(sens) + params_opt = [0] * self.num_params + max_acc = 0 + p, q = 0, 0 + + if tau != 0: + for a, b in self.range(eps, tau): + samples = dist_x.rvs(size=20) # TODO: why 20? + params = self.gradientDescent(dist, a, b, samples, z_1) + + t = self.getValueForX(dist, a, b, params, z_1, X) + y_pred = np.where(t > 0, 1, -1) + + acc = accuracy_score(y, y_pred) + gamma = self.gamma(y, y_pred, sens) + + if max_acc < acc and gamma >= tau - 0.2: # TODO: why - 0.2? + max_acc = acc + params_opt = params + p, q = a, b + return partial(self.getValueForX, dist, p, q, params_opt, z_1) diff --git a/aif360/algorithms/inprocessing/celisMeta/StatisticalRate.py b/aif360/algorithms/inprocessing/celisMeta/StatisticalRate.py index 34f49d44..86df15b5 100644 --- a/aif360/algorithms/inprocessing/celisMeta/StatisticalRate.py +++ b/aif360/algorithms/inprocessing/celisMeta/StatisticalRate.py @@ -1,153 +1,75 @@ -from __future__ import division - -import os,sys -from scipy.stats import multivariate_normal -import scipy.stats as st import numpy as np -import math - -import site -site.addsitedir('.') -from .General import * -from . import utils as ut +from aif360.algorithms.inprocessing.celisMeta.General import General class StatisticalRate(General): - - def getExpectedGrad(self, dist_params, params, samples, mu, z_0, z_1, a, b): - a, b = a[0], b[0] - l_1, l_2 = params[0], params[1] - res1 = [] - res2 = [] - for x in samples: - temp = np.append(np.append(x, 1), 1) - prob_1_1 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, -1), 1) - prob_m1_1 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, 1), 0) - prob_1_0 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, -1), 0) - prob_m1_0 = ut.getProbability(dist_params, temp) - - - prob_y_1 = (prob_1_1 + prob_1_0) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - #print(prob_y_1) - - prob_z_0 = (prob_m1_0 + prob_1_0) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - prob_z_1 = (prob_m1_1 + prob_1_1) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - - c_0 = prob_y_1 - 0.5 - c_1 = prob_z_0/z_0 - c_2 = prob_z_1/z_1 - - t = math.sqrt((c_0 + c_1*l_1 + c_2*l_2)*(c_0 + c_1*l_1 + c_2*l_2) + mu*mu) - t1 = (c_0 + c_1*l_1 + c_2*l_2) * c_1/t - t2 = (c_0 + c_1*l_1 + c_2*l_2) * c_2/t - #print(t1,t2) - res1.append(t1) - res2.append(t2) - - exp1 = np.mean(res1) - exp2 = np.mean(res2) - dl1 = exp1 - b + (b-a)/2 + (b-a)* l_1 / (2* math.sqrt(l_1*l_1 + mu*mu)) - dl2 = exp2 - b + (b-a)/2 + (b-a)* l_2 / (2* math.sqrt(l_2*l_2 + mu*mu)) - return [dl1, dl2] - - def getValueForX(self, dist_params, a,b, params, samples, z_0, z_1, x, flag): - a, b = a[0], b[0] - l_1, l_2 = params[0], params[1] - - temp = np.append(np.append(x, 1), 1) - prob_1_1 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, -1), 1) - prob_m1_1 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, 1), 0) - prob_1_0 = ut.getProbability(dist_params, temp) - - temp = np.append(np.append(x, -1), 0) - prob_m1_0 = ut.getProbability(dist_params, temp) - if (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) == 0: - #print("Probability is 0.\n") - return 0 - - - prob_y_1 = (prob_1_1 + prob_1_0) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - #print(prob_y_1) - - prob_z_0 = (prob_m1_0 + prob_1_0) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - prob_z_1 = (prob_m1_1 + prob_1_1) / (prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - - c_0 = prob_y_1 - 0.5 - c_1 = prob_z_0/z_0 - c_2 = prob_z_1/z_1 - if flag==1: - print(c_0, c_1, c_2, prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1) - - t = c_0 + c_1*l_1 + c_2*l_2 - return t - - def getFuncValue(self, dist_params, a,b, params, samples, z_0, z_1): - res = [] - for x in samples: - t = abs(self.getValueForX(dist_params, a,b, params, samples, z_0, z_1, x, 0)) - res.append(t) - - l_1 = params[0] - l_2 = params[1] - a, b = a[0], b[0] - - exp = np.mean(res) - result = exp - b*l_1 - b*l_2 - if l_1 > 0 : - result += (b-a)*l_1 - if l_2 > 0 : - result += (b-a)*l_2 - - return result - - def getNumOfParams(self): - return 2 - - def getStartParams(self, i): - num = self.getNumOfParams() - return [i-5] * num - - def getGamma(self, y_test, y_res, x_control_test): - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - - if x_control_test[j] == 0: - z1_0 += 1 - if x_control_test[j] == 1: - z1_1 += 1 - - if result == 1 and x_control_test[j] == 0: - pos_0 += 1 - if result == 1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - return 0 - else: - return min(pos_0/pos_1 , pos_1/pos_0) - - -if __name__ == '__main__': - obj = StatisticalRate() - obj.testPreprocessedData() - #obj.testSyntheticData() + def getExpectedGrad(self, dist, a, b, params, samples, mu, z_prior): + l_1, l_2 = params + + t, c_1, c_2 = self.getValueForX(dist, a, b, params, z_prior, samples, + return_cs=True) + + t1 = t * c_1/np.sqrt(t**2 + mu**2) + t2 = t * c_2/np.sqrt(t**2 + mu**2) + + exp1 = np.mean(t1) + exp2 = np.mean(t2) + dl1 = exp1 - b + (b-a)/2 + (b-a)*l_1 / (2*np.sqrt(l_1**2 + mu**2)) + dl2 = exp2 - b + (b-a)/2 + (b-a)*l_2 / (2*np.sqrt(l_2**2 + mu**2)) + return dl1, dl2 + + def getValueForX(self, dist, a, b, params, z_prior, x, return_cs=False): + l_1, l_2 = params + z_0, z_1 = 1-z_prior, z_prior + + pos = np.ones(len(x)) + prob_1_1 = self.prob(dist, np.c_[x, pos, pos]) + prob_m1_1 = self.prob(dist, np.c_[x, -pos, pos]) + prob_1_0 = self.prob(dist, np.c_[x, pos, np.zeros(len(x))]) + prob_m1_0 = self.prob(dist, np.c_[x, -pos, np.zeros(len(x))]) + + total = prob_1_1 + prob_1_0 + prob_m1_0 + prob_m1_1 + # if total == 0: + # return 0 + + prob_y_1 = (prob_1_1 + prob_1_0) / total + prob_z_0 = (prob_m1_0 + prob_1_0) / total + prob_z_1 = (prob_m1_1 + prob_1_1) / total + + c_0 = prob_y_1 - 0.5 + c_1 = prob_z_0 / z_0 + c_2 = prob_z_1 / z_1 + + t = c_0 + c_1*l_1 + c_2*l_2 + if return_cs: + return t, c_1, c_2 + else: + return t + + def getFuncValue(self, dist, a, b, params, samples, z_prior): + l_1, l_2 = params + + exp = np.mean(np.abs(self.getValueForX(dist, a, b, params, z_prior, + samples))) + result = exp - b*l_1 - b*l_2 + if l_1 > 0: + result += (b-a)*l_1 + if l_2 > 0: + result += (b-a)*l_2 + + return result + + @property + def num_params(self): + return 2 + + def init_params(self, i): + return [i-5] * self.num_params + + def gamma(self, y_true, y_pred, sens): + pos_0 = np.mean(y_pred[sens == 0] == 1) + pos_1 = np.mean(y_pred[sens == 1] == 1) + if pos_0 == 0 or pos_1 == 0: + return 0 + return min(pos_0/pos_1, pos_1/pos_0) diff --git a/aif360/algorithms/inprocessing/celisMeta/__init__.py b/aif360/algorithms/inprocessing/celisMeta/__init__.py index 56aa17b7..b3c32724 100644 --- a/aif360/algorithms/inprocessing/celisMeta/__init__.py +++ b/aif360/algorithms/inprocessing/celisMeta/__init__.py @@ -1,3 +1,2 @@ from aif360.algorithms.inprocessing.celisMeta.FalseDiscovery import FalseDiscovery from aif360.algorithms.inprocessing.celisMeta.StatisticalRate import StatisticalRate -import aif360.algorithms.inprocessing.celisMeta.utils diff --git a/aif360/algorithms/inprocessing/celisMeta/utils.py b/aif360/algorithms/inprocessing/celisMeta/utils.py deleted file mode 100644 index ac687948..00000000 --- a/aif360/algorithms/inprocessing/celisMeta/utils.py +++ /dev/null @@ -1,489 +0,0 @@ -from __future__ import division - -import os,sys -from scipy.stats import multivariate_normal -import scipy.stats as st -import numpy as np -import math -from sklearn.mixture import GaussianMixture -import logging - -def getDistribution(x_train, y_train, x_control_train): - train = list(x_train) - for i in range(0,len(train)): - train[i] = np.append(train[i], y_train[i]) - train[i] = np.append(train[i], x_control_train[i]) - - #print(train) - - mean = np.mean(train, axis=0) - cov = np.cov(train, rowvar=0) - clf = GaussianMixture(n_components=2, covariance_type='full') - model = clf.fit(train) - - dist_params = {"mean":mean, "cov":cov, "model":model} - - mean_train = np.mean(x_train, axis=0) - cov_train = np.cov(x_train, rowvar=0) - clf_train = GaussianMixture(n_components=2, covariance_type='full') - model_train = clf_train.fit(list(x_train)) - - #print(train, train_label, train_label==train) - - dist_params_train = {"mean":mean_train, "cov":cov_train, "model":model_train} - return dist_params, dist_params_train - -def getProbability(dist_params, x): - mean, cov = dist_params["mean"], dist_params["cov"] - return multivariate_normal.pdf(x, mean=mean, cov=cov, allow_singular=1) - -def getRandomSamples(dist_params_train): - mean, cov, model = dist_params_train["mean"], dist_params_train["cov"], dist_params_train["model"] - return multivariate_normal(mean, cov, allow_singular=1).rvs(size=20, random_state=12345) - -def getAccuracy(y_test, y_res): - total, fail = 0, 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - total += 1 - if actual != result: - fail += 1 - - return 1 - fail/(float(total)) - -def getStats(y_test, y_res, x_control_test): - try: - total_0 = 0 - total_1 = 0 - fail = 0 - pos_0 = 0 - pos_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - - if x_control_test[j] == 0: - total_0 += 1 - if actual == result: - pos_0 += 1 - else: - total_1 += 1 - if actual == result: - pos_1 += 1 - - total_0 = float(total_0) - total_1 = float(total_1) - - #print("Accuracy DIFF: ", abs(pos_0/total_0 - pos_1/total_1)) - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - - if actual == 1 and x_control_test[j] == 0: - z1_0 += 1 - if actual == 1 and x_control_test[j] == 1: - z1_1 += 1 - - if result == 1 and actual == 1 and x_control_test[j] == 0: - pos_0 += 1 - if result == 1 and actual == 1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - # if pos_0 == 0 or pos_1 == 0: - # print("Observed tau : 0") - # else: - # print("TPR DIFF : ", abs(pos_0 - pos_1)) - - - - - total = 0 - fail = 0 - pos_0 = 0 - pos_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - - total += 1 - if actual != result: - fail += 1 - - - print("Accuracy : ", fail, total, 1 - fail/(float(total))) - acc = 1 - fail/(float(total)) - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - - if x_control_test[j] == 0: - z1_0 += 1 - if x_control_test[j] == 1: - z1_1 += 1 - - if result == 1 and x_control_test[j] == 0: - pos_0 += 1 - if result == 1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - print("Observed tau : 0") - else: - print("SR tau : ", min(pos_0/pos_1 , pos_1/pos_0)) - sr = min(pos_0/pos_1 , pos_1/pos_0) - - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - - if actual == -1 and x_control_test[j] == 0: - z1_0 += 1 - if actual == -1 and x_control_test[j] == 1: - z1_1 += 1 - - if result == 1 and actual == -1 and x_control_test[j] == 0: - pos_0 += 1 - if result == 1 and actual == -1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - print("Observed tau : 0") - else: - print("FPR tau : ", min(pos_0/pos_1 , pos_1/pos_0)) - - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - - if actual == 1 and x_control_test[j] == 0: - z1_0 += 1 - if actual == 1 and x_control_test[j] == 1: - z1_1 += 1 - - if result == -1 and actual == 1 and x_control_test[j] == 0: - pos_0 += 1 - if result == -1 and actual == 1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - print("Observed tau : 0") - else: - print("FNR tau : ", min(pos_0/pos_1 , pos_1/pos_0)) - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - - if actual == 1 and x_control_test[j] == 0: - z1_0 += 1 - if actual == 1 and x_control_test[j] == 1: - z1_1 += 1 - - if result == 1 and actual == 1 and x_control_test[j] == 0: - pos_0 += 1 - if result == 1 and actual == 1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - print("Observed tau : 0") - else: - print("TPR tau : ", min(pos_0/pos_1 , pos_1/pos_0)) - - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - - if actual == -1 and x_control_test[j] == 0: - z1_0 += 1 - if actual == -1 and x_control_test[j] == 1: - z1_1 += 1 - - if result == -1 and actual == -1 and x_control_test[j] == 0: - pos_0 += 1 - if result == -1 and actual == -1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - print("Observed tau : 0") - else: - print("TNR tau : ", min(pos_0/pos_1 , pos_1/pos_0)) - - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - actual = y_test[j] - - if x_control_test[j] == 0: - z1_0 += 1 - if x_control_test[j] == 1: - z1_1 += 1 - - if result == actual and x_control_test[j] == 0: - pos_0 += 1 - if result == actual and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - print("Observed tau : 0") - else: - print("AR tau : ", min(pos_0/pos_1 , pos_1/pos_0)) - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - - if result == 1 and x_control_test[j] == 0: - z1_0 += 1 - if result == 1 and x_control_test[j] == 1: - z1_1 += 1 - - actual = y_test[j] - if result == 1 and actual == -1 and x_control_test[j] == 0: - pos_0 += 1 - if result == 1 and actual == -1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - print("Observed tau : 0") - else: - print("FDR tau : ", min(pos_0/pos_1 , pos_1/pos_0)) - fdr = min(pos_0/pos_1 , pos_1/pos_0) - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - - if result == -1 and x_control_test[j] == 0: - z1_0 += 1 - if result == -1 and x_control_test[j] == 1: - z1_1 += 1 - - actual = y_test[j] - if result == -1 and actual == 1 and x_control_test[j] == 0: - pos_0 += 1 - if result == -1 and actual == 1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - print("Observed tau : 0") - else: - print("FOR tau : ", min(pos_0/pos_1 , pos_1/pos_0)) - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - - if result == 1 and x_control_test[j] == 0: - z1_0 += 1 - if result == 1 and x_control_test[j] == 1: - z1_1 += 1 - - actual = y_test[j] - if result == 1 and actual == 1 and x_control_test[j] == 0: - pos_0 += 1 - if result == 1 and actual == 1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - print("Observed tau : 0") - else: - print("PPR tau : ", min(pos_0/pos_1 , pos_1/pos_0)) - - pos_0 = 0 - pos_1 = 0 - - z1_0 = 0 - z1_1 = 0 - for j in range(0,len(y_test)): - result = y_res[j] - - if result == -1 and x_control_test[j] == 0: - z1_0 += 1 - if result == -1 and x_control_test[j] == 1: - z1_1 += 1 - - actual = y_test[j] - if result == -1 and actual == -1 and x_control_test[j] == 0: - pos_0 += 1 - if result == -1 and actual == -1 and x_control_test[j] == 1: - pos_1 += 1 - - - pos_0 = float(pos_0)/z1_0 - pos_1 = float(pos_1)/z1_1 - if pos_0 == 0 or pos_1 == 0: - print("Observed tau : 0") - else: - print("NPR tau : ", min(pos_0/pos_1 , pos_1/pos_0)) - - return acc, sr, fdr - except ZeroDivisionError: - print("Stats inconclusive") - -def getData(): - x_control_train = [] - x_train = [] - y_train = [] - x_control_test = [] - x_test = [] - y_test = [] - - folder = sys.argv[1] - temp = [] - with open(folder + "/x_train.txt") as f: - temp = f.readlines() - - for line in temp: - temp2 = line[:-1].split(' ') - a = [] - for i in temp2[:-1]: - a.append(float(i)) - x_train.append(np.array(a)) - temp = [] - with open(folder + "/x_test.txt") as f: - temp = f.readlines() - - for line in temp: - temp2 = line.split(' ') - a = [] - for i in temp2[:-1]: - a.append(float(i)) - x_test.append(np.array(a)) - - temp = [] - with open(folder + "/y_train.txt") as f: - temp = f.readlines() - for line in temp: - y_train.append(float(line)) - y_train = np.array(y_train) - - temp = [] - with open(folder + "/y_test.txt") as f: - temp = f.readlines() - for line in temp: - y_test.append(float(line)) - y_test = np.array(y_test) - - temp = [] - with open(folder + "/x_control_train.txt") as f: - temp = f.readlines() - for line in temp: - x_control_train.append(float(line)) - x_control_train = np.array(x_control_train) - - temp = [] - with open(folder + "/x_control_test.txt") as f: - temp = f.readlines() - for line in temp: - x_control_test.append(float(line)) - x_control_test = np.array(x_control_test) - - return x_train, y_train, x_control_train, x_control_test, x_test, y_test - -def checkNormalFit(x_train, y_train, x_control_train): - train = [] - for i in range(0, len(y_train)): - temp1 = np.append(x_train[i], y_train[i]) - temp2 = np.append(temp1, x_control_train[i]) - train.append(temp2) - - mean = np.mean(train, axis=0) - cov = np.cov(train, rowvar=0) - l = len(mean) - 2 - for i in range(0, l): - for j in range(0, l): - if i != j: - cov[i][j] = 0 - - for i in range(0, len(train[0])): - data = [] - for elem in train: - data.append(elem[i]) - - def cdf(x): - return st.norm.cdf(x, mean[i], math.sqrt(cov[i][i])) - - print(st.kstest(data, cdf)) diff --git a/aif360/algorithms/inprocessing/meta_fair_classifier.py b/aif360/algorithms/inprocessing/meta_fair_classifier.py index e31f7d2e..3aa7f88c 100644 --- a/aif360/algorithms/inprocessing/meta_fair_classifier.py +++ b/aif360/algorithms/inprocessing/meta_fair_classifier.py @@ -3,8 +3,8 @@ import numpy as np from aif360.algorithms import Transformer -from aif360.algorithms.inprocessing.celisMeta.FalseDiscovery import FalseDiscovery -from aif360.algorithms.inprocessing.celisMeta.StatisticalRate import StatisticalRate +from aif360.algorithms.inprocessing.celisMeta import FalseDiscovery +from aif360.algorithms.inprocessing.celisMeta import StatisticalRate class MetaFairClassifier(Transformer): """The meta algorithm here takes the fairness metric as part of the input @@ -17,7 +17,7 @@ class MetaFairClassifier(Transformer): """ - def __init__(self, tau=0.8, sensitive_attr="", type="fdr"): + def __init__(self, tau=0.8, sensitive_attr="", type="fdr", seed=None): """ Args: tau (double, optional): Fairness penalty parameter. @@ -27,9 +27,10 @@ def __init__(self, tau=0.8, sensitive_attr="", type="fdr"): (statistical rate/disparate impact) are supported. To use another type, the corresponding optimization class has to be implemented. + seed (int, optional): Random seed. """ super(MetaFairClassifier, self).__init__(tau=tau, - sensitive_attr=sensitive_attr) + sensitive_attr=sensitive_attr, type=type, seed=seed) self.tau = tau self.sensitive_attr = sensitive_attr @@ -37,6 +38,9 @@ def __init__(self, tau=0.8, sensitive_attr="", type="fdr"): self.obj = FalseDiscovery() elif type == "sr": self.obj = StatisticalRate() + else: + raise NotImplementedError("Only 'fdr' and 'sr' are supported yet.") + self.seed = seed def fit(self, dataset): """Learns the fair classifier. @@ -49,15 +53,18 @@ def fit(self, dataset): """ if not self.sensitive_attr: self.sensitive_attr = dataset.protected_attribute_names[0] - sens_index = dataset.feature_names.index(self.sensitive_attr) + sens_idx = dataset.protected_attribute_names.index(self.sensitive_attr) x_train = dataset.features - y_train = np.array([1 if y == [dataset.favorable_label] else - -1 for y in dataset.labels]) - x_control_train = x_train[:, sens_index].copy() + y_train = np.where(dataset.labels.flatten() == dataset.favorable_label, + 1, -1) + x_control_train = np.where( + np.isin(dataset.protected_attributes[:, sens_idx], + dataset.privileged_protected_attributes[sens_idx]), + 1, 0) self.model = self.obj.getModel(self.tau, x_train, y_train, - x_control_train) + x_control_train, self.seed) return self @@ -72,14 +79,10 @@ def predict(self, dataset): Returns: BinaryLabelDataset: Transformed dataset. """ - predictions, scores = [], [] - for x in dataset.features: - t = self.model(x) - predictions.append(int(t > 0)) - scores.append((t+1)/2) + t = self.model(dataset.features) pred_dataset = dataset.copy() - pred_dataset.labels = np.array([predictions]).T - pred_dataset.scores = np.array([scores]).T + pred_dataset.labels = (t > 0).astype(int).reshape((-1, 1)) + pred_dataset.scores = ((t + 1) / 2).reshape((-1, 1)) return pred_dataset diff --git a/examples/demo_meta_classifier.ipynb b/examples/demo_meta_classifier.ipynb index 4fbc5d54..5b62ef56 100644 --- a/examples/demo_meta_classifier.ipynb +++ b/examples/demo_meta_classifier.ipynb @@ -1,137 +1,51 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": { + "scrolled": true + }, + "source": [ + "# Meta-Algorithm for fair classification.\n", + "The fairness metrics to be optimized have to specified as \"input\". Currently we can handle the following fairness metrics:\n", + "Statistical Rate, False Positive Rate, True Positive Rate, False Negative Rate, True Negative Rate,\n", + "Accuracy Rate, False Discovery Rate, False Omission Rate, Positive Predictive Rate, Negative Predictive Rate.\n", + "\n", + "-----------------------------\n", + "\n", + "The example below considers the cases of False Discovery Parity and Statistical Rate (disparate impact).\n" + ] + }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 1, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], + "outputs": [], "source": [ - "%load_ext autoreload\n", - "%autoreload 2\n", + "from IPython.display import Markdown, display\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from sklearn.preprocessing import MaxAbsScaler\n", + "from tqdm import tqdm\n", "\n", - "import sys\n", - "sys.path.append(\"../\")\n", - "from aif360.datasets import BinaryLabelDataset\n", - "from aif360.datasets import AdultDataset, GermanDataset, CompasDataset\n", "from aif360.metrics import BinaryLabelDatasetMetric\n", "from aif360.metrics import ClassificationMetric\n", - "from aif360.metrics.utils import compute_boolean_conditioning_vector\n", - "from sklearn.linear_model import LogisticRegression\n", - "from sklearn.preprocessing import StandardScaler, MaxAbsScaler\n", - "from sklearn.metrics import accuracy_score\n", - "\n", - "from aif360.algorithms.preprocessing.optim_preproc_helpers.data_preproc_functions import load_preproc_data_adult, load_preproc_data_compas, load_preproc_data_german\n", + "from aif360.algorithms.preprocessing.optim_preproc_helpers.data_preproc_functions import load_preproc_data_adult\n", + "from aif360.algorithms.inprocessing import MetaFairClassifier\n", "\n", - "from aif360.algorithms.inprocessing.meta_fair_classifier import MetaFairClassifier\n", - "from aif360.algorithms.inprocessing.celisMeta.utils import getStats\n", - "from IPython.display import Markdown, display\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import pandas as pd\n", - "\n" + "np.random.seed(12345)" ] }, { - "cell_type": "code", - "execution_count": 30, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/markdown": [ - "### Meta-Algorithm for fair classification." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "The fairness metrics to be optimized have to specified as \"input\". Currently we can handle the following fairness metrics." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "Statistical Rate, False Positive Rate, True Positive Rate, False Negative Rate, True Negative Rate," - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "Accuracy Rate, False Discovery Rate, False Omission Rate, Positive Predictive Rate, Negative Predictive Rate." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "#### -----------------------------" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "The example below considers the case of False Discovery Parity." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "display(Markdown(\"### Meta-Algorithm for fair classification.\"))\n", - "display(Markdown(\"The fairness metrics to be optimized have to specified as \\\"input\\\". Currently we can handle the following fairness metrics.\"))\n", - "display(Markdown(\"Statistical Rate, False Positive Rate, True Positive Rate, False Negative Rate, True Negative Rate,\"))\n", - "display(Markdown(\"Accuracy Rate, False Discovery Rate, False Omission Rate, Positive Predictive Rate, Negative Predictive Rate.\"))\n", - "display(Markdown(\"#### -----------------------------\"))\n", - "display(Markdown(\"The example below considers the case of False Discovery Parity.\"))\n" + "## Original Training dataset" ] }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -140,225 +54,92 @@ "privileged_groups = [{'sex': 1}]\n", "unprivileged_groups = [{'sex': 0}]\n", "\n", - "dataset_orig_train, dataset_orig_test = dataset_orig.split([0.7], shuffle=True)\n" + "dataset_orig_train, dataset_orig_test = dataset_orig.split([0.7], shuffle=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "min_max_scaler = MaxAbsScaler()\n", + "dataset_orig_train.features = min_max_scaler.fit_transform(dataset_orig_train.features)\n", + "dataset_orig_test.features = min_max_scaler.transform(dataset_orig_test.features)" ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 4, "metadata": { - "scrolled": true + "scrolled": true, + "tags": [] }, "outputs": [ { + "output_type": "display_data", "data": { - "text/markdown": [ - "#### Training Dataset shape" - ], - "text/plain": [ - "" - ] + "text/plain": "", + "text/markdown": "#### Training Dataset shape" }, - "metadata": {}, - "output_type": "display_data" + "metadata": {} }, { - "name": "stdout", "output_type": "stream", - "text": [ - "(34189, 18)\n" - ] - }, - { - "data": { - "text/markdown": [ - "#### Favorable and unfavorable labels" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { "name": "stdout", - "output_type": "stream", - "text": [ - "(1.0, 0.0)\n" - ] + "text": "(34189, 18)\n" }, { + "output_type": "display_data", "data": { - "text/markdown": [ - "#### Protected attribute names" - ], - "text/plain": [ - "" - ] + "text/plain": "", + "text/markdown": "#### Favorable and unfavorable labels" }, - "metadata": {}, - "output_type": "display_data" + "metadata": {} }, { - "name": "stdout", "output_type": "stream", - "text": [ - "['sex', 'race']\n" - ] - }, - { - "data": { - "text/markdown": [ - "#### Privileged and unprivileged protected attribute values" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { "name": "stdout", - "output_type": "stream", - "text": [ - "([array([1.]), array([1.])], [array([0.]), array([0.])])\n" - ] + "text": "1.0 0.0\n" }, { + "output_type": "display_data", "data": { - "text/markdown": [ - "#### Dataset feature names" - ], - "text/plain": [ - "" - ] + "text/plain": "", + "text/markdown": "#### Protected attribute names" }, - "metadata": {}, - "output_type": "display_data" + "metadata": {} }, { - "name": "stdout", "output_type": "stream", - "text": [ - "['race', 'sex', 'Age (decade)=10', 'Age (decade)=20', 'Age (decade)=30', 'Age (decade)=40', 'Age (decade)=50', 'Age (decade)=60', 'Age (decade)=>=70', 'Education Years=6', 'Education Years=7', 'Education Years=8', 'Education Years=9', 'Education Years=10', 'Education Years=11', 'Education Years=12', 'Education Years=<6', 'Education Years=>12']\n" - ] - } - ], - "source": [ - "display(Markdown(\"#### Training Dataset shape\"))\n", - "print(dataset_orig_train.features.shape)\n", - "display(Markdown(\"#### Favorable and unfavorable labels\"))\n", - "print(dataset_orig_train.favorable_label, dataset_orig_train.unfavorable_label)\n", - "display(Markdown(\"#### Protected attribute names\"))\n", - "print(dataset_orig_train.protected_attribute_names)\n", - "display(Markdown(\"#### Privileged and unprivileged protected attribute values\"))\n", - "print(dataset_orig_train.privileged_protected_attributes, \n", - " dataset_orig_train.unprivileged_protected_attributes)\n", - "display(Markdown(\"#### Dataset feature names\"))\n", - "print(dataset_orig_train.feature_names)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "#### Training Dataset shape" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { "name": "stdout", - "output_type": "stream", - "text": [ - "(34189, 18)\n" - ] + "text": "['sex', 'race']\n" }, { + "output_type": "display_data", "data": { - "text/markdown": [ - "#### Favorable and unfavorable labels" - ], - "text/plain": [ - "" - ] + "text/plain": "", + "text/markdown": "#### Privileged and unprivileged protected attribute values" }, - "metadata": {}, - "output_type": "display_data" + "metadata": {} }, { - "name": "stdout", "output_type": "stream", - "text": [ - "(1.0, 0.0)\n" - ] - }, - { - "data": { - "text/markdown": [ - "#### Protected attribute names" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { "name": "stdout", - "output_type": "stream", - "text": [ - "['sex', 'race']\n" - ] + "text": "[array([1.]), array([1.])] [array([0.]), array([0.])]\n" }, { + "output_type": "display_data", "data": { - "text/markdown": [ - "#### Privileged and unprivileged protected attribute values" - ], - "text/plain": [ - "" - ] + "text/plain": "", + "text/markdown": "#### Dataset feature names" }, - "metadata": {}, - "output_type": "display_data" + "metadata": {} }, { - "name": "stdout", "output_type": "stream", - "text": [ - "([array([1.]), array([1.])], [array([0.]), array([0.])])\n" - ] - }, - { - "data": { - "text/markdown": [ - "#### Dataset feature names" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { "name": "stdout", - "output_type": "stream", - "text": [ - "['race', 'sex', 'Age (decade)=10', 'Age (decade)=20', 'Age (decade)=30', 'Age (decade)=40', 'Age (decade)=50', 'Age (decade)=60', 'Age (decade)=>=70', 'Education Years=6', 'Education Years=7', 'Education Years=8', 'Education Years=9', 'Education Years=10', 'Education Years=11', 'Education Years=12', 'Education Years=<6', 'Education Years=>12']\n" - ] + "text": "['race', 'sex', 'Age (decade)=10', 'Age (decade)=20', 'Age (decade)=30', 'Age (decade)=40', 'Age (decade)=50', 'Age (decade)=60', 'Age (decade)=>=70', 'Education Years=6', 'Education Years=7', 'Education Years=8', 'Education Years=9', 'Education Years=10', 'Education Years=11', 'Education Years=12', 'Education Years=<6', 'Education Years=>12']\n" } ], "source": [ @@ -372,548 +153,301 @@ "print(dataset_orig_train.privileged_protected_attributes, \n", " dataset_orig_train.unprivileged_protected_attributes)\n", "display(Markdown(\"#### Dataset feature names\"))\n", - "print(dataset_orig_train.feature_names)\n" + "print(dataset_orig_train.feature_names)" ] }, { "cell_type": "code", - "execution_count": 34, - "metadata": {}, + "execution_count": 5, + "metadata": { + "tags": [] + }, "outputs": [ { - "name": "stdout", "output_type": "stream", - "text": [ - "Train set: Difference in mean outcomes between unprivileged and privileged groups = -0.193944\n", - "Test set: Difference in mean outcomes between unprivileged and privileged groups = -0.195913\n", - "Train set: Difference in mean outcomes between unprivileged and privileged groups = -0.193944\n", - "Test set: Difference in mean outcomes between unprivileged and privileged groups = -0.195913\n" - ] + "name": "stdout", + "text": "Train set: Difference in mean outcomes between unprivileged and privileged groups = -0.193\nTest set: Difference in mean outcomes between unprivileged and privileged groups = -0.199\n" } ], "source": [ "metric_orig_train = BinaryLabelDatasetMetric(dataset_orig_train, \n", " unprivileged_groups=unprivileged_groups,\n", " privileged_groups=privileged_groups)\n", - "#display(Markdown(\"#### Original training dataset\"))\n", - "print(\"Train set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_orig_train.mean_difference())\n", + "print(\"Train set: Difference in mean outcomes between unprivileged and privileged groups = {:.3f}\".format(metric_orig_train.mean_difference()))\n", "metric_orig_test = BinaryLabelDatasetMetric(dataset_orig_test, \n", - " unprivileged_groups=unprivileged_groups,\n", - " privileged_groups=privileged_groups)\n", - "print(\"Test set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_orig_test.mean_difference())\n", - "\n", - "\n", - "\n", + " unprivileged_groups=unprivileged_groups,\n", + " privileged_groups=privileged_groups)\n", + "print(\"Test set: Difference in mean outcomes between unprivileged and privileged groups = {:.3f}\".format(metric_orig_test.mean_difference()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Algorithm without debiasing\n", "\n", - "min_max_scaler = MaxAbsScaler()\n", - "dataset_orig_train.features = min_max_scaler.fit_transform(dataset_orig_train.features)\n", - "dataset_orig_test.features = min_max_scaler.transform(dataset_orig_test.features)\n", - "metric_scaled_train = BinaryLabelDatasetMetric(dataset_orig_train, \n", - " unprivileged_groups=unprivileged_groups,\n", - " privileged_groups=privileged_groups)\n", - "#display(Markdown(\"#### Scaled dataset - Verify that the scaling does not affect the group label statistics\"))\n", - "print(\"Train set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_scaled_train.mean_difference())\n", - "metric_scaled_test = BinaryLabelDatasetMetric(dataset_orig_test, \n", - " unprivileged_groups=unprivileged_groups,\n", - " privileged_groups=privileged_groups)\n", - "print(\"Test set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_scaled_test.mean_difference())\n" + "Get classifier without fairness constraints" ] }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 6, "metadata": { "scrolled": false }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "# Get classifier without fairness constraints\n", - "biased_model = MetaFairClassifier(tau=0, sensitive_attr=\"sex\")\n", - "biased_model.fit(dataset_orig_train)" + "biased_model = MetaFairClassifier(tau=0, sensitive_attr=\"sex\", type=\"fdr\").fit(dataset_orig_train)" ] }, { - "cell_type": "code", - "execution_count": 36, + "cell_type": "markdown", "metadata": {}, + "source": [ + "Apply the unconstrained model to test data" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dataset_bias_test = biased_model.predict(dataset_orig_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "tags": [] + }, "outputs": [ { - "name": "stdout", "output_type": "stream", - "text": [ - "('Accuracy : ', 3148, 14653, 0.7851634477581383)\n", - "('SR tau : ', 0.5128381178595508)\n", - "('FPR tau : ', 0.7945499159671334)\n", - "('FNR tau : ', 0.910501272336843)\n", - "('TPR tau : ', 0.7721613485851896)\n", - "('TNR tau : ', 0.986749402037707)\n", - "('AR tau : ', 0.8525978220135617)\n", - "('FDR tau : ', 0.5030017152658662)\n", - "('FOR tau : ', 0.3717552930362757)\n", - "('PPR tau : ', 0.5485001947798986)\n", - "('NPR tau : ', 0.827615343560593)\n", - "0.503001715266\n" - ] + "name": "stdout", + "text": "Test set: Classification accuracy = 0.787\nTest set: Balanced classification accuracy = 0.619\nTest set: Disparate impact = 0.433\nTest set: False discovery rate ratio = 0.492\n" } ], "source": [ - "# Apply the unconstrained model to test data\n", - "dataset_bias_test = biased_model.predict(dataset_orig_test)\n", - "\n", - "predictions = [1 if y == dataset_orig_train.favorable_label else -1 for y in list(dataset_bias_test.labels)]\n", - "y_test = np.array([1 if y == [dataset_orig_train.favorable_label] else -1 for y in dataset_orig_test.labels])\n", - "x_control_test = pd.DataFrame(data=dataset_orig_test.features, columns=dataset_orig_test.feature_names)[\"sex\"]\n", + "classified_metric_bias_test = ClassificationMetric(dataset_orig_test, dataset_bias_test,\n", + " unprivileged_groups=unprivileged_groups,\n", + " privileged_groups=privileged_groups)\n", + "print(\"Test set: Classification accuracy = {:.3f}\".format(classified_metric_bias_test.accuracy()))\n", + "TPR = classified_metric_bias_test.true_positive_rate()\n", + "TNR = classified_metric_bias_test.true_negative_rate()\n", + "bal_acc_bias_test = 0.5*(TPR+TNR)\n", + "print(\"Test set: Balanced classification accuracy = {:.3f}\".format(bal_acc_bias_test))\n", + "print(\"Test set: Disparate impact = {:.3f}\".format(classified_metric_bias_test.disparate_impact()))\n", + "fdr = classified_metric_bias_test.false_discovery_rate_ratio()\n", + "fdr = min(fdr, 1/fdr)\n", + "print(\"Test set: False discovery rate ratio = {:.3f}\".format(fdr))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Debiasing with FDR objective\n", "\n", - "acc, sr, unconstrainedFDR = getStats(y_test, predictions, x_control_test)\n", - "print(unconstrainedFDR)" + "Learn a debiased classifier" ] }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 9, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "('Training Accuracy: ', 0.7350317353534763, ', Training gamma: ', 0.672899406837947)\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "# Learn debiased classifier\n", - "tau = 0.8\n", - "debiased_model = MetaFairClassifier(tau=tau, sensitive_attr=\"sex\")\n", - "debiased_model.fit(dataset_orig_train)\n" + "debiased_model = MetaFairClassifier(tau=0.7, sensitive_attr=\"sex\", type=\"fdr\").fit(dataset_orig_train)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Apply the debiased model to test data" ] }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ - "# Apply the debiased model to test data\n", - "dataset_debiasing_train = debiased_model.predict(dataset_orig_train)\n", - "dataset_debiasing_test = debiased_model.predict(dataset_orig_test)\n" + "dataset_debiasing_test = debiased_model.predict(dataset_orig_test)" ] }, { - "cell_type": "code", - "execution_count": 39, + "cell_type": "markdown", "metadata": {}, + "source": [ + "### Model - with debiasing - dataset metrics" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "tags": [] + }, "outputs": [ { - "data": { - "text/markdown": [ - "#### Model - with debiasing - dataset metrics" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", "output_type": "stream", - "text": [ - "Train set: Difference in mean outcomes between unprivileged and privileged groups = -0.201319\n", - "Test set: Difference in mean outcomes between unprivileged and privileged groups = -0.195210\n" - ] + "name": "stdout", + "text": "Test set: Difference in mean outcomes between unprivileged and privileged groups = -0.126\n" } ], "source": [ - "# Metrics for the dataset from model with debiasing\n", - "display(Markdown(\"#### Model - with debiasing - dataset metrics\"))\n", - "metric_dataset_debiasing_train = BinaryLabelDatasetMetric(dataset_debiasing_train, \n", - " unprivileged_groups=unprivileged_groups,\n", - " privileged_groups=privileged_groups)\n", - "\n", - "print(\"Train set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_dataset_debiasing_train.mean_difference())\n", - "\n", "metric_dataset_debiasing_test = BinaryLabelDatasetMetric(dataset_debiasing_test, \n", " unprivileged_groups=unprivileged_groups,\n", " privileged_groups=privileged_groups)\n", "\n", - "print(\"Test set: Difference in mean outcomes between unprivileged and privileged groups = %f\" % metric_dataset_debiasing_test.mean_difference())\n" + "print(\"Test set: Difference in mean outcomes between unprivileged and privileged groups = {:.3f}\".format(metric_dataset_debiasing_test.mean_difference()))" ] }, { - "cell_type": "code", - "execution_count": 40, + "cell_type": "markdown", "metadata": {}, + "source": [ + "### Model - with debiasing - classification metrics" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "tags": [] + }, "outputs": [ { - "data": { - "text/markdown": [ - "#### Model - with debiasing - classification metrics" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", "output_type": "stream", - "text": [ - "Test set: Classification accuracy = 0.731932\n", - "Test set: Balanced classification accuracy = 0.716763\n", - "Test set: Disparate impact = 0.539856\n", - "Test set: Equal opportunity difference = -0.120467\n", - "Test set: Average odds difference = -0.117636\n", - "Test set: Theil_index = 0.128652\n" - ] + "name": "stdout", + "text": "Test set: Classification accuracy = 0.694\nTest set: Balanced classification accuracy = 0.712\nTest set: Disparate impact = 0.730\nTest set: False discovery rate ratio = 0.643\n" } ], "source": [ - "display(Markdown(\"#### Model - with debiasing - classification metrics\"))\n", "classified_metric_debiasing_test = ClassificationMetric(dataset_orig_test, \n", " dataset_debiasing_test,\n", " unprivileged_groups=unprivileged_groups,\n", " privileged_groups=privileged_groups)\n", - "print(\"Test set: Classification accuracy = %f\" % classified_metric_debiasing_test.accuracy())\n", + "print(\"Test set: Classification accuracy = {:.3f}\".format(classified_metric_debiasing_test.accuracy()))\n", "TPR = classified_metric_debiasing_test.true_positive_rate()\n", "TNR = classified_metric_debiasing_test.true_negative_rate()\n", "bal_acc_debiasing_test = 0.5*(TPR+TNR)\n", - "print(\"Test set: Balanced classification accuracy = %f\" % bal_acc_debiasing_test)\n", - "print(\"Test set: Disparate impact = %f\" % classified_metric_debiasing_test.disparate_impact())\n", - "print(\"Test set: Equal opportunity difference = %f\" % classified_metric_debiasing_test.equal_opportunity_difference())\n", - "print(\"Test set: Average odds difference = %f\" % classified_metric_debiasing_test.average_odds_difference())\n", - "print(\"Test set: Theil_index = %f\" % classified_metric_debiasing_test.theil_index())\n" + "print(\"Test set: Balanced classification accuracy = {:.3f}\".format(bal_acc_debiasing_test))\n", + "print(\"Test set: Disparate impact = {:.3f}\".format(classified_metric_debiasing_test.disparate_impact()))\n", + "fdr = classified_metric_debiasing_test.false_discovery_rate_ratio()\n", + "fdr = min(fdr, 1/fdr)\n", + "print(\"Test set: False discovery rate ratio = {:.3f}\".format(fdr))" ] }, { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "('Accuracy : ', 3928, 14653, 0.7319320275711458)\n", - "('SR tau : ', 0.5398556890759312)\n", - "('FPR tau : ', 0.6157226437750696)\n", - "('FNR tau : ', 0.7093999136230463)\n", - "('TPR tau : ', 0.8293479564733099)\n", - "('TNR tau : ', 0.8593163406441414)\n", - "('AR tau : ', 0.8892945217528149)\n", - "('FDR tau : ', 0.6832866118898019)\n", - "('FOR tau : ', 0.3834976405176844)\n", - "('PPR tau : ', 0.5596391928376183)\n", - "('NPR tau : ', 0.8967236467236467)\n", - "(0.6832866118898019, 0.5030017152658662)\n" - ] - } - ], + "cell_type": "markdown", + "metadata": { + "tags": [] + }, "source": [ - "### Testing \n", - "predictions = list(dataset_debiasing_test.labels)\n", - "predictions = [1 if y == dataset_orig_train.favorable_label else -1 for y in predictions]\n", - "y_test = np.array([1 if y == [dataset_orig_train.favorable_label] else -1 for y in dataset_orig_test.labels])\n", - "x_control_test = pd.DataFrame(data=dataset_orig_test.features, columns=dataset_orig_test.feature_names)[\"sex\"]\n", - "\n", - "acc, sr, fdr = getStats(y_test, predictions, x_control_test)\n", - "print(fdr, unconstrainedFDR)\n", - "assert(fdr >= unconstrainedFDR)" + "We see that the FDR ratio has increased meaning it is now closer to parity." ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "biased_model = MetaFairClassifier(tau=0, sensitive_attr=\"race\")\n", - "biased_model.fit(dataset_orig_train)\n", - "\n", - "dataset_bias_test = biased_model.predict(dataset_orig_test)\n", - "\n", - "predictions = [1 if y == dataset_orig_train.favorable_label else -1 for y in list(dataset_bias_test.labels)]\n", - "y_test = np.array([1 if y == [dataset_orig_train.favorable_label] else -1 for y in dataset_orig_test.labels])\n", - "x_control_test = pd.DataFrame(data=dataset_orig_test.features, columns=dataset_orig_test.feature_names)[\"race\"]\n", - "\n", - "acc, sr, unconstrainedFDR = getStats(y_test, predictions, x_control_test)" + "## Running the algorithm for different tau values" ] }, { "cell_type": "code", - "execution_count": 10, - "metadata": {}, + "execution_count": 13, + "metadata": { + "tags": [] + }, "outputs": [ { - "data": { - "text/markdown": [ - "#### Running the algorithm for different tau values" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", "output_type": "stream", - "text": [ - "Tau: 0.10\n", - "('Training Accuracy: ', 0.59007283044254, ', Training gamma: ', 0.8471557184765197)\n", - "('Accuracy : ', 6015, 14653, 0.5895038558656931)\n", - "('SR tau : ', 0.8607089248858592)\n", - "('FPR tau : ', 0.8957864358026685)\n", - "('FNR tau : ', 0.9194857234907978)\n", - "('TPR tau : ', 0.9919093179930415)\n", - "('TNR tau : ', 0.8974125546638897)\n", - "('AR tau : ', 0.9991230759162755)\n", - "('FDR tau : ', 0.8457246400235614)\n", - "('FOR tau : ', 0.5351545846135752)\n", - "('PPR tau : ', 0.6980432406212983)\n", - "('NPR tau : ', 0.972325603734294)\n", - "Tau: 0.20\n", - "('Training Accuracy: ', 0.7089122232296938, ', Training gamma: ', 0.8560547557579788)\n", - "('Accuracy : ', 4219, 14653, 0.7120726131167678)\n", - "('SR tau : ', 0.6866930102717664)\n", - "('FPR tau : ', 0.6726467708167688)\n", - "('FNR tau : ', 0.9258698009067614)\n", - "('TPR tau : ', 0.9788702965603217)\n", - "('TNR tau : ', 0.8609042092761701)\n", - "('AR tau : ', 0.9016318454549019)\n", - "('FDR tau : ', 0.8985716754370806)\n", - "('FOR tau : ', 0.5212835077229696)\n", - "('PPR tau : ', 0.8634340785883854)\n", - "('NPR tau : ', 0.9509873699572469)\n", - "Tau: 0.30\n", - "('Training Accuracy: ', 0.7305566117757174, ', Training gamma: ', 0.8652540142403449)\n", - "('Accuracy : ', 3971, 14653, 0.7289974749198116)\n", - "('SR tau : ', 0.6378556299285792)\n", - "('FPR tau : ', 0.6258949415833267)\n", - "('FNR tau : ', 0.8021281808953761)\n", - "('TPR tau : ', 0.9157061270745418)\n", - "('TNR tau : ', 0.8661540136913607)\n", - "('AR tau : ', 0.9010399037361635)\n", - "('FDR tau : ', 0.8970117068060988)\n", - "('FOR tau : ', 0.6040206475603341)\n", - "('PPR tau : ', 0.8695616726701354)\n", - "('NPR tau : ', 0.9531107873071419)\n", - "Tau: 0.40\n", - "('Training Accuracy: ', 0.6383339670654304, ', Training gamma: ', 0.8874069404811007)\n", - "('Accuracy : ', 5277, 14653, 0.6398689688118474)\n", - "('SR tau : ', 0.6738297875613554)\n", - "('FPR tau : ', 0.644122920953404)\n", - "('FNR tau : ', 0.7865711339087011)\n", - "('TPR tau : ', 0.9673632005976219)\n", - "('TNR tau : ', 0.7621665735103976)\n", - "('AR tau : ', 0.8627152073258121)\n", - "('FDR tau : ', 0.9207857965052172)\n", - "('FOR tau : ', 0.5333710407239819)\n", - "('PPR tau : ', 0.869572944869857)\n", - "('NPR tau : ', 0.9685594512195121)\n", - "Tau: 0.50\n", - "('Training Accuracy: ', 0.6278920120506596, ', Training gamma: ', 0.8424560564810398)\n", - "('Accuracy : ', 5474, 14653, 0.6264246229441071)\n", - "('SR tau : ', 0.8298481425555508)\n", - "('FPR tau : ', 0.8569955013034397)\n", - "('FNR tau : ', 0.928239074324443)\n", - "('TPR tau : ', 0.9916079407319798)\n", - "('TNR tau : ', 0.8873302430084463)\n", - "('AR tau : ', 0.9673097194084582)\n", - "('FDR tau : ', 0.8523093321100546)\n", - "('FOR tau : ', 0.4555634964843873)\n", - "('PPR tau : ', 0.7360851226839791)\n", - "('NPR tau : ', 0.9639178758413839)\n", - "Tau: 0.60\n", - "('Training Accuracy: ', 0.688964286758899, ', Training gamma: ', 0.8364392682037156)\n", - "('Accuracy : ', 4525, 14653, 0.6911895175049478)\n", - "('SR tau : ', 0.7999629846862536)\n", - "('FPR tau : ', 0.8174527554362845)\n", - "('FNR tau : ', 0.7909665888208081)\n", - "('TPR tau : ', 0.953958901547282)\n", - "('TNR tau : ', 0.9070827451204897)\n", - "('AR tau : ', 0.9394597060776729)\n", - "('FDR tau : ', 0.8613593842228706)\n", - "('FOR tau : ', 0.4055043530080791)\n", - "('PPR tau : ', 0.7937196009266697)\n", - "('NPR tau : ', 0.9433076267447764)\n", - "Tau: 0.70\n", - "('Training Accuracy: ', 0.758694316885548, ', Training gamma: ', 0.8794270410853803)\n", - "('Accuracy : ', 3569, 14653, 0.7564321299392616)\n", - "('SR tau : ', 0.6227876622165098)\n", - "('FPR tau : ', 0.5866903792182638)\n", - "('FNR tau : ', 0.9190407482450215)\n", - "('TPR tau : ', 0.9560780895648338)\n", - "('TNR tau : ', 0.890147909980094)\n", - "('AR tau : ', 0.896234124640508)\n", - "('FDR tau : ', 0.9343469954055406)\n", - "('FOR tau : ', 0.5509667897652915)\n", - "('PPR tau : ', 0.9298652703704154)\n", - "('NPR tau : ', 0.9372291956457304)\n", - "Tau: 0.80\n", - "('Training Accuracy: ', 0.7235953084325368, ', Training gamma: ', 0.8054119984862806)\n", - "('Accuracy : ', 4059, 14653, 0.7229918787961509)\n", - "('SR tau : ', 0.854029993599877)\n", - "('FPR tau : ', 0.8938353737389849)\n", - "('FNR tau : ', 0.6857428917603186)\n", - "('TPR tau : ', 0.9027407287653024)\n", - "('TNR tau : ', 0.9581570773154029)\n", - "('AR tau : ', 0.9535764486010664)\n", - "('FDR tau : ', 0.8409937049267278)\n", - "('FOR tau : ', 0.37742963089855464)\n", - "('PPR tau : ', 0.7856525093953137)\n", - "('NPR tau : ', 0.9281236852587971)\n", - "Tau: 0.90\n", - "('Training Accuracy: ', 0.7241217935593319, ', Training gamma: ', 0.8099147766891792)\n", - "('Accuracy : ', 4051, 14653, 0.7235378420801202)\n", - "('SR tau : ', 0.8381936758377602)\n", - "('FPR tau : ', 0.8732228179504548)\n", - "('FNR tau : ', 0.7206111743921992)\n", - "('TPR tau : ', 0.9125888094427421)\n", - "('TNR tau : ', 0.9504356649707367)\n", - "('AR tau : ', 0.9489248561688661)\n", - "('FDR tau : ', 0.8448827898766063)\n", - "('FOR tau : ', 0.39272980229352533)\n", - "('PPR tau : ', 0.791857698925242)\n", - "('NPR tau : ', 0.9297660413700446)\n" - ] + "name": "stderr", + "text": "100%|██████████| 10/10 [00:16<00:00, 1.65s/it]\n" } ], "source": [ - "display(Markdown(\"#### Running the algorithm for different tau values\"))\n", - "\n", - "accuracies, false_discovery_rates, statistical_rates = [], [], []\n", + "accuracies, statistical_rates = [], []\n", "s_attr = \"race\"\n", - "# Converting to form used by celisMeta.utils file\n", - "y_test = np.array([1 if y == [dataset_orig_train.favorable_label] else -1 for y in dataset_orig_test.labels])\n", - "x_control_test = pd.DataFrame(data=dataset_orig_test.features, columns=dataset_orig_test.feature_names)[s_attr]\n", "\n", - "all_tau = np.linspace(0.1, 0.9, 9)\n", - "for tau in all_tau:\n", - " print(\"Tau: %.2f\" % tau)\n", - " debiased_model = MetaFairClassifier(tau=tau, sensitive_attr=s_attr)\n", + "all_tau = np.linspace(0, 0.9, 10)\n", + "for tau in tqdm(all_tau):\n", + " debiased_model = MetaFairClassifier(tau=tau, sensitive_attr=s_attr, type='sr')\n", " debiased_model.fit(dataset_orig_train)\n", - " \n", + "\n", " dataset_debiasing_test = debiased_model.predict(dataset_orig_test)\n", - " predictions = dataset_debiasing_test.labels\n", - " predictions = [1 if y == dataset_orig_train.favorable_label else -1 for y in predictions]\n", - " \n", - " acc, sr, fdr = getStats(y_test, predictions, x_control_test)\n", - " \n", - " ## Testing\n", - " assert (tau < unconstrainedFDR) or (fdr >= unconstrainedFDR)\n", - " \n", - " accuracies.append(acc)\n", - " false_discovery_rates.append(fdr)\n", - " statistical_rates.append(sr)\n", - " " + " metric = ClassificationMetric(dataset_orig_test, dataset_debiasing_test,\n", + " unprivileged_groups=[{s_attr: 0}],\n", + " privileged_groups=[{s_attr: 1}])\n", + "\n", + " accuracies.append(metric.accuracy())\n", + " sr = metric.disparate_impact()\n", + " statistical_rates.append(min(sr, 1/sr))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Output fairness is represented by $\\gamma_{sr}$, which is the disparate impact ratio of different sensitive attribute values." ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 14, "metadata": {}, "outputs": [ { + "output_type": "display_data", "data": { - "text/markdown": [ - "### Plot of accuracy and output fairness vs input constraint (tau)" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/markdown": [ - "#### Output fairness is represented by $\\gamma_{fdr}$, which is the ratio of false discovery rate of different sensitive attribute values." - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] + "text/plain": "
", + "image/svg+xml": "\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA04AAAHGCAYAAABD3NsdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nOzdd3hU1dbA4d+iFxGlSPGCKIICCtIGQRNBxV5QEfDa/cSCYgFBvWIXRFAUO+BVwYqCYlekKpgoVRQQECkqvYgYOtnfH2vmZowpk2RmzpmZ9T7PPJOcOXNmJZkkZ5299trinMMYY4wxxhhjTP5KeR2AMcYYY4wxxvidJU7GGGOMMcYYUwhLnIwxxhhjjDGmEJY4GWOMMcYYY0whLHEyxhhjjDHGmEJY4mSMMcYYY4wxhbDEyRhjjDHGGGMKYYmTMcYYY4wxxhTCEidjjMlFRL4RERd2a+J1TCZyIjIt7GfXwOt44kFEVuZ6z+Z3W+l1rMYYk6gscTLGmDAi0hBon2vz5V7EYowxxhj/sMTJGGP+7rI8tv1bRCTukRSBiFTwOgbjHedcA+echG65HpOwWwOPQjTGmIRniZMxxvzdpcH7ncDbwY8PA9Jz7ygirUTkLRH5XUT2iMgmEZkqIoEi7vO/0rJcx//HdhF5NazsKk1ExonINmBx8PHuIvKliPwqIjtEZLeI/CIiL4pIraJ8DSLyVNhrtcv1vNnB7VtFpGJ+38yixJPra+sgIq8Hj79ZRMaLSO08jn+NiCwTkV0iMk9ETs8vlnziGyci60Xk7DweGysiP4lIuaIcM4/jPBn2dR2f67Fvg9v/EpEqInK4iIwRkdXBr+kPEfkx+L05pCRx5HrdovxcIn5/GmNMUnPO2c1udrOb3ZwDOB5wwdt7wBlhn4/Kte8FwN6wx8NvV0W6T3C/aaHtuV7jH9uBV8OOsSns45XBx1/M5/Uc8BNQLtKvATgC2B/8/JWw5zUK2++5Qr6nRYkn/Gvbmsf+k3Id+6o89tkLbAj7vEEh8QWCcUzJtf2U4PNPjcL7qnlYPMPDtjcM2/5qcNvCAr5fxxThNf/3vCj8XCJ+f9rNbnazWzLfbMTJGGNyhJfpjQMmA38EP+8qIuUBgiMso4AywcfuA2oBNYCLgV8i2ScK8f6JzseqCJwV3PYm0C74OmWDr/lK8LGjQvtFEp9z7hfgo+Dj3UXkoODHPcJiGFVIjBHFk4cVaGLRGE2EAE4RkTrB+EsBA8P2vwI4EOgP1Cwkpv9xzn0HvAEcE9omImWBZ4F3nXOTIj1WAa+xAJgT/LSbiJQOfnxJ2G4vi0h1oGnw86eBykA1oC1wL7CtpLGEKe7PxRhjUlaZwncxxpjkFzxZ7h78dDfwsXNur4h8hDaHOAg4F02oTgCqB/ed5px7OOxQ44LHO7WwfaJggHMuM/jxouD9WjQJOgmojZ4UhzsqeF/o1xD0JHA+mpxdCQwn5/s0xzk3v5AYI40nt/uCiRsi8jVwUXD7YcFjHgXUDW6b55x7LRSviNwO1CskrnCLgJoiUt05txnoA/wL6FyEYxTmZaA1+j3oBEwiJ3H62Tn3VTAZ/AN9r50JbEdLML93zj0SxVig+D8XY4xJWTbiZIwx6gz06jvAXKC+iBwDfB+2T2hEKnwOyCLyFsk+hSns4ta88E9EpCowA42zHv88GQZNgCKOzzk3Pex1rheRY4Fmwc9fKii4IsaT25Kwj7PCPg41wagetu23XM/9vaC48vBT8L6JiPwLHd15yDmX+7j5ElXQ/9Q3gV3Bj/8tIi3IGV16GcA5l40m6b+h5ZD3AK8DP4jIDyJSlGSwoFhL8nMJZxdfjTEpxRInY4xR4WV67YEfgrfHw7afKSLVgPVh2/Jb4ymSfUJ2hz6QYHc8ERHg8EKetzPX552AUAOByUAdpx3WbilhfMPD9nsm+PEONBkoSFHiyW1v2Md5NR/YFPbxv3I9dmgExw+3DJ3L1QQdYVsFPBV6UEQ6ichMEZkrIktFpHdw+0PBBhYfoSND/2he8b8vwLk/gAnBTy9E52cRfN3RYft9DNRHR3zOAx4K7nMMMKCIX1d+ivpzKe770xhjkoolTsaYlCciB6JleIUph5apzQQ2B7d1EpH/iEhNETlYRLqISHqE+4SsCvs4FEdvckrRIrUv7ONdQJaINAseK7eixPcWOYnWScH7d5xzf0YxnqJaCqwJftxSRC4PdqUrapkezrk9wHLgOqArcLNzLjxxewvo7pxrhSY0rwe3t0aTnMucc0c759ZQsJeD91WBm4MffxH+PBF5Bm1M8RfwOTCenMSlflG+rgIU9ecSrfenMcYkNEucjDFGT5ZDpUnvuL+veyPAaWH7Xuac2wn0JOcEdCDawGAL8D5wRCT7hB3zjbCP3xGR7egoT+4RpcLMBDYGPz4bbR7xY147FiW+YGLxfK5DFFimV9R4iipY1nZP2KYxweM/jnbkK6rFQBvgbefc1FyP/QY8KyI9gMrOudDxWwO3OucibdowGVgd/DhU5vZyrn1uBL5Eyw33oKWilYKPfRHh6xSmqD+XaL0/jTEmoVniZIwxfy/TG5PH45PJmTfTQUSOcM69j3Ylexsd+diHJh3TCc4ZimSf4H7TgWvRUZTd6OjHxcB3Rfkigif0Z6LzV3YEX/MBYHA++0cUX9AL5Ix8LHbOzYx2PEXlnHsV+D/0+7UHLa28EFhQjMP9jI6+9M3jsePRLndpwDIRqRqcC1XGOTcvj/3zizcbbbkesgn4MNdug9Hv1wb057EDnXN3CzklkyVSjPdJVN6fxhiT6MQ5W7fOGGNMwUSkKZqQlEZHWZ72OKSoEpGxQD3nXIdc248GljrnskXkUHQE6DDgVOAG59yZ8Y/WGGOMF6wjjjHGmHyJyAXAY2iyUBotW4ukTC/RtAY+y2P77egcsCx0ROoy51yWiLQGZsUzQGOMMd6yxMkYY0xBqqKtsXcBXwO9nHM7vA0puoLtuY9AS+L+xjl3fV7Pcc7dF+u4jDHG+IuV6hljjDHGGGNMIaw5hDHGGGOMMcYUIuVL9UqVKuUqVoxkgXRjjDHGGGNMfnbs2OGcc0k7MJPyiVPFihXJysryOgxjjDHGGGMSmogUuL5bcHH1O9CGPHWBq4NLSxT0nGOBZ4EAumTGCOBh58F8o6TNCI0xxhhjjDG+cgC64PatRLCItogciC4Kvh5oG3xeP6BPDGPMV8qPOBljjDHGGGNizzn3KfApgIi8GsFTLgUqAVc653YCPwbX1+sjIsPiPepkI07GGGOMMcYYP2oPfB1MmkK+QMv8GsQ7mJQfcapWrRrTpk3zOgxjjDHGGGMSXRkRmR32+Ujn3MgSHK82uvB6uPVhj60owbGLLOUTpy1bttCxY0evwzDGGGOMMSbR7XPOtfE6iFixUj1jjDHGGGOMH60DauXaVivssbiyxMkYY4wxxhjjRxlAmohUCNvWGVgDrIx3MJY4GWOMMcYYY2JORA4QkeNE5Dg0D6kf/Lx+8PFHRWRy2FPeBHYAr4rIMSJyIXAXEPeOemCJkzHGGGOMMSY+2gDzgreKwIPBjx8KPl4HaBja2Tm3DR1hqgvMBp4DngCGxS/kHOJBsuYrlStXdllZWV6HYYwxxhhjTEITkR3OucpexxErNuJkjDHGGGOMMYWwxMkYY4wxxhhjCuFJ4iQivURkhYjsEpE5IpJWyP7/FpH5IrJDRNaJyOsiUjvXPheJyCIR2R28vyC2X4UxxhhjjDEmVcQ9cRKR7sBwYBDQEvgG+CzUTSOP/U8AXgNGA82ALkBT4I2wfdoDY4Pbjgvevysi7WL3lRhjjDHGGGNSRdybQ4jIt8AC51zPsG3LgHHOubvz2P8OoLdz7rCwbVcDzzjnDgh+Phao5pzrHLbPJGCjc+6SguLxvDnEjh2waBG0SdpFlo0xxhhjTAz98gtUqAB163obhzWHiCIRKQe0Bibmemgi0CGfp80E6ojIuaJqAD2AT8P2aZ/HMb8o4Jj+MWwYBALw559eR2KMMcYYYxLEihUwZIhee2/YEJ5/3uuIkl+8S/VqAKWB9bm2rwdq/3N3cM5loInSG8AeYCMgwJVhu9UuyjFF5DoRmS0is/ft21fUryG6AgFwDmbP9jYOY4wxxhjjaytXwtCh0LYtHHEE3HknlC6t23r2LPTppoTKeB1AYUSkKfAM8DA6ilQHGAqMAK4ozjGdcyOBkaCletGJtJhCJXrffQcnn+xpKMYYY4wxxl9WroRx4+Cdd2DWLN3Wtq0mS127QoMGXkaXWuKdOG0C9gO1cm2vBazL5zl3A98554YGP18gIlnA1yLyH+fcb8HnFuWY/lGtGjRqpImTMcYYY4xJeatW5SRLoVPENm20NK9rVzj8cG/jS1VxTZycc3tEZA7QGXg37KHOwPh8nlYJTbbChT4PlRpmBI8xNGyfzmjHPv8LBGDqVK+jMMYYY4wxHlm9OidZ+vZb3da6NTz2mCZLRxzhbXzGm1K9YcBrIvId2vjhBqAu8CKAiIwBcM6FyvA+AkaJyI3klOo9Bcx1zq0O7jMc+EpE7gImABcAnYAT4/IVlVS7dvDGG/D773DooV5HY4wxxpTY2rVQsSIcdJDXkRjjX7/+mpMsZWbqtlatYPBgTZYaNvQ2PvN3cU+cnHNjRaQ6MABNgn4EznLOrQruUj/X/q+KSBXgZuAJYBswBbgzbJ9vRKQH8AjwELAc6O6c+zbWX09UBAJ6/913cIGt22uMMSaxbd4MLVrAv/6lvY9KxX3VSGP867ffcpKljAzd1rIlPPqoJktHHultfCZ/cV/HyW88X8cJYNcuOPBA6NtXf2uMMcaYBHbNNfDKK/rxa6/BZZd5G48xXvv995xk6ZvgRJLjjoNu3eDii5MnWUr2dZwscfJD4gTaHuXAA2HyZK8jMcYYY4pt2jTo1An694dJk3T06aefdHFOY1JJKFl6912YOVO3tWiRkyw1auRtfLFgiVOS803idPPNMGYMbN2qDfmNMcaYBLNrl54Y7tsHP/6oJ4udO8MTT0CfPl5HZ0zsrVmTkyzNmKHbmjfPSZYaN/Y2vlhL9sTJqo79IhCA7dthyRKvIzHGGGOKZdAgWLoUXnxRG0OceiqcdhoMHAh//OF1dMbExpo18MwzkJ6u8/puvRW2bYOHH9bR1u+/h3vuSf6kKRVY4uQX4Q0ijDHGmASzaJF2ArvsMh1lCnnsMS2mGDzYu9iMiba1a+HZZ+GkkzRZuuUWfZ8/+CAsXgwLFsCAAXDUUV5HaqLJSvX8UqqXnQ0HHwyXXgrPP+91NMYYY0zEsrP1BHLRIr3CXrPm3x+//HItX1q6FOrV8yZGY0pq3ToYP17L8L76CpyDZs1yyvCaNPE6Qu8le6meJU5+SZxAaxq2boU5c7yOxBhjjInYyJFw/fXw8stw9dX/fHzVKi1TuvRS3ceYRLF+fU6yNH16TrJ08cV6a9rU6wj9xRKnJOerxOmee2DIEPjzTy0ON8ZE1ahRWmv+7LNeR2JM8li3Do4+WtehmTIFRPLe7447YNgw/R089tj4xmhMUaxfD++9l5MsZWfraFJoZKlZM68j9C9LnJKcrxKnDz6ALl20wX/79l5HY0zSadsW5s3Tgd0qVbyOxpjk0KMHTJigczoKmvy+ZQs0bAgdOsAnn8QvPmMisWGDJkvvvJOTLB19tCZL3bpZshSpZE+crDmEn1iDCGNiZudOmD8f9u/PWandGFMyn34KY8dG1jGsWjW4+259zrRpcQnPmAJt3AgjRsApp0CdOnDjjdoh75574IcfdM7egw9a0mRy2IiTn0acQGfNpqXBm296HYkxSWXGDP3VAu109PDD3sZjTKLLytITysqVdSS3XLnCn7NzpyZYderAt9/mX9ZnTKxs3Ajvv68jS1On6shS48Y5I0vHHGPvy5JI9hGnMl4HYHJp185GnIyJgcxMvT/8cO2GZIwpmfvv16YPX38dWdIEOn334Ye1gcS77+qJqjGxtmnT35Ol/fuhUSMdAe3WTefcWbJkImEjTn4bcRoyBO68U3/Lq1f3OhpjksZFF2mpXpcu8Nxzujhh+fJeR2VMYpo7V+cMXnutljoVxf792khixw4thYo06TKmKDZvzkmWpkzR992RR+aMLDVvbslSLCT7iJPNcfKb0DynWbO8jcOYJOKczmtq317L9Xbvtl8xY4pr3z647jpdq6k4i9qWLq2L4i5frm3MjYmWzZvhv/+F00+HWrWgZ09YsQL699dy0qVLYeBAaNHCkiZTPJY4+U3r1vrbbOV6xkTNr7/qKu/t28OJJ+q2r7/2NiZjEtWzz+pyg08/reu2F8cZZ0CnTjrx/s8/oxufSS1btujaYGecAbVr6yjo8uXQr5+OjC5dCoMGwXHHWbJkSs4SJ7+pUkVXU/v2W68jMSZphLroHX881Kihv2I2z8mYolu9WpurnHWWrmdTXCJamb5pEwwdGr34TGrYuhVeeQXOPFNHlv7v/2DZMujbV5P6Zcvg0Ue1JNSSJRNN1hzCj9q1gw8/1Poi+403psQyM3VSevPm+nlaGrz1lta8ly7tbWzGJArn4Kab9P6550r+76lNG+jeXRfF7dVLO+0Zk5+tW3W5y3fegUmTYO9ebfbTp4/OWWrVyk6ZTOzZiJMfBQJ6GW7lSq8jMSYpZGToSVrZsvp5erqWBy1Y4G1cxiSS8ePh44+1K16DBtE55sCBegL8wAPROZ5JPuvXw3nn6cjS1VfD4sVw++06T3X5cp0vF5rlYEysWeLkR7YQrjFRs3u3Tgpu3z5nW2g9JyvXMyYyf/wBvXvrVf1bbonecRs2hBtu0An9P/0UveOa5HHzzTBxItx2m54W/fKLJktt2liyZOLPEic/OuYYqFDB5jkZEwVz58KePTq/KaRePb1ibg0ijInM3XfDhg3aBa9MlIv8770XKlXS1zAm3Ecfwbhx+h4ZMkRb4FuyZLxkiZMflS2r48424mRMiYUaQ4SPOIGOOn31lc7XMMbk75tv4MUX4dZb9V9TtNWsqcsXTpgAM2dG//gmMW3frnPqmjXTDnnG+IElTn4VCOil8r17vY7EmISWmamjS7Vr/317ejps3Kitao0xeduzR9dsql8fHnoodq9z223aHKJfP7uYYdS99+pSEiNH2iLJxj8scfKrQAB27oSFC72OxJiElpHx9zK9EJvnZEzhhg7Vf0PPPQcHHBC716lcWdd0ysjQkSeT2mbNgmeegRtvhA4dvI7GmByWOPmVNYgwpsR++01vucv0ABo3hkMOsXlOxuRn2TLtoHfxxXDOObF/vauvhqOP1rlO+/bF/vWMP+3bp6OctWrpWkzG+IklTn51+OG6Uqc1iDCm2DIz9T6vEScRHXWyxMmYf3JOu91VqADDh8fnNcuUgcGDYckS7bJnUtNTT8H8+TriVLWq19EY83eWOPmViI462YiTMcWWmQnly8Nxx+X9eFqaLpf2669xDcsY3xszBqZM0UQmngvTnncenHCCruuUlRW/1zX+sGIF3HcfnHsuXHih19EY80+WOPlZIKDF5du3ex2JMQkpI0O7gOU3sTg9Xe9t1MmYHJs2Qd++Orfkuuvi+9oiOq9q3ToYNiy+r2285Rz06gWlS+ucOms7bvzIEic/CwT0L8ncuV5HYkzC2bMH5szJe35TSPPmcOCB1iDCmHB9+8Kff2o3s1IenCW0b6+jDUOG6NpRJjW8/TZ8/jk88oiutWeMH1ni5Gdt2+q9zXMypsjmz4fdu/Oe3xRSurSWBdmIkzFq0iQt0+vfX9fP8cqgQdpYNpYt0I1/bNmiLenbtIGbb/Y6GmPyZ4mTn9WoAQ0b2jwnY4ohv4Vvc0tLg0WLtDzJmFS2c6c2hGjUCAYM8DaWo46Cnj1hxAjt7meSW//+sHkzjBqlF7SM8StLnPzOGkQYUyyZmVruceihBe8Xmuc0Y0bsYzJJZNu2pFup9ZFHYPlyePFF7abntfvv1+Yu99zjdSQmlqZP1y6Kffrk38jHGL+wxMnvAgFt+bV2rdeRGJNQ8lv4Nrc2bfTkzMr1TMQ++UQXAWvfPmneOD/8oHOKrrwSTj7Z62hU7do63+rdd+36YbLavRuuvx4aNNBE2Ri/s8TJ70IL4c6a5W0cxiSQtWth1arCy/RAk6Z27axBhInQlClw0UVaz/bbbzpk2aUL/PST15EVW3a2nrwedBA8/rjX0fzdHXdojtq/f9IN8Bl0gdslS+CFF6ByZa+jMfEkIr1EZIWI7BKROSKSVsj+N4nIYhHZKSJLROSKeMUazhInv2vZUlcFtAYRxkSsoIVv85KeDvPmWed/U4hvvtGFhho10vqipUv1zG/qVDjmGJ0gtG6d11EW2YgROkI7bJhOrfWTKlV0JGL6dPj0U6+jMdG0eLH++lxyCZxxhtfRmHgSke7AcGAQ0BL4BvhMROrns/+NwGPAQ0Az4H7gORE5Nz4Rh8XiUvwSTuXKlV2W31fZa90aqlWDL7/0OhJjEsKdd+rq83/+qSNKhZk4EU4/Hb74Ak47LfbxmQQ0d67WsNWsqeV5tWvnPLZpk04Qev55XTTsjjv0dsAB3sUboTVroEkTbeL65Zf+XDtn717t8FeuHHz/vTUPSAbZ2dCxI/z4oyZQtWp5HZGJFhHZ4ZwrcPxQRL4FFjjneoZtWwaMc87dncf+3wDfOuduD9v2BNDOOXdi9KIvnI04JYJAQEv1srO9jsSYhJCRoYO1kSRNoCV9pUsnzXQVE20LF2pGXbUqTJ7896QJdJjmqaf0DPDss+HBB+HII7XLwt693sQcoVtu0TXPXnzRn0kTQNmy2p584UIYPdrraEw0vPyy/r0dOtSSplQjIuWA1sDEXA9NBDrk87TywK5c23YCAREpG90IC5byI0716tVzr732mtdhFGzzZli5UktBIj0TNCZF7dsnnHPOiZx77hpuuml5xM+74YZWlC+fzfDh82MYnUk4u3frJAzQHtmR/A3OytL5T3/9pe3pDj1UJxD5zMyZ1Rkw4FiuvfYXLr10tdfhFMg5uOmmVmzcWJ7XXvuWChXsQmKi2rKlHFde2ZaGDbN48sn5vk3YTfF06tRpD/BD2KaRzrmRoU9EpC7wO3CSc+6rsO33AZc6547KfUwRGQT8H3AOMBtNvD4GagF1nXNx66CW8olTQpTqLVyoSdPo0XCFJ3PhjEkYc+Zop7yxY6Fbt8if17cvPPecdpm26xMGgNWrdaGvrCydZFOUFWGdg48/1rrRxYt1peWhQyPrWBIH27dD06aaz82dq6M6fvfVV3DSSTov5q67vI7GFNcll8B778GCBXotwiSXwkr1ipk4VQSeAy4HBFgPvA70B2o759ZH96vIn5XqJYKjj9YZstaP1ZhChRa+jbQxREhamg4uWANLA2iTh1NP1Ux64sSiJU2gdW/nnqtnhyNH6gJJHTpA166+WNH13nvh9981tERImkCbuJxzDgwerIUYJvF89hm8/bauzWVJU8raBOxHR4vC1QLy7K7jnNvpnLsGqAQ0AOoDK4HtwMZYBZoXS5wSQenSegndEidjCpWZCXXr6uK3RXFicHqpzXMybN4MnTtr54RPP4VWrYp/rDJloGdP+PlneOgh7UDStCncfDNs2BC9mItg1ix45hm48UbfDIBFbPBgHS0bONDrSExRZWXpe+7oo3Ug1qQm59weYA7QOddDndHuegU9d69z7jfn3H6gB/Cxcy6udbuWOCWKQADmz9dL4saYfIUWvi1q3XyNGno+a4lTitu2TVssLlsGH36oo0TRULmyDvP8/DNcd512Y2jYULvxxbFcfN8+fflatbThQqJp1gyuvlrLales8DoaUxT336/r640caeXQhmHAVSJyrYg0EZHhQF3gRQARGSMiY0I7i0hjEblcRBqJSEBE3gaOAf4T78AtcUoUgYB2Z5pvE9eNyc+GDfDLL8W/ip6WBjNnwv790Y3LJIisLO2K9/33MH68th+Ptlq19Kw/1Knv3nt1XaiXXtKsJsaeekr/jTz7rDYJTEQPPqiFGAMGeB2JidTcufDkkzr4mlbgMqcmFTjnxgK3AQOA+cCJwFnOuVXBXeoHbyGlgT7A98CXQAWgg3NuZbxiDrHEKVEEAnpv5XrG5KuoC9/mlp6uaz8tWBC9mEyC2LULunTRIcs339QEKpaOOkqTs5kz4fDD9YyyRQttKBGjpk0rVuhV//POgwsuiMlLxMWhh8Jtt+mPae5cr6MxhQmNctasCY895nU0xi+cc8875xo458o751qHN4pwznV0znUM+3yxc66lc66Sc66qc66Lc26JF3Fb4pQo/vUvnbhhiZMx+crM1CklrVsX7/mhK6FffVXwfibJ7N2rLRgnTdIFZi6+OH6v3aEDzJihbcb27dOGEp06Rb1LiXPQqxeUKqWjTYneAvrOO6F6dZsrkwiefVa7nQ4fDgcf7HU0xpSMJU6JJBCwxMmYAoQWvq1YsXjPr1cPGjSweU4pZf9+uPxy+OgjLaG78sr4xyCiQ0A//gjPP6/tywMB6NFDu/FFwdix8Pnn2lShqI1T/KhqVS3VmzRJmx4af1q9Wn9OZ55ZtOUhjPErS5wSSSAAS5fC1q1eR2KM7+zbp9cVilumF5KWpiNOKb7EXWrIztYSubFjYcgQHZLxUtmy2nbs55/hvvs0mWvSROvSNm0q9mG3boVbb4W2beGmm6IYr8duvFEvdNx5p/4ojb+ERjmd0+sBiT7KaQxY4pRYQvOcbKEZY/7hxx9hx46St1dOS4ONG/UahUlizmlC8sormqT06+d1RDmqVNEOCD//rC3knnlGO/ANHgw7dxb5cP37a4f1kSO1qUKyKF9eR9Dmz9f5TsZfxo2DTz7RLvwNGngdjTHRYYlTImnTRi/ZWLmeMf9Q3IVvc0tP13sr10ty99yjCUmfPvDAA15Hk7c6dWDECPjhB+jYEe6+Gxo3hldfjbj149dfa8O+Pn3guONiGq0nevTQZbYGDND+HsYf/vgDbrlFS6dvvdXraIyJHkucEknVqrpynCVOxvxDZqZ2ei7plc3GjeGQQ6xBRFIbNAgefRSuvx4ef9z/NURNm8IHH8D06dok6Oqr9Yz0888LrCndvfOjptcAACAASURBVFu7mTVooN30klGpUlpluWqVTlEz/nDXXbo8xKhR2rDHmGRhiVOiCTWIsAkYxvxNcRe+zU1Ey/VsxClJDR+uo02XXZZ4Ey/S0/UKwTvvaF3qmWdC58759uQePBh++gleeEHX301Wp5yiaxYPHGhTgP1gxgwdKL311uJ3ODXGryxxSjSBAKxfr61qjDGAzt9Ytqzk85tC0tJg5Ur49dfoHM/4xEsv6bymCy/UuU2lEvBfoIi2S1+0CJ5+Wif4tG6tieCqVf/b7aefdGDtkkvgjDM8jDdOHntMy8MGD/Y6ktS2Z48O5Navr3ObjEk2CfhfI8XZQrjG/ENJF77NzeY5JaG33tK6tTPP1I8TvX6oXDno3Vvbld99ty6m27gx9OtH9uatXH89VKoETz7pdaDx0aKF5o7Dh9sFDy8NGaI5/fPPwwEHeB2NMdFniVOiad5cWwlZ4mTM/2RkaLewNm2ic7zmzeHAA22eU9KYMEHXajrpJE0wypXzOqLoqVpVh5aWLYNLL4UnnuCV+vfz1VcwdNBeatXyOsD4efhhrWK/7z6vI0lNS5fCI4/ogOjZZ3sdjTGxIS7F58pUrlzZZWVleR1G0bRvr//4p0/3OhJjfOHUU3Vuw5w50TvmWWdp5dPChdE7pvHAF1/AeedpM4Uvv9RW30lsw7RFHH1aPY7dO5ep9a+i1KBHtF4vEcsSi+GOO2DYMPj+ezj2WK+jSR3O6VyzuXN1/eY6dbyOyHhFRHY455J2VmVq/CVNNoEAzJ6tK34ak+L274dvv41emV5IWpqWnJRg3VHjta++ggsu0EVkP/ss6ZMmgNtHNSVLqjDi5XKUqlFN69fatIFJk7wOLS7+8x8dhLvrLq8jSS2jR8PUqTrXzJImk8wscUpEgYB2VFq0yOtIjPHcokXw11/RawwRkpam9zNmRPe4Jk6++w7OOQcOOwwmToSDD/Y6opj7/HNdCPbuu+Hoq9vrYulvvAFbtmj3vTPO0KGYJFatmiZPn36qJ/Im9jZuhL594YQToGdPr6MxJrYscUpE7drpvc1zMiZqC9/m1ratTie0BhEJaMECTRJq1NCRlkMO8TqimNuxA3r1gqOO0sQJ0PK8f/8bliyBJ57Q/xktW8JVVyV1B4XevaFePejfH7KzvY4m+fXpA9u3w8iRKVMRalKYvcUTUcOGevXUEidjyMzU8+OGDaN73PLl9RqFNYhIMEuW6OhKpUoweTIceqjXEcXFgw/CihV68lq+fK4Hy5fXs9vly3US0Ntvawe+u+7SHt5JpkIFbRQxeza8+67X0SS3L7+E11/Xt1LTpl5HY0zsWXOIRGwOAXo1dd06XcPDmBTWpAkceSR89FH0j33vvfDoo9p4IgWmxyS+FSu0xnLvXs14jzrK64jiYv58ncZ01VW6VFWhVq3SN/frr+tFuHvvhRtvzCPjSlz79+vgWlaWNitIpkaKfrFjhzbgKFNGK0ArVPA6IuMH1hzC+FMgAD/8oP8VjElRW7boQp/Rnt8UkpamJ2ChckDjY7//ru0Vd+zQy+ApkjTt36/LU1WvrmvoROSww2DMGG1D2aoV3H67XoEYOzZpattKl9ZGBb/8AiNGeB1NcnrooZzvryVNJlVY4pSoAgH9Bzd3rteRGOOZULVqrBKn9u31BMzmOfncxo2aNG3YoB0Smjf3OqK4ef557QHx1FPaGKFIQi3av/hCh1R79NDJgtOmxSLUuDvjDDj5ZD3B//NPr6NJLgsWwOOPw9VXQ8eOXkdjTPx4kjiJSC8RWSEiu0RkjoikFbDvqyLi8rhlhe3TMZ99jo7PV+SBQEDvbZ6TSWEZGToZuW3b2By/ShU9t7R5Tj62dSucdpqWn33ySc7fxhTw66/aQe700zXnKbbTTtOLcKNHawl4p05w7rkJv4iZiI7CbdpUhNE4U6j9+7V7XrVqMHSo19EYE19xT5xEpDswHBgEtAS+AT4Tkfr5POVWoE6u2y/AO3ns2yzXfsuiGryfHHIINGhgiZNJaZmZWmN/wAGxe420NF0navfu2L2GKabt23Wl4kWL4P33IT3d64jiqndvPYl94QVNEkqkdGm44gptrvHYYzrM2ry5niGvWROVeL3QurUmlcOGJfSX4SsvvKCnHk8+qSWixqQSL0ac+gCvOudGOecWO+d6A2uBG/Pa2Tm3zTm3LnQDGgJHAKPy2H1D+L7Ouf0x+yr8IBCwxMmkrOzs2Cx8m1t6uiZNs2fH9nVMEe3cCeedp3VqY8fqsEsKef99+OAD7aZ3+OFRPHDFitrHe/lyuPVWHYU68khtIJGg9W4DB+p68Q884HUkie+337Td/Wmnaad7Y1JNXBMnESkHtAYm5npoItAhwsP0BBY6577J47HZIrJWRCaLSKcShJoYAgFYuVLr+o1JMT/9BNu2xW5+U8iJJ+q9lev5yO7dcOGFMH26Njno0sXriOJq2za4+WZo0QJuuy1GL1K9ug7T/PSTfn8feUQTqOee066FCeSII7Rp4H//qx32TPFFdZTTmAQU7xGnGkBpYH2u7euB2oU9WUSqAt3452hTaMTqIuBCYAkwOb+5UyJynYjMFpHZ+/btK9pX4Ce2EK5JYbFa+Da3GjV0fRJrEOET+/bppe7PP9dFi1Lwsvc998DatTBqFJQtG+MXO+IIePNNHdlr1kwztmbNYPx4SKDlTAYMgMqVwxYHNkX2/vswYYKO3B1xhNfRGOONROuqdxka82vhG51zS5xzLzrn5jjnMpxzvYDPgX55HcQ5N9I518Y516ZMmTKxjzpWWrbUunRLnEwKyszUJWgaN479a6WlwcyZeqXVeCg7W9t4vfeeTrC49lqvI4q7zEztpNe7d+yaouSpTRuYMkUbcJQrB127QocOMGNGHIMovpo14c47tbxx5kyvo0k8f/6pOXPz5tq93phUFe/EaROwH6iVa3stYF0Ez+8JjHfObYlg32+BRkULL8FUrgzHHGOJk0lJGRk62hSPcpH0dD1xWLAg9q9l8uEc9Oqli7Y+8kgMa9T8a+9e7dVw6KH6LYg7EW3G8f33utLu6tV6VaFLFy3p87nbb4e6daFfv4QaLPOF//wnjqOcxvhYXBMn59weYA7QOddDndHuevkSkQDQgrybQuTlOLSEL7mFGkTYfwGTQrZt00ZqsZ7fFJIWLPq1eU4ecQ7uuENX2rzrLj2LS0FPPAE//qjTjKpU8TCQ0qXh//4Pli3TzgtTpuhFvBtv1HbmPlWpkjbTyMjQsjMTmdAo5803p1S3f2Py5EWp3jDgKhG5VkSaiMhwoC7wIoCIjBGRMXk87zpgmXNuWu4HROQ2EekiIo1EpJmIPAp0AZ6N3ZfhE4GArmPy889eR2JM3ISuFcQrcapXDw47zOY5eebBB7VRwc03w6BBKTkrffly/TZceKE2E/SFSpU0iV2+XEcDX3pJG0g8+CD89ZfX0eXpqqugSROd65RgPS48ET7KOXCg19EY4724J07OubHAbcAAYD5wInCWc25VcJf6wdv/iEgVoAfwUj6HLQcMBRYAXwePebZz7r2ofwF+Yw0iTArKyNBz53he/UxP18TJBnfjbOhQPRG/+moYPjwlkybndDCnbFl4+mmvo8lDzZoa2OLFWsr3wAOaQI0Yoc08fKRMGRg8GJYu1S57pmChUc5nn/V4lNMYnxCX4mcBlStXdllZWV6HUXz790PVqlo2MXy419EYExdnnQW//go//BC/1xw1Cq67TqdyHHVU/F43pT3/PNx0E3TvDm+8oSViKej11+Hyy7VEr1cvr6OJQGamTiSaMQOuucZ3GYpzeiFk2TIt1ojlAtqJbPlyrcA86yxtomhMJERkh3OustdxxEqiddUzuZUurUuj24iTSRHZ2XpeFus25Lmlp+u9levFyejRmjSdey689lrKJk2bN2tTg+OPhxtu8DqaCB1/vE4IvPpqePtt8NnFSREYMgTWr9cKUPNPzun7zbejnMZ4xBKnZBAIwLx5sGeP15EYE3PLlum0vnjNbwpp3BgOOcQaRMTFuHE6UnHKKfDOOyndxqtfP/jjD12yqlQi/ccWgSuugB07tIW5z7Rvr/PFhg61NeTz8vrrMGmSljUeeqjX0RjjH4n0Z9jkp1072L3beiWblBCvhW9zE9HuejbiFGOffAKXXKJnth98ABUqeB2RZ6ZOhVde0eTp2GO9jqYY0tKgdm0YO9brSPL06KOwcyc89JDXkfjLpk3Qp0+CjXIaEyeWOCWD0Ax5K9czKSAjAw46CI4+Ov6vnZYGK1fq/CoTA1OmwEUXQYsWmkBVTtoy+ULt2gXXXw8NG8K993odTTGVLq0L5X76KWzf7nU0/9C4sc5bHDFCR7KNSthRTmPiwH4lkkG9elCrliVOJiVkZuogqxf/0EPrOdmoUwx884322W7UCL74QpvepLBBg/Rk/sUXoWJFr6Mpge7dNQv86COvI8nT/fdD+fIpuzTYP0yZAq++msCjnMbEmCVOySDUl/nbb72OxJiY2r5dW+PGu0wvpEULbclriVOUzZ2rrbvq1IEvv4Tq1b2OyFOLFunckssvh1NP9TqaEurQQSfJ+LRcr1YtXVt53Dj7F7pzZxKMchoTY5Y4JYtAQPskb9vmdSTGxMysWdpVL96NIUJKl4YTTrAGEVG1cCGcdpqOME2erHNiUlh2tpaPHXigrqGT8EqVgosvhs8/9+3/p759tfFL//6pvU7bwIHanj3hRzmNiSFLnJJFaCHc2bO9jcOYGAo1hojnwre5pafriMCmTd7FkDR+/hk6d9aueZMnQ/36hT8nyb30EsycCY8/ruvKJoXu3bXr6wcfeB1JnqpU0ZK9r77yZQPAuPjxR3jssSQZ5TQmhixxShZt2ui9zXMySSwzE5o0gYMP9i6G0DynGTO8iyEprF6t7cb37NG+x0ce6XVEnlu7Vkc9OnWCK6/0OpooatdOk+J33vE6knz17KnT6+66S9eVTyXZ2VqiV7VqkoxyGhNDljgli4MP1hZBqV6kbZKWc94sfJtb27Y6mdzmOZXAunV6WfuPP2DiRGjWzOuIfOG227SPwogROnU1aYhAt276s9661eto8lS2rLYnX7hQ115OJSNHam+WJ55IolFOY2LEEqdkEmoQkcpF2iZpLV+u5XFezW8KKV9eL6DbPKdi2rxZy/N+/x0++wxatfI6Il/45BMdkBkwQEc+kk63brB3L0yY4HUk+brwQr0wc++9um5vKlizBu68E04+WdcrNsYUzBKnZNKunV7J/f13ryMxJupC85u8TpxA5znNm+fLpWn8bds2OP107bP94Yfacc3w11/Qqxc0baqlekmpTRs4/HDfdtcDHRgbMkSTieHDvY4mPm69FXbv1oYQSTXKaUyMWOKUTGwhXJPEMjJ0EneTJl5HovOc9u/PSeZMBLKy4Jxz4PvvtffzKad4HZFv3H+/TvkaORLKlfM6mhgJletNmuTrzippaXDuudoO3sdhRsVHH+mv4n33JekopzExYIlTMmnRQgu1LXEySSi08G3p0l5HoqNepUrZPKeI7doFF1ygEyneeEMTKAPoElZPPaWT8084wetoYqx7d73i8P77XkdSoMGDdRRw4ECvI4md7dvhppt0euEdd3gdjTGJwxKnZFK+PBx3nDWIMEknKwsWLPC+MURIlSo6NccSpwjs3asjDV9+CS+/rB8bAPbt025uhxyiJ+tJ77jjdGjDx+V6oCWTV18Nzz0HK1Z4HU1s3Hsv/PYbjBqVxKOcxsSAJU7JJhDQtZxSrZ+qSWqht7Qf5jeFpKXpKNju3V5H4mP79+vCMB99pGehSdVju+SeeUZHnJ5+Gg46yOto4iBUrjd1KmzY4HU0BXrwQShTRpt1JJtZs/S9d8MN/vqbakwisMQp2bRrpzUGP/3kdSTGRE1oLlFonWc/SE/XpMnWnM5HdrYOp4wdqzPue/XyOiJfWbVKr/qffTZ07ep1NHHUvbu+N8aP9zqSAh16KNx+O7z5pia3yWLfPrjuOqhVS9uvG+MVEeklIitEZJeIzBGRtEL2/7eIzBeRHSKyTkReF5Ha8Yo3xBKnZGMNIkwSyszUZcqqV/c6khwnnqj31pY8D87pokSvvKIzz/v18zoiX3FO55c4pwNxKdXN7Jhj4Oijfb0Ybkj//vo3p3//5Fnl46mnYP58HXGqWtXraEyqEpHuwHBgENAS+Ab4TETq57P/CcBrwGigGdAFaAq8EZeAw1jilGwaNdK/hjbPySQJ53TEyS/zm0Jq1NC5EDbPKQ/33KNnZn36wAMPeB2N74wbp+s2PfIIHHaY19HEmYiOOk2fDmvXeh1NgapW1VHByZN17d5Et2KFXsc47zxds8oYD/UBXnXOjXLOLXbO9QbWAjfms3974Dfn3JPOuRXOuUzgGSDudShl4v2CflOtWjWmTZvmdRjRNXSojscn29dlUtKaNRXYsOF4qldfyrRpa7wO528aNmzMlCmHMHnyDF90+/OFdev0Mv3o0VC/vp4gm//5668y3HBDWxo12kPz5nOZNi1JhjKK4vjj9f/U119rZwwfa9JEqFMnwE037WfkyNmUStDLzc7BXXcdC1Tl0ktnMX26Tc40MVNGRMKL2Ec650aGPhGRckBr4PFcz5sI5Le430xgkIicC3wMVAd6AJ9GLeoIpXzitGXLFjp27Oh1GNE1aZK2aNq+HSpW9DoaY0rkzTf1/sorG9OiRWNvg8nl99+170G1ah1p2dLraHxg+HAt0bvsMk2cEvUsM4ZuuAH++AO+/LI8rVqd5HU43unXTztiJMCQ7RNPwL//Db//3pHLL/c6muJ56y2t4B8+HLp1s44QJqb2OefaFPB4DaA0sD7X9vXAqXk9wTmXISI90NK8imj+8iUQ945D9l8tGQUC2s1q3jyvIzGmxDIyoHJlXW/Eb9LT9T4Bzv1i76WXNGm64AKd22RJ0z/MnAkjRui3qVUrr6PxWPfuMGOG9sT2ue7doXVr7bC3a5fX0RTdli36nmvbVufWGZNoRKQpWpr3MDpadQZQGxgR71jsP1syattW761BhEkCmZl6LaCMD8fH69XTOSop3yDirbe0VdcZZ+jHfvxheWzPHv0W1a+vra5TXmg9r3HjvI0jAqVKwWOPwerV2swj0fTvD5s3w8iR/lhA3KS8TcB+oFau7bWAdfk8527gO+fcUOfcAufcF0Av4HIR+VfsQv0nS5ySUZ06ekZnDSJMgtu5UztA+a0xRLj0dB1xSpauW0X2wQe6VlN6uraYLl/e64h8acgQWLQInn8eDjjA62h8oHFjXRDX54vhhpxyil4XGDgQtm71OprIffUV/Pe/2qfluOO8jsYYcM7tAeYAnXM91BntrpeXSmiyFS70eVxzGUucklUgYCNOJuHNmaN9Tvy8SGNamq7luXSp15F4YOJEHTlo00Yne1Wq5HVEvrR0qXbQ69ZN120yQd266ZDyqlVeRxKRxx7T+WmJsv7R7t06ynn44XD//V5HY8zfDAOuEpFrRaSJiAwH6gIvAojIGBEZE7b/R8D5InKjiBwRbE/+NDDXObc6noFb4pSs2rWDX36BTZu8jsSYYvPjwre5pew8p6+/hi5doEkT+OwzqFLF64h8yTltCFGhgk7MN2FC5XrvvuttHBFq3lwHV59+Wsv2/O7RR2HJEnjhBZ0naoxfOOfGArcBA4D5wInAWc650FWU+sFbaP9X0RbmNwM/AuOApcD58YtaiUvZ+hJVuXJll5WV5XUY0Td9OnTsCJ9+Cmee6XU0xhTLRRfB99/Dzz97HUn+nIPateH002HMmML3TwrffQenngp162otkM9bSnvp1Vfh6qvhxRfh+uu9jsaH2rTRtZ1mzfI6koisXq1Vhj166M/WrxYv1tK8rl3hjbgvEWpSmYjscM4lbapuI07JqnVrndFq85xMggotfOvnMj3Qc74TT0yhEacFC3SyR40aujKoJU352rgR+vaFE06Anj29jsanuneH2bO1QiIB1K8PvXvrRZIFC7yOJm/Z2ZqkV64MTz7pdTTGJBdLnJLVAQdA06Y2z8kkrNWrYe1afzeGCElPh5Ur4ddfvY4kxpYsgc6ddS7T5Mlw6KFeR+RrffvqcnojR1p39nyFyvXeecfbOIrg7ruhalW46y6vI8nbyy/rhZzHH7frGsZEm/0pT2bt2mnilOLlmCYxZWbqvd9HnEAbRECSjzqtWKGtxUCTpsMP9zYen/vyS3jtNbjzTr2GZfJx2GH6vyqBEqdq1eA//9GpfVOneh3N361bp2sLn3SSlogaY6LLEqdkFgjo4g0rVngdiTFFlpEBFSvCscd6HUnhWrTQ3ghJmzj9/rvOadqxQzOCo47yOiJf27kTbrwRGjWCe+7xOpoE0L27Lti+bJnXkUSsd28t2+vfX0vj/OL22/XXdMQILSM2xkSXJU7JLBDQeyvXMwkoM1PXci5b1utICle6tM5jScqFcDdu1KRpwwb4/HNtLWYK9PDDsHy5nrxWqOB1NAmga1e9T5A1nUB/rg8/rNOz/DJY9tln8PbbmqzbtQ1jYsMSp2TWrJlesrcGESbB7NoFc+cmxvymkPR0XeA0qVYA2LoVTjtN19n55JOcizEmXz/8AEOHwlVXQadOXkeTIOrV0ysPfslAInTppXod4Z57YM8eb2PJytJRziZNtDzUGBMbljgls7JloVUrG3FKBc7pWVq3bvDnn15HU2Lz5sHevYkxvykkNM9pxgxv44ia7dvhrLNg4UJ4//2cBatMvrKzdcHRgw7SifmmCLp106xz8WKvI4lY6dK6KO4vv2i7eS/df79e3xg5EsqX9zYWY5KZJU7Jrl07vXS/d6/XkZhY+uEHmDZNF5Js1w5++snriEoktPBtIo04tW2rJyxJMc9p50447zxdW2fsWF2kyhTqxRe1xPTJJ6F6da+jSTBdu+qknAQbdTr9dDj5ZC3b8+qa1dy5+p7r2VOXRjDGxI4lTskuENC6px9/9DoSE0sTJuhJx9tva0OQQAA+/NDrqIotIwMaNNCFZRNF+fKasyZ84rR7t648PH06jB4NF1zgdUQJ4ffftT11585awmWKqG5dHdUcOzahOsGKwJAhWqI7ZEj8X3/fPh3lrFlTR7+MMbFliVOyC81JsHlOyW3CBOjQIWcxycaN4fzz4YEH/NXyKUKZmYlVpheSlqZXf//6y+tIimnVKj15/ewzHT6xDCBit9yiA/svvGDdzIqtWzct1Vu40OtIiqR1a7jkEhg2DNasie9rP/sszJkDw4fDwQfH97WNSUWWOCW7Bg2gRg2b55TMVq7USUGhkYH69XXY48or4cEHNYHats3TEIvit9/0lkhleiHp6bB/f06pYUL55BNo2VJPXN99Vy9jm4h88AG8957OM2nY0OtoEthFF+lKwQnUXS9k4EAd/bn//vi95urVMGCATkUMrSNsjIktS5ySnUjOQrgmOX3wgd6ff37OtooV4ZVX9HLk55/rBJxFi7yJr4gSaeHb3Nq31/O+hGpLvm8f3H03nHOOJt1z5+a0hzaF2r4dbr5Z1xvr29fraBJcrVrQsWPCleuBrgfdqxe8/HJ8/tQ6p6/nHDz3nI1yGhMvljilgkBA/5Jv3+51JCYWJkyAY46BI4/8+3YRuOkmmDJFR5zatdPL4j6XkaFrpLRo4XUkRVelijayTJh5TmvWwCmnwODBOrM8I+Of7yNToAEDdH7TyJGJseaY73Xvrgvhfv+915EU2YABcMABeh0i1saN00Hihx/WwhJjTHxY4pQKAgG9LDV7tteRmGjbvFmHN7p0yX+ftDQtgm/aVEthBgzQejKfyszUOQPlynkdSfGkpenXsHu315EUYsoULc2bPRvGjNEz/4oVvY4qoXz3HTzzjF75T8TSUl+68ELt852A5Xo1augaSh9+GNtlCf74Q+fUtWql98aY+LHEKRW0bav3Vq6XfD76SJs/FNb57F//0i5p11yjxfjnnquLm/rMnj2a4yXySWh6uiZNvr1OkZ2tl6k7d4Zq1fTvwuWXex1Vwtm7V6eB1akDgwZ5HU0SqVFDR0HfeSfhyvUAbrtNGwT26xe78O+6CzZs0GsdZcrE5jWMMXmzxCkVVK+uM5YtcUo+EyZAvXo6clCYChXgpZe07dekSZpQ+6xN/bx5mnQk4vymkNA6Kr6c57Rxo84kv+8+6NFD12lq1szrqBLSU09pNdmzz8KBB3odTZLp3l1XlZ0zx+tIiqxSJe3Jk5mp60ZH24wZMGIE3HqrjswbY+LLEqdUYQ0iks+OHTBxopbpRTozWARuuAGmToWsLB3aeffd2MZZBIncGCKkRg1o0sSH85y++UYT7KlTtdX466/rhAxTZBs3ave088+3Za5ioksXHUpJsMVwQ666Siuj7747umvP79kD11+vPVweeih6xzXGRM4Sp1QRCGiP53gvMmFiZ+JE2Lmz4PlN+TnhBL2a27y59rG9+25fzHvKyNABtLp1vY6kZNLTYeZMX3xLtV5o2DA46SRdpTcjQ8++rA1Xsb31lv7qPfKI15EkqWrV4LTTErZcr0wZ7beydKkO8kfLkCHa5+n55+2ahzFescQpVYQWwrVRp+Tx/vu64mF6evGeX7eujj5cf73+lz/rLNiyJboxFlGiLnybW1oa/PknLFjgcSB//KGT7fv21Xltc+bojHJTIqNH67fxmGO8jiSJdeumCzIn6OLt55yjfwcefDA6C2IvXaqJerducPbZJT+eMaZ4LHFKFccdp5fBLHFKDvv2aWOIc88t2ezg8uW1bGvkSJg2Ddq08exsf+1aPU9K5MYQIaFc1tNyvVCS9PHH8MQTMH48HHSQhwElhx9/1KWurrzS60iS3Pnna2vNBC3XE9ERovXr9devJJzTCusKFWD48OjEZ4wpHkucUkXFirowjiVOyeHrr7UrXnHK9PLSs6d23Qt1Znj77egc9Y2Z5wAAIABJREFUtwiSYX5TSL16cNhhHjWIcE6T4Q4ddILF9OnQp4+V5kXJ6NF6reKSS7yOJMkddBCcfromTtnZXkdTLMcfrytADB2qCVRxjR6txQFDhkDt2tGLzxhTdJY4pZJAQLtoJeg/IRNmwgS9/HjaadE75vHH6yhFy5Z6Vtivn45sxUlGhl5gjqRBYCJIT9f8Nq5TNP76Cy67DG68ETp10jaFHTrEMYDktm+f9tQ4+2yoWdPraFJA9+66unBGhteRFNugQbBrV/GbOWzcqJW2J5wA114b3diMMUVniVMqCQR04sWSJV5HYkrCOU2cTj8dKleO7rFr19aFUXv1gscfhzPOgE2bovsa+cjM1Mqy8uXj8nIxl5ama60sXRqnF1y4UFvMv/22rtP06afa4s9EzZdfwrp1VqYXN+edp38QEnAx3JDGjXW9r5EjYdmyoj+/Tx/Yvl2fX8rO2IzxnP0aphJrEJEc5s2D1aujV6aXW7ly8Nxz8N//6pBJmzb6mjG0d68uGJsMZXohaWl6H5d5Tq+9pr/fW7fq2f2AAXaWFQOjR+uyeDY5P06qVNGmNePG+aRFZfHcf7/mf//5T9Ge9+WXOsJ5113a3twY4z37z5pKjj5a/xFZ4pTYJkzQk+Jzzont61xzjZ7179un5V5vvBGzl/r+e23vnAyNIUKOOkrLuWKaOO3cqfPTrrgiJ8E9+eQYvmDq+uMP/dW75BK9tmDipHt37RwzY4bXkRRbrVpa+TxuXM5czsLs2KENIRo3LnrCZYyJHUucUkmpUlrKY4lTYpswQYcz4lGGFQjovKdAQOfO3H57TOY9JVNjiBAR/THFrEHEsmX6DXvpJV2Ha/JkqFMnRi9m3nlHe6dYmV6cnX22NjdK4HI90HlKtWpB//6RzXt86CH45RcYMUKnsxpj/MESp1QTCOjl/V27vI7EFMfy5fDDD3DBBfF7zVq1YNIkuOUWeOop6NxZZyxHUUaGLiv1r39F9bCeS0+HlSvh11+jfODx46F1ay3Z/PhjnYFekrb0plCjR2u5VOvWXkeSYg44QEfXx4+Pa7OaaDvgAC3Z+/pr/ZUtyIIFOsX0mmugY8e4hGeMiZAlTqkmENAJJfPnex2JKY4JE/T+/PPj+7ply+oCIqNH6/BQ69Y6EhUloYVvk61jdtTnOe3ZA7fdBl276ln8vHk24SYOli2Db77R0aZke48mhG7dtNPK9OleR1Ii116rpXd33ZV/Drh/v1bfVqumbcyNMf5iiVOqsQYRiW3CBF3MuEEDb17/iit0roGI9scdM6bEh9ywQUtSkml+U0iLFjqtMCqJ0+rVOoQ1fDjceqvWAB52WBQObAozZoxWOl92mdeRpKizztIOogm6GG5I2bI6OLxokV6DyssLL+i/56ee0uTJGOMvkSVOIknSINhw6KF6s8Qp8WzYADNnxq6bXqRat9YWeB066CX4W27RUcxiSsb5TSGlS2t+WeJ5Tp98ogtcLVoE776rZ1XWoSAusrM1cercWctJjQcqVdLW5OPHl+hvjR9ceKFeJLrvPm0AEe6333S64mmn2QLLxvhVpCNOaxB5GpHmMY3GxEcgYIlTIvrwQ51VHM/5TfmpWRMmTtRmEc88A6eeCuvXF+tQGRk6PadVqyjH6BPp6ZrvbN5cjCfv26cttc45B+rV0/LIrl2jHqPJ3/TpOthnTSE81q2b/hJNnep1JCUiAkOGwJo1OngcrndvLdV74QUrCTXGryJNnA4GbgLmIfIdIj0ROSCGcZlYCgS0aH/LFq8jMUUxYQIcfjgce6zXkagyZWDYMF1oZNYsHYkqRkKekaGDKRUrxiBGHwjNcypyN+W1azUhffRRnRyRkQGNGkU9PlOw0aPhwAO9H+hNeWecoXWvCd5dD/RvwnnnweDBOeuLv/++/ol/4AE44ghPwzPGFCDSxGkuIMFbG+BFYC0iLyGShAU2SS40z2nWLG/jMJHbvl0723Xp4r9LkZdeqiWEZcroGcHLL0f81H379G2YjGV6IW3b6uKXRSrXmzpVs8lZs/TMfdSo5M0sfeyvv3TtnW7d7NvvuQoVtCnOe+9pk5QE9+ij+v565BH480+4+WadE3n77V5HZowpSGSJk3NtgMbAfcBCNIGqDFwNzEDkR0RuQiSi1QZEpJeIrBCRXSIyR0TSCtj3VRFxedyycu13UvBYu0TkFxG5IaKvLRW1aaMn31aulzi++EIXkfHrZe+WLXXeU1oa/N//Qa9eEZ3c/PCD1vknY2OIkPLloV27CBtEZGfrmdSpp8LBB+vv6BVXxDxGk7f33oOsLPsR+Eb37roS8aRJXkdSYk2barvx55+Hq67SAeaRI7WBhDHGvyLvqufczzj3CM4dCzQHppMzCtUEeBr4CZGmBR1GRLoDw4FBQEvgG+AzEamfz1NuBerkuv0C/K+9jogcDnwaPFZL4FHgGRG5KOKvL5UceCA0aWKJUyJ5/31d8PaEE7yOJH81asDnn0O/flqkf/LJsG5dgU9J5sYQ4dLSYO5cvcKcr02btHvYvfdCjx462tSsWdxiNP80erSWTZ14oteRGEA7dFStmhTlegAPPqgD9e+/r/ObQsUgxhj/Klo7cpEDEekNvA2kA6H1r/cA2UB94LlCjtIHeNU5N8o5t9g51xtYC9yY187OuW3OuXWhG9AQOAIYFbbbDcAa51zv4DFHAaOBO4r09aWSUIOISJYwN97as0e7qp13nrZp87MyZXTm81tv6RpDrVvnZEd5yMjQ9XWTvat2erpO+s7IyGeHb77RUbupUzXpfP11XTHTeGb1av1xXHGF/6pjU1b58tocZ8IEHYFPcHXr6gBzy5Z6b4zxv0jbkbdF5L/AGuApoCk60rQBuB+oB7RAE6h8r5mISDmgNTAx10MTgQ4RxtwTWOic+yZsW/s8jvkF0EZEbOA7L4GAtrdetcrrSExhpk+Hbdv8W6aXlx49NEuoUEGzhlGj8twtWRe+za19e10H6B/znJzTBhsnnaQ1OhkZcMMNyf8NSQCvvaY/HivT85nu3XVS0BdfeB1JVPTpo80yq1TxOhJjTCQiHXH6FrgKqIQmTPOCn9fHuYdxbhPOLQJWAwXNc6oBlAZy9y1eD9QuLAgRqQp04++jTQSfm9cxywRfM/dxrhOR2SIye19+y3cnO1sIN3FMmKCLP556qteRFE3z5lpudvLJcN11cP31f7tKvGmTNndM5vlNIVWqaLv1v81z+uMPuOgi6NtX243PnZu8PdkTjHNappeero0sjY+ccoquDJvgi+GGs+skxiSOopTqOeADoCPOtca5MTiXeyW6/sA1UYvuny5DY36tJAdxzo10zrVxzrUpU6ZMdCJLNM2ba9mDJU7+lp2tidMZZyRmW69q1bTM8O67deZzx466gAnw7be6S7LPbwpJS9MRtt270SSpdWv46CN44gntQnDQQV6HaIIyMzWpt7WbfKhsWV1F9oMPYOdOr6MxxqSYSBOn4UAjnLsA5/JvquvcBJwbXcBxNgH7gVq5ttcCCp5FrnoC451zuRcgWpfPMfcFX9PkVrasXt22xMnfZs/WRCORyvRyK10aBg2Cd9/VNnqtW8PMmWRk6ENt2ngdYHykpWnSNHvABOjQQT+ZPl1rdeySs6+MHq3XKWytYZ/q1k07rXz2mdeRGGNSTKTtyG/HuRUlfTHn3B5gDtA510Od0Y54+RKRADqPKq/JEhn5HHO2++eomAkJBLS4OlXLFRPBhAmaXZx9tteRlFzXrnopv3Jl6NSJjHG/0aKFo1IlrwOLjxOP05Z6Xz+eqSNv8+ZpAmV8Zdcubdp24YXagNT4UKdO2sUzicr1jDGJIdLmEEMR+QWRO3JtvyO4fUgRXnMYcJWIXCsiTURkOFAXXVQXERkjImPyeN51wDLn3LQ8HnsROFREngoe81p0DtbjRYgr9QQCuojOwoVeR2LyM2GCnmQffLDXkUTHMcfArFnsP+U0vltSlfY7p+iZarJbtIiaZwdowiK+anQtfPop1KzpdVQmDx9+qNPPrEzPx8qU0fmBH32kC20ZY0ycRFqqdz5wGPBxru0fAg2Cj0fEOTcWuA0YAMwHTgTOcs6F2rvVD97+R0SqAD2Al/I55grgLLRF+nzgHuAW59z4SONKSe3a6b2V6/nTkiWweLG2300mBx/MwkEf8BdVOH7xKzoD/7ffvI4qdl57Ddq2hc2bST+nKjPXH8l+V7SVIEz8jB4N/8/efYdHWWUPHP9eehdRQAGpIoJKZ1jKRBZFRRQENVFR1HV1bfizsSpVUMGuqGtjXQ0qNpQBKYqiqGjiUkQQkN6lCII0KUnu74+TWUJMmSTzzp1yPs8zz2gy884Bkpn3vPfcc+rWlZ4mKoqlpMiFv+nTXUeilEogoX5618u+X5fr6xuy708pyotaa1+01ja01pa31razOfZNWWu7WWu75Xr8XmttFWttvitb1tqvrLVts4/ZyFr7clFiSkiNG8vmfU2colMgIPe9e7uNwwPpc2UeVacXB0hy2K5dHr26Y9wff0g3wQEDZCPXwoX4r6jLnj2waJHr4FRetm6VLtfXXBP9I9MSXlKSDIGLk2G4SqnYEGriFNwEc1aur5+V6/sqlhgj5XrB9mYqugQCcsJ9SpGuS8SEtDTZotD45vPk5696dWkz/MIL8TGUedUq2b80bhzcfz/MmgUnn0xSknz7mLbkKmq8/bYMKtYyvRhQurTsm5w2TRpFKJXoJk+GXbtcRxEyY8ytxpi1xpiDxpj5xhh/AY99wxhj87hFvFY31MRpefb9fzCmK8acgDFdOVo693P4Q1MR4fPJHif94IkuW7ZII4VY7qZXgGMG37ZoIauePXvCwIFw/fWx3Wb4ww+lY+X69TB1KowZI3sykBy4QYP4W1yLB8HZTT4fnH6662hUSFJSZI/kxx+7jkQpt9avlwsJDz3kOpKQGGNSkI7do4E2SIO4GcaY+vk85f+Ak3Pd1gAR7xATauL0LjL4tgXwFbA9+/4sZL7Tu55Ep7zn88msoAULXEeicpo8We7jbX8T8Ntv8PPPuQbfHnecrLA9+KCcvfr9sGFDfoeITocPw513yodX8+bSNS+Pboh+v6w4xcPCWjxZuFC65etqUwzp0gXq1NFyPaWezO6FdtddbuMI3d3AG9bacdbaZdbagcAW4Ja8Hmyt/d1auzV4A5oAjcm707anQk2cnkOyQZPrBvBt9vdVLPL55F73OUWXQACaNpUT8DiT7+DbUqVgxAhJGleulH1Ps2dHOrzi2bBB9lyMHQt33CGZUYMGeT40KQm2b5c/oooeqalQrhxccYXrSFTISpWCyy+XeU579riORik3tm2Df/9b9tPGQGm/MaYc0A6YmetbM4FQZ3TcCCyx1hY4ysgLxoZ62dOY8shS2cXIcNltSFe957D2kFcBeu2UU06xb775pusw3PrpJ6hUSZpFKPcyM+HHH2Xjc926rqMJu9dfb8hbbzVg6tQ5VKyYmfeDDh2SfUIHD8oHQa1akQ2yKPbsgbVrZeW2YcNCW8dv2FCJa6/1ce+9y+nVa0tkYlQFysgwXH55J1q2/J2RI3U8Q0zZv1+WsBs1kmZHSiWazZuls82ZZ0L58q6j4a9//ethYHGOL71qrX01+D/GmDrAZuDsnM3hjDHDgf7W2mYFHd8YcxyyOvWAtXZsWIMPQeiJU5yqXLmy3Z/ocyCuuEJ2669fX/hjlffefReuvBK+/TYuB6Sed56suCxcWMgD9+yRuqlAAK6+Gl55haialpuRAcOHyx6mli1h4kRZJSyEtZIT9+wpqxzKvSlToE8fub/4YtfRqCIJXrBo1Ur3OqnEs3s31K8PF14o5w5RwBhzwFpbuYDvlzRxug14Cqhjrf0tTGGHrGjDRIypjjEdMCbpTzcVu3w+KTXautV1JApg0iQ5sz5mE1B8yMqSUr0/lenlpVo1abTw0EPS7qxrV1i3zusQQ7NlC/ToIUnT3/8u3S5CSJpAGmL4/dogIpqkpso84gsucB2JKrJSpSA5WfrIx1BHMaXC4oUXYO9eeOAB15EUxQ4gE6ley6k2EMqJ6I3Ahy6SJgg1cTKmLMa8BvwKpANf5rp94VWAKgKCg3DnznUbh5IStenT5fJ3qfgbkrpsmSwkhZwTlioFQ4fKleQ1a6Q9+6xZnsZYqC+/hDZtJAN84w1pOV6xYpEOkZQkOeDGjZ5EqIpg50758erfH8qWdR2NKpbkZDhy5GhTHaUSwf798Oyz0oSoVSvX0YTMWnsYmA/0yPWtHkg/hXwZY3xAKxw0hQgK9czsXuB6oDR/bhCRs1GEikVt2shMDG0Q4d4XX0hr+DhuQw4hrjjl1KuXJPa1a0ut31NPRb4tXVYWPPIInHuu7GP673+L3YLNnz2tQuc5uffuu3LOrd30YliHDlKup931VCIZN06u/Awe7DqS4ngauM4Y83djTHNjzFigDvAygDFmvDFmfB7PuwlYaa2dHblQjxVq4nQF0nY8uCvBAh8BB4FVgFbqx7JKleCss3QQbjQIBKBqVeje3XUknkhLk/3bIVa1HatpU8m8+vaFe++Fq66SK26RsGOHJG9Dh8rsmLlzZSNuMbVqJf/Mmji5N368bFFr3dp1JKrYjJFVp88/lxNJpeLdoUPSgvzss2NyL7S19j3gTmAoklt0BS601gY329fPvv2PMaYqko/8G4dCTZyaZN9f9r+vWHsZcDnQCNAdmbHO55OTwaws15EkrsxMKTW58MKo6IzjhbQ0KdMzxV2jrloVPvgARo+Wq8udO0sJn5fS0mRV9osv4KWXZL9VlSolOmTp0jKCRhMnt37+uUQLhyqapKRIw5ZJk1xHopT33nxTuunF5moTANbaF621Da215a217XI2irDWdrPWdsv1+L3W2irW2scjHmwOoSZOwcrv9ciGLjCmIvA5Ur43MuyRqcjy+aQ7y6pVriNJXN9/L/MY4rRMb/duWLq0GGV6uRkjG2GnT5emJu3bw8zc4yDCwFqpH09Kks0v330HN99cgqzvWH4/LFmiF8hdSk2VJLZ/f9eRqBJr0waaNNFyPRX/MjLg0Udl1mGP3NuElNdCTZyCrWoqAsEuFsOAe7L/+9RwBqUcCDaI0H1O7gQCcoLes6frSDwR/NEKW7PACy6AefOgXj35O3vssfDte/r9d7jsMpnC3qsXzJ8vH1JhlJTdi3TOnLAeVoUoM1Mu2l5wgWydUzHOGFl1+uIL+PVX19Eo5Z2JE2H1alltCtOFPBW6UBOnYC1MXWAB0gziPuAhZL/T2vCHpiKqeXOoXFkTJ1eslRKT7t3huONcR+OJ9HR5j/f5wnjQJk2klO6yy+D+++XEad++kh3zhx+gbVsZ6vPUU/LvUshQ2+Lo0EEqMrUtuRtffCGVLlqmF0dSUqTc/MMPXUeilDeslVL15s3jtjol2oWaOH0GrABOB54Esji2m96o8IemIqp0aSl50gYRbixdKmWSffu6jsQzaWlwxhkynimsKleW1miPPy4nTJ06Fa/k1FoZstupk2y8nT0b7r7bsyt65cvLQq/uc3IjNRWqV9eBt3HlrLOgWTN4/33XkSjljWnTYPFiKVePw5ElsSC0v3VrR2Btc6ydjLWzgCRgLDK5NwnpjqFinc8HCxfKSaOKrEBA7nv3dhuHR4o0+LY4jIFBg+CTT+CXX2Q5Z8aM0J+/bx9cc43sYTr7bFl16tLFo2CP8vthwYKSL5KpotmzBz76CK64AipUcB2NCptgud5XX+lAdxV/rJWRGA0bypuXKhJjMMZwUkmPU3jiZEx5jPkPxryGMdJdz9rvsPYurB2Etd+WNAgVJTp2hMOHYdEi15EknkBANv+cfLLrSDyxYgXs2hXG/U356dFD9j01aCB7k0aPLnzf09KlctFgwgQYNUqaTtSs6XGgIilJ9tqkpUXk5VS2iRPhjz+0TC8uJSfLlZqJE11HolR4zZ4tNe///KdO6y4Ga7HAFyU9TuGJk7WHkL7p1wG/lPQFVRQLbj7RfU6RtXGjnOzHcb1ysQffFkejRtIB74orYMgQ2f+0d2/ej33rLVmd2rkTPvsMhg2TstUI6dRJqi10n1NkpabCaacd7Ymj4sgZZ8hNy/VUvBk9WjrZXH+960hi2SpjqFqSA4RaIBkcfBuZy7DKjXr14KSTdJ9TpE2eLPdxvr+penXZfhARlSrJvKWnnpLVvI4dZdkr6OBB+Mc/pDyvfXspzTvnnAgFd1TVqtJFWfc5Rc7atZKoXnutNqSKW8nJ0q5y82bXkSgVHv/9rwx4vucerS8umd+Bj42hZXEPEGri9E/gEPAyxmjj1ngVbHmmK06RFQhIh5zTTnMdiWfS0iR3ieheVmOkucNnn0l74g4dYOpUaePaqRO8+ircdx/MmgV16kQwsGMlJcm1Ct1aGBnjx8uPxjXXuI5EeSYlRUp0tVxPxYsxY+Tq4803u44k1q0B9gGfGsN2Y5hmDA8W5QChnsaMRwbfng/8gjFbMGZNjtvqIoWtopfPB8uXy7RS5b1du6RuOY7L9PbuhZ9+ilCZXl66d5dSyFNPlRZqrVrB+vXw8ccyRLBMGUeBCb9fFsDmzXMaRkKwVhKn7t3hlFNcR6M806yZ/J7rMFwVD5YskQusd9whZQqq2KxlhLVcZC0nA22AVzjaITwkoSZODYFK2f9tgNrZX8t5U/EgWPSvZ3GRMW2adAeI48Tpv/+VE1bPG0MUpEEDKd35+9/lZ3zBArjoIocBHdW1q9xruZ735syBNWu0KURCSE6Wpe4NG1xHolTJPPqojN244w7XkcQ8Y7jNGILDMvcAn1nLiKIcI9TEaUOO2/o8bvrOFC/at5d7LdeLjEmTpEws+Pceh4KNIZxvxK9YEcaNk9K8hg0dB3NUzZpSqakNIryXmgpVqkC/fq4jUZ5LTpb7Dz5wG4dSJbFmDbzzjpTonXCC62jiwUBr+d0YKgPLgfXG0KMoBwh1jlNDrG1U4E3Fh+AOfm0Q4b0//pC5Q5dcEteD7NLSJDGoXt11JNErKQm+/VYWH5U3DhyQRmuXXSYXb1WcO/VUaNtWy/VUbHv8cen0evfdriOJF8GpiRcBHwGtwZs9TiqR+HySOBU2/0aVzOefy9lcHJfpWSsrTs72N8UIv1+GsuoINe8EArLfTsv0EkhKCsydK60UlYo1v/wCr78u7ccdNjCKMweNoQ6QAky0ll+AikU5QGiJkzEDCr2p+NGxI2zbBps2uY4kvgUCcNxxcPbZriPxzKpVMiLJ6f6mGOD3y73uc/JOaqpsdUtKch2JipjLL5d7nemkYtHTT0NGhgy8VUVmDHl1fhoGzAfqAV8bgwGKVIMQajupN4CClh8s0nlPxYOcg3C19ZQ3MjJgyhTo1QvKlXMdjWfS0uReV5wKVr++nNR/843u//XC5s2ywDt4cFxXxarcGjWSz7P335fRA0rFip074eWX4coroXFj19HEqkXGcJu1fBn8QvZ/nxz8f2NoBke/H4qifISYQm4qXrRsKSfzus/JO999Bzt2xPXQW5AyvWrVoEUL15FEP79fGkRohWz4vfUWZGXBAK2NSDwpKdJFc9Uq15EoFbrnn4f9++H++11HEssWA58bwzvGHE2WcrKW5dZSpOFYoSZO1+e63QiMAbYD+4Hbi/KiKsqVLw+tW2tnPS8FAvL3fP75riPxVFqaXPDVq/yFS0qC7dth5UrXkcQXa6VMr3NnaNrUdTQq4rRcT8WavXvhueegTx8480zX0cQsa0kBzgNaAT8bw93GULqkxw21q15qrttrWDsE8CPznbSrXrzx+WSWk7b5Cj9rJXE699y4Hma3f780O9AyvdAE9zlpW/LwmjcPli3TphAJ65RTJGvW7noqVrzyCuzaJbXFqkSsZRbQEhgNjAQWGkOJdrqW9DrwKuAA0L+Ex1HRpmNHOfNdtsx1JPFn0SLp8hTH3fRAmlllZWljiFA1ayYznbRBRHilpsribnCsj0pAycnyvvvzz64jUapgBw/CU0/JhdXgfnNVItaSYS2PAacDPwNfGsNbxlC7OMcrSVe9m4AA0o2iSnFeXEWx4C+s7nMKv0AAjIHevV1H4qmoGXwbI4w5us9JhcehQzI78pJLdI5YQrvsMvkF03I9Fe3eeAO2btXVpjAzhuOBBsAnSFe9q4A1xjDHGMYaQ8g7YI0NZSeyMVkU3FXvC6wt0uTdaFG5cmW7f/9+12FEn6wsmVKdnCzLxip82rSBKlXifmmhTx+5wLt8uetIYsfYsXDnnbBxI9Sr5zqa2PfRR3DppTB9OvTs6Toa5VRSknQqW7LEdSRK5e3IETjtNDjpJGkgZWKz75ox5oC11vmYcWPoCdwDnAnURBrZZQKrgWVI1dwpQDugkbWhdRoPR1e91cBtRTiOigWlSkGHDtogItzWrYOFC+O+TE8H3xaPznMKr9RUOQfpEZOX9VRYpaTA0qWaOKno9e67co4weHDMJk1R5nWgLvACcDmSQFWyltOtpa+1DLKWK6ylKVAj1IMWt6ve9cgyVxegOdauCP3PoWJGx46weDEcOOA6kvgRCMh9nCdOa9dKhzhNnIqmVSvpF6LleiX366+y0nT11VAm1ImFKn5deqlcENQmESoaZWXBmDFw1lky31GFwzfAAGt52Fo+spal1nIkrwday55QDxrax4m1qaEeUMURn0+66v3wA3Tp4jqa+BAIyBtjkyauI/FUcPCtNoYomtKl5VdNV5xKbsIEmTOt3fQUIEuPZ58t+5xGjtQr+iq6TJ4szbgmTND5HWFiLZd7cdxQm0M0wpgkjGme6+vNs7+u7cjjUYcOcq8NIsJjxw45I47z1SaQMr3KlXUERXH4/VJNtHOn60hiW2oqtG2rP4Mqh5QU2XS5aJHrSJQ6yloYPVouqF7uybm+CqNQ09p/AV8CuXsjts/++gvhDEpFiZNOgvr1dZ9TuEyhHxC3AAAgAElEQVSdKsvxCZA4BQffli7xqLnEk5Q9YWLOHLdxxLLFi2WhXFeb1DH69ZM3JS3XU9Hk889l4Nx992ldcQwINXFqm30/I9fXP0EaRLRFxSefTxOncJk0SRLRNm1cR+KpAwfgxx91f1Nxdeggc4d0n1PxpabK+ceVV7qOREWVmjWhe3cp1wulo7BSkTB6NNStCwNC7oitHAo1cTo++/5grq8fzr4PuRuFijEdO8pO/19/dR1JbNu/H2bOlNWmOK+tnz9f9pbo/qbiKV9efu10n1PxZGTAW2/J/uqaNV1Ho6JOcjKsXg0LFriORClpOz57Ntx7r7z5q6gXauK0K/s+d/Hlpbm+r+JNcBCurjqVzMyZMhE8Acr0goNvNXEqPr9fzuv27XMdSeyZORO2bdMyPZWPfv1kOVKH4apoMGaMzMy88UbXkagQhZo4pSMleS9izGsYcw/G/Bt4CRmMm+5VgMqxtm2lw4smTiUTCMDxxx8d1BPH0tJkj6te7S8+v18aWga7E6rQpabKeYh29FV5qlFDBntpuZ5y7ccfZe/znXdKNyUVE0JNnMYiCVIZ4DrgcWSWU9nsrz/jRXAqClSpAmecoYlTSRw5Ah9/DBdfHPcbP62Vk33d31QynTvL9Qot1yuaXbukq++VV0K5cq6jUVErOVkGjc6d6zoSlcjGjJHBfbfd5joSVQShJU7WfgncCRxBVp6Ct8PAXVj7lVcBqijQsaMkTnp1rni++UbO6Pr2dR2J5zZsgK1bNXEqqapVpYeINogomvffh0OHtExPFeKSS6BsWe2up9xZsULesG69VapRVMwIfcqWtc8DTYAbgaHZ902yv67imc8Hv/0Ga9a4jiQ2BQJQsSKcd57rSDyng2/DJylJRqgdOuQ6ktiRmgotWkC7dq4jUVGtenU4/3w5cc3Kch2NSkSPPy7NIO66y3UkqoiKNp7Y2s1Y+xrWjs6+3+xRXCqaBBtE6CDcorNWEqfzzoNKlVxH47n0dMkRW7Z0HUns8/uln8i8ea4jiQ0rVkjifu21cd+4UoVDSgps2nS0m41SkbJxI4wfDzfcALVru45GFVFoiZMxgzDmC4y5JdfXb8n++j1eBKeixBlnyNmw7nMqugUL5E0yAbrpgZy4dugQ91u5IqJrV7nXfU6hGT9e9oVdfbXrSFRM6N1brvhruZ6KtKeekouqgwa5jkQVQ6grTtcCZ/Pn7nnfAt2QRhEqXpUpI7UvDhOn1atjdItVICBncxdf7DoSzx08CD/8oPubwqVmTWjeXPc5hSIrC958U5ql1anjOhoVE6pVg5494YMPtFxPRc6vv8Krr8oVngYNXEejiiHUxKlh9v2yXF9fkX2v//rxrmNHWT05ciTiLz1rFpx6KvznPxF/6ZILBGSzygknuI7Ec8EfD93fFD5+P3z7rbQmV/mbPVsak2hTCFUkKSmwZQvMmeM6EpUoxo6Vq4z33ec6ElVMoSZOwYrxRrm+3riIx1GxyueTXeqLFkX0Za2FIUPkvx9+2EneVnyrVsFPPyVUmR7oilM4JSXBnj2weLHrSKJbaqosICTIr5oKl4sukjJ0HYarIuH33+GFF+DSS+H0011Ho4op1IRndfb9SxhTDyD7/l+5vq/iVbBBRITL9aZPl54Ul14qYzfGj4/oy5dMICD3ffq4jSNC0tOhUSPd6xpOwXnJWq6Xv3374MMPZTRPxYquo1ExpUoVmZQ8caIu6yrvvfiiJE8PPOA6ElUCoSZOAWTVyQ+sx5i9wHogCRmA+5E34amo0aCBbLqIYOJkLQwbBo0bw4QJ0L49PPJIDK06BQIyjKdhQ9eRRERampbphVv9+vKrpw0i8vfhh7B/v5bpqWJKToZt2+ArHUepPHTgADzzDFxwAbRt6zoaVQKhJk6PI/uZgoNvK+f47xXAk55Ep6KHMUcH4UbIpEnSbGD4cChXTu7XroW33opYCMW3bRt8913C1A5t2gSbN2uZnhf8fllxisnmKBGQmgpNmkCXLq4jUTGpVy8ZFaHlespLr70mjSEGD3YdiSqh0BIna/cBXYCXgc1ARvb9i9lfP9Gj+FQ08flg2TLZdOGxrCwYMQJOOw3695evXXSRXKh55BHIyPA8hJL5+GM5002QxEkH33onKQm2b4eVK11HEn3Wr4cvv4QBA3R2kyqmSpWk6+mHH8bAB4uKSYcPwxNPyIyJYP21ilmhN3WwdifW3oq1p2BtOaAl8BMwGVjlUXwqmvh8kgxEYCLn++9LX4WRI4/OBDJGVp1Wr5bSvagWCMiGn7POch1JRKSnQ4UK0KqV60jij+5zyl9w9XnAALdxqBiXkgI7dkgWrlS4vf22zHPU1aa4ULRueMaUxZh+GPMR8AvSHKILR7vuqXjWoYPce1yul5Ehq01nninl5zn17i0n5w8/HMUXB/fuhc8+g759E+YyeFqajPoqV851JPGnWTPZXqj7nI5lrZTpnX12wmwjVF7p2VMaRegwXBVumZnw6KOy3/mCC1xHE1WMMbcaY9YaYw4aY+YbYwpcjjPGlDPGjMp+ziFjzAZjzB2RijcotMTJGD/GvAJsBT4A+gDlOZowbfYkOhVdatSQgUoeJ05vvw0rVshqU6lcP6HBVaeVK+Hddz0No/g++USW5hOkTO/QIZnhpPubvGGMrDpp4nSs9HR5H9CmEKrEKlSQ7qcffRRD3YdUTPjoIzmhGTw4YS6khsIYkwKMBUYDbYDvgBnGmPoFPO1d4ALgJqAZcDkQ2Rk5gLH57Tg2phlwDXAVRwfc5v5Xt8D5wCzyPVB0q1y5st2/f7/rMGLH1VfLtMlNmzw5/JEjcoW9enWYPz/v95msLGjdWnKTJUugdGlPQim+/v1h5kzYujUKgwu/77+XvU0ffgj9+rmOJj49+yzcdZdUe9Sr5zqa6HDzzfDmm/JrVrWq62hUzPv4YylpmD5dVqCUKilrZWP2H39E6cmKN4wxB6y1lQt5zPfAImvtjTm+thKYaK39U792Y8x5yMJNE2vtjnDHXBQFrTgtAx4AGnK0g95u4E3g3v89ytrPYzVpUsXg80n7tM3eLDK+/rp0znvoofwvzpQqJatOy5dHYSOkw4dh2jT5AE6QN0ltDOG9pCS511UncfCgVFX166dJkwqT886D447Tcj0VPjNmwMKFcP/9CXM+EApjTDmgHTAz17dmAp3zedolwFzgbmPMJmPMSmPMc8aYKh6GmqcyITzGIstjqcAXWJuBMWcQJy3Ia9SowezZs12HETuaNIEnn4S5c8Pe5uvwYcOwYR1p3vwwlSotoKB/lho1oGHDDjzwANSqNTd63pP27JHhU6eeSoF/gDgyZUoLateuxooV6axY4Tqa+JSZCZUqdeXdd7dx8snaXu/LL2uye/cZtG79I7Nn73IdjooXzz4Lu3dLkwgtq1IltXEjPPecDONLkPOBbGWMMTm7iL1qrX01x/+fCJQGtuV63jbg3HyO2RjoChwCLgWqA88DdYDLwhF0qAoq1ctCkiaAP4BPkGWyaUjp3mLAYm2RT1mNMbcCg4CTgSXAndbafK+lZmenQ5HSwTrIX+6T1trnsr9/HfB6Hk+taK09WFAsWqpXRAcPQrVqcM89MGZMWA/9wgswcKD0VTg3v1+dHN57D664QvY6paSENZTiu/VWGD9e5jVUrOg6moho0EBWm/RCrbd69pTP4Z9+ch2Je716waJFsG6dXshVYTR9uvxwTZkiLcqVKq6vv5bONc8/D7ff7jqaiCqsVM8YUwfpjXC2tfbrHF8fDvS31jbL4zkzAT9wkrX29+yvnQd8mv213EmYZwoq1UvnaIleJaAvMAHYDrxS3Bf0cEPYASQR+9+tsKRJFUOw53SYG0QcOCDzmZKS4JxzQnvOZZdB8+ZS1peVFdZwiicrCyZPls45CZI0/fILbNigjSEiwe+XMvmdO11H4tbWrfDpp3DNNZo0qTA791w4/vgorAFXMWf0aKhVC264wXUk0WgHkAnUzvX12kgTurxsATYHk6Zsy7LvC8ofwi7/xMnazsCpwEhgJUeTqArA0dMkYyZgTFF2Ut4NvGGtHWetXWatHYj8hdyS14OzM8pzgAuttZ9Za9dZa7+31s7+U8TWbs15K0JMqih8PinVy8wM2yFfeklOiAra25Rb6dJSFbdkiTSucW7ePMkkEqSbHkhnM9D9TZEQ3Oc0Z47bOFx7+21569HZTSrsypWTjXOTJ0t1hVLFMX++XN25666EuYhaFNbaw8B8oEeub/VAFlPy8i1QJ9eeptOy79eHN8KCFdyO3No1WDsSWTbrhMxt2sGx3fVSgI9DeTGPN4RVNMasz37MVGNMm1BiUsXg88msouXLw3K4fftkzEGPHkdPDkOVnCxd+EaNioJVp0mTZFpvr16OA4mc9HQ512ijv22e69ABypdP7AYRwdlNPh+cfrrraFRcSk6Wz7cZM1xHomLVmDHSaOSWPNcDlHgauM4Y83djTHNjzFhkK87LAMaY8caY8TkePwHYCbxujDnDGNMFqV6baK3dHsnAQx+Aa+33yOpQHaA38D5wkKMrUaEoaEPYSfk8J7ghrBWyIex2pGzvjRyPWQ78DZkvdWV2XN8aY5rmdUBjzE3GmHnGmHkZUTtFNYr5fHIfpnK9556Toe0PPVT055YuDUOHwuLFEAiEJZziCwSgWzcp9UgQaWnSbbV8edeRxL/y5eVX7+uvC39svFq4UH7XdXaT8kz37nDCCVqup4pn2TIpgRk4UJInlSdr7XvAnUj/goXIef6F1trg6lF9cpTgWWv3IY0jjkMWU94HvkLO/SMq/+YQIT3bVEX2G/XH2kJ3pkRqQ5gxpjTyD/GltbbAqcLaHKIYsrIkOejfH158sUSH2r0bGjWCLl1g6tTiHSMjA1q0gEqV4IcfHDVD+vln2XD1wgtw220OAoi8w4ePXlR7+mnX0SSGoUNldXb3bqgS8Sas7t15p5T1btkinTWV8sQ//iE1odu3yweLUqG67jr44ANYvx5OPNF1NE6EMscploW+4pQXa/di7X9CSZqyRWRDmLU2E5gH5LnipEqoVCmpGwrDitMzz8hJ4KhRxT9GmTJyQvnjj9IMyYnJk+W+Tx9HAUTeokWyDUAbQ0SO3y/7e4KzsxLJkSMwYYI0O9OkSXkqJQX275cue0qFat06eOstuOmmhE2aEkHJEqciitSGMGOMAVoiSZfygs8nmcoffxT7EDt3SuLUr5+Ue5XEVVfJiKmRI2UfRMRNmiTJZL16Dl7cDR18G3mdO8t1i0Tc5zRjhnT51zI95bmkJOmIpjMWVFE88YS8Qd9zj+tIlIcimjhlC/uGMGPMCGPM+caYxsaY1sBrSOL0cgT/XInF55MauYULi32IJ5+UxhAjR5Y8nDJlYMgQKdUrbslfsf3yC3z/fUJ10wNpDFG3LpxyiutIEkfVqtKIIxH3OaWmQs2a0u1fKU+VKSPzLqZNkw8ppQqzdSu89ppc2UmgC6iJKOKJk0cbwqoDryIlfDOBukCStTa8w4bUUSVsELFtmzSFuOIKOPPM8IR09dWyX2rUqAivOgXrAxMscUpL09UmF5KSJE8/dMh1JJGzcyd8/LFsqyxb1nU0KiGkpEhFRcSvxKmY9MwzUk/8z3+6jkR5zMWKE9baF621Da215a217XI2irDWdrPWdsv1+OXW2vOstZWstXWttbdZa/fm+P5d1toG2cerZa0931qbgLsAIqhOHbmqUszE6bHHZH/MiBHhC6lsWVl1mjcvwp1kAwFo2lSaQySIbdtg7Vrd3+SC3y+/O/PmuY4kct59V85JtExPRUyXLnDyyVqupwq3a5c0ykpOlnMBFdecJE4qTvh8cum7iDZvls5Y11wjM5jCacAAaNAggnudfv8dvvgC+vZ11M7PDR18607XrnKfSPucUlOhZUto3dp1JCphlC4Nl18uV+H27HEdjYpmL7wgJZ0PPOA6EhUBmjip4vP5YPVqqaMpgtGjZXvU8OHhD6lsWRg8WBbCPv00/Mf/k+nT5VJ4gpXppafL33W7dq4jSTw1a8riZqIkTsuWwdy5utqkHEhOlppYZ+1aVdTbtw+efVbafbZs6ToaFQGaOKniC+5zmjs35KesXw/jxsHf/gaNG3sT1nXXQf36EVp1CgSgdm3o2NHjF4ouaWnSpKBCBdeRJCa/H+bMkdbk8S41VS7+9+/vOhKVcDp1kpJ0HYar8jNuHPz2m1yxVQlBEydVfO3aSXlaEfY5PfywPGXoUO/CKldOVszT0+Hzz717HQ4dkhWnPn2kBWmCyMiQXFnL9NxJSpLqocWLXUfircxMePNN6aRXO/f0P6W8VqqUlOt98okMHFQqp0OHpD3wX/+qH4gJJHHO9lT4VasGLVqEnDitWgWvvy5D2b1uYX399XKh0NNVp1mzZJk+wcr0Fi+GAwe0MYRLfr/cx3tb8lmzpNu/lukpZ1JSpBw7OORcqaDx4+UNSlebEoomTqpkgg0iQshORo2SfTGR2D9Zvjzcfz98+630bvBEICCDdbp39+gFopMOvnWvfn1pghLv+5xSU6F6ddk+oJQTPp/8sml3PZVTRgY8+qgMvj/nHNfRqAjSxEmVjM8HO3bAunUFPmzZMnj7bbj9dunwGgk33CBd00eN8uDgmZlyBfLCCyVLSyDp6XDSSXIuodzx+2XFKaIzyyJozx6YNElmveleOuWMMdIk4rPPitwIScWx99+HNWtktSmBOuoqTZxUSYU4CPfBB6FixcjOhqtQQVadvv4aZs8O88G//x62b0+4Mj04OvhWPyvc8vvlR3DlSteReOODD2T+qJbpKedSUmSFIRBwHYmKBllZMGaMbFXo3dt1NCrCNHFSJXPWWZKhFJA4LVokF2f+7/+klXIk3XijrHCNHBnmA0+aJHWHPXuG+cDRbccO2aum+5vcS0qS+3gt10tNhdNOS7iGlSoatW0rbWC1XE8BTJ0KP/0k+w4SqDGUEvovrkqmbFn5UClgEO6IEXDccXDvvRGMK1uFCnDffbLiFLaN9NZK4nTOOfIHSyA6+DZ6NGsmFyLisUHEmjWSEF57ra5sqihgjKw6ffEF/Pqr62iUS9bCI49Ao0ZSR6wSjiZOquR8PliwQDoP5TJvnlQ33H03HH+8g9iAm26SVsZh2+u0dKkM/k3QMr0yZaB9e9eRKGOkXC8eV5zGj5c/3zXXuI5EqWzJybK39aOPXEeiXPryS6mwue8++TBUCUcTJ1VyPp9sRliy5E/fGj4catSAO+90EFe24N6qWbOky16JBevcE7C2OT0dWrWCSpVcR6JAEqe1a2HTJteRhE9WliRO3bt7P7ZAqZC1aiW1ozoMN7GNHi31/7r5MmFp4qRKLp8GEd99BzNmSNJSrZqDuHK4+WaoVStMe50mTZJatUi1B4wSmZnyT6xletEjHvc5zZkjyaCel6ioEizXmz0btm1zHY1y4fvv5QrsPfdoq88EpomTKrnGjeGEE/6UOA0bJsnK7bc7iiuHSpVg0CDpKBucQ1QsGzfC/PnQt2/YYosVS5bIvF9tDBE9WrWSUWLxtM8pNRWqVIF+/VxHolQuycmyJDpxoutIlAujR8ueg3/8w3UkyiFNnFTJGXN0EG622bNlH+3990Plyu5Cy+mWW+DEE0u46hScHp+g+5tAV5yiSenS0KVL/Kw4HTggbcgvuyx63jeU+p8zz5QW1Fqul3gWL4YpU6Q9cJUqrqNRDmnipMLD55Mlib17sVZWm+rUkRK5aFG5snT2+/TTApsAFiwQgObNpdY9waSnSxe3xo1dR6Jy8vvlVy8eZnNOmgR792qZnopiyclypeKXX1xHoiLp0UflJGLgQNeRKMc0cVLh4fNJm84FC5g5U/YpDBkijRmiyW23SVVhsTrs/fabLKUl4GoT6ODbaOX3y/2cOW7jCIfUVGjQ4OjeLaWiTnKyfNZpuV7iWL0a3n1XylZq1HAdjXJMEycVHtkNIuz3/2XYMKhfH264wXFMeahSRfZ1Tp8Oc+cW8cnTpkmHhATc3/Tbb7B8ue5vikYdOkD58rFfrrdpE3z+OQwYoDMlVRRr3lwGv+sw3MTx+OMys/Luu11HoqKAfjyp8DjxRGjcmKmBDObOlTbk5cu7Dipvt90m+zuLvOoUCEDdutCunSdxRbNgaaMmTtGnQgW5bhHrDSLeeksu5A8Y4DoSpQqRkiJtYzdudB2J8trmzfDGG/C3vyVcJ12VN02cVNhkdejIsHm9adIkuk9+qlWTC0dTp8rc3pD88Qd88gn06ZOQl8PT0uSPrYNvo1NSkvws79vnOpLisVbK9Lp0gVNPdR2NUoVITpb7Dz5wG4fy3tNPS6XJoEGuI1FRIvHOAJVnPqpwFT8eOYMR/7ebsmVdR1OwgQOhevUirDp99pm0/ErQ/U3p6dCypTYTilZ+v3y2l6jVvkNz58LPP2tTCBUjmjaFNm20XC/e7dwJL78MV10FjRq5jkZFCU2cVFhkZsKIr7pzOsu4ql701wwddxzcdZd0F1+4MIQnBALypG7dvA4t6mRlSametiGPXp07y4pgrO5zSk2VksPghXylol5KiswuXLfOdSTKK889JxdM77/fdSQqimjipMLi3Xdh6bpKjDQjKT2vuL2+I+uOOyQXKnTVKSND5jdcdBFRv5TmgWXLYM8e3d8UzapWlQvgsbjP6dAheOcdWcw97jjX0SgVossvl3ud6RSf9uyRxKlvX5ndpVQ2TZxUiWVkyFDZli3hslYr5SpcDKheXWbZTZoEixYV8MDvvpMl+wQt09PBt7HB75eVwUOHXEdSNFOnwq5dWqanYkzjxtLSUhOn+PTyy7B7NzzwgOtIVJTRxEmV2JtvwsqVsnJTqmMH2bCQleU6rJDceac0i3jooQIeNGmStAi84IKIxRVN0tNl9lXTpq4jUQVJSoKDB2H+fNeRFE1qqjSr6tHDdSRKFVFysvzCrVrlOhIVTn/8IU0hevSQ5FipHDRxUiVy+LCsNrVvD717I32Rf/9dMqkYcPzxUrI3cSL89FMeD7BW9jf16JGwnRF08G1s6NpV7mOpXG/7dpgxA66+GkqXdh2NUkWk3fXi0+uvw7ZtMHiw60hUFNLESZXIf/4D69fLapMxQMeO8o0YKdcDWXWqUiWfVadFi2Tzb4KW6e3eDUuXapleLKhZU2ZzxlKDiHfekVLfaB5foFS+6teXzZ/aXS9+HDkiA287dYKzz3YdjYpCmjipYjt4EB5+WDp6/a+K7fTTJQv5PjYaRICUoQ0cKBcNly7N9c1AQDLCiy92EptrwfxXG0PEBr8f5syRLpexIDUV2raFM890HYlSxZScDD/+CMuXu45EhcM778jV4CFDtMxC5UkTJ1Vsr7wiQ7UfeijH+0vp0lK3F0MrTiADcStVkkTwGJMmyVTOWrWcxOVaWpr822qZd2xISpJmUIsXu46kcIsXww8/aFMIFeO0u178yMqCMWOk09WFF7qORkUpTZxUsRw4IO8v3bpB9+65vunzyXCkGGrvdeKJcPvt0lb955+zv7h2rVxJ7NvXaWwupafLakC1aq4jUaHw++U+FvY5paZCmTJw5ZWuI1GqBOrWlQ2GWq4X+wIBOQEYPFhXm1S+NHFSxfKvf8neyTz3BXXsKHXCP/4Y8bhK4p57oGLFHKtOkyfLfZ8+zmJyKStLEifd3xQ76teXW7Tvc8rIgLfegl69ZG+WUjEtJQWWLJGbik3WwujRcOqpcNllrqNRUUwTJ1Vke/fCY4/B+ecf7eR1DJ9P7mNonxPICdytt0qJ84oVyNWns86CJk1ch+bEihXSHEL3N8WWpCRJnKx1HUn+Zs6UCy9apqfiwqWXygqFluvFrpkzpbX8/fdri09VIE2cVJGNHSvzYEeNyucBdevKYJYY2+cEcO+9MrLpkWEH5ewzQbvpgQ6+jVV+vyQl0TwRIDVVmrL06uU6EqXC4OSTpQPb++9H9xULlb/Ro6FePbjmGteRqCiniZMqkl274MknZWZTcGHpT4yRb8Zg4lS7NtxyC7w9sRyrshol9P6mtDSoXh2aNXMdiSqKpCS5j9ZyvV27pAr2yiuhXDnX0SgVJikpsj8mFjqzqGPNmSMbQ++9V9+UVKE0cVJF8vTTMt8239WmIJ9Par127YpIXOE0aBCU5QiPVB4NrVu7DseZ4P6mUvouEVOaNZOy02htEPH++9I3Rsv0VFzp10/eLLVJROwZM0Y6RP39764jUTFAT4lUyHbsgGefle6rrVoV8uDgINx58zyPK9xOqrqff5hxvHngUtasTczOOnv2wE8/aZleLDJGyvWidcUpNRVatIB27VxHolQY1aolLWa1XC+2LFwI06fDXXdB5cquo1ExQBMnFbInnoD9++HBB0N4cPv2ch9jDSIA+PRT/pk5mjJlpOw5Ec2dK5/92hgiNvn90k1/0ybXkRxrxQopAb32Wu32q+JQcjKsWiUDylRsGDNG5m3ceqvrSFSM0MRJhWTrVnj+ebjqKrlaXKjjjoPTT4/JfU4EAtSpcYibbjKkpsK6da4DirxgY4h897GpqBat+5zGj5dqpquvdh2JUh7o1086sml3vdiwYgV88AHcdpts6FUqBJo4qZA8+igcPgwjRhThScEGEbFUtnDkCEydChdfzH0PlKJUqcRcdUpPlwRZP0tiU6tWULVqdCVOWVnw5pvQowfUqeM6GqU8cMIJcO65ss8plj73EtVjj0kb3TvvdB2JiiGaOKlCbdoEL78s5TVNmxbhiR07Sl/kjRs9iy3svvlGGlpccgl168pe0TfegPXrXQcWOdbq4NtYV7o0dO4cXQ0iZs+GDRu0KYSKcykpUqYQg/t7E8qGDbIEfuONsj9NqRBp4qQK9cgjcrV42LAiPjEWB+FOmgQVK8J55wEyCw9kxS1RrFolc7p0f1NsS0qCJUvk3zIapKbKVoIEHo2mEsEll0DZsiZYTDMAACAASURBVNpdL9o9+aTc33uv2zgSmDHmVmPMWmPMQWPMfGOMv4DHdjPG2Dxup0cyZtDESRVi3Tp47TVZeWnYsIhPbtlSZiLEyj4nayEQgPPPh0qVADjlFLjhBvk7iKWFs5II7m/SxCm2+bM/gubMcRsHwL598OGHsne+YkXX0SjloeOPlwtv778vVxxV9Nm+HcaNk2G39eu7jiYhGWNSgLHAaKAN8B0wwxhT2D/IGcDJOW4RH/WuiZMq0EMPyWbuIUOK8eRy5aBNm9hJnBYskLrEXJfEH3hA7hNl1SktTVYGmjd3HYkqiQ4dpHw/GvY5ffihdOTUMj2VEFJS5EpbLFVbJJJnn5Vhcvfd5zqSRHY38Ia1dpy1dpm1diCwBbilkOdtt9ZuzXHL9D7UY5WJ9AtGmxo1ajB79mzXYUSlTZsq8sYbPvr23czKlatYWZy8/rbbZABULPwd//KLLN/Xq/eneM877zTGjTuJbt3SqVnzsJv4IuTzz9tx2mlH+PrrRa5DUSXUrFlrpk0rxUUXLXAax9ixrahTpwJHjnwfE28FSpVInTrw1FNS93zokOtoVE6ZmbKn6d//hi1b5KbCrYwxJucmv1etta8G/8cYUw5oBzyZ63kzgc6FHHueMaY8sBR42Fr7ZTgCLgpjE7zzS+XKle3+/ftdhxGVrr5atvysXg0nnVTMg7z9thxo0SI466ywxhd2Z54JNWvCl3/+PVy3Thpj3HILPPdc5EOLlH37pJP8kCEwapTraFRJDR0qK6W7d0OVKm5iWL9eynxHjoThw93EoFTEXXKJDMTbuFHKNlR0GD1aPuB++AFat3YdTVwyxhyw1uY7TdgYUwfYDJxtrf06x9eHA/2ttc3yeE4z4K/AXKAccA1wc/YxIlpXob/NKk9Ll8KECXD77SVImiB2GkSsXCk76fv2zfPbDRtKmdGrr8rCVLyaN0/K8nV/U3zw++UCa3Dfmgtvvin3Awa4i0GpiEtJkQ+Lb791HYkKOnAAnnkGLrxQk6YYY61dbq192Vo731qbZq29FfgEGBTpWDRxUnkaMQIqV4ZBJf2RPPVUGQYU7fucJk+W+z598n3I4MGQkQGPPx6hmBwInmB37Og2DhUenTrJxW5X+5yslY6/Z59djOYySsWyiy6CChV0GG40+fe/ZevA4MGuI0l0O4BMoHaur9cGthbhON8DRRmSExaaOKk/WbgQJk6Eu+6CE08s4cGMOToIN5oFAtLIokGDfB/SuLE04Xnllfgti05Ph2bNoEYN15GocKhWTX6sXSVOaWmymKtNIVTCqVoVevWSD9PMiO9fV7kdPgxPPCFzGrp0cR1NQrPWHgbmAz1yfasH0l0vVK2RhhIRpYmT+pMRI2SR6O67w3TAjh3hp5+krVY02rYNvvsupAEzQ4bAkSNHR0DEE2vlRFfL9OKL3y8JsYs96qmp0tn/sssi/9pKOZecDFu3Rtck6kT15pvSNVdXm6LF08B1xpi/G2OaG2PGAnWAlwGMMeONMeODDzbG3GmMucQY09QYc4YxZgxwCfBCpAPXxEkd47//hSlT4J57JHkKC59PrrgtcNvZK19TpkjWkM/+ppxOPRX694eXXpJ8K56sWQO//gp/+YvrSFQ4JSXBwYMwf35kX/ePP2QGaL9+cvFdqYTTq5dcOdByPbcyM6VLTtu2/xtur9yy1r4H3AkMBRYCXYELrbXrsx9SP/sWVA54AlgEfJP9+F7W2o8iFnQ2TZzUMYYPhxNOgP/7vzAetEMHuY/Wcr1AQOrwzjwzpIcPGSJX7+Nt1Sk9Xe51xSm+dO0q95G+6D1lCvz+u5bpqQRWubLsdfrwQ9kgq9yYOFFaww8eLNsHVFSw1r5orW1orS1vrW2Xs8OetbabtbZbjv9/3Frb1Fpb0Vpbw1rrt9ZOdxG3Jk7qf+bMgU8/lZlwYb1CXLu27B2KxsRp7174/HMp0wvxDfW00+DKK+HFF2UAebxIS5OW1Wec4ToSFU41a8ow40jvc0pNlZFof/1rZF9XqaiSkiJL+TrAzA1rpQX56aeHVFWiVGE0cVL/M2yY5Di33ebBwaO1QcSMGbJpNIT9TTkNHSqlSE8/7VFcDqSnyz9T6dKuI1Hh5vfLhZFI7VHfskUuwlxzjf48qQTXs6dckXrvPdeRJKbp02WO5AMP6DwtFRb6U6QA+OILuSA2eLCUZIddx44yRTbalmgCAbkk37mwYdXHOv10uOIKeOEF6W4a6w4cgB9/1P1N8crvhz17YPHiyLze22/LPDAt01MJr2JF6N0bPvpIOgupyLEWHnlEKl6uvNJ1NCpOaOKksFZWm+rVg5tu8uhFgoNwo2nV6fBhmDZNPtSKcVl86FBJOOJh1Wn+fCnB1/1N8SkpSe4jUa5nrZTpdewore2VSngpKfDbbzBrlutIEsvXX0sN+j//CWXLuo5GxQlNnBSffCLduIcMkXl9nmjbVpbJoylxmj1bLsMXsUwvqEULuPxyeP552LkzvKFFmg6+jW/168stEg0ifvhBpg/oapNS2c4/X4aqableZI0eLfsPrr/edSQqjmjilOCslU56DRvC3/7m4QtVrixd66IpcZo0SeI699xiH2LYMNi3D559NoxxOZCeLq3Wa9Z0HYnySlKSrDhZ6+3rpKZCuXJykV0pBZQvLxfoJk2SSgflvXnzYOZMGUhZsaLraFQc0cQpwU2ZIu8vw4fLyY6nOnaUxMnrM7dQZGXB5MmycbcEy2xnninDPZ97DnbtCmN8EaSDbxOD3y+zx1au9O41Dh+GCROk+rVGDe9eR6mYk5ws/flnznQdSWIYPVqGUd58s+tIVJzRxCmBZWXJiknTptL9ynM+n2QXq1ZF4MUKMXeutP4qZpleTsOGScVfrK46rV8vw+21MUR8i8Q+pxkzpFmKlukplUuPHnD88ToMNxKWLpXVvYEDpURSqTDSxCmBTZwoXbYefBDKlInAC0ZTg4hAQP7QF15Y4kO1bCnjIcaOhd27wxBbhOng28TQrJmUYnq5zyk1FWrVki0dSqkcypWTD4pAAA4edB1NfHv0UWkPfMcdriNRcchJ4mSMudUYs9YYc9AYM98Y4y/k8eWMMaOyn3PIGLPBGHNHrsdcaoxZmv39pcYYnXRWgMxMGDFCGhxEbC9CixbyZhYNidOkSdCtm1wBDIPhw6UK47nnwnK4iEpLk3+Ws85yHYnykjFSrufVitPOnTB1KvTvrw2slMpTcrIMXf/0U9eRxK+1a6Ve+B//gBNPdB2NikMRT5yMMSnAWGA00Ab4DphhjKlfwNPeBS4AbgKaAZcDi3IcsxPwHvA20Dr7/gNjjPYIy8eECfDzzzByZAQHVJYpA+3auU+cfv4Zli8PS5leUOvW0KcPPPOMJFCxJD0dOnSI0Kqjcsrvl/OKTZvCf+x33pExNVqmp1Q+uneHE07Q7npeeuIJOam55x7Xkag45WLF6W7gDWvtOGvtMmvtQGALcEteDzbGnAecA1xorf3MWrvOWvu9tXZ2jofdCXxprX0k+5iPALOzv65yOXJEEqbWraFfvwi/eMeO0q/YZWehQEDu+/QJ62GHD5dSveefD+thPXXwoPxz6P6mxODPXtv3YtUpNRVatZKbUioPZcvKh+6UKTIEUIXXli3wn//AdddB3bquo1FxKqKJkzGmHNAOyN1WZibQOZ+nXQLMBe42xmwyxqw0xjxnjKmS4zGd8jjmpwUcM6GlpsLq1TBqlIxWiiifDw4dgkWLCn+sVwIBWWKpVy+sh23bFi66SAbi7tkT1kN7ZsECSaR1f1NiaNUKqlYNf+K0dKl05xwwILzHVSrupKTA/v3SSUWF1zPPyAfaP//pOhIVxyJ92nwiUBrYluvr24CT8nlOY6Ar0Aq4FLgdKdt7I8djTirKMY0xNxlj5hlj5mVkZBQl/ph36BA89JDkLxdd5CAA1w0iNm+G778Pa5leTiNGSOPAf/3Lk8OHXXDwra44JYYyZaBz5/A3iEhNleqY/v3De1yl4s7ZZ0uXFi3XC6/ffoOXXoIrroAmTVxHo+JYLHTVKwVY4KrsEr1PkeTpUmNM7eIc0Fr7qrW2vbW2fZkE29jx2muwYYMkT8Y4CKB+fWm75SpxmjJF7j1KnNq3l0Z9Tz0lg3GjXVoaNGokw9VVYkhKgiVLpJlDOGRmwltvwQUX6M+RUoUqU0aG/02dKitPKjyef14+dO+/33UkKs5FOnHaAWQCuT9eawNb83nOFmCztTbnlvtl2ffBhhJbi3jMhPTHH/Dww9C1q4yUcMKYo4NwXQgE4LTToHlzz15ixAg5KY2FVaf0dC3TSzTBfU5z5oTneJ9/Dr/8ok0hlApZSop8IE+d6jqS+LB3r8wD6d1b28Mqz0U0cbLWHgbmA7lP23sg3fXy8i1QJ9eeptOy79dn36cV8ZgJ6eWXZe/kww87Wm0K8vmks12k28/t3g1ffCGrTR7+Bfh8cvX9ySeje9Vp40apXNQyvcTSoQOULx++fU6pqVC9Olx8cXiOp1Tc69oVTjpJh+GGy6uvSo38Aw+4jkQlABelek8D1xlj/m6MaW6MGQvUAV4GMMaMN8aMz/H4CcBO4HVjzBnGmC5IO/OJ1trt2Y8ZC3Q3xtxvjDndGPMA8Ffg2Uj9oaLdvn0yE+6cc6TE2imfD6yV3eSRNH06ZGR4VqaX0/DhsGOHJKvRSgffJqYKFeRXMBz7nH7/XUaiXXGFHFcpFYLSpeHyy+Uzae9e19HEtoMHpTa+e3e9CqgiIuKJk7X2PaRN+FBgIdL44UJrbXD1qD5HS/Cw1u4DzgWOQ7rrvQ98Bfwtx2O+A64ArkPmOw0AUqy133v8x4kZL7wA27fL3ibn2reX+0iX6wUCcpWvo/fjvTp1knLIJ56I3q6zaWlystuypetIVKT5/dJRsaQroh98IOctWqanVBElJ8svT3DfrSqe1FQppRkyxHUkKkEYa63rGJyqXLmy3R/nGzT37JEGAH/5C0yb5jqabKedBmecIZerI+HgQelk1L9/xJaBvv1WKjKeegruvjsiL1kknTvLhU8vZvqo6Pbpp1JO+tlncO65xT9OUhJs2yaVt07Lf5WKNVlZ0iypXTuYPNl1NLEpI0POJWrVkiuB+iYUFYwxB6y1lV3H4ZVY6KqnSujZZ6VT56hRriPJoWNHaQseqcT9iy/k8noEyvSCunSR0sjHH4++VadDh2D+fK1sSFSdOskMt5KU661ZI0n3tdfq+YpSRVaqlJTrffKJ7L9VRffee7B2LQwerG9CKmI0cYpzv/0mKx6XXCIXtqKGzyfL65s3R+b1AgGZ/PnXv0bm9bINHy5X5MeNi+jLFuqHH+DwYd3flKiqVYM2bUq22jh+vJyrXHNN+OJSKqGkpMgbsZbrFV1WFowZA2ee6WgopUpUmjjFuaeekr2nUbXaBJEdhJuZKaUQF14o7cQiKCkJunWDxx6TasFoEWwMoStOicvvl5+DQ4eK/tysLEmcuneHU04Jf2xKJYSOHaVcb9w4KTXbti1yVRix7uOPZSDdAw/I6p1SEaI/bXHs119ltEFychSONmjVCsqWjUzilJ4unTH69vX+tfIwYoQsrkXTqlNamnxe16njOhLlSlKSJPPz5xf9uXPmSIWMNoVQqgSMgQED5Beqc2dpXlSlinxg9+kDd90lg12nTYNly2T2k5Lk8pFHoHFjOcFRKoLKuA5Aeeexx+R99sEHXUeShwoVoHXryCROgYAkaT17ev9aeejWTU5SH30UbrwxOto26+Bb1bWr3H/9tZyzFUVqqpzf9esX/riUSigjR8JVV8mmweBt7Vq5nzULcjevOvlkSRjyup10UmKsvsyaBXPnwiuvQBk9jVWRpV314rSr3pYtRy/GpKa6jiYft98uwe3eLe3dvGAtNG0qtxkzvHmNEMyaJd3L/vUvuPVWZ2EA8MsvULcuPPMM3Hmn21iUW82by/tEUbptHjgg52eXXgqvv+5dbEolPGuldCRnUpXztmnTsaV9FSpIC91Gjf6cVDVqJFc74kH37tLKc+3aiJffq8LFe1c9TdXj1JgxcOSINCeIWj6fZBI//yytyb2wZAmsXg2DBnlz/BB17y5d9saMgRtucPter4NvVVBSkjSmyswM/drFpEmyb1LL9JTymDHSartWrbw3pB46BBs25J1UzZkjs0hyqlXr2EQqZ2JVt653FzDDKS0NvvxSNnBr0qQc0MQpDm3YICvY118PTZq4jqYAORtEeJU4BQLy4dOnjzfHD5ExstfpvPPkKv3NN7uLJS0NypWTSkmV2Px+ePVVWLw49J+H1FRo0ECSLqWUQ+XLH62oyM1aaaubs/QveEtLO3rFJKhsWWjYMO8SwEaN4LjjIvbHKtCYMXDCCXDTTa4jUQlKS/XisFTvH/+AN96AlSulAUDUysqCGjXgyivhpZe8eY327SVL+O47b45fBNbKqtPmzfJvU66cmzj8fvm8jIK/EuXYhg2SBD33HAwcWPjjN22S95ShQ6OwU6dSKnRHjsDGjXnvrVqzRpKunGrUyH9v1SmnRGav0aJF0lhq1CgYNsz711PFoqV6KqasWQP/+Y8kT1GdNIFsYu3QQQbhemHjRmkZ9thj3hy/iIyR0smePSWxdXHB7PBhmDfP/T4rFR3q15fb11+Hlji99ZZcABgwwPvYlFIeKlv2aOKTl927/7xStWYNLFgAH30EGRlHH1u6tFyByWtvVePGcPzx4RlQ++ijsk/r9ttLfiylikkTpzgzapRc+Bk82HUkIfL5jrb/q1gxvMcOBOT+kkvCe9wSOP98+SOPHi2llGXLRvb1f/xRWlDr/CYVlJQEn30mCVFB5zbWSplely5w6qmRi08p5UD16jIlu02bP38vM1NKJ/LaWxUISEOLnI477s+lf8H/btAgtPKLVaukvPDeeyURU8oRTZziyPLl8Oab0iktZubz+HzyJvzDD0XviVyYQABatIDTTgvvcUsguNepVy8ZIHrDDZF9fW0MoXLz+2UlaeXKgn9V5s6VPi6vvhq52JRSUah06aPL1d26/fn7e/ceXa3KuWq1ZAlMnXrs1O1SpaBevfz3VtWsKR+cjz8uVxrvuitif0yl8qKJUxwZOVIWbe67z3UkRZCzQUQ4E6fffoOvvorKv4yePWXr1SOPSMlTJFed0tKkeVK9epF7TRXdgk0evvmm4MQpNVW6Heu8SaVUgapWhZYt5ZZbVpbMS8lrb9WMGfK9nCpXliTq559lEOJJJ0Xmz6BUPjRxihM//QTvvit5Qq1arqMpgpNPlo2l4R6EO22arGRFUZleUHCvU+/ecqX/+usj99o6+Fbl1qyZXNT95pv8V0APHYJ33pFfp2hprqWUikGlSsnVu7p1Zbk7twMHYN26P5cAVq8O998f8XCVyk0TpzgxYoRc5HE8rqh4fL7wN4iYNEnemNu1C+9xw+Sii6BtW1l1uuaayDQk2rZNLuzddpv3r6VihzHQtas0iMjP1Kmwa5fOblJKeaxSJSmxb9HCdSRK5amU6wBUyQWb3Nx1l3QMjTk+n1xR2rEjPMc7cAA++UQuj5eKzh/x4KrT6tUwYUJkXlP3N6n8JCVJUr1pU97fT02VxeEePSIbl1JKKRVNovOsUhXJ8OHSZCZm90wG9znNnRue433+uXTpi8IyvZx695aRFA8/fGxnV6+kpcl+qrZtvX8tFVuCFTPffPPn723fLlsPrr5a9oQrpZRSiUoTpxiXni7beQYNiuG9B+3ayRJMuPY5BQLyl3H22eE5nkeCq04rV8r+NK+lpUln2QoVvH8tFVtatZJS37wSpwkTJLHXMj2llFKJzlhrXcfgVOXKle3+/ftdh1Fs550HCxdKpVuVKq6jKYGzzpImEdOnl+w4GRnSdeeCC6TzQpTLyoLWrWUw7ZIl3l3Rz8iAatVk6O6zz3rzGiq2XXCBlOr99NOxX2/TRn4u581zE5dSSqnYYYw5YK2t7DoOr+iKUwz7+msZXHnffTGeNIGU6/33vzJlsyS+/RZ27oS+fcMTl8dKlZJVp+XL4f33vXudRYukelEH36r8JCVJ8r5z59GvLVokF2Z0tUkppZTSxClmWQvDhsmG7VtucR1NGPh8csa2dm3JjhMIQPnycP754YkrAvr1gzPOgIcekg7qXtDGEKowwX1O33579GupqbIv7sor3cSklFJKRRNNnGLUrFmy4jR4sHTvjHk5B+EWl7WSOPXoEVNLcKVKSRK8bBlMnOjNa6SlSQVj/freHF/Fvg4doFy5o23JMzLg7behVy848US3sSmllFLRQBOnGGQtDB0qW4JuvNF1NGFy5plQsWLJ5jn9+KMMzovybnp5uewyaN5cVp2yssJ//ODgW2PCf2wVHypUgI4djzaI+PRTmf2lZXpKKaWU0MQpBk2fLvnFsGFSlRYXgn2yS7LiFAjI8k3v3uGLK0JKl5Z/zyVLZCZXOP36K6xapfubVOH8fpg/H/btkzK9E06ACy90HZVSSikVHTRxijHBvU2NG8N117mOJsx8Ppnme+RI8Z4fCECXLlCzZnjjipDkZDj9dBg1KryrTsFFPN3fpAqTlCT77GbMgMmT4aqrpHxPKaWUCidjzK3GmLXGmIPGmPnGGH+Iz+tqjMkwxvxU+KPDTxOnGDNpEvzwA4wYIYs0ccXng4MH/9wPORRr10qpXgyW6QWVLi0lmIsXSw4YLmlpUKaMjMtSqiCdOsmi7aBB0iJfy/SUUkqFmzEmBRgLjAbaAN8BM4wxBe7ENsYcD4wHZnkeZD40cYohWVmSMDVrBv37u47GAyVpEBHMNGI4cQJISYGmTWXVKVwj1tLSZMBpXDQRUZ6qVk3mNq1fL50e27Z1HZFSSqk4dDfwhrV2nLV2mbV2ILAFKKxP9GtAKpDmdYD50cQphrz/vizGPPigd4NSnWrUSNp3FadBRCAALVtKDWMMK1NGVp1+/BGmTCn58TIzJQ/VMj0VqmBb8muv1WYiSimlwssYUw5oB8zM9a2ZQOcCnncrUBt42LvoClfG5YtHgxo1ajB79mzXYRQqM9Pwz392oFGjLGrVmkcMhFw8Y8ZIjVBR/oAZGdIQ4uSTi/a8KFW3rqFu3Q4MGpRJtWrzS3TyumpVZfbv70C1akuZPXt7+IJUcatx42rUq3c6TZosZPbsw67DUUopFVvKGGPm5fj/V621r+b4/xOB0sC2XM/bBpyb1wGNMWcBI4C/WGszjcOregmfOP32229069bNdRiFSk2FjRul41r37t0cR+Ohr76CkSPh99+hatXQnvP663DvvdJYok0bb+OLkIcfhuuvh337unHxxcU/zvLlcn/DDS1o3LhFeIJTca1bNxg4EAq48KeUUkrlJ8Na2z5cBzPGlAfeA+611q4N13GLS0v1YsCRI5JLtG0b81t4Cufzyeae+fNDf86kSdCgAbRu7V1cEda/v1QulnSvU1qaNBls1Ch8sSmllFJKFdMOIBMpu8upNrA1j8efDDQHXs/uppcBDAfOyP7/8zyNNhdNnGLA669L07iHHkqAPQfBBhGh7nPatw9mzpSMMo7+csqWhSFDYN48aQ1dXDr4VimllFLRwlp7GJgP9Mj1rR5Id73cNgNnAa1z3F4GVmX/d17P8YwmTlHu0CEp2/rLX6BnT9fR/H979x4kV1kmYPx5CcSEBBGIhESEcBFEvFFQgyII7hpFVEAQRbRiUEGCkBJFJV6QYhHZgkXAKmXBWgIqtezikiowShQFJCQQ2EUKpDCuGJZIiCEhQGKuvPvH11O0Y890ZtK3mX5+VV2nzznfOfN215fufvPdWmCXXWCffbZ8Zr1588qbNAKb4qZNgylTSmvjUFqdVq4sXfWcGEKSJHWQy4HpEfGZiDggIq4EJlMSIiLihoi4ASAzN2bmI9UPYDmwvrL/YisDN3HqcNdeW8Y2dUVrU6+eni1PnObMgZ13hsMPb25MbbDddvDVr5a34vbbB3/9woVl+7a3NTYuSZKkocrMm4DPA18HHgIOB47JzCWVIntUHh0nslGLxQxT48aNyzVr1rQ7jJrWri2NL/vvD7/+dRclTldcAeecA0uXwuTJ/ZfbuBF23RWOOw5mz25ZeK20YUNZ12nyZLj33sHVgfPPh299C55/HsaNa16MkiRJABGxNjNH7K8OW5w62Pe/D8uWdVlrE7w8zmnRooHL3X03PPccfOhDzY+pTUaPhlmzSuvRL385uGsXLChLW5k0SZIkbT0Tpw714otwySUwderLC1J2jYMOKivB1psgYs4cGDu2vEkj2Kmnwu67D26s0+bN5e1zfJMkSVJjmDh1qKuughUrSmtT1xk7tjSVDDTOKbMkTu99L2y/fetia4NXvKK0Os2fD7/61ZZd89hj8MILjm+SJElqFBOnDrR6NVx2GXzgA3Dooe2Opk16ekpXvZdeqn3+wQfhqadG5Gx6tXzqU2Wc04UXbln53okhbHGSJElqDBOnDvSd78CqVVv+I3lE6ukpsxr8/ve1z8+ZA6NGleyyC4wZA+edV4Z13Xln/fILFpSZ3ffdt+mhSZIkdQUTpw7z7LNw+eVw4ollqE/X6m1q62+c05w58M53luygS5x2GkyaVMY61bNwYemm11WTikiSJDWRiVOHueyyMjHElvw4HtH23x922KH2OKfFi+HRR7umm16vMWPgK18pLU53391/ueeeg9/9zm56kiRJjWTi1EGWLy+TQpx8Mhx4YLujabNRo+CQQ2onTnPmlO1xx7U2pg5w+ukwceLAiXVvI50TQ0iSJDWOiVMHueQSWLcOLrig3ZF0iJ4e+O1vy5tSbc6c0o9xzz3bE1cbjR0LX/5ymV3vnntql1m4sHTR610OS5IkSVvPxKlD/PnPZcHbadNgv/3aHU2H6OmBjRtL8tRr2bIy88EIXvS2njPOgF137X/ykAUL4I1vLD0dJUmS1BgmTh3i4oth0yY4kQAouwAADG9JREFU//x2R9JBak0QceutZQ2nLhvfVG377eFLX4Jf/KIkSdVeesmFbyVJkprBxKkDLFkC11wDn/407LVXu6PpIK95TVm8qHqc0y23wN57lyaVLjZjBkyY8PdjnR5/vEwO4fgmSZKkxjJx6gAXXVTGpHzta+2OpAP19LycOD3/PNxxR2lt6vJ5tseNg3PPhdtv/9sGORe+lSRJag4Tpzb7wx/guuvgs5+F17623dF0oJ6eMv34ypXw85/Dhg1dPb6p2uc+V5axqh7rtGAB7LST4+QkSZIazcSpzW68EUaPhlmz2h1Jh+od57RoUZlN79WvtjmlYvx4+OIXYe7c8vZASZwOPRS28V+2JElSQ/nzqs2+8Q146CGYNKndkXSogw8u3fLuuQd++lM49tiyxpMAOOss2Hnn0ur0/PNlXWDzSkmSpMYzcWqzCLtVDWjHHeH1r4fvfa9kBl08m14tO+wA55wDt90GV19dJhx0YghJkqTGi8xsdwxtNW7cuFyzZk27w9BApk+H668vMyKsWAFjxrQ7oo6yejVMmQJr1pQp7VetKvmmJElSK0XE2swc1+44msUWJ3W+np6yfd/7TJpq2HHH0uq0cSMccIBJkyRJUjOYOKnzHXFE2Z50Unvj6GAzZ5bZ9I46qt2RSJIkjUx21bOr3vCweDHsu2/Xr980kKVLS2vT+PHtjkSSJHWjkd5Vz8TJxEmSJEnaaiM9cbKrniRJkiTVYeIkSZIkSXWYOEmSJElSHW1JnCLizIh4IiLWRcSDEXHEAGWPiois8Xh9VZnp/ZRx7mpJkiRJW23bVv/BiPgocCVwJnBPZfuziHhDZj45wKUHAiur9v/S5/xaYJ/qA5m5busjliRJktTtWp44AV8AZmfmtZX9syPiaGAGMGuA65Zn5ooBzmdmLmtUkJIkSZLUq6Vd9SJiNHAwMK/PqXnAYXUufyAino6IOyLiXTXOj42IJRHxVETcFhEHNSJmSZIkSWr1GKcJwCjgmT7HnwF26+eapymtUScCJwCPA3f0GRf1OPAp4DjgY8A6YH5EvK7WDSPi9Ih4ICIe2LRp01BfiyRJkqQu0dIFcCNiMrAUODIz7646fj7w8czcfwvvMxfYlJnH9nN+FPAQ8OvMnDnQvVwAV5IkSdp6LoDbWCuAzcDEPscnAoMZn3QfULM1CSAzNwMPDFRGkiRJkrZUSxOnzNwAPAhM7XNqKnDvIG71VkoXvpoiIoA3D1RGkiRJkrZUO2bVuxz4YUTcD8wHzgAmA1cDRMQNAJk5rbL/eeBPwKPAaOATwPGUMU9UynwTWAgsBl4JzKQkTjNa8YIkSZIkjWwtT5wy86aI2AX4OjAJeAQ4JjOXVIrs0eeS0cClwO7AXykJ1Pszc25VmVcB11AmmFgN/A/wzsy8v2kvRJIkSVLXaOnkEJ3IySEkSZKkrefkEJIkSZLU5bq+xSkiXqJ0AWynbQEXlFIjWJfUCNYjNYp1SY1gPRo+xmbmiG2Y6frEqRNExAOZeUi749DwZ11SI1iP1CjWJTWC9UidYsRmhJIkSZLUKCZOkiRJklSHiVNnuKbdAWjEsC6pEaxHahTrkhrBeqSO4BgnSZIkSarDFidJkiRJqsPESZIkSZLqMHGSJEmSpDpMnFogIs6MiCciYl1EPBgRR9Qpf2Sl3LqI+GNEnNGqWNXZBlOXIuKEiJgXEX+JiBci4r6IOLaV8aozDfYzqeq6wyNiU0Q80uwYNTwM4fttdERcWLlmfUQ8GREzWxWvOtMQ6tEpEfFQRKyNiGUR8aOI2K1V8ap7mTg1WUR8FLgSuBg4CLgX+FlE7NFP+b2AuZVyBwHfBr4bESe2JmJ1qsHWJeBI4FfA+yvl5wK3bOmPZI1MQ6hHvdftBNwA3NH0IDUsDLEu/TtwNHA6sD9wEvBwk0NVBxvC76R3AD8ErgcOBI4H3gD8uCUBq6s5q16TRcR9wMOZeVrVscXAzZk5q0b5fwZOyMzXVR37AXBgZr69FTGrMw22LvVzj/uB32TmF5sUpjrcUOtRRPwX8FsggA9n5hubHqw62hC+394D/CewT2auaF2k6mRDqEfnAmdn5p5Vx04FvpuZ41sRs7qXLU5NFBGjgYOBeX1OzQMO6+eyt9cofztwSERs19gINVwMsS7VsgOwqlFxaXgZaj2KiDOBicBFzYtOw8kQ69LxwCLgCxHxVEQsjoirIsIfu11qiPVoPjApIj4YxQTgZEqvCqmpTJyaawIwCnimz/FngP764u7WT/ltK/dTdxpKXfobEfE5YHdKFwd1p0HXo4h4E/BN4BOZubm54WkYGcpn0t7A4cBbgBOBsyjd9mY3J0QNA4OuR5m5gJIo/RjYAPyF0hL+yeaFKRUmTlIXqIyRuxQ4JTOXtDseDQ8R8QrgJuDczHyi3fFo2NsGSMrn0H2ZeTsleToxIia2NzQNFxHxBuC7wD9RWquOpiRZ/9rOuNQdtm13ACPcCmAzpYtLtYnAsn6uWdZP+U2V+6k7DaUuARARH6YM6p+Wmbc2JzwNE4OtR5OAA4DrIuK6yrFtgIiITcAxmdm3i426w1A+k54Glmbm6qpjj1W2e/D3rQ4a+YZSj2YB92fmpZX9hyNiDfCbiPhqZj7VnFAlW5yaKjM3AA8CU/ucmkqZNaaWBf2UfyAzNzY2Qg0XQ6xLRMRHKF3zpmfmzc2LUMPBEOrRUuBNwFurHlcDf6g877fuaWQb4mfSfGBynzFN+1W2toR3oSHWo+0pyVa13n1/16qpbHFqvsuBH1ZmM5sPnAFMpvz4ICJuAMjMaZXyVwNnRcQVlGbndwDTgY+1Nmx1oEHVpYg4mZI0nQvcXbXGxYbMXNni2NU5trgeVf6z5m/WbIqI5cD6zHQtJw32++1G4BuUFswLgFdRpqG+OTOXtzZ0dZDB1qNbgWsjYgZl8qxJwBXAf2fmky2OXV3GxKnJMvOmiNgF+DrlH/cjlO4tvf+7tkef8k9ExDHAd4AZwJ+BmZn5kxaGrQ402LpE+fLZlvKFckXV8buAo5obrTrVEOqRVNMQvt9ejIh3U8anLKLM8DkHOK91UavTDKEezY6IHSjj4/4FWE1Zs/ArrYta3cp1nCRJkiSpDvuCSpIkSVIdJk6SJEmSVIeJkyRJkiTVYeIkSZIkSXWYOEmSJElSHSZOkiRJklSHiZMkdbGIuCAisvK4oN3x1FKJ8YKImL4FZadUvZ56j9nNj16SNFK4AK4kqdN9s7K9C5jdxjgkSV3MFidJ0oiRmX/KzOh9AO+qOn1X9bnMnN6mMCVJw5CJkyTp70TE7KoubYdFxI8iYlVEPBsRP4mI3arKVnePmx0Rp0bEYxGxPiIe79vFLiLu7C0/0PGImN6nzJFVf+fOBr7WiyPivoh4JiI2RMSaiHgoIr4cEdtVlTu66u+fV++4JGlksaueJKmenwKvqto/AdgReHeNsu8HPlm1vx9wXURsk5n/1rwQt8opwJ5V+9sBb6k89gJmtCMoSVJnscVJklTPE8A+lCRoeeXYP0bEpBplJ1ASp1cCH686/u3q1pstkZmzK93telV3tTtqMPeq41zgAEoyOJryOh+tnPtMRIxv4N+SJA1TJk6SpHrOz8w/ZuZi4DdVx/esUfbezLwhM1/IzBuBeyvHdwXe3OxAh2gNcBXwv8Bfgd8DB1bObUtJGiVJXc6uepKkeh6ver6m6vmYGmWfrLF/WOX5hDp/p+XfSRHxD5SuiDFAsbF1buN3qSR1AVucJEn1bKx6nv2WKvYYYH9FZbu+90BEjKlsgzKeqNU+wstJ04XA+Er3wLk1yq6vel6dNO7dpNgkSR3ExEmS1EiHRcTHI2J8RJzCy61Ny4GHK8+XVJX/YGV7NjC5n3s+W9nuGRE7NTRa2FT1/AVgc0QcD0ytUbY67vdExOiImAzMbHBMkqQOZOIkSWqkp4EfUZKQH1cdn5WZvS1X1cf/IyJeAK6kjC+qZWFlOwVYWZn2+4IGxXtL1fNLKzHcDPxf34KZ+ceqWN4OrKqUqzVJhiRphDFxkiQ10jzKbHqPARuAxcCp1VORZ+ZdwGcokzCsp0zKcBJwfz/3PJvSdW5Vo4PNzDuA6VWxPEKZbn1RP5d8BLgNWA2sBX4AnNbouCRJnScy63VXlySpfxExhTJlOcD1mTm9bcFIktQktjhJkiRJUh0mTpIkSZJUh131JEmSJKkOW5wkSZIkqQ4TJ0mSJEmqw8RJkiRJkuowcZIkSZKkOkycJEmSJKmO/welwvr5B2QpBAAAAABJRU5ErkJggg==\n" }, "metadata": { "needs_background": "light" - }, - "output_type": "display_data" + } } ], "source": [ - "display(Markdown(\"### Plot of accuracy and output fairness vs input constraint (tau)\"))\n", - "\n", - "display(Markdown(\"#### Output fairness is represented by $\\gamma_{fdr}$, which is the ratio of false discovery rate of different sensitive attribute values.\"))\n", - "\n", "fig, ax1 = plt.subplots(figsize=(13,7))\n", "ax1.plot(all_tau, accuracies, color='r')\n", - "ax1.set_title('Accuracy and $\\gamma_{fdr}$ vs Tau', fontsize=16, fontweight='bold')\n", + "ax1.set_title('Accuracy and $\\gamma_{sr}$ vs Tau', fontsize=16, fontweight='bold')\n", "ax1.set_xlabel('Input Tau', fontsize=16, fontweight='bold')\n", "ax1.set_ylabel('Accuracy', color='r', fontsize=16, fontweight='bold')\n", "ax1.xaxis.set_tick_params(labelsize=14)\n", "ax1.yaxis.set_tick_params(labelsize=14)\n", "\n", "ax2 = ax1.twinx()\n", - "ax2.plot(all_tau, false_discovery_rates, color='b')\n", - "ax2.set_ylabel('$\\gamma_{fdr}$', color='b', fontsize=16, fontweight='bold')\n", + "ax2.plot(all_tau, statistical_rates, color='b')\n", + "ax2.set_ylabel('$\\gamma_{sr}$', color='b', fontsize=16, fontweight='bold')\n", "ax2.yaxis.set_tick_params(labelsize=14)\n", - "ax2.grid(True)\n" + "ax2.grid(True)" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# # \n", - "# References:\n", - "# Celis, L. E., Huang, L., Keswani, V., & Vishnoi, N. K. (2018). \n", - "# \"Classification with Fairness Constraints: A Meta-Algorithm with Provable Guarantees.\"\"\n" + "References:\n", + "\n", + " Celis, L. E., Huang, L., Keswani, V., & Vishnoi, N. K. (2018). \n", + " \"Classification with Fairness Constraints: A Meta-Algorithm with Provable Guarantees.\"\"\n" ] } ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3.6.9 64-bit", "language": "python", - "name": "python2" + "name": "python_defaultSpec_1596663900877" }, "language_info": { "codemirror_mode": { @@ -930,4 +464,4 @@ }, "nbformat": 4, "nbformat_minor": 2 -} +} \ No newline at end of file diff --git a/tests/test_meta_classifier.py b/tests/test_meta_classifier.py index 45931cdd..af695e54 100644 --- a/tests/test_meta_classifier.py +++ b/tests/test_meta_classifier.py @@ -1,67 +1,57 @@ import numpy as np -import pandas as pd from aif360.datasets import AdultDataset from aif360.metrics import ClassificationMetric from aif360.algorithms.inprocessing import MetaFairClassifier -from aif360.algorithms.inprocessing.celisMeta.utils import getStats -def test_adult(): - np.random.seed(1) - # np.random.seed(9876) - protected = 'sex' - ad = AdultDataset(protected_attribute_names=[protected], - privileged_classes=[['Male']], categorical_features=[], - features_to_keep=['age', 'education-num', 'capital-gain', - 'capital-loss', 'hours-per-week']) - - #scaler = MinMaxScaler(copy=False) - # ad.features = scaler.fit_transform(ad.features) - - test, train = ad.split([16281]) - - biased_model = MetaFairClassifier(tau=0, sensitive_attr=protected) - biased_model.fit(train) +protected = 'sex' +ad = AdultDataset(protected_attribute_names=[protected], + privileged_classes=[['Male']], categorical_features=[], + features_to_keep=['age', 'education-num', 'capital-gain', + 'capital-loss', 'hours-per-week']) +test, train = ad.split([16281], shuffle=False) +def test_adult_sr(): + biased_model = MetaFairClassifier(tau=0, sensitive_attr=protected, + type='sr', seed=123).fit(train) dataset_bias_test = biased_model.predict(test) biased_cm = ClassificationMetric(test, dataset_bias_test, - unprivileged_groups=[{protected: 0}], privileged_groups=[{protected: 1}]) - unconstrainedFDR2 = biased_cm.false_discovery_rate_ratio() - unconstrainedFDR2 = min(unconstrainedFDR2, 1/unconstrainedFDR2) + unprivileged_groups=[{protected: 0}], + privileged_groups=[{protected: 1}]) + spd1 = biased_cm.disparate_impact() + spd1 = min(spd1, 1/spd1) - predictions = [1 if y == train.favorable_label else - -1 for y in dataset_bias_test.labels.ravel()] - y_test = np.array([1 if y == train.favorable_label else - -1 for y in test.labels.ravel()]) - x_control_test = pd.DataFrame(data=test.features, - columns=test.feature_names)[protected] + debiased_model = MetaFairClassifier(tau=0.9, sensitive_attr=protected, + type='sr', seed=123).fit(train) + dataset_debiasing_test = debiased_model.predict(test) - acc, sr, unconstrainedFDR = getStats(y_test, predictions, x_control_test) - assert np.isclose(unconstrainedFDR, unconstrainedFDR2) + debiased_cm = ClassificationMetric(test, dataset_debiasing_test, + unprivileged_groups=[{protected: 0}], + privileged_groups=[{protected: 1}]) + spd2 = debiased_cm.disparate_impact() + spd2 = min(spd2, 1/spd2) + assert(spd2 >= spd1) + +def test_adult_fdr(): + biased_model = MetaFairClassifier(tau=0, sensitive_attr=protected, + type='fdr', seed=123).fit(train) + dataset_bias_test = biased_model.predict(test) - tau = 0.9 - debiased_model = MetaFairClassifier(tau=tau, sensitive_attr=protected) - debiased_model.fit(train) + biased_cm = ClassificationMetric(test, dataset_bias_test, + unprivileged_groups=[{protected: 0}], + privileged_groups=[{protected: 1}]) + fdr1 = biased_cm.false_discovery_rate_ratio() + fdr1 = min(fdr1, 1/fdr1) - #dataset_debiasing_train = debiased_model.predict(dataset_orig_train) + debiased_model = MetaFairClassifier(tau=0.9, sensitive_attr=protected, + type='fdr', seed=123).fit(train) dataset_debiasing_test = debiased_model.predict(test) - predictions = list(dataset_debiasing_test.labels) - predictions = [1 if y == train.favorable_label else - -1 for y in dataset_debiasing_test.labels.ravel()] - y_test = np.array([1 if y == train.favorable_label else - -1 for y in test.labels.ravel()]) - x_control_test = pd.DataFrame(data=test.features, - columns=test.feature_names)[protected] - - acc, sr, fdr = getStats(y_test, predictions, x_control_test) - debiased_cm = ClassificationMetric(test, dataset_debiasing_test, - unprivileged_groups=[{protected: 0}], privileged_groups=[{protected: 1}]) + unprivileged_groups=[{protected: 0}], + privileged_groups=[{protected: 1}]) fdr2 = debiased_cm.false_discovery_rate_ratio() fdr2 = min(fdr2, 1/fdr2) - assert np.isclose(fdr, fdr2) - #print(fdr, unconstrainedFDR) - assert(fdr2 >= unconstrainedFDR2) + assert(fdr2 >= fdr1)