Skip to content

Update bank reserves example #250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
22 changes: 10 additions & 12 deletions examples/bank_reserves/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

## Summary

A highly abstracted, simplified model of an economy, with only one type of agent and a single bank representing all banks in an economy. People (represented by circles) move randomly within the grid. If two or more people are on the same grid location, there is a 50% chance that they will trade with each other. If they trade, there is an equal chance of giving the other agent $5 or $2. A positive trade balance will be deposited in the bank as savings. If trading results in a negative balance, the agent will try to withdraw from its savings to cover the balance. If it does not have enough savings to cover the negative balance, it will take out a loan from the bank to cover the difference. The bank is required to keep a certain percentage of deposits as reserves. If run.py is used to run the model, then the percent of deposits the bank is required to retain is a user settable parameter. The amount the bank is able to loan at any given time is a function of the amount of deposits, its reserves, and its current total outstanding loan amount.
A highly abstracted, simplified model of an economy, with only one type of agent and a single bank representing all banks in an economy. People (represented by circles) move randomly within the grid. If two or more people are on the same grid location, there is a 50% chance that they will trade with each other. If they trade, there is an equal chance of giving the other agent $5 or $2. A positive trade balance will be deposited in the bank as savings. If trading results in a negative balance, the agent will try to withdraw from its savings to cover the balance. If it does not have enough savings to cover the negative balance, it will take out a loan from the bank to cover the difference. The bank is required to keep a certain percentage of deposits as reserves. If app.py is used to run the model, then the percent of deposits the bank is required to retain is a user settable parameter. The amount the bank is able to loan at any given time is a function of the amount of deposits, its reserves, and its current total outstanding loan amount.

The model demonstrates the following Mesa features:
- MultiGrid for creating shareable space for agents
- CellAgent object inheritance
- OrthogonalMooreGrid for creating shareable space for agents
- DataCollector for collecting data on individual model runs
- Slider for adjusting initial model parameters
- ModularServer for visualization of agent interaction
- Agent object inheritance
- Solara for visualization of agent interaction
- Using a BatchRunner to collect data on multiple combinations of model parameters

## Installation
Expand All @@ -22,13 +22,13 @@ To install the dependencies use pip and the requirements.txt in this directory.

## Interactive Model Run

To run the model interactively, use `mesa runserver` in this directory:
To run the model interactively, use `solara` in this directory:

```
$ mesa runserver
$ solara run app.py
```

Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/), select the model parameters, press Reset, then Start.
Then open your browser to [http://127.0.0.1:8765/](http://127.0.0.1:8765/), select the model parameters, press Reset, then Start.

## Batch Run

Expand All @@ -43,11 +43,9 @@ To update the parameters to test other parameter sweeps, edit the list of parame

## Files

* ``bank_reserves/random_walker.py``: This defines a class that inherits from the Mesa Agent class. The main purpose is to provide a method for agents to move randomly one cell at a time.
* ``bank_reserves/agents.py``: Defines the People and Bank classes.
* ``bank_reserves/model.py``: Defines the Bank Reserves model and the DataCollector functions.
* ``bank_reserves/server.py``: Sets up the interactive visualization server.
* ``run.py``: Launches a model visualization server.
* ``agents.py``: Defines the People and Bank classes.
* ``model.py``: Defines the Bank Reserves model and the DataCollector functions.
* ``app.py``: Sets up the interactive solara server for visualization.
* ``batch_run.py``: Basically the same as model.py, but includes a Mesa BatchRunner. The result of the batch run will be a .csv file with the data from every step of every run.

## Further Reading
Expand Down
71 changes: 71 additions & 0 deletions examples/bank_reserves/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from agents import Person
from mesa.visualization import (
Slider,
SolaraViz,
make_plot_component,
make_space_component,
)
from model import BankReservesModel

"""
Citation:
The following code was adapted from server.py at
https://github.com/projectmesa/mesa/blob/main/examples/wolf_sheep/wolf_sheep/server.py
Accessed on: November 2, 2017
Author of original code: Taylor Mutch
"""


def person_portrayal(agent):
if agent is None:
return

portrayal = {}

# update portrayal characteristics for each Person object
if isinstance(agent, Person):
color = "tab:blue"
# set agent color based on savings and loans
if agent.savings > agent.model.rich_threshold:
color = "green"
if agent.savings < 10 and agent.loans < 10:
color = "tab:blue"
if agent.loans > 10:
color = "tab:red"

portrayal["color"] = color

return portrayal


model_params = {
"init_people": Slider(
label="People",
value=25,
min=1,
max=200,
),
"rich_threshold": Slider(
label="Rich Threshold",
value=10,
min=1,
max=20,
),
"reserve_percent": Slider(
label="Reserves",
value=50,
min=1,
max=100,
),
}

SpacePlot = make_space_component(person_portrayal)
CategoryPlot = make_plot_component(["Rich", "Poor", "Middle Class"])
model = BankReservesModel()

page = SolaraViz(
BankReservesModel(),
components=[SpacePlot, CategoryPlot],
model_params=model_params,
name="Bank Reserves",
)
90 changes: 0 additions & 90 deletions examples/bank_reserves/bank_reserves/server.py

This file was deleted.

11 changes: 5 additions & 6 deletions examples/bank_reserves/batch_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,23 @@
every step of every run.
"""

import mesa
import pandas as pd
from bank_reserves.model import BankReservesModel
from mesa.batchrunner import batch_run
from model import BankReservesModel


def main():
# parameter lists for each parameter to be tested in batch run
br_params = {
"width": 20,
"height": 20,
"init_people": [25, 100],
"rich_threshold": [5, 10],
"reserve_percent": 5,
}

# The existing batch run logic here
data = mesa.batch_run(
BankReservesModel,
br_params,
)
data = batch_run(model_cls=BankReservesModel, parameters=br_params)
br_df = pd.DataFrame(data)
br_df.to_csv("BankReservesModel_Data.csv")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@

import mesa
import numpy as np
from agents import Bank, Person
from mesa.experimental.cell_space import OrthogonalMooreGrid

from .agents import Bank, Person

"""
If you want to perform a parameter sweep, call batch_run.py instead of run.py.
For details see batch_run.py in the same directory as run.py.
Expand Down Expand Up @@ -97,19 +96,14 @@ class BankReservesModel(mesa.Model):
amount.
"""

# grid height
grid_h = 20
# grid width
grid_w = 20

"""init parameters "init_people", "rich_threshold", and "reserve_percent"
are all set via Slider"""

def __init__(
self,
height=grid_h,
width=grid_w,
init_people=2,
height=20,
width=20,
init_people=5,
rich_threshold=10,
reserve_percent=50,
):
Expand Down Expand Up @@ -158,7 +152,3 @@ def step(self):
self.agents.shuffle_do("step")
# collect data
self.datacollector.collect(self)

def run_model(self):
for i in range(self.run_time):
self.step()
9 changes: 5 additions & 4 deletions examples/bank_reserves/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
itertools
mesa~=2.0
numpy
pandas
mesa==3.1.4
solara
matplotlib
altair
networkx
3 changes: 0 additions & 3 deletions examples/bank_reserves/run.py

This file was deleted.

13 changes: 6 additions & 7 deletions examples/boltzmann_wealth_model_network/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ In this network implementation, agents must be located on a node, with a limit o

As the model runs, the distribution of wealth among agents goes from being perfectly uniform (all agents have the same starting wealth), to highly skewed -- a small number have high wealth, more have none at all.

JavaScript library used in this example to render the network: [sigma.js](http://sigmajs.org/).

## Installation

Expand All @@ -22,19 +21,19 @@ To install the dependencies use pip and the requirements.txt in this directory.

## How to Run

To run the model interactively, run ``mesa runserver`` in this directory. e.g.
To run the model interactively, run ``solara run app.py`` in this directory.

```
$ mesa runserver
$ solara run app.py
```

Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and press Reset, then Run.
Then open your browser to [http://127.0.0.1:8765/](http://127.0.0.1:8765/) and press Reset, then Run.

## Files

* ``run.py``: Launches a model visualization server.
* ``model.py``: Contains the agent class, and the overall model class.
* ``server.py``: Defines classes for visualizing the model (network layout) in the browser via Mesa's modular server, and instantiates a visualization server.
* ``agent.py``: Defines the agent class.
* ``model.py``: Defines the model class.
* ``app.py`` : Defines the visualization and spins up a solara server.

## Further Reading

Expand Down
Empty file.
20 changes: 20 additions & 0 deletions examples/boltzmann_wealth_model_network/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from mesa.experimental.cell_space import CellAgent


class MoneyAgent(CellAgent):
"""An agent with fixed initial wealth"""

def __init__(self, model):
super().__init__(model)
self.wealth = 1

def give_money(self):
neighbours = list(self.cell.neighborhood.agents)
if len(neighbours) > 0:
other = self.random.choice(neighbours)
other.wealth += 1
self.wealth -= 1

def step(self):
if self.wealth > 0:
self.give_money()
Loading
Loading