{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import networkx as nx\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import scipy.stats as sts\n",
    "import seaborn as sns\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "#import conviction files\n",
    "from conviction_helpers import *\n",
    "from conviction_system_logic3 import *\n",
    "from bonding_curve_eq import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook uses the differential games framework developed by BlockScience. It is currently in private beta, and building towards a full open source release.\n",
    "\n",
    "**Description:**\n",
    "\n",
    "cadCAD is a Python library that assists in the processes of designing, testing and validating complex systems through simulation. At its core, cadCAD is a differential games engine that supports parameter sweeping and Monte Carlo analyses and can be easily integrated with other scientific computing Python modules and data science workflows.\n",
    "\n",
    "To learn more about cadCAD, follow our [tutorial series](https://github.com/BlockScience/cadCAD-Tutorials/tree/master/01%20Tutorials)\n",
    "\n",
    "**Installing cadCAD:**\n",
    "\n",
    "cadCAD is in private beta. Tokens are issued to participants. Replace `<TOKEN>` in the installation URL below\n",
    "```bash\n",
    "pip3 install cadCAD --extra-index-url https://<TOKEN>@repo.fury.io/blockscience/\n",
    "```\n",
    "\n",
    "If you'd like to participate in the beta program, contact cadcad [at] block [dot] science.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#THIS policy is one of the main paramters of this system!\n",
    "\n",
    "#maximum share of funds a proposal can take\n",
    "default_beta = .2 #later we should set this to be param so we can sweep it\n",
    "# tuning param for the trigger function\n",
    "default_rho = .5*default_beta**2\n",
    "\n",
    "def trigger_threshold(requested, funds, supply, beta=default_beta , rho=default_rho):\n",
    "    \n",
    "    share = requested/funds\n",
    "    if share < beta:\n",
    "        return rho*supply/(beta-share)**2\n",
    "    else: \n",
    "        return np.inf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/Zargham/Documents/GitHub/conviction/conviction_helpers.py:212: RuntimeWarning: divide by zero encountered in log10\n",
      "  demo_data_Z0[sof_ind,ts_ind] = np.log10(trigger)\n",
      "/Users/Zargham/Documents/GitHub/conviction/conviction_helpers.py:214: RuntimeWarning: invalid value encountered in double_scalars\n",
      "  demo_data_Z2[sof_ind,ts_ind] = trigger/tc #share of maximum possible conviction\n",
      "/Users/Zargham/Documents/GitHub/conviction/conviction_helpers.py:215: RuntimeWarning: invalid value encountered in double_scalars\n",
      "  demo_data_Z3[sof_ind,ts_ind] = np.log10(trigger/tc)\n"
     ]
    }
   ],
   "source": [
    "dict1 = trigger_sweep('token_supply',trigger_threshold)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.15940000000000001, 1008990000.0, 'fixed alpha = 0.5')"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 35316 characters]\n",
      "text/plain": [
       "<Figure size 720x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "trigger_plotter(dict1['share_of_funds'],\n",
    "                dict1['log10_trigger'], \n",
    "                'log10_trigger',\n",
    "                dict1['total_supply'],\n",
    "                'Token Supply')\n",
    "axis = plt.axis()\n",
    "plt.text(.2*axis[0]+.8*axis[1],axis[-1]*1.01, 'fixed alpha = 0.5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "dict2 = trigger_sweep('alpha',trigger_threshold)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['log10_trigger', 'trigger', 'share_of_max_conv', 'log10_share_of_max_conv', 'alpha', 'share_of_funds'])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict2.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 30888 characters]\n",
      "text/plain": [
       "<Figure size 720x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "trigger_plotter(dict2['share_of_funds'],\n",
    "                dict2['log10_share_of_max_conv'], \n",
    "                'Log10 Share of Conviction Required to Pass',\n",
    "                dict2['alpha'],\n",
    "                'alpha')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "n= 60 #initial participants\n",
    "m= 3 #initial proposals\n",
    "\n",
    "initial_sentiment = .6\n",
    "\n",
    "theta =.35\n",
    "kappa = 6\n",
    "sale_price = .1\n",
    "\n",
    "def TFGTS(total_supply):\n",
    "    #wrap initializer params to pass the function correctly\n",
    "    return total_funds_given_total_supply(total_supply, theta = theta, initial_price = sale_price) \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "#initializers\n",
    "network, initial_funds, initial_supply, total_requested = initialize_network(n,m,TFGTS,trigger_threshold)\n",
    "initial_reserve, invariant, initial_price= initialize_bonding_curve(initial_supply, initial_price = sale_price, kappa =kappa, theta = theta)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.7955407857599857e+31"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "invariant"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "proposals = get_nodes_by_type(network, 'proposal')\n",
    "participants = get_nodes_by_type(network, 'participant')\n",
    "\n",
    "supporters = get_edges_by_type(network, 'support')\n",
    "influencers = get_edges_by_type(network, 'influence')\n",
    "competitors = get_edges_by_type(network, 'conflict')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "67040.16629275207"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "initial_reserve"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "36098.55108071265"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "initial_funds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'type': 'proposal',\n",
       " 'conviction': 0,\n",
       " 'status': 'candidate',\n",
       " 'age': 0,\n",
       " 'funds_requested': 11443.91427929522,\n",
       " 'trigger': inf}"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#sample proposal\n",
    "network.nodes[proposals[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'type': 'participant',\n",
       " 'holdings': 5718.0718806896575,\n",
       " 'sentiment': 0.17859148389446788}"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#sample participant\n",
    "network.nodes[participants[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'affinity': 0.4047245410553306,\n",
       " 'tokens': 0,\n",
       " 'conviction': 0,\n",
       " 'type': 'support'}"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#sample relationship participant to proposal\n",
    "network.edges[supporters[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'influence': 4.314493792217198, 'type': 'influence'}"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "network.edges[influencers[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'conflict': 0.8304060260811613, 'type': 'conflict'}"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "network.edges[competitors[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Participants Social Network')"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 111556 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "nx.draw_kamada_kawai(network, nodelist = participants, edgelist=influencers)\n",
    "plt.title('Participants Social Network')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Proposals Conflict Network')"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 8252 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "nx.draw_kamada_kawai(network, nodelist = proposals, edgelist=competitors, node_color='b')\n",
    "plt.title('Proposals Conflict Network')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Histogram of Participants Token Holdings')"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 8656 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist([ network.nodes[i]['holdings'] for i in participants])\n",
    "plt.title('Histogram of Participants Token Holdings')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Histogram of Proposals Funds Requested')"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 8768 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist([ network.nodes[i]['funds_requested'] for i in proposals])\n",
    "plt.title('Histogram of Proposals Funds Requested')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "affinities = np.empty((n,m))\n",
    "for i_ind in range(n):\n",
    "    for j_ind in range(m):\n",
    "        i = participants[i_ind]\n",
    "        j = proposals[j_ind]\n",
    "        affinities[i_ind][j_ind] = network.edges[(i,j)]['affinity']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 137.58, 'participant_id')"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 19612 characters]\n",
      "text/plain": [
       "<Figure size 1440x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "dims = (20, 5)\n",
    "fig, ax = plt.subplots(figsize=dims)\n",
    "\n",
    "sns.heatmap(affinities.T,\n",
    "            xticklabels=participants,\n",
    "            yticklabels=proposals,\n",
    "            square=True,\n",
    "            cbar=True,\n",
    "            ax=ax)\n",
    "\n",
    "plt.title('affinities between participants and proposals')\n",
    "plt.ylabel('proposal_id')\n",
    "plt.xlabel('participant_id')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.5, 0.8, 0.9]\n"
     ]
    }
   ],
   "source": [
    "#power of 1 token forever\n",
    "conviction_capacity = [2,5,10]\n",
    "alpha = [1-1/cc for cc in conviction_capacity]\n",
    "print(alpha)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "params= {\n",
    "    'sensitivity': [.75],\n",
    "    'tmin': [7], #unit days; minimum periods passed before a proposal can pass\n",
    "    'min_supp':[50], #number of tokens that must be stake for a proposal to be a candidate\n",
    "    'sentiment_decay': [.01], #termed mu in the state update function\n",
    "    'alpha': alpha,\n",
    "    'base_completion_rate': [100],\n",
    "    'base_failure_rate': [200],\n",
    "    'trigger_func': [trigger_threshold],\n",
    "    'kappa': [kappa], #bonding curve curvature\n",
    "    'invariant': [invariant], #set by bonding curve choices\n",
    "    'tax_rate': [.02]\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "function"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(trigger_threshold)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
    "# Settings of general simulation parameters, unrelated to the system itself\n",
    "# `T` is a range with the number of discrete units of time the simulation will run for;\n",
    "# `N` is the number of times the simulation will be run (Monte Carlo runs)\n",
    "time_periods_per_run = 100\n",
    "monte_carlo_runs = 1\n",
    "\n",
    "from cadCAD.configuration.utils import config_sim\n",
    "simulation_parameters = config_sim({\n",
    "    'T': range(time_periods_per_run),\n",
    "    'N': monte_carlo_runs,\n",
    "    'M': params\n",
    "})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'N': 1,\n",
       "  'T': range(0, 100),\n",
       "  'M': {'sensitivity': 0.75,\n",
       "   'tmin': 7,\n",
       "   'min_supp': 50,\n",
       "   'sentiment_decay': 0.01,\n",
       "   'alpha': 0.5,\n",
       "   'base_completion_rate': 100,\n",
       "   'base_failure_rate': 200,\n",
       "   'trigger_func': <function __main__.trigger_threshold(requested, funds, supply, beta=0.2, rho=0.020000000000000004)>,\n",
       "   'kappa': 6,\n",
       "   'invariant': 1.7955407857599857e+31,\n",
       "   'tax_rate': 0.02}},\n",
       " {'N': 1,\n",
       "  'T': range(0, 100),\n",
       "  'M': {'sensitivity': 0.75,\n",
       "   'tmin': 7,\n",
       "   'min_supp': 50,\n",
       "   'sentiment_decay': 0.01,\n",
       "   'alpha': 0.8,\n",
       "   'base_completion_rate': 100,\n",
       "   'base_failure_rate': 200,\n",
       "   'trigger_func': <function __main__.trigger_threshold(requested, funds, supply, beta=0.2, rho=0.020000000000000004)>,\n",
       "   'kappa': 6,\n",
       "   'invariant': 1.7955407857599857e+31,\n",
       "   'tax_rate': 0.02}},\n",
       " {'N': 1,\n",
       "  'T': range(0, 100),\n",
       "  'M': {'sensitivity': 0.75,\n",
       "   'tmin': 7,\n",
       "   'min_supp': 50,\n",
       "   'sentiment_decay': 0.01,\n",
       "   'alpha': 0.9,\n",
       "   'base_completion_rate': 100,\n",
       "   'base_failure_rate': 200,\n",
       "   'trigger_func': <function __main__.trigger_threshold(requested, funds, supply, beta=0.2, rho=0.020000000000000004)>,\n",
       "   'kappa': 6,\n",
       "   'invariant': 1.7955407857599857e+31,\n",
       "   'tax_rate': 0.02}}]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "simulation_parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "initial_conditions = {'network':network,\n",
    "                      'supply': initial_supply,\n",
    "                      'funds':initial_funds,\n",
    "                      'reserve': initial_reserve,\n",
    "                      'spot_price': initial_price,\n",
    "                      'sentiment': initial_sentiment}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'network': <networkx.classes.digraph.DiGraph at 0x1a1cec28d0>,\n",
       " 'supply': 1031387.173734647,\n",
       " 'funds': 36098.55108071265,\n",
       " 'reserve': 67040.16629275207,\n",
       " 'spot_price': 0.3900000000000005,\n",
       " 'sentiment': 0.6}"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "initial_conditions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
    "# The Partial State Update Blocks\n",
    "partial_state_update_blocks = [\n",
    "    { \n",
    "        'policies': { \n",
    "            #new proposals or new participants\n",
    "            'random': driving_process\n",
    "        },\n",
    "        'variables': {\n",
    "            'network': update_network,\n",
    "            'funds':increment_funds,\n",
    "            'supply':increment_supply,\n",
    "            'reserve': increment_reserve\n",
    "        }\n",
    "    },\n",
    "    {\n",
    "      'policies': {\n",
    "          'completion': check_progress #see if any of the funded proposals completes\n",
    "        },\n",
    "        'variables': { # The following state variables will be updated simultaneously\n",
    "            'sentiment': update_sentiment_on_completion, #note completing decays sentiment, completing bumps it\n",
    "            'network': complete_proposal #book-keeping\n",
    "        }\n",
    "    },\n",
    "        {\n",
    "      'policies': {\n",
    "          'release': trigger_function #check each proposal to see if it passes\n",
    "        },\n",
    "        'variables': { # The following state variables will be updated simultaneously\n",
    "            'funds': decrement_funds, #funds expended\n",
    "            'sentiment': update_sentiment_on_release, #releasing funds can bump sentiment\n",
    "            'network': update_proposals #reset convictions, and participants sentiments\n",
    "                                        #update based on affinities\n",
    "        }\n",
    "    },\n",
    "    { \n",
    "        'policies': { \n",
    "            #currently naive decisions; future: strategic\n",
    "            'participants_act': participants_decisions, #high sentiment, high affinity =>buy\n",
    "                                                        #low sentiment, low affinities => burn\n",
    "                                                        #assign tokens to top affinities\n",
    "        },\n",
    "        'variables': {\n",
    "            'supply': update_supply, #book-keeping from participants decisions\n",
    "            'reserve': update_reserve, #funds under the bonding curve\n",
    "            'spot_price': update_price, #new bonding curve spot price\n",
    "            'funds': update_funds, #capture taxes\n",
    "            'network': update_tokens #update everyones holdings \n",
    "                                    #and their conviction for each proposal\n",
    "        }\n",
    "    }\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "from cadCAD.configuration import append_configs\n",
    "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\n",
    "# The configurations above are then packaged into a `Configuration` object\n",
    "append_configs(\n",
    "    initial_state=initial_conditions, #dict containing variable names and initial values\n",
    "    partial_state_update_blocks=partial_state_update_blocks, #dict containing state update functions\n",
    "    sim_configs=simulation_parameters #dict containing simulation parameters\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tabulate import tabulate\n",
    "from cadCAD.engine import ExecutionMode, ExecutionContext, Executor\n",
    "from cadCAD import configs\n",
    "import pandas as pd\n",
    "\n",
    "exec_mode = ExecutionMode()\n",
    "multi_proc_ctx = ExecutionContext(context=exec_mode.multi_proc)\n",
    "run = Executor(exec_context=multi_proc_ctx, configs=configs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "multi_proc: [<cadCAD.configuration.Configuration object at 0x1a1d8d0ef0>, <cadCAD.configuration.Configuration object at 0x1a1d3baa90>, <cadCAD.configuration.Configuration object at 0x1a1d8e60b8>]\n",
      "[<cadCAD.configuration.Configuration object at 0x1a1d8d0ef0>, <cadCAD.configuration.Configuration object at 0x1a1d3baa90>, <cadCAD.configuration.Configuration object at 0x1a1d8e60b8>]\n"
     ]
    }
   ],
   "source": [
    "i = 0\n",
    "verbose = False\n",
    "results = {}\n",
    "for raw_result, tensor_field in run.execute():\n",
    "    result = pd.DataFrame(raw_result)\n",
    "    if verbose:\n",
    "        print()\n",
    "        print(f\"Tensor Field: {type(tensor_field)}\")\n",
    "        print(tabulate(tensor_field, headers='keys', tablefmt='psql'))\n",
    "        print(f\"Output: {type(result)}\")\n",
    "        print(tabulate(result, headers='keys', tablefmt='psql'))\n",
    "        print()\n",
    "    results[i] = {}\n",
    "    results[i]['result'] = result\n",
    "    results[i]['simulation_parameters'] = simulation_parameters[i]\n",
    "    i += 1\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[6]"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "params['kappa']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'sensitivity': [0.75],\n",
       " 'tmin': [7],\n",
       " 'min_supp': [50],\n",
       " 'sentiment_decay': [0.01],\n",
       " 'alpha': [0.5, 0.8, 0.9],\n",
       " 'base_completion_rate': [100],\n",
       " 'base_failure_rate': [200],\n",
       " 'trigger_func': [<function __main__.trigger_threshold(requested, funds, supply, beta=0.2, rho=0.020000000000000004)>],\n",
       " 'kappa': [6],\n",
       " 'invariant': [1.7955407857599857e+31],\n",
       " 'tax_rate': [0.02]}"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "params"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.5, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a1b921bf8>, 'kappa': 6, 'invariant': 1.7955407857599857e+31, 'tax_rate': 0.02}}\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 15756 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.8, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a1b921bf8>, 'kappa': 6, 'invariant': 1.7955407857599857e+31, 'tax_rate': 0.02}}\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 10652 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'N': 1, 'T': range(0, 100), 'M': {'sensitivity': 0.75, 'tmin': 7, 'min_supp': 50, 'sentiment_decay': 0.01, 'alpha': 0.9, 'base_completion_rate': 100, 'base_failure_rate': 200, 'trigger_func': <function trigger_threshold at 0x1a1b921bf8>, 'kappa': 6, 'invariant': 1.7955407857599857e+31, 'tax_rate': 0.02}}\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 11540 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "for ind in range(len(results)):\n",
    "    r=results[ind]['result']\n",
    "    print(results[ind]['simulation_parameters'])\n",
    "    r.plot(x='timestep', y='funds')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [],
   "source": [
    "#I ran multiple experiments above, pick1\n",
    "experiment_index = 2\n",
    "df = results[experiment_index]['result']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['conviction'] = df.network.apply(lambda g: np.array([g.nodes[j]['conviction'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate']))\n",
    "df['candidate_count'] = df.network.apply(lambda g: len([j for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate']))\n",
    "df['candidate_funds'] = df.network.apply(lambda g: np.sum([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate']))\n",
    "df['killed_count'] = df.network.apply(lambda g: len([j for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='killed']))\n",
    "df['killed_funds'] = df.network.apply(lambda g: np.sum([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='killed']))\n",
    "df['candidate_funds_requested'] = df.network.apply(lambda g: np.array([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate']))\n",
    "df['active_count'] = df.network.apply(lambda g: len([j for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='active']))\n",
    "df['active_funds'] = df.network.apply(lambda g: np.sum([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='active']))\n",
    "df['failed_count'] = df.network.apply(lambda g: len([j for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='failed']))\n",
    "df['failed_funds'] = df.network.apply(lambda g: np.sum([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='failed']))\n",
    "df['completed_count'] = df.network.apply(lambda g: len([j for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='completed']))\n",
    "df['completed_funds'] = df.network.apply(lambda g: np.sum([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='completed']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['funds_requested'] = df.network.apply(lambda g: np.array([g.nodes[j]['funds_requested'] for j in get_nodes_by_type(g, 'proposal')]))\n",
    "df['share_of_funds_requested'] = df.candidate_funds_requested/df.funds\n",
    "\n",
    "df['share_of_funds_requested_all'] = df.funds_requested/df.funds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['triggers'] = df.network.apply(lambda g: np.array([g.nodes[j]['trigger'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate' ]))\n",
    "df['conviction_share_of_trigger'] = df.conviction/df.triggers\n",
    "df['age'] = df.network.apply(lambda g: np.array([g.nodes[j]['age'] for j in get_nodes_by_type(g, 'proposal') if g.nodes[j]['status']=='candidate' ]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['age_all'] = df.network.apply(lambda g: np.array([g.nodes[j]['age'] for j in get_nodes_by_type(g, 'proposal') ]))\n",
    "df['conviction_all'] = df.network.apply(lambda g: np.array([g.nodes[j]['conviction'] for j in get_nodes_by_type(g, 'proposal') ]))\n",
    "df['triggers_all'] = df.network.apply(lambda g: np.array([g.nodes[j]['trigger'] for j in get_nodes_by_type(g, 'proposal')  ]))\n",
    "\n",
    "df['conviction_share_of_trigger_all'] = df.conviction_all/df.triggers_all"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [],
   "source": [
    "rdf= df[df.substep==4].copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>funds</th>\n",
       "      <th>supply</th>\n",
       "      <th>reserve</th>\n",
       "      <th>spot_price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>36098.551081</td>\n",
       "      <td>1.031387e+06</td>\n",
       "      <td>67040.166293</td>\n",
       "      <td>0.390000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>36100.064380</td>\n",
       "      <td>1.031387e+06</td>\n",
       "      <td>67040.166293</td>\n",
       "      <td>0.390000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>36100.064380</td>\n",
       "      <td>1.031387e+06</td>\n",
       "      <td>67040.166293</td>\n",
       "      <td>0.390000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>36100.064380</td>\n",
       "      <td>1.031387e+06</td>\n",
       "      <td>67040.166293</td>\n",
       "      <td>0.390000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>36100.073955</td>\n",
       "      <td>1.031411e+06</td>\n",
       "      <td>67049.592773</td>\n",
       "      <td>0.390046</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>36101.408899</td>\n",
       "      <td>1.031411e+06</td>\n",
       "      <td>67049.592773</td>\n",
       "      <td>0.390046</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>36101.408899</td>\n",
       "      <td>1.031411e+06</td>\n",
       "      <td>67049.592773</td>\n",
       "      <td>0.390046</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>36101.408899</td>\n",
       "      <td>1.031411e+06</td>\n",
       "      <td>67049.592773</td>\n",
       "      <td>0.390046</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>36101.813061</td>\n",
       "      <td>1.031403e+06</td>\n",
       "      <td>67046.482855</td>\n",
       "      <td>0.390031</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>36103.530070</td>\n",
       "      <td>1.031403e+06</td>\n",
       "      <td>67046.482855</td>\n",
       "      <td>0.390031</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          funds        supply       reserve  spot_price\n",
       "0  36098.551081  1.031387e+06  67040.166293    0.390000\n",
       "1  36100.064380  1.031387e+06  67040.166293    0.390000\n",
       "2  36100.064380  1.031387e+06  67040.166293    0.390000\n",
       "3  36100.064380  1.031387e+06  67040.166293    0.390000\n",
       "4  36100.073955  1.031411e+06  67049.592773    0.390046\n",
       "5  36101.408899  1.031411e+06  67049.592773    0.390046\n",
       "6  36101.408899  1.031411e+06  67049.592773    0.390046\n",
       "7  36101.408899  1.031411e+06  67049.592773    0.390046\n",
       "8  36101.813061  1.031403e+06  67046.482855    0.390031\n",
       "9  36103.530070  1.031403e+06  67046.482855    0.390031"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[['funds','supply', 'reserve','spot_price']].head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1.7955407857599857e+31]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0    1.795541e+31\n",
       "1    1.795541e+31\n",
       "2    1.795541e+31\n",
       "3    1.795541e+31\n",
       "4    1.795541e+31\n",
       "5    1.795541e+31\n",
       "6    1.795541e+31\n",
       "7    1.795541e+31\n",
       "8    1.795541e+31\n",
       "9    1.795541e+31\n",
       "Name: invar, dtype: float64"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(params['invariant'])\n",
    "df['invar'] = df.supply**kappa/df.reserve\n",
    "df.invar.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>supply</th>\n",
       "      <th>reserve</th>\n",
       "      <th>spot_price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>24.169046</td>\n",
       "      <td>9.426480</td>\n",
       "      <td>0.000046</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>-7.973369</td>\n",
       "      <td>-3.109918</td>\n",
       "      <td>-0.000015</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      supply   reserve  spot_price\n",
       "0        NaN       NaN         NaN\n",
       "1   0.000000  0.000000    0.000000\n",
       "2   0.000000  0.000000    0.000000\n",
       "3   0.000000  0.000000    0.000000\n",
       "4  24.169046  9.426480    0.000046\n",
       "5   0.000000  0.000000    0.000000\n",
       "6   0.000000  0.000000    0.000000\n",
       "7   0.000000  0.000000    0.000000\n",
       "8  -7.973369 -3.109918   -0.000015\n",
       "9   0.000000  0.000000    0.000000"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[['supply', 'reserve','spot_price']].head(10).diff()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Summary of Local Economy')"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 25700 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax1 = plt.subplots()\n",
    "ax2 = ax1.twinx()  # instantiate a second axes that shares the same x-axis\n",
    "\n",
    "rdf.plot(x='timestep', y=['funds', 'reserve','supply'], ax=ax1)\n",
    "rdf.plot(x='timestep', y='spot_price',style='--',color = 'red', ax=ax2, legend = False)\n",
    "ax2.set_ylabel('Price in xDAI per Token', color='red')\n",
    "ax1.set_ylabel('Quantity of Assets')\n",
    "ax2.tick_params(axis='y', labelcolor='red')\n",
    "plt.title('Summary of Local Economy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1a352c2d68>"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 23332 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "rdf.plot(x='reserve', y='supply', kind='scatter', alpha=.5)\n",
    "axis = plt.axis()\n",
    "xrange = np.arange(axis[0], axis[1], (axis[1]-axis[0])/100)\n",
    "yrange = np.array([supply(x, invariant, kappa) for x in xrange ])\n",
    "plt.plot(xrange, yrange, 'y')\n",
    "plt.title('Bonding Curve Invariant')\n",
    "plt.legend(['Invariant', 'Observed Data'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1a35890e10>"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 21976 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "rdf.plot(x='reserve', y='spot_price', kind='scatter', alpha=.5)\n",
    "axis = plt.axis()\n",
    "xrange = np.arange(axis[0], axis[1], (axis[1]-axis[0])/100)\n",
    "yrange = np.array([spot_price(x, invariant, kappa) for x in xrange ])\n",
    "\n",
    "plt.plot(xrange, yrange, 'y')\n",
    "plt.title('Bonding Curve Price')\n",
    "plt.legend(['Price Curve', 'Observed Price'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [],
   "source": [
    "last_net= df.network.values[-1]\n",
    "last_props=get_nodes_by_type(last_net, 'proposal')\n",
    "M = len(last_props)\n",
    "last_parts=get_nodes_by_type(last_net, 'participant')\n",
    "N = len(last_parts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [],
   "source": [
    "affinities = np.empty((N,M))\n",
    "for i_ind in range(N):\n",
    "    for j_ind in range(M):\n",
    "        i = last_parts[i_ind]\n",
    "        j = last_props[j_ind]\n",
    "        affinities[i_ind][j_ind] = last_net.edges[(i,j)]['affinity']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 67.14155844155843, 'participant_id')"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 33260 characters]\n",
      "text/plain": [
       "<Figure size 1440x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "dims = (20, 5)\n",
    "fig, ax = plt.subplots(figsize=dims)\n",
    "\n",
    "sns.heatmap(affinities.T,\n",
    "            xticklabels=last_parts,\n",
    "            yticklabels=last_props,\n",
    "            square=True,\n",
    "            cbar=True,\n",
    "            ax=ax)\n",
    "\n",
    "plt.title('affinities between participants and proposals')\n",
    "plt.ylabel('proposal_id')\n",
    "plt.xlabel('participant_id')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [],
   "source": [
    "#working on deduplicating colors\n",
    "#\n",
    "#last_props=get_nodes_by_type(last_net, 'proposal')\n",
    "#M = len(last_props)\n",
    "\n",
    "#cm = plt.get_cmap('gist_rainbow')\n",
    "#c= [cm(1.*j/M) for j in range(M)] "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1a37493c88>"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 29172 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "rdf.plot(x='timestep',y=['candidate_count','active_count','completed_count', 'killed_count', 'failed_count'])\n",
    "plt.title('Proposal Status')\n",
    "plt.ylabel('count of proposals')\n",
    "plt.legend(ncol = 3,loc='upper center', bbox_to_anchor=(0.5, -0.15))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1a2cc0fb38>"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 27504 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "rdf.plot(x='timestep',y=['candidate_funds','active_funds','completed_funds', 'killed_funds', 'failed_funds'])\n",
    "plt.title('Proposal Status weighted by funds requested')\n",
    "plt.ylabel('Funds worth of proposals')\n",
    "plt.legend(ncol = 3,loc='upper center', bbox_to_anchor=(0.5, -0.15))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'share_of_funds_requested')"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 21312 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.semilogy(rdf.timestep,make2D('share_of_funds_requested_all', rdf))\n",
    "plt.title('share_of_funds_requested by proposal')\n",
    "plt.xlabel('time $t$')\n",
    "plt.ylabel('share_of_funds_requested')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 0, 'share_of_funds_requested')"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 15704 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.loglog(make2D('share_of_funds_requested_all', rdf), make2D('conviction_all', rdf), '.')\n",
    "plt.ylabel('conviction')\n",
    "plt.xlabel('share_of_funds_requested')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 0, 'proposal_age')"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 15008 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(make2D('age_all', rdf), make2D('triggers_all', rdf))\n",
    "plt.ylabel('triggers')\n",
    "plt.xlabel('proposal_age')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'phase: Triggers & Conviction')"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 19380 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.loglog(make2D('conviction_all', rdf), make2D('triggers_all', rdf))\n",
    "a = plt.axis()\n",
    "plt.loglog(a[:2],a[2:], 'k',alpha=.5 )\n",
    "plt.ylabel('triggers')\n",
    "plt.xlabel('conviction')\n",
    "plt.title('phase: Triggers & Conviction')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.LineCollection at 0x1a34696898>"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 33232 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "T = time_periods_per_run\n",
    "plt.plot(rdf.timestep,make2D('conviction_share_of_trigger_all', rdf))\n",
    "plt.title('conviction_share_of_trigger')\n",
    "plt.xlabel('time $t$')\n",
    "plt.ylabel('conviction_share_of_trigger')\n",
    "plt.hlines(1,0,T, linestyle='--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.LineCollection at 0x1a34b3e080>"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 15736 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.semilogy(make2D('age_all', rdf), make2D('conviction_share_of_trigger_all', rdf))\n",
    "plt.ylabel('triggers')\n",
    "plt.xlabel('proposal_age')\n",
    "plt.hlines(1,0,T, linestyle='--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [],
   "source": [
    "nets = rdf.network.values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 111348 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "K = 3\n",
    "snap_plot(nets[K:K+1], size_scale = 1/300)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 144692 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "K = 56\n",
    "snap_plot(nets[K:K+1], size_scale = 1/300)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "metadata": {},
   "outputs": [],
   "source": [
    "def quantile_plot(xkey, ykey, dataframe, dq=.1, logy=False, return_df = False):\n",
    "    qX = np.arange(0,1+dq,dq)\n",
    "    \n",
    "    data = dataframe[[xkey,ykey]].copy()\n",
    "    \n",
    "    qkeys = []\n",
    "    for q in qX:\n",
    "        qkey= 'quantile'+str(int(100*q))\n",
    "        #print(qkey)\n",
    "        data[qkey] = data[ykey].apply(lambda arr: np.quantile(arr,q) )\n",
    "        #print(data[qkey].head())\n",
    "        qkeys.append(qkey)\n",
    "    \n",
    "    data[[xkey]+qkeys].plot(x=xkey,  logy=logy)\n",
    "        \n",
    "    plt.title(ykey + \" Quantile Plot\" )\n",
    "    plt.ylabel(ykey)\n",
    "    labels = [str(int(100*q))+\"$^{th}$ Percentile\" for q in qX ]\n",
    "    \n",
    "    plt.legend(labels, ncol = 1,loc='center left', bbox_to_anchor=(1, .5))\n",
    "    if return_df:\n",
    "        return data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 64240 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "quantile_plot('timestep','conviction', rdf, .25)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.LineCollection at 0x1a1fc7be10>"
      ]
     },
     "execution_count": 129,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 62620 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "quantile_plot('timestep','conviction_share_of_trigger', rdf, .25)\n",
    "plt.hlines(1,0,T, linestyle='--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
