{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from cadCAD.engine import ExecutionMode, ExecutionContext, Executor\n",
    "from cadCAD.configuration import Configuration\n",
    "import networkx as nx\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import scipy.stats as sts\n",
    "import pandas as pd\n",
    "%matplotlib inline\n",
    "\n",
    "import page_ranker as pr\n"
   ]
  },
  {
   "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": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#generate an initial set of contributors\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#helper functions\n",
    "def get_nodes_by_type(g, node_type_selection):\n",
    "    return [node for node in g.nodes if g.nodes[node]['type']== node_type_selection ]\n",
    "\n",
    "def get_edges_by_type(g, edge_type_selection):\n",
    "    return [edge for edge in g.edges if g.edges[edge]['type']== edge_type_selection ]\n",
    "\n",
    "def edge_count(g,src,dst):\n",
    "    i =0\n",
    "    stop = False\n",
    "    while not(stop):\n",
    "        try:\n",
    "            g.edges[(src,dst,i)]\n",
    "            i=i+1\n",
    "        except:\n",
    "            stop = True\n",
    "            return i"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'address': ('sourcecred',\n",
       "  'github',\n",
       "  'COMMENT',\n",
       "  'ISSUE',\n",
       "  'sourcecred',\n",
       "  'research',\n",
       "  '5',\n",
       "  '468081422'),\n",
       " 'type': 'github/comment'}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#sample comment\n",
    "base_graph.nodes[get_nodes_by_type(base_graph, 'github/comment')[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(33, 18, 0)\n",
      "{'address': ('sourcecred', 'github', 'USERLIKE', 'USER', 'BrianLitwin'), 'type': 'github/user'}\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'address': ('sourcecred',\n",
       "  'github',\n",
       "  'AUTHORS',\n",
       "  '5',\n",
       "  'sourcecred',\n",
       "  'github',\n",
       "  'USERLIKE',\n",
       "  'USER',\n",
       "  'BrianLitwin',\n",
       "  '6',\n",
       "  'sourcecred',\n",
       "  'github',\n",
       "  'ISSUE',\n",
       "  'sourcecred',\n",
       "  'research',\n",
       "  '2'),\n",
       " 'type': 'github/authors'}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#sample author edge\n",
    "ex_auth_edge = get_edges_by_type(base_graph, 'github/authors')[0]\n",
    "print(ex_auth_edge)\n",
    "print(base_graph.nodes[ex_auth_edge[0]])\n",
    "base_graph.edges[ex_auth_edge]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3, 20, 0)\n",
      "{'address': ('sourcecred', 'github', 'COMMENT', 'ISSUE', 'sourcecred', 'research', '5', '468081422'), 'type': 'github/comment'}\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'address': ('sourcecred',\n",
       "  'github',\n",
       "  'HAS_PARENT',\n",
       "  '8',\n",
       "  'sourcecred',\n",
       "  'github',\n",
       "  'COMMENT',\n",
       "  'ISSUE',\n",
       "  'sourcecred',\n",
       "  'research',\n",
       "  '5',\n",
       "  '468081422'),\n",
       " 'type': 'github/hasParent'}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#sample has parent edge\n",
    "ex_parent_edge = get_edges_by_type(base_graph, 'github/hasParent')[0]\n",
    "print(ex_parent_edge)\n",
    "print(base_graph.nodes[ex_parent_edge[0]])\n",
    "base_graph.edges[ex_parent_edge]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "#need the ability to add contributions\n",
    "def synthetic_random_comment(g, author_input='random'):\n",
    "    graph=g.copy()\n",
    "    \n",
    "    new_node_id = len(graph.nodes)\n",
    "    graph.add_node(new_node_id)\n",
    "    graph.nodes[new_node_id][\"type\"] = 'github/comment'\n",
    "    graph.nodes[new_node_id][\"address\"] = ('sythethic')\n",
    "    \n",
    "    #pick an author\n",
    "    author_candidates = get_nodes_by_type(graph, 'github/user')\n",
    "    if author_input in author_candidates:\n",
    "        author = author_input\n",
    "    else:\n",
    "        author = np.random.choice(author_candidates)\n",
    "    \n",
    "    author_edge_id = (author, new_node_id, edge_count(graph,author,new_node_id))\n",
    "    graph.add_edge(author, new_node_id)\n",
    "    graph.edges[author_edge_id]['type'] = 'github/authors'\n",
    "    graph.edges[author_edge_id]['address'] = ('sythethic')\n",
    "    \n",
    "    #pick the thing being commented on\n",
    "    commented_on_candidates = get_nodes_by_type(graph, 'github/comment') \\\n",
    "        + get_nodes_by_type(graph, 'github/review')\\\n",
    "        + get_nodes_by_type(graph, 'github/issue')  \n",
    "    \n",
    "    commented_on =  np.random.choice(commented_on_candidates)\n",
    "    commented_on_edge_id = (new_node_id, commented_on, edge_count(graph,new_node_id, commented_on))\n",
    "    graph.add_edge(new_node_id,commented_on)\n",
    "    graph.edges[commented_on_edge_id]['type'] = 'github/hasParent'\n",
    "    graph.edges[commented_on_edge_id]['address'] = ('sythethic')\n",
    "    \n",
    "    \n",
    "    #pick some references\n",
    "    refs_candidates =  get_nodes_by_type(graph, 'github/issue') \\\n",
    "        + get_nodes_by_type(graph, 'github/user') \\\n",
    "        + get_nodes_by_type(graph, 'github/review')\n",
    "    \n",
    "    #number of references\n",
    "    mu = 2 #expected number of references\n",
    "    num_refs = sts.poisson.rvs(mu)\n",
    "    \n",
    "    refs = np.random.choice(refs_candidates,2, replace=False)\n",
    "    for ref in refs:\n",
    "        if graph.nodes[ref][\"type\"] == 'github/user':\n",
    "            ref_type = 'github/mentionsAuthor'\n",
    "        else :\n",
    "            ref_type ='github/references'\n",
    "        \n",
    "        ref_edge_id = (new_node_id, ref, edge_count(graph,new_node_id, ref))\n",
    "        graph.add_edge(new_node_id,ref)\n",
    "        graph.edges[ref_edge_id]['type'] = ref_type\n",
    "        graph.edges[ref_edge_id]['address'] = ('sythethic')\n",
    "    \n",
    "    return graph"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def synthetic_new_user(g, include_comment= True):\n",
    "    graph=g.copy()\n",
    "    new_node_id = len(graph.nodes)\n",
    "    graph.add_node(new_node_id)\n",
    "    graph.nodes[new_node_id][\"type\"] = 'github/user'\n",
    "    graph.nodes[new_node_id][\"address\"] = ('sythethic','','','','SyntheticUser'+str(new_node_id))\n",
    "    \n",
    "    if include_comment:\n",
    "        graph = synthetic_random_comment(graph, author_input=new_node_id)\n",
    "    \n",
    "    return graph\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<networkx.classes.multidigraph.MultiDiGraph at 0x1a26e6abe0>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "synthetic_new_user(base_graph)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "nodes = [n for n in base_graph.nodes]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'address': ('sourcecred', 'github', 'USERLIKE', 'USER', 'mzargham'),\n",
       " 'type': 'github/user'}"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "base_graph.nodes[nodes[-2]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'SourceCred/Research')"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 74496 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "isg.inspectSubGraph(base_graph, nodes)\n",
    "plt.title(\"SourceCred/Research\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Simplifed SourceCred/Research Subgraph = $G_0$')"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 33844 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "subgraph = isg.inspectSubGraph(base_graph, get_nodes_by_type(base_graph, 'github/issue'))\n",
    "plt.title(\"Simplifed SourceCred/Research Subgraph = $G_0$\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "smaller_base_graph = nx.convert_node_labels_to_integers(subgraph, first_label=0)\n",
    "\n",
    "g0 = smaller_base_graph.copy()\n",
    "g1 = synthetic_new_user(g0, include_comment= True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, \"New Synthetic user Comment on Decentralion's Prior Comment:\\n mentions mZargham and Decentralion\")"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 26448 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "isg.inspectSubGraph(g1, [node for node in g1.nodes][-2:], expand = True)\n",
    "plt.title(\"New Synthetic user Comment on Decentralion's Prior Comment:\\n mentions mZargham and Decentralion\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "T = 50 #iterations of graph update in our simulation\n",
    "\n",
    "#set up the pagerank algorithm params\n",
    "iterations = 25\n",
    "\n",
    "alpha = .01\n",
    "seed = {n:0.0 for n in base_graph.nodes}\n",
    "source_id = get_nodes_by_type(smaller_base_graph, 'github/repo')[0]\n",
    "seed[source_id]=1.0 #source_id is the repo itself\n",
    "self_loop_wt = 1/10004\n",
    "\n",
    "#memory coef of time weighted cred\n",
    "gamma = .9"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "_,_, network= pr.pageRanker(smaller_base_graph,\n",
    "                         alpha,\n",
    "                         iterations,\n",
    "                         seed=seed,\n",
    "                         initial_value = seed,\n",
    "                         lazy=True,\n",
    "                         self_loop_wt=self_loop_wt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "for node in network.nodes:\n",
    "    network.nodes[node]['cumulative']= network.nodes[node]['score']\n",
    "    network.nodes[node]['time_weighted']=network.nodes[node]['score']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "def drop_and_normalize(vec, drop_bunch):\n",
    "    for node in drop_bunch:\n",
    "        vec[node]=0\n",
    "    \n",
    "    new_total = sum(vec)\n",
    "    return vec/new_total\n",
    "\n",
    "def indicator_of(graph, node):\n",
    "    seed = {n:0.0 for n in graph.nodes}\n",
    "    seed[node]=1.0 #source_id is the repo itself\n",
    "    return seed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "scores = np.array([network.nodes[node]['score'] for node in network.nodes])\n",
    "cred = drop_and_normalize(scores, [source_id])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Personalized PageRank with seed sourcecred/research')"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 36896 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "scale=2500\n",
    "\n",
    "nx.draw_kamada_kawai(network, node_size=scores*scale, alpha=.8)\n",
    "nx.draw_kamada_kawai(network, node_size=cred*scale, alpha=.8, node_color='b')\n",
    "plt.title(\"Personalized PageRank with seed sourcecred/research\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'address': ('sourcecred', 'github', 'USERLIKE', 'USER', 'BrianLitwin'),\n",
       " 'type': 'github/user',\n",
       " 'color': (1.0, 0.5816993464052289, 0.0, 1.0),\n",
       " 'label': 'BrianLitwin',\n",
       " 'score': 0.047760156485161666,\n",
       " 'all_nbr': {7, 8},\n",
       " 'in_nbr': set(),\n",
       " 'out_nbr': {7, 8},\n",
       " 'self_wt': 9.996001599360256e-05,\n",
       " 'total_wt': 2.0000999600159934,\n",
       " 'cumulative': 0.047760156485161666,\n",
       " 'time_weighted': 0.047760156485161666}"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "network.nodes[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([2., 2., 4., 0., 0., 0., 0., 1., 0., 2.]),\n",
       " array([0.        , 0.02487285, 0.0497457 , 0.07461855, 0.0994914 ,\n",
       "        0.12436425, 0.1492371 , 0.17410995, 0.1989828 , 0.22385565,\n",
       "        0.2487285 ]),\n",
       " <a list of 10 Patch objects>)"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 5828 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(cred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 26220 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "nx.draw_kamada_kawai(network, node_size=scores*scale, alpha=.8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.047760156485161666\n",
      "0.03946556774186552\n",
      "0.020897886169731095\n",
      "0.039852462510800525\n",
      "0.03893956062101374\n",
      "0.016939929153401815\n",
      "0.02232470711821712\n",
      "0.12854041573228447\n",
      "0.15772689869128453\n",
      "0.16965945837705845\n",
      "0.31789295739918205\n"
     ]
    }
   ],
   "source": [
    "for node in network.nodes:\n",
    "    print(network.nodes[node]['cumulative'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "initial_conditions = {'cred':cred,\n",
    "                      'cumulative_cred':cred,\n",
    "                      'time_weighted_cred':cred,\n",
    "                      'network':network}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "def update_network(params, step, sL, s, _input):\n",
    "    \n",
    "    prior_network = s['network']\n",
    "    \n",
    "    if _input['new_user']:\n",
    "        new_network = synthetic_new_user(prior_network)\n",
    "    else:\n",
    "        new_network = synthetic_random_comment(prior_network)\n",
    "    \n",
    "    _,_,new_network = pr.pageRanker(new_network,\n",
    "                         alpha,\n",
    "                         iterations,\n",
    "                         seed=indicator_of(new_network,source_id),\n",
    "                         initial_value = indicator_of(new_network,source_id),\n",
    "                         lazy=True,\n",
    "                         self_loop_wt=self_loop_wt)\n",
    "    \n",
    "    for node in new_network.nodes:\n",
    "        if node in prior_network.nodes:\n",
    "            new_network.nodes[node]['cumulative']=prior_network.nodes[node]['cumulative']\\\n",
    "                +new_network.nodes[node]['score']\n",
    "            new_network.nodes[node]['time_weighted']=gamma*prior_network.nodes[node]['time_weighted']\\\n",
    "                +(1-gamma)*new_network.nodes[node]['score']\n",
    "        else:\n",
    "            new_network.nodes[node]['cumulative']= new_network.nodes[node]['score']\n",
    "            new_network.nodes[node]['time_weighted']=new_network.nodes[node]['score']\n",
    "    \n",
    "    key = 'network'\n",
    "    value = new_network \n",
    "    \n",
    "    return (key, value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "def update_cred(params, step, sL, s, _input):\n",
    "    \n",
    "    network = s['network']\n",
    "    scores = np.array([network.nodes[node]['score'] for node in network.nodes])\n",
    "    cred = drop_and_normalize(scores, [source_id])\n",
    "    \n",
    "    key = 'cred'\n",
    "    value = cred\n",
    "    \n",
    "    return (key, value)\n",
    "\n",
    "def update_cumulative(params, step, sL, s, _input):\n",
    "    \n",
    "    network = s['network']\n",
    "    cumulative_cred = np.array([network.nodes[node]['cumulative'] for node in network.nodes])\n",
    "    #cumulative_cred = drop_and_normalize(cumulative, [source_id])\n",
    "    \n",
    "    key = 'cumulative_cred'\n",
    "    value = cumulative_cred\n",
    "    \n",
    "    return (key, value)\n",
    "\n",
    "def update_time_weighted(params, step, sL, s, _input):\n",
    "    \n",
    "    network = s['network']\n",
    "    time_weighted_cred = np.array([network.nodes[node]['time_weighted'] for node in network.nodes])\n",
    "    #time_weighted_cred = drop_and_normalize(time_weighted, [source_id])\n",
    "    \n",
    "    key = 'time_weighted_cred'\n",
    "    value = time_weighted_cred\n",
    "    \n",
    "    return (key, value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "def random_contribution(params, step, sL, s):\n",
    "    \n",
    "    network = s['network']\n",
    "    users = get_nodes_by_type(network, 'github/user')\n",
    "    num_users = len(users)\n",
    "    \n",
    "    max_users = 50\n",
    "    rv = np.random.uniform(0,1)\n",
    "    #probability of new user ~ .2\n",
    "    thresh = .2\n",
    "    new_user = bool(rv<thresh)\n",
    "\n",
    "    return({'new_user':new_user})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
    "# The Partial State Update Blocks\n",
    "partial_state_update_blocks = [\n",
    "    { \n",
    "        'policies': { \n",
    "            #The following policy functions will be evaluated \n",
    "            #and their returns will be passed to the state update functions\n",
    "            'random': random_contribution\n",
    "        },\n",
    "        'variables': { # The following state variables will be updated simultaneously\n",
    "            'network': update_network\n",
    "            \n",
    "        }\n",
    "    },\n",
    "    {\n",
    "      'policies': {\n",
    "          #Updates in this block are entirely state dependent in this version\n",
    "        },\n",
    "        'variables': { # The following state variables will be updated simultaneously\n",
    "            'cred': update_cred,\n",
    "            'cumulative_cred': update_cumulative,\n",
    "            'time_weighted_cred':update_time_weighted\n",
    "        }\n",
    "    }\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "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",
    "# In this example, we'll run the simulation once (N=1) and its duration will be of 10 timesteps\n",
    "# We'll cover the `M` key in a future article. For now, let's leave it empty\n",
    "simulation_parameters = {\n",
    "    'T': range(T),\n",
    "    'N': 1,\n",
    "    'M': {}\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
    "# The configurations above are then packaged into a `Configuration` object\n",
    "config = Configuration(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_config=simulation_parameters #dict containing simulation parameters\n",
    "                      )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "single_proc: [<cadCAD.configuration.Configuration object at 0x1a27b3c5c0>]\n"
     ]
    }
   ],
   "source": [
    "exec_mode = ExecutionMode()\n",
    "exec_context = ExecutionContext(exec_mode.single_proc)\n",
    "executor = Executor(exec_context, [config]) # Pass the configuration object inside an array\n",
    "raw_result, tensor = executor.main() # The `main()` method returns a tuple; its first elements contains the raw results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame(raw_result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "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>cred</th>\n",
       "      <th>cumulative_cred</th>\n",
       "      <th>network</th>\n",
       "      <th>run</th>\n",
       "      <th>substep</th>\n",
       "      <th>time_weighted_cred</th>\n",
       "      <th>timestep</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>[0.06958144399968927, 0.06416827285204604, 0.0...</td>\n",
       "      <td>[0.09582370795773174, 0.083789958094328, 0.038...</td>\n",
       "      <td>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>[0.0477904959839025, 0.039951450002925215, 0.0...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>[0.06958144399968927, 0.06416827285204604, 0.0...</td>\n",
       "      <td>[0.09582370795773174, 0.083789958094328, 0.038...</td>\n",
       "      <td>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>[0.0477904959839025, 0.039951450002925215, 0.0...</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>[0.06791312665052263, 0.06611420825626564, 0.0...</td>\n",
       "      <td>[0.14311993209471474, 0.1298333751264821, 0.05...</td>\n",
       "      <td>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>[0.047741068799210556, 0.0405606467058481, 0.0...</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                cred  \\\n",
       "0  [0.07001856527247696, 0.057858320288537865, 0....   \n",
       "1  [0.07001856527247696, 0.057858320288537865, 0....   \n",
       "2  [0.06958144399968927, 0.06416827285204604, 0.0...   \n",
       "3  [0.06958144399968927, 0.06416827285204604, 0.0...   \n",
       "4  [0.06791312665052263, 0.06611420825626564, 0.0...   \n",
       "\n",
       "                                     cumulative_cred  \\\n",
       "0  [0.07001856527247696, 0.057858320288537865, 0....   \n",
       "1  [0.07001856527247696, 0.057858320288537865, 0....   \n",
       "2  [0.09582370795773174, 0.083789958094328, 0.038...   \n",
       "3  [0.09582370795773174, 0.083789958094328, 0.038...   \n",
       "4  [0.14311993209471474, 0.1298333751264821, 0.05...   \n",
       "\n",
       "                                      network  run  substep  \\\n",
       "0          (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)    1        0   \n",
       "1      (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)    1        1   \n",
       "2      (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)    1        2   \n",
       "3  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)    1        1   \n",
       "4  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)    1        2   \n",
       "\n",
       "                                  time_weighted_cred  timestep  \n",
       "0  [0.07001856527247696, 0.057858320288537865, 0....         0  \n",
       "1  [0.07001856527247696, 0.057858320288537865, 0....         1  \n",
       "2  [0.0477904959839025, 0.039951450002925215, 0.0...         1  \n",
       "3  [0.0477904959839025, 0.039951450002925215, 0.0...         2  \n",
       "4  [0.047741068799210556, 0.0405606467058481, 0.0...         2  "
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "nets = df[df.substep==1].network.values\n",
    "pos = nx.kamada_kawai_layout(nets[-1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 39316 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 44792 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 47828 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 52044 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 55816 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 61540 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 60596 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 67932 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 70268 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 75176 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 76576 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 81476 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 85016 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 89820 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 95336 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 96996 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 99296 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 104216 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 108664 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 109152 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 112392 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 115328 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 116612 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 119984 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 118268 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 119592 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 117444 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 120092 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 122460 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 126080 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 128012 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 127844 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 129508 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 131688 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 133228 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 134788 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 135708 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 139136 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 132540 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 122404 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 124172 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 126152 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 124912 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 128056 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 129592 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 132504 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 134568 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 137724 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 136644 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "for i in range(len(nets)-1):\n",
    "    nx.draw(nets[i],pos=pos, alpha=.5, node_color='b')\n",
    "    nx.draw(nets[i+1],pos=pos,  alpha=.5, node_color='g')\n",
    "    plt.title(\"Update: $G_{\"+str(i)+\"}$ to $G_{\"+str(i+1)+\"}$\")\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "df['node_count'] = df.network.apply(lambda x: len(x.nodes))\n",
    "df['edge_count'] = df.network.apply(lambda x: len(x.edges))\n",
    "df['user_count'] = df.network.apply(lambda x: len(get_nodes_by_type(x, 'github/user')))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "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>cred</th>\n",
       "      <th>cumulative_cred</th>\n",
       "      <th>network</th>\n",
       "      <th>run</th>\n",
       "      <th>substep</th>\n",
       "      <th>time_weighted_cred</th>\n",
       "      <th>timestep</th>\n",
       "      <th>node_count</th>\n",
       "      <th>edge_count</th>\n",
       "      <th>user_count</th>\n",
       "      <th>padded_cred</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>0</td>\n",
       "      <td>11</td>\n",
       "      <td>16</td>\n",
       "      <td>4</td>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>20</td>\n",
       "      <td>4</td>\n",
       "      <td>[0.07001856527247696, 0.057858320288537865, 0....</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>[0.07534469335075676, 0.05521551921623299, 0.0...</td>\n",
       "      <td>[0.0996831812410881, 0.0775167780351914, 0.041...</td>\n",
       "      <td>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>[0.048176443312238144, 0.039324131997011555, 0...</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>20</td>\n",
       "      <td>4</td>\n",
       "      <td>[0.07534469335075676, 0.05521551921623299, 0.0...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>[0.07534469335075676, 0.05521551921623299, 0.0...</td>\n",
       "      <td>[0.0996831812410881, 0.0775167780351914, 0.041...</td>\n",
       "      <td>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>[0.048176443312238144, 0.039324131997011555, 0...</td>\n",
       "      <td>2</td>\n",
       "      <td>13</td>\n",
       "      <td>24</td>\n",
       "      <td>4</td>\n",
       "      <td>[0.07534469335075676, 0.05521551921623299, 0.0...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>[0.07240542509332236, 0.05825145940997595, 0.0...</td>\n",
       "      <td>[0.15049440428302882, 0.11839531569703045, 0.0...</td>\n",
       "      <td>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>[0.0484399212852084, 0.039479572563494304, 0.0...</td>\n",
       "      <td>2</td>\n",
       "      <td>13</td>\n",
       "      <td>24</td>\n",
       "      <td>4</td>\n",
       "      <td>[0.07240542509332236, 0.05825145940997595, 0.0...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                cred  \\\n",
       "0  [0.07001856527247696, 0.057858320288537865, 0....   \n",
       "1  [0.07001856527247696, 0.057858320288537865, 0....   \n",
       "2  [0.07534469335075676, 0.05521551921623299, 0.0...   \n",
       "3  [0.07534469335075676, 0.05521551921623299, 0.0...   \n",
       "4  [0.07240542509332236, 0.05825145940997595, 0.0...   \n",
       "\n",
       "                                     cumulative_cred  \\\n",
       "0  [0.07001856527247696, 0.057858320288537865, 0....   \n",
       "1  [0.07001856527247696, 0.057858320288537865, 0....   \n",
       "2  [0.0996831812410881, 0.0775167780351914, 0.041...   \n",
       "3  [0.0996831812410881, 0.0775167780351914, 0.041...   \n",
       "4  [0.15049440428302882, 0.11839531569703045, 0.0...   \n",
       "\n",
       "                                      network  run  substep  \\\n",
       "0          (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)    1        0   \n",
       "1      (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)    1        1   \n",
       "2      (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)    1        2   \n",
       "3  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)    1        1   \n",
       "4  (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)    1        2   \n",
       "\n",
       "                                  time_weighted_cred  timestep  node_count  \\\n",
       "0  [0.07001856527247696, 0.057858320288537865, 0....         0          11   \n",
       "1  [0.07001856527247696, 0.057858320288537865, 0....         1          12   \n",
       "2  [0.048176443312238144, 0.039324131997011555, 0...         1          12   \n",
       "3  [0.048176443312238144, 0.039324131997011555, 0...         2          13   \n",
       "4  [0.0484399212852084, 0.039479572563494304, 0.0...         2          13   \n",
       "\n",
       "   edge_count  user_count                                        padded_cred  \n",
       "0          16           4  [0.07001856527247696, 0.057858320288537865, 0....  \n",
       "1          20           4  [0.07001856527247696, 0.057858320288537865, 0....  \n",
       "2          20           4  [0.07534469335075676, 0.05521551921623299, 0.0...  \n",
       "3          24           4  [0.07534469335075676, 0.05521551921623299, 0.0...  \n",
       "4          24           4  [0.07240542509332236, 0.05825145940997595, 0.0...  "
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1a23a923c8>"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 21136 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "df.plot(x='timestep', y=['node_count', 'user_count', 'edge_count'], logy=True)\n",
    "#df.plot(x='timestep', y='user_count')\n",
    "#df.plot(x='timestep', y='edge_count')\n",
    "plt.title('size in network over time')\n",
    "plt.xlabel('time')\n",
    "plt.ylabel('count')\n",
    "plt.legend([\"nodes\",\"users\",\"edges\"])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pad(vec, length,fill=True):\n",
    "    \n",
    "    if fill:\n",
    "        padded = np.zeros(length,)\n",
    "    else:\n",
    "        padded = np.empty(length,)\n",
    "        padded[:] = np.nan\n",
    "        \n",
    "    for i in range(len(vec)):\n",
    "        padded[i]= vec[i]\n",
    "        \n",
    "    return padded\n",
    "\n",
    "def make2D(key, data, fill=False):\n",
    "    maxL = data[key].apply(len).max()\n",
    "    newkey = 'padded_'+key\n",
    "    data[newkey] = data[key].apply(lambda x: pad(x,maxL,fill))\n",
    "    reshaped = np.array([a for a in data[newkey].values])\n",
    "    \n",
    "    return reshaped"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'pagerank($G_t$)')"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 68980 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.semilogy(df.index,make2D('cred', df, False))\n",
    "plt.title('Cred for all contributions')\n",
    "plt.xlabel('time $t$')\n",
    "plt.ylabel('pagerank($G_t$)')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'exponentiall smoothed pagerank($G_t$)\\n with $\\\\gamma=.9$')"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 66332 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "r2df = df[df.substep==2].copy() \n",
    "plt.semilogy(r2df.index,make2D('time_weighted_cred', r2df))\n",
    "plt.title('Smoothed Averge Cred for all contributions')\n",
    "plt.xlabel('time $t$')\n",
    "plt.ylabel('exponentiall smoothed pagerank($G_t$)\\n with $\\gamma=.9$')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, ' $\\\\sum_{T < t}$ pagerank($G_T$)')"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 109300 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.semilogy(r2df.index,make2D('cumulative_cred', r2df))\n",
    "plt.title('Cumulative Cred for all contributions')\n",
    "plt.xlabel('time $t$')\n",
    "plt.ylabel(' $\\sum_{T < t}$ pagerank($G_T$)')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [],
   "source": [
    "#now lets look at just users cred of all 3 types\n",
    "user_nodes = get_nodes_by_type(nets[-1], 'github/user')\n",
    "user_names = [nets[-1].nodes[u]['address'][4] for u in user_nodes ]\n",
    "U = len(user_nodes)\n",
    "N = len(nets)\n",
    "user_cred = np.empty((U,N))\n",
    "user_cumulative_cred = np.empty((U,N))\n",
    "user_time_weighted_cred = np.empty((U,N))\n",
    "for i in range(N):\n",
    "    net = nets[i]\n",
    "    for u in range(U):\n",
    "        user = user_nodes[u]\n",
    "        if user in net.nodes:\n",
    "            user_cumulative_cred[u,i] = net.nodes[user]['cumulative']\n",
    "            user_time_weighted_cred[u,i]= net.nodes[user]['time_weighted']\n",
    "            user_cred[u,i] = net.nodes[user]['score']\n",
    "        else:\n",
    "            user_cumulative_cred[u,i] = np.nan\n",
    "            user_time_weighted_cred[u,i]= np.nan\n",
    "            user_cred[u,i] = np.nan\n",
    "            "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(15, 50)"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "user_cred.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'pagerank($G_t$)')"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 72096 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.semilogy(range(N),user_cred.T)\n",
    "plt.legend(user_names, bbox_to_anchor=(1.5, 1))\n",
    "plt.title('Cred for all Users')\n",
    "plt.xlabel('time $t$')\n",
    "plt.ylabel('pagerank($G_t$)')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, '$\\\\sum_{T < t}$ pagerank($G_T$)')"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 81116 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.semilogy(range(N),user_cumulative_cred.T)\n",
    "plt.legend(user_names, bbox_to_anchor=(1.5, 1))\n",
    "plt.title('Cumulative Cred for all Users')\n",
    "plt.xlabel('time $t$')\n",
    "plt.ylabel('$\\sum_{T < t}$ pagerank($G_T$)')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'smoothed weighted average of pagerank($G_t$)')"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 72360 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.semilogy(range(N),user_time_weighted_cred.T)\n",
    "plt.legend(user_names, bbox_to_anchor=(1.5, 1))\n",
    "plt.title('Smoothed Cred for Users')\n",
    "plt.xlabel('time $t$')\n",
    "plt.ylabel('smoothed weighted average of pagerank($G_t$)')"
   ]
  },
  {
   "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
}
