def participants_decisions(params, step, sL, s): network = s['network'] participants = get_nodes_by_type(network, 'participant') proposals = get_nodes_by_type(network, 'proposal') candidates = [ j for j in proposals if network.nodes[j]['status'] == 'candidate' ] sensitivity = params['sensitivity'] gain = .01 delta_holdings = {} proposals_supported = {} for i in participants: force = network.nodes[i]['sentiment'] - sensitivity delta_holdings[i] = network.nodes[i]['holdings'] * gain * force support = [] for j in candidates: affinity = network.edges[(i, j)]['affinity'] cutoff = sensitivity * np.max( [network.edges[(i, p)]['affinity'] for p in candidates]) if cutoff < .5: cutoff = .5 if affinity > cutoff: support.append(j) proposals_supported[i] = support return ({ 'delta_holdings': delta_holdings, 'proposals_supported': proposals_supported })
def driving_process(params, step, sL, s): #placeholder plumbing for random processes arrival_rate = 10 / (1 + s['sentiment']) rv1 = np.random.rand() new_participant = bool(rv1 < 1 / arrival_rate) supporters = get_edges_by_type(s['network'], 'support') len_parts = len(get_nodes_by_type(s['network'], 'participant')) supply = s['supply'] expected_holdings = .1 * supply / len_parts if new_participant: h_rv = expon.rvs(loc=0.0, scale=expected_holdings) new_participant_holdings = h_rv else: new_participant_holdings = 0 network = s['network'] affinities = [network.edges[e]['affinity'] for e in supporters] median_affinity = np.median(affinities) proposals = get_nodes_by_type(network, 'proposal') fund_requests = [ network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status'] == 'candidate' ] funds = s['funds'] total_funds_requested = np.sum(fund_requests) proposal_rate = 1 / median_affinity * (1 + total_funds_requested / funds) rv2 = np.random.rand() new_proposal = bool(rv2 < 1 / proposal_rate) sentiment = s['sentiment'] funds = s['funds'] 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 ({ 'new_participant': new_participant, 'new_participant_holdings': new_participant_holdings, 'new_proposal': new_proposal, 'funds_arrival': funds_arrival })
def update_sentiment_on_release(params, step, sL, s, _input): network = s['network'] proposals = get_nodes_by_type(network, 'proposal') accepted = _input['accepted'] proposals_outstanding = np.sum([ network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status'] == 'candidate' ]) proposals_accepted = np.sum( [network.nodes[j]['funds_requested'] for j in accepted]) sentiment = s['sentiment'] force = proposals_accepted / proposals_outstanding if (force >= 0) and (force <= 1): sentiment = get_sentimental(sentiment, force, False) else: sentiment = get_sentimental(sentiment, 0, False) key = 'sentiment' value = sentiment return (key, value)
def trigger_function(params, step, sL, s): network = s['network'] funds = s['funds'] supply = s['supply'] proposals = get_nodes_by_type(network, 'proposal') tmin = params['tmin'] trigger_func = params['trigger_func'] accepted = [] triggers = {} for j in proposals: if network.nodes[j]['status'] == 'candidate': requested = network.nodes[j]['funds_requested'] age = network.nodes[j]['age'] threshold = trigger_func(requested, funds, supply) if age > tmin: conviction = network.nodes[j]['conviction'] if conviction > threshold: accepted.append(j) else: threshold = np.nan triggers[j] = threshold return ({'accepted': accepted, 'triggers': triggers})
def update_sentiment_on_completion(params, step, sL, s, _input): network = s['network'] proposals = get_nodes_by_type(network, 'proposal') completed = _input['completed'] grants_outstanding = np.sum([ network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status'] == 'active' ]) grants_completed = np.sum( [network.nodes[j]['funds_requested'] for j in completed]) sentiment = s['sentiment'] force = grants_completed / grants_outstanding mu = params['sentiment_decay'] if (force >= 0) and (force <= 1): sentiment = get_sentimental(sentiment, force, mu) else: sentiment = get_sentimental(sentiment, 0, mu) key = 'sentiment' value = sentiment return (key, value)
def update_network(params, step, sL, s, _input): network = s['network'] funds = s['funds'] supply = s['supply'] trigger_func = params['trigger_func'] #print(trigger_func) new_participant = _input['new_participant'] #T/F new_proposal = _input['new_proposal'] #T/F if new_participant: new_participant_holdings = _input['new_participant_holdings'] network = gen_new_participant(network, new_participant_holdings) 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)
def gen_new_proposal(network, funds, supply, total_funds, trigger_func): 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 = scale_factor * funds / total_funds r_rv = gamma.rvs(3, loc=0.001, scale=rescale) network.node[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 return network
def update_tokens(params, step, sL, s, _input): network = s['network'] delta_holdings = _input['delta_holdings'] proposals = get_nodes_by_type(network, 'proposal') candidates = [ j for j in proposals if network.nodes[j]['status'] == 'candidate' ] proposals_supported = _input['proposals_supported'] participants = get_nodes_by_type(network, 'participant') alpha = params['alpha'] min_support = params['min_supp'] for i in participants: network.nodes[i][ 'holdings'] = network.nodes[i]['holdings'] + delta_holdings[i] supported = proposals_supported[i] total_affinity = np.sum( [network.edges[(i, j)]['affinity'] for j in supported]) for j in candidates: if j in supported: normalized_affinity = network.edges[ (i, j)]['affinity'] / total_affinity network.edges[( i, j)]['tokens'] = normalized_affinity * network.nodes[i][ 'holdings'] else: network.edges[(i, j)]['tokens'] = 0 prior_conviction = network.edges[(i, j)]['conviction'] current_tokens = network.edges[(i, j)]['tokens'] network.edges[( i, j)]['conviction'] = current_tokens + alpha * prior_conviction for j in candidates: network.nodes[j]['conviction'] = np.sum( [network.edges[(i, j)]['conviction'] for i in participants]) total_tokens = np.sum( [network.edges[(i, j)]['tokens'] for i in participants]) if total_tokens < min_support: network.nodes[j]['status'] = 'killed' key = 'network' value = network return (key, value)
def participants_decisions(params, step, sL, s): network = s['network'] participants = get_nodes_by_type(network, 'participant') proposals = get_nodes_by_type(network, 'proposal') candidates = [ j for j in proposals if network.nodes[j]['status'] == 'candidate' ] sensitivity = params['sensitivity'] gain = .01 delta_holdings = {} proposals_supported = {} for i in participants: engagement_rate = .3 * network.nodes[i]['sentiment'] if np.random.rand() < engagement_rate: force = network.nodes[i]['sentiment'] - sensitivity delta_holdings[i] = network.nodes[i]['holdings'] * gain * force support = [] for j in candidates: booster = social_affinity_booster(network, j, i) #print(booster) affinity = network.edges[(i, j)]['affinity'] + booster cutoff = sensitivity * np.max( [network.edges[(i, p)]['affinity'] for p in candidates]) if cutoff < .5: cutoff = .5 if affinity > cutoff: support.append(j) proposals_supported[i] = support else: delta_holdings[i] = 0 proposals_supported[i] = [ j for j in candidates if network.edges[(i, j)]['tokens'] > 0 ] return ({ 'delta_holdings': delta_holdings, 'proposals_supported': proposals_supported })
def update_proposals(params, step, sL, s, _input): network = s['network'] accepted = _input['accepted'] triggers = _input['triggers'] participants = get_nodes_by_type(network, 'participant') proposals = get_nodes_by_type(network, 'proposals') sensitivity = params['sensitivity'] for j in proposals: network.nodes[j]['trigger'] = triggers[j] #bookkeeping conviction and participant sentiment for j in accepted: network.nodes[j]['status'] = 'active' network.nodes[j]['conviction'] = np.nan #change status to active for i in participants: #operating on edge = (i,j) #reset tokens assigned to other candidates network.edges[(i, j)]['tokens'] = 0 network.edges[(i, j)]['conviction'] = np.nan #update participants sentiments (positive or negative) affinities = [ network.edges[(i, p)]['affinity'] for p in proposals if not (p in accepted) ] if len(affinities) > 1: max_affinity = np.max(affinities) force = network.edges[ (i, j)]['affinity'] - sensitivity * max_affinity else: force = 0 #based on what their affinities to the accepted proposals network.nodes[i]['sentiment'] = get_sentimental( network.nodes[i]['sentiment'], force, False) key = 'network' value = network return (key, value)
def complete_proposal(params, step, sL, s, _input): network = s['network'] participants = get_nodes_by_type(network, 'participant') proposals = get_nodes_by_type(network, 'proposal') competitors = get_edges_by_type(network, 'conflict') completed = _input['completed'] for j in completed: network.nodes[j]['status'] = 'completed' for c in proposals: if (j, c) in competitors: conflict = network.edges[(j, c)]['conflict'] for i in participants: network.edges[(i, c)]['affinity'] = network.edges[ (i, c)]['affinity'] * (1 - conflict) for i in participants: force = network.edges[(i, j)]['affinity'] sentiment = network.nodes[i]['sentiment'] network.nodes[i]['sentiment'] = get_sentimental(sentiment, force, decay=0) failed = _input['failed'] for j in failed: network.nodes[j]['status'] = 'failed' for i in participants: force = -network.edges[(i, j)]['affinity'] sentiment = network.nodes[i]['sentiment'] network.nodes[i]['sentiment'] = get_sentimental(sentiment, force, decay=0) key = 'network' value = network return (key, value)
def check_progress(params, step, sL, s): network = s['network'] proposals = get_nodes_by_type(network, 'proposal') completed = [] for j in proposals: if network.nodes[j]['status'] == 'active': grant_size = network.nodes[j]['funds_requested'] base_completion_rate = params['base_completion_rate'] likelihood = 1.0 / (base_completion_rate + np.log(grant_size)) if np.random.rand() < likelihood: completed.append(j) return ({'completed': completed})
def driving_process(params, step, sL, s): #placeholder plumbing for random processes arrival_rate = 10 / s['sentiment'] rv1 = np.random.rand() new_participant = bool(rv1 < 1 / arrival_rate) if new_participant: h_rv = expon.rvs(loc=0.0, scale=1000) new_participant_holdings = h_rv else: new_participant_holdings = 0 network = s['network'] affinities = [network.edges[e]['affinity'] for e in network.edges] median_affinity = np.median(affinities) proposals = get_nodes_by_type(network, 'proposal') fund_requests = [ network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status'] == 'candidate' ] funds = s['funds'] total_funds_requested = np.sum(fund_requests) proposal_rate = 10 / median_affinity * total_funds_requested / funds rv2 = np.random.rand() new_proposal = bool(rv2 < 1 / proposal_rate) sentiment = s['sentiment'] funds = s['funds'] scale_factor = 1 + 4000 * sentiment**2 #this shouldn't happen but expon is throwing domain errors if scale_factor > 1: funds_arrival = expon.rvs(loc=0, scale=scale_factor) else: funds_arrival = 0 return ({ 'new_participant': new_participant, 'new_participant_holdings': new_participant_holdings, 'new_proposal': new_proposal, 'funds_arrival': funds_arrival })
def complete_proposal(params, step, sL, s, _input): network = s['network'] participants = get_nodes_by_type(network, 'participant') completed = _input['completed'] for j in completed: network.nodes[j]['status'] = 'completed' for i in participants: force = network.edges[(i, j)]['affinity'] sentiment = network.node[i]['sentiment'] network.node[i]['sentiment'] = get_sentimental(sentiment, force, decay=0) key = 'network' value = network return (key, value)
def trigger_function(params, step, sL, s): network = s['network'] funds = s['funds'] supply = s['supply'] proposals = get_nodes_by_type(network, 'proposal') tmin = params['tmin'] trigger_func = params['trigger_func'] accepted = [] triggers = {} funds_to_be_released = 0 for j in proposals: if network.nodes[j]['status'] == 'candidate': requested = network.nodes[j]['funds_requested'] age = network.nodes[j]['age'] threshold = trigger_func(requested, funds, supply) if age > tmin: conviction = network.nodes[j]['conviction'] if conviction > threshold: accepted.append(j) funds_to_be_released = funds_to_be_released + requested else: threshold = np.nan triggers[j] = threshold #catch over release and keep the highest conviction results if funds_to_be_released > funds: #print('funds ='+str(funds)) #print(accepted) ordered = conviction_order(network, accepted) #print(ordered) accepted = [] release = 0 ind = 0 while release + network.nodes[ ordered[ind]]['funds_requested'] < funds: accepted.append(ordered[ind]) release = network.nodes[ordered[ind]]['funds_requested'] ind = ind + 1 return ({'accepted': accepted, 'triggers': triggers})
def gen_new_participant(network, new_participant_holdings): 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'] = new_participant_holdings 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'] network.edges[(i, j)]['conviction'] = 0 return network