Skip to content

Instantly share code, notes, and snippets.

@yrevar
Created August 23, 2021 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yrevar/fd325d8c002e28886c66279bbedf0013 to your computer and use it in GitHub Desktop.
Save yrevar/fd325d8c002e28886c66279bbedf0013 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from bloom_filter import BloomFilter\n",
"import os, os.path as osp, numpy as np\n",
"\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"%load_ext autoreload\n",
"%autoreload 2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Set membership of character"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/yrevar/anaconda3/envs/ltl/lib/python3.7/site-packages/bloom_filter/bloom_filter.py:454: RuntimeWarning: overflow encountered in long_scalars\n",
" result += ((result + integer + prime1) * prime2) % prime3\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Bloom: k 1, fp 9800.00, fpr 1.00\n",
"Bloom: k 5, fp 9800.00, fpr 1.00\n",
"Bloom: k 10, fp 9800.00, fpr 1.00\n",
"Bloom: k 20, fp 9740.53, fpr 0.99\n",
"Bloom: k 40, fp 9085.80, fpr 0.93\n",
"Bloom: k 60, fp 7310.07, fpr 0.75\n",
"Bloom: k 80, fp 5595.43, fpr 0.57\n",
"Bloom: k 100, fp 4345.13, fpr 0.44\n",
"Bloom: k 120, fp 3268.57, fpr 0.33\n",
"Bloom: k 140, fp 2251.87, fpr 0.23\n",
"Bloom: k 160, fp 1718.30, fpr 0.18\n",
"Bloom: k 180, fp 1320.90, fpr 0.13\n",
"Bloom: k 200, fp 1031.97, fpr 0.11\n",
"Bloom: k 220, fp 774.40, fpr 0.08\n",
"Bloom: k 240, fp 623.47, fpr 0.06\n",
"Bloom: k 260, fp 484.50, fpr 0.05\n",
"Bloom: k 280, fp 428.53, fpr 0.04\n",
"Bloom: k 300, fp 361.47, fpr 0.04\n"
]
}
],
"source": [
"fps = []\n",
"fprs = []\n",
"bloom_elems = [1,5,10] + list(range(20,320,20))\n",
"total_entries = 200\n",
"n_repeat = 30\n",
"error_rate = 0.1\n",
"for k in bloom_elems:\n",
" fp_sum = 0\n",
" fpr_sum = 0\n",
" for rep in range(n_repeat):\n",
" x_space = list(np.random.choice(np.arange(10000), 10000, replace=False))\n",
" x1 = x_space[:total_entries]\n",
" x2 = x_space[total_entries:]\n",
" bloom = BloomFilter(max_elements=k, error_rate=error_rate)\n",
" for x in x1:\n",
" bloom.add(x)\n",
" fp = 0\n",
" for x in x2:\n",
" if x in bloom:\n",
" fp += 1\n",
" fp_sum += fp\n",
" fpr = 1. * fp / len(x2)\n",
" fpr_sum += fpr\n",
" fp_mean = fp_sum / n_repeat\n",
" fpr_mean = fpr_sum / n_repeat\n",
" print(\"Bloom: k {}, fp {:.2f}, fpr {:.2f}\".format(k, fp_mean, fpr_mean))\n",
" fps.append(fp_mean)\n",
" fprs.append(fpr_mean)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.plot(bloom_elems, fprs)\n",
"plt.xlabel(\"Bloom filter elements\")\n",
"plt.ylabel(\"False Positive Rate (Mean over {} runs)\".format(n_repeat))\n",
"plt.vlines(bloom_elems[np.argmin(np.abs(np.asarray(fprs) - error_rate))], plt.ylim()[0], plt.ylim()[1], linestyles='dashed')\n",
"_ = plt.text(bloom_elems[np.argmin(np.abs(np.asarray(fprs) - error_rate))] + 5, plt.ylim()[1] - 0.5, \"FPR = {}\".format(error_rate))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Set membership of string (array)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Bloom: k 1, fp 800.00, fpr 1.00\n",
"Bloom: k 5, fp 800.00, fpr 1.00\n",
"Bloom: k 10, fp 800.00, fpr 1.00\n",
"Bloom: k 20, fp 800.00, fpr 1.00\n",
"Bloom: k 40, fp 745.30, fpr 0.93\n",
"Bloom: k 60, fp 623.40, fpr 0.78\n",
"Bloom: k 80, fp 471.57, fpr 0.59\n",
"Bloom: k 100, fp 358.33, fpr 0.45\n",
"Bloom: k 120, fp 256.07, fpr 0.32\n",
"Bloom: k 140, fp 188.37, fpr 0.24\n",
"Bloom: k 160, fp 142.23, fpr 0.18\n",
"Bloom: k 180, fp 105.23, fpr 0.13\n",
"Bloom: k 200, fp 80.43, fpr 0.10\n",
"Bloom: k 220, fp 62.63, fpr 0.08\n",
"Bloom: k 240, fp 49.77, fpr 0.06\n",
"Bloom: k 260, fp 42.53, fpr 0.05\n",
"Bloom: k 280, fp 31.70, fpr 0.04\n",
"Bloom: k 300, fp 26.50, fpr 0.03\n"
]
}
],
"source": [
"fps = []\n",
"fprs = []\n",
"bloom_elems = [1,5,10] + list(range(20,320,20))\n",
"total_entries = 200\n",
"n_repeat = 30\n",
"error_rate = 0.1\n",
"for k in bloom_elems:\n",
" fp_sum = 0\n",
" fpr_sum = 0\n",
" for rep in range(n_repeat):\n",
" x_space = list(np.random.choice(np.arange(1000 * 10), (1000, 10), replace=False))\n",
" x1 = x_space[:total_entries]\n",
" x2 = x_space[total_entries:]\n",
" bloom = BloomFilter(max_elements=k, error_rate=error_rate)\n",
" for x in x1:\n",
" bloom.add(x.flatten().tostring())\n",
" fp = 0\n",
" for x in x2:\n",
" if x.flatten().tostring() in bloom:\n",
" fp += 1\n",
" fp_sum += fp\n",
" fpr = 1. * fp / len(x2)\n",
" fpr_sum += fpr\n",
" fp_mean = fp_sum / n_repeat\n",
" fpr_mean = fpr_sum / n_repeat\n",
" print(\"Bloom: k {}, fp {:.2f}, fpr {:.2f}\".format(k, fp_mean, fpr_mean))\n",
" fps.append(fp_mean)\n",
" fprs.append(fpr_mean)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEGCAYAAABo25JHAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAgAElEQVR4nO3deXhU9dn/8fedjSRAEiBBliSEfZM9gqBiEKuCC6WggtWKtQ8upRW3n9qqdetTtdS6L/RRadUqiBuiVIUCooIaICyC7FsQJYRV9uX+/XFOcAghcxIyczKZ+3VdczFzlpnPcWLunHO+i6gqxhhjoleM3wGMMcb4ywqBMcZEOSsExhgT5awQGGNMlLNCYIwxUS7O7wAVlZ6erjk5OX7HMMaYiDJ37twtqppR1rqIKwQ5OTnk5+f7HcMYYyKKiKw70Tq7NGSMMVHOCoExxkQ5KwTGGBPlrBAYY0yUs0JgjDFRzgqBMcZEOSsExhgT5awQGGNMlLNCYIwxUc4KgTHmGFOnTmXq1Kl+xzBhFHSICRFJBC4CzgKaAHuBxcAHqvpNaOMZY8LtoYceAuDcc8/1OYkJl3ILgYjcj1MEZgBfApuBRKAN8LBbJG5V1YUhzmmMMSZEgp0RfKWqfzrBusdEpCGQXcWZjDHGhFG5hUBVPyi9TERigDqqulNVN+OcJRhjjIlQnm4Wi8i/RSRFRGrj3B9YIiK3B9nnJRHZLCKLT7BeRORJEVkpIgtFpHvF4xtjjDlZXlsNdVDVncDPgSlAc+CqIPuMAy4oZ/0AoLX7GAk85zGLMSaEXnjhBV544QW/Y5gw8joxTbyIxOMUgqdV9aCIaHk7qOqnIpJTziaDgH+pqgJzRCRNRBqr6iaPmSrkqzVbmbm86q5ixcbE8POuTWiRUafK3tOY6qBt27Z+RzBh5rUQvACsBRYAn4pIM2DnSX52U2BDwOtCd9lxhUBERuKcNZCdXbl70ws2bOeFmasrtW9ZDqvy/MxVjOrXiuvObkGtuNgqe29j/PT+++8DcPHFF/ucxISLOH+QV2JHkThVPRRkmxxgsqqeWsa6ycDDqvqZ+3oacIeqljsPZW5urlaHqSo379zHA5OXMHnhJlpk1OZ/B3fi9BYN/I5lzEnLy8sDYMaMGb7mMFVLROaqam5Z6zydEYhILWAIkFNqnwdOItdGICvgdaa7LCI0TEnk6Su6M7THZu55bzHDxs7h0h6Z3DWwPfVrJ/gdzxhjPPN6s/g9nGv6h4DdAY+TMQn4ldt66HRgR6juD4RSXtuGfDz6bG7Ia8k78zfS/28zmDi3kMqeaRljTLh5vUeQqarltQA6joi8DuQB6SJSCPwJiAdQ1eeBD4GBwEpgD3BNRd6/OklKiOWOC9oxqGsT/vD2Im57cwET527gz4M70dJuJhtjqjmvheALEemkqou8vrGqDg+yXoHfen2/SNCuUQoTr+/D61+v5+Ep3zLg8Vnc2K8lN+S1tJvJxphqy9PNYhFZArQC1gD7AcH5Xd45tPGOV11uFgezedc+Hpq8lEkLvqNFem3+PLgTvVvazWRT/W3Y4DTmy8rKCrKliSTl3Sz2WgialbVcVdedZLYKi5RCUGLm8iLufncRG7buZUj3TP54od1MNsaEX3mFwOvNYj3BwwRxdpsMPh59NjfmteS9Audm8oT8DXYz2VRb48ePZ/z48X7HMGHk9YxgEc4vfsEZhro5sExVO4Y23vEi7Ywg0PIfdvGHtxeRv24bvZrX58+DO9Gqod1MNtWL9SOomU76jEBVO6lqZ/ff1kBPYHZVhowGbU6py4TrevOXX3Ri6aadDHjiUx77ZDn7Dh72O5oxJopVaqpKVZ0H9KriLFEhJkYY3jObabfmcWGnxjw5bQUDnpjFFyu3+B3NGBOlvPYsviXgZQzQHfguJImiREbdWjw+rBtDemRy97uLueL/vuS6vi24a2B7v6MZY6KM1zOCugGPWsAHOD2NzUk6q3UGH43uy7DTsnjh09VMWRRxnauNMRHOy+T1sUBdVb0tDHmiUmJ8LA8MOpUlm3Zy59uL6JKVRpO0JL9jmSg1ceJEvyOYMAt6RqCqh4EzwpAlqiXExfDEsG4cPHyEm8cXcPiINS81/khPTyc9Pd3vGCaMvF4aKhCRSSJylYj8ouQR0mRRqHl6be6/pCNfrtnK8zNX+R3HRKlx48Yxbtw4v2OYMPI61lAiUAycE7BMgberPFGUG9ojk5nLi3jsk+X0admAbtn1/I5kokxJERgxYoSvOUz4eCoEqhqxI4NGGhHhz4M7MX/9dm56o4APfn8mdRPj/Y5ljKnBKtWPwIRWalI8TwzrSuG2PfzpvW/8jmOMqeGsEFRTuTn1+X3/1rw9fyPvzo+YiduMMRHICkE1NqpfK3Kb1ePudxezvniP33GMMTVU0EHnROR84OdAU3fRRuA9Vf1PiLOVKZIHnauMwm17GPDELFo1rMOb1/UmLtZqtwmtPXucPzqSk5N9TmKqUqUHnRORx4GbgJnAo+5jJvB7EXmiqoOa42XWSz568/jJaSv8jmOiQHJyshWBKBOs1dBAVW1TeqGIjAeW4xQJE2KXdGnCp8uLeHr6Ss5olU6vFjbTmQmdZ599FoAbb7zR5yQmXIJdZ9gnIqeVsfw0YF8I8pgTuO+SjmTXT+bm8QXs2HPQ7zimBpswYQITJkzwO4YJo2CFYATwtIgsEZGP3cdS4El3nQmTOrXieGJYNzbv2s9d7yy0Gc6MMVWm3EtDJfMOiEgjAm4Wq+r3IU9mjtMlK41bz2vLI//5ljfzC7nsNJtc3Bhz8oI2QXGLAKo6F1gP9BGRDqEOZsp2Xd8W9GnZgD9N+oZVRT/6HccYUwMEazV0Hc6UlHNE5AZgMnAh8I6IXBuGfKaUmBjhscu6Uis+hpvemM+BQ0f8jmSMiXDl9iNwJ63vBSQB64BWqvq9iNQDpqtq1/DE/Em09SM4kY+/+Z6Rr8y1Wc2MMZ6czOT1B1V1j6oWA6tK7g2o6jac0UeNT87r2IgrT8/mhU9X89kKm+/YGFN5wQqBikjJ0JcXliwUkUQP+5oQ++PADrRuWIdbJhRQ/ON+v+OYGmLMmDGMGTPG7xgmjIL9Mh+M+5e/qhYGLG8A3BqqUMabpIRYnhzeje17D3LHW9ak1FSNyZMnM3nyZL9jmDAqtxCo6npVPVTG8o2qOjXYm4vIBSKyTERWisidZazPFpHpIjJfRBaKyMCKxTftG6dw14B2TF26mVfnrPM7jjEmAoXs8o476f0zwACgAzC8jGandwMTVLUbMAx4NlR5arIRfXLIa5vBQx8sZdn3u/yOY4yJMKG8zt8TWKmqq1X1APAGMKjUNgqkuM9Tge9CmKfGEhHGXNqFuonx/P71+ew7eNjvSMaYCOKlQ1msiLxWifduCmwIeF3IT72TS9wHXCkihcCHwO9OkGGkiOSLSH5RUVElotR86XVqMebSziz7YRcPT/nW7zgmgiUlJZGUlOR3DBNGQQuBqh4GmolIQgg+fzgwTlUzgYHAKyJyXCZVHauquaqam5GREYIYNUNe24Zce2Zzxn2xlv9++4PfcUyEmjJlClOmTPE7hgkjr5eGVgOfi8g9InJLySPIPhuBwMFwMt1lga4FJgCo6mwgEUj3mMmU4f9d0Jb2jVO47c2FbN5pA8QaY4LzWghW4QwvEQPUDXiU52ugtYg0d88mhgGTSm2zHugPICLtcQqBXfs5CbXiYnlqeFf2HDjErW8usCalpsIefPBBHnzwQb9jmDAKNjENAKp6P4CIJKuqp8lzVfWQiIwCPgJigZdU9RsReQDIV9VJOH0R/iEiN+PcOB6h9pvrpLVqWJe7L+zA3e8u5r2C7/h5t9K3Zow5sWnTpgFwzz33+JzEhIunQiAivYEXgTpAtoh0Aa5T1XKnMFLVD3FuAgcuuzfg+RLgjIqGNsFd0TObCfkbeHjKt5zX8RSSEzx91caYKOT10tDjwPlAMYCqLgD6hiqUOXkxMcKfLu7I9zv38fyMVX7HMcZUY577EajqhlKLrLF6NdejWT0GdW3CC5+uZsNWT1f0jDFRyGsh2CAifXAHoROR24ClIcxlqsidA9oRI2J9C4xnDRo0oEGDBn7HMGHk9cLx9cATOB3CNgIfA78NVShTdRqnJnFDXkse+2Q5V60u5vQW9j+4Kd9bb73ldwQTZl7PCERVf6mqp6hqQ1W90p2jwESAkX1b0DQtiQfeX8LhI9YoyxhzLK+F4HMR+VhErhWRtJAmMlUuMT6Wuwa2Y8mmnUzIL32rx5hj3XXXXdx1111+xzBh5KkQqGobnJFCOwLzRGSyiFwZ0mSmSl3YqTE9c+oz5qNl7Nh70O84phqbPXs2s2fP9juGCaOKtBr6SlVvwRlVdCvwz5ClMlVORLj34g5s3XOAp6at8DuOMaYa8VQIRCRFRK4WkSnAF8AmnIJgIsipTVMZdloW475Yy6qiH/2OY4ypJryeESwAugIPqGobVb1DVeeGMJcJkVvPa0tSfCx//sBa/xpjHF4LQQtVvRlYJCJ1QhnIhFZ6nVr8vn9r/vvtZqYv2+x3HFMNZWZmkpmZ6XcME0biZYw3ETkVeAWoDwjOCKFXq+ri0MY7Xm5urubn54f7Y2uUA4eOcP7jnyICH43uS3xsKCeqM8ZUByIyV1Vzy1rn9TfAWOAWVW2mqtk4o4aOraqAJrwS4mK456L2rC7azb9m24T3xkQ7r4WgtqpOL3mhqjOA2iFJZMKiX9uG9G2TweNTl1P8436/45hqZPTo0YwePdrvGCaMPM9Q5s5OluM+7saZtcxEKBHh3ovas+fAYR77ZLnfcUw1UlBQQEFBgd8xTBh5LQS/BjKAt4G3cKaT/HWoQpnwaNWwLr/q3YzXv1rPku92+h3HGOMTrz2Lt6nq71W1u6r2UNXRqrot1OFM6I3u34bUpHgemPyNTWtpTJSy5iJRLjU5nlvOa8uc1Vv56Jvv/Y5jjPGBFQLD8NOyaNeoLg99sJR9B22+oWjXpk0b2rRp43cME0ZWCAxxsTHce1EHCrft5cXP1vgdx/hs7NixjB1rrcOjidfJ6zOA/wFyAvdRVbthXEP0aZXOBR0b8cz0lQzpnkmj1ES/IxljwsTrGcF7QCowFfgg4GFqkD8MbM+hw8qj/7FpLaPZyJEjGTlypN8xTBh5naoyWVXvCGkS47vsBsn85qzmPDtjFVf1bka37Hp+RzI+WL7c+pVEG69nBJNFZGBIk5hq4cZ+rWhYtxb3v7+EIzatpTFRwWshuAmnGOwVkZ0isktErAdSDVSnVhx3XNCOgg3bebdgo99xTDUTGxtL165djz7Wrl3LjBkzSE1NpWvXrrRv3577778f4Jjl7dq147bbbquSDGvWrKFXr160atWKyy+/nAMHDhy3TXFxMf369aNOnTqMGjWqSj63JvPaoayuqsaoapKqprivU0IdzvhjcLemdMlK4+Ep37J7/yG/45hqJCkp6egQFAUFBeTk5ABw1llnUVBQQH5+Pq+++irz5s07Zvn8+fOZPHkyn3/++UlnuOOOO7j55ptZuXIl9erV48UXXzxum8TERB588EHGjBlz0p8XDTw3HxWReiLSU0T6ljxCGcz4JyZGuPeiDmzetZ/nZqzyO44Js5K/9iujdu3a9OjRg5UrVx6zPCkpia5du7Jx48mdZaoq//3vfxk6dCgAV199Ne+++26ZOc4880wSE631mxdem4/+BufyUCZQAJwOzAbOCV0046cezeoxuFtTxs5azeWnZZFVP9nvSCZMHn/88ROu27t379Ei0bx5c955551j1hcXFzNnzhzuueceioqKji7ftm0bK1asoG/f4/9+XLZsGZdffnmZnzdjxgzS0tKOef+0tDTi4pxfXZmZmSddXIz3VkM3AacBc1S1n4i0A/432E4icgHwBBAL/J+qPlzGNpcB9wEKLFDVKzxmMiF2xwXt+M/i7/nfD5fy3JU9/I5jqoGSS0OlzZo1i27duhETE8Odd95Jx44dmTFjBrNmzaJLly6sWLGC0aNH06hRo+P2bdu2rY126jOvhWCfqu4TEUSklqp+KyJty9tBRGKBZ4CfAYXA1yIySVWXBGzTGrgLOENVt4lIw0oehwmBRqmJ3JjXkr99spzZq4rp3bKB35FMGFx55ZUAvPrqq573Oeuss5g8efIJl69Zs4bTTz+dyy677LjLThU5I2jQoAHbt2/n0KFDxMXFUVhYSNOmTT3nNGXzeo+gUETSgHeBT0TkPSDY1FY9gZWqulpVDwBvAINKbfM/wDMlI5mqqk2iW838T98WNE1L4v73v+GwNSeNCoWFhRQWFlbpezZv3pw777yTRx555Lh1JWcEZT0CiwA482j069ePiRMnAvDPf/6TQYNK/1oxFeW11dBgVd2uqvcB9wAvAj8PsltTYEPA60J3WaA2QBsR+VxE5riXkkw1khgfyx8vbM+33+/ija/X+x3HRLDrr7+eTz/9lLVr157U+zzyyCM89thjtGrViuLiYq699loAJk2axL333nt0u5ycHG655RbGjRtHZmYmS5YsOdFbRj1Pk9cDiMiZQGtVfdkde6iOqp5whDIRGQpcoKq/cV9fBfRS1VEB20wGDgKX4dyI/hTopKrbS73XSGAkQHZ2do9162ye3XBSVYaNncPyH3Yx47Z+pCbH+x3JhFBeXh7gXJYxNcdJT14vIn8C7sC5ng8QDwS7gLgRyAp4nekuC1QITFLVg25RWQ60Lv1GqjpWVXNVNTcjI8NLZFOFRIR7L+7Ajr0Hue99m8DGmJrG6z2CwcAlwG4AVf0OqBtkn6+B1iLSXEQSgGHApFLbvAvkAYhIOs6lIpsLuRrq2CSVm/q34Z35G3ntS7tEVJP17t2b3r17+x3DhJHXVkMHVFVFRAFEpHawHVT1kIiMAj7CaT76kqp+IyIPAPmqOsldd56ILAEOA7eranGljsSE3O/OacX8Ddt44P0lnNo0la5ZacF3MhHnL3/5i98RTJh5ukcgIrfhXLL5GfAXnInr/62qT4U23vFyc3M1Pz8/3B9rXNt2H+Cipz5DVZn8+7OoXzvB70jGGA9O+h6Bqo4BJgJvAW2Be/0oAsZ/9Won8NyV3dny4wFuemO+NSmtgYYMGcKQIUP8jmHCyPNYQ6r6iarerqq3qeonoQxlqrfOmWncP6gjs1Zs4YlpK/yOY6pYcXExxcV2hTaalHuPQER24Qz9cNwqQG0E0ug17LQs5q7bxpPTVtAtK41+7axTuDGRKtgZwTRgCfAQcKo7BLUNQ20QER4cdCrtG6cwenwBG7bu8TuSMaaSyi0Eqvpz4HygCPiHiMwUkRtFpH5Y0plqLSkhlud+2Z0jqtz42jz2HTzsdyRjTCUEvUegqjtU9WVgAPAC8AAwIsS5TITISa/N3y7twqKNO7j/fevCXxP079+f/v37+x3DhFHQfgQi0gcYDpwFfAYMVtVZoQ5mIsd5HRtxQ15Lnpuxiu7ZaVyamxV8J1Nt3XPPPX5HMGEW7GbxWmA7zsihI4FD7vLuAKo6L8T5TIS49WdtKFi/nbvfXUyHJil0bJLqdyRjjEfldigTkRn81GpIcVoLlVBVDfsMZdahrPra8uN+LnxyFrXiYnn/d2eSmmSD00WiAQMGADBlyhSfk5iqVF6HsnLPCFQ1LySJTI2UXqcWz/6yO5e/MIdbJxQw9qpcYmIk+I6mWtm7d6/fEUyYlXuz2B16urz1KSJyatVGMpGsR7P6/PHC9kxdupnnP7WJ742JBMFuFg8RkUeB/wBzcZqRJgKtgH5AM+DWkCY0EWdEnxzmrtvGmI+W0TUzjT6t0v2OZIwpR7B+BDcDFwGbgEuBB4FbcAage0FV+6rq1yFPaSKKiPDIkM60yKjD716fz/c79vkdyRhTjqDNR1V1K/AP92GMJ7VrxfH8ld255OnPufG1ubwxsjcJcZ6HtjI+uuiii/yOYMLM81SV1YW1Goos7y/4jt+9Pp8RfXK475KOfscxJmqd9DDUxlTWxV2acM0ZOYz7Yi2TFnzndxxjTBmsEJiQ+8PA9uQ2q8edby1kxQ+7/I5jgsjLyzs6gb2JDl4nr08WkXtE5B/u69YiYhcSjSfxsTE8fUV3khNiuf7Vufy4/5DfkYwxAbyeEbwM7AdKZrTeiDM0tTGeNEpN5Mnh3VizZTd3vLWQSLs3ZUxN5rUQtFTVR4GDAKq6h2OHmzAmqD4t07n9/HZ8sHATL3++1u84xhiX10JwQESScMcdEpGWOGcIxlTI9We34GcdTuF/P1xK/tqtfscxxuC9ENyH07s4S0Rew5m57I5QhTI1l4gw5tIuNK2XxG//PY+iXfb3RHVz2WWXcdlll/kdw4SR534EItIAOB3nktAcVd0SymAnYv0IaoYl3+3kF899TufMNF69tpd1NjMmxE66H4GITFPVYlX9QFUnq+oWEZlWtTFNNOnQJIVHhnTmqzVbuevtRXbzuBrZs2cPe/bYHNTRJNjENIlAMpAuIvX46QZxCtA0xNlMDTeoa1PWbNnN41NXkNMgmd/1b+13JAMMHDgQgBkzZvgbxIRNsLGGrgNGA01wRh8tKQQ7gadDmMtEiZv6t2Zd8R7+9slyshskM6ir/X1hTLgFm5jmCeAJEfmdqj4VpkwmiogIDw/pxMZte7l94kKapiWRm1Pf71jGRBVP9whU9SkROVVELhORX5U8Qh3ORIdacbG8cFUPmqYlMfKVuawr3u13JGOiitebxX8CnnIf/YBHgUtCmMtEmXq1E3hpxGkcUeWacV+zY89BvyMZEzW8ttkbCvQHvlfVa4AuQGqwnUTkAhFZJiIrReTOcrYbIiIqImU2bTLRoXl6bV64sgcbtu7hulfzOXDoiN+RotKIESMYMWKE3zFMGHktBHtV9QhwSERSgM1AVnk7iEgs8AwwAOgADBeRDmVsVxe4CfiyIsFNzdSrRQMeHdqZOautWalfrBBEH6+FIF9E0nBmKZsLzANmB9mnJ7BSVVer6gHgDWBQGds9CDwC2HyGBoDB3TK5qX9r3ppXyDPTV/odJ+ps2bKFLVt86S9qfBJ0qkoAVb3Rffq8iPwHSFHVhUF2awpsCHhdCPQK3EBEugNZqvqBiNx+ojcSkZHASIDs7GwvkU2EG31ua9Zv3cOYj5eT3aA2l3Rp4nekqDF06FDA+hFEkwr361fVtcC+krkJKktEYoDHgFs9fOZYVc1V1dyMjIyT+VgTIUqalfbMqc9tby5g7joboM6YUCm3EIhIZxH5WEQWi8hDItJYRN4C/gssCfLeGzn2PkKmu6xEXeBUYIaIrMUZx2iS3TA2JUqalTZJTeR//mXNSo0JlWBnBP8A/g0MAYqAAmAV0EpV/x5k36+B1iLSXEQSgGHApJKVqrpDVdNVNUdVc4A5wCWqaiPKmaPq1U7g5Wt6WrNSY0IoWCGoparjVHWZ28t4t6r+P1UNemNXVQ8Bo4CPgKXABFX9RkQeEBHrg2A8s2alxoRWsJvFiSLSjZ/GGNof+FpV55W3s6p+CHxYatm9J9g2z0tgE51KmpXePH4Bf3hnEX8d2hkRmyQvFG644Qa/I5gwC1YINuHc0C3xfcBrBc4JRShjyjK4WyZrt+zhiWnOaKWjzrHRSkPh8ssv9zuCCbNgg871C1cQY7wYfW5r1hXvZszHy2nWoDYXW7PSKrdhg9PqOyur3D6jpgbx1I/AmOpCRHhkaGc2bt/LrW8uoElaIj2a2WilVemqq64CrB9BNLH5AU3EcZqV5lqzUmOqiBUCE5Hq22ilxlQZr8NQi4hcKSL3uq+zRaRnaKMZU74WGXWONiu9/tW51qzUmEryekbwLNAbGO6+3oUzsqgxvippVjp7dTF/eMdGKzWmMrzeLO6lqt1FZD6Aqm5zewsb47vB3TJZs2UPT05bQfP02vy2Xyu/I0W0W28NOvyXqWG8FoKD7vwCCiAiGYCdh5tq42a3WelfP1rG7v2HuOVnbYiLtVtglXHxxRf7HcGEmddC8CTwDtBQRP6MM2PZ3SFLZUwFiQiPDu1MckIsz85YRcGG7Tw5vBvpdWr5HS3iLFu2DIC2bdv6nMSEi3i9pioi7XCmqxRgmqouDWWwE8nNzdX8fBuXzpzYhPwN3PPuYtKS43nmiu7k5lg/g4rIy8sDrB9BTSMic1W1zNGdvbYaehKor6rPqOrTfhUBY7y4LDeLt2/sQ2J8LMPGzuGlz9bYTWRjyuH1Iupc4G4RWSUiY2zOAFPddWySyqRRZ5LXtiEPTF7CqNfn8+P+Q37HMqZa8lQIVPWfqjoQOA1YBjwiIitCmsyYk5SaFM/Yq3pwxwXtmLJoE5c8/Rkrftjldyxjqp2KNqtoBbQDmgHfVn0cY6pWTIxwQ15LXv1NL3buPcigZz7nvYKNwXc0Jop4ajUkIo8Cg3FmJxsPPKiq20MZzJiq1KdlOh/8/ix++9o8bnqjgHnrtvHHCzuQEGdNTEu7+25rEBhtvDYfXQX0VtUtoQxjTCidkpLI6yNP5+Ep3/LiZ2tYuHEHz1zRnSZpSX5Hq1bOPfdcvyOYMAs2eX079+nXQLaIdA98hD6eMVUrPjaGey7qwDNXdGf597u46KnP+GyF/X0TqKCggIKCAr9jmDAqtx+BiIxV1ZEiMr2M1aqqYZ+hzPoRmKqyquhHrn9lLiuLfuTWn7XhxrxWxMTY9JfWj6BmKq8fQbAZyka6TweUnrBeRBKrKJ8xvmiZUYd3f3sGf3hnEWM+Xs689dv5+2VdSU2O9zuaMWHl9U7ZFx6XGRNRateK4/HLu/LgoI7MWlHEhU/NYlHhDr9jGRNWwe4RNBKRHkCSiHQLuD+QBySHJaExISYiXNU7hwnX9ebwEWXI81/wxlfrrTeyiRrBWg2dD4wAMoHHApbvAv4QokzG+KJbdj0m/+5MRo8v4M63FzF33TYe/PmpJMbH+h3NmJDyNOiciAxR1bfCkCcou1lsQu3wEeWJaSt4ctoK2jdO4YlhXWlzSl2/Y4XNF184V3379OnjcxJTlcq7WRys1dCVqvqqiNyKOxdBIFV9rIzdQsoKgQmX6d9uZvT4AnbtO8jgbpmMPrc1WfXtiqiJTCcz+mht9986QN0yHjI2nJcAABTvSURBVMbUWP3aNWT6bXn8+ozmvL/wO8752wzum/QNRbv2+x0tpL744oujZwUmOniej6C6sDMC44dNO/by5LQVTMgvJCE2hl+fmcPIvi1JTap5TU2tH0HNVBXzETwqIikiEi8i00SkSESurNqYxlRfjVOT+MsvOvPJzX05t8MpPDN9FX0fnc5zM1ax98Bhv+MZc1K89iM4T1V3AhcBa3FGIb092E4icoGILBORlSJyZxnrbxGRJSKy0C0wzSoS3phwa5FRh6eGd+OD359J9+w0HvnPt5z91+m8MmcdBw7ZNN4mMnktBCXNTC8E3lTVoD1u3MnunwEGAB2A4SLSodRm84FcVe0MTAQe9ZjHGF91bJLKy9f0ZMJ1vWnWIJl73l3MuY/N5J35hRw+ElmXW43xWggmi8i3QA9gmohkAPuC7NMTWKmqq1X1APAGMChwA1Wdrqp73JdzcPorGBMxejavz4TrevPyiNOoXSuOm8cvYOATs/hkyQ/WIc1EjIpMXl8f2KGqh0UkGUhR1e/L2X4ocIGq/sZ9fRXQS1VHnWD7p4HvVfWhMtaNBEYCZGdn91i3bp2nzMaE05EjygeLNvHYJ8tZs2U33bLTuP38tvRpme53tAopGXm0a9euPicxVanSg84FvEE8cCXQV0QAZgLPV2HAK4Fc4Oyy1qvqWGAsOK2GqupzjalKMTHCxV2acMGpjZg4t5Anpq7gin98yVmt07n9/LZ0zkzzO6InVgCij9dLQ8/hXBZ61n10d5eVZyOQFfA60112DBE5F/gjcImq1uwG2iYqxMfGMLxnNjNuz+PuC9uzeOMOLnn6c2fI683Vf87kqVOnMnXqVL9jmDDyOsTEAlXtEmxZqfVxwHKgP04B+Bq4QlW/CdimG85N4gtUdYWXwNaPwESaXfsO8n+z1vB/s1az9+BhBnVtyjVn5FTbMwTrR1AznfSlIeCwiLRU1VXuG7YAym08raqHRGQU8BEQC7ykqt+IyANAvqpOAv6K02v5TfeS03pVvcRjJmMiQt3EeG7+WRt+1bsZz81Yxb+/Ws878zfSNSuNEX1yGNCpEbXibGA74x+vZwT9gZeB1YAAzYBrVLWsmctCys4ITKTbue8gb80t5F+z17Fmy27S6yQwvGc2V/TKpnGq//Mn2xlBzXTSZwSqOk1EWgNt3UXL7Hq+MZWTkhjPNWc05+reOXy2cgv/mr2Wp6ev5NkZqzi/4yn8qncOvZrXxz1LNibkyi0E7i//MUBLYBFwm6oed8PXGFNxMTFC3zYZ9G2TwYate3hlzjrGf72BDxd9T9tT6vKrPs0Y3K0pyQler+AaUznBhqGeBfwL+BS4BOitqr8IU7Yy2aUhU5PtPXCYSQs2Mu6LdSzdtJO6iXFc2iOLX/VuRk567eBvUAWWLVsGQNu2bYNsaSLJycxHUKCqXQNez1PV7iHI6JkVAhMNVJW567bxz9nrmLJoE4eOKHltM7i6dw5nt8kgJsYuG5mKOZl7BIluE8+Sn7qkwNeqOq/qYhpjSogIuTn1yc2pz+YL2/Pvr9bz2pfruWbc1zRrkMxVpzfj0h5ZpCZX/TDY77//PgAXX3xxlb+3qZ6CnRGU1ypIVfWcqo9UPjsjMNHqwKEjfPTN9/zzi7Xkr9tGYnwMg7s15arTc+jQJKXKPsdaDdVMlT4jUNV+oYlkjKmohLgYLu7ShIu7NGHxxh28Mnsdb8/byOtfbaBZg2TObpPB2W0y6N2ygd1gNhViPy3GRKBTm6byyNDO3DWwHe8v+I4Zy4p4M9/pm5AQG0PP5vXJa+sUhlYN61hTVFMuKwTGRLC05ASu6p3DVb1z2H/oMF+v2cbM5ZuZubyIhz5YykMfLKVpWhJ922SQ1zaDPi0bUDex5k2vaU6OFQJjaohacbGc2TqdM1un88cLYeP2vXy6vIgZyzbz/oLveP2r9cTFCLk59Ti7TUPObpNB+8Z17WzBeB5iQoBfAi1U9QERyQYaqepXoQ5Ymt0sNqbiDh4+wtx125i5vIgZy4pYumknAA3r1uLsNhnktW3Ima3SSU2OZ8OGDQBkZWWV95YmwlS6H0HAGzwHHAHOUdX2IlIP+FhVT6vaqMFZITDm5P2wcx8zlxcxc3kRs5YXsXPfIWJjhG5ZaZzdJoNeLRrQsUkKtWvZRYOaoipGH+2lqt1FZD6Aqm4TkYQqS2iMCatTUhK5LDeLy3KzOHT4CAsKtzNzWREzlhfxt0+WAxAj0KphHTo1TaNT0xQ6ZabRsUkKifE2UmpN47UQHHQno1cAd87iIyFLZYwJm7jYGHo0q0+PZvW55by2nHXuAPbXacwVo+5kUeEOZi4v4q15hQDExgitG9ahc2YqnTLT6Nw0lXaN69ow2hHOayF4EngHaCgifwaGAneHLJUxxjexh/aSvH01o89tAzjDXfywcz8LC7ezaOMOFhbu4JMlPzAh3ykO8bFC20Z16dQ0zSkQTVNp26gu8bFeJ0A0fvM6DPVrIjIXZ7YxAX6uqktDmswYUy2ICI1SE2mU2ojzOjYCnOKwcfteFhXuYOHGHSwq3MEHC52WSeB0fmvfOIXOTVPplJlKxyYpNE+vbR3dqimvk9e3BNao6jMikgf8TEQ2qer2kKYzxlRLIkJmvWQy6yUzoFNjwCkO64r3uIVhOwsLd/D2vEJembPu6H6NUhJpnl6bnPTatEivffR5dv1kEuLsDMIvXsvzW0CuiLQCXgAmAf8GBoYqmDEmsogIOe4v9ku6NAHgyBFl9ZbdLN20k7VbdrOmeDdrtuzmP4s3sW3PwaP7xghk1kumuVscAh9N0pKItdFWQ8prITjizkH8C+BpVX2qpAWRMaZmmThxYpW9V0yM0KphHVo1rHPcuu17DrBmi1MY1m7ZzWr3ef7arew+8NOU6AmxMTRrkHzMWUSzBrVpmFKLBrUTSEmMt2G5T1JFWg0NB34FlIxNa/3UjamB0tPTw/I5ackJdMtOoFt2vWOWqypFu/YfLRJrinezpmg3a4t3M3N5EQcOHdtgMTZGqJecQIPaCdSvnUCDOiXPa1G/TsBy99+05AQ7wyjFayG4Brge+LOqrhGR5sAroYtljPHLuHHjABgxYoQvny8iNExJpGFKIr1aNDhm3eEjyqYde1lXvIctP+6n+McDbN19gOLdPz1f8t1OincfYMfeg2W+f4xAvWSnKJQUjvq1E2iUkkjTeknuvY8kGtZNjJqC4alncXViPYuNCa2aMh/BwcNH2Lb7AMW7S4rFAbb+uJ+tuw+wZfcBtgYWkd0H2L7n2MIRFyM0SUsis14STdN+KhBOsUiiUUoicRHURLbSPYtFZBFuJ7KyqGrnk8xmjDEhER8bc/TMwot9Bw+zcfteCrftpXDbHjZu++n5pyuK+GHn/mO2j40RGqUkBhQHp1BkukWjUWpixLSECnZp6KKwpDDGGJ8lxsfSMqMOLTOOv7ENsP/QYTZt3/dToQgoGnNWFfP9zo0c0dLvGUPdxHhSEuOomxhP3cQ4Ukr+TYqnbq046gasq5sYT0rST9vUqRUXlrOOYDOUrStvvTHGRItacbFHm8eW5eDhI3y/Yx8btu2hcNteftixj137D7Fr30F27j3Ezn0H2bXvEN9t38uufc7rfQeDj9STnBB7tDDcdG5rLurcpKoPzXOHstOBp4D2QAIQC+xW1aqbKNUYYyJYfGwMWfWTyaqf7Hmfg4ePsGufUyx27TvEzr0H2RnwumRdSRFJCdGkQl5bDT0NDAPeBHJxmpG2CUkiY4yvPvzwQ78jRI342JijrZf85Pnik6quBGJV9bCqvgxcELpYxhi/JCcnk5zs/a9aE/m8FoI97vwDBSLyqIjc7GVfEblARJaJyEoRubOM9bVEZLy7/ksRyalQemNMlXv22Wd59tln/Y5hwshrIbjK3XYUsBvIAoaUt4M7f8EzwACgAzBcRDqU2uxaYJuqtgL+DjziPboxJhQmTJjAhAkT/I5hwihYP4JsVV0f0HpoH3C/x/fuCaxU1dXue70BDAKWBGwzCLjPfT4ReFpERCOtl5sxxkSwYGcE75Y8EZG3KvjeTYENAa8L3WVlbqOqh4AdQINS2yAiI0UkX0Tyi4qKKhjDGGNMeYIVgsCBNlqEMkh5VHWsquaqam5GRoZfMYwxpkYKVgj0BM+92IhzL6FEpruszG1EJA5IBYor+DnGGGNOQrB+BF1EZCfOmUGS+xz3tQbpUPY10NodqXQjTj+EK0ptMwm4GpiNMw/yf+3+gDH+ivTB5kzFBRtiIrayb+xOZDMK+AinJ/JLqvqNiDwA5KvqJOBF4BURWQlsxSkWxhhjwiikM0mr6ofAh6WW3RvwfB9waSgzGGOMKV9kjJFqjDEmZKwQGGNMlLNCYIwxUc4KgTHGRDkrBMYYE+WsEBhjTJSzQmCMMVFOIq0jr4gUAZWZSzkd2FLFcfxix1I92bFUT3YsjmaqWuZgbRFXCCpLRPJVNdfvHFXBjqV6smOpnuxYgrNLQ8YYE+WsEBhjTJSLpkIw1u8AVciOpXqyY6me7FiCiJp7BMYYY8oWTWcExhhjymCFwBhjolxUFAIRuUBElonIShG50+88FSUia0VkkYgUiEi+u6y+iHwiIivcf+v5nbMsIvKSiGwWkcUBy8rMLo4n3e9poYh09y/58U5wLPeJyEb3uykQkYEB6+5yj2WZiJzvT+rjiUiWiEwXkSUi8o2I3OQuj7jvpZxjicTvJVFEvhKRBe6x3O8uby4iX7qZx4tIgru8lvt6pbs+p9Ifrqo1+oEzO9oqoAWQACwAOvidq4LHsBZIL7XsUeBO9/mdwCN+5zxB9r5Ad2BxsOzAQGAKzlSopwNf+p3fw7HcB9xWxrYd3J+1WkBz92cw1u9jcLM1Brq7z+sCy928Efe9lHMskfi9CFDHfR4PfOn+954ADHOXPw/c4D6/EXjefT4MGF/Zz46GM4KewEpVXa2qB4A3gEE+Z6oKg4B/us//CfzcxywnpKqf4kxDGuhE2QcB/1LHHCBNRBqHJ2lwJziWExkEvKGq+1V1DbAS52fRd6q6SVXnuc93AUuBpkTg91LOsZxIdf5eVFV/dF/Guw8FzgEmustLfy8l39dEoL+ISGU+OxoKQVNgQ8DrQsr/QamOFPhYROaKyEh32Smqusl9/j1wij/RKuVE2SP1uxrlXjJ5KeASXUQci3s5oRvOX58R/b2UOhaIwO9FRGJFpADYDHyCc8ayXVUPuZsE5j16LO76HUCDynxuNBSCmuBMVe0ODAB+KyJ9A1eqc24Yke2AIzm76zmgJdAV2AT8zd843olIHeAtYLSq7gxcF2nfSxnHEpHfi6oeVtWuQCbOmUq7cHxuNBSCjUBWwOtMd1nEUNWN7r+bgXdwfkB+KDk9d//d7F/CCjtR9oj7rlT1B/d/3iPAP/jpMkO1PhYRicf5xfmaqr7tLo7I76WsY4nU76WEqm4HpgO9cS7FxbmrAvMePRZ3fSpQXJnPi4ZC8DXQ2r3znoBzU2WSz5k8E5HaIlK35DlwHrAY5xiudje7GnjPn4SVcqLsk4Bfua1UTgd2BFyqqJZKXSsfjPPdgHMsw9yWHc2B1sBX4c5XFvc68ovAUlV9LGBVxH0vJzqWCP1eMkQkzX2eBPwM557HdGCou1np76Xk+xoK/Nc9k6s4v++Uh+OB0+phOc71tj/6naeC2VvgtHJYAHxTkh/nWuA0YAUwFajvd9YT5H8d59T8IM71zWtPlB2n1cQz7ve0CMj1O7+HY3nFzbrQ/R+zccD2f3SPZRkwwO/8AbnOxLnssxAocB8DI/F7KedYIvF76QzMdzMvBu51l7fAKVYrgTeBWu7yRPf1Snd9i8p+tg0xYYwxUS4aLg0ZY4wphxUCY4yJclYIjDEmylkhMMaYKGeFwBhjopwVAuMbETnsjgy5QETmiUgfd3lO4AifYciR4Y7eOF9EzhKRDwPac/8YkOmKEGaYISK+TLAuIiNEpIkfn22qBysExk97VbWrqnYB7gL+4lOO/sAiVe2mqrNUdaA6PTsD5QAVKgQBvUGruxGAFYIoZoXAVBcpwLbSC90x2l8WZz6G+SLSL8jyESLyrjjj6a8VkVEicou7zRwRqV/q/bviDL88yD07SXL3Sy8V5WHgLHebm93Bwf4qIl+7A5td575fnojMEpFJwJIyjuc8EZntngG96Y6R42kbN9df3Az5ItJdRD4SkVUicn3A/rcH5CoZ0z5HRJaKyD/EGev+Y/dYhwK5wGsBx/+wOOP7LxSRMd6/QhOx/O5NZ4/ofQCHcXqCfoszcmIPd3kO7pj/wK3AS+7zdsB6nB6VJ1o+AqenZV0gw33f693t/o4zKFnpHCOApwNer8Wd/wH40f03D5gcsM1I4G73eS0gH2d8+zxgN9C8jM9JBz4Faruv7+Cn3qMzcH4hl7fNWn4ai/7vOD1QS47zB3f5eTgTnAvOH3qTceZRyAEOAV3d7SYAVwZ+tvu8AU6P25LOpml+/5zYI/SPSDl1NTXTXnVGWkREegP/EpFTS21zJvAUgKp+KyLrgDblLAeYrs7Y9LtEZAfwvrt8EU43/qpwHtDZ/YsanAG/WgMHgK/UGeu+tNNxJkb53BkihwRgdgW3KRknaxHOJCYlx7nfva9xnvuY725Xx821HlijqgXu8rk4xaG0HcA+4EURmYxTSEwNZ4XAVAuqOtu9HJNRBW+3P+D5kYDXR6i6n3kBfqeqHx2zUCQP54zgRPt8oqrDg7xvedsEHkvp44xz9/+Lqr5QKldOqe0PA0ml31xVD4lIT5z7JkOBUTgTo5gazO4RmGpBRNrhTCtaehjdWcAv3W3aANk4ly5OtDxUduFchinxEXCDOEMgIyJtxBkdtjxzgDNEpJW7T203e0W3Kc9HwK8D7is0FZGGQfY5emzufqmq+iFwM9ClAp9tIpSdERg/JYkzGxM4f8leraqH5djZ9p4FnhORRTjXuEeo6n4ROdHyUGVdCBwWkQXAOOAJnEsr88T50CKCTBeqqkUiMgJ4XURquYvvxhkZ1/M2QT7jYxFpD8x2/1v8CFyJcwZwIuOA50VkL87kR++JSCLOd3KLl881kc1GHzXGmChnl4aMMSbKWSEwxpgoZ4XAGGOinBUCY4yJclYIjDEmylkhMMaYKGeFwBhjotz/B9BxXO0VL9L7AAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.plot(bloom_elems, fprs)\n",
"plt.xlabel(\"Bloom filter elements\")\n",
"plt.ylabel(\"False Positive Rate (Mean over {} runs)\".format(n_repeat))\n",
"plt.vlines(bloom_elems[np.argmin(np.abs(np.asarray(fprs) - error_rate))], plt.ylim()[0], plt.ylim()[1], linestyles='dashed')\n",
"_ = plt.text(bloom_elems[np.argmin(np.abs(np.asarray(fprs) - error_rate))] + 5, plt.ylim()[1] - 0.5, \"FPR = {}\".format(error_rate))"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Bloom: k 1, fp 800.00, fpr 1.00\n",
"Bloom: k 5, fp 800.00, fpr 1.00\n",
"Bloom: k 10, fp 800.00, fpr 1.00\n",
"Bloom: k 20, fp 798.90, fpr 1.00\n",
"Bloom: k 40, fp 763.33, fpr 0.95\n",
"Bloom: k 60, fp 608.40, fpr 0.76\n",
"Bloom: k 80, fp 476.43, fpr 0.60\n",
"Bloom: k 100, fp 344.43, fpr 0.43\n",
"Bloom: k 120, fp 249.93, fpr 0.31\n",
"Bloom: k 140, fp 186.30, fpr 0.23\n",
"Bloom: k 160, fp 138.37, fpr 0.17\n",
"Bloom: k 180, fp 106.87, fpr 0.13\n",
"Bloom: k 200, fp 84.63, fpr 0.11\n",
"Bloom: k 220, fp 62.57, fpr 0.08\n",
"Bloom: k 240, fp 49.53, fpr 0.06\n",
"Bloom: k 260, fp 41.43, fpr 0.05\n",
"Bloom: k 280, fp 31.30, fpr 0.04\n",
"Bloom: k 300, fp 26.53, fpr 0.03\n"
]
}
],
"source": [
"fps = []\n",
"fprs = []\n",
"bloom_elems = [1,5,10] + list(range(20,320,20))\n",
"total_entries = 200\n",
"n_repeat = 30\n",
"error_rate = 0.1\n",
"for k in bloom_elems:\n",
" fp_sum = 0\n",
" fpr_sum = 0\n",
" for rep in range(n_repeat):\n",
" x_space = list(np.random.choice(np.arange(1000 * 100), (1000, 100), replace=False))\n",
" x1 = x_space[:total_entries]\n",
" x2 = x_space[total_entries:]\n",
" bloom = BloomFilter(max_elements=k, error_rate=error_rate)\n",
" for x in x1:\n",
" bloom.add(x.flatten().tostring())\n",
" fp = 0\n",
" for x in x2:\n",
" if x.flatten().tostring() in bloom:\n",
" fp += 1\n",
" fp_sum += fp\n",
" fpr = 1. * fp / len(x2)\n",
" fpr_sum += fpr\n",
" fp_mean = fp_sum / n_repeat\n",
" fpr_mean = fpr_sum / n_repeat\n",
" print(\"Bloom: k {}, fp {:.2f}, fpr {:.2f}\".format(k, fp_mean, fpr_mean))\n",
" fps.append(fp_mean)\n",
" fprs.append(fpr_mean)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.plot(bloom_elems, fprs)\n",
"plt.xlabel(\"Bloom filter elements\")\n",
"plt.ylabel(\"False Positive Rate (Mean over {} runs)\".format(n_repeat))\n",
"plt.vlines(bloom_elems[np.argmin(np.abs(np.asarray(fprs) - error_rate))], plt.ylim()[0], plt.ylim()[1], linestyles='dashed')\n",
"_ = plt.text(bloom_elems[np.argmin(np.abs(np.asarray(fprs) - error_rate))] + 5, plt.ylim()[1] - 0.5, \"FPR = {}\".format(error_rate))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [conda env:ltl]",
"language": "python",
"name": "conda-env-ltl-py"
},
"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.7"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment