{
 "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": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "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",
    "from aif360.datasets import AdultDataset, GermanDataset, CompasDataset\n",
    "from aif360.metrics import BinaryLabelDatasetMetric\n",
    "from aif360.metrics import ClassificationMetric\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",
    "np.random.seed(12345)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Original Training dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset_orig = load_preproc_data_adult()\n",
    "\n",
    "privileged_groups = [{'sex': 1}]\n",
    "unprivileged_groups = [{'sex': 0}]\n",
    "\n",
    "dataset_orig_train, dataset_orig_test = dataset_orig.split([0.7], shuffle=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset_orig = GermanDataset()\n",
    "privileged_groups = [{'sex': 1}]\n",
    "unprivileged_groups = [{'sex': 0}]\n",
    "dataset_orig_train, dataset_orig_test = dataset_orig.split([0.7], shuffle=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "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": 35,
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "#### Training Dataset shape"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(34189, 18)\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "#### Favorable and unfavorable labels"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0 0.0\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "#### Protected attribute names"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['sex', 'race']\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "#### Privileged and unprivileged protected attribute values"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([1.]), array([1.])] [array([0.]), array([0.])]\n"
     ]
    },
    {
     "data": {
      "text/markdown": [
       "#### Dataset feature names"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "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"
     ]
    }
   ],
   "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)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train set: Difference in mean outcomes between unprivileged and privileged groups = -0.193\n",
      "Test set: Difference in mean outcomes between unprivileged and privileged groups = -0.197\n"
     ]
    }
   ],
   "source": [
    "metric_orig_train = BinaryLabelDatasetMetric(dataset_orig_train, \n",
    "                                             unprivileged_groups=unprivileged_groups,\n",
    "                                             privileged_groups=privileged_groups)\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 = {:.3f}\".format(metric_orig_test.mean_difference()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Algorithm without debiasing\n",
    "\n",
    "Get classifier without fairness constraints"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "biased_model = MetaFairClassifier(tau=0, sensitive_attr=\"sex\", type=\"fdr\").fit(dataset_orig_train)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Apply the unconstrained model to test data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "dataset_bias_test = biased_model.predict(dataset_orig_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set: Classification accuracy = 0.789\n",
      "Test set: Balanced classification accuracy = 0.623\n",
      "Test set: Disparate impact = 0.466\n",
      "Test set: False discovery rate ratio = 0.508\n"
     ]
    }
   ],
   "source": [
    "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",
    "Learn a debiased classifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "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": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset_debiasing_test = debiased_model.predict(dataset_orig_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Model - with debiasing - dataset metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set: Difference in mean outcomes between unprivileged and privileged groups = -0.110\n"
     ]
    }
   ],
   "source": [
    "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 = {:.3f}\".format(metric_dataset_debiasing_test.mean_difference()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Model - with debiasing - classification metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set: Classification accuracy = 0.657\n",
      "Test set: Balanced classification accuracy = 0.713\n",
      "Test set: Disparate impact = 0.794\n",
      "Test set: False discovery rate ratio = 0.660\n"
     ]
    }
   ],
   "source": [
    "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 = {:.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 = {:.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": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "We see that the FDR ratio has increased meaning it is now closer to parity."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Running the algorithm for different tau values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 10/10 [00:07<00:00,  1.35it/s]\n"
     ]
    }
   ],
   "source": [
    "accuracies, statistical_rates = [], []\n",
    "s_attr = \"sex\"\n",
    "\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",
    "    dataset_debiasing_test = debiased_model.predict(dataset_orig_test)\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": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 87780 characters]",
      "text/plain": [
       "<Figure size 1300x700 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax1 = plt.subplots(figsize=(13,7))\n",
    "ax1.plot(all_tau, accuracies, color='r')\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, 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)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 100/100 [04:16<00:00,  2.56s/it]\n"
     ]
    }
   ],
   "source": [
    "DEOO_fin = []\n",
    "DPE_fin = []\n",
    "mis_fin = []\n",
    "sigma = 1\n",
    "for step in tqdm(range(100)):\n",
    "    mu_00 = 3 * np.random.rand(1)\n",
    "    mu_01 = np.random.rand(1)\n",
    "    mu_10 = np.random.rand(1)\n",
    "    mu_11 = np.random.rand(1)\n",
    "    for i in range(1000):\n",
    "        if(dataset_orig.labels[i] == 2 and dataset_orig.features[:,7][i] == 0):\n",
    "            #z = np.random.normal(mu_00, sigma, 57)\n",
    "            #z = np.random.chisquare(2,57)\n",
    "            z = np.random.standard_t(4, 57)\n",
    "            for j in range(7):\n",
    "                dataset_orig.features[i][j] = z[j]\n",
    "            for j in range(8, 58):\n",
    "                dataset_orig.features[i][j] = z[j - 1]\n",
    "        elif(dataset_orig.labels[i] == 2 and dataset_orig.features[:,7][i] == 1):\n",
    "            #z = np.random.normal(mu_01, sigma, 57)\n",
    "            #z = np.random.standard_t(4, 57)\n",
    "            z = np.random.chisquare(2,57)\n",
    "            for j in range(7):\n",
    "                dataset_orig.features[i][j] = z[j]\n",
    "            for j in range(8, 58):\n",
    "                dataset_orig.features[i][j] = z[j - 1]\n",
    "        elif(dataset_orig.labels[i] == 1 and dataset_orig.features[:,7][i] == 0):\n",
    "            #z = np.random.normal(mu_10, sigma, 57)\\\n",
    "            z = np.random.chisquare(4,57)\n",
    "            for j in range(7):\n",
    "                dataset_orig.features[i][j] = z[j]\n",
    "            for j in range(8, 58):\n",
    "                dataset_orig.features[i][j] = z[j - 1]\n",
    "        else:\n",
    "            #z = np.random.normal(mu_11, sigma, 57)\n",
    "            #z = np.random.chisquare(1,57)\n",
    "            z = np.random.laplace(mu_11, sigma, 57)\n",
    "            for j in range(7):\n",
    "                dataset_orig.features[i][j] = z[j]\n",
    "            for j in range(8, 58):\n",
    "                dataset_orig.features[i][j] = z[j - 1]\n",
    "    randseed = np.random.randint(10000)\n",
    "    dataset_orig_train, dataset_orig_vt = dataset_orig.split([0.6], shuffle=True, seed = np.random.randint(0, 10000))\n",
    "    dataset_orig_valid, dataset_orig_test = dataset_orig_vt.split([0.5], shuffle=True, seed = np.random.randint(0, 10000))\n",
    "    # Placeholder for predicted and transformed datasets\n",
    "    dataset_orig_train_pred = dataset_orig_train.copy(deepcopy=True)\n",
    "    dataset_orig_valid_pred = dataset_orig_valid.copy(deepcopy=True)\n",
    "    dataset_orig_test_pred = dataset_orig_test.copy(deepcopy=True)\n",
    "\n",
    "    dataset_new_valid_pred = dataset_orig_valid.copy(deepcopy=True)\n",
    "    dataset_new_test_pred = dataset_orig_test.copy(deepcopy=True)\n",
    "\n",
    "    y_test = dataset_orig_test.labels.ravel()\n",
    "\n",
    "    debiased_model = MetaFairClassifier(tau=0.7, sensitive_attr=\"sex\", type=\"fdr\").fit(dataset_orig_train)\n",
    "    dataset_debiasing_test = debiased_model.predict(dataset_orig_test)\n",
    "\n",
    "    eq = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(dataset_debiasing_test.labels.ravel()[i] == y_test[i]):\n",
    "            eq += 1\n",
    "    mis_fin.append(eq / len(y_test))\n",
    "    n_10 = 0\n",
    "    n_11 = 0\n",
    "    c_10 = 0\n",
    "    c_11 = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(y_test[i] == 1 and dataset_debiasing_test.protected_attributes[:,1][i] == 0):\n",
    "            n_10 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_10 += 1\n",
    "        elif(y_test[i] == 1 and dataset_debiasing_test.protected_attributes[:,1][i] == 1):\n",
    "            n_11 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_11 += 1\n",
    "    DEOO_fin.append(c_10 / n_10 - c_11 / n_11)\n",
    "    n_00 = 0\n",
    "    n_01 = 0\n",
    "    c_00 = 0\n",
    "    c_01 = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(y_test[i] == 2 and dataset_debiasing_test.protected_attributes[:,1][i] == 0):\n",
    "            n_00 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_00 += 1\n",
    "        elif(y_test[i] == 2 and dataset_debiasing_test.protected_attributes[:,1][i] == 1):\n",
    "            n_01 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_01 += 1\n",
    "    DPE_fin.append(c_00 / n_00 - c_01 / n_01)\n",
    "DEOO_fin = np.array(DEOO_fin)\n",
    "DPE_fin = np.array(DPE_fin)\n",
    "mis_fin = np.array(mis_fin)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 100/100 [02:07<00:00,  1.27s/it]\n"
     ]
    }
   ],
   "source": [
    "DEOO_fin = []\n",
    "DPE_fin = []\n",
    "mis_fin = []\n",
    "sigma = 1\n",
    "for step in tqdm(range(100)):\n",
    "    randseed = np.random.randint(10000)\n",
    "    dataset_orig_train, dataset_orig_vt = dataset_orig.split([0.6], shuffle=True, seed = np.random.randint(0, 10000))\n",
    "    dataset_orig_valid, dataset_orig_test = dataset_orig_vt.split([0.5], shuffle=True, seed = np.random.randint(0, 10000))\n",
    "    # Placeholder for predicted and transformed datasets\n",
    "    dataset_orig_train_pred = dataset_orig_train.copy(deepcopy=True)\n",
    "    dataset_orig_valid_pred = dataset_orig_valid.copy(deepcopy=True)\n",
    "    dataset_orig_test_pred = dataset_orig_test.copy(deepcopy=True)\n",
    "\n",
    "    dataset_new_valid_pred = dataset_orig_valid.copy(deepcopy=True)\n",
    "    dataset_new_test_pred = dataset_orig_test.copy(deepcopy=True)\n",
    "\n",
    "    y_test = dataset_orig_test.labels.ravel()\n",
    "\n",
    "    debiased_model = MetaFairClassifier(tau=0.7, sensitive_attr=\"sex\", type=\"fdr\").fit(dataset_orig_train)\n",
    "    dataset_debiasing_test = debiased_model.predict(dataset_orig_test)\n",
    "\n",
    "    eq = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(dataset_debiasing_test.labels.ravel()[i] == y_test[i]):\n",
    "            eq += 1\n",
    "    mis_fin.append(eq / len(y_test))\n",
    "    n_10 = 0\n",
    "    n_11 = 0\n",
    "    c_10 = 0\n",
    "    c_11 = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(y_test[i] == 1 and dataset_debiasing_test.protected_attributes[:,1][i] == 0):\n",
    "            n_10 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_10 += 1\n",
    "        elif(y_test[i] == 1 and dataset_debiasing_test.protected_attributes[:,1][i] == 1):\n",
    "            n_11 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_11 += 1\n",
    "    DEOO_fin.append(c_10 / n_10 - c_11 / n_11)\n",
    "    n_00 = 0\n",
    "    n_01 = 0\n",
    "    c_00 = 0\n",
    "    c_01 = 0\n",
    "    for i in range(len(y_test)):\n",
    "        if(y_test[i] == 0 and dataset_debiasing_test.protected_attributes[:,1][i] == 0):\n",
    "            n_00 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_00 += 1\n",
    "        elif(y_test[i] == 0 and dataset_debiasing_test.protected_attributes[:,1][i] == 1):\n",
    "            n_01 += 1\n",
    "            if(dataset_debiasing_test.labels.ravel()[i] == 1):\n",
    "                c_01 += 1\n",
    "    DPE_fin.append(c_00 / n_00 - c_01 / n_01)\n",
    "DEOO_fin = np.array(DEOO_fin)\n",
    "DPE_fin = np.array(DPE_fin)\n",
    "mis_fin = np.array(mis_fin)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.17228323181597385\n",
      "0.19381204311392067\n",
      "0.6879598730678679\n",
      "0.7466424403726072\n",
      "0.2529187688423358\n",
      "0.27060087655248294\n"
     ]
    }
   ],
   "source": [
    "print(np.mean(abs(DEOO_fin)))\n",
    "print(np.mean(abs(DPE_fin)))\n",
    "print(np.mean(mis_fin))\n",
    "print(np.percentile(mis_fin, 95))\n",
    "print(np.percentile(abs(DEOO_fin), 95))\n",
    "print(np.percentile(abs(DPE_fin), 95))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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 3.7.13 ('aif360')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.13"
  },
  "vscode": {
   "interpreter": {
    "hash": "d27cd899c2aad711dbfe864d87d8e4a3aa2aa47421b84ce5060d18007824eabc"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
