Skip to content

Instantly share code, notes, and snippets.

@peter0749
Created June 11, 2025 14:17
Show Gist options
  • Select an option

  • Save peter0749/92282ede6267a4b7b53f05385f58e341 to your computer and use it in GitHub Desktop.

Select an option

Save peter0749/92282ede6267a4b7b53f05385f58e341 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,
"id": "1b7f177c-855c-4b7a-b4a3-e6dcaf350f3c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Starting EMD Speed Comparison...\n",
"Distribution Size (N_POINTS): 200\n",
"Benchmark Iterations: 50\n",
"\n",
"PyTorch MPS (Apple Silicon GPU) Backend Test\n",
"MPS is available!\n",
"\n",
"Generating custom cost matrix for OpenCV...\n",
"Done.\n",
"\n",
"--- Benchmarking OpenCV (Internal L2 Distance) ---\n",
"OpenCV (Internal Dist) EMD result: 0.082058\n",
"\n",
"--- Benchmarking OpenCV (Custom Distance Matrix) ---\n",
"OpenCV (Custom Dist) EMD result: 0.082058\n",
"\n",
"--- Benchmarking POT (PyTorch MPS) ---\n",
"Performing a warm-up run...\n",
"Warm-up complete.\n",
"POT EMD result: 0.082058\n",
"\n",
"==================================================\n",
" Benchmark Results\n",
"==================================================\n",
"OpenCV (Internal Dist) Avg Time: 37.3655 ms\n",
"OpenCV (Custom Dist) Avg Time: 36.8845 ms\n",
"POT (PyTorch MPS) Avg Time: 2.7723 ms\n",
"==================================================\n",
"\n",
"Generating plot...\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABc0AAAN0CAYAAABmxgALAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAXEgAAFxIBZ5/SUgAAtNZJREFUeJzs3QeYVOX5P+6XooIKEsQCgtgb1kQlamyxl1hi19gSe7CXGE3U2EvsEIMmUdGowVi+sRtLNHZNRAMKdsVekWoD/tfz/s7sf3bYBgzsLnvf1zXX7M6cOefMzJkzu5/znOdtN3Xq1KkJAAAAAABI7Zt7BQAAAAAAoKUQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQKFj6QcAYPr8+Mc/Tu+9994MPXafffZJJ598cs3vl19+eRo4cOA00y200ELpscceq3c+u+66a3rhhRemuX3HHXdM5557bs3v7777btpkk00aXKe55porzT///KlXr17pBz/4QfrZz36W+vbtm6rpm2++Sffff396+OGH0/Dhw9Nnn32Wvv7669StW7e03HLLpXXXXTfttNNO+Xdmvdh2VltttVm6jO+++y69/PLLaZVVVmn0M/Tggw+m3r17p9bmxBNPTLfddttMzWPUqFH5eu+9907PPPNMze1DhgxJ/fv3T23B66+/nu6+++70+OOP5+3iiy++SJ07d04LL7xw3idttdVWaZ111mnu1WzTbr311vTrX/+63u+atuzbb79N2223XXrjjTdS9+7d0yOPPJLmnnvuOj/X8d19xhln1Duvyu/stddeO1133XWzbN0///zzdNNNN+V1jvWfNGlSWmCBBdKKK66Ytt122/STn/wkdejQocF5xPO7/vrr03//+980ZsyY/D0en9t47muuuWaj6zBy5Mh09dVXp6effjp9+umnqWvXrmnllVdOu+22W51/v8Q6b7jhhvnvivjbIR4LANWk0hwAWrBPPvkkB0l1GT9+fBoxYkRV/+GPkCrmGUHdlltumc4+++w0efLkqsw/gvJtttkmHXvssenOO+9Mb731Vho3blz+h/fjjz/OBwfOP//8tPHGG8/ScID/F9Dutdde6fe///0sXc5zzz2XQ7W//vWvs3Q5tG6xH4iDiBHOxcHD559/Pu8TYp80duzY9Nprr6W//e1vab/99svb7YwerIRZKULbCJzDLrvsUhOY1+Xvf/97eumll1JL8K9//SsfkLr00kvTsGHD8mcuPnsRXP/73/9Ov/rVr/LnLkLq+sRjIxy/77778t8t8fi4vvfee/MB+LqKAsrF5zsOmN9+++3pgw8+yI+Pg+oR4h922GF5/zB16tRaj4kDE/F3SnjiiSfysgCgmoTmANDCRdVVXf7zn//kKt5ZZcqUKenaa69NRx555DT/rM5ImHDooYemd955p9FpJ06cmM4888z029/+dqaWSd2vbRwI+elPf5oD7VklwpUTTjghBy2vvPLKLFsOrd+HH36Y9txzzxwixj6nMbHdxvZbqsyHliCC3j/84Q/553bt2uVK8obEth7fc83txRdfTAMGDMiV4Q2JA1kRXtf1N0cE3aXnXpf4+yHOpvvHP/5R7984p556aoN/z8T+4Yorrpjm9qhCLznvvPNyhTwAVIv2LABQJTvvvHM+FbkplllmmSbPN/6hjFCpUvmp3jMiQs3vfe97+R/aqPaOas8IoqJFRvk/nv/85z/TNddck/bff/8ZWs5dd901zen70QYmKttWWGGFvKz//e9/uW1LeTg/dOjQtOqqq+aKPaojXuc4EDI7Khf/7//+r0nbYAT5JbE9ttbPfrRPqPTAAw/kz1PJkksumQ466KAG53XggQfm6vySpZZaKs2pYr8Tr0flgZX43McZJ9HeYfTo0bl6tby6PAK+I444Im9jnTp1aoY1b7viO+6cc86p+X3xxRdv1vVpKa666qqa781op9SUNlNx4DvOuoozLJpLfDdHVXdJfOZ233331KNHj/Tss8/mz155cB5tqMq/k2P/XXnGUrTd+tGPfpSr1OMMs5ILLrggbbbZZrnlUkl855911lm1vvvXWmut/PdBBPoRyJdceeWVuRp9kUUWqbkt2r4sscQS+cy1999/P5+l1tg+FgCaSmgOAFUME6ICshrat29fU3UZ4Xj8QxnVa/VVoEev0elto7LFFlvU+Y99nFL9y1/+slav9EsuuSQHedPba/yjjz5Kp5xySq3b1lhjjXTZZZflPsXl4h/kX/ziF/nU8PJTvrfffvsGT3On9SqdWt/aRXBTV8/eCHrLQ/MYo6CxfcQGG2yQ2oqLL764VsV47Md+97vfTXOg7KijjkqnnXZa7qddEiFZtHTYd999Z+s6t3UxzkW1x7po7b788staYxpE/++miiA5QuZ55503zW5xQCqC+5JYh1tuuaXm74Jot3LhhRfmsLokqsXLP58RisffDCUx5kBUncffK3GwP+YR4XuIlksx/dZbb10zffydUb4PWHrppdNf/vKX/J0fZyrF30GlCvU4KBE/x4HFcqW2TuHGG2/Mf0c01n8dAJpCexYAaIGiAru81cWrr746TT/z8n6o5dPPrAj24lTq+eabr+a2r776Kld+T6+o+op1LZ93/ANeGZiXqkvLKxhD/DP+0EMPTfdygZYtqsUj4KoMx+s6s2SeeebJgyZWDiZ78803z/L1hMbEAJqlM2Y6duyYNt100+lqTzR48ODUHMoD87DRRhtNcyB9jz32qPV7ZVukOJumXLSlKR3gj+uoWi8XZ6419Pg4OF9+kLzyLLvKx5cKAEqi2ry8uh0AZoZKcwBooVXr5aF4VJsvt9xytf7ZLa8sj+mrOShonP4c1XIRBpTEadrTc9pzrF9lqHXAAQekrl271vuYTTbZJJ/u36VLl3yK+w9/+MM6K3hLXn755Rzmx+tRGjwsgvl4TPzzXVfLjBAVq7/+9a9rfh80aFAOOu655550ww03pJEjR+YKt+WXXz5Xspb/U37HHXfkaSI8iIAk2mdEUFBXBXGcDbDPPvvU/B794aMv7JNPPpnbpER1/YQJE/JzjmVEC5zygxX1rW88t8qWN+HEE0+sVfEYByFivd5999382laK7SqeY4i+tocffnjNffH847nefffd+XWOQWLjtmitE8FKVBTG+i644IL1Pt+SWKfSepXWKUSFZXnbjajKrq+twYy+15XPPXrgnn766bnKMnrtx0BzUQG5wAIL5G0untPKK6+cmktUZpa3XopBeWO9SkrvV4jnFVWdb775Zm4P8fjjj+f3adFFF81V/AcffHDN9hSDacYBqxgwL87miGni8fGZLH8P6zpbJNozxesUgVQEYfHYddddNwdaURk6I6LtQnkbqGjN01ALqPisxfJisOB4r+M1KX9dKkWIGdtutId6++238wG42K9Ei5wIByMMjG25LuXbZRyQjDYwsY3EaxwH8WJe8ZpFC5n4PEcrixDbZbzG0Z4oBjGM26NN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tMkmm6TDDjssde/ePU9z6623pl//+teNzmvIkCGpf//+DU4zadKkdO2116Y777wzjR49OnXp0iWtv/76eXl9+vSpme7pp59O++yzT6PLPOecc9JPf/rTJj1XAAAAAJqX0Bxo0caNG5f23HPP9Prrr6d11lknh+VvvPFGuu6669J9992Xhg4dmnr27JlWXHHFNGDAgDrn8c4776R//OMfaaGFFkpLL710g8v79ttv00EHHZSeeeaZtOqqq+Zlf/jhh+n//u//8vL++te/5mWFxRZbrN5lRtB//fXXp3nnnTfPBwAAAIDWQWgOtGgDBw7Mgfnhhx9eK6COQPqMM85Il112Wa7kjiC7FGaX++abb9Luu++eOnTokC655JLUo0ePBpd344035sA8KsNjviUPP/xwOuSQQ9LZZ5+dA/vQu3fvvF51iWnDmWeemZZZZpkZfv4AAAAAzF56mgMt2rvvvpuD7l/84he1bt9+++3z9fPPP9/g4wcNGpRGjBiRH7/mmms2ury33nordevWLbdiKbfxxhunBRZYIA0bNqzRedx88805ZN9mm23yBQAAAIDWQ6U50KJF6F2XqD4P0XKlPtGP/C9/+UuDbVQqnXLKKflS6eOPP05jx45NvXr1arSdzEUXXZTmn3/+dNJJJzVpmQAAAAC0HCrNgVblyy+/zL3Fjz766NSxY8dpKsLLXXjhhbk9S0w7zzzzzNDyxo8fnx577LF0wAEHpKlTp9bbjqXkj3/8Y/r888/TgQce2GgrGAAAAABaHpXmQKsR/cZPO+20/HP0KL/gggvy4KD1VZlHuL7EEkukrbfeeoaW9+ijj+bwu+T4449PO+64Y4MBe6xj165d089+9rMZWiYAAAAAzUulOdBqdO/ePYfYO+ywQ64cP+6449Kf/vSnOqe99tpr05QpU/L0EbDPiE6dOuVe6LvssktacMEFc0gfA3tGxXld/v73v6cJEybkwDzaswAAAADQ+qg0B1qNLbbYIl9CtEnZbbfdcpDdv3//tMoqq9RM991336U77rgjdenSJW233XYzvLy11147X8IXX3yRw/DrrrsurbXWWjXrUe6WW25J7du3T7vvvvsMLxMAAACA5qXSHGiVevfunfuMhwcffLDWfc8++2waM2ZM2myzzdLcc89dleV973vfS0ceeWT++YEHHqizHcwrr7ySA/VFFlmkKssEgHLx3XbeeeflA7errrpq2njjjfMZUDGWRqWvvvoqD6a91VZb5QPLG264YTrmmGPSW2+9NV3LHDp0aD7DK5a3xhprpL333ju3L6tLrMepp56al7XyyiunH/3oR3lQ7I8++miGnzMAADQHoTnQYsUgno8//ni9/5z36dMnX1eGBQ8//HC+nt5e5tF25amnnkr333//dC0vPPTQQzO0TABoinHjxqU999wz/eUvf0k9e/bMZz8tv/zy+Qyo7bffPn3wwQc1006aNCntt99+6bLLLksLLLBADrojxL777rvTrrvumt5+++0mLfPss89Ov/3tb9Onn36aW5Vtu+22afjw4emggw7KZ1dVBvox75tuuikttthieZmxfjHdzjvvLDgHAKBV0Z4FaNGhefQkn3feedMTTzwxTdX4iBEj8vWSSy5Z6/bnn38+t0n5wQ9+MF3La9euXTr66KPzP/4R1C+00EJNWl5pmSEqzQGg2gYOHJhef/313J5swIABNbdff/316YwzzsgB+TnnnFMzbXwv/fznP0+/+tWvaqa97bbb0oknnpguvvjidMkllzS4vDfffDMNGTIkB+C33npr6tatW7593333zSH4WWedlQ8Ud+7cOd9+9dVX57OuIsyPoL18vS+//PK8fvEYAABoDVSaAy1WDKa5ySab5Oq6+Ke7XFS6XXPNNTlQj8q3km+//TaNGjUqB9tx3/SKar0YQDROf4/rkggCImCIMD7CgkqxPrG8ugJ1AJhZ7777burRo0ceoLrye6v84O3XX3+dbrzxxrTEEkukY489dppp4zusb9++jS7vxRdfzGdgRauzUmAelllmmTzeRwx8/eqrr9bc/sILL+TrqEgvF9Xx5esHAACtgUpzoEU7+eSTcyA9ePDg9Nxzz6XVVlstvf/++7mPeVSGR7VceUX4hx9+mAODpvQVj8FC45/+gw8+OPdID1G9Fy1a4r7XXnst/fCHP0yfffZZ7mMe/WF/85vfpBVWWKHWfCZPnpzDjMUXXzyH6gBQbdGfvC5RfR5K34Uxrkd8t+21116pY8faf+rHd1RTq71jLI/w3nvvTXPfxx9/XGuayunLvydL03bv3r1JywUAgJZAugO0aIsuumjuhxq9UaNfa5wq/swzz6RNN9003Xzzzfm63BdffJGvu3Tp0ui877zzzjzAWXkgENXtN9xwQzrk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qUePHukXv/hFrdu33377fP3888/X3DZq1Kh8vfzyy8/mtQQAAAAAoDVo9ZXmgwYNqvP2qD4PCy20UM1tL7/8cr5eYYUVZtPaAQAAAADQmrT60LzSl19+mZ566ql07rnnpo4dO+bBQCtD85deeimdd9556dVXX01zzz13WnfdddMRRxyRllxyySYvJ+bVrl27WfIcAGBGjRgxorlXAQCane9DYEZ8/fXX+do+BFq3qVOnzvQ8Wn17lnI33nhjWnvttXMA/tFHH6Xzzz8/Dw5aMnLkyHx98cUXp6WWWirtvvvuabnllkt333132nnnndOLL77YjGsPAAAAAEBzm6Mqzbt3754OPPDA9Mknn6T7778/HXfccemDDz5IBxxwQJo4cWJaeOGF04ILLpiuuOKK1KtXr5rH3XTTTenUU09Nxx9/fA7QO3To0OiyVlxxxSZNN+d5rblXAIAG9OvXr7lXoe0Y3twrAEB9fB8CM6JUYW4fAq3b5MmT07Bhw2ZqHnNUaL7FFlvkSzj88MPTbrvtli644ILUv3//tMoqq6Rbb721zsdFxfntt9+eBw2NavM11lhjNq85AAAAAAAtwRzVnqVc7969c4V5ePDBBxudftVVV83X77zzzixfNwAAAAAAWqZWXWn+zTffpGeffTaX3G+wwQbT3N+nT598/fnnn6cvvvgivfHGG7mFS10Dfk6aNClfd+rUaTasOQAAAAAALVH71h6aRw/zY445Jv9cXy+qCMmffPLJtOeee6Zzzz13mummTJmS/vvf/6Z27drlNi4AAAAAALRNrTo0n3/++dMmm2ySxo0blwYOHFjrvuHDh6drrrkmzTvvvGnbbbfNlehdunRJjz76aHr88cdrTTto0KD02muvpc0226zWAKEAAAAAALQtrbo9Szj55JNzQD548OD03HPPpdVWWy29//77uY95VI5ffPHFaaGFFsrTnn766em4447L1ekRkPfs2TMP/hmjqS611FLptNNOa+6nAwAAAABAM2r1ofmiiy6abrnllvSHP/whB+UvvPBC6tq1a9p0003TIYccklZYYYWaabfeeutcSf7HP/4xt2uZOHFi/v2ggw5KBx98cK5cBwAAAACg7Wr1oXmIwT1/85vf5EtjVl999RyaAwAAAADAHNXTHAAAAAAAqkloDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQEFoDgAAAAAABaE5AAAAAAAUhOYAAAAAAFAQmgMAAAAAQKFjmgOMGTMmDR48OD300EPpgw8+SAsuuGDaZJNN0mGHHZa6d+9ea9ovvvgiDRo0KD388MPpk08+Sb169Uo77bRT2n///VPHjnPEywEAAAAAQFutNB83blzac88901/+8pfUs2fP9LOf/Swtv/zy6brrrkvbb799DtFLxo4dm/bee+90/fXXp379+qV99tknde7cOf3+979PxxxzTLM+DwAAAAAAml+rL60eOHBgev3119Phhx+eBgwYUHN7BONnnHFGuuyyy9I555yTb4sK81dffTWdeuqpOWgPRx99dDrqqKPSfffdl+6///60+eabN9tzAQAAAACgebX6SvN333039ejRI/3iF7+odXtUmYfnn38+X3/11Vdp6NChuRp99913r5muQ4cO6YQTTsg/33TTTbN13QEAAAAAaFlafaV5VI/XJarPw0ILLZSvX3zxxTRx4sS02Wabpfbtax8r6NOnT+rdu3d69tln0+TJk3OQDgAAAABA29PqQ/NKX375ZXrqqafSueeemwf2jMFAw1tvvZWvF1988TofF8F5VK3HpW/fvo0u5+WXX07t2rWr8toDwMwZMWJEc68CADQ734fAjPj666/ztX0ItG5Tp06d6XnMUaH5jTfemE477bT8c1SLX3DBBWmdddbJv48ZMyZfd+vWrc7HdunSpWawUAAAAAAA2qY5KjTv3r17OvDAA9Mnn3ySB/U87rjj0gcffJAOOOCA9M033+Rp5p577jofW7q9dFSxMSuuuGIbbePyWnOvAAAN6NevX3OvQtsxvLlXAID6+D4EZkSpwtw+BFq3aL89bNiwmZrHHBWab7HFFvkSDj/88LTbbrvlavP+/funTp065du//fbbOh9bCtXnm2++2bjGAAAAAAC0JLVHxJyDxMCeUWEeHnzwwbTAAgs02H5l3Lhx+Xr++eefjWsJAAAAAEBL0qpD86gOf/zxx9Ojjz5a7+Ce4fPPP09LLbVU/vmdd96pc9q4fd555029evWahWsMAAAAAEBL1rG1h+bRwzzC7ieeeGKafuWlXlRLLrlkWnnllXPrlWeeeSZNmTIltW///x8vGD16dHrvvffSuuuu20b7lAMAAAAA0OorzaOVyiabbJJbqwwcOLDWfcOHD0/XXHNNDtS33XbbNM888+Trd999Nw0ZMqRWY/jzzz8//7zXXnvN9ucAAAAAAEDL0aorzcPJJ5+cA/LBgwen5557Lq222mrp/fffz33M27Vrly6++OK00EIL5WmPOuqo9Nhjj6VzzjknPfXUU2mZZZbJFepRkb7VVlvlAB4AAAAAgLar1Yfmiy66aLrlllvSH/7whxyUv/DCC6lr165p0003TYccckhaYYUVaqbt3r17uummm9Kll16a/vWvf+XAPAYMPf7449M+++yTQ3YAAAAAANquVh+al8Lw3/zmN/nSmIUXXjidddZZs2W9AAAAAABoXVp1T3MAAAAAAKgmoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAAAFoTkAAAAAABSE5gAAAAAAUBCaAwAAAABAQWgOAAAAAACFjmkOMGHChDR48OB0//33p/feey/NNddcaaWVVkr77rtv2myzzWpNu+uuu6YXXnihzvlstNFGeT4AAAAAALRNrT40Hz9+fNpzzz3TqFGjUr9+/fLP48aNywH6gAED0jHHHJMOPvjgPO2UKVPSK6+8knr37p122GGHaea1xBJLNMMzAAAAAACgpWj1oflVV12VA/Pdd989nXbaaaldu3b59iOPPDLttNNO6dJLL01bbrll6tu3b3rzzTfTpEmT0nrrrZcOP/zw5l51AAAAAABamFbf0/yee+7JQfmxxx5bE5iHRRZZJO2xxx5p8uTJ6ZFHHsm3Rbgell9++WZbXwAAAAAAWq5WX2kefcujHUvXrl2nuW/uueeu6XkeXn755Xy9wgorzOa1BAAAAACgNWj1oflee+1V5+1Tp07Nfc3LK8tLoflLL72UzjvvvPTqq6/mYH3ddddNRxxxRFpyySVn45oDAAAAANDStPrQvD433HBDevHFF1OfPn3S+uuvn28bOXJkvr744ovT5ptvnn7wgx+k4cOHp7vvvjs9+uij6eqrr06rrrpqk+YfAXx5OxgAaAlGjBjR3KsAAM3O9yEwI77++ut8bR8CrVsUU8+sOTI0jxD8rLPOSh07dkznnntummuuudLEiRPTwgsvnBZccMF0xRVXpF69etVMf9NNN6VTTz01HX/88fmxHTp0aNb1BwAAAACgeXScEyvMzzjjjFwFHi1Y1lxzzXz7vPPOm2699dY6H7P77run22+/PT3//PO5On2NNdZodDkrrrhiGw3XX2vuFQCgAf369WvuVWg7hjf3CgBQH9+HwIwoVZjbh0DrNnny5DRs2LCWF5rHTuapp55Ko0ePTp9//nn68ssvU6dOnXKV91JLLZXbokQblGqGzlOmTEnnn39+brESfcovvPDC3IKlqWJ9IjR/5513mhSaAwAAAAAw56laaP7666+n66+/Pt1zzz05JK+rh0x5D/Bu3bqlbbbZJu23336pd+/eM7Xsb775Jh177LF54M+Y76BBg2oqzEu++OKL9MYbb6Tu3bvXOeDnpEmT8nWE+wAAAAAAtE0zHZq/++676aKLLkr33ntvrvYO8803X1p22WVzON21a9fUuXPnNHbs2Bxcf/jhh7kSPX6OkD36iW+//fbpkEMOyYN2zki5/ZFHHpkeeuihHL5fddVVuZq90pNPPpmOPvrotNFGG6XBgwfXui/W+7///W8O9VdZZZWZeDUAAAAAAGizofmVV16ZB9WMKu1lllkmh9/rr79+WmGFFRqtDP/f//6XHn300XTbbbelW265Jd1555051I7K8+ldhwjMY2DP6Ge+yCKL1DndBhtskLp06ZKX+fjjj6f11luv5r6oTH/ttddyO5fyAUIBAAAAAGhbZjg032uvvdJ//vOftO6666bDDjtsmnYoDYme49HXPC5HHHFEevjhh9Of//zndO655+YAfMiQIU2az5gxY3JoXhqYc+jQoXVOF+u2zjrrpNNPPz0dd9xx6cADD0ybbbZZ6tmzZ+5jHo3hozr9tNNOa/JzAAAAAABgzjPDoXkM8BmBdVRwz4wYDHTTTTfNl/vuuy+3emmq5557Lk2cODH//OCDD+ZLXaL1S4TmW2+9da4k/+Mf/5jbtcRj4/eDDjooHXzwwWn++eefqecCAAAAAEAbDc3vuOOO1LFj1cYRzbbYYou0ySabNHn6CNpHjRo1XctYffXVc2gOAAAAAACV2qcZVO3AfFbPFwAAAAAAGjPbEuqvvvoqPfHEE2nKlCm5x3i3bt1m16IBAAAAAKB5QvOPPvooXXHFFTW9wsPrr7+e9t9///TJJ5/k3zt37pzOPPPM3GMcAAAAAADmyNA8Bgfddddd08cff5w22mijmttPOeWUfFu7du3SfPPNl8aPH59OOOGEtPzyy6ell166mqsAAAAAAACzv6d5Xa699tpcab744oun3XbbLd/29ttvp//85z+pQ4cO6cYbb0zPPfdcrkD/7rvv0jXXXFPNxQMAAAAAQMsJzR999NE8kOef//znmkrzf/3rX/n6+9//flp99dXzz4cffnjq2rVreuqpp6q5eAAAAAAAaDmh+ejRo9MSSyyRevfuXXNbDP4ZbVnWXXfdmtvmmmuuPE20bAEAAAAAgDkyNP/qq6/S3HPPXfN7tGB59tln889rr712rWknTZqUw3QAAAAAAJgjQ/OFF144vffee+nbb7/Nv0dgPnHixDz4Z6k1S4i+51GV3rNnz2ouHgAAAAAAWk5o3r9//zR27Nj0+9//Po0cOTJdcskluZp8ww03zAOBhs8++ywdf/zxafLkyWmdddap5uIBAAAAAKDlhOYHHnhg6tSpUxoyZEjacccd0wsvvJDD8rg9PPfcczlAjwr0Ll26pJ///OfVXDwAAAAAALSc0HyppZZKf/nLX9Iqq6ySe5svt9xy6YorrkgrrLBCTfuW6HO+7LLLphtvvLHWgKEAAAAAANDcOlZ7hmussUYaOnRonfdFSH777bfXhOgAAAAAADDHVpo3urD27QXmAAAAAAC0nUrz8M0336Q33ngjjR8/Pk2dOrXBaddaa61ZsQoAAAAAAND8ofnFF1+cBwL96quvGp22Xbt26aWXXqr2KgAAAAAAQPOH5tdcc00aPHhwk6dvrAodAAAAAABabWgeA4BG9fhPf/rT9Mtf/jItvPDCqWPHWdIBBgAAAAAAqq6qifbo0aPTggsumM4444w86CcAAAAAALQmVU22559//rTQQgsJzAEAAAAAaJWqmm6vtdZa6c0330wTJkyo5mwBAAAAAKD1heaHHXZYmjx5cvrd735nkE8AAAAAANp2T/MVVlghXXrppWnAgAFp2LBhab311kvdu3fPg4PWJ6YFAAAAAIA5LjQfP358uuqqq9KUKVPyoKA33XRTo48RmgMAAAAAMEeG5pdcckl6/vnn888xIGivXr3SXHPNVc1FAAAAAABA6wjNH3jggdyK5eyzz0477rhjNWcNAAAAAACtayDQzz//PPXt21dgDgAAAABAq1TV0HzhhRdOHTp0qOYsAQAAAACgdYbmW2yxRXrjjTfSiBEjqjlbAAAAAACYLaoamh966KFp8cUXz9f33ntvmjBhQjVnDwAAAAAArWcg0NNPPz316dMnPfbYY+noo4/Og4J26dIlde7cuc7p4/6HH364mqsAAAAAAAAtIzT/xz/+UfPz1KlT8+XLL7/Ml/pCcwAAAAAAmCND83POOaeaswMAAAAAgNYbmu+4447VnB0AAAAAALTegUABAAAAAKBNhuY///nP02uvvVbVlRkxYkTaZ599qjpPAAAAAACY5aH5e++9l7bffvv029/+Nr3//vtpZowcOTIdf/zxaZdddkmffPLJTM0LAAAAAABme0/z22+/PQ/8efPNN6dbb701rb/++mm77bbL1126dGn08R9++GF69NFH8+OHDx+eb9tzzz1zeA4AAAAAAK0qNO/cuXM6/fTT0w477JDOPffc9K9//Ss98sgjqUOHDmnppZdOyy67bOrbt28O0GPasWPHpi+++CJ99NFH6fnnn08ffPBBns/UqVPTWmutlY488si05pprVvO5AQAAAADA7AnNS77//e+noUOH5sB8yJAh6cknn0yjRo3Kl3bt2k0zfYTkecEdO6Yf/ehH6Re/+EUOzQEAAAAAoNWH5iUbbrhhvnz55Zfp6aefzpd33303ffbZZ7nKfJ555kk9evRISy65ZA7a11133dS9e/dqLR4AAAAAAFpOaF6ywAILpM033zxfAAAAAACgNWnf3CsAAAAAAAAthdAcAAAAAAAKQnMAAAAAACgIzQEAAAAAoCA0BwAAAACAgtAcAAAAAAAKQnMAAAAAACgIzQEAAAAAoNAxzSJffvllevLJJ9Mbb7yRxo0bl371q1+lr7/+Or3wwgtp7bXXnlWLBQAAAACAlhOaT506NV1++eXp6quvTl999VXN7RGav/vuu2nfffdNq6++eho0aFDq3r17tRcPAAAAAAAtpz3LCSeckK644oo0adKk1K1bt9S5c+ea+8aMGZND9WHDhqW99947TwMAAAAAAHNkaH7//fenO+64I1eQX3XVVbk9yworrFBz/w9+8IP017/+NS244IK5bcuQIUOquXgAAAAAAGg5ofnf/va31K5du3ThhRem9ddfv85pIji/5JJLcsX5fffdV83FAwAAAABAywnNhw8fnnr27Jl++MMfNjjdmmuumRZbbLH01ltvVXPxAAAAAADQckLziRMn5j7mTREtXL777rtqLh4AAAAAAFpOaN6jR4/09ttv59YrDfn2229zlXlMDwAAAAAAc2Rovvbaa+dq8xtuuKHB6a699to0bty43KYFAAAAAADmyNB8//33T+3bt0/nnXdeGjJkSPriiy9q3f/ZZ5/lQUAvuuiiPN3Pfvazai4eAAAAAABmSsdURSussEI66aST0plnnpnOOeecfClZZ5110pgxY/LP0b7lyCOPTKuuumo1Fw8AAAAAAC2n0jzstdde6Y9//GNafvnlczheukTVeVwvvvjiudL80EMPrfaiAQAAAACg5VSal2y44Yb58t5776VXX3019y/v3LlzWnLJJdPSSy89KxYJAAAAAAAtMzQvWWyxxfIFAAAAAADadGge1eXjx4/PLVka0qtXr1m1CgAAAAAA0Lyh+dChQ9OVV16ZW7M0pl27dumll16q9ioAAAAAAEDzh+a33357OuWUU5o8fWNV6AAAAAAA0GpD8yFDhuTr9ddfPx100EFp4YUXTh07ztK26QAAAAAAUDVVTbRfe+21tMACC6SBAwemeeaZp5qzBgAAAACAWa59NWfWqVOntNhiiwnMAQAAAABolaoamq+yyirp7bffTt9++201ZwsAAAAAAK0vNI8+5hMnTkwXX3xxNWcLAAAAAACtr6d5//7906mnnppOP/30NHz48LTBBhuk7t27p/bt68/md9hhh2quAgAAAAAAtIzQPNqyPPvss2nKlCn5Oi4NadeundAcAAAAAIA5MzQfNGhQuuuuu/LPUV0eVeZzzTVXNRcBAAAAAACtIzSPwDyqxw877LB04IEHpk6dOlVz9gAAAAAA0HpC848++ij17NkzHX744dWcLQAAAAAAzBb1j9A5A773ve+lLl26VHOWAAAAAADQOkPzjTbaKL322mtp9OjR1ZwtAAAAAAC0vtB8wIABqVu3brmn+f/+979qzhoAAAAAAFpXT/Mbbrghrb322umee+5Ju+66a27Xsuiii6bOnTvXOX0MGnr99ddXcxUAAAAAAKBlhOZXXHFFDsLD1KlT0+eff54v9SlNCwAAAAAAc1xoHu1ZmsOECRPS4MGD0/3335/ee++9NNdcc6WVVlop7bvvvmmzzTarNe0XX3yRBg0alB5++OH0ySefpF69eqWddtop7b///qljx6q+HAAAAAAAtDKtPjQfP3582nPPPdOoUaNSv3798s/jxo3LAXqszzHHHJMOPvjgPO3YsWPT3nvvnQcr3XzzzdPiiy+eHn/88fT73/8+92C/7LLLZvv6AwAAAADQcrT60uqrrroqB+a77757Ou2002pavhx55JG5gvzSSy9NW265Zerbt2+uMH/11VfTqaeemsP1cPTRR6ejjjoq3XfffTlojzAdAAAAAIC2qf2MPnD06NH5Mnny5Glum57LzIpBRyMoP/bYY2v1SF9kkUXSHnvskdfvkUceSV999VUaOnRo6tmzZw7YSzp06JBOOOGE/PNNN9000+sDAAAAAEAbrDSPXuHt27dPd911V1pyySXzbdNbpR0h90svvZRmRvQtj3YsXbt2nea+ueeeu6bn+YsvvpgmTpxYs97l+vTpk3r37p2effbZHLJHkA4AAAAAQNszU+1ZpkyZUuv3qVOnTtfjp3f6uuy11171zjvarYTll18+vfXWW/nn6GNelwjO33333XyJVi6Nefnll2tVtgNASzBixIjmXgUAaHa+D4EZ8fXXX+dr+xBo3aqROc9waP7ggw/WtEGpvK0luOGGG3J1eYTh66+/frr66qvz7d26datz+i5dutQMFgoAAAAAQNs0w6H5wIEDc1uWgw46qOa2xRZbLLUEd999dzrrrLNSx44d07nnnpvmmmuu9M0339Rq2VKpdHvpqGJjVlxxxTbaxuW15l4BABrQr1+/5l6FtmN4c68AAPXxfQjMiFKFuX0ItG7RfnvYsGHNMxDobbfdlgfYbGmiwjwGBQ3nnXdeWnPNNfPPnTp1ytfffvttnY8rherzzTffbFtXAAAAAADmoJ7mLUn0Vz///PNzG5aoGr/wwgtrDUy6wAILNNh+JQYTDfPPP/9sWmMAAAAAAFqaOSI0jyrxqC6PgT+jZ/mgQYNqKsxLllpqqXz9zjvv1DmPuH3eeedNvXr1mi3rDAAAAABAyzPD7VlaUo+aI488MgfmvXv3TjfeeOM0gXlYeeWVc+uVZ555Jlellxs9enR677330uqrr95G+5QDAAAAADBHhOZXXnlleuihh3KFePQzL1WUV5pnnnnStttum9599900ZMiQWqF7tHUJe+2112xbbwAAAAAA5rD2LK+88kraZ599Zvjx7dq1S9dee+0MP37MmDE5NA8rrrhiGjp0aJ3TReX5Ouusk4466qj02GOPpXPOOSc99dRTaZlllklPPPFEHh15q622SptssskMrwsAAAAAAG08NB8/fnxudzIzofnMeO6559LEiRPzzw8++GC+1OWQQw7JoXn37t3TTTfdlC699NL0r3/9Kwfm0dLl+OOPz+H/zK4PAAAAAABtODRfcMEF0/rrr5+ay6abbppGjRo1XY9ZeOGF01lnnTXL1gkAAAAAgDYamvft2ze3OgEAAAAAgDlBqx8IFAAAAAAAqkVoDgAAAAAABaE5AAAAAAAUhOYAAAAAADCzA4EOGDAg9ezZc0YfDgAAAAAAc1ZoDgAAAAAAcxLtWQAAAAAAoCA0BwAAAACAgtAcAAAAAAAKQnMAAAAAACgIzQEAAAAAoCA0BwAAAACA2RGaf/755+m5555LDz/8cP59ypQpacKECbNykQAAAAAAMMM6plngySefTJdcckl68cUX8+/t2rVLL730UnrvvffSjjvumPbaa6901FFH5dsBAAAAAGCOrTT/61//mn7xi1+kF154IU2dOrXmEj788MM0fvz4dOWVV6Zjjjmm2osGAAAAAICWE5pHNfnZZ5+d2rdvnw444IB0xx13pNVXX73m/lVWWSUdeeSRqUOHDunee+9N//jHP6q5eAAAAAAAaDmh+Z///Ofct/zXv/51Ou6449Kyyy6bA/SSTp06pUMPPTSdeuqpufr81ltvrebiAQAAAACg5YTmzz77bFpggQXSnnvu2eB0O++8c+revXt6+eWXq7l4AAAAAABoOaH5559/nvr06dPoAJ9x/2KLLZYmTJhQzcUDAAAAAEDLCc27du2aPvjggyZN+9FHH+XpAQAAAABgjgzNV1555fTZZ5+lJ554osHpHn744fTxxx/n6QEAAAAAYI4MzXfdddc8wOdvfvObNHLkyDqnefLJJ/NAodGi5ac//Wk1Fw8AAAAAADOlY6qiTTfdNG277bbpzjvvTDvuuGNaZpll0ocffpjvO/LII9Nrr72W3njjjRysb7zxxmnLLbes5uIBAAAAAKDlhObhvPPOSz179kzXXnttevXVV2tuv++++/J1hw4d0i677JJOOumkai8aAAAAAABaVmgeofixxx6b9ttvv/Too4+mV155JY0fPz517tw5LbnkkmnDDTdMvXr1qvZiAQAAAACg5YXmJQsuuGBu0QIAAAAAAG1yIFAAAAAAAGjNqlppvskmmzR9wR07pk6dOqUePXqkfv36pZ122in17du3mqsDAAAAAADNF5q/99570/2YUaNGpSeeeCJdd9116ayzzkpbb711NVcJAAAAAACaJzR/8MEH03nnnZfuv//+tPzyy6e99torrbzyymn++edPEyZMSCNHjkxDhw5Nzz//fFpttdXSPvvsk8aMGZMeeeSRPGjoSSedlB+39NJLV3O1AAAAAABg9vc0HzZsWPrnP/+Ztthii3TLLbekXXfdNa200kpp8cUXTyuuuGIeGPTGG29Mu+yyS3rxxRfTPPPMk4P1K6+8Mg0YMCB99dVX+X4AAAAAAGj1oXm0WIkg/Mwzz8w9y+sTFeWdO3dOV199dc1tBx10UJpvvvnSY489Vs1VAgAAAACA5gnNoz/5Msssk7p06dLgdBGYRwuWl156qea2ueeeO/Xp0yd9/PHH1VwlAAAAAABontC8U6dO6fPPP2/StJ999lnq0KFDrdumTJmS5pprrmquEgAAAAAANE9oHlXmH3zwQbrvvvsanO6hhx5K77//flp22WVrbhs3blx65513Us+ePau5SgAAAAAA0DyheQzqOXXq1HTiiSfmAT2/+eabWvfH7zfffHM6/vjjU7t27fJAoSFaspx66qnp66+/Tuutt141VwkAAAAAAJqs/tE6Z8CWW26ZdtlllxyMn3766encc89Nffv2TfPOO2+aMGFCevvtt9O3336bg/Vtttkm7bjjjvlxRx99dPrPf/6Tp9tnn32quUoAAAAAANA8oXmIsHzllVdOl19+efr000/TK6+8Uuv+7t27p0MOOSTtvffeNbdFmL7SSiulk08+OS2yyCLVXiUAAAAAAGie0Dzaruy222659cqwYcPSq6++mr744ovUuXPntNxyy6Uf/OAH0wz2GT3O55577mqvCgAAAAAANG9oXh6er7HGGvnSGIE5AAAAAABz3ECgdZkyZUqtSwwGOnbs2Ny2ZfDgwbN68QAAAAAA0HyV5o8++mjuZx6heATkjTn44IOrvQoAAAAAAND8ofnw4cPTYYcdliZPnpymTp3a8II7dmxS6xYAAAAAAGiVofmQIUPSd999l5Zddtl0wAEHpE6dOqUjjzwybbHFFnlw0A8//DDdeuut6bnnnktrrrlmuuaaa6q5eAAAAAAAaDmheYThHTp0SJdddllacskl8209e/ZMo0ePTuuuu27+fccdd0xHHHFEeuCBB9Jdd92Vttlmm2quAgAAAAAAtIyBQD/77LPUq1evmsA8rLDCCrX6m7dr1y79+te/zj9H1TkAAAAAAMyRoXno1q1brd+XWGKJ3OP8zTffrLktgvW+ffumUaNGVXvxAAAAAADQMkLzBRdcMH3yySe1buvdu3e+fu2112rdPt9886UxY8ZUc/EAAAAAANByQvOVV145ffTRR+nf//53zW1LLbVUmjp1anr22Wdrbvvqq6/S22+/nRZYYIFqLh4AAAAAAFpOaL799tvngDwG+rzgggvSd999l1ZfffXUqVOn9Pe//z3dfvvtub/5b37zmzR+/Phavc8BAAAAAGCOCs032WSTtM0226RJkyala6+9NnXo0CF17tw57bnnnjlAjwFAI1i/66678oCg++yzTzUXDwAAAAAAM6VjqrILL7wwrbfeeunxxx/PwXg45phj0hdffJErzaMSPcL0/fffP22++ebVXjwAAAAAALSM0Hzs2LGpa9eu6ac//Wm+1CykY8d0zjnnpKOPPjq9//77afHFF0/du3ev5qIBAAAAAKBlheb77bdf7l/+hz/8IXXr1m2a+xdeeOF8AQAAAACAOT40f/PNN3MFeV2BOQAAAAAAtKmBQOeaa64077zzVnOWAAAAAADQOkPz7bbbLr322mvp3nvvreZsAQAAAACg9bVn2WWXXdJLL72UB/z861//mr7//e/nHubzzDNPvY/Zeeedq7kKAAAAAADQMkLzHXbYIV9PnTo1Pffcc/nSGKE5AAAAAABzZGjes2fPas4OAAAAAABab2j+0EMPVXN2AAAAAADQegcCBQAAAACA1qyqleblpkyZkkaMGJHeeOONNG7cuPSzn/0sffvtt+nDDz9Mffr0mVWLBQAAAACAlhWa33LLLenyyy9PH330Uc1tEZq///77aeutt05bbbVVOuuss9I888wzKxYPAAAAAAAtIzS/6KKL0lVXXZWmTp2a2rdvny+TJ0/O90WVefx811135UD96quvTh07zrJidwAAAAAAaL6e5k899VS68sorU6dOndJpp52WnnnmmbTqqqvW3N+/f/90/vnnp86dO6fnnnsu/e1vf6vm4gEAAAAAoOWE5tddd11q165dOvvss9Puu++e5p9//mmm2W677XJwHpXod9xxRzUXDwAAAAAALSc0HzZsWOrRo0fuWd6QTTfdNC288MLptddeq+biAQAAAACg5YTmX375ZVpkkUWaNG1M99VXX1Vz8QAAAAAA0HJC827duqXRo0c3Ol20Znn33XfT9773vWouHgAAAAAAWk5o/v3vfz+NHTs23XXXXQ1Od9ttt6UvvvgirbHGGtVcPAAAAAAAtJzQfO+9985V5Keffnp68MEHp7l/ypQp6eabb873x4ChMVgoAAAAAAC0FB2rObO11lorHXDAAelPf/pTGjBgQJpvvvnSt99+m+/beeed01tvvZUmTJiQg/Vdd901rbvuutVcPAAAAAAAtJzQPBx33HGpd+/e6fLLL0+fffZZze3Dhw/P1126dEkHHXRQOvDAA6u9aAAAAAAAaFmheYi2KzvttFN6/vnn06uvvprGjRuXOnfunJZccslcjR4/AwAAAADAHB2ajx49OvXp0yf/PNdcc6W11147XwAAAAAAoM0NBLr55pvnwUBvu+22NGnSpGrOGgAAAAAAWldoHp599tl00kknpfXWWy9fx+8AAAAAANDmQvOHH344HXPMMWnppZdOEydOTLfeemvaZ5990mabbZb+8Ic/pPfff7+aiwMAAAAAgJYbmi+66KLpoIMOSnfeeWcOzKNVS/fu3XOv88svvzxtuumm6ec//3m644470tdff13NRQMAAAAAQMtrz1Ky0korpZNPPjk9+uijafDgwWmrrbZK88wzT3riiSfSCSeckNu3nHLKKbNk2UcddVTaYIMN6rzv6KOPTssvv3ydl2233XaWrA8AAAAAAK1Dx1m9gA4dOqQNN9wwX2Jw0Jtvvjldeumlafz48fnn008/varLGzhwYLrnnnvSIossUuf9L7/8clpggQVyFXylqIoHAAAAAKDtmuWhefj000/TXXfdle677770wgsvpMmTJ+fbl1tuuaotI9q9nHHGGTmIr0+E9m+//XZad9110+GHH161ZQMAAAAAMGeYZaF5DAR6//335/7lTz31VJoyZUqaOnVqrvL+yU9+kn7605/mFi7V8NBDD6Uzzzwzvffee7mi/ZFHHqlzuldeeSWvR7RiAQAAAACAWRqaRwX5v//97xyUR5D91Vdf5aC8ffv26Uc/+lEOyjfZZJM099xzV3Ox6e9//3uaMGFCOvXUU9Mee+yRVlhhhXpbs4T67gcAAAAAoG2ramgewfiYMWNyUB769u2bdtppp7T99tvX22O8Gvbdd990/vnnp/nnn7/B6Uqh+fvvv597mo8cOTKv6w9+8IP0y1/+Mq266qqzbB0BAAAAAGhjofkXX3yR5p133rTVVlvlqvIIo+vz0Ucfpb/97W/piCOOmOnl9u/fv0nTjRo1Kl8PGjQoV7zvsssu6bXXXsvtXB5//PF0+eWXp4033rhJ84oAvl27djO13gBQbSNGjGjuVQCAZuf7EJjR8fKCfQi0bqWC7hYTmp977rlpiy22SJ07d653mgiob7rpptzGJdq5VCM0b6pOnTrl6vfLLrusVouWWKdDDjkknXjiienBBx9stGIdAAAAAIA5U1VD8x122KHO2z///PPcd3zo0KF5sM5S4j+7K7WvueaaOm+PwUO33nrrdOedd6Z//etfadttt210XiuuuGLq0KFDantea+4VAKAB/fr1a+5VaDuGN/cKAFAf34fAjChVmNuHQOsWhdrDhg1rOaF5paeffjpXlT/wwAPpu+++qymNj0r0n/zkJ2nPPfdMLUX0M4/Q/J133mnuVQEAAAAAoJlUPTQfN25cuvXWW3O/8jfffDPfVgrLl1122bT77rvngUFndwuU8ePH5/7l0aKlvDVLyaRJk/J13A8AAAAAQNtUtdD8xRdfTDfeeGO655578sAJpaA8BgadOHFiWmSRRdIdd9yRmssbb7yRdttttxzcR0V5pWeffbam4hwAAAAAgLZppkLzCMMjCI+q8pdffjnfFmF59Pped91103bbbZc23XTTtMYaa8z2/uWVVl555bT44ounV199NfdX33nnnWvui8r4xx57LPes+sEPftCs6wkAAAAAQCsMzU877bQcmEdwXqoqjyrtGEQzLt27d08tSfv27dM555yTDjjggHTyySen+++/Py299NJp5MiR6YknnkgLLbRQuvDCC5s93AcAAAAA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379/2m677dKHH36YHnrooXTsscfm1i3HHHNMkwYTjeAdAFqSESNGNPcqAECz830IzIivv/46X9uHQOs2derUmZ5Hx7b4oi222GLp8MMPTzvuuGPN7aNHj0577LFHGjx4cNpggw3Smmuu2azrCQAAAADA7NfmQvOoJo9LpT59+qQjjjgi/fa3v03/+Mc/Gg3NV1xxxdShQ4fU9rzW3CsAQAP69evX3KvQdgxv7hUAoD6+D4EZUaowtw+B1m3y5Mlp2LBhMzWPNtfTvCHR2zy88847zb0qAAAAAAA0gzYVmk+ZMiUNHz48PfPMM3XeP3HixHzdqVOn2bxmAAAAAAC0BG2uPcvee++dJk2alB5//PG04IIL1rrvueeey9errLJKM60dAAAAAADNqU1Vmrdv3z5tueWWeTDQCy64IFeel4wcOTIPAjrvvPOmnXfeuVnXEwAAAACA5tHmKs2PO+649J///CfddtttadSoUal///7po48+Sg888EAO0S+++OK0yCKLNPdqAgAAAADQDNpUpXmIliw333xz2n///dPYsWPT9ddfn5544om04YYbpr/97W9p8803b+5VBAAAAACgmbS5SvOwwAILpBNPPDFfAAAAAACgzVaaAwAAAABAfYTmAAAAAABQEJoDAAAAAEBBaA4AAAAAAAWhOQAAAAAAFITmAAAAAABQEJoDAAAAAEBBaA4AAAAAAAWhOQAAAAAAFITmAAAAAABQEJoDAAAAAEBBaA4AAAAAAAWhOQAAAAAAFITmAAAAAABQEJoDAAAAAEBBaA4AAAAAAIWOpR8AAAAAoDWaMGFCGjx4cLr//vvTe++9l+aaa6600korpX333TdtttlmDT728ssvTwMHDmx0GQ8++GDq3bt3+vGPf5yX0ZC11147XXfdddP9PICWQWgOAAAAQKs1fvz4tOeee6ZRo0alfv365Z/HjRuXA/QBAwakY445Jh188MENBtwx3ccff5x/X3jhhWvuGzFiRHr44YfTsssum3r06JFv22efffL86/L3v/89ffjhh+mHP/xh1Z8nMPsIzQEAAABota666qocmO++++7ptNNOS+3atcu3H3nkkWmnnXZKl156adpyyy1T375963x8//798yUC8hDBe/jyyy/TDjvskOadd95cid6pU6d8+3777VfnfO67774cmK+//vrpsMMOm0XPFpgd9DQHAAAAoNW65557clB+7LHH1gTmYZFFFkl77LFHmjx5cnrkkUeme75nnHFGev/999OvfvWrtMQSSzQ47WeffZZ++9vfpq5du6Zzzjmn1noArY9KcwAAAABarehbHu1SIrCuNPfcc9f0PJ8e//nPf9Idd9yRVl999bTbbrs1Ov0ll1ySK9NPPfXUtNBCC03XsoCWR2gOAAAAQKu111571Xn71KlTc1/zsPzyy0/XPM8999x8HVXmjVWNv/LKK7mX+VJLLdWkgB1o+bRnAQAAAGCOc8MNN6QXX3wx9enTJ/cZb6qnn346Py4G8/z+97/f6PR/+ctf0pQpU/Jgox06dJjJtQZaAqE5AAAAAHOUu+++O5111lmpY8eOuWp8rrnmavJjr7nmmnx9yCGHNDrtJ598ku68887Uu3fvtO22287UOgMth9AcAAAAgDmqwjwGBQ3nnXdeWnPNNZv82LFjx+ZBQ6PVyjrrrNPo9BGYf/vtt7ktSwT0wJzBpxkAAACAVi9apJx//vnp6quvzgOAXnjhhWnzzTefrnk8++yzafLkyWmbbbZp0vQPPPBA7nne1OmB1kFoDgAAAECr9s033+Tq8hj4s1u3bmnQoEHTVWFeHpqHrbfeutFpx4wZk55//vm02mqrpcUWW2yG1htomYTmAAAAALRaURl+5JFHpoceeij3Fr/qqqtye5UZ8corr6QePXo06fEvvPBCXvaMhPNAy6anOQAAAACt1pVXXpkD8169euV+5jMamH/66ae5enyllVZq0vTDhw/P1/369Zuh5QEtl0pzAAAAAFqlCLkjNA8rrrhiGjp0aJ3TRTV4DOz59NNPp2eeeSZPu+mmm9aa5oMPPsjXiyyySJOW/c4770zX9EDrITQHAAAAoFV67rnn0sSJE/PPDz74YL7U5ZBDDsmheQTmAwcOTDvuuOM0ofnYsWPzdZcuXZq07M8//zxfd+3adSafBdDSCM0BAAAAaJUi+B41alSTpz/88MPzpS7rrbdevjS13Ur0TgfmTHqaAwAAAABAQWgOAAAAAAAF7VkAAACAGfL49js19ypA1T3e3CsAVbTe/93S3KvQKqk0BwAAAACAgtAcAAAAAAAKQnMAAACA/6+984Cyq6za8EHhFxV7FxULioKKgBRFEOkiEiVANCBGUGroBqRIR4OooRgFaQFBQEUBIfQiGAMWQGkqKiqKYkPAhgj+6/m876wvh3vvTEKSyWSeZ627ZnLLOd85k3X33u+3i4iISAdFcxERERERERERERGRDormIiIiIiIiIiIiIiIdFM1FRERERERERERERDoomouIiIiIiIiIiIiIdFA0FxERERERERERERHpoGguIiIiIiIiIiIiItJB0VxEREREREREREREpIOiuYiIiIiIiIiIiIhIB0VzEREREREREREREZEOiuYiIiIiIiIiIiIiIh0UzUVEREREREREREREOiiai4iIiIiIiIiIiIh0UDQXEREREREREREREemgaC4iIiIiIiIiIiIi0kHRXERERERERERERESkg6K5iIiIiIiIiIiIiEgHRXMRERERERERERERkQ6K5iIiIiIiIiIiIiIiHRTNRUREREREREREREQ6KJqLiIiIiIiIiIiIiHRQNBcRERERERERERER6aBoLiIiIiIiIiIiIiLSQdFcRERERERERERERKSDormIiIiIiIiIiIiISAdFcxERERERERERERGRDormIiIiIiIiIiIiIiIdFM1FRERERERERERERDoomouIiIiIiIiIiIiIdFA0FxERERERERERERHpoGguIiIiIiIiIiIiItJB0VxEREREREREREREpIOiuYiIiIiIiIiIiIhIB0VzEREREREREREREZEOiuYiIiIiIiIiIiIiIh0UzUVEREREREREREREOiiai4iIiIiIiIiIiIh0UDQXEREREREREREREemgaC4iIiIiIiIiIiIi0kHRXERERERERERERESkg6K5iIiIiIiIiIiIiEgHRXMRERERERERERERkQ6K5iIiIiIiIiIiIiIiHRTNRUREREREREREREQ6KJqLiIiIiIiIiIiIiIx20fy8885rNt1002aFFVZo3vKWtzQf/ehHm9/+9rfDvSwRERERERERERERGUZGpWg+ZcqUZp999mkeeuihZvz48UU0nz59ejN27Njm7rvvHu7liYiIiIiIiIiIiMgwsWgzyvjxj3/cHH/88c1KK63UTJs2rfm///u/8vw73/nOZuLEic0RRxxRXhcRERERERERERGR0ceoyzQ//fTTy8+dd955QDCH9dZbr1l55ZWba665prn33nuHcYUiIiIiIiIiIiIiMlyMukzz66+/vll00UWLQN5mtdVWa773ve+V94wZM+Yxr//3v/8d+P2RRx5pRiOLPXGR4V6CiIj0YbTap+FgsUVGnRslIjJi0B7ORxZbbLhXICIifRiNNvGR6pprPXd2GFXR3r///e/mnnvuaZZccslZsszDS1/60vLzF7/4RdfPP/roowO/33LLLc1oZP9xSw73EkREpA8333zzcC9h1LDnqyYM9xJERKQH2sP5x+L7ThruJYiISB9Gu018tNJzZ4dR1Z7l/vvvL7sLz3jGM7q+/rSnPa38fPDBB+fzykRERERERERERERkQWBUZZo//PDD5We3LPP6+Yceeqjr67R1ecMb3lB+f8ITntAssoitSkREREREREREREQWFEiaToY5eu6cMKpE88UXX3wW8bxb+xZ4ylOe0vV1hPJegruIiIiIiIiIiIiIjHxGVXuWJZZYogjfvdqv5Pm0aRERERERERERERGR0cWoEs3JEmfYJ8NAu2Wb33333eXn0ksvPQyrExEREREREREREZHhZlSJ5rDKKqsUwfzGG298zGszZ84sfcpXXHHFYVmbiIiIiIiIiIiIiAwvo040Hzt2bPk5ZcqU5l//+tfA85dffnnz/e9/v1l77bWbF77whcO4QhEREREREREREREZLhb5L+NERxmHHnpoc+aZZzYvf/nLm3XWWae59957m4svvrh51rOe1Zx99tmlhYuIiIiIiIiIiIiIjD5GpWjOJSOan3POOc0vf/nL5pnPfGaz6qqrNrvttpuCuYiIiIiIiIiIiMgoZlSK5iIyejj99NPLEOD3vOc9zeKLLz7cyxEREZkv/POf/2ye9KQnNU94wv+6MW633XbN6173uvLzqU996nAvT0REZFi44447mr/85S/Naqut1jzxiU8c7uWIyALMqOtpLiILL8wpuPrqq5s//OEPszw/derU0npJRERkNHDTTTc1F154YfPXv/514Dk2j88///zm1FNPHda1iYiIzCseeeSR5u67725+9KMfNT/96U8Hnn/00UdLxwH41re+1eyzzz7NV7/61YHXRES6sWjXZ0VERhj/+Mc/mgMPPLC58847m6OOOqp5/vOfXxygrbfeunnggQeaE088sbRiQjTg+WTeiYiILEgQ1C+yyCLl94cffrhZbLHFZuvzv/rVr5qPfexjzdOf/vTmrW9968AxN9poo+Z3v/td88UvfrF57nOf27zvfe+b5VwiIiIjidqGnXvuuc15553X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ufXWW0tJ+sYbb1ymllOGXnP11Vc3u+66a7PFFls0EydOLNkCiAaDBft1f1UzAkREZDjRDoqIiIiIiMjcxEzzhQB2+umxSv/VmTNnFoGArDuCfvqvMoV8vfXWK5PGu5XYMeTsV7/6VREA+Ew9bKxfdpz9VUVEZEFAOygiIjJ/wEbyGOoQUBERkZGKlm4hgfLy8ePHN2PGjGn++c9/lh6r/RyZZM7Rb5VBZA888EBz//33l1L3fiKBiIjIgoh2UEREZN5DdZXtVEREZDSgtVuIQACgrJzgH6GAf9OXNRlzNREDGFpGptztt9/e/OEPfxiGVYuIiMwdtIMiIiIiIiIyN7Cn+SiHbLzrrruuefjhh5s11lijZNyJiIiMFrSDIiIiIiIi0kbRXERERERERERERESkg+1ZREREREREREREREQ6KJqLiIiIiIiIiIiIiHRQNBcRERERERERERER6aBoLiIiIiIiIiIiIiLSQdFcRERERERERERERKSDormIiIiIiIiIiIiISAdFcxERERERERERERGRDormIiIiIiIiIiIiIiIdFM1FRERERERERERERDoomouIiIiIiIiIiIiIdFA0FxERERERERERERHpoGguIiIiIiIiIiIiItJB0VxEREREREREREREpIOiuYiIiIiIiIiIiIhIB0VzEREREREREREREZHmf/w/G+MO/ttO0GsAAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 1500x900 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Plot displayed.\n"
]
}
],
"source": [
"\"\"\"\n",
"EMD Speed Comparison: OpenCV (CPU) vs. POT Library (PyTorch MPS on Apple Silicon)\n",
"\n",
"This script benchmarks the computation of the Earth Mover's Distance (EMD).\n",
"\n",
"It now includes three methods:\n",
"1. OpenCV (`cv2.EMD`): Using its internal L2 distance calculation.\n",
"2. OpenCV (`cv2.EMD`): Using a user-provided custom distance matrix.\n",
"3. POT (`ot.emd2`): Using a pre-computed distance matrix on PyTorch.\n",
"\n",
"This version adds a matplotlib bar chart to visualize the results.\n",
"\"\"\"\n",
"\n",
"import time\n",
"import numpy as np\n",
"import torch\n",
"import cv2\n",
"import ot # Python Optimal Transport (POT) library\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# --- Configuration ---\n",
"N_POINTS = 200\n",
"N_ITERATIONS = 50\n",
"\n",
"def setup_device():\n",
" \"\"\"Checks for MPS availability and sets the device.\"\"\"\n",
" print(\"PyTorch MPS (Apple Silicon GPU) Backend Test\")\n",
" if torch.backends.mps.is_available():\n",
" print(\"MPS is available!\")\n",
" return torch.device(\"mps\")\n",
" else:\n",
" print(\"MPS not available. Using CPU instead.\")\n",
" return torch.device(\"cpu\")\n",
"\n",
"def generate_data_for_pot(num_points, device):\n",
" \"\"\"Generates data for the POT library.\"\"\"\n",
" coords1 = torch.rand(num_points, 2, device=device, dtype=torch.float32)\n",
" coords2 = torch.rand(num_points, 2, device=device, dtype=torch.float32)\n",
" weights1 = torch.rand(num_points, device=device, dtype=torch.float32)\n",
" weights1 = weights1 / weights1.sum()\n",
" weights2 = torch.rand(num_points, device=device, dtype=torch.float32)\n",
" weights2 = weights2 / weights2.sum()\n",
" cost_matrix = ot.dist(coords1, coords2, metric='euclidean')\n",
" return weights1, weights2, cost_matrix, coords1, coords2\n",
"\n",
"def convert_pot_data_to_opencv(weights1, weights2, coords1, coords2):\n",
" \"\"\"Converts POT/PyTorch data to OpenCV/NumPy format.\"\"\"\n",
" w1_np = weights1.cpu().numpy().reshape(-1, 1)\n",
" c1_np = coords1.cpu().numpy()\n",
" w2_np = weights2.cpu().numpy().reshape(-1, 1)\n",
" c2_np = coords2.cpu().numpy()\n",
" signature1 = np.hstack([w1_np, c1_np]).astype(np.float32)\n",
" signature2 = np.hstack([w2_np, c2_np]).astype(np.float32)\n",
" return signature1, signature2, c1_np, c2_np\n",
"\n",
"def benchmark_opencv_internal_dist(sig1, sig2, iterations):\n",
" \"\"\"Benchmarks cv2.EMD using its internal L2 distance.\"\"\"\n",
" print(\"\\n--- Benchmarking OpenCV (Internal L2 Distance) ---\")\n",
" start_time = time.perf_counter()\n",
" for _ in range(iterations):\n",
" emd_val, _, _ = cv2.EMD(sig1, sig2, cv2.DIST_L2)\n",
" end_time = time.perf_counter()\n",
"\n",
" total_time = end_time - start_time\n",
" avg_time = (total_time / iterations) * 1000\n",
" print(f\"OpenCV (Internal Dist) EMD result: {emd_val:.6f}\")\n",
" return avg_time\n",
"\n",
"def benchmark_opencv_custom_cost(sig1, sig2, custom_cost_matrix, iterations):\n",
" \"\"\"Benchmarks cv2.EMD using a user-provided distance matrix.\"\"\"\n",
" print(\"\\n--- Benchmarking OpenCV (Custom Distance Matrix) ---\")\n",
" # IMPORTANT: Ensure the cost matrix is of type np.float32\n",
" cost_matrix_f32 = custom_cost_matrix.astype(np.float32)\n",
"\n",
" start_time = time.perf_counter()\n",
" for _ in range(iterations):\n",
" # Use cv2.DIST_USER and pass the matrix to the `cost` parameter\n",
" emd_val, _, _ = cv2.EMD(sig1, sig2, cv2.DIST_USER, cost=cost_matrix_f32)\n",
" end_time = time.perf_counter()\n",
"\n",
" total_time = end_time - start_time\n",
" avg_time = (total_time / iterations) * 1000\n",
" print(f\"OpenCV (Custom Dist) EMD result: {emd_val:.6f}\")\n",
" return avg_time\n",
"\n",
"def benchmark_pot_mps(a, b, M, iterations):\n",
" \"\"\"Benchmarks the POT ot.emd2 function on the MPS device.\"\"\"\n",
" print(\"\\n--- Benchmarking POT (PyTorch MPS) ---\")\n",
" print(\"Performing a warm-up run...\")\n",
" _ = ot.emd2(a, b, M)\n",
" torch.mps.synchronize()\n",
" print(\"Warm-up complete.\")\n",
"\n",
" start_time = time.perf_counter()\n",
" for _ in range(iterations):\n",
" emd_val = ot.emd2(a, b, M)\n",
" torch.mps.synchronize()\n",
" end_time = time.perf_counter()\n",
"\n",
" total_time = end_time - start_time\n",
" avg_time = (total_time / iterations) * 1000\n",
" print(f\"POT EMD result: {emd_val.item():.6f}\")\n",
" return avg_time\n",
"\n",
"def plot_results(times, labels):\n",
" \"\"\"Visualizes the benchmark results using a bar chart.\"\"\"\n",
" print(\"\\nGenerating plot...\")\n",
" plt.style.use('seaborn-v0_8-whitegrid')\n",
" fig, ax = plt.subplots(figsize=(10, 6), dpi=150)\n",
"\n",
" colors = ['#4c72b0', '#55a868', '#c44e52']\n",
" bars = ax.bar(labels, times, color=colors[:len(labels)])\n",
"\n",
" ax.set_ylabel('Average Time (ms)', fontsize=12)\n",
" ax.set_title(f'EMD Computation Time Comparison (N={N_POINTS})', fontsize=14, fontweight='bold')\n",
" ax.set_xticks(range(len(labels)))\n",
" ax.set_xticklabels(labels, rotation=8, ha='right')\n",
" \n",
" # Add text labels on top of each bar\n",
" for bar in bars:\n",
" yval = bar.get_height()\n",
" ax.text(bar.get_x() + bar.get_width()/2.0, yval, f'{yval:.2f}', va='bottom', ha='center', fontsize=10)\n",
"\n",
" plt.tight_layout()\n",
" plt.show()\n",
" print(\"Plot displayed.\")\n",
"\n",
"if __name__ == \"__main__\":\n",
" print(\"Starting EMD Speed Comparison...\")\n",
" print(f\"Distribution Size (N_POINTS): {N_POINTS}\")\n",
" print(f\"Benchmark Iterations: {N_ITERATIONS}\\n\")\n",
"\n",
" # 1. Set up device\n",
" pytorch_device = setup_device()\n",
"\n",
" # 2. Generate data for POT on the target device\n",
" pot_weights1, pot_weights2, pot_cost_matrix, pot_coords1, pot_coords2 = generate_data_for_pot(\n",
" N_POINTS, pytorch_device\n",
" )\n",
"\n",
" # 3. Convert data for OpenCV\n",
" opencv_sig1, opencv_sig2, coords1_np, coords2_np = convert_pot_data_to_opencv(\n",
" pot_weights1, pot_weights2, pot_coords1, pot_coords2\n",
" )\n",
" \n",
" # 4. Create the custom cost matrix for OpenCV\n",
" print(\"\\nGenerating custom cost matrix for OpenCV...\")\n",
" custom_cost_matrix_np = pot_cost_matrix.detach().cpu().numpy()\n",
" print(\"Done.\")\n",
"\n",
" # 5. Run Benchmarks\n",
" opencv_internal_time = benchmark_opencv_internal_dist(opencv_sig1, opencv_sig2, N_ITERATIONS)\n",
" opencv_custom_time = benchmark_opencv_custom_cost(opencv_sig1, opencv_sig2, custom_cost_matrix_np, N_ITERATIONS)\n",
" \n",
" pot_mps_time = -1\n",
" if pytorch_device.type == 'mps':\n",
" pot_mps_time = benchmark_pot_mps(pot_weights1, pot_weights2, pot_cost_matrix, N_ITERATIONS)\n",
" \n",
" # 6. Print Final Comparison\n",
" print(\"\\n\" + \"=\"*50)\n",
" print(\" Benchmark Results\")\n",
" print(\"=\"*50)\n",
" print(f\"OpenCV (Internal Dist) Avg Time: {opencv_internal_time:>12.4f} ms\")\n",
" print(f\"OpenCV (Custom Dist) Avg Time: {opencv_custom_time:>12.4f} ms\")\n",
" \n",
" # Prepare data for plotting\n",
" times = [opencv_internal_time, opencv_custom_time]\n",
" labels = ['OpenCV (Internal Dist)', 'OpenCV (Custom Dist)']\n",
" \n",
" if pot_mps_time != -1:\n",
" print(f\"POT (PyTorch MPS) Avg Time: {pot_mps_time:>12.4f} ms\")\n",
" times.append(pot_mps_time)\n",
" labels.append('POT (PyTorch MPS)')\n",
" print(\"=\"*50)\n",
" \n",
" # 7. Visualize results\n",
" plot_results(times, labels)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5a30fe63-f181-467b-a2b4-ced42e7da007",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.12.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment