driving_process() rewritten, now passes new_participant_tokens. add_participants_proposals_to_network() and new_participants_and_new_funds_commons() handle the results of driving_process()

This commit is contained in:
Andrew Chiw 2020-06-02 16:20:20 +02:00
parent 02581fa95c
commit 8f214ed043
2 changed files with 373 additions and 72 deletions

225
network_helpers.py Normal file
View File

@ -0,0 +1,225 @@
from scipy.stats import expon, gamma
import numpy as np
import networkx as nx
from hatch import TokenBatch
from convictionvoting import trigger_threshold
from IPython.core.debugger import set_trace
def get_nodes_by_type(g, node_type_selection):
return [node for node in g.nodes if g.nodes[node]['type']== node_type_selection ]
def get_edges_by_type(g, edge_type_selection):
return [edge for edge in g.edges if g.edges[edge]['type']== edge_type_selection ]
def get_proposals(network):
return get_nodes_by_type(network, "proposal")
def get_participants(network):
return get_nodes_by_type(network, "participant")
def initial_social_network(network: nx.DiGraph, scale = 1, sigmas=3) -> nx.DiGraph:
participants = get_participants(network)
for i in participants:
for j in participants:
if not(j==i):
influence_rv = expon.rvs(loc=0.0, scale=scale)
if influence_rv > scale+sigmas*scale**2:
network.add_edge(i,j)
network.edges[(i,j)]['influence'] = influence_rv
network.edges[(i,j)]['type'] = 'influence'
return network
def initial_conflict_network(network: nx.DiGraph, rate = .25) -> nx.DiGraph:
proposals = get_proposals(network)
for i in proposals:
for j in proposals:
if not(j==i):
conflict_rv = np.random.rand()
if conflict_rv < rate :
network.add_edge(i,j)
network.edges[(i,j)]['conflict'] = 1-conflict_rv
network.edges[(i,j)]['type'] = 'conflict'
return network
def add_proposals_and_relationships_to_network(n: nx.DiGraph, proposals: int, funding_pool: float, token_supply: float) -> nx.DiGraph:
participant_count = len(n)
for i in range(proposals):
j = participant_count + i
n.add_node(j, type="proposal", conviction=0, status="candidate", age=0)
r_rv = gamma.rvs(3,loc=0.001, scale=10000)
n.nodes[j]['funds_requested'] = r_rv
n.nodes[j]['trigger']= trigger_threshold(r_rv, funding_pool, token_supply)
for i in range(participant_count):
n.add_edge(i, j)
rv = np.random.rand()
a_rv = 1-4*(1-rv)*rv #polarized distribution
n.edges[(i, j)]['affinity'] = a_rv
n.edges[(i, j)]['tokens'] = 0
n.edges[(i, j)]['conviction'] = 0
n.edges[(i, j)]['type'] = 'support'
n = initial_conflict_network(n, rate = .25)
n = initial_social_network(n, scale = 1)
return n
# =========================================================================================================
def gen_new_participant(network, new_participant_tokens):
i = len([node for node in network.nodes])
network.add_node(i)
network.nodes[i]['type']="participant"
s_rv = np.random.rand()
network.nodes[i]['sentiment'] = s_rv
network.nodes[i]['holdings_vesting']=None
network.nodes[i]['holdings_nonvesting']=TokenBatch(new_participant_tokens, 5, 5)
# Connect this new participant to existing proposals.
for j in get_nodes_by_type(network, 'proposal'):
network.add_edge(i, j)
rv = np.random.rand()
a_rv = 1-4*(1-rv)*rv #polarized distribution
network.edges[(i, j)]['affinity'] = a_rv
network.edges[(i,j)]['tokens'] = a_rv*network.nodes[i]['holdings_nonvesting'].value
network.edges[(i, j)]['conviction'] = 0
network.edges[(i,j)]['type'] = 'support'
return network
def gen_new_proposal(network, funds, supply, trigger_func, scale_factor = 1.0/100):
j = len([node for node in network.nodes])
network.add_node(j)
network.nodes[j]['type']="proposal"
network.nodes[j]['conviction']=0
network.nodes[j]['status']='candidate'
network.nodes[j]['age']=0
rescale = funds*scale_factor
r_rv = gamma.rvs(3,loc=0.001, scale=rescale)
network.nodes[j]['funds_requested'] = r_rv
network.nodes[j]['trigger']= trigger_func(r_rv, funds, supply)
participants = get_nodes_by_type(network, 'participant')
proposing_participant = np.random.choice(participants)
for i in participants:
network.add_edge(i, j)
if i==proposing_participant:
network.edges[(i, j)]['affinity']=1
else:
rv = np.random.rand()
a_rv = 1-4*(1-rv)*rv #polarized distribution
network.edges[(i, j)]['affinity'] = a_rv
network.edges[(i, j)]['conviction'] = 0
network.edges[(i,j)]['tokens'] = 0
network.edges[(i,j)]['type'] = 'support'
return network
def calc_total_funds_requested(network):
proposals = get_proposals(network)
fund_requests = [network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status']=='candidate' ]
total_funds_requested = np.sum(fund_requests)
return total_funds_requested
def calc_median_affinity(network):
supporters = get_edges_by_type(network, 'support')
affinities = [network.edges[e]['affinity'] for e in supporters ]
median_affinity = np.median(affinities)
return median_affinity
def driving_process(params, step, sL, s):
network = s['network']
commons = s['commons']
funds = s['funding_pool']
sentiment = s['sentiment']
def randomly_gen_new_participant(participant_count, sentiment, current_token_supply, commons):
arrival_rate = 10/(1+sentiment)
rv1 = np.random.rand()
new_participant = bool(rv1<1/arrival_rate)
if new_participant:
# Below line is quite different from Zargham's original, which gave
# tokens instead. Here we randomly generate each participant's
# post-Hatch investment, in DAI/USD. Here the settings for
# expon.rvs() should generate investments of ~0-500 DAI.
new_participant_investment = expon.rvs(loc=0.0, scale=100)
new_participant_tokens = commons.dai_to_tokens(new_participant_investment)
return new_participant, new_participant_investment, new_participant_tokens
else:
return new_participant, 0, 0
def randomly_gen_new_proposal(total_funds_requested, median_affinity, funding_pool):
proposal_rate = 1/median_affinity * (1+total_funds_requested/funding_pool)
rv2 = np.random.rand()
new_proposal = bool(rv2<1/proposal_rate)
return new_proposal
def randomly_gen_new_funding(funds, sentiment):
"""
Each step, more funding comes to the Commons through the exit tribute,
because after the hatching phase, all incoming money goes to the
collateral reserve, not to the funding pool.
"""
scale_factor = funds*sentiment**2/10000
if scale_factor <1:
scale_factor = 1
#this shouldn't happen but expon is throwing domain errors
if sentiment>.4:
funds_arrival = expon.rvs(loc = 0, scale = scale_factor )
else:
funds_arrival = 0
return funds_arrival
new_participant, new_participant_investment, new_participant_tokens = randomly_gen_new_participant(len(get_participants(network)), sentiment, s['token_supply'], commons)
new_proposal = randomly_gen_new_proposal(calc_total_funds_requested(network), calc_median_affinity(network), funds)
funds_arrival = randomly_gen_new_funding(funds, sentiment)
return({'new_participant':new_participant,
'new_participant_investment':new_participant_investment,
'new_participant_tokens': new_participant_tokens,
'new_proposal':new_proposal,
'funds_arrival':funds_arrival})
def add_participants_proposals_to_network(params, step, sL, s, _input):
network = s['network']
funds = s['funding_pool']
supply = s['token_supply']
trigger_func = params[0]["trigger_threshold"][0]
new_participant = _input['new_participant'] #T/F
new_proposal = _input['new_proposal'] #T/F
if new_participant:
network = gen_new_participant(network, _input['new_participant_tokens'])
if new_proposal:
network= gen_new_proposal(network,funds,supply,trigger_func )
#update age of the existing proposals
proposals = get_nodes_by_type(network, 'proposal')
for j in proposals:
network.nodes[j]['age'] = network.nodes[j]['age']+1
if network.nodes[j]['status'] == 'candidate':
requested = network.nodes[j]['funds_requested']
network.nodes[j]['trigger'] = trigger_func(requested, funds, supply)
else:
network.nodes[j]['trigger'] = np.nan
key = 'network'
value = network
return (key, value)

File diff suppressed because one or more lines are too long