Skip to content

Add custom matches #1397

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

Merged
merged 22 commits into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
88ec7b2
Added match class argument
zewaywong Aug 18, 2021
68a1f06
Heterogeneous play unit tests
zewaywong Aug 18, 2021
0f30f65
Documentation for custom heterogeneous matches
zewaywong Aug 18, 2021
b5aa7de
Fixed spelling, added reference, feedback edits
zewaywong Aug 30, 2021
e9e842f
Update docs/how-to/heterogeneous_matches.rst
zewaywong Aug 30, 2021
d744fce
Update docs/how-to/heterogeneous_matches.rst
zewaywong Sep 8, 2021
5a72f72
Change seed in Moran process test.
drvinceknight Oct 26, 2021
b42bb0f
Add a test to the moran process for custom match
drvinceknight Oct 26, 2021
657b917
Remove the match_class from tournament.
drvinceknight Oct 26, 2021
dce16c4
Remove unnecessary tests.
drvinceknight Oct 26, 2021
95698d8
Modify the documentation.
drvinceknight Oct 26, 2021
5766046
Remove incorrect file path from how-to doc index.
drvinceknight Oct 26, 2021
ccf7205
Fix some broken rst.
drvinceknight Oct 26, 2021
2512ec2
Run black.
drvinceknight Oct 26, 2021
bdd11a4
Delete unnecessary file
drvinceknight Oct 26, 2021
95daa38
Fix typos in index.rst
marcharper Oct 26, 2021
32b655f
Edit docstring in test_moran
marcharper Oct 26, 2021
cb3e5c7
Revise wording in use_custom_matches.rst
marcharper Oct 26, 2021
132ec54
Remove an empty file.
drvinceknight Oct 27, 2021
913c5ad
Merge branch 'add-custom-matches' of github.com:Axelrod-Python/Axelro…
drvinceknight Oct 27, 2021
b346867
Pin docutils.
drvinceknight Oct 27, 2021
9dc600f
Move back to having a specific rtd reqs file.
drvinceknight Oct 27, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion axelrod/moran.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def __init__(
mutation_method="transition",
stop_on_fixation=True,
seed=None,
match_class=Match,
) -> None:
"""
An agent based Moran process class. In each round, each player plays a
Expand Down Expand Up @@ -106,6 +107,7 @@ def __init__(
else:
self.deterministic_cache = DeterministicCache()
self.turns = turns
self.match_class = match_class
self.prob_end = prob_end
self.game = game
self.noise = noise
Expand Down Expand Up @@ -376,7 +378,7 @@ def score_all(self) -> List:
for i, j in self._matchup_indices():
player1 = self.players[i]
player2 = self.players[j]
match = Match(
match = self.match_class(
(player1, player2),
turns=self.turns,
prob_end=self.prob_end,
Expand Down
20 changes: 19 additions & 1 deletion axelrod/tests/unit/test_moran.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,25 @@ def test_different_game(self):
# Possible for Cooperator to become fixed when using a different game
p1, p2 = axl.Cooperator(), axl.Defector()
game = axl.Game(r=4, p=2, s=1, t=6)
mp = MoranProcess((p1, p2), turns=5, game=game, seed=88)
mp = MoranProcess((p1, p2), turns=5, game=game, seed=3)
populations = mp.play()
self.assertEqual(mp.winning_strategy_name, str(p1))

def test_different_match(self):
"""Test alternative Match class, mainly to show that the results are different
than the results of `test_different_game` where the same seed is used."""
# Using a different game where the scores are all constant
class StandInMatch(axl.Match):
"""A Match were all players get a score of 3"""

def final_score_per_turn(self):
return 0, 3

p1, p2 = axl.Cooperator(), axl.Defector()
game = axl.Game(r=4, p=2, s=1, t=6)
mp = MoranProcess(
(p1, p2), turns=5, game=game, match_class=StandInMatch, seed=3
)
populations = mp.play()
self.assertEqual(mp.winning_strategy_name, str(p2))

Expand Down
1 change: 1 addition & 0 deletions docs/how-to/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ with the Axelrod library.
use_parallel_processing.rst
use_a_cache.rst
use_different_stage_games.rst
use_custom_matches.rst
set_a_seed.rst
set_player_information.rst
check_player_equality.rst
Expand Down
24 changes: 24 additions & 0 deletions docs/how-to/use_custom_matches.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.. _use-custom-matches:

Use custom matches
==================

The Moran process supports custom match classes. Below
creates a new class of a match where both players end with a score of 2::


>>> import axelrod as axl
>>> class MassBaseMatch(axl.Match):
... """Axelrod Match object with a modified final score function to enable mass to influence the final score as a multiplier"""
... def final_score_per_turn(self):
... return 2, 2

We then create a Moran process with the custom match class by passing our custom
:code:`MassBaseMatch` to the Moran process with the :code:`match_class` keyword
argument::

>>> players = [axl.Cooperator(), axl.Defector(), axl.TitForTat(), axl.Grudger()]
>>> mp = axl.MoranProcess(players=players, match_class=MassBaseMatch, seed=0)
>>> population = mp.play()
>>> print(mp.winning_strategy_name)
Defector
1 change: 1 addition & 0 deletions docs/reference/bibliography.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ documentation.
.. [Hilbe2017] Hilbe, C., Martinez-Vaquero, L. A., Chatterjee K., Nowak M. A. (2017). Memory-n strategies of direct reciprocity, Proceedings of the National Academy of Sciences May 2017, 114 (18) 4715-4720; doi: 10.1073/pnas.1621239114.
.. [Kuhn2017] Kuhn, Steven, "Prisoner's Dilemma", The Stanford Encyclopedia of Philosophy (Spring 2017 Edition), Edward N. Zalta (ed.), https://plato.stanford.edu/archives/spr2017/entries/prisoner-dilemma/
.. [Kraines1989] Kraines, David, and Vivian Kraines. "Pavlov and the prisoner's dilemma." Theory and decision 26.1 (1989): 47-79. doi:10.1007/BF00134056
.. [Krapohl2020] Krapohl, S., Ocelík, V. & Walentek, D.M. The instability of globalization: applying evolutionary game theory to global trade cooperation. Public Choice 188, 31–51 (2021). https://doi.org/10.1007/s11127-020-00799-1
.. [LessWrong2011] Zoo of Strategies (2011) LessWrong. Available at: http://lesswrong.com/lw/7f2/prisoners_dilemma_tournament_results/
.. [Li2007] Li, J, How to Design a Strategy to Win an IPD Tournament, in Kendall G., Yao X. and Chong S. (eds.) The iterated prisoner’s dilemma: 20 years on. World Scientific, chapter 4, pp. 29-40, 2007.
.. [Li2009] Li, J. & Kendall, G. (2009). A Strategy with Novel Evolutionary Features for the Iterated Prisoner’s Dilemma. Evolutionary Computation 17(2): 257–274.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
.. _create-heterogeneous-moran-processes:

Create Heterogeneous Moran Processes
====================================

Axelrod Matches are homogeneous by nature but can be extended to utilize
additional attributes of heterogeneous players. This tutorial indicates how the
Axelrod :code:`Match` class can be manipulated in order to play heterogeneous
tournaments and Moran processes using mass as a score modifier similarly to the
work of [Krapohl2020]_.

The following lines of code creates a list of players from the available demo
strategies along with an ascending list of masses we will use for the players.
This is equivalent in principle to the country masses discussed in
[Krapohl2020]_::

>>> import axelrod as axl
>>> players = [player() for player in axl.demo_strategies]
>>> masses = [i for i in range(len(players))]
>>> players
[Cooperator, Defector, Tit For Tat, Grudger, Random: 0.5]

Using the :code:`setattr()` function, additional attributes can be passed to
players to enable access during matches and tournaments without manual
modification of individual strategies::

>>> def set_player_mass(players, masses):
... """Add mass attribute to player strategy classes to be accessable via self.mass"""
... for player, mass in zip(players, masses):
... setattr(player, "mass", mass)
...
>>> set_player_mass(players, masses)

The :code:`Match` class can be partially altered to enable different behaviour
(see :ref:`use-custom-matches`).
Here we extend :code:`axl.Match` and overwrite its
:code:`final_score_per_turn()` function to utilize the player mass attribute as
a multiplier for the final score::

>>> class MassBaseMatch(axl.Match):
... """Axelrod Match object with a modified final score function to enable mass to influence the final score as a multiplier"""
... def final_score_per_turn(self):
... base_scores = axl.Match.final_score_per_turn(self)
... return [player.mass * score for player, score in zip(self.players, base_scores)]

In [Krapohl2020]_ a non standard Moran process is used where the mass of
individuals is not reproduced so we will use inheritance to create a new Moran
process that keeps the mass of the individuals constant::

>>> class MassBasedMoranProcess(axl.MoranProcess):
... """Axelrod MoranProcess class """
... def __next__(self):
... set_player_mass(self.players, masses)
... super().__next__()
... return self

>>> mp = MassBasedMoranProcess(players, match_class=MassBaseMatch, seed=0)
>>> populations = mp.play()
>>> print(mp.winning_strategy_name)
Random: 0.5

Note that the snippets here only influence the final score of matches. The
behavior of matches, and Moran processes can be more heavily influenced by
partially overwriting other :code:`match` functions or :code:`birth` and
:code:`death` functions within :code:`MoranProcess`.
1 change: 1 addition & 0 deletions docs/tutorials/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ Contents:

new_to_game_theory_and_or_python/index.rst
running_axelrods_first_tournament/index.rst
creating_heterogenous_player_moran_process/index.rst