This commit is contained in:
Andrew Clark 2020-08-21 16:55:39 -04:00
parent 7dd7f3da61
commit 9a9e367d35
14 changed files with 71466 additions and 938 deletions

View File

@ -104,7 +104,7 @@ cadCAD links:
## Model Reproducibility ## Model Reproducibility
In order to reperform this code, we recommend the researcher use the following link https://www.anaconda.com/products/individual to download Python 3.7. To install the specific version of cadCAD this repository was built with, run the following code: In order to reperform this code, we recommend the researcher use the following link https://www.anaconda.com/products/individual to download Python 3.7. To install the specific version of cadCAD this repository was built with, run the following code:
pip install cadCAD==0.4.18 pip install cadCAD==0.4.21
Then run cd Aragon_Conviction_Voting to enter the repository. Finally, run jupyter notebook to open a notebook server to run the various notebooks in this repository. Then run cd Aragon_Conviction_Voting to enter the repository. Finally, run jupyter notebook to open a notebook server to run the various notebooks in this repository.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 KiB

After

Width:  |  Height:  |  Size: 340 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,28 +6,36 @@
"tags": [] "tags": []
}, },
"source": [ "source": [
"# Transforming Continuous Values to Discrete Events\n", "# The Trigger Function\n",
"\n", "\n",
"The role of the trigger function in the conviction voting algorithm is to determine if a sufficient amount of conviction has accumulated in support of a particular proposal. In the 1hive use case for conviction, proposals map to precise quantities of resources $r$ requested from a communal resource pool $R$ (which is time varying $R_t$ but we will drop the subscript for ease of reading). Further more there is a supply of governance tokens $S$ which are being used as part of the goverance process. In the implementation the quantity $S$ will be the effective supply which is the subset of the total Supply for the governance token in question. We assume a time varying supply $S_t$ and thereforewe can interpret $S_t$ as the effective supply without loss of generality. Furthermore we drop the subscript and refer to $S$ for ease of reading. The process of passing a proposal results in an allocation of $r$ funds as shown in the figure below.\n", "## Transforming Continuous Preferences into Discrete Events\n",
"\n",
"This notebook is a mathematical deep dive into the derivation of the Trigger Function used in Conviction Voting for the 1Hive use case.\n",
"\n",
"The role of the trigger function in the conviction voting algorithm is to determine if a sufficient amount of conviction has accumulated in support of a particular proposal, at which point it passes from being a candidate proposal to an active proposal. \n",
"\n",
"In the 1Hive use case for conviction, proposals map to precise quantities of resources $r$ requested from a communal resource pool $R$ (which is time varying $R_t$ but we will drop the subscript for ease of reading). Furthermore, there is a supply of governance tokens $S$ which are being used as part of the goverance process. In the implementation the quantity $S$ will be the effective supply which is the subset of the total Supply for the governance token in question. \n",
"\n",
"We assume a time varying supply $S_t$ and thereforewe can interpret $S_t$ as the effective supply without loss of generality. From here forward, we will drop the subscript and refer to $S$ for ease of reading. The process of passing a proposal results in an allocation of $r$ funds as shown in the figure below.\n",
"\n", "\n",
"![](images/stockflow_cv_trigger.png)\n", "![](images/stockflow_cv_trigger.png)\n",
"\n", "\n",
"The trigger function is characterized by a set of parameters in addition to the current state of the system: $R$ and $S$. Those parameters are $\\alpha$, $\\beta$ and $\\rho$.\n", "The trigger function is characterized by a set of parameters in addition to the current state of the system: $R$ and $S$. Those parameters are $\\alpha$, $\\beta$ and $\\rho$.\n",
"\n", "\n",
"$\\alpha \\in (0,1)$ is the conviction rate parameter defined in [Deriving Alpha](Deriving_Alpha.ipynb) and should be tuned according to a desired half life.\n", "* $\\alpha \\in (0,1)$ is the conviction rate parameter defined in the [Deriving Alpha notebook](https://nbviewer.jupyter.org/github/BlockScience/Aragon_Conviction_Voting/blob/master/models/v3/Deriving_Alpha.ipynb) and should be tuned according to a desired half life.\n",
"\n", "\n",
"$\\beta\\in (0,1)$ is the assymptotic limit for trigger function. It is impossible to discharge more $\\beta$ share of funds. \n", "* $\\beta\\in (0,1)$ is the asymptotic limit for trigger function. It is impossible to discharge more than $\\beta$ share of funds. \n",
"\n", "\n",
"$\\rho \\in (0, \\beta^2)$ is a the scale factor for trigger function. Note that we require $0<\\rho <\\beta^2$ \n", "* $\\rho \\in (0, \\beta^2)$ is a the scale factor for trigger function. Note that we require $0<\\rho <\\beta^2$ \n",
"\n", "\n",
"The trigger function:\n", "The trigger function is defined by: $y^*(r) = \\frac{\\rho S}{(1-\\alpha)\\left(\\beta^2 - \\frac{r}{R}\\right) }$\n",
"\n",
"$y^*(r) = y^*(r) = \\frac{\\rho S}{(1-\\alpha)\\left(\\beta^2 - \\frac{r}{R}\\right) }$\n",
"\n", "\n",
"The geometric properties of this function with respect to the parameter choices are shown here:\n", "The geometric properties of this function with respect to the parameter choices are shown here:\n",
"\n", "\n",
"![](images/trigger_geometry.png)\n", "![](images/trigger_geometry.png)\n",
"\n", "\n",
"On this plot we can see that there is a maximum conviction that can be reached for a proposal, and also a maximum achievable funds released for a single proposal, which are important bounds for a community to establish for their funding pool.\n",
"\n",
"Note that by requiring that: $0<\\rho <\\beta^2$ the following holds $0<\\frac{\\rho}{\\beta^2}<1$ and $0<\\beta - \\sqrt \\rho <\\beta <1$" "Note that by requiring that: $0<\\rho <\\beta^2$ the following holds $0<\\frac{\\rho}{\\beta^2}<1$ and $0<\\beta - \\sqrt \\rho <\\beta <1$"
] ]
}, },
@ -52,7 +60,9 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Pull params out of the existing files or use this notebook to ovewrite them with your own choices to see how the plots are affected." "## Reader Tutorial:\n",
"\n",
"Feel free to pull parameters out of the existing files or use this notebook to ovewrite them with your own choices to see how the plots are affected."
] ]
}, },
{ {
@ -144,17 +154,17 @@
"source": [ "source": [
"## Simple derivations:\n", "## Simple derivations:\n",
"\n", "\n",
"min_required_conviction = $y^*(0) = \\frac{\\rho S}{(1-\\alpha)\\beta^2}$\n", "We can plug in some boundary conditions to determine our minimum required and maximum achievable conviction. We can also determine the maximum achievable funds a proposal is able to request, to understand the upper bounds of individual proposal funding.\n",
"\n", "\n",
"max_achievable_conviction = $\\frac{S}{1-\\alpha}$\n", "* min_required_conviction = $y^*(0) = \\frac{\\rho S}{(1-\\alpha)\\beta^2}$\n",
"\n", "\n",
"min_required_conviction_as_a_share_of_max = $\\frac{\\rho S}{(1-\\alpha)\\beta^2} \\cdot \\frac{1-\\alpha}{S} = \\frac{\\rho}{\\beta^2}$\n", "* max_achievable_conviction = $\\frac{S}{1-\\alpha}$\n",
"\n", "\n",
"To compute the max_achievable_request solve: \n", "* min_required_conviction_as_a_share_of_max = $\\frac{\\rho S}{(1-\\alpha)\\beta^2} \\cdot \\frac{1-\\alpha}{S} = \\frac{\\rho}{\\beta^2}$\n",
"\n", "\n",
"$\\frac{S}{1-\\alpha} = \\frac{\\rho S}{(1-\\alpha)\\left(\\beta-\\frac{r}{R}\\right)^2}$\n", "* To compute the max_achievable_request solve: $\\frac{S}{1-\\alpha} = \\frac{\\rho S}{(1-\\alpha)\\left(\\beta-\\frac{r}{R}\\right)^2}$\n",
"\n", "\n",
"max_achievable_request = $r = (\\beta -\\sqrt\\rho)F$" "* max_achievable_request = $r = (\\beta -\\sqrt\\rho)F$"
] ]
}, },
{ {
@ -208,7 +218,9 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"First set of plots in \"Absolute Terms\" based on alpha, Supply and Funds as above" "## Plot series 1: \"Absolute Terms\" \n",
"\n",
"These plots demonstrate the trigger function based on alpha, Supply and Funds as above."
] ]
}, },
{ {
@ -371,7 +383,9 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Second set of plots in \"Relative Terms\" which knock out the dependence on alpha and supply, as well as treating requests as share of total funds." "## Plot series 2: \"Relative Terms\" \n",
"\n",
"This set of plots looks at what happens when we knock out the dependence on alpha and supply, as well as treating requests as share of total funds."
] ]
}, },
{ {
@ -534,7 +548,9 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"Third set of plots are heatmaps to show the simultaneous variation of multiple parameters with a focus on alpha and supply.\n", "## Plot series 3: Heat Maps\n",
"\n",
"The next set of plots show the simultaneous variation of multiple parameters with a focus on alpha and supply.\n",
"\n", "\n",
"Note: that i am using params stored in the supporting files, this won't have changed even if you have edited the plots above" "Note: that i am using params stored in the supporting files, this won't have changed even if you have edited the plots above"
] ]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 286 KiB

View File

@ -33,16 +33,9 @@ exp.append_configs(
partial_state_update_blocks=partial_state_update_blocks partial_state_update_blocks=partial_state_update_blocks
) )
# Initialize network x # Initialize network x
for c in configs: config_initialization(configs,initial_values)
c.initial_state = deepcopy(c.initial_state)
print("Params (config.py) : ", c.sim_config['M'])
c.initial_state['network'] = initialize_network(initial_values['n'],initial_values['m'],
initial_values['funds'],
initial_values['supply'],c.sim_config['M'])
def get_configs(): def get_configs():
''' '''

View File

@ -50,8 +50,8 @@ def complete_proposal(params, step, sL, s, _input):
for c in proposals: for c in proposals:
if (j,c) in competitors: if (j,c) in competitors:
conflict = network.edges[(j,c)]['conflict'] conflict = network.edges[(j,c)]['conflict']
for i in participants: # for i in participants:
network.edges[(i,c)]['affinity'] = network.edges[(i,c)]['affinity'] *(1-conflict) # network.edges[(i,c)]['affinity'] = network.edges[(i,c)]['affinity'] *(1-conflict)
for i in participants: for i in participants:
force = network.edges[(i,j)]['affinity'] force = network.edges[(i,j)]['affinity']

View File

@ -5,7 +5,8 @@ import matplotlib.pyplot as plt
import matplotlib.colors as colors import matplotlib.colors as colors
import matplotlib.cm as cmx import matplotlib.cm as cmx
import seaborn as sns import seaborn as sns
from copy import deepcopy
#from cadCAD import configs
def trigger_threshold(requested, funds, supply, alpha, params): def trigger_threshold(requested, funds, supply, alpha, params):
@ -243,7 +244,7 @@ def social_affinity_booster(network, proposal, participant):
return np.sum(boosts) return np.sum(boosts)
def snap_plot(nets, size_scale = 1/10, dims = (30,30), savefigs=False): def snap_plot(nets, size_scale = 1/10, dims = (10,10), savefigs=False):
''' '''
''' '''
@ -333,18 +334,10 @@ def snap_plot(nets, size_scale = 1/10, dims = (30,30), savefigs=False):
tokens = net.edges[e]['tokens'] tokens = net.edges[e]['tokens']
included_edge_color[ind] = scalarMap.to_rgba(tokens) included_edge_color[ind] = scalarMap.to_rgba(tokens)
# nx.draw(net,
# pos=pos,
# node_size = node_size,
# node_color = node_color,
# edge_color = included_edge_color,
# edgelist=included_edges,
# labels = net_node_label)
# plt.title('Tokens Staked by Partipants to Proposals')
else: else:
plt.figure() plt.figure(figsize=dims)
nx.draw(net, nx.draw(net,
pos=pos, pos=pos,
node_size = node_size, node_size = node_size,
@ -358,7 +351,6 @@ def snap_plot(nets, size_scale = 1/10, dims = (30,30), savefigs=False):
plt.xticks([]) plt.xticks([])
plt.yticks([]) plt.yticks([])
if savefigs: if savefigs:
#plt.savefig('images/' + unique_id+'_fig'+str(counter)+'.png')
plt.savefig('images/snap/'+str(counter)+'.png',bbox_inches='tight') plt.savefig('images/snap/'+str(counter)+'.png',bbox_inches='tight')
counter = counter+1 counter = counter+1
@ -391,13 +383,14 @@ def make2D(key, data, fill=False):
def affinities_plot(df, dims = (8.5, 11) ): def affinities_plot(network, dims = (20, 5)):
''' '''
''' '''
last_net= df.network.values[-1]
last_props=get_nodes_by_type(last_net, 'proposal')
last_props=get_nodes_by_type(network, 'proposal')
M = len(last_props) M = len(last_props)
last_parts=get_nodes_by_type(last_net, 'participant') last_parts=get_nodes_by_type(network, 'participant')
N = len(last_parts) N = len(last_parts)
affinities = np.empty((N,M)) affinities = np.empty((N,M))
@ -405,7 +398,7 @@ def affinities_plot(df, dims = (8.5, 11) ):
for j_ind in range(M): for j_ind in range(M):
i = last_parts[i_ind] i = last_parts[i_ind]
j = last_props[j_ind] j = last_props[j_ind]
affinities[i_ind][j_ind] = last_net.edges[(i,j)]['affinity'] affinities[i_ind][j_ind] = network.edges[(i,j)]['affinity']
fig, ax = plt.subplots(figsize=dims) fig, ax = plt.subplots(figsize=dims)
@ -586,7 +579,8 @@ def initialize_network(n,m, initial_funds, supply, params):
network.nodes[j]['status'] = 'candidate' network.nodes[j]['status'] = 'candidate'
network.nodes[j]['age'] = 0 network.nodes[j]['age'] = 0
r_rv = gamma.rvs(3,loc=0.001, scale=500) # This is a gamma random variable (wikipedia link) - scipy link
r_rv = gamma.rvs(3,loc=0.001, scale=(initial_funds * params['beta'])*.05)
network.nodes[j]['funds_requested'] = r_rv network.nodes[j]['funds_requested'] = r_rv
network.nodes[j]['trigger']= trigger_threshold(r_rv, initial_funds, initial_supply, params['alpha'],params) network.nodes[j]['trigger']= trigger_threshold(r_rv, initial_funds, initial_supply, params['alpha'],params)
@ -608,3 +602,21 @@ def initialize_network(n,m, initial_funds, supply, params):
network = initial_social_network(network, scale = 1) network = initial_social_network(network, scale = 1)
return network return network
def config_initialization(configs,initial_values):
'''
from copy import deepcopy
from cadCAD import configs
'''
# Initialize network x
for c in configs:
c.initial_state = deepcopy(c.initial_state)
print("Params (config.py) : ", c.sim_config['M'])
c.initial_state['network'] = initialize_network(initial_values['n'],initial_values['m'],
initial_values['funds'],
initial_values['supply'],c.sim_config['M'])
return c.initial_state['network']

View File

@ -8,9 +8,6 @@ def run():
''' '''
Definition: Definition:
Run simulation Run simulation
Parameters:
input_config: Optional way to pass in system configuration
''' '''
# Single # Single
exec_mode = ExecutionMode() exec_mode = ExecutionMode()

View File

@ -1,8 +1,13 @@
from .parts.utils import * from .parts.utils import *
from .parts.sys_params import * from .parts.sys_params import *
import networkx as nx
# copy of this structure called state_scheme.py with the name of the class.
# add utility for checking state. Tell you what fails. Dictionary with key if true/false.
# use https://pydantic-docs.helpmanual.io/? and then flow into pytest. # run type check at the end of the
# simulation before the results.
state_variables = { state_variables = {
'network': 0, # will initialize during config.py 'network': nx.DiGraph(), # will initialize during config.py as a networkX object
'funds':initial_values['funds'], 'funds':initial_values['funds'],
'sentiment': initial_values['sentiment'], 'sentiment': initial_values['sentiment'],
'effective_supply': (initial_values['supply']-initial_values['funds'])*.8, 'effective_supply': (initial_values['supply']-initial_values['funds'])*.8,