{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Aggregation: Sum\n", "\n", "This notebook is a deep-dive on transformations for computing the sum with bounded stability.\n", "\n", "---\n", "Any constructors that have not completed the proof-writing and vetting process may still be accessed if you opt-in to \"contrib\".\n", "Please contact us if you are interested in proof-writing. Thank you!" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import opendp.prelude as dp\n", "dp.enable_features(\"contrib\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Known/Unknown Dataset Size\n", "Constructing a sum transformation is easy!\n", "First, describe the metric space you are working in. \n", "This can also be filled in from the previous transformation." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# the space of all integer vectors,\n", "# where distances between vectors are measured by the symmetric distance\n", "input_space = dp.vector_domain(dp.atom_domain(bounds=(0, 10))), dp.symmetric_distance()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Then construct the sum transformation:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\n", "sum_trans = input_space >> dp.t.then_sum()\n", "\n", "# compute the sum\n", "assert sum_trans([1, 2, 4]) == 7 # 1 + 2 + 4\n", "\n", "# compute the sensitivity\n", "assert sum_trans.map(d_in=1) == 10 # d_in * max(|L|, U)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "In the integer case, since the sensitivity is scaled by \$max(|L|, U)\$, the sensitivity won't increase if you were to widen \$L\$ to \$min(L, -U)\$, or widen \$U\$ to \$max(-L, U)\$.\n", "This doesn't hold for floating-point datasets with unknown size, for reasons we'll cover in the next section.\n", "\n", "If the dataset size is public information, then restrict the input space:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# the space of all length-3 integer vectors,\n", "# where distances between vectors are measured by the symmetric distance\n", "input_space = dp.vector_domain(dp.atom_domain(bounds=(-10, 10)), size=3), dp.symmetric_distance()\n", "sum_trans = input_space >> dp.t.then_sum()\n", "\n", "# compute the sum\n", "assert sum_trans([1, 2, 4]) == 7 # 1 + 2 + 4\n", "\n", "# compute the sensitivity\n", "assert sum_trans.map(d_in=2) == 20 # (d_in // 2) * (U - L)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Since the sensitivity is scaled by \$U - L\$, the sensitivity won't increase if you shift both bounds by the same fixed constant. Therefore, the sensitivity remains small in situations where \$L\$ and \$U\$ share the same sign and are large in magnitude.\n", "\n", "_All_ sum transformations expect a `d_in` in terms of the `SymmetricDistance`.\n", "However, when the dataset size is known, we are operating in the bounded-DP regime where adjacent datasets have the same size.\n", "This means it takes both an addition and a removal to change any single record, to reach any adjacent dataset.\n", "This results in a stair-step relationship between \$d_{in}\$ and \$d_{out}\$:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "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izQzyzxJeW8F4SYUM7OMcgI3M8soJ3Azs4xq8GdirlixgoULF/L55583dChmRdGiRQs6depE06ZNGzoU+4pp8AS+cOFCNttsM0pLS1nz7p9m2RcRvP/++yxcuJBtt922ocOxr5iCmlAknZ3ed3iOpNsltZC0bXrP31eVPMuw2foE8Pnnn9O2bVsnb/tKkkTbtm39C9OKotYELqkjyVNfyiOiB8lz9Y4kufn71RGxPfAhcNL6BuHkbV9l/n5bsRR6ErMJ0FJSE5Inkywieb5exd3GxpLcC9iq+M53vgPAggULuO22L2/HPH36dEaMGFHdYgCMHj2am2++GYAxY8bwzjvv1Dh/Poceeijz58+vcZ7S0lLee++9dV53rilTpnDAAQfUOM+yZcv405/+tEHljBkzhtNPPx1Yc/9UF9MTTzyxQeWti/Hjx/OrX/2q3sozq7UNPCLelnQV8CbJDdonkjwRfFlErExnW0g1z0GUdDJwMkDnzrU/wat05ISCAi/UglFD6nR966oigVQk8KOPPhqA8vJyysvLa1z2lFNOqRweM2YMPXr0oEOHwh/T+MILL7Bq1Sq222679Yi87lUk8B//OO8zfddZ7v7JZ8qUKbRq1aryIFpsQ4YM4Ze//CUjR45kk002qX0BW0td//8XomqO2BhiKFQhTSibkzwFZluSh8VuCuxXaAERcV1ElEdEeUnJWj1BG9x///tfhgwZQu/evenRowd33pk8LWzGjBnsueee7LLLLgwePJhFixYBMGDAAM477zz69etHly5dmDp1KpAky379+lFWVkavXr2YNy952EirVsmzbEeOHMnUqVMpKyvj6quvrqyxrl69mtLSUpYtW1YZ0w477MDixYu56KKLuOqqqxg3bhzTp09n+PDhlJWVMWHCBIYNG1Y5/6RJkzj44IOp6tZbb2Xo0KGV70899VTKy8vp3r07F1544RrzXnHFFfTs2ZN+/frx6quvAnD33XfTo0cPevfuzR577AEk5yxOOOEEevbsSZ8+fXjkkUfWKrci7go9evRgwYIFjBw5ktdee42ysjLOPTd52taVV15J37596dWr11oxVbjpppvo0qUL/fr14/HHH89bzjXXXMNOO+1Er169OPLII1mwYAGjR4/m6quvpqysjKlTp3L//ffTv39/+vTpw6BBg1i8eHHlek488UQGDBjAdtttxzXXXFNZxs0330yvXr3o3bs3xx6bPLpx6dKlfP/736dv37707du3MiZJDBgwgPHjx+fdDrO6VshVKINInqW3FEDSP4DdgDaSmqS18E58+SDbTHnwwQfp0KEDEyYkR93ly5ezYsUKzjjjDO69915KSkq48847ueCCC7jxxhsBWLlyJU8//TQPPPAAF198MQ899BCjR4/mzDPPZPjw4XzxxResWrVqjXJGjRrFVVddVfnPPWXKFAAaNWrE0KFDueeeezjhhBOYNm0a22yzDe3bt69c9tBDD+UPf/gDV111FeXl5UQEP/nJT1i6dCklJSXcdNNNnHjiiWtt2+OPP85RRx1V+f6yyy5jiy22YNWqVQwcOJBZs2bRq1cvAFq3bs3s2bO5+eabOeussxg/fjyXXHIJ//73v+nYsWPlAeaPf/wjkpg9ezYvvfQS++67L6+88kpB+3rUqFHMmTOH5557DoCJEycyb948nn76aSKCgw46iEcffbTyYAGwaNEiLrzwQmbMmEHr1q3Za6+96NOnT951v/766zRv3pxly5bRpk0bTjnlFFq1asVPf/pTAD788EOeeuopJHH99ddzxRVX8Nvf/haAl156iUceeYSPP/6Yrl27cuqpp/LKK69w6aWX8sQTT9CuXTs++OADAM4880zOPvtsdt99d958800GDx7M3LlzgeSX1dSpUzn88MML2idmG6KQNvA3gW9L2iR9yvdAkpviPwIcms5zHHBvcUIsrp49ezJp0iTOO+88pk6dSuvWrXn55ZeZM2cO++yzD2VlZVx66aUsXLiwcplDDjkEgF122YUFCxYAsOuuu/LrX/+ayy+/nDfeeIOWLVsWHMMRRxxRWfO/4447OOKII2qcXxLHHnsst9xyC8uWLePJJ59k//3Xfq7tokWLyP3Vc9ddd7HzzjvTp08fXnjhBV588ctnG1Qk+qOOOoonn3wSgN12243jjz+ev/71r5UHpMcee4xjjjkGgG7durHNNtsUnMCrmjhxIhMnTqRPnz7svPPOvPTSS5W/XCpMmzaNAQMGUFJSQrNmzardN7169WL48OHccsstNGmSv16ycOFCBg8eTM+ePbnyyit54YUXKqcNGTKE5s2b065dO7bccksWL17Mww8/zGGHHUa7du0A2GKLLQB46KGHOP300ykrK+Oggw7io48+4pNPPgFgyy23XK9zFWbro5A28GmSxgEzSZ70/SxwHclz7e6QdGk67oZiBlosXbp0YebMmTzwwAP84he/YODAgRx88MF07969MpFV1bx5cwAaN27MypXJaYCjjz6a/v37M2HCBL73ve/xl7/8hb333rugGHbddVdeffVVli5dyj//+U9+8Ytf1LrMCSecwIEHHkiLFi047LDD8iatli1bVl6+9vrrr3PVVVfxzDPPsPnmm3P88cevcWlb7pUSFcOjR49m2rRpTJgwgV122YUZM2YUtD1NmjRh9eovH3Be3SV0EcHPf/5zfvSjHxW03ppMmDCBRx99lPvvv5/LLruM2bNnrzXPGWecwTnnnMNBBx3ElClTuOiiiyqnVXymsObnms/q1at56qmnaNGixVrTPv/883U6eJttiIKuQomICyOiW0T0iIhjI+J/ETE/IvpFxPYRcVhE/K/YwRbDO++8wyabbMIxxxzDueeey8yZM+natStLly6tTOArVqxYo7aWz/z589luu+0YMWIEQ4cOZdasWWtM32yzzfj444/zLiuJgw8+mHPOOYcdd9yRtm3brjVP1eU7dOhAhw4duPTSSznhhBPyrnfHHXesbM/+6KOP2HTTTWndujWLFy/mX//61xrzVvwCuPPOO9l1110BeO211+jfvz+XXHIJJSUlvPXWW3z3u9/l1ltvBeCVV17hzTffpGvXrmusq7S0lJkzZwIwc+ZMXn/99bzbMHjwYG688cbK2uvbb7/NkiVL1lhX//79+c9//sP777/PihUruPvuu9faztWrV/PWW2+x1157cfnll7N8+XI++eSTtcpbvnw5HTsm59rHjh2bd5/l2nvvvbn77rt5//33ASqbUPbdd1+uvfbayvkqmoQq9kmPHj1qXbdZXWjwnpgNbfbs2Zx77rk0atSIpk2b8uc//5lmzZoxbtw4RowYwfLly1m5ciVnnXUW3bt3r3Y9d911F3/7299o2rQp3/zmNzn//PPXmN6rVy8aN25M7969Of7449dqxz3iiCPo27cvY8aMybv+448/nlNOOYWWLVvy5JNP0rJlS4YPH87SpUvZcccd8y4zZMgQpkyZwqBBg+jduzd9+vShW7dubL311uy2225rzPvhhx/Sq1cvmjdvzu233w7Aueeey7x584gIBg4cSO/evenWrRunnnoqPXv2pEmTJowZM2aN2ivA97//fW6+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", "text/plain": [ "