{ "cells": [ { "cell_type": "markdown", "id": "49145f82", "metadata": {}, "source": [ "# Fair-Seldonian — Quickstart\n", "\n", "*Fairness-constrained machine learning with high-confidence guarantees.*\n", "\n", "This notebook walks through the [`fair-seldonian`](https://github.com/parulgupta1004/fair-seldonian) package end to end:\n", "\n", "1. Generate synthetic data with a controllable fairness gap\n", "2. Train a model with the **Quasi-Seldonian Algorithm (QSA)**\n", "3. Read the safety guarantee (`passed` + the high-confidence upper bound)\n", "4. See the difference between a *fair* dataset (model returned) and an *unfair* one (**No Solution Found**)\n", "5. Customise the constraint, confidence level $\\delta$, and inequality\n", "6. Compare the five algorithm variants\n", "\n", "The Seldonian guarantee: given a behavioural constraint and a confidence level $\\delta$, QSA either returns a model that satisfies the constraint with probability $\\ge 1 - \\delta$, or it returns **No Solution Found** — it never returns an unsafe model." ] }, { "cell_type": "markdown", "id": "fe50f837", "metadata": {}, "source": [ "## 0. Install\n", "\n", "Uncomment if the package isn't already in your environment." ] }, { "cell_type": "code", "execution_count": 1, "id": "e9a6237d", "metadata": { "execution": { "iopub.execute_input": "2026-08-24T05:09:38.237906Z", "iopub.status.busy": "2026-08-24T05:09:38.237756Z", "iopub.status.idle": "2026-08-24T05:09:38.246314Z", "shell.execute_reply": "2026-08-24T05:09:38.245497Z" } }, "outputs": [], "source": [ "# %pip install fair-seldonian" ] }, { "cell_type": "code", "execution_count": 2, "id": "741d2210", "metadata": { "execution": { "iopub.execute_input": "2026-08-24T05:09:38.249285Z", "iopub.status.busy": "2026-08-24T05:09:38.249084Z", "iopub.status.idle": "2026-08-24T05:09:41.117404Z", "shell.execute_reply": "2026-08-24T05:09:41.116991Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fair-seldonian version: 3.1.0\n" ] } ], "source": [ "import warnings\n", "\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import torch\n", "\n", "import fair_seldonian\n", "from fair_seldonian.algorithms import QSA\n", "from fair_seldonian.config import SeldonianConfig\n", "from fair_seldonian.constraints.inequalities import Inequality\n", "from fair_seldonian.data import data_split, get_data\n", "from fair_seldonian.models import eval_ghat, predict, simple_logistic\n", "\n", "warnings.filterwarnings(\"ignore\") # keep the demo output tidy\n", "\n", "print(\"fair-seldonian version:\", fair_seldonian.__version__)" ] }, { "cell_type": "markdown", "id": "7ccfdb94", "metadata": {}, "source": [ "## 1. The data\n", "\n", "`get_data` builds a synthetic binary-classification dataset where each row carries a **sensitive attribute** `T` $\\in \\{0, 1\\}$ (e.g. a protected group).\n", "\n", "| argument | meaning |\n", "|---|---|\n", "| `N` | number of samples |\n", "| `features` | number of feature columns |\n", "| `t_ratio` | fraction of rows in group `T=1` |\n", "| `tp0_ratio` | base positive-label rate for group `T=0` |\n", "| `tp1_ratio` | base positive-label rate for group `T=1` |\n", "| `random_seed` | reproducibility |\n", "\n", "The gap between `tp0_ratio` and `tp1_ratio` controls how *unfair* the underlying data is. `data_split` then returns train/test arrays as `(X_test, Y_test, T_test, X_train, Y_train, T_train)`." ] }, { "cell_type": "code", "execution_count": 3, "id": "eb872929", "metadata": { "execution": { "iopub.execute_input": "2026-08-24T05:09:41.118847Z", "iopub.status.busy": "2026-08-24T05:09:41.118710Z", "iopub.status.idle": "2026-08-24T05:09:41.125086Z", "shell.execute_reply": "2026-08-24T05:09:41.124718Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "train: (4000, 5) test: (2000, 5)\n", "group balance (train): {0: 2366, 1: 1634}\n" ] } ], "source": [ "data = get_data(\n", " N=10000, features=5, t_ratio=0.4, tp0_ratio=0.4, tp1_ratio=0.6, random_seed=42\n", ")\n", "X_te, Y_te, T_te, X_tr, Y_tr, T_tr = data_split(\n", " frac=0.5, all_data=data, random_state=1, m_test=0.2\n", ")\n", "\n", "print(\"train:\", X_tr.shape, \" test:\", X_te.shape)\n", "print(\"group balance (train):\", {g: int((T_tr == g).sum()) for g in (0, 1)})" ] }, { "cell_type": "markdown", "id": "d0733f52", "metadata": {}, "source": [ "## 2. Train with QSA\n", "\n", "```python\n", "QSA(X, Y, T, seldonian_type, init_sol, init_sol1, config=DEFAULT_CONFIG)\n", "```\n", "\n", "Internally QSA splits the training data into a **candidate** set (used to find a solution) and a **safety** set (used to certify it). It returns a `QSAResult` with four fields:\n", "\n", "- `theta`, `theta1` — the logistic-regression parameters (weights + bias)\n", "- `passed_safety` — `True` only if the candidate model passed the high-confidence safety test\n", "- `diagnostics` — why the run ended as it did. `diagnostics.failure_mode` distinguishes `candidate_infeasible` (no feasible model was found at all) from `safety_test_rejected` (one was found, but the safety data could not certify it). The two call for different remedies, so a bare \"No Solution Found\" hides the useful half of the answer.\n", "\n", "Passing `init_sol=None` lets QSA warm-start from a plain logistic-regression fit. `\"opt\"` selects the variant with all confidence-bound optimisations enabled (see §6).\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "f1ee544b", "metadata": { "execution": { "iopub.execute_input": "2026-08-24T05:09:41.126353Z", "iopub.status.busy": "2026-08-24T05:09:41.126271Z", "iopub.status.idle": "2026-08-24T05:09:41.336023Z", "shell.execute_reply": "2026-08-24T05:09:41.335572Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "No Solution Found — QSA refused to return a model it could not certify.\n" ] } ], "source": [ "theta, theta1, passed, _ = QSA(X_tr, Y_tr, T_tr, \"opt\", None, None)\n", "\n", "if passed:\n", " ub = float(eval_ghat(theta, theta1, X_te, Y_te, T_te, \"opt\"))\n", " print(\"Safety test PASSED \\u2713\")\n", " print(f\"High-confidence upper bound on the constraint (test set): {ub:.4f}\")\n", " print(\"A value \\u2264 0 means the fairness constraint is satisfied.\")\n", "else:\n", " print(\n", " \"No Solution Found \\u2014 QSA refused to return a model it could not certify.\"\n", " )" ] }, { "cell_type": "markdown", "id": "af2fe1c0", "metadata": {}, "source": [ "## 3. What is the constraint?\n", "\n", "Constraints are written in **reverse-Polish (postfix) notation** over per-group base variables.\n", "\n", "There are two kinds, and the difference matters:\n", "\n", "- **Cells** — `TP(g)`, `FP(g)`, `TN(g)`, `FN(g)` — are fractions of the *whole* group: `TP(g)` is $P(\\hat{Y}=1, Y=1 \\mid T=g)$, a joint probability. The four cells sum to 1 within a group.\n", "- **Rates** — `TPR(g)`, `FPR(g)`, `TNR(g)`, `FNR(g)` — condition on the label as well: `TPR(g)` is $P(\\hat{Y}=1 \\mid Y=1, T=g)$, a mean over only that group's positive rows, and so carries its own smaller sample size.\n", "- **Predicted-positive / negative rates** — `PR(g)` and `NR(g)`, which are `TP + FP` and `TN + FN`. They ignore the label, so like the cells they are means over the whole group. Demographic parity written over `PR` costs two leaves rather than four.\n", "\n", "The default constraint is:\n", "\n", "```\n", "TP(1) TP(0) - abs 0.25 TP(1) * -\n", "```\n", "\n", "which decodes to\n", "\n", "$$ g = \\bigl|\\, \\mathrm{TP}(1) - \\mathrm{TP}(0) \\,\\bigr| \\; - \\; 0.25 \\cdot \\mathrm{TP}(1) $$\n", "\n", "so the gap in the **joint** true-positive cell must stay within 25 % of group 1's. Note this is *not* equal opportunity, which compares true-positive **rates**; for that use `TPR` directly, or the ready-made builder `equal_opportunity(epsilon)`. QSA certifies an *upper confidence bound* on $g$ rather than its point estimate — that is what makes the guarantee high-confidence.\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "72b3fbf1", "metadata": { "execution": { "iopub.execute_input": "2026-08-24T05:09:41.337373Z", "iopub.status.busy": "2026-08-24T05:09:41.337284Z", "iopub.status.idle": "2026-08-24T05:09:41.339745Z", "shell.execute_reply": "2026-08-24T05:09:41.339375Z" } }, "outputs": [], "source": [ "def tp_rates(\n", " theta: torch.Tensor,\n", " theta1: torch.Tensor,\n", " X: np.ndarray,\n", " Y: np.ndarray,\n", " T: np.ndarray,\n", ") -> dict[int, float]:\n", " \"\"\"Empirical true-positive rate per group (for interpretation only).\"\"\"\n", " p = predict(theta, theta1, X).detach().numpy()\n", " yhat = (p >= 0.5).astype(int)\n", " rates: dict[int, float] = {}\n", " for g in (0, 1):\n", " mask = (T == g) & (Y == 1)\n", " rates[g] = float(yhat[mask].mean()) if mask.sum() else float(\"nan\")\n", " return rates" ] }, { "cell_type": "markdown", "id": "4761d44f", "metadata": {}, "source": [ "## 4. Fair vs. unfair data\n", "\n", "The same algorithm behaves very differently depending on whether the constraint is *achievable*. We use the t-test inequality here, which gives tighter bounds than Hoeffding when the sample is reasonably large." ] }, { "cell_type": "code", "execution_count": 6, "id": "169ce4d9", "metadata": { "execution": { "iopub.execute_input": "2026-08-24T05:09:41.341020Z", "iopub.status.busy": "2026-08-24T05:09:41.340930Z", "iopub.status.idle": "2026-08-24T05:09:41.965163Z", "shell.execute_reply": "2026-08-24T05:09:41.964409Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== Fair data (tp0 = tp1 = 0.5) ===\n", " PASSED ✓ upper bound g = -0.0438 (≤ 0 ⇒ fair)\n", " test TP rates = {0: 0.8553076402974983, 1: 0.8302488832163369}\n", "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "=== Unfair data (tp0 = 0.3, tp1 = 0.7) ===\n", " PASSED ✓ upper bound g = -0.0037 (≤ 0 ⇒ fair)\n", " test TP rates = {0: 0.5568581477139508, 1: 0.22650602409638554}\n", "\n" ] } ], "source": [ "def run_scenario(name: str, tp0: float, tp1: float, config: SeldonianConfig) -> None:\n", " data = get_data(\n", " N=20000,\n", " features=5,\n", " t_ratio=0.5,\n", " tp0_ratio=tp0,\n", " tp1_ratio=tp1,\n", " random_seed=7,\n", " )\n", " X_te, Y_te, T_te, X_tr, Y_tr, T_tr = data_split(\n", " frac=1.0, all_data=data, random_state=1, m_test=0.3\n", " )\n", " theta, theta1, passed, _ = QSA(X_tr, Y_tr, T_tr, \"opt\", None, None, config)\n", " print(f\"=== {name} ===\")\n", " if passed:\n", " ub = float(eval_ghat(theta, theta1, X_te, Y_te, T_te, \"opt\", config))\n", " print(f\" PASSED \\u2713 upper bound g = {ub:+.4f} (\\u2264 0 \\u21d2 fair)\")\n", " print(f\" test TP rates = {tp_rates(theta, theta1, X_te, Y_te, T_te)}\")\n", " else:\n", " print(\" No Solution Found \\u2014 constraint could not be certified.\")\n", " print()\n", "\n", "\n", "cfg = SeldonianConfig(delta=0.05, inequality=Inequality.T_TEST)\n", "run_scenario(\"Fair data (tp0 = tp1 = 0.5)\", 0.5, 0.5, cfg)\n", "run_scenario(\"Unfair data (tp0 = 0.3, tp1 = 0.7)\", 0.3, 0.7, cfg)" ] }, { "cell_type": "markdown", "id": "3919b52c", "metadata": {}, "source": [ "With the default 25 % *relative* tolerance, both datasets certify — but look at what it costs. On the fair data the two groups' true-positive rates come out close together and near the achievable ceiling. On the strongly unfair data QSA can only satisfy the constraint by suppressing predictions for the higher-base-rate group, which is visible in the lopsided TP rates: the model is dragged well away from the accuracy-maximising fit.\n", "\n", "Refusal is still the behaviour that matters, and §5 shows it: tighten $\\delta$ and the tolerance and QSA returns **No Solution Found** rather than a model it cannot prove is fair.\n" ] }, { "cell_type": "markdown", "id": "f60403b0", "metadata": {}, "source": [ "## 5. Custom configuration\n", "\n", "`SeldonianConfig` is a frozen dataclass:\n", "\n", "| field | default | meaning |\n", "|---|---|---|\n", "| `delta` | `0.05` | failure probability $\\delta$; the guarantee holds w.p. $\\ge 1-\\delta$ |\n", "| `inequality` | `HOEFFDING_INEQUALITY` | confidence-bound method — see below |\n", "| `constraint` | TP-gap constraint | postfix constraint string |\n", "| `candidate_ratio` | `0.40` | fraction of training data used as the candidate set (rest is the safety set) |\n", "| `optimizer` | `\"Powell\"` | any `method` accepted by `scipy.optimize.minimize` |\n", "| `max_iter` | `10000` | iteration cap for candidate selection |\n", "| `penalty` | `100.0` | weight on the constraint violation in the candidate objective |\n", "\n", "Four inequalities are available. `HOEFFDING_INEQUALITY`, `EMPIRICAL_BERNSTEIN` and `BETTING` are distribution-free and give a genuine high-confidence guarantee; `T_TEST` assumes approximate normality of the sample mean, which is what makes the result *quasi*-Seldonian. Empirical Bernstein and betting pay for the variance they measure rather than assuming the worst case of 1/4, so they are much tighter when a group's rate is far from 1/2 — the common case for a minority group. Betting is the tightest and the slowest.\n", "\n", "Below: a stricter confidence level ($\\delta = 0.01$) and a tighter constraint — the gap must stay within **15 %** of group 1's cell (vs. 25 % by default).\n" ] }, { "cell_type": "code", "execution_count": 7, "id": "30971cad", "metadata": { "execution": { "iopub.execute_input": "2026-08-24T05:09:41.966538Z", "iopub.status.busy": "2026-08-24T05:09:41.966438Z", "iopub.status.idle": "2026-08-24T05:09:42.833500Z", "shell.execute_reply": "2026-08-24T05:09:42.833080Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== Strict (δ=0.01, 15% gap) ===\n", " No Solution Found — constraint could not be certified.\n", "\n" ] } ], "source": [ "strict = SeldonianConfig(\n", " delta=0.01,\n", " inequality=Inequality.T_TEST,\n", " constraint=\"TP(1) TP(0) - abs 0.15 TP(1) * -\",\n", " candidate_ratio=0.5,\n", ")\n", "run_scenario(\"Strict (\\u03b4=0.01, 15% gap)\", 0.5, 0.5, strict)" ] }, { "cell_type": "markdown", "id": "b85916e3", "metadata": {}, "source": [ "## 6. Algorithm variants\n", "\n", "The `seldonian_type` string selects how the confidence interval is constructed. Tighter bounds make it easier to certify a fair model on a given amount of data.\n", "\n", "| Mode | Description |\n", "|------|-------------|\n", "| `base` | Standard Hoeffding bound, uniform $\\delta$-splitting |\n", "| `mod` | Decomposed candidate/safety estimation error |\n", "| `const` | Constant-aware $\\delta$ allocation |\n", "| `bound` | Union-bound optimisation for repeated variables |\n", "| `opt` | All optimisations combined |\n", "| `affine` | Compiles the constraint to a max of affine forms and bounds each with a single interval, exploiting the independence of disjoint groups. Roughly halves the slack, but only applies to constraints built from `+`, `-`, scaling by a constant and `abs`; anything else raises `NotAffine`. |\n", "\n", "We run each variant on the same fair dataset and compare the certified upper bound (lower = tighter).\n" ] }, { "cell_type": "code", "execution_count": 8, "id": "ef458a49", "metadata": { "execution": { "iopub.execute_input": "2026-08-24T05:09:42.834973Z", "iopub.status.busy": "2026-08-24T05:09:42.834873Z", "iopub.status.idle": "2026-08-24T05:09:43.076602Z", "shell.execute_reply": "2026-08-24T05:09:43.076023Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " mode | passed | upper bound g (test)\n", "----------------------------------------\n", " base | True | -0.0402\n", " mod | True | -0.0402\n", " const | True | -0.0408\n", " bound | True | -0.0422\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ " opt | True | -0.0438\n" ] } ], "source": [ "data = get_data(\n", " N=20000, features=5, t_ratio=0.5, tp0_ratio=0.5, tp1_ratio=0.5, random_seed=7\n", ")\n", "X_te, Y_te, T_te, X_tr, Y_tr, T_tr = data_split(\n", " frac=1.0, all_data=data, random_state=1, m_test=0.3\n", ")\n", "cfg = SeldonianConfig(delta=0.05, inequality=Inequality.T_TEST)\n", "\n", "print(f\"{'mode':>6} | {'passed':>6} | upper bound g (test)\")\n", "print(\"-\" * 40)\n", "for mode in (\"base\", \"mod\", \"const\", \"bound\", \"opt\"):\n", " theta, theta1, passed, _ = QSA(X_tr, Y_tr, T_tr, mode, None, None, cfg)\n", " ub = float(eval_ghat(theta, theta1, X_te, Y_te, T_te, mode, cfg))\n", " print(f\"{mode:>6} | {str(passed):>6} | {ub:+.4f}\")" ] }, { "cell_type": "markdown", "id": "ecce3468", "metadata": {}, "source": [ "## 7. With vs. without QSA — the price and value of the guarantee\n", "\n", "The clearest way to see what QSA buys you is to run the **same dataset** through two models:\n", "\n", "- **Without QSA** — plain logistic regression (`simple_logistic`), which only maximises accuracy.\n", "- **With QSA** — the Seldonian algorithm, which maximises accuracy *subject to* the fairness constraint holding with high confidence.\n", "\n", "We compare test accuracy and the high-confidence upper bound on the constraint $g$ (the same quantity `eval_ghat` returns). Plain logistic regression is a few points more accurate, but its bound sits **above zero** — on this data its fairness cannot be certified. QSA trades a little accuracy for a **certified** guarantee ($g \\le 0$). That trade — a small, explicit accuracy cost in exchange for a *provable* safety guarantee — is the whole point of the Seldonian approach." ] }, { "cell_type": "code", "execution_count": 9, "id": "41c72d84", "metadata": { "execution": { "iopub.execute_input": "2026-08-24T05:09:43.078070Z", "iopub.status.busy": "2026-08-24T05:09:43.077957Z", "iopub.status.idle": "2026-08-24T05:09:43.608888Z", "shell.execute_reply": "2026-08-24T05:09:43.608460Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Without QSA: accuracy=0.854 bound g=+0.107 → NOT certifiable\n", "With QSA : accuracy=0.787 bound g=-0.032 → certified fair\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA3kAAAGMCAYAAABnMGtWAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjksIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvJkbTWQAAAAlwSFlzAAAPYQAAD2EBqD+naQAAi6tJREFUeJzt3QeYE2X3NvBD7733IkqRKkgXpEhVutKkVwUpighKEZBepUkv+tIEAREQRbr0jvQubem9t3zXffwm/0k22U2WZLM7e/+ua2AzmUwmk8nMnKecJ5rNZrMJERERERERWUL0QG8AERERERER+Q6DPCIiIiIiIgthkEdERERERGQhDPKIiIiIiIgshEEeERERERGRhTDIIyIiIiIishAGeURERERERBbCII+IiIiIiMhCGOQRERERERFZCIM8IiIfevfddyVatGg6nT17lvvWz7CPjf2Nfe+pb7/91v66WbNmSVQVluM1rPuciIjCT8xwfC8iiiIuXLgg/fr1k9WrV8ulS5ckXrx4kipVKsmdO7e8/fbb0qdPn0BvYoS2dOlS2bdvn/7dvHlzyZo1q0QkuMk3AqOCBQtKrVq1JKK5ffu2jBkzRv/G/sN+JM/h+zWCvi5dukjSpEktua1PnjyRqVOnys8//ywHDx6U+/fvS4oUKaRIkSLSsmVLqV27tsvX/e9//5NJkybJgQMHdB3JkyeXDBkyyFtvvaWvK168eLDX4FyYKVMmefnypT5OkiSJXLlyReLEiRPmz05E5JaNiMiHgoKCbOnSpbPh9OJqihEjhqX3d9myZe2f9cyZM2FaR7NmzezrWLdunS2iwTYZ24dtDaTHjx/bNm3apNOBAwfs87HvjW3Ed+Ksb9++9udnzpxpi6qwz4z9h33pyXEc2r6NLL+5ixcv2goUKOD2XIXpww8/tD19+tThdd9++22IrxkwYIDL9xs1alSwZZcsWfLKn5+IyBXW5BGRT40bN06CgoL07woVKkiHDh0kYcKEWtK+Y8cOraUi8hXUgpQuXZo7NIzy5csXJfcdatPq1Kkj+/fv18eZM2fWFgao9d22bZsMHDhQHj16JAsXLtTnRowYocuhpm/w4MH6N1ooDBgwQGuzb968KSdOnJDffvtNm7G6Mm/evGDz5s+fHyFrwonIAlyGfkREYVSlShV7KbW5ZsXw4MEDh8cbNmyw1atXz5YjRw5bkiRJbLFixdKaQJSg79+/323ty7Rp07REPW3atLZEiRLZGjRoYLt165btxo0bto8//tiWOHFiW7JkyWzt2rWzPXr0KNh2LF261FahQgVb0qRJbbFjx7a98cYbur6HDx969DmfP3+u25M+fXpbvHjxbO+++65t3759bmsVPv/8c1uJEiV0e/F+CRIksBUqVMg2fPhw27Nnz4LVkLiajFq9wYMH6/tkyJDBFjduXH3/3Llz27755ptg+xfbVKNGDVuqVKlsMWPGtCVPnlxrL7Bf/v33X4dlN27caPvggw9sKVOm1O8ha9astq5du9pu3rxpX8b8+ZynsNTq4RgxXt+4cWP7fHwW5/147949rQnGvKJFi7qtVTLXhDpPxjLONXkTJkzQYxDfTf78+W1r1qwJcbtRu5MiRQp9Pfap8R0acDzhuThx4tj336JFi2ylSpXSYxP7N02aNPq4e/futpcvX9rC4q233tL3wfqMY/fEiRP2z4bPafjoo4/s8w8fPqzznI9Xcy2tqwnLOO9zHGPly5fX4xCfCd/dixcvHLbzyZMntiFDhuixFz9+fF0W+xnHMp4zM9adJUsWh/lh2VZ3fvnlF/ty+F1gn5nNmjXL/jyOiUuXLun8bdu22efXqVPH5bqdf4Nw8uRJ++vwnWfKlEn/xr64f/++2+0kIgorBnlE5FMIzoybGQQXaAbmfBNnhps8dzdpuAEybkadb8xfe+21YMsjwMTNv/N83HSa9e7d2+17vvPOOyFur6FDhw7BXoubdwRGrm4ycbPv7j1btGjhVZCXM2dOt8uUK1fO/p7Xr1/X4M7dsqtXr7YvO3XqVFv06NFdLof3MwIVXwd5CG4QjBvfqQFBg7HeuXPn6jwEXsa8bt26+SzIQ4DsvBwKDszBrSvt27e3L//nn3/a56Nwwphfu3Ztnbd+/Xq3+xeTc5Doqc6dO9vXgd8a/Pjjj/Z5lSpVsi9rBBY4JgyvGuRlzJjRljBhwmDL4XgyoBlomTJl3K4Tz5l/c+ER5KEgyFgOhUzO8H2gQMZYZsaMGTr/0KFDDr/3SZMm2c6fPx/q9/Tdd9/ZX/f999/bunTpEuz4JiLyJWbXJCKfqlixov3vZcuWyTvvvCOJEiXSJnUjR46UBw8eOCxftGhRbeKJZdetW6fJWoYOHarPPXz4UEaPHu3yfdD8c9iwYbJgwQJdP6xatUoOHz4s06ZNkx9++MG+7OTJk+1/79y5U5tYQbp06WT69On6uurVq+u8TZs2uX1Pw9GjR2XixIn6d/To0TVT4/Lly6VEiRJuMxR+88032lwL77V+/XpZvHixFCtWzJ44AslqsD14/6pVq9pfN3bsWJ2HqVChQjqvffv28tNPP8nKlSt1Xdh31apV0+ewD7ds2aJ/b926Va5du6Z/N2zYUPctmsui6VnZsmUlRowY+tzFixelY8eO2oQN+xLfxx9//CEtWrTQ548dOyZff/21/o3nsE0GbKuxffiM3kLTNqO55alTp3R7X7x4oU17DcbnMf4HHFfuYDvQzM6A5nTGNmL7nR05ckS++uor3Y8FChTQeffu3ZO5c+eGuO0ff/yx/e9Fixa5/NtYBs34jIQbgwYNkjVr1mhTvV69ekmePHncNvELTZkyZex/4/s2/w/bt2/X98V3fP78eZ0XUvNWHGPYT9hnBuxLY//hGDXDcYt99uuvv0qnTp1c/uaQAGfjxo36NxKPYL/it4BmkIDnQvvN+WJbzXCeMJhfb4gZM6a8+eab9seHDh3S/19//XX7dt+9e1d/i/hMmPB7Me97V0018T3XrVtX6tWrZ38OxwERkc/5NGQkoigPzRjR7M5d6Tpqa8w1JGjahGaS+fLl05o75+XRpNFgrn1p1KiRfX716tXt81FLZ3jzzTft82/fvh2s5uPrr7+2J5347bff7PPz5s0b4vc4dOhQ+7KouTTgPcyfwVyT8Pfff9tq1qyptQNoHub8OX/99VePE68cPHhQm6eiFgXN9JzXhZoCWLVqlX0emgSeO3fOZbPA0aNHO9QqGvsEzTeNz4OmtEYTPF8nXhk2bJjDfkDzP/xtfH+FCxfW5apVq6aPo0WLps1yQ0oC4k3iFXwvhvnz59vno7YlJNiX2bJl02VTp06txz4YNYNoCmwkM+nRo4d9vQsXLtRaVl+4evVqsFrDggULOuy/f/75x/bzzz/bl0MCEIO75sWeJl5BU8bLly/rfBwfxvGCz25As0xjefzODObfHJpxeluT58m2uoOmucZrJk+e7HIZ/MaMZdq0aePQxBzft7tznPH7M2D/G8+hybZx7KCpt7EP0dSciMiXWJNHRD6F2iGkF0fygi+++EJL21HbZUBtzfDhw+2PUcOEmrB//vlHa+5cpcJ3BTWABqQvNyD1uSFlypTB1nP8+HH7PNSooEYI0wcffOBQUxeS06dP2//GkBAGpETPmTNnsOVRK1WuXDmt7bh8+bI8f/7c48/p7N9//5WSJUtq6T9qUZ49e+Z2XfhcqHkA1HqiBgLbiLHNkDbeqFky75OZM2fa9wlqiYzv5M6dO5oC3h+ca6OM2hDUeKCGBMkxUAOMYwpQ82X+zl8VajUNSJ/v6XeCWplGjRrp31evXtUaKdQQoWYQUFtjpMdv3Lix/e8PP/xQj800adJo8o+//vorzNuOoUly5cqlf2O/ITEIfkv4rrFuowbU01pQb+G98TkAv/NkyZIF23fm48uovXb+DZuXCQ9G7T9cv37d5TJGLTgYn9E4XlG7jRYDNWvWdDhmoEePHg6f35xwxajBM2r04OnTp1qzT0TkSwzyiMgvcDOHZoF79uzR4MC44QTMg3PnzmkTOUAGTjSBRPNDTAYjEHGGYMVgDiITJ07scvn/Kgg8gyAMY1+FhatmdxhPywjG3n//fW1mieZkTZs2DfVzOps9e7Y2EwM0D0XzS6yre/fuwdYVP3582bx5s/Tv31/Kly8vadOm1WaIGzZskLZt22rg5w3npra+UrhwYUmQIEGwIA+fDxO+DzRPRQZDXwcpYAQmRjM9b44Z5yab5qaaCOwMefPmld27d2uTRvw2cPwiMFyyZIlUrlzZIQgLa5CMAgSM94bmrsa+c96n+J0ZzX59ve+c919oQmuiis9h5i4YCwsUFBgQFDvDMWc00QSjsMSAsfhatWqlvz98jytWrNBsm4CsnOaCIjQpN6DgyxhI3tx0mE02icjXGOQRkU+hNgO1CWYoBW/WrFmwmzf0EzLgRveTTz7RWhV/Dg78xhtvONRa/f8EVA4TgpmQtiF79uz2v3ft2mX/G7VdKOF3Zv6cSL+OfmzoF4WBkF0xB63OwZ95Xegnh5oErAvv7QyfBTU9vXv31j5gGNoCtZC40Qej9sC8T/r27et2nxi1lCFtX1ggMDAGj0afyb///ltvghEMGYGKMbC5c82fO77expBqsjAAtrE/jb6AqIE01xBiH6KP1/fff681kqjpMQJCbN+rDC1iDnqNvm3Yb9in2I8oNNm7d6/ORy2w0RczvPaf+fgy97VEf0FXyxgFODdu3LAXjqCvq7sa9rBsq3nYAnxvRn9Fc+0bgmZAAYQxKDoKGowaZfP7o0+sUaNqPsfh86L1QmjWrl2rwSIRka9wnDwi8qkpU6ZoqTaapOEmN3369BrMoGmkcxPHLFmyONzk4MYKN6BGkg9/QPM63GhD165d9aYtf/78etONm7E///xTt2vGjBlu14GmnUjUAb/88osmckFt1Pjx413Wdpk/J4I8BLy///67JjcJrXYETV+xTzAhmDOvCwlQYseOrTfLSCDjDLVDqDlCszDURKCJ4IEDB+xNMI3aSjQhQxMzPB4yZIgGBggSsNyZM2c0mQtqJ5C4xXn7EJDhs6D5G27UU6dOrUEFmqcCPisSy4QGgRsCUbwnAtHcuXPr+xhBnjl49qQmz7yNqKlBEIXPj2aMRuIMX0FtHmqnERQYgQGOM3NNFWpNsV+Q4Afvj8DB/P2ba44xVhua5Xpam2gOeg8ePKj/Y79hHyAwNwdHntaCmvcfmvYiiEFNlbk5tKewL3DcAcbNRG0y9g2OOXOzbUOOHDm01hPHHF6Lz4dafueavVfZVgRteB6FNGguiSbMSIKD35cxTp4B5yOjeSfOF0YAjXVgnMFYsWLp+Wvfvn26DAqIcE5xbqpZv379YElvcFziuMdnQwEB9g8RkU/4tIcfEUV5ISVdwYTEI0FBQS6TppjHkXKVfMF5bLPQEpW4S8gQ0hAKniYTMafPNyaM/YWx65zfc/v27ZosxLwsHiMJg6vPY05IYZ4AY9u5SlBj3mfG2GhInhLS58TwFZ4MoeCcvMQ5vbzzZwhLYpa1a9c6rKtly5Y6H6n1zcNPYIgKs5ASrCBhi/M2GvvG3bEUlm3HGGrG+H3uxogcMGCA232L/Y7EPAYc8+bv3BOZM2e2vwZjJ2IcP0AiHfN7YSgHM3e/kXHjxgXbTuO3GNI+d7XtSD6DoUk8HUIBiVCcl8EwDUg05O22hgRDHyDhU0i/ESRcMScrMo9B6G5CIikjEY2RXAUTErC4Gq/TeL506dKhbjMRkafYXJOIfArN/VBrUalSJXnttde0xgK1TfgbzTFRco6+YQb0tUJtD2pZ0M+lSZMmmm7en9BHDUMeVKlSRZMmoCQ+Q4YMWsqOmqx+/fqFug70p0EzSKRpjxs3rpQqVUpL5FEL4QwJJtD3CqX+WBbN9lBqj33kCvrtoT8j9plzHyfUAqG2EetEbQWWQS1H69atg60HNWuocUStA5rMYl1oqoma1AkTJthrIwGvR1Nb9J00lsX/eB98TmPICMBz6EuJ/WVOYOGqyZynTW+xjThODEYNHuahltTgTX881KLgO3buN+ZrOAbQ59GAWhx812aoXWrXrp32zcP2oGYWyWNwDKBGD8fPqzDX5mF/4Zg270djX5oTn4QE24rjA8ebuTlkWOAYQC0wflvYNzhu8TvAPkLNNo5n83ePY7Fnz55aK4xlsW/R7xTHui+3NWPGjNqcEr9l7D98L+baV5zL0DLBPA81fWjeiffE0AvYRvwecO5CbeCcOXP0dYDfk5GsKFu2bPrdO3vvvfd0XwD6zzo3GyUiCqtoiPTC/GoiIiIno0aN0gQTuPlFZkxzkguiiAxJjVAIgmyfKHhCoZS5iTQRUWTBmjwiIvIpZO+Ezp07M8CjSAXZeVHrjhpvZPNEYiNXQ7sQEUV0rMkjIiKfQVNN1ICgCRqSpbhqzkkU0aHpNZqIGk0qX7U5LRFReGOQR0REREREZCFsrklERERERGQhDPKIiIiIiIgshEEeERERERGRhTDIIyIiIiIishAGeURERERERBbCII+IiIiIiMhCGOQRERERERFZCIM8IiIiIiIiC2GQR0REREREZCEM8oiIiIiIiCyEQR4REREREZGFMMgjIiIiIiKyEAZ5REREREREFsIgj4iIiIiIyEIY5BEREREREVkIgzwiIiIiIiILYZBHRERERERkIQzyiIiIiIiILIRBHhERERERkYUwyCMiIiIiIrIQBnlEREREREQWwiCPiIiIiIjIQhjkERERERERWQiDPCIiIiIiIgthkEdERERERGQhDPKIiIiIiIgshEEeERERERGRhTDIIyIiIiIishAGeURERERERBbCII+IiIiIiMhCGOQRERERERFZCIM8IiIiIiIiC2GQR0REREREZCEM8oiIiIiIiCyEQR4REREREZGFMMgjIiIiIiKyEAZ5REREREREFsIgj4iIiIiIyEIY5BH5yc8//yzJkyeX+/fv2+dFixZNOnbsGOprZ82apcuePXvW6/c1Xrtr1y6xAit9nkmTJknmzJnlyZMngd4UooBbv369/rbxP9GrqlatmrRp04Y7MhJ49913dTK7cuWK1KtXT1KkSKHnhTFjxvjlHPHtt9/qOj3x008/Sa5cuSRWrFiSNGlSr96nefPmkjVrVo+WPXz4sMSMGVMOHjwovsQgj9yaOHGi/hCK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Bl11gQor9skjCgHac6ONtzmZiydw4UBTTTQbctVuPCxcjaNj9KXAxY0iPvS/QEIIV+NXEZF1oOkVCgmdkzagqSjP176HJnnoJoGmqCFdN9EPE83r0FyRAR5FFOgriGbavq4UYE0ekQvIeIU22/jBoc9bWMc18qVZs2bphE7YSBDw999/a+ZPXNhepSMxERH5Fvo4oV8y0tCjNQhqmNBXHX3wkMwivPonRnWoOUVQjWzG6EuJFjlIVIIso+bsiERWxMQrRC4ggQc6bOMCgcAqIsC4NOhcjpJKpGE2krGgqSYREUUcaEaPhCRIEoHWIEj6gQQhSGjBAC/8oFAUyXSQ1RJN4ZBsBIEeAzyKCliTR0REREREZCHsk0dERERERGQhUa655suXL7U9NgaLDMvYYkRE5F9I+owxO9GXKbRBhsm3eI0kIrLGNTLKBXkI8DJlyhTozSAiolCcP39eMmbMyP0UjniNJCKyxjUyygV5qMEzdkzixIkDvTlEROQEiYVQGGecryn88BpJRGSNa2SUC/KMJpoI8BjkERFFXGxSH7h9zmskEVHkvkayswMREREREZGFMMgjIiIiIiKyEAZ5REREREREFsIgj4iIiIiIyEIY5BEREREREVkIgzwiIiIiIiILYZBHRERERERkIQzyiIiIiIiILIRBHhERERERkYUwyCMiIiIiIrKQmIHeACIiIn9IliyZRIsWLdh8zIsbN67kyJFDmjdvLi1atOAXQERElsIgj4iILKlPnz4ycOBAqVq1qhQtWlTn7dixQ1atWiUdOnSQM2fOyCeffCLPnz+XNm3aBHpziYiIfIZBHhERWdLff/8t3333nbRv395h/uTJk+XPP/+UX375RfLnzy9jx45lkEdERJYS0D55GzdulA8++EDSp0+vzWeWLl0a6mvWr18vb731lsSJE0eb2syaNStctpWIiCKXP/74QypWrBhsfoUKFfQ5qFatmpw+fToAW0dERGTRIO/BgwdSoEABmTBhgkfLo2lN9erVpVy5crJv3z7p0qWLtG7d2n6xJiIiMiRPnlx+++23YDsE8/CccR1KlCgRdxoREVlKQJtrop8EJk9NmjRJsmXLJiNHjtTHuXPn1uY4o0ePlsqVK7t8zZMnT3Qy3L171wdbTkREEV3v3r21z926devsffJ27twpK1eu1OsJrF69WsqWLRvgLSUi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06fLkCFDpFSpUjrv77//lm+//VYeP37MViBERGRZDPKIiMiSZs+eLdOmTZMaNWrY5+XPn1/7en/66acM8oiIyLI45gAREVnSzZs3JVeuXMHmYx6eIyIisioGeUREZEkFChSQ8ePHB5uPeXiOiIjIqthck4iILGnYsGFSvXp1+euvv6REiRI6b+vWrXL+/HlZuXJloDePiIjIb1iTR0REllS2bFk5fvy41K5dW27fvq1TnTp15NixY/LOO+8EevOIiIj8hjV5RERkWenTp2eCFSIiinJYk0dERJZ169YtGTFihLRq1UonjJkXXklXJkyYIFmzZpW4ceNKsWLFZMeOHSEuv3DhQk0Kg+Xz5csXrElptGjRXE7Dhw+3L4P3c34eQ0gQEVHUwiCPiIgsaePGjRr0jB07VoM9TPg7W7Zs+pw/LViwQD7//HPp27ev7NmzRxO9VK5cWa5evepy+S1btkjDhg01EN27d6/UqlVLp4MHD9qXCQoKcphmzJihQVzdunUd1tW/f3+H5T777DO/flYiIop4GOQREZEldejQQerXry9nzpyRxYsX63T69Glp0KCBPudPo0aNkjZt2kiLFi0kT548MmnSJIkfP74GZq58//33UqVKFfnyyy8ld+7cMmDAAHnrrbccsoOmTZvWYfr111+lXLlykj17dod1JUqUyGG5BAkSuN3OJ0+eyN27dx0mIiKKgkHeunXr/LMlREREPnTy5En54osvJEaMGPZ5+Bs1bHjOX54+fSq7d++WihUr2udFjx5dHyO7pyuYb14eUPPnbvkrV67IihUrtObPGZpnpkiRQgoVKqRNOZ8/f+52WwcPHixJkiSxT5kyZfLikxIRkWWCPJQ0vvbaa/Ldd99pGmoiIqKICDVhR44cCTYf8/w5Tt7169flxYsXkiZNGof5eHz58mWXr8F8b5afPXu21tghW6hZp06dZP78+Vog265dOxk0aJB0797d7bb27NlT7ty5Y594XSciiqLZNS9evCg//fSTXmD69esn5cuX15JE9B2IHTu2f7aSiIjIAwcOHHAIeDp37qy1dsWLF9d527Zt04QokT0ZCZp9Nm7cWJO0mKGW0pA/f369LiPYQ41dnDhxgq0H81zNJyKiyM3rIC9lypTStWtXndCZfObMmfLpp5/q1KhRIw34/FlCSkRE5E7BggU1GYnNZrPPc1WT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Os6doWTJkjp2H7ojIEkMhglCJum8efPq82jBgrFoa9SooS1aMJ4eCkpRO2nukjBnzhwdUB3NNzF0AlrZYJ1ERBS1eN0nDxkuzTA+Hi5UGMsHNW3eXgSvXbumF0E0ucSF0PkiiIyb5g7zf/zxh3Tt2lU7nKNEFgEfsmsSERGZIaDDNQOBjgG1XihcRI2Xv6EWzd1QDUiW4uzDDz/UyZV48eLpZwkNMmn6e6B3IiKyYJBXq1Yth8cYAB1DGZQvX16bmfj7IoimnGiuQkREFJIUKVJIkiRJgs3HvGTJknHnERGRZXkd5Jn7wxEREUVUvXr10m4BP/30kz2hF1qNoG9b7969A715REREESfIIyIiigx++OEHTdaVOXNmnYxuAOjDhq4CkydPti+7Z8+eAG4pERFRgIM8DCxbtGjRYP3ghg0bJjt37pSFCxf6cvuIiIjCxLl7ARERUVThdZC3ceNGTe3srGrVqmHqk0dEROQPffv25Y4lIqIoyeshFDBWj6sx6WLFiqVjEhEREREREVEkCvLy5csnCxYsCDZ//vz5kidPHl9tFxER0SvBEDwYX87dREREZFVeN9dERrI6derIqVOndNgEWLNmjcybN4/98YiIKMJYsmSJw+Nnz57J3r17Zfbs2dKvX7+AbRcREVGEC/I++OADWbp0qQwaNEgWLVqkA7RiYPK//vpLypYt65+tJCIi8lLNmjWDzatXr568+eab2iKlVatW3KdERGRJYRpCoXr16joRERFFNsWLF5e2bdsGejOIiIgiTp88DJOwffv2YPMxb9euXb7aLiIiIp979OiRjB07VjJkyMC9S0REluV1kNehQwc5f/58sPkXL17U54iIiCKCZMmSSfLkye0THidKlEhmzJghw4cPD/TmERERRZzmmocPH5a33nor2PxChQrpc0RERBHBmDFjgmXbTJUqlRQrVkwDPiIiIqvyOsiLEyeOXLlyRbJnz+4wPygoSGLGDFMXPyIiIp9r1qwZ9yoREUVJXjfXrFSpkvTs2VPu3Lljn3f79m35+uuv5b333vP19hEREREREZEXvK56GzFihJQpU0ayZMmiTTRh3759kiZNGvnpp5+8XR0REREREREFMshDRrIDBw7InDlzZP/+/TpOXosWLaRhw4YSK1YsX24bEREREREReSlMnegSJEjAMYaIiIiIiIgioDBnSkEmzXPnzsnTp08d5teoUcMX20VERPTKnj9/LuvXr5dTp05Jo0aNdAiFS5cuSeLEiSVhwoTcw0REZEleJ145ffq0FChQQPLmzSvVq1eXWrVq6VS7dm2diIiIIoJ///1X8uXLJzVr1tRxXK9du6bzhw4dKt26dfP7+0+YMEGyZs0qcePG1WEbduzYEeLyCxculFy5cuny2O6VK1fan3v27Jl89dVXOh+tadKnTy9NmzbVgNUM7xctWjSHaciQIX77jEREZJEgr3PnzpItWza5evWqxI8fXw4dOiQbN26UIkWKaGkpERFRRIDrFa5Nt27d0v7jBhRIrlmzxq/vvWDBAvn888+lb9++smfPHi0crVy5sl47XdmyZYv2bW/VqpXs3bvXXoB68OBBff7hw4e6nt69e+v/ixcvlmPHjrlsPdO/f38d1siYPvvsM79+ViIiskBzza1bt8ratWslZcqUOrAsptKlS8vgwYOlU6dOenEiIiIKtE2bNmnwFDt27GC1XRcvXvTre48aNUratGmjiclg0qRJsmLFCpkxY4b06NEj2PLff/+9VKlSRb788kt9PGDAAFm9erWMHz9eX5skSRJ9bIbnihYtql0nMmfObJ+PJqlp06b1aDufPHmik+Hu3bth/sxERBSJa/JevHihFxBAoGc0FcGQCihVJCIiighevnyp1yxnFy5csF/H/AF91Xfv3i0VK1a0z0OBKB6joNQVzDcvD6j5c7c8YLxaNMdMmjSpw3w0z0yRIoUOczR8+HDtl+gOCmgRQBpTpkyZvPikRERkmSAPffEwdAKgj8GwYcNk8+bN2jwke/bs/thGIiIir1WqVEnGjBljf4yA6P79+9qEslq1an7bo9evX9fgEuPHmuHx5cuXXb4G871Z/vHjx9pHD008kUTGgBY18+fPl3Xr1km7du1k0KBB0r17d7fb2rNnTw0Wjen8+fNefloiIrJEc81evXrJgwcP9G8Edu+//7688847WmqIPghEREQRwciRI7U2LE+ePBoUIbvmiRMntBXKvHnzJLJCEpaPPvpIbDab/PDDDw7PoR+gIX/+/NpUFcEeauzixIkTbF2Y52o+ERFFsSAPF0xDjhw55OjRo3Lz5k1JliyZlpISERFFBBkzZtSWJyiAxP+oxUNik8aNGzskYvE1BJExYsSQK1euOMzHY3d95TDfk+WNAA+ZQ9E/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XsHjEiVKuHwN5puXB2TINJZHdwgEauZlcKFHAauxDP5HTSX6AxrWrl2r720emoiIiKzP45q8devW6f8tWrSQ77//niV8REQUoaH/OGqynKH1iXOtma+h9UuzZs00CUrRokVlzJgxmj0T11Bo2rSpZMiQQfvEQefOnbX5DYZ9qF69usyfP1927dqlQxYZrWi6dOki3333nbz++usa9CGIRcZMDLUAuXPnlipVqmhNJTJyYnxAjEOLpCyeZNYkIqIo3Cdv5syZ/tkSIiIiH6pQoYI2y5w2bZq9aQxquT755BO/D6OAIRHQHxCDlyPpCZo/YjgDI3EKslEj66WhZMmS2rwUNYxff/21BnLIrIlxaA0YlxaBIsa9Q40dMoZineb+8HPmzNHADp8d68eg794koyEioig8Tl5kxnHyKCLhOHlkVRFhnDwEWahNQyAUK1YsnYeaPQxNgO4FzpkoyfdjFBJZSbp+rptbE3krqK/r4XQCOk4eERFRZJAqVSpZuXKlHD9+3D50Qa5cueSNNzhQNxERWRuDPCIisjQEdQzsiIgoKmGQR0REloGEJwMGDJAECRI4jP/myqhRo8Jtu4iIiMITgzwiIrIMDOuDrJKwZ88ezUrpirv5REREVsAgj4iILMM8xM/69esDvTlEREQB4fFg6ERERBFdoUKF5Pr16/p39uzZ5caNG4HeJCIionDHII+IiCwjadKkcubMGf377Nmz8vLly0BvEhERUbhjc00iIrIMDP5dtmxZSZcunfa7K1KkiMSIEcPlsqdPnw737SMiIgoPDPKIiMgypkyZInXq1JGTJ09Kp06dpE2bNpIoUaJAbxYREVG4YpBHRESWUqVKFf1/9+7d0rlzZwZ5REQU5TDIIyIiS5o5c2agN4GIiCggGOQREZElPXjwQIYMGSJr1qyRq1evBkvCwj55RERkVQzyiIjIklq3bi0bNmyQJk2a2BOxEBERRQUM8oiIyJJ+//13WbFihZQqVSrQm0JERBSuOE4eERFZUrJkySR58uSB3gwiIqJwxyCPiIgsacCAAdKnTx95+PBhoDeFiIgoXLG5JhERWdLIkSPl1KlTkiZNGsmaNavEihXL4fk9e/YEbNuIiIj8iUEeERFZUq1atQK9CURERAHBII+IiCypb9++gd4EIiKigGCfPCIisrTdu3fL//73P5327t3r9/e7efOm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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Same dataset for both models. get_data seeds its own generator\n", "# from random_seed, so the draw is reproducible without touching\n", "# the global NumPy RNG.\n", "cmp_data = get_data(\n", " N=20000, features=5, t_ratio=0.5, tp0_ratio=0.4, tp1_ratio=0.6, random_seed=7\n", ")\n", "Xc_te, Yc_te, Tc_te, Xc_tr, Yc_tr, Tc_tr = data_split(\n", " frac=1.0, all_data=cmp_data, random_state=1, m_test=0.3\n", ")\n", "cmp_cfg = SeldonianConfig(delta=0.05, inequality=Inequality.T_TEST)\n", "\n", "\n", "def accuracy(\n", " theta: torch.Tensor, theta1: torch.Tensor, X: np.ndarray, Y: np.ndarray\n", ") -> float:\n", " yhat = (predict(theta, theta1, X).detach().numpy() >= 0.5).astype(int)\n", " return float((yhat == Y).mean())\n", "\n", "\n", "# Without QSA: plain logistic regression, no fairness constraint.\n", "lr_theta, lr_theta1 = simple_logistic(Xc_tr, Yc_tr)\n", "lr_acc = accuracy(lr_theta, lr_theta1, Xc_te, Yc_te)\n", "lr_bound = float(eval_ghat(lr_theta, lr_theta1, Xc_te, Yc_te, Tc_te, \"opt\", cmp_cfg))\n", "\n", "# With QSA: same data, fairness constraint enforced with high confidence.\n", "qsa_theta, qsa_theta1, qsa_passed, _ = QSA(\n", " Xc_tr, Yc_tr, Tc_tr, \"opt\", None, None, cmp_cfg\n", ")\n", "qsa_acc = accuracy(qsa_theta, qsa_theta1, Xc_te, Yc_te)\n", "qsa_bound = float(eval_ghat(qsa_theta, qsa_theta1, Xc_te, Yc_te, Tc_te, \"opt\", cmp_cfg))\n", "\n", "for name, acc, bound in [\n", " (\"Without QSA\", lr_acc, lr_bound),\n", " (\"With QSA \", qsa_acc, qsa_bound),\n", "]:\n", " verdict = \"certified fair\" if bound <= 0 else \"NOT certifiable\"\n", " print(f\"{name}: accuracy={acc:.3f} bound g={bound:+.3f} → {verdict}\")\n", "\n", "labels = [\"Without QSA\\n(plain LR)\", \"With QSA\"]\n", "accs = [lr_acc, qsa_acc]\n", "bounds = [lr_bound, qsa_bound]\n", "\n", "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 4))\n", "\n", "ax1.bar(labels, accs, color=[\"#9aa0a6\", \"#1a73e8\"])\n", "ax1.set_ylim(0, 1.08)\n", "ax1.set_ylabel(\"test accuracy\")\n", "ax1.set_title(\"Accuracy (higher = better)\")\n", "for i, v in enumerate(accs):\n", " ax1.annotate(\n", " f\"{v:.3f}\", (i, v), textcoords=\"offset points\", xytext=(0, 4), ha=\"center\"\n", " )\n", "\n", "bar_colors = [\"#d93025\" if b > 0 else \"#188038\" for b in bounds]\n", "ax2.bar(labels, bounds, color=bar_colors)\n", "ax2.axhline(0, color=\"black\", linewidth=1)\n", "pad = 0.04\n", "ax2.set_ylim(min(bounds) - pad, max(bounds) + pad)\n", "ax2.set_ylabel(\"high-confidence upper bound on g\")\n", "ax2.set_title(\"Fairness guarantee (g ≤ 0 ⇒ certified fair)\")\n", "for i, v in enumerate(bounds):\n", " ax2.annotate(\n", " f\"{v:+.3f}\",\n", " (i, v),\n", " textcoords=\"offset points\",\n", " xytext=(0, 6 if v >= 0 else -14),\n", " ha=\"center\",\n", " fontweight=\"bold\",\n", " color=bar_colors[i],\n", " )\n", "\n", "fig.suptitle(\"Same dataset, with vs. without QSA\", fontweight=\"bold\")\n", "fig.tight_layout(rect=[0, 0, 1, 0.96])\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "fc06d79c", "metadata": {}, "source": [ "## Next steps\n", "\n", "- Swap in your own data: arrange features as `X`, binary labels as `Y`, and a binary sensitive attribute as `T` (all NumPy arrays), then call `QSA(X, Y, T, \"opt\", None, None, config)`.\n", "- Write your own constraint in postfix form over the cells `TP/FP/TN/FN(group)` and the rates `TPR/FPR/TNR/FNR(group)` — or start from a builder such as `demographic_parity`, `equal_opportunity` or `equalized_odds`.\n", "- Read the docs: https://parulgupta1004.github.io/fair-seldonian/\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.13.7" } }, "nbformat": 4, "nbformat_minor": 5 }