Cooperation
Cooperation: evolutionary games between neighbours, in hyperedges, and in tournaments, with imitation.
ContributorElement(label, visual=None, *, strategy=1.0, payoff=0.0, synergy=4.5, noise=0.5)
Bases: Element
Player of the spatial public goods game, a cooperator at 1 and a defector at 0, with its payoff.
The play is a PublicGoodsInteraction of the lattice or a HyperedgeGoodsInteraction of a hypergraph, and the
imitation an ImitationInteraction that reads the payoffs of the same step, which public_goods_game and
hypergraph_public_goods add.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the player or the lattice group. |
required |
visual
|
VisualSpec | None
|
How the agent is drawn, or |
None
|
strategy
|
Annotated[float, StateSpec(domain=FiniteEnumeratedSet([0, 1]))]
|
The initial strategy, 1 or 0. |
1.0
|
payoff
|
Annotated[float, StateSpec()]
|
The payoff of the last play, the sum of the shares of its groups minus its contributions. |
0.0
|
synergy
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The factor that multiplies the contributions of a group. |
4.5
|
noise
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The noise of the Fermi imitation. |
0.5
|
Examples:
>>> from skcomplex.models.social.cooperation import ContributorElement
>>> ContributorElement('player').synergy
4.5
Source code in src/skcomplex/models/social/cooperation/_contributor.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
DilemmaElement(label, visual=None, *, strategy=1.0, payoff=0.0, triangles=1.0)
Bases: Element
Player of the social dilemmas on a simplicial complex, a cooperator at 1 and a defector at 0, with its payoff.
The play is a SimplicialDilemmaInteraction of the network, and the imitation an ImitationInteraction that
reads the payoffs of the same step, which simplicial_social_dilemmas adds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the player or the group. |
required |
visual
|
VisualSpec | None
|
How the player is drawn, or |
None
|
strategy
|
Annotated[float, StateSpec(domain=FiniteEnumeratedSet([0, 1]))]
|
The initial strategy, 1 or 0. |
1.0
|
payoff
|
Annotated[float, StateSpec()]
|
The payoff of the last play, the mean payoff of the player over the links of its triangles. |
0.0
|
triangles
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The number of triangles of the network that hold the player. |
1.0
|
Examples:
>>> from skcomplex.models.social.cooperation import DilemmaElement
>>> DilemmaElement('player').triangles
1.0
Source code in src/skcomplex/models/social/cooperation/_dilemma.py
44 45 46 47 48 49 50 51 52 53 54 55 56 | |
HyperedgeGoodsInteraction(label, *, target, phase=None)
Bases: CouplingInteraction
Play of the public goods game in every hyperedge around a player, which sets the payoffs.
It is a CouplingInteraction over the hyperedges of a network in the map form, a cooperator at 1 and a defector
at 0. In every hyperedge of m members a cooperator pays 1, and the pot multiplied by synergy is shared by the
m members, so the payoff of a player is the sum over its hyperedges of its share minus its contribution. The
synergy is a parameter of the players.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the players on the network. |
required |
phase
|
str | None
|
The phase of the step the play runs in, or |
None
|
Examples:
>>> from skcomplex.models.social.cooperation import HyperedgeGoodsInteraction
>>> HyperedgeGoodsInteraction('play', target='players').check().write
'payoff'
Source code in src/skcomplex/models/social/cooperation/_hyperedge_goods.py
40 41 42 43 44 45 46 47 48 49 | |
PrisonerElement(label, visual=None, *, strategy=1.0, temptation=1.85, noise=0.1)
Bases: Element
Player of the spatial prisoner's dilemma, a cooperator at 1 and a defector at 0.
The play and the imitation are a PrisonersDilemmaInteraction of the lattice, which spatial_prisoners_dilemma
adds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the player or the lattice group. |
required |
visual
|
VisualSpec | None
|
How the agent is drawn, or |
None
|
strategy
|
Annotated[float, StateSpec(domain=FiniteEnumeratedSet([0, 1]))]
|
The initial strategy, 1 or 0. |
1.0
|
temptation
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The payoff of a defector against a cooperator. |
1.85
|
noise
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The noise of the Fermi imitation. |
0.1
|
Examples:
>>> from skcomplex.models.social.cooperation import PrisonerElement
>>> PrisonerElement('player').temptation
1.85
Source code in src/skcomplex/models/social/cooperation/_prisoner.py
44 45 46 47 48 49 50 51 52 53 54 55 56 | |
PrisonersDilemmaInteraction(label, *, target, imitation='best')
Bases: LocalRuleInteraction
Play of the weak prisoner's dilemma between neighbours, and imitation of more successful neighbours.
It is a stochastic LocalRuleInteraction of the strategies over the 5 by 5 square around a player, a cooperator
at 1 and a defector at 0. Every step each player plays the weak dilemma, with reward 1, temptation temptation,
and 0 otherwise, against itself and its eight neighbours. It then copies the best player among them, or a random
neighbour with the Fermi probability 1 / (1 + exp((P_own - P_other) / noise)). The temptation and the noise are
parameters of the players.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the players on the lattice. |
required |
imitation
|
str
|
|
'best'
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
The imitation is unknown, raised by |
Examples:
>>> from skcomplex.models.social.cooperation import PrisonersDilemmaInteraction
>>> PrisonersDilemmaInteraction('play', target='players', imitation='fermi').check().imitation
'fermi'
Source code in src/skcomplex/models/social/cooperation/_prisoners_dilemma.py
57 58 59 | |
PublicGoodsInteraction(label, *, target, phase=None)
Bases: GroupingInteraction
Play of the public goods game in the groups of a player and its four neighbours, which sets the payoffs.
It is a symbolic GroupingInteraction of the von Neumann neighbourhoods of a lattice, a cooperator at 1 and a
defector at 0. Every player joins five groups, the one centred on itself and those centred on its four neighbours.
In each group a cooperator pays 1, and the pot multiplied by synergy is shared by the members, so the payoff of a
player is the sum of its shares minus its contributions. The synergy is a parameter of the players.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the players on the lattice. |
required |
phase
|
str | None
|
The phase of the step the play runs in, or |
None
|
Examples:
>>> from skcomplex.models.social.cooperation import PublicGoodsInteraction
>>> PublicGoodsInteraction('play', target='players').check().write
'payoff'
Source code in src/skcomplex/models/social/cooperation/_public_goods.py
40 41 42 43 44 45 46 47 48 49 | |
SimplicialDilemmaInteraction(label, *, target, sucker=-0.2, temptation=1.2, sucker_allied=0.5, temptation_allied=0.8, sucker_opposed=-0.2, temptation_opposed=1.2, phase=None)
Bases: CouplingInteraction
Play of two-player games along the links of the triangles of a simplicial complex, which sets the payoffs.
It is a CouplingInteraction over the hyperedges of a network in the map form, a cooperator at 1 and a defector
at 0. Every game pays 1 for mutual cooperation, 0 for mutual defection, and the sucker's payoff S and the
temptation T when the strategies differ. A triangle of three links is three hyperedges of two members, along
which the players play game 1 of S1 and T1. A triangle filled as a 2-simplex is one hyperedge of three members,
where a player plays each other member while the third looks on: game 2 of S2 and T2 when the third member
shares the player's strategy, and game 3 of S3 and T3 otherwise. The payoff of a player is the sum over the two
links of every triangle around it divided by twice its number of triangles, a parameter of the players.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the players on the network. |
required |
sucker
|
Annotated[float, ParameterSpec()]
|
The payoff |
-0.2
|
temptation
|
Annotated[float, ParameterSpec()]
|
The payoff |
1.2
|
sucker_allied
|
Annotated[float, ParameterSpec()]
|
The payoff |
0.5
|
temptation_allied
|
Annotated[float, ParameterSpec()]
|
The payoff |
0.8
|
sucker_opposed
|
Annotated[float, ParameterSpec()]
|
The payoff |
-0.2
|
temptation_opposed
|
Annotated[float, ParameterSpec()]
|
The payoff |
1.2
|
phase
|
str | None
|
The phase of the step the play runs in, or |
None
|
Examples:
>>> from skcomplex.models.social.cooperation import SimplicialDilemmaInteraction
>>> SimplicialDilemmaInteraction('play', target='players', temptation_allied=0.8).check().temptation_allied
0.8
Source code in src/skcomplex/models/social/cooperation/_simplicial_dilemma.py
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | |
StrategistElement(label, visual=None, *, genome=1.0, fitness=0.0)
Bases: Element
Agent of the prisoner's dilemma tournament, with a genome of responses and the fitness of its last games.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the agent is drawn, or |
None
|
genome
|
Annotated[ArrayLike, StateSpec(vector=True)]
|
The seven moves, 1 to cooperate and 0 to defect, for the opponent's last two moves: none, C, D, CC, CD, DC, and DD. |
1.0
|
fitness
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The mean score per round of the last tournament. |
0.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.social.cooperation import StrategistElement
>>> group = GroupElement('agents', element=StrategistElement, size=10, values={'genome': [1.0] * 7})
>>> group.label, group.element.__name__, group.size
('agents', 'StrategistElement', 10)
Source code in src/skcomplex/models/social/cooperation/_strategist.py
42 43 44 45 46 47 48 49 50 51 52 | |
StrategistView(agent, stepper)
Bases: AgentView
View of a strategist of the iterated prisoner's dilemma, with its states as attributes.
Source code in src/skcomplex/engine/solvers/_mesa.py
513 514 515 | |
TournamentInteraction(label, *, target, rounds=6, phase=None)
Bases: GroupingInteraction
Tournament of strategies of the iterated prisoner's dilemma.
Every step the agents stand in a random ring, and every agent forms a group with its two neighbours in the ring, whom it plays. Its fitness is its mean score per round.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the group of strategists. |
required |
rounds
|
int
|
The number of rounds of every game. |
6
|
phase
|
str | None
|
The phase of the step the tournament runs in, or |
None
|
Examples:
>>> from skcomplex.models.social.cooperation import TournamentInteraction
>>> TournamentInteraction('tournament', target='agents').rounds
6
Source code in src/skcomplex/models/social/cooperation/_tournament.py
95 96 97 98 99 100 101 102 103 104 | |
act_on(members, model)
Set the fitness of the first member to its mean score per round against the two others.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
members
|
list[AgentViewProtocol]
|
The agent, followed by its two neighbours in the ring. |
required |
model
|
ModelViewProtocol
|
The model view of the rule. |
required |
Source code in src/skcomplex/models/social/cooperation/_tournament.py
114 115 116 117 118 119 120 121 122 123 124 125 126 | |
hypergraph_public_goods(n_nodes=400, *, sizes=(3, 5), hyperdegree=2.0, synergy=4.0, noise=0.5, share=0.5, seed=0)
Return the public goods game on a hypergraph, played in every hyperedge, with Fermi imitation.
Every hyperedge is a group that plays the public goods game: a cooperator pays 1, and the pot multiplied by
synergy is shared by the members. Every step has two phases. In the phase play every player takes the sum of
its shares minus its contributions over the hyperedges around it, and in the phase imitate every player copies a
random neighbour, a member of one of its hyperedges, with the Fermi probability 1 / (1 + exp((P_own - P_other) /
K)) of the payoffs of the same step, at the noise K. In a well-mixed population defection wins in a group of m
for synergy < m, so cooperation needs a synergy near the sizes of the hyperedges.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_nodes
|
int
|
The number of players. |
400
|
sizes
|
Sequence[int]
|
The sizes of the hyperedges. |
(3, 5)
|
hyperdegree
|
float
|
The mean number of hyperedges of every size around a player, whose members are drawn at random. |
2.0
|
synergy
|
float
|
The factor that multiplies the contributions of a hyperedge. |
4.0
|
noise
|
float
|
The noise of the Fermi imitation. |
0.5
|
share
|
float
|
The share of cooperators at the start. |
0.5
|
seed
|
int
|
The seed of the hypergraph and the initial strategies. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the strategies |
Examples:
>>> from skcomplex.models.social.cooperation import hypergraph_public_goods
>>> hypergraph_public_goods(30).elements[0].check().prepare().size_
30
Source code in src/skcomplex/models/social/cooperation/_hypergraph_games.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | |
play(first, second, rounds=6)
Return the scores of two genomes in an iterated prisoner's dilemma.
A genome holds seven moves, 1 to cooperate and 0 to defect, for the opponent's last two moves: none, C, D, CC, CD, DC, and DD. A round pays 3 to both cooperators, 1 to both defectors, and 5 to a defector against a cooperator, who gets 0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
first
|
ArrayLike
|
The genome of the first player. |
required |
second
|
ArrayLike
|
The genome of the second player. |
required |
rounds
|
int
|
The number of rounds. |
6
|
Returns:
| Name | Type | Description |
|---|---|---|
scores |
tuple[float, float]
|
The total scores of the two players. |
Examples:
>>> from skcomplex.models.social.cooperation import play
>>> play([1] * 7, [0] * 7)
(0.0, 30.0)
Source code in src/skcomplex/models/social/cooperation/_tournament.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
prisoners_dilemma_tournament(n_agents=100, *, rounds=6, death=0.1, mutation=0.05, random_state=0)
Return the evolution of strategies of the iterated prisoner's dilemma from random genomes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_agents
|
int
|
The number of agents. |
100
|
rounds
|
int
|
The number of rounds of every game. |
6
|
death
|
float
|
The probability that an agent dies every step. |
0.1
|
mutation
|
float
|
The probability that an offspring has one gene flipped. |
0.05
|
random_state
|
int | Generator | None
|
The seed or generator of the initial genomes. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Examples:
>>> from skcomplex.models.social.cooperation import prisoners_dilemma_tournament
>>> prisoners_dilemma_tournament(10, random_state=0).elements[0].check().prepare().size_
10
Source code in src/skcomplex/models/social/cooperation/_tournaments.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
public_goods_game(shape=(50, 50), *, synergy=4.5, noise=0.5, share=0.5, random_state=0)
Return the spatial public goods game in groups of five neighbours, with Fermi imitation.
Every step has two phases. In the phase play every player takes the payoff of its five groups, and in the phase
imitate every player copies a random neighbour with the Fermi probability 1 / (1 + exp((P_own - P_other) / K))
of the payoffs of the same step, at the noise K.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shape
|
Sequence[int]
|
The number of rows and columns of the periodic lattice. |
(50, 50)
|
synergy
|
float
|
The factor that multiplies the contributions of a group. |
4.5
|
noise
|
float
|
The noise of the Fermi imitation. |
0.5
|
share
|
float
|
The share of cooperators at the start. |
0.5
|
random_state
|
int | Generator | None
|
The seed or generator of the initial strategies. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the strategies |
Examples:
>>> from skcomplex.models.social.cooperation import public_goods_game
>>> public_goods_game((10, 10)).elements[0].check().prepare().size_
100
Source code in src/skcomplex/models/social/cooperation/_spatial_games.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
simplicial_social_dilemmas(n_nodes=500, *, simplices=0.5, sucker=-0.2, temptation=1.2, sucker_allied=0.5, temptation_allied=0.8, sucker_opposed=None, temptation_opposed=None, noise=0.1, share=0.5, seed=0)
Return the social dilemmas of Guo et al. on the links and the 2-simplices of a simplicial complex.
The network grows from a complete graph on five nodes, every new node joining both ends of a random link, which
forms one new triangle. A share simplices of the triangles, drawn at random, are 2-simplices, and the others are
three links. Players play game 1 along the links of a plain triangle, and in a 2-simplex game 2 against a member
when the third member shares their strategy and game 3 otherwise, every game paying 1 for mutual cooperation, 0
for mutual defection, and S and T to a cooperator and a defector that meet. The payoff of a player is the mean
over the two links of every triangle around it. Every step has two phases: in play every player takes its
payoff, and in imitate every player copies a random neighbour with the Fermi probability 1 / (1 + exp((P_own -
P_other) / K)) at the noise K.
The review of Majhi et al. writes the payoff as a mean over the links of a player of the mean over the triangles of
each link, and picks game 2 when s_ki = s_kj. This model takes the mean over the links of the triangles, which
counts a link once per triangle, and reads the condition as the third member sharing the strategy of the player.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_nodes
|
int
|
The number of players. |
500
|
simplices
|
float
|
The share of the triangles that are 2-simplices. |
0.5
|
sucker
|
float
|
The sucker's payoff |
-0.2
|
temptation
|
float
|
The temptation |
1.2
|
sucker_allied
|
float
|
The sucker's payoff |
0.5
|
temptation_allied
|
float
|
The temptation |
0.8
|
sucker_opposed
|
float | None
|
The sucker's payoff |
None
|
temptation_opposed
|
float | None
|
The temptation |
None
|
noise
|
float
|
The noise of the Fermi imitation. |
0.1
|
share
|
float
|
The share of cooperators at the start. |
0.5
|
seed
|
int
|
The seed of the network, the 2-simplices, and the initial strategies. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the strategies |
Examples:
>>> from skcomplex.models.social.cooperation import simplicial_social_dilemmas
>>> simplicial_social_dilemmas(30).elements[0].check().prepare().size_
30
Source code in src/skcomplex/models/social/cooperation/_hypergraph_games.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | |
spatial_prisoners_dilemma(shape=(50, 50), *, temptation=1.85, imitation='best', noise=0.1, share=0.9, random_state=0)
Return the spatial prisoner's dilemma of Nowak and May, with best-neighbour or Fermi imitation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shape
|
Sequence[int]
|
The number of rows and columns of the periodic lattice. |
(50, 50)
|
temptation
|
float
|
The payoff of a defector against a cooperator. |
1.85
|
imitation
|
str
|
|
'best'
|
noise
|
float
|
The noise of the Fermi imitation. |
0.1
|
share
|
float
|
The share of cooperators at the start. |
0.9
|
random_state
|
int | Generator | None
|
The seed or generator of the initial strategies. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the strategies |
Examples:
>>> from skcomplex.models.social.cooperation import spatial_prisoners_dilemma
>>> spatial_prisoners_dilemma((10, 10)).elements[0].check().prepare().size_
100
Source code in src/skcomplex/models/social/cooperation/_spatial_games.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | |