Kala: agent-based econ games
Project description
Kala, agent-based econ games
This package defines a general framework to implement different agent-based models (ABMs). One of the most important things that we aim to support is a networked topology, with agents being represented as nodes that can only be matched against their neighbours. However, we also support games that do not include a network topology.
To begin with, we have used the framework to coded the model presented in Ernst, Ekkehard. ‘The Evolution of Time Horizons for Economic Development’, 2004. [Ernst04] (DOI). We added some extensions, including support for networks.
Installation
The package is written in Python (minimal version: 3.10). We recommend that the installation is made inside a virtual environment and to do this, one can use either conda (recommended in order to control the Python version) or the Python builtin venv (if the system's version of Python is compatible).
Create a virtual environment using Python's builtin venv
The first step is running
$ python -m venv kala
This creates a folder that contains the virtual environment kala (a different name can be used; change below as appropriate). We activate it using
$ source kala/bin/activate
Using conda (recommended)
The tool conda, which comes bundled with Anaconda has the advantage that it lets us specify the version of Python that we want to use. Python>=3.10 is required.
A new environment can be created with
$ conda create -n kala python=3.10 -y
Like before, the environment's name can be anything else instead of kala (simply change the name below). We activate it using
$ conda activate kala
Local install of the package
Once we are working inside an active virtual environment, we install (the dependencies and) the package by running
[$ pip install -r requirements.txt]
$ pip install -e .
Coming soon
In the future, we would like to completely package the code and publish it in PyPI so that a local installation isn't needed any more, and the installation can be solved directly by the package manager of choice.
User guide
The user-facing interface of the package is located under kala.models but the concrete classes have been added to the top-level package so that they can be imported directly.
Before going into more detail, we'll give and comment a full example that creates a working game.
We start with 3 imports
import networkx as nx
from kala import InvestorAgent, CooperationStrategy, DiscreteTwoByTwoGame, SimpleGraph
We've imported Networkx as a handy tool to create a pre-defined network from which we "steal" the edges, but other ways of creating graph topologies will be supported in the future.
The first step is defining the agents.
num_nodes = 10
# A list of InvestorAgents, half of them savers and half non-savers
is_saver = savers = [True, False] * 5
agents = [InvestorAgent(is_saver=is_saver[i]) for i in range(num_nodes)]
Next, we create a network (with NetworkX) and we instantiate our own SimpleGraph which can take a NetworkX object as argument. We also pass the agents so that there is a one-to-one mapping between the nodes in the graph and the individual agents.
g = nx.barabasi_albert_graph(num_nodes, 8, seed=0)
G = SimpleGraph(g, nodes=agents)
We initialise a strategy
coop = CooperationStrategy(
stochastic=True, # True to draw random numbers
differential_efficient=0.5, # eta_hat_hat = 1 + differential_efficient
differential_inefficient=0.05, # eta_hat = 1 - differential_inefficient
rng=0, # this seeds the random number generator (not needed in general)
)
and then we combine the graph (which already encompasses the agents) and the strategy into a game.
game = DiscreteTwoByTwoGame(G, coop)
All we need to do now is call a method and, if we want, keep track of different properties like so:
for _ in range(10):
game.play_round()
wealth, num_savers = game.get_total_wealth(), game.get_num_savers()
print(f"wealth={wealth:.2f}, {num_savers=}")
More complicated configurations can be added in several places. For example, we can create agents that have memory, an update rule, and some amount of homophily by calling
from kala import FractionMemoryRule
agents = [
InvestorAgent(
is_saver=is_saver[i],
updates_from_n_last_games=5,
update_rule=FractionMemoryRule(fraction=0.75),
homophily=0.8
)
for i in range(num_nodes)
]
Agents
Agents should be the starting point of any model. Agents are created by passing arguments that are specific to the model, but that can be broken down into two categories (traits and properties). Once created, an agent should have all of the necessary information to call the update() method which for example adds a payoff to the running total of the agent.
In order to implement the models in [Ernst04], we define the class InvestorAgent which takes the following arguments:
is_saver: Boolean indicating whether the agent is a saver or not. This trait is important because it will influence the payoff that our agent will get once they play an opponent that can have the same trait or not.homophily: Normally, agents are paired using the topology of a graph in which they are the nodes. The homophily is an optional probability (a number between [0, 1]) which controls whether agents should preferentially select opponents with the same trait or avoid them entirely.updates_from_n_last_games: Agents can have a memory ofnprevious games. This goes hand-in hand with the...update_rule: A rule which codifies what the agent should do with the outcome of previousngames. Normally, an agent records whether their payoff has been smaller than that of its opponent, so they might decide to change their saver trait after loosing half of thengames, or allngames.
Traits and properties
Traits and properties belong to agents. Roughly speaking, traits were thought as fixed and properties as changing in time, but the distinction is no longer clear-cut and in the future we might decide to deprecate one of the two classes.
Memory rules
Rules also belong to agents. They handle all the logic of deciding whether the agent should flip its saving strategy based on the past n games. The following rules are available (ordered from simplest to most general):
AnyPastMemoryRuleAllPastMemoryRuleAverageMemoryRuleFractionMemoryRuleWeightedMemoryRule
A description of the rules will follow shortly.
Graphs
Agents are initialised and organised inside a SimpleGraph which encodes the topology, that is, the connections of agents. For the time being, the connections are fixed but in the future this can easily be extended so that edges can be re-wired as a game progresses.
Strategies
A strategy encodes what two agents should do when they "encounter" and they play each other. The main method exposed is calculate_payoff().
Following [Ernst04], we coded the class CooperationStrategy which draws payoffs from a log-normal distribution with mean 1.0 and a variance (and therefore risk) that depends on the specialization of each agent. The specialization depends the two values:
differential_inefficient: When a saver meets a non-saver, their specialization is set to1 - differential_inefficientwhich in the paper's notation is $\hat{\eta}$.differential_efficient: When two savers play each other, they decide to cooperate and they select a higher specialization set to1 + differential_efficient($\hat{\hat{\eta}}$ in the paper).
Games
A game is defined by the graph (which itself already contains initialised agents) and the strategy. It handles the logic of matching two (or more) opponents calculating and distributing the payoffs. The most important method is play_round(), but there are also convenient methods to get summaries such as get_total_wealth() or get_num_savers().
In order to implement the models [Ernst04], we use DiscreteTwoByTwoGame.
Contributing
The package has a couple of utilities (linters, formatters, etc.) that automatically run checks and help correct simple problems.
To run on new contributions, use
$ pre-commit run --all-files
You might find it useful to create an alias, for example alias pcr='pre-commit run --all-files.
Extending the existing models
In all cases, we define a base class which can be extended easily to define new models. For example, one could define a new set of agent "traits" like so:
class MyNewTraits(BaseAgentTraits):
color: str
age: int
is_tall: bool
When possible, we have have strived to make all such sub-classes interoperable meaning that other parts of the code tend not to assume any functionality other than the one specified in the base class (there are exceptions to this but are working on getting around them).
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kala_econ_games-0.1.0.tar.gz.
File metadata
- Download URL: kala_econ_games-0.1.0.tar.gz
- Upload date:
- Size: 24.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: pdm/2.10.4 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
49314f63effa459312af2ee51af689daea2c3f00117bd3fd52233585b9f955cc
|
|
| MD5 |
8a76d84d352995bd9a8c857b9036a92d
|
|
| BLAKE2b-256 |
85b8188cf166afd1648e0227cec7a6d24236b9b5283d9f5e14879c04c06c399a
|
File details
Details for the file kala_econ_games-0.1.0-py3-none-any.whl.
File metadata
- Download URL: kala_econ_games-0.1.0-py3-none-any.whl
- Upload date:
- Size: 22.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: pdm/2.10.4 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c913712d906c4c11a574ee9db1ac324f2b3a27431b6a3f40b93abd467c7a52e
|
|
| MD5 |
d8237e631f91c3f1c80c0a1b65d385f4
|
|
| BLAKE2b-256 |
8cd1a91c281407e86cb27094a39b0ea4b67d157e0cc299a155126c06b20fe8e9
|