![EGTtools](docs/images/logo-full.png)
# Toolbox for Evolutionary Game Theory
[![PyPI version](https://badge.fury.io/py/egttools.svg)](https://badge.fury.io/py/egttools)
[![Documentation Status](https://readthedocs.org/projects/egttools/badge/?version=latest)](https://egttools.readthedocs.io/en/latest/?badge=latest)
[![Build](https://github.com/Socrats/EGTTools/actions/workflows/ci.yml/badge.svg)](https://github.com/Socrats/EGTTools/actions/workflows/ci.yml) [![Join the chat at https://gitter.im/EGTTools/community](https://badges.gitter.im/EGTTools/community.svg)](https://gitter.im/EGTTools/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/Socrats/EGTTools/HEAD?labpath=docs%2Fexamples)
[![DOI](https://zenodo.org/badge/242180332.svg)](https://zenodo.org/badge/latestdoi/242180332)
[//]: # ([![PyPI Downloads](https://img.shields.io/pypi/dm/egttools.svg?label=PyPI%20downloads)](https://pypi.org/project/egttools/))
**EGTtools** provides a centralized repository with analytical and numerical methods to study/model game theoretical
problems under the Evolutionary Game Theory (EGT) framework.
This library is composed of two parts:
- a set of analytical methods implemented in Python 3
- a set of computational methods implemented in C++ with (Python 3 bindings)
The second typed is used in cases where the state space is too big to solve analytically, and thus require estimating
the model parameters through monte-carlo simulations. The C++ implementation provides optimized computational methods
that can run in parallel in a reasonable time, while Python bindings make the methods easily accecible to a larger range
of researchers.
## Table of Contents
1. [Requirements](#requirements)
2. [Downloading sources](#downloading-sources)
3. [Examples of usage](#examples-of-usage)
4. [Documentation](#documentation)
5. [Caveats](#caveats)
6. [Citing](#citing)
7. [Licence](#licence)
8. [Acknowledgements](#acknowledgements)
## Requirements
To be able to install EGTtools, you must have:
* A recent version of Linux (only tested on Ubuntu), MacOSX (Mojave or above) or Windows
* [**CMake**](https://cmake.org) version 3.17 or higher
* [**C++ 17**](https://en.cppreference.com/w/cpp/17)
* [**Eigen**](https://eigen.tuxfamily.org/index.php?title=Main_Page) 3.3.*
* [**Boost**](https://www.boost.org/) 1.80.*
* **Python** 3.7 or higher
* If you want support for parallel operations you should install [**OpenMP**](https://www.openmp.org)
* Ideally, you should also install [**OpenBLAS**](https://www.openblas.net), which offers optimized implementations of
linear algebra kernels for several processor architectures, and install numpy and scipy versions that use it.
## Downloading sources
When cloning the repository you should also clone the submodules so that pybind11 is downloaded. You can do that by
running:
```bash
git clone --recurse-submodules -j8 https://github.com/Socrats/EGTTools.git
```
## Installation
### With pip
You can install `egttools` directly from PyPi with:
```bash
pip install egttools
```
Currently, only the Linux build supports OpenMP parallelization for numerical simulations. This should normally be ok
for most applications, since numerical simulations are heavy and should be run on High Power Computing (HPC) clusters
which normally run Linux distributions.
We are investigating how to provide support for OpenMP in both Windows and Mac. In the meantime, if you really want to
run numerical simulations on either of the two platforms, you should follow the compilation instructions below and try
to link OpenMP for your platform yourself. Please, if you manage to do so, open an issue or a pull request with your
solutions.
**Note**: For Apple M1 (arm64) you should install using ```pip install egttools --no-deps``` so that pip does not
install the dependencies of the package. You should then install these dependencies through a virtual environment
created with [miniforge](https://github.com/conda-forge/miniforge) (see [Caveats](#caveats) for more information on why
this is necessary). Once you have miniforge installed you can do the following (assuming that you are in the base
miniforge environment):
```bash
conda create -n egtenv python=3.9
conda activate egtenv
conda install numpy
conda install scipy
conda install matplotlib
conda install networkx
conda install seaborn
```
### Build from source
To build `egttools` from source follow the following steps.
To **install all required packages** run:
```bash
python -m venv egttools-env
source egttools-env/bin/activate
pip install -r requirements.txt
```
Or with anaconda:
```bash
conda env create -f environment.yml
conda activate egttools-env
```
Also, to make your virtual environment visible to jupyter:
```bash
conda install ipykernel # or pip install ipykernel
python -m ipykernel install --user --name=egttools-env
```
You can **build EGTtools** in your virtual environment by running:
```bash
pip install build
cd <path>
python -m build
```
Where ```<path>``` represents the path to the EGTtools folder. If you are running this while inside the EGTtools folder,
then ```<path>``` is simply ```./```.
Finally, you can install EGTtools in **development** mode, this will allow the installation to update with new
modifications to the package:
```bash
python -m pip install -e <path>
```
If you don't want development mode, you can skip the option ```-e```.
## Examples of usage
The [Analytical example](docs/examples/hawk_dove_dynamics.ipynb) is a jupyter notebook which analyses analytically the
evolutionary dynamics in a (2-person, 2-actions, one-shot) Hawk-Dove game.
The [Numerical example](docs/examples/normal_form_game_mc_simulations.ipynb) is a jupyter notebook which analyses
through numerical simulations the evolutionary dynamics in a (2-person, 2-actions, one-shot) Hawk-Dove game.
The [Invasion example](docs/examples/plot_invasion_diagram.ipynb) is a jupyter notebook calculates the fixation
probabilities and stationary distribution of a Normal Form Game with 5 strategies and then plots an invasion diagram.
The [Plot 2 Simplex](docs/examples/plot_simplex.ipynb) is a jupyter notebook that shows how to use EGTtools to plot the
evolutionary dynamics in a 2 Simplex (a triangle), both for infinite and finite populations.
You can also check all these notebooks and a bit more on
this [tutorial repository](https://github.com/Socrats/egt-tutorial)
For example, assuming the following payoff matrix:
![A=\begin{pmatrix} -0.5 & 2 \\ 0 & 0 \end{pmatrix}](https://latex.codecogs.com/gif.latex?A=\begin{pmatrix}&space;-0.5&space;&&space;2&space;\\\\&space;0&space;&&space;0&space;\end{pmatrix})
You can plot the gradient of selection in a finite population of \(Z=100\) individuals and assuming and intensity of
selection ![\beta=1](https://latex.codecogs.com/gif.latex?\beta=1) in the following way:
```python
import numpy as np
from egttools.analytical import PairwiseComparison
from egttools.games import Matrix2PlayerGameHolder
beta = 1;
Z = 100;
nb_strategies = 2;
A = np.array([[-0.5, 2.], [0., 0.]])
pop_states = np.arange(0, Z + 1, 1)
game = Matrix2PlayerGameHolder(nb_strategies, payoff_matrix=A)
# Instantiate evolver and calculate gradient
evolver = PairwiseComparison(population_size=Z, game=game)
gradients = np.array([evolver.calculate_gradient_of_selection(beta, np.array([x, Z - x])) for x in range(Z + 1)])
```
Afterwards, you can plot the results with:
```python
from egttools.plotting import plot_gradients
plot_gradients(gradients, figsize=(4, 4), fig_title="Hawk-Dove game stochastic dynamics",
marker_facecolor='white',
xlabel="frequency of hawks (k/Z)", marker="o", marker_size=20, marker_plot_freq=2)
```
![Gradient of selection](docs/images/hawk_dove_analytical_gradient.png)
And you can plot the stationary distribution for a mutation
rate ![\mu=1eˆ{-3}](https://latex.codecogs.com/gif.latex?\mu=1e-3) with:
```python
import matplotlib.pyplot as plt
from egttools.utils import calculate_stationary_distribution
transitions = evolver.calculate_transition_matrix(beta, mu=1e-3)
stationary_with_mu = calculate_stationary_distribution(transitions.transpose())
fig, ax = plt.subplots(figsize=(5, 4))
fig.patch.set_facecolor('white')
lines = ax.plot(np.arange(0, Z + 1) / Z, stationary_with_mu)
plt.setp(lines, linewidth=2.0)
ax.set_ylabel('stationary distribution', size=16)
ax.set_xlabel('$k/Z$', size=16)
ax.set_xlim(0, 1)
plt.show()
```
![Stationary distribution](docs/images/hawk_dove_analytical_full_sd.png)
We can obtain the same results through numerical simulations. The error will depend on how many independent simulations
you perform and for how long you let the simulation run. While a future implementation will offer an adaptive method to
vary these parameters depending on the variations between the estimated distributions, for the moment it is important
that you let the simulation run for enough generations after it has achieved a steady state. Here is a comparison
between analytical and numerical results:
```python
from egttools.numerical import PairwiseComparisonNumerical
from egttools.games import NormalFormGame
# Instantiate the game
game = NormalFormGame(1, A)
numerical_evolver = PairwiseComparisonNumerical(Z, game, 1000000)
# We do this for different betas
betas = np.logspace(-4, 1, 50)
stationary_points = []
# numerical simulations
for i in range(len(betas)):
stationary_points.append(numerical_evolver.stationary_distribution(30, int(1e6), int(1e3),
betas[i], 1e-3))
stationary_points = np.asarray(stationary_points)
# Now we estimate the probability of Cooperation for each possible state
state_frequencies = np.arange(0, Z + 1) / Z
coop_level = np.dot(state_frequencies, stationary_points.T)
```
Lastly, we plot the results:
```python
from sklearn.metrics import mean_squared_error
mse = mean_squared_error(1 - coop_level_analytical, coop_level)
# Finally, we plot and compare visually (and check how much error we get)
fig, ax = plt.subplots(figsize=(7, 5))
# ax.scatter(betas, coop_level, label="simulation")
ax.scatter(betas, coop_level_analytical, marker='x', label="analytical")
ax.scatter(betas, coop_level, marker='o', label="simulation")
ax.text(0.01, 0.535, 'MSE = {0:.3e}'.format(mse), style='italic',
bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})
ax.legend()
ax.set_xlabel(r'$\beta$', fontsize=15)
ax.set_ylabel('Cooperation level', fontsize=15)
ax.set_xscale('log')
plt.show()
```
![Comparison numerical analytical](docs/images/hawk_dove_comparison.png)
Finally, you may also visualize the result of independent simulations:
```python
init_states = np.random.randint(0, Z + 1, size=10, dtype=np.uint64)
output = []
for i in range(10):
output.append(evolver.run(int(1e6), 1, 1e-3,
[init_states[i], Z - init_states[i]]))
# Plot each year's time series in its own facet
fig, ax = plt.subplots(figsize=(5, 4))
for run in output:
ax.plot(run[:, 0] / Z, color='gray', linewidth=.1, alpha=0.6)
ax.set_ylabel('k/Z')
ax.set_xlabel('generation')
ax.set_xscale('log')
```
![Comparison numerical analytical](docs/images/hawk_dove_indep_runs.png)
### Plotting the dynamics in a 2 Simplex
EGTtools can also be used to visualize the evolutionary dynamics in a 2 Simplex. In the example bellow, we use the
`egttools.plotting.plot_replicator_dynamics_in_simplex` which calculates the gradients on a simplex given an initial
payoff matrix and returns a `egttools.plotting.Simplex2D` object which can be used to plot the 2 Simplex.
```python
import numpy as np
import matplotlib.pyplot as plt
from egttools.plotting import plot_replicator_dynamics_in_simplex
payoffs = np.array([[1, 0, 0],
[0, 2, 0],
[0, 0, 3]])
type_labels = ['A', 'B', 'C']
fig, ax = plt.subplots(figsize=(10, 8))
simplex, gradient_function, roots, roots_xy, stability = plot_replicator_dynamics_in_simplex(payoffs, ax=ax)
plot = (simplex.add_axis(ax=ax)
.draw_triangle()
.draw_gradients(zorder=0)
.add_colorbar()
.add_vertex_labels(type_labels)
.draw_stationary_points(roots_xy, stability)
.draw_trajectory_from_roots(gradient_function,
roots,
stability,
trajectory_length=15,
linewidth=1,
step=0.01,
color='k', draw_arrow=True,
arrowdirection='right',
arrowsize=30, zorder=4, arrowstyle='fancy')
.draw_scatter_shadow(gradient_function, 300, color='gray', marker='.', s=0.1, zorder=0)
)
ax.axis('off')
ax.set_aspect('equal')
plt.xlim((-.05, 1.05))
plt.ylim((-.02, simplex.top_corner + 0.05))
plt.show()
```
![2 Simplex dynamics in infinite populations](docs/images/simplex_example_infinite_pop_1.png)
The same can be done for finite populations, with the added possibility to plot the stationary distribution inside the
triangle (see [simplex plotting](docs/examples/plot_simplex.ipynb)
and [simplified simplex plotting](docs/examples/plot_simplex_simplified.ipynb)
for a more in depth examples).
## Documentation
The [analytical](src/egttools/analytical/sed_analytical.py) module contains classes and functions that you may use to
investigate the evolutionary dynamics in N-player games. For now only the replicator dynamics (for infinite populations)
and the Pairwise Comparison imitation process (for finite populations) are implemented.
When your state-space is too big (in finite populations), it might become computationally hard to solve the system
analytically. Thus, we provide an efficient [numerical](cpp/src/egttools.cpp) module written in C++ and compiled to
Python. You may use it to estimate the fixation probabilities and stationary distribution through Monte-Carlo
simulations, or perform individual runs of the Moran process.
You can find more information in the [ReadTheDocs](https://egttools.readthedocs.io/en/latest/) documentation.
### Caveats
1. On Apple M1 (arm64) you should install (for the moment) [miniforge](https://github.com/conda-forge/miniforge), create
a conda environment using it, and install EGTtools from the conda environment.
2. In MacOSX it is assumed that you have [Homebrew](https://brew.sh) installed.
3. You should install libomp with homebrew ``brew install libomp`` if you want to have support for parallel operations (
there is a big difference in computation time).
4. You **must** have Eigen 3.3.* installed.
5. You **do not** need any of the above if you install EGTtools through ```pip install egttools --no-deps```. However,
on Apple M1 (arm64) you still need to install the dependencies through miniforge, since only there you can find a
scipy wheel that supports this architecture.
## Citing
If you use EGTtools in your publications, please cite it in the following way with bibtex:
```latex
@article{Fernandez2023,
author = {Fernández Domingos, Elias and Santos, Francisco C. and Lenaerts, Tom},
title = {EGTtools: Evolutionary game dynamics in Python},
journal = {iScience},
volume = {26},
number = {4},
pages = {106419},
year = {2023},
issn = {2589-0042},
doi = {https://doi.org/10.1016/j.isci.2023.106419}
}
```
Or in text format:
```
Fernández Domingos, E., Santos, F. C. & Lenaerts, T. EGTtools: Evolutionary game dynamics in Python. iScience 26, 106419 (2023).
```
And to cite the current version of EGTtools you can use:
```latex
@misc{Fernandez2020,
author = {Fernández Domingos, Elias},
title = {EGTTools: Toolbox for Evolutionary Game Theory (0.1.12)},
year = {2022},
month = {Dec},
journal = {Zenodo},
doi = {10.5281/zenodo.7458631}
}
```
Moreover, you may find our article at [here](https://www.cell.com/iscience/pdf/S2589-0042(23)00496-0.pdf).
## Licence
* EGTtools is released under the [GNU General Public Licence](LICENSE), version 3 or later.
* [pybind11](https://github.com/pybind/pybind11) is released under [a BSD-style license](pybind11/LICENSE).
## Acknowledgements
* Great parts of this project have been possible thanks to the help of
[Yannick Jadoul](https://github.com/YannickJadoul) author of
[Parselmouth](https://github.com/YannickJadoul/Parselmouth)
and [Eugenio Bargiacchi](https://github.com/Svalorzen) author of [AIToolBox](https://github.com/Svalorzen/AI-Toolbox).
They are both great programmers and scientists, so it is always a good idea to check out their work.
* EGTtools makes use of the amazing [pybind11](https://github.com/pybind/pybind11). library to provide a Python
interface for optimized monte-carlo simulations written in C++.
Raw data
{
"_id": null,
"home_page": "https://github.com/Socrats/EGTTools",
"name": "egttools",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "evolutionary game theory,social dynamics,evolutionary dynamics",
"author": "Elias F. Domingos",
"author_email": "elias.fernandez.domingos@vub.be",
"download_url": "https://files.pythonhosted.org/packages/3b/b5/5d1ae9185d1d1e8d8d68efcc09c0dea8ac157ac7cfd83ef2736d662520ae/egttools-0.1.13.5.tar.gz",
"platform": null,
"description": "![EGTtools](docs/images/logo-full.png)\n\n# Toolbox for Evolutionary Game Theory\n\n[![PyPI version](https://badge.fury.io/py/egttools.svg)](https://badge.fury.io/py/egttools)\n[![Documentation Status](https://readthedocs.org/projects/egttools/badge/?version=latest)](https://egttools.readthedocs.io/en/latest/?badge=latest)\n[![Build](https://github.com/Socrats/EGTTools/actions/workflows/ci.yml/badge.svg)](https://github.com/Socrats/EGTTools/actions/workflows/ci.yml) [![Join the chat at https://gitter.im/EGTTools/community](https://badges.gitter.im/EGTTools/community.svg)](https://gitter.im/EGTTools/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/Socrats/EGTTools/HEAD?labpath=docs%2Fexamples)\n[![DOI](https://zenodo.org/badge/242180332.svg)](https://zenodo.org/badge/latestdoi/242180332)\n\n[//]: # ([![PyPI Downloads](https://img.shields.io/pypi/dm/egttools.svg?label=PyPI%20downloads)](https://pypi.org/project/egttools/))\n\n**EGTtools** provides a centralized repository with analytical and numerical methods to study/model game theoretical\nproblems under the Evolutionary Game Theory (EGT) framework.\n\nThis library is composed of two parts:\n\n- a set of analytical methods implemented in Python 3\n- a set of computational methods implemented in C++ with (Python 3 bindings)\n\nThe second typed is used in cases where the state space is too big to solve analytically, and thus require estimating\nthe model parameters through monte-carlo simulations. The C++ implementation provides optimized computational methods\nthat can run in parallel in a reasonable time, while Python bindings make the methods easily accecible to a larger range\nof researchers.\n\n## Table of Contents\n\n1. [Requirements](#requirements)\n2. [Downloading sources](#downloading-sources)\n3. [Examples of usage](#examples-of-usage)\n4. [Documentation](#documentation)\n5. [Caveats](#caveats)\n6. [Citing](#citing)\n7. [Licence](#licence)\n8. [Acknowledgements](#acknowledgements)\n\n## Requirements\n\nTo be able to install EGTtools, you must have:\n\n* A recent version of Linux (only tested on Ubuntu), MacOSX (Mojave or above) or Windows\n* [**CMake**](https://cmake.org) version 3.17 or higher\n* [**C++ 17**](https://en.cppreference.com/w/cpp/17)\n* [**Eigen**](https://eigen.tuxfamily.org/index.php?title=Main_Page) 3.3.*\n* [**Boost**](https://www.boost.org/) 1.80.*\n* **Python** 3.7 or higher\n* If you want support for parallel operations you should install [**OpenMP**](https://www.openmp.org)\n* Ideally, you should also install [**OpenBLAS**](https://www.openblas.net), which offers optimized implementations of\n linear algebra kernels for several processor architectures, and install numpy and scipy versions that use it.\n\n## Downloading sources\n\nWhen cloning the repository you should also clone the submodules so that pybind11 is downloaded. You can do that by\nrunning:\n\n```bash\ngit clone --recurse-submodules -j8 https://github.com/Socrats/EGTTools.git\n```\n\n## Installation\n\n### With pip\n\nYou can install `egttools` directly from PyPi with:\n\n```bash\npip install egttools\n```\n\nCurrently, only the Linux build supports OpenMP parallelization for numerical simulations. This should normally be ok\nfor most applications, since numerical simulations are heavy and should be run on High Power Computing (HPC) clusters\nwhich normally run Linux distributions.\n\nWe are investigating how to provide support for OpenMP in both Windows and Mac. In the meantime, if you really want to\nrun numerical simulations on either of the two platforms, you should follow the compilation instructions below and try\nto link OpenMP for your platform yourself. Please, if you manage to do so, open an issue or a pull request with your\nsolutions.\n\n**Note**: For Apple M1 (arm64) you should install using ```pip install egttools --no-deps``` so that pip does not\ninstall the dependencies of the package. You should then install these dependencies through a virtual environment\ncreated with [miniforge](https://github.com/conda-forge/miniforge) (see [Caveats](#caveats) for more information on why\nthis is necessary). Once you have miniforge installed you can do the following (assuming that you are in the base\nminiforge environment):\n\n```bash\nconda create -n egtenv python=3.9\nconda activate egtenv\nconda install numpy\nconda install scipy\nconda install matplotlib\nconda install networkx\nconda install seaborn\n```\n\n### Build from source\n\nTo build `egttools` from source follow the following steps.\n\nTo **install all required packages** run:\n\n```bash\npython -m venv egttools-env\nsource egttools-env/bin/activate\npip install -r requirements.txt\n```\n\nOr with anaconda:\n\n```bash\nconda env create -f environment.yml\nconda activate egttools-env\n```\n\nAlso, to make your virtual environment visible to jupyter:\n\n```bash\nconda install ipykernel # or pip install ipykernel\npython -m ipykernel install --user --name=egttools-env\n```\n\nYou can **build EGTtools** in your virtual environment by running:\n\n```bash\npip install build\ncd <path>\npython -m build\n```\n\nWhere ```<path>``` represents the path to the EGTtools folder. If you are running this while inside the EGTtools folder,\nthen ```<path>``` is simply ```./```.\n\nFinally, you can install EGTtools in **development** mode, this will allow the installation to update with new\nmodifications to the package:\n\n```bash\npython -m pip install -e <path>\n```\n\nIf you don't want development mode, you can skip the option ```-e```.\n\n## Examples of usage\n\nThe [Analytical example](docs/examples/hawk_dove_dynamics.ipynb) is a jupyter notebook which analyses analytically the\nevolutionary dynamics in a (2-person, 2-actions, one-shot) Hawk-Dove game.\n\nThe [Numerical example](docs/examples/normal_form_game_mc_simulations.ipynb) is a jupyter notebook which analyses\nthrough numerical simulations the evolutionary dynamics in a (2-person, 2-actions, one-shot) Hawk-Dove game.\n\nThe [Invasion example](docs/examples/plot_invasion_diagram.ipynb) is a jupyter notebook calculates the fixation\nprobabilities and stationary distribution of a Normal Form Game with 5 strategies and then plots an invasion diagram.\n\nThe [Plot 2 Simplex](docs/examples/plot_simplex.ipynb) is a jupyter notebook that shows how to use EGTtools to plot the\nevolutionary dynamics in a 2 Simplex (a triangle), both for infinite and finite populations.\n\nYou can also check all these notebooks and a bit more on\nthis [tutorial repository](https://github.com/Socrats/egt-tutorial)\n\nFor example, assuming the following payoff matrix:\n\n![A=\\begin{pmatrix} -0.5 & 2 \\\\ 0 & 0 \\end{pmatrix}](https://latex.codecogs.com/gif.latex?A=\\begin{pmatrix}&space;-0.5&space;&&space;2&space;\\\\\\\\&space;0&space;&&space;0&space;\\end{pmatrix})\n\nYou can plot the gradient of selection in a finite population of \\(Z=100\\) individuals and assuming and intensity of\nselection ![\\beta=1](https://latex.codecogs.com/gif.latex?\\beta=1) in the following way:\n\n```python\nimport numpy as np\nfrom egttools.analytical import PairwiseComparison\nfrom egttools.games import Matrix2PlayerGameHolder\n\nbeta = 1;\nZ = 100;\nnb_strategies = 2;\nA = np.array([[-0.5, 2.], [0., 0.]])\npop_states = np.arange(0, Z + 1, 1)\n\ngame = Matrix2PlayerGameHolder(nb_strategies, payoff_matrix=A)\n\n# Instantiate evolver and calculate gradient\nevolver = PairwiseComparison(population_size=Z, game=game)\ngradients = np.array([evolver.calculate_gradient_of_selection(beta, np.array([x, Z - x])) for x in range(Z + 1)])\n```\n\nAfterwards, you can plot the results with:\n\n```python\nfrom egttools.plotting import plot_gradients\n\nplot_gradients(gradients, figsize=(4, 4), fig_title=\"Hawk-Dove game stochastic dynamics\",\n marker_facecolor='white',\n xlabel=\"frequency of hawks (k/Z)\", marker=\"o\", marker_size=20, marker_plot_freq=2)\n```\n\n![Gradient of selection](docs/images/hawk_dove_analytical_gradient.png)\n\nAnd you can plot the stationary distribution for a mutation\nrate ![\\mu=1e\u02c6{-3}](https://latex.codecogs.com/gif.latex?\\mu=1e-3) with:\n\n```python\nimport matplotlib.pyplot as plt\nfrom egttools.utils import calculate_stationary_distribution\n\ntransitions = evolver.calculate_transition_matrix(beta, mu=1e-3)\nstationary_with_mu = calculate_stationary_distribution(transitions.transpose())\nfig, ax = plt.subplots(figsize=(5, 4))\nfig.patch.set_facecolor('white')\nlines = ax.plot(np.arange(0, Z + 1) / Z, stationary_with_mu)\nplt.setp(lines, linewidth=2.0)\nax.set_ylabel('stationary distribution', size=16)\nax.set_xlabel('$k/Z$', size=16)\nax.set_xlim(0, 1)\nplt.show()\n```\n\n![Stationary distribution](docs/images/hawk_dove_analytical_full_sd.png)\n\nWe can obtain the same results through numerical simulations. The error will depend on how many independent simulations\nyou perform and for how long you let the simulation run. While a future implementation will offer an adaptive method to\nvary these parameters depending on the variations between the estimated distributions, for the moment it is important\nthat you let the simulation run for enough generations after it has achieved a steady state. Here is a comparison\nbetween analytical and numerical results:\n\n```python\nfrom egttools.numerical import PairwiseComparisonNumerical\nfrom egttools.games import NormalFormGame\n\n# Instantiate the game\ngame = NormalFormGame(1, A)\nnumerical_evolver = PairwiseComparisonNumerical(Z, game, 1000000)\n\n# We do this for different betas\nbetas = np.logspace(-4, 1, 50)\nstationary_points = []\n# numerical simulations\nfor i in range(len(betas)):\n stationary_points.append(numerical_evolver.stationary_distribution(30, int(1e6), int(1e3),\n betas[i], 1e-3))\nstationary_points = np.asarray(stationary_points)\n# Now we estimate the probability of Cooperation for each possible state\nstate_frequencies = np.arange(0, Z + 1) / Z\ncoop_level = np.dot(state_frequencies, stationary_points.T)\n```\n\nLastly, we plot the results:\n\n```python\nfrom sklearn.metrics import mean_squared_error\n\nmse = mean_squared_error(1 - coop_level_analytical, coop_level)\n\n# Finally, we plot and compare visually (and check how much error we get)\nfig, ax = plt.subplots(figsize=(7, 5))\n# ax.scatter(betas, coop_level, label=\"simulation\")\nax.scatter(betas, coop_level_analytical, marker='x', label=\"analytical\")\nax.scatter(betas, coop_level, marker='o', label=\"simulation\")\nax.text(0.01, 0.535, 'MSE = {0:.3e}'.format(mse), style='italic',\n bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})\nax.legend()\nax.set_xlabel(r'$\\beta$', fontsize=15)\nax.set_ylabel('Cooperation level', fontsize=15)\nax.set_xscale('log')\nplt.show()\n```\n\n![Comparison numerical analytical](docs/images/hawk_dove_comparison.png)\n\nFinally, you may also visualize the result of independent simulations:\n\n```python\ninit_states = np.random.randint(0, Z + 1, size=10, dtype=np.uint64)\noutput = []\nfor i in range(10):\n output.append(evolver.run(int(1e6), 1, 1e-3,\n [init_states[i], Z - init_states[i]]))\n# Plot each year's time series in its own facet\nfig, ax = plt.subplots(figsize=(5, 4))\n\nfor run in output:\n ax.plot(run[:, 0] / Z, color='gray', linewidth=.1, alpha=0.6)\nax.set_ylabel('k/Z')\nax.set_xlabel('generation')\nax.set_xscale('log')\n```\n\n![Comparison numerical analytical](docs/images/hawk_dove_indep_runs.png)\n\n### Plotting the dynamics in a 2 Simplex\n\nEGTtools can also be used to visualize the evolutionary dynamics in a 2 Simplex. In the example bellow, we use the\n`egttools.plotting.plot_replicator_dynamics_in_simplex` which calculates the gradients on a simplex given an initial\npayoff matrix and returns a `egttools.plotting.Simplex2D` object which can be used to plot the 2 Simplex.\n\n```python\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom egttools.plotting import plot_replicator_dynamics_in_simplex\n\npayoffs = np.array([[1, 0, 0],\n [0, 2, 0],\n [0, 0, 3]])\ntype_labels = ['A', 'B', 'C']\n\nfig, ax = plt.subplots(figsize=(10, 8))\n\nsimplex, gradient_function, roots, roots_xy, stability = plot_replicator_dynamics_in_simplex(payoffs, ax=ax)\n\nplot = (simplex.add_axis(ax=ax)\n .draw_triangle()\n .draw_gradients(zorder=0)\n .add_colorbar()\n .add_vertex_labels(type_labels)\n .draw_stationary_points(roots_xy, stability)\n .draw_trajectory_from_roots(gradient_function,\n roots,\n stability,\n trajectory_length=15,\n linewidth=1,\n step=0.01,\n color='k', draw_arrow=True,\n arrowdirection='right',\n arrowsize=30, zorder=4, arrowstyle='fancy')\n .draw_scatter_shadow(gradient_function, 300, color='gray', marker='.', s=0.1, zorder=0)\n )\n\nax.axis('off')\nax.set_aspect('equal')\n\nplt.xlim((-.05, 1.05))\nplt.ylim((-.02, simplex.top_corner + 0.05))\nplt.show()\n```\n\n![2 Simplex dynamics in infinite populations](docs/images/simplex_example_infinite_pop_1.png)\n\nThe same can be done for finite populations, with the added possibility to plot the stationary distribution inside the\ntriangle (see [simplex plotting](docs/examples/plot_simplex.ipynb)\nand [simplified simplex plotting](docs/examples/plot_simplex_simplified.ipynb)\nfor a more in depth examples).\n\n## Documentation\n\nThe [analytical](src/egttools/analytical/sed_analytical.py) module contains classes and functions that you may use to\ninvestigate the evolutionary dynamics in N-player games. For now only the replicator dynamics (for infinite populations)\nand the Pairwise Comparison imitation process (for finite populations) are implemented.\n\nWhen your state-space is too big (in finite populations), it might become computationally hard to solve the system\nanalytically. Thus, we provide an efficient [numerical](cpp/src/egttools.cpp) module written in C++ and compiled to\nPython. You may use it to estimate the fixation probabilities and stationary distribution through Monte-Carlo\nsimulations, or perform individual runs of the Moran process.\n\nYou can find more information in the [ReadTheDocs](https://egttools.readthedocs.io/en/latest/) documentation.\n\n### Caveats\n\n1. On Apple M1 (arm64) you should install (for the moment) [miniforge](https://github.com/conda-forge/miniforge), create\n a conda environment using it, and install EGTtools from the conda environment.\n\n2. In MacOSX it is assumed that you have [Homebrew](https://brew.sh) installed.\n3. You should install libomp with homebrew ``brew install libomp`` if you want to have support for parallel operations (\n there is a big difference in computation time).\n\n4. You **must** have Eigen 3.3.* installed.\n\n5. You **do not** need any of the above if you install EGTtools through ```pip install egttools --no-deps```. However,\n on Apple M1 (arm64) you still need to install the dependencies through miniforge, since only there you can find a\n scipy wheel that supports this architecture.\n\n## Citing\n\nIf you use EGTtools in your publications, please cite it in the following way with bibtex:\n\n```latex\n@article{Fernandez2023,\n author = {Fern\u00e1ndez Domingos, Elias and Santos, Francisco C. and Lenaerts, Tom},\n title = {EGTtools: Evolutionary game dynamics in Python},\n journal = {iScience},\n volume = {26},\n number = {4},\n pages = {106419},\n year = {2023},\n issn = {2589-0042},\n doi = {https://doi.org/10.1016/j.isci.2023.106419}\n}\n```\nOr in text format:\n\n```\nFern\u00e1ndez Domingos, E., Santos, F. C. & Lenaerts, T. EGTtools: Evolutionary game dynamics in Python. iScience 26, 106419 (2023).\n```\n\nAnd to cite the current version of EGTtools you can use:\n\n```latex\n@misc{Fernandez2020,\n author = {Fern\u00e1ndez Domingos, Elias},\n title = {EGTTools: Toolbox for Evolutionary Game Theory (0.1.12)},\n year = {2022},\n month = {Dec},\n journal = {Zenodo},\n doi = {10.5281/zenodo.7458631}\n}\n```\n\nMoreover, you may find our article at [here](https://www.cell.com/iscience/pdf/S2589-0042(23)00496-0.pdf).\n\n## Licence\n\n* EGTtools is released under the [GNU General Public Licence](LICENSE), version 3 or later.\n* [pybind11](https://github.com/pybind/pybind11) is released under [a BSD-style license](pybind11/LICENSE).\n\n## Acknowledgements\n\n* Great parts of this project have been possible thanks to the help of\n [Yannick Jadoul](https://github.com/YannickJadoul) author of\n [Parselmouth](https://github.com/YannickJadoul/Parselmouth)\n and [Eugenio Bargiacchi](https://github.com/Svalorzen) author of [AIToolBox](https://github.com/Svalorzen/AI-Toolbox).\n They are both great programmers and scientists, so it is always a good idea to check out their work.\n* EGTtools makes use of the amazing [pybind11](https://github.com/pybind/pybind11). library to provide a Python\n interface for optimized monte-carlo simulations written in C++.\n",
"bugtrack_url": null,
"license": "GPLv3",
"summary": "Efficient Python library for EGT",
"version": "0.1.13.5",
"project_urls": {
"Bug Tracker": "https://github.com/Socrats/EGTTools/issues",
"Documentation": "https://egttools.readthedocs.io/en/latest/",
"Homepage": "https://github.com/Socrats/EGTTools",
"Source Code": "https://github.com/Socrats/EGTTools"
},
"split_keywords": [
"evolutionary game theory",
"social dynamics",
"evolutionary dynamics"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "31b5033d8b04c6116fd97e243f6bafdea637dd2ea616e685d77477ef246d6d3a",
"md5": "f80dcbb7ecd5960b49a89efd8a78f1f3",
"sha256": "b6cacd9add7d2c40781f76d617c61957ac6455c69bf3b3641687c5036296e718"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp310-cp310-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "f80dcbb7ecd5960b49a89efd8a78f1f3",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.7",
"size": 548346,
"upload_time": "2023-11-23T08:00:53",
"upload_time_iso_8601": "2023-11-23T08:00:53.792286Z",
"url": "https://files.pythonhosted.org/packages/31/b5/033d8b04c6116fd97e243f6bafdea637dd2ea616e685d77477ef246d6d3a/egttools-0.1.13.5-cp310-cp310-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5c6313ab6c6c8fe0e6ac79eddf871b0a28c363de8d2e6dea60c179b0cffb17d4",
"md5": "e2ab278f82633ced0bd643d1d62676d7",
"sha256": "c6116eb64567995350436356fc927d763d5cfd373b1eb81a085112d9eb39bfe8"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp310-cp310-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "e2ab278f82633ced0bd643d1d62676d7",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.7",
"size": 498552,
"upload_time": "2023-11-23T08:00:55",
"upload_time_iso_8601": "2023-11-23T08:00:55.568900Z",
"url": "https://files.pythonhosted.org/packages/5c/63/13ab6c6c8fe0e6ac79eddf871b0a28c363de8d2e6dea60c179b0cffb17d4/egttools-0.1.13.5-cp310-cp310-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "242d898a0ddc642e8a731e6d41e0c25dda82647f6f2f06e353017e3780a48693",
"md5": "feb8288a9d8ed02fe3039eecb8d3c9cd",
"sha256": "6157db51fd46f1b847ec1d078acf7e211642ff13295d59cb2be78f59d4d59773"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "feb8288a9d8ed02fe3039eecb8d3c9cd",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.7",
"size": 638631,
"upload_time": "2023-11-23T08:00:57",
"upload_time_iso_8601": "2023-11-23T08:00:57.501166Z",
"url": "https://files.pythonhosted.org/packages/24/2d/898a0ddc642e8a731e6d41e0c25dda82647f6f2f06e353017e3780a48693/egttools-0.1.13.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "85f4e02a3dec72e656aba329b21bfea4c0ab72b50cfd349a0931569be8d38c02",
"md5": "6085235b0982b9de548ca8b467daa4d4",
"sha256": "b9daa1d5e20f39f50f0ff8d15fb0810454221fe3ce8de76d027c7c1f619317ad"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp310-cp310-win_amd64.whl",
"has_sig": false,
"md5_digest": "6085235b0982b9de548ca8b467daa4d4",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": ">=3.7",
"size": 490801,
"upload_time": "2023-11-23T08:00:59",
"upload_time_iso_8601": "2023-11-23T08:00:59.493105Z",
"url": "https://files.pythonhosted.org/packages/85/f4/e02a3dec72e656aba329b21bfea4c0ab72b50cfd349a0931569be8d38c02/egttools-0.1.13.5-cp310-cp310-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ee6a86388353bdf2a18305000b2995530d2eaca3df85591303ac76af7b651998",
"md5": "8c2aa2cfac68d47122d4c609297c0d70",
"sha256": "c79ae02876076a167905bdb8f14cff32e8fefb53b7ff604f8a07217f2ef01ee3"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp311-cp311-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "8c2aa2cfac68d47122d4c609297c0d70",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": ">=3.7",
"size": 549830,
"upload_time": "2023-11-23T08:01:01",
"upload_time_iso_8601": "2023-11-23T08:01:01.504600Z",
"url": "https://files.pythonhosted.org/packages/ee/6a/86388353bdf2a18305000b2995530d2eaca3df85591303ac76af7b651998/egttools-0.1.13.5-cp311-cp311-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b085eb3a371877b663ce0575be02cc179afcb3ed3e403519e4b214353161d54b",
"md5": "f4905659fbb91d9fb7712658eedbee04",
"sha256": "8bde603b2df5bb60757c70d5091ce461deda42b1303e21d702b3d3508a7f9b85"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp311-cp311-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "f4905659fbb91d9fb7712658eedbee04",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": ">=3.7",
"size": 499462,
"upload_time": "2023-11-23T08:01:04",
"upload_time_iso_8601": "2023-11-23T08:01:04.855544Z",
"url": "https://files.pythonhosted.org/packages/b0/85/eb3a371877b663ce0575be02cc179afcb3ed3e403519e4b214353161d54b/egttools-0.1.13.5-cp311-cp311-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3c8db6836528aab156434d51e5ebbb7bb45f79f9ccd1ca307bb75be1f3c09f62",
"md5": "d6ff5d883d71df6ecb1c238b46e9eac3",
"sha256": "0d4fa33ee071f3b4417002fe3d4da5c86b54cd40761d32d50e17c3889b40894b"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "d6ff5d883d71df6ecb1c238b46e9eac3",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": ">=3.7",
"size": 638713,
"upload_time": "2023-11-23T08:01:06",
"upload_time_iso_8601": "2023-11-23T08:01:06.705388Z",
"url": "https://files.pythonhosted.org/packages/3c/8d/b6836528aab156434d51e5ebbb7bb45f79f9ccd1ca307bb75be1f3c09f62/egttools-0.1.13.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9654b3029b1a92b85fb5b74895565b65bb91b712f0c0ee67df2441f9da814d5d",
"md5": "d25442a0359b7d2a540e8f20c5e84bab",
"sha256": "d11045a4ef60d53da2b8e5a52fcf5867ffc6266f9a9a84b05d8521010b8d3d47"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp311-cp311-win_amd64.whl",
"has_sig": false,
"md5_digest": "d25442a0359b7d2a540e8f20c5e84bab",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": ">=3.7",
"size": 492286,
"upload_time": "2023-11-23T08:01:08",
"upload_time_iso_8601": "2023-11-23T08:01:08.279222Z",
"url": "https://files.pythonhosted.org/packages/96/54/b3029b1a92b85fb5b74895565b65bb91b712f0c0ee67df2441f9da814d5d/egttools-0.1.13.5-cp311-cp311-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "809ec06ab2624ceafb8a91d8ce2c069455def0398c2630fc4074103ba0667c63",
"md5": "45d81aee5720dc60ad34e071a6d712f5",
"sha256": "a102126f8fb3284ccca34d4e40409750aea7fb1611a2302e20af0ab7955bd5f9"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp312-cp312-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "45d81aee5720dc60ad34e071a6d712f5",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": ">=3.7",
"size": 562645,
"upload_time": "2023-11-23T08:01:09",
"upload_time_iso_8601": "2023-11-23T08:01:09.884958Z",
"url": "https://files.pythonhosted.org/packages/80/9e/c06ab2624ceafb8a91d8ce2c069455def0398c2630fc4074103ba0667c63/egttools-0.1.13.5-cp312-cp312-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7ac406e217373a231fe16e243f42b89eb1cfd6f6d8a921d9c033a2d2441d1bb2",
"md5": "f02ca50457663570a75417fa1dd29d44",
"sha256": "19fc3f94e636a74147095f1fac70dd7bf6973b6b7dae578b39c2f35b2c62769b"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp312-cp312-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "f02ca50457663570a75417fa1dd29d44",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": ">=3.7",
"size": 504218,
"upload_time": "2023-11-23T08:01:11",
"upload_time_iso_8601": "2023-11-23T08:01:11.928701Z",
"url": "https://files.pythonhosted.org/packages/7a/c4/06e217373a231fe16e243f42b89eb1cfd6f6d8a921d9c033a2d2441d1bb2/egttools-0.1.13.5-cp312-cp312-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "68f8dfedab1caf0f005dd406081afbce93c8321467083fe699ce86fbcad4d1df",
"md5": "ae99644a5c9b43429c9c3815a0a15d13",
"sha256": "3b5e72f58da6d79e85a54a6c200aecade8c1cfc8eb5b6b347154afbda0337776"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "ae99644a5c9b43429c9c3815a0a15d13",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": ">=3.7",
"size": 633908,
"upload_time": "2023-11-23T08:01:13",
"upload_time_iso_8601": "2023-11-23T08:01:13.995480Z",
"url": "https://files.pythonhosted.org/packages/68/f8/dfedab1caf0f005dd406081afbce93c8321467083fe699ce86fbcad4d1df/egttools-0.1.13.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ec3c879e8417a444d82eab9375f188fd72e7349397737019b06ba6b486ece143",
"md5": "6d7938d48d0ecc79dd23cb44dc205894",
"sha256": "d57f621a18c73d13cf5be383e1ca117c3a5047297800b5bff91cbe7c5d725d5d"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp312-cp312-win_amd64.whl",
"has_sig": false,
"md5_digest": "6d7938d48d0ecc79dd23cb44dc205894",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": ">=3.7",
"size": 493943,
"upload_time": "2023-11-23T08:01:15",
"upload_time_iso_8601": "2023-11-23T08:01:15.524166Z",
"url": "https://files.pythonhosted.org/packages/ec/3c/879e8417a444d82eab9375f188fd72e7349397737019b06ba6b486ece143/egttools-0.1.13.5-cp312-cp312-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "62b2a85655af68222e2caa7fd12c5dadfe9572a0917904ee10e26cf76ee25f55",
"md5": "d63f244dea5a687fb01a7ab86b91536d",
"sha256": "658131f289713aff0e516709c1ba71ab0d98c5a3747818cc100597c3b4aeb527"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp37-cp37m-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "d63f244dea5a687fb01a7ab86b91536d",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 535736,
"upload_time": "2023-11-23T08:01:16",
"upload_time_iso_8601": "2023-11-23T08:01:16.888454Z",
"url": "https://files.pythonhosted.org/packages/62/b2/a85655af68222e2caa7fd12c5dadfe9572a0917904ee10e26cf76ee25f55/egttools-0.1.13.5-cp37-cp37m-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3af0c4b2253bfe36bbf04187b8a528151fe4b140f89cb39f68db8df5bc4f4d88",
"md5": "2d86161ad7cc8d1aa1ebe9a6ecc466b4",
"sha256": "25305ed17da20469e762b676d1ffceac29655291861f3383cb45d8116aad5c33"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "2d86161ad7cc8d1aa1ebe9a6ecc466b4",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 657560,
"upload_time": "2023-11-23T08:01:18",
"upload_time_iso_8601": "2023-11-23T08:01:18.276788Z",
"url": "https://files.pythonhosted.org/packages/3a/f0/c4b2253bfe36bbf04187b8a528151fe4b140f89cb39f68db8df5bc4f4d88/egttools-0.1.13.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "24b15a073dfbb228f38858ff0c558ea45c59acab968f5e518dae5c2b7c1255e5",
"md5": "d7a56dd49c0ceedf54e850bbf8025a59",
"sha256": "a6d29153682332253e1c3d36d0adcd7c305cb1c1a2de78a2b28354d2897be56e"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp37-cp37m-win32.whl",
"has_sig": false,
"md5_digest": "d7a56dd49c0ceedf54e850bbf8025a59",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 402675,
"upload_time": "2023-11-23T08:01:20",
"upload_time_iso_8601": "2023-11-23T08:01:20.316863Z",
"url": "https://files.pythonhosted.org/packages/24/b1/5a073dfbb228f38858ff0c558ea45c59acab968f5e518dae5c2b7c1255e5/egttools-0.1.13.5-cp37-cp37m-win32.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c5a84441797b98ca3365eeae6722af80a891d590fade9a82d6790c162b342d34",
"md5": "2513277c4bb3bff9c8475186c1dea42f",
"sha256": "88f1afbf62f93c7efa420d1b870af6b422679112b6d0e2b7204dcfc5cef7fca7"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp37-cp37m-win_amd64.whl",
"has_sig": false,
"md5_digest": "2513277c4bb3bff9c8475186c1dea42f",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 494612,
"upload_time": "2023-11-23T08:01:21",
"upload_time_iso_8601": "2023-11-23T08:01:21.788529Z",
"url": "https://files.pythonhosted.org/packages/c5/a8/4441797b98ca3365eeae6722af80a891d590fade9a82d6790c162b342d34/egttools-0.1.13.5-cp37-cp37m-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "d69f2d288491b9f32c7f3e484b6e54ad0a914ec403cd49be603b2edb6ceca2cc",
"md5": "be34fe5b341f3bc4f42bc01e7d1f4752",
"sha256": "5bdbcfb7c46bc81967c65736962de99c2b215d11179d1cd0c2316a2ec5d47560"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp38-cp38-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "be34fe5b341f3bc4f42bc01e7d1f4752",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.7",
"size": 548089,
"upload_time": "2023-11-23T08:01:23",
"upload_time_iso_8601": "2023-11-23T08:01:23.048523Z",
"url": "https://files.pythonhosted.org/packages/d6/9f/2d288491b9f32c7f3e484b6e54ad0a914ec403cd49be603b2edb6ceca2cc/egttools-0.1.13.5-cp38-cp38-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e2cbe979998e65a7bcc0bfa314bb05f23b87412735affb3d99857f30bd0e863e",
"md5": "7ca0658bfd81bc583b20e7fa554f66b8",
"sha256": "ff705d4d50d876216d3a09821ee0245776d28007c57e1ee885c2a07ea85d03aa"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp38-cp38-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "7ca0658bfd81bc583b20e7fa554f66b8",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.7",
"size": 498446,
"upload_time": "2023-11-23T08:01:24",
"upload_time_iso_8601": "2023-11-23T08:01:24.312843Z",
"url": "https://files.pythonhosted.org/packages/e2/cb/e979998e65a7bcc0bfa314bb05f23b87412735affb3d99857f30bd0e863e/egttools-0.1.13.5-cp38-cp38-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "1b45cba61743864bab1697cbe6e0164a703172f85d798ba7625e0d3fed15dbcc",
"md5": "57f6db5a7589b5a7880c027cb4536576",
"sha256": "55a75ae3964e95dd73d2ad1ccd2274cb6d75d2e9de3db637d4d85771a5e69519"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "57f6db5a7589b5a7880c027cb4536576",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.7",
"size": 638320,
"upload_time": "2023-11-23T08:01:26",
"upload_time_iso_8601": "2023-11-23T08:01:26.358878Z",
"url": "https://files.pythonhosted.org/packages/1b/45/cba61743864bab1697cbe6e0164a703172f85d798ba7625e0d3fed15dbcc/egttools-0.1.13.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "aa9b987c73f2c7e085f8a5f05b502dc04e057f8415d3652af12228d05cb44b14",
"md5": "185e81b0f59445221c8b3420205f48eb",
"sha256": "b938ba41fd583efa5c8959b2e141a24a83562bd3280a0b63b80b360c3067755b"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp38-cp38-win_amd64.whl",
"has_sig": false,
"md5_digest": "185e81b0f59445221c8b3420205f48eb",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": ">=3.7",
"size": 490991,
"upload_time": "2023-11-23T08:01:27",
"upload_time_iso_8601": "2023-11-23T08:01:27.655045Z",
"url": "https://files.pythonhosted.org/packages/aa/9b/987c73f2c7e085f8a5f05b502dc04e057f8415d3652af12228d05cb44b14/egttools-0.1.13.5-cp38-cp38-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "85311cfb3568d2f67b3a3215bedbdcdcc61a93e3eb34f4b30538f1caed0028d8",
"md5": "149de02eed212b77a58e2bc4b8d79630",
"sha256": "fe97068d1e0e4eddb300a2a481f68c2217f4301a204d75ebbce6d246a16c6f95"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp39-cp39-macosx_10_9_x86_64.whl",
"has_sig": false,
"md5_digest": "149de02eed212b77a58e2bc4b8d79630",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": ">=3.7",
"size": 548446,
"upload_time": "2023-11-23T08:01:28",
"upload_time_iso_8601": "2023-11-23T08:01:28.981129Z",
"url": "https://files.pythonhosted.org/packages/85/31/1cfb3568d2f67b3a3215bedbdcdcc61a93e3eb34f4b30538f1caed0028d8/egttools-0.1.13.5-cp39-cp39-macosx_10_9_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "70b4931282bdc8e216f3fbfc702cccc62860d8bc8a63c55cd564889b37d4e6fc",
"md5": "1eef834ae47ec2c3a699e33f18b24c1b",
"sha256": "cefa1b77decac855972ab4803aa14ed613f3ceb81fa3d7cc4e71d7c94fd0a32e"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp39-cp39-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "1eef834ae47ec2c3a699e33f18b24c1b",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": ">=3.7",
"size": 498666,
"upload_time": "2023-11-23T08:01:30",
"upload_time_iso_8601": "2023-11-23T08:01:30.496601Z",
"url": "https://files.pythonhosted.org/packages/70/b4/931282bdc8e216f3fbfc702cccc62860d8bc8a63c55cd564889b37d4e6fc/egttools-0.1.13.5-cp39-cp39-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5f1d1035540eadfa1b82bab4d32313c0091bc17842107370d65b484e03507390",
"md5": "304b62690a18329c59a2855d721101c9",
"sha256": "ec05611bb84506b0fb13da7d669a94373f6898bfda78c177778fcab315e3dcd0"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "304b62690a18329c59a2855d721101c9",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": ">=3.7",
"size": 638640,
"upload_time": "2023-11-23T08:01:32",
"upload_time_iso_8601": "2023-11-23T08:01:32.442319Z",
"url": "https://files.pythonhosted.org/packages/5f/1d/1035540eadfa1b82bab4d32313c0091bc17842107370d65b484e03507390/egttools-0.1.13.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e2a03ff51eee613ce760f3bb4620add06b216499d8a98b2838aa8f6ff88d524e",
"md5": "dabd3bbe1b3131d479272be6bcea1013",
"sha256": "77c278a28dcd129e2af1cadce2b5fd1afdf30c89b93b89a37626f57c1b8c6826"
},
"downloads": -1,
"filename": "egttools-0.1.13.5-cp39-cp39-win_amd64.whl",
"has_sig": false,
"md5_digest": "dabd3bbe1b3131d479272be6bcea1013",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": ">=3.7",
"size": 468228,
"upload_time": "2023-11-23T08:01:34",
"upload_time_iso_8601": "2023-11-23T08:01:34.528314Z",
"url": "https://files.pythonhosted.org/packages/e2/a0/3ff51eee613ce760f3bb4620add06b216499d8a98b2838aa8f6ff88d524e/egttools-0.1.13.5-cp39-cp39-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3bb55d1ae9185d1d1e8d8d68efcc09c0dea8ac157ac7cfd83ef2736d662520ae",
"md5": "340498aba6b68da81d217a5ab6cb59de",
"sha256": "0b4f6bcf68d7911454fce47fc5587685857369c2b5ffa73888edeb6ac9d6df73"
},
"downloads": -1,
"filename": "egttools-0.1.13.5.tar.gz",
"has_sig": false,
"md5_digest": "340498aba6b68da81d217a5ab6cb59de",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 3195459,
"upload_time": "2023-11-23T08:01:35",
"upload_time_iso_8601": "2023-11-23T08:01:35.890938Z",
"url": "https://files.pythonhosted.org/packages/3b/b5/5d1ae9185d1d1e8d8d68efcc09c0dea8ac157ac7cfd83ef2736d662520ae/egttools-0.1.13.5.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-11-23 08:01:35",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Socrats",
"github_project": "EGTTools",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "egttools"
}