Note

You can download this demonstration as a Jupyter Notebook here

Wealth transfer

This is a tutorial for beginners on how to create a simple agent-based model with the agentpy package. It shows the how to create a basic model with a custom agent type, run a simulation, record data, and visualize results.

About the model

The model explores the distribution of wealth under a trading population of agents. We will see that their random interaction will create an inequality of wealth that follows a Boltzmann distribution. The original version of this model been written in MESA and can be found here.

Getting started

To install the latest version of agentpy, run the following command:

[1]:
# !pip install agentpy

Once installed, the recommended way to import the package is as follows:

[2]:
import agentpy as ap

We also import two other libraries that will be used in this demonstration.

[3]:
import numpy as np  # Scientific computing tools
import matplotlib.pyplot as plt  # Visualization

Model definition

We start by defining a new type of agent as a subcluss of Agent. Each agent starts with one unit of wealth. When wealth_transfer() is called, the agent selects another agent at random and gives them one unit of their own wealth if they have one to spare.

[4]:
class WealthAgent(ap.Agent):

    """ An agent with wealth """

    def setup(self):

        self.wealth = 1

    def wealth_transfer(self):

        if self.wealth > 0:

            partner = self.model.agents.random()
            partner.wealth += 1
            self.wealth -= 1

Next, we define a method to calculate the Gini Coefficient, which will measure the inequality among our agents.

[5]:
def gini(x):

    """ Calculate Gini Coefficient """
    # By Warren Weckesser https://stackoverflow.com/a/39513799

    mad = np.abs(np.subtract.outer(x, x)).mean()  # Mean absolute difference
    rmad = mad / np.mean(x)  # Relative mean absolute difference
    return 0.5 * rmad

Finally, we define our model as a subclass of Model. In Model.setup(), we define how many agents should be created at the beginning of the simulation. In Model.step(), we define that at every time-step all agents will perform the action wealth_transfer. In Model.update(), we calculate and record the current Gini coefficient. And in Model.end(), we further record the wealth of each agent.

[6]:
class WealthModel(ap.Model):

    """ A simple model of random wealth transfers """

    def setup(self):

        self.add_agents(self.p.agents, WealthAgent)

    def step(self):

        self.agents.wealth_transfer()

    def update(self):

        self.record('Gini Coefficient', gini(self.agents.wealth))

    def end(self):

        self.agents.record('wealth')

Running a simulation

To run a simulation, we define a dictionary of parameters that defines the number of agents and the number of steps that the model will run.

[7]:
parameters = {
    'agents': 100,
    'steps': 100
}

To perform a simulation, we initialize our model with these parameters and call the method Model.run, which returns a DataDict of our recorded variables and measures.

[8]:
model = WealthModel(parameters)
results = model.run()
Completed: 100 steps
Run time: 0:00:00.183086
Simulation finished

To visualize the evolution of our Gini Coefficient, we can use pandas.DataFrame.plot().

[9]:
data = results.variables.WealthModel
ax = data.plot()
_images/agentpy_wealth_transfer_23_0.png

And to visualize the final distribution of wealth, we can use pandas.DataFrame.hist().

[10]:
data = results.variables.WealthAgent
data.hist(bins=range(data.wealth.max()+1))

plt.title('')
plt.xlabel('Wealth')
plt.ylabel('Number of agents')
plt.show()
_images/agentpy_wealth_transfer_25_0.png

What we get is a Boltzmann distribution. For those interested to understand this result, you can read more about it here.