pythonpython-3.xjupyter-notebookmesa-abm

Coding Moral Worth


I am a beginner programmer and currently trying to code moral worth in the context of a public good game with cooperators, deceptors, and peer-punishers.

To start, I wanted to start simple and associate being a cooperator and a peer-punisher with +1 moral worth, and being a deceptor with -1 moral worth.

What I tried

# Calculate moral worth
def computeMoralWorth(k, playertype):  
    mw = 0
    if playertype == 'D':
        mw -= 1
    elif playertype == 'C' or playertype == 'Pep':
        mw += 1   
    return mw

# Simulate moral worth over time
def simulateMoralWorth(k, T, s):
    m_w = {} # Used to store moral worth data
    for playertype in k.keys():
        m_w[playertype] = [k[playertype]]*T
    for i in range(T):
        pop = generatePop(k)
        moralw = {}
        for playertype in k.keys():
            moralw[playertype] = computeMoralWorth(k, playertype)
        m_w = logmoralw(m_w, moralw, i)
    return m_w

# Generate population based on initial composition 'k'
def generatePop(k):
    pop = []
    for playertype in k.keys():
        for i in range(int(k[playertype])):
            player = {}
            player['type'] = playertype
            pop.append(player)
    return pop

# Log moral worth data over time
def logmoralw(m_w, moralw, i):
    for playertype in moralw.keys():
        m_w[playertype][i] = moralw[playertype]
    return m_w

# Define simulation parameters
k = {'C':0, 'D':N, 'Pep':0}
T = 100000 # Time
N = 100 # Total population size
s = np.inf # Imitation strength

# Run simulation
moral_worth_data = simulateMoralWorth(k, T, s)
print(moral_worth_data['C'][-1])
print(moral_worth_data['D'][-1])
print(moral_worth_data['Pep'][-1])

Output it gives me:

0 100 0

I expected to have something like this show up:

{'C': some_number,
     'D': some_number,
     'PeP':some_number}

BUT

It seems when I try to run the simulation, nothing actually shows up. What am I doing wrong? (I get no errors btw)


Solution

  • You haven't output anything. Try adding this to the end -

    print(moral_worth_data)

    here is the full code with added line, and a value substituted into the population size N, which is assigned to variable 'D':

    import numpy as np
    # Calculate moral worth
    def computeMoralWorth(k, playertype):  
        mw = 0
        if playertype == 'D':
            mw -= 1
        elif playertype == 'C' or playertype == 'Pep':
            mw += 1   
        return mw
    
    # Simulate moral worth over time
    def simulateMoralWorth(k, T, s):
        m_w = {} # Used to store moral worth data
        for playertype in k.keys():
            m_w[playertype] = [k[playertype]]*T
        for i in range(T):
            pop = generatePop(k)
            moralw = {}
            for playertype in k.keys():
                moralw[playertype] = computeMoralWorth(k, playertype)
            m_w = logmoralw(m_w, moralw, i)
        return m_w
    
    # Generate population based on initial composition 'k'
    def generatePop(k):
        pop = []
        for playertype in k.keys():
            for i in range(int(k[playertype])):
                player = {}
                player['type'] = playertype
                pop.append(player)
        return pop
    
    # Log moral worth data over time
    def logmoralw(m_w, moralw, i):
        for playertype in moralw.keys():
            m_w[playertype][i] = moralw[playertype]
        return m_w
    
    # Define simulation parameters
    k = {'C':0, 'D':500, 'Pep':0}
    T = 100000 # Time
    N = 100 # Total population size
    s = np.inf # Imitation strength
    
    # Run simulation
    moral_worth_data = simulateMoralWorth(k, T, s)
    

    Suggested addition at the end:

    # Assign final values to new dictionary
    Output = {key:moral_worth_data[key][-1] for key in moral_worth_data.keys()}
    # show results
    print(Output)
    

    Alternatively use a for loop

    for key in moral_worth_data.keys():
        print(key,":",np.average(moral_worth_data[key]))
    

    or hard code your print statement:

    print('C :',moral_worth_data['C'])
    print('D :',moral_worth_data['D'])
    print('Pep :',moral_worth_data['Pep'])
    

    The added step is a dictionary comprehension that extracts the last score given to / item in the list for 'C', 'D', and 'Pep', rather than assigning an aggregate value such as sum(moral_worth_data[key]) or np.mean(moral_worth_data[key]). I take this from the discussion in comments.