conviction/conviction_cadCAD.ipynb

906 lines
67 KiB
Plaintext

{
"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",
"from scipy.stats import expon\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": 20,
"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"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"92089.22219636562\n"
]
}
],
"source": [
"#generate an initial set of 'n' participants\n",
"network = nx.DiGraph()\n",
"n = 100\n",
"for i in range(n):\n",
" network.add_node(i)\n",
" network.nodes[i]['type']=\"participant\"\n",
" \n",
" h_rv = expon.rvs(loc=0.001, scale=1000)\n",
" network.nodes[i]['holdings'] = h_rv\n",
" \n",
" s_rv = np.random.rand() \n",
" network.nodes[i]['sentiment'] = s_rv\n",
"\n",
"participants = get_nodes_by_type(network, 'participant')\n",
"initial_supply = np.sum([ network.nodes[i]['holdings'] for i in participants])\n",
"print(initial_supply)\n",
"\n",
"initial_funds = initial_supply\n"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1.7484479178693189\n"
]
}
],
"source": [
"#generate initial proposals\n",
"m = 12\n",
"for j in range(m):\n",
" ind = n+j\n",
" network.add_node(ind)\n",
" network.nodes[ind]['type']=\"proposal\"\n",
" network.nodes[ind]['conviction']=0\n",
" network.nodes[ind]['status']='candidate'\n",
" network.nodes[ind]['age']=0\n",
" \n",
" r_rv = expon.rvs(loc=0.001, scale=10000)\n",
" network.node[ind]['funds_requested'] = r_rv\n",
" \n",
" for i in range(n):\n",
" network.add_edge(i, ind)\n",
" \n",
" a_rv = np.random.rand() \n",
" network.edges[(i, ind)]['affinity'] = a_rv\n",
" network.edges[(i,ind)]['tokens'] = a_rv*network.nodes[i]['holdings']\n",
" network.edges[(i, ind)]['conviction'] = 0\n",
"\n",
"proposals = get_nodes_by_type(network, 'proposal')\n",
"total_requested = np.sum([ network.nodes[i]['funds_requested'] for i in proposals])\n",
"print(total_requested/initial_funds)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'type': 'proposal',\n",
" 'conviction': 0,\n",
" 'status': 'candidate',\n",
" 'funds_requested': 10417.252006928056}"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.nodes[get_nodes_by_type(network, 'proposal')[0]]"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'type': 'participant',\n",
" 'holdings': 1307.1683720857025,\n",
" 'sentiment': 0.008125570765641466}"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"network.nodes[get_nodes_by_type(network, 'participant')[0]]"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0.5, 1.0, 'Histogram of Participants Token Holdings')"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.hist([ network.nodes[i]['holdings'] for i in participants])\n",
"plt.title('Histogram of Participants Token Holdings')"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0.5, 1.0, 'Histogram of Proposals Funds Requested')"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.hist([ network.nodes[i]['funds_requested'] for i in proposals])\n",
"plt.title('Histogram of Proposals Funds Requested')"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0.5, 1.0, 'Histogram of Affinities between Participants and Proposals')"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.hist([ network.edges[e]['affinity'] for e in network.edges])\n",
"plt.title('Histogram of Affinities between Participants and Proposals')"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0.5, 1.0, 'Histogram of Affinities between Participants and Proposals weighted by holdings')"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.hist([ network.edges[e]['affinity'] for e in network.edges], weights = [network.nodes[e[0]]['holdings']for e in network.edges],alpha = 1)\n",
"plt.title('Histogram of Affinities between Participants and Proposals weighted by holdings')"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [],
"source": [
"T = 50 #iterations of graph update in our simulation\n",
"#param for conviction accumilation\n",
"alpha = .01 #later we should set this to be param so we can sweep it\n",
"\n",
"#sentiment of the outside world which drives grants\n",
"initial_sentiment = .5\n",
"\n",
"#sentiment decay rate\n",
"gamma =.001 #later we should set this to be param so we can sweep it\n",
"\n",
"#maximum share of funds a proposal can take\n",
"beta = .2 #later we should set this to be param so we can sweep it\n",
"# tuning param for the trigger function\n",
"rho = 1\n",
"\n",
"#minimum periods passed before a proposal can pass\n",
"tmin = 7\n"
]
},
{
"cell_type": "code",
"execution_count": 45,
"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",
"# 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": 46,
"metadata": {},
"outputs": [],
"source": [
"initial_conditions = {'network':network,\n",
" 'supply': initial_supply,\n",
" 'funds':initial_funds,\n",
" 'sentiment': initial_sentiment}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#functions for partial state update block 1\n",
"\n",
"def driving_process(params, step, sL, s):\n",
" \n",
" #placeholder plumbing for random process\n",
" \n",
" return({'new_participant':False, 'new_proposal':False})\n",
"\n",
"def update_network(params, step, sL, s, _input):\n",
" \n",
" network = s['network']\n",
" #placeholder plumbing for new proposals and new participants\n",
" new_participant = _input['new_participant'] #T/F\n",
" new_proposal = _input['new_proposal'] #T/F\n",
" # IF THEN logic to create new nodes // left out for now since always FALSE\n",
" \n",
" #update age of the existing proposals\n",
" proposals = get_nodes_by_type(network, 'proposal')\n",
" for j in proposals:\n",
" network.nodes[j]['age']= network.nodes[j]['age']+1\n",
" \n",
" key = 'network'\n",
" value = network\n",
" \n",
" return (key, value)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#partial state update block 2\n",
"def check_process(params, step, sL, s):\n",
" \n",
" network = s['network']\n",
" proposals = get_nodes_by_type(network, 'proposal')\n",
" \n",
" completed = []\n",
" for j in proposals:\n",
" if network.nodes[j]['status'] == 'active':\n",
" grant_size = network.nodes[j]['funds_requested']\n",
" likelihood = 1.0/np.log(grant_size)\n",
" if np.random.rand() < likelihood:\n",
" completed.append(j)\n",
" \n",
" return({'completed':completed})\n",
"\n",
"def complete_proposal(params, step, sL, s, _input):\n",
" \n",
" network = s['network']\n",
" participants = get_nodes_by_type(network, 'participant')\n",
" \n",
" completed = _input['completed']\n",
" for j in completed:\n",
" network.nodes[j]['status']='completed'\n",
" for i in participants:\n",
" force = network.edge[(i,j)]['affinity']\n",
" sentiment = network.node[i]['sentiment']\n",
" network.node[i]['sentiment'] = get_sentimental(sentiment, force, decay=False)\n",
" \n",
" key = 'network'\n",
" value = network\n",
" \n",
" return (key, value)\n",
"\n",
"def update_sentiment_on_completion(params, step, sL, s, _input):\n",
" \n",
" network = s['network']\n",
" proposals = get_nodes_by_type(network, 'proposal')\n",
" completed = _input['completed']\n",
" \n",
" grants_outstanding = np.sum([network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status']=='active'])\n",
" \n",
" grants_completed = np.sum([network.nodes[j]['funds_requested'] for j in completed])\n",
" \n",
" sentiment = s['sentiment']\n",
" force = grants_completed/grants_outstanding\n",
" sentiment = get_sentimental(sentiment, force)\n",
" \n",
" key = 'sentiment'\n",
" value = sentiment\n",
" \n",
" return (key, value)\n",
"\n",
"def get_sentimental(sentiment, force, decay=True):\n",
" sentiment = sentiment*(1-int(decay)*gamma) + force\n",
" \n",
" if sentiment > 1:\n",
" sentiment = 1\n",
" \n",
" return sentiment"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def trigger_threshold(requested, funds, supply):\n",
" \n",
" share = request/funds\n",
" if share < beta:\n",
" return rho*supply/(beta-share)**2\n",
" else: \n",
" return np.inf\n",
" \n",
" \n",
"\n",
"#partial state update block 3\n",
"def trigger_function(params, step, sL, s):\n",
" \n",
" network = s['network']\n",
" funds = s['funds']\n",
" supply = s['supply']\n",
" proposals = get_nodes_by_type(network, 'proposal')\n",
" \n",
" accepted = []\n",
" for j in proposals:\n",
" if network.nodes[j]['status'] == 'candidate':\n",
" requested = network.nodes[j]['funds_requested']\n",
" age = network.nodes[j]['age']\n",
" if age > tmin:\n",
" threshold = trigger_threshold(requested, funds, supply)\n",
" conviction = network.nodes[j]['conviction']\n",
" if conviction >threshold:\n",
" accepted.append(j)\n",
" \n",
" return({'accepted':accepted})\n",
"\n",
"def update_funds(params, step, sL, s, _input):\n",
" \n",
" funds = s['funds']\n",
" network = s['network']\n",
" accepted = _input['accepted']\n",
"\n",
" #decrement funds\n",
" for j in accepted:\n",
" funds = funds - network.nodes[j]['funds_requested']\n",
" \n",
" key = 'funds'\n",
" value = funds\n",
" \n",
" return (key, value)\n",
"\n",
"def update_proposals(params, step, sL, s, _input):\n",
" \n",
" network = s['network']\n",
" accepted = _input['accepted']\n",
" participants = get_nodes_by_type(network, 'participant')\n",
" \n",
" #bookkeeping conviction and participant sentiment\n",
" for j in accepted:\n",
" #change status to active\n",
" for i in participants:\n",
" \n",
" edge = (i,j)\n",
" #reset tokens assigned to other candidates\n",
" \n",
" #update participants sentiments (positive or netai)\n",
" \n",
" key = 'network'\n",
" value = network\n",
" \n",
" return (key, value)\n",
"\n",
"def update_sentiment_on_release(params, step, sL, s, _input):\n",
" \n",
" network = s['network']\n",
" proposals = get_nodes_by_type(network, 'proposal')\n",
" accepted = _input['accepted']\n",
" \n",
" proposals_outstanding = np.sum([network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status']=='candidate'])\n",
" \n",
" proposals_accepted = np.sum([network.nodes[j]['funds_requested'] for j in accepted])\n",
" \n",
" sentiment = s['sentiment']\n",
" force = proposals_accepted/proposals_outstanding\n",
" sentiment = get_sentimental(sentiment, force, False)\n",
" \n",
" key = 'sentiment'\n",
" value = sentiment\n",
" \n",
" return (key, value)"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'driving_processes' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-47-3e002ec54fcb>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 5\u001b[0m 'policies': { \n\u001b[1;32m 6\u001b[0m \u001b[0;31m#new proposals or new participants\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0;34m'random'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mdriving_processes\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m },\n\u001b[1;32m 9\u001b[0m 'variables': {\n",
"\u001b[0;31mNameError\u001b[0m: name 'driving_processes' is not defined"
]
}
],
"source": [
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # \n",
"# The Partial State Update Blocks\n",
"partial_state_update_blocks = [\n",
" { \n",
" 'policies': { \n",
" #new proposals or new participants\n",
" 'random': driving_processes\n",
" },\n",
" 'variables': {\n",
" 'network': update_network\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",
" 'funds': update_funds, #only get new funds when things are completed\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': update_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",
" #new proposals or new participants\n",
" 'bond': increase_holdings, #high sentiment, high affinity\n",
" 'burn': decrease_holdings #low sentiment\n",
" },\n",
" 'variables': {\n",
" 'supply': update_supply,\n",
" 'network': update_holdings #update everyones holdings \n",
" #and their conviction for each proposal\n",
" }\n",
" }\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"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": null,
"metadata": {},
"outputs": [],
"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": null,
"metadata": {},
"outputs": [],
"source": [
"df = pd.DataFrame(raw_result)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"nets = df[df.substep==1].network.values\n",
"pos = nx.kamada_kawai_layout(nets[-1])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"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": null,
"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": null,
"metadata": {},
"outputs": [],
"source": [
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"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": null,
"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": null,
"metadata": {},
"outputs": [],
"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": null,
"metadata": {},
"outputs": [],
"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": null,
"metadata": {},
"outputs": [],
"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": null,
"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": null,
"metadata": {},
"outputs": [],
"source": [
"user_cred.shape"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"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": null,
"metadata": {},
"outputs": [],
"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": null,
"metadata": {},
"outputs": [],
"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
}