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)
Example #7
0
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})
Example #13
0
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})
Example #16
0
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