Evolution
Evolution: evolutionary games, quasispecies, hypercycles, finite populations, landscapes, and coevolution.
AdaptiveClimbingInteraction(label, *, target, mutation=0.1, length=20, seed=0)
Bases: EvolutionInteraction
One generation of a population that climbs a random fitness landscape as a whole, under strong selection.
All individuals share one genome. Each mutates one random locus with probability u, to a genome of random fitness
in [0, 1], with probability mutation. If a mutant is fitter, the whole population takes the fittest mutant. If
every individual mutated to a less fit genome, the population escapes to the fittest of them. Otherwise it stays.
It is the best-mutant
replacement of EvolutionInteraction on genomes stored as the integers their bits spell.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the group of individuals. |
required |
mutation
|
Annotated[float, ParameterSpec(domain=closed(0, 1))]
|
The probability that an individual mutates in a generation. |
0.1
|
length
|
int
|
The number of loci of a genome. |
20
|
seed
|
int
|
The seed of the fitness landscape. |
0
|
Examples:
>>> from skcomplex.models.biology.evolution import AdaptiveClimbingInteraction
>>> AdaptiveClimbingInteraction('climbing', target='population', mutation=0.1).check().replacement
'best-mutant'
Source code in src/skcomplex/models/biology/evolution/_adaptive_climbing.py
48 49 50 51 52 53 54 55 56 57 58 59 | |
CatalysisInteraction(label, *, target, omega=1.0, topology=((0.0, 1.0), (1.0, 0.0)))
Bases: ReplicatorInteraction
Catalysed replication of the molecules of a group, with a common outflow that keeps the total at 1.
Molecule i replicates at the rate f_i = lambda_i + omega sum_j T_ij x_j, with its own growth lambda_i and the
0 or 1 topology T of the catalytic links read as the weights of a total over the molecules. The outflow is the
total replication, so the concentrations follow the replicator equation dx_i/dt = x_i (f_i - sum_j x_j f_j).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the group of molecules. |
required |
omega
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The catalytic rate of a link. |
1.0
|
topology
|
Sequence[Sequence[float]]
|
The catalytic links, 1 where molecule |
((0.0, 1.0), (1.0, 0.0))
|
Examples:
>>> from skcomplex.models.biology.evolution import CatalysisInteraction
>>> CatalysisInteraction('catalysis', target='soup', topology=((0, 1), (1, 0))).topology
((0, 1), (1, 0))
Source code in src/skcomplex/models/biology/evolution/_catalysis.py
45 46 47 48 49 50 51 52 53 54 55 | |
CatalyticLinkElement(label, visual=None)
Bases: Element
Catalytic link from a species to a species that catalyses it, which carries no state of its own.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the link or of the group of links. |
required |
Examples:
>>> from skcomplex.models.biology.evolution import CatalyticLinkElement
>>> CatalyticLinkElement('link').label
'link'
Source code in src/skcomplex/core/elements/_base.py
70 71 72 | |
ChemicalElement(label, visual=None, *, x=0.0, tie=0.5, fresh=1.0, h=0.5, p=0.02, period=10.0, k=1)
Bases: Element
Molecular species of a pool whose relative population grows with the populations of its catalysts.
The populations follow the catalytic network: every species gains h times the populations of the species that
catalyse it, and the populations are normalised, so they approach the Perron eigenvector of the network. Every
period steps the least populated species, with ties broken at random, is replaced by a new species with k
random catalysts, and every species catalyses the new one with probability p.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the species or of the group of species. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
x
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The relative population. |
0.0
|
tie
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The random key that breaks ties between the least populated species. |
0.5
|
fresh
|
Annotated[float, StateSpec(domain=FiniteEnumeratedSet([0, 1]))]
|
Whether the species appeared at the previous graph update. |
1.0
|
h
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The growth of a step from the catalysts. |
0.5
|
p
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The probability of every catalytic link of a new species. |
0.02
|
period
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The number of steps between two graph updates. |
10.0
|
k
|
int
|
The number of catalysts of a new species. |
1
|
Examples:
>>> from skcomplex.models.biology.evolution import ChemicalElement
>>> ChemicalElement('species').period
10.0
Source code in src/skcomplex/models/biology/evolution/_chemical.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
ClimberElement(label, visual=VisualSpec('agents', {'color_by': 'fitness', 'color_range': (0.0, 1.0)}), *, genome=0.0, fitness=0.0, n=10.0, k=2.0, seed=0.0)
Bases: Element
Agent that walks an NK fitness landscape, flipping one random bit of its genome when that raises its fitness.
The fitness of a genome of n bits is the mean of the contributions of its bits, each a random function of the bit
and the next k bits, fixed by seed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
VisualSpec('agents', {'color_by': 'fitness', 'color_range': (0.0, 1.0)})
|
genome
|
Annotated[float, StateSpec(domain=NN)]
|
The bits of the genome. |
0.0
|
fitness
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The fitness of the genome. |
0.0
|
n
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The number of bits. |
10.0
|
k
|
Annotated[float, ParameterSpec(domain=NN)]
|
The number of other bits each bit interacts with. |
2.0
|
seed
|
Annotated[float, ParameterSpec(domain=NN)]
|
The seed of the landscape. |
0.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.biology.evolution import ClimberElement
>>> GroupElement('climbers', element=ClimberElement, size=10).size
10
Source code in src/skcomplex/models/biology/evolution/_climber.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
climb(agent, model)
Flip a random bit, and keep the flip when it raises the fitness.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
ClimberView
|
The climber. |
required |
model
|
ModelView
|
The model. |
required |
Source code in src/skcomplex/models/biology/evolution/_climber.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |
CyclicSpeciesElement(label, visual=None, *, strategy=0)
Bases: Element
Site of a lattice of rock, paper, and scissors, 0, 1, and 2, where each strategy beats the one before it.
The sites update one at a time in random order by a LocalRuleInteraction, and a site adopts the strategy of a
random neighbour that beats it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the site or the lattice group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
strategy
|
Annotated[float, StateSpec(domain=NN)]
|
The initial strategy, 0, 1, or 2. |
0
|
Examples:
>>> from skcomplex.models.biology.evolution import CyclicSpeciesElement
>>> CyclicSpeciesElement('site', strategy=2).strategy
2
Source code in src/skcomplex/models/biology/evolution/_cyclic_species.py
36 37 38 39 40 41 42 43 44 | |
DependencyFieldInteraction(label, *, species, couplings)
Bases: Interaction
Field of every species, the sum of the couplings w of its edges to the species it depends on.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
species
|
Annotated[str, RoleSpec()]
|
The path of the group of species on the nodes. |
required |
couplings
|
Annotated[str, RoleSpec()]
|
The path of the variable group on the edges. |
required |
Examples:
>>> from skcomplex.models.biology.evolution import DependencyFieldInteraction
>>> DependencyFieldInteraction('field', species='species', couplings='couplings').couplings
'couplings'
Source code in src/skcomplex/models/biology/evolution/_dependency_field.py
34 35 36 37 38 39 40 41 42 43 | |
GenotypeClassElement(label, visual=None, *, x=0.0)
Bases: Element
Share of a population whose genomes lie a given number of point mutations away from the master sequence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the class. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
x
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial share. |
0.0
|
Examples:
>>> from skcomplex.models.biology.evolution import GenotypeClassElement
>>> GenotypeClassElement('k1', x=0.1).x
0.1
Source code in src/skcomplex/models/biology/evolution/_genotype_class.py
34 35 36 37 38 39 40 41 42 | |
IndividualElement(label, visual=VisualSpec('agents', {'color_by': 'trait'}), *, trait=0.0, fitness=1.0)
Bases: Element
Individual of a finite population, with an integer trait or genome.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
VisualSpec('agents', {'color_by': 'trait'})
|
trait
|
Annotated[float, StateSpec(domain=ZZ)]
|
The trait, a type index or the bits of a genome. |
0.0
|
fitness
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The fitness of the trait. |
1.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.biology.evolution import IndividualElement
>>> GroupElement('population', element=IndividualElement, size=10, values={'trait': 0.0}).size
10
Source code in src/skcomplex/models/biology/evolution/_individual.py
39 40 41 42 43 44 45 46 47 48 49 | |
LocusElement(label, visual=VisualSpec('image', {'low': -1.0, 'high': 1.0, 'history': 64}), *, s=-1.0, h=0.0)
Bases: Element
Locus of the genome shared by a monomorphic population, with an allele of -1 or 1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the locus or the group of loci. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
VisualSpec('image', {'low': -1.0, 'high': 1.0, 'history': 64})
|
s
|
Annotated[float, StateSpec(domain=ZZ)]
|
The allele, |
-1.0
|
h
|
Annotated[float, ParameterSpec()]
|
The random field of the locus, the fitness gained by the allele |
0.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.biology.evolution import LocusElement
>>> GroupElement('genome', element=LocusElement, size=10, values={'h': 0.05}).size
10
Source code in src/skcomplex/models/biology/evolution/_locus.py
37 38 39 40 41 42 43 44 45 46 47 | |
MasterSequenceElement(label, visual=None, *, x=0.0, u=0.3, sigma=0.5)
Bases: GenotypeClassElement
Share of the population with the fittest genome, in a sharp-peak landscape where every other genome is less fit.
The master sequence has fitness 1 and every other genome 1 - sigma. A genome mutates at one locus with
probability u per generation. The master sequence holds the parameters of the landscape that the maps of every
class read.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the class. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
x
|
float
|
The initial share. |
0.0
|
u
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The mutation rate per genome and generation. |
0.3
|
sigma
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The selective disadvantage of the other genomes. |
0.5
|
Examples:
>>> from skcomplex.models.biology.evolution import MasterSequenceElement
>>> MasterSequenceElement('master', u=0.2).u
0.2
Source code in src/skcomplex/models/biology/evolution/_master_sequence.py
44 45 46 47 48 49 50 51 52 53 54 55 | |
MoleculeElement(label, visual=None, *, x=0.5, growth=0.0)
Bases: Element
Self-replicating molecule of a prebiotic soup, with its concentration x and its own growth rate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the molecule or of the group of molecules. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
x
|
Annotated[object, StateSpec(domain=closed_open(0, oo))]
|
The initial concentration. |
0.5
|
growth
|
Annotated[object, ParameterSpec()]
|
The rate of replication without catalysis. |
0.0
|
Examples:
>>> from skcomplex.models.biology.evolution import MoleculeElement
>>> MoleculeElement('molecule', growth=0.1).growth
0.1
Source code in src/skcomplex/models/biology/evolution/_molecule.py
37 38 39 40 41 42 43 44 45 46 47 | |
MoranStepInteraction(label, *, target, advantage=0.0, mutation=0.0, phase=None)
Bases: EvolutionInteraction
One generation of the Moran process: as many birth and death events as there are individuals.
At every event an individual reproduces with probability proportional to its fitness (1 + advantage)^trait,
its offspring mutates to the trait one above or one below with probability mutation / 2 each, and it replaces an
individual chosen uniformly at random, so the size of the population stays constant. It is the Moran replacement
of EvolutionInteraction with proportional selection and steps of the trait.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the group of individuals. |
required |
advantage
|
Annotated[float, ParameterSpec()]
|
The selective advantage of one unit of the trait. |
0.0
|
mutation
|
Annotated[float, ParameterSpec(domain=closed(0, 1))]
|
The probability that an offspring mutates. |
0.0
|
phase
|
str | None
|
The phase of the step the generation runs in, or |
None
|
Examples:
>>> from skcomplex.models.biology.evolution import MoranStepInteraction
>>> MoranStepInteraction('moran', target='population', advantage=0.1).check().replacement
'moran'
Source code in src/skcomplex/models/biology/evolution/_moran_step.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
ReplicatorInteraction(label, *, target, fitness=None, state='x')
Bases: RateInteraction
Replicator equation of the shares of a group, dx_i/dt = x_i (f_i - sum_j x_j f_j), with a fitness f.
Every member of the group holds the share of a type, such as a strategy or a molecule. Its share grows with its fitness above the mean fitness of the group, so the total of the shares stays constant.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the group of types. |
required |
fitness
|
Callable[[SimpleNamespace], object] | None
|
The function of the namespace that returns the fitness of a member, such as
|
None
|
state
|
str
|
The name of the state of the members that holds the share. |
'x'
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
The fitness is not callable, raised by |
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.core.laws.utils import total
>>> from skcomplex.core.system import System
>>> from skcomplex.engine.runtime import Simulation
>>> from skcomplex.models.biology.evolution import ReplicatorInteraction, StrategyElement
>>> population = GroupElement('population', element=StrategyElement, size=2, values={'x': [0.5, 0.5]})
>>> payoff = ((1.0, 1.0), (0.0, 0.0))
>>> replication = ReplicatorInteraction(
... 'replication', target='population', fitness=lambda s: total(s.target.x, weights=payoff)
... )
>>> system = System(elements=[population], interactions=[replication])
>>> trajectory = Simulation(system, dt=0.1).check().prepare().run(until=20.0).trajectory_
>>> [round(float(share), 3) for share in trajectory.values('population.x')[-1]]
[1.0, 0.0]
Source code in src/skcomplex/models/biology/evolution/_replicator.py
59 60 61 62 63 64 65 66 67 68 | |
SpeciesElement(label, visual=None, *, fitness=0.5, updates=200, neighbors='ring')
Bases: Element
Species of the Bak-Sneppen model, with a fitness in the unit interval that depends on its neighbours.
Every update replaces the fitness of the least fit species and of its neighbours by new uniform random numbers, and
is recorded as an extinction event with the replaced species and its fitness. One step holds updates updates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the species or the lattice group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
fitness
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial fitness. |
0.5
|
updates
|
int
|
The number of updates per step. |
200
|
neighbors
|
str
|
|
'ring'
|
Examples:
>>> from skcomplex.models.biology.evolution import SpeciesElement
>>> SpeciesElement('species').updates
200
Source code in src/skcomplex/models/biology/evolution/_coevolution.py
64 65 66 67 68 69 70 71 72 73 74 75 76 | |
StrategyElement(label, visual=None, *, x=0.5)
Bases: Element
Strategy of an evolutionary game, with the share x of the population that plays it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the strategy or of the group of strategies. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
x
|
Annotated[object, StateSpec(domain=closed_open(0, oo))]
|
The initial share. |
0.5
|
Examples:
>>> from skcomplex.models.biology.evolution import StrategyElement
>>> StrategyElement('hawks', x=0.4).x
0.4
Source code in src/skcomplex/models/biology/evolution/_strategy.py
34 35 36 37 38 39 40 41 42 | |
SubstitutionInteraction(label, *, target, N=100.0, mu=0.01, F0=1.0, couplings=None, state='s')
Bases: TransitionInteraction
Origin and fixation of mutants that flip one locus of the genome of a monomorphic population.
Every locus of each of the N individuals mutates at the rate mu, so mutants of a given locus arise at the rate
N mu. A mutant from the fitness f to f' fixes with the Moran probability
(1 - f / f') / (1 - (f / f')^N), so the allele s of the locus moves between -1 and 1 by transitions at the
product of the two. The fitness is F0 + sum_i h_i s_i + sum_ij J_ij s_i s_j / 2, and a flip of locus i changes
it by -2 s_i (h_i + sum_j J_ij s_j).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the group of loci. |
required |
N
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The size of the population. |
100.0
|
mu
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The rate at which one locus of an individual mutates. |
0.01
|
F0
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The fitness of a genome without fields and couplings, above the sum of the |
1.0
|
couplings
|
ArrayLike | None
|
The symmetric matrix |
None
|
state
|
str
|
The name of the state of the loci that holds the allele. |
's'
|
Examples:
>>> from skcomplex.models.biology.evolution import SubstitutionInteraction
>>> SubstitutionInteraction('substitution', target='genome', N=50.0).N
50.0
Source code in src/skcomplex/models/biology/evolution/_substitution.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | |
TangledNatureLifeCycleInteraction(label, *, target, k=5.0, mu=0.01, p_mut=0.01, p_kill=0.2, length=8, seed=0, phase='generation')
Bases: LifeCycleInteraction
Life cycle of the organisms of the Tangled Nature model, run by the visits of a phase drawn with replacement.
A visited organism of type S reproduces with probability 1 / (1 + exp(-H(S))), where
H(S) = k / N sum_S' J(S, S') n(S') - mu N reads the composition n of the population of N organisms, and is
replaced by two offspring, whose genome bits flip with probability p_mut each. Then a random organism dies with
probability p_kill. The couplings J are uniform in [-1, 1] between different types, 0 within a type, and fixed
by seed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the life cycle. |
required |
target
|
Annotated[str, RoleSpec()]
|
The path of the variable group of organisms. |
required |
k
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The strength of the couplings. |
5.0
|
mu
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The limit of resources, which lowers reproduction in large populations. |
0.01
|
p_mut
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The probability that a bit of an offspring's genome flips. |
0.01
|
p_kill
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The probability that a visit kills a random organism. |
0.2
|
length
|
int
|
The number of bits of a genome. |
8
|
seed
|
int
|
The seed of the couplings. |
0
|
phase
|
str | None
|
The phase whose visits run the life cycle. |
'generation'
|
Examples:
>>> from skcomplex.models.biology.evolution import TangledNatureLifeCycleInteraction
>>> TangledNatureLifeCycleInteraction('evolution', target='organisms').check().offspring
2
Source code in src/skcomplex/models/biology/evolution/_tangled_nature_life_cycle.py
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 | |
compute_birth(agent, model)
Return the probability 1 / (1 + exp(-H(S))) that an organism of type S reproduces.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
IndividualView
|
The organism. |
required |
model
|
ModelView
|
The model view of the life cycle. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
probability |
float
|
The probability of reproduction. |
Source code in src/skcomplex/models/biology/evolution/_tangled_nature_life_cycle.py
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
compute_kill(agent, model)
Return the probability p_kill that a visit kills a random organism.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
IndividualView
|
The visited organism. |
required |
model
|
ModelView
|
The model view of the life cycle. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
probability |
float
|
The probability of a death. |
Source code in src/skcomplex/models/biology/evolution/_tangled_nature_life_cycle.py
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | |
mutate_genome(values, model)
Return the values of an offspring whose every genome bit flips with probability p_mut.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
dict[str, object]
|
The values of the offspring, with the genome of its parent as |
required |
model
|
ModelViewProtocol
|
The model view of the life cycle. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
values |
dict[str, object]
|
The values with the mutated genome. |
Source code in src/skcomplex/models/biology/evolution/_tangled_nature_life_cycle.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
TaxonElement(label, visual=None, *, h=1.0, age=0.0)
Bases: Element
Species of an ecosystem with its field, the sum of the couplings of the species it depends on, and its age.
A species whose field is negative goes extinct, and a new species takes its niche.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the species or of the group of species. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
h
|
Annotated[float, StateSpec()]
|
The field, the sum of the couplings of its dependencies. |
1.0
|
age
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The number of steps since the species appeared. |
0.0
|
Examples:
>>> from skcomplex.models.biology.evolution import TaxonElement
>>> TaxonElement('species').h
1.0
Source code in src/skcomplex/models/biology/evolution/_taxon.py
39 40 41 42 43 44 45 46 47 48 49 | |
adaptive_climbing(size=10, *, u=0.1, length=20, seed=0)
Return a finite population that climbs a random fitness landscape by mutation and strong selection.
The population climbs to a local optimum in an adaptive walk, ever slower near the top. When every individual
mutates in the same generation, which is likely only in small populations with a large u, it escapes to a lower
genome and starts a new walk, the wandering regime.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
int
|
The number of individuals. |
10
|
u
|
float
|
The probability that an individual mutates in a generation. |
0.1
|
length
|
int
|
The number of loci of a genome. |
20
|
seed
|
int
|
The seed of the fitness landscape. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Examples:
>>> from skcomplex.models.biology.evolution import adaptive_climbing
>>> adaptive_climbing(5).elements[0].check().prepare().size_
5
Source code in src/skcomplex/models/biology/evolution/_finite_populations.py
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 | |
bak_sneppen(size=200, *, graph=None, updates=None, random_state=0)
Return the Bak-Sneppen model, whose fitnesses self-organise above a critical value with avalanches of extinction.
On a ring the fitnesses gather above the critical value 0.667, and the minimum fitness rises towards it through avalanches of every size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
int
|
The number of species on the ring, unused on a graph. |
200
|
graph
|
Graph | None
|
The graph whose nodes are the species, or |
None
|
updates
|
int | None
|
The number of updates per step, or |
None
|
random_state
|
int | Generator | None
|
The seed or generator of the initial fitnesses. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the fitnesses |
Examples:
>>> from skcomplex.models.biology.evolution import bak_sneppen
>>> bak_sneppen(50).elements[0].values['updates']
50
Source code in src/skcomplex/models/biology/evolution/_coevolution.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 | |
eigen_quasispecies(classes=12, *, u=0.3, sigma=0.5)
Return the shares of a population at every number of mutations from the master sequence, the linear chain model.
Below the error threshold, u < sigma, a quasispecies forms around the master sequence, whose share settles at
x0 = 1 - u / sigma. Above it the master sequence is lost, the error catastrophe. Back mutations and multiple
mutations are neglected, so the chain holds only forward mutations, and the last class collects the far mutants.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
classes
|
int
|
The number of classes of mutants after the master sequence. |
12
|
u
|
float
|
The mutation rate per genome and generation. |
0.3
|
sigma
|
float
|
The selective disadvantage of the mutants. |
0.5
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the shares |
Examples:
>>> from skcomplex.models.biology.evolution import eigen_quasispecies
>>> [element.label for element in eigen_quasispecies(2).elements]
['master', 'k1', 'k2']
Source code in src/skcomplex/models/biology/evolution/_prebiotic.py
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 91 92 93 94 95 96 97 98 | |
hypercycles(molecules=4, *, alpha=0.1, omega=1.0, topology='cycle')
Return a network of self-replicating molecules whose catalysis keeps a set of them alive, a hypercycle.
The growth rates rise as lambda_i = alpha i. In a 'cycle', every molecule catalyses the next one. Up to four
molecules the hypercycle keeps all of them at a fixed point, and from five some members die out and the others
settle at a fixed point. In a 'complete' network every molecule catalyses every other, and about
sqrt(2 omega / alpha) of the fastest replicators survive while the others die out.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
molecules
|
int
|
The number of molecules. |
4
|
alpha
|
float
|
The step of the autocatalytic growth rates. |
0.1
|
omega
|
float
|
The catalytic rate of a link. |
1.0
|
topology
|
str
|
|
'cycle'
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the concentrations |
Raises:
| Type | Description |
|---|---|
ValidationError
|
The topology is unknown. |
Examples:
>>> from skcomplex.models.biology.evolution import hypercycles
>>> hypercycles(3).interactions[0].topology
((0.0, 0.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0))
Source code in src/skcomplex/models/biology/evolution/_prebiotic.py
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 160 161 162 163 164 165 166 167 168 169 | |
jain_krishna(n=40, *, p=0.02, h=0.5, period=10, seed=1)
Return the model of Jain and Krishna, where selection of the fittest builds autocatalytic sets of molecules.
The populations of n molecular species approach the Perron eigenvector of their catalytic network between graph
updates, every period steps. At every graph update the least populated species is replaced by a new one, linked
to the others with probability p. Once a cycle of catalysts forms by chance, the species it supports win, and the
autocatalytic set grows until it spans the network, so the number of links and the populated species jump.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
The number of species. |
40
|
p
|
float
|
The probability of every catalytic link. |
0.02
|
h
|
float
|
The growth of a step from the catalysts. |
0.5
|
period
|
int
|
The number of steps between two graph updates. |
10
|
seed
|
int | None
|
The seed of the initial network. |
1
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the populations |
Examples:
>>> from skcomplex.models.biology.evolution import jain_krishna
>>> round(float(jain_krishna(n=10).elements[0].values['x'].sum()), 6)
1.0
Source code in src/skcomplex/models/biology/evolution/_networks.py
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 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 | |
moran_process(size=50, *, mutants=1, selection=0.0, mutation=0.0)
Return the Moran process, a population of constant size where fitter traits fix by selection and drift.
The population starts with mutants individuals of trait 1 among individuals of trait 0. Without mutation one trait
eventually fixes, the mutant with probability (1 - 1 / r^m) / (1 - 1 / r^N) for the relative fitness
r = 1 + selection. With mutation the traits diffuse along the trait axis, in clusters rather than as a spreading
Gaussian, which distinguishes evolutionary diffusion from a random walk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
int
|
The number of individuals. |
50
|
mutants
|
int
|
The initial number of individuals of trait 1. |
1
|
selection
|
float
|
The selective advantage of one unit of the trait. |
0.0
|
mutation
|
float
|
The probability that an offspring's trait mutates by one unit. |
0.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Examples:
>>> from skcomplex.models.biology.evolution import moran_process
>>> float(moran_process(10, mutants=3).elements[0].values['trait'].sum())
3.0
Source code in src/skcomplex/models/biology/evolution/_finite_populations.py
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 | |
nk_landscape(climbers=50, *, n=10, k=2, seed=0, random_state=0)
Return agents that climb Kauffman's NK fitness landscape from random genomes until they reach local peaks.
The landscape grows more rugged with k, from a single peak at k = 0 to a random landscape at k = n - 1, so
the climbers end on more peaks of lower fitness.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
climbers
|
int
|
The number of agents. |
50
|
n
|
int
|
The number of bits of a genome. |
10
|
k
|
int
|
The number of other bits each bit interacts with. |
2
|
seed
|
int
|
The seed of the landscape. |
0
|
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.biology.evolution import nk_landscape
>>> nk_landscape(5).elements[0].check().prepare().size_
5
Source code in src/skcomplex/models/biology/evolution/_finite_populations.py
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | |
origin_fixation_walk(loci=96, *, N=100.0, mu=0.01, field=0.01, coupling=0.0, F0=1.0, random_state=0)
Return a monomorphic population that climbs a fitness landscape as mutants arise and fix one at a time.
Under strong selection and weak mutation the population carries one genome of loci alleles -1 or 1, and
every substitution of a mutant moves it to a neighbouring genome. The walk climbs the landscape and settles on the
stationary distribution Q ~ f^(N - 1), a Boltzmann distribution of the energy -ln f at the temperature
1 / (N - 1). Random fields alone, coupling = 0, give a landscape with one peak. Couplings J_ij of variance
coupling^2 / loci give the rugged landscape of a spin glass, where a small population escapes local peaks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
loci
|
int
|
The number of loci of the genome. |
96
|
N
|
float
|
The size of the population. |
100.0
|
mu
|
float
|
The rate at which one locus of an individual mutates. |
0.01
|
field
|
float
|
The standard deviation of the random fields |
0.01
|
coupling
|
float
|
The scale of the random couplings |
0.0
|
F0
|
float
|
The fitness of a genome without fields and couplings, above the sum of the |
1.0
|
random_state
|
int | Generator | None
|
The seed or generator of the fields and couplings. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the alleles |
Examples:
>>> from skcomplex.models.biology.evolution import origin_fixation_walk
>>> origin_fixation_walk(8).elements[0].check().prepare().size_
8
Source code in src/skcomplex/models/biology/evolution/_substitutions.py
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 | |
replicator_dynamics(x=None, *, payoff=None, V=2.0, C=3.0)
Return the replicator dynamics of a game, by default hawks and doves, which settle at a share V / C of hawks.
Every strategy is a member of the group population, and it grows with its payoff above the mean payoff. The
hawks and doves game has the payoff matrix ((V - C) / 2, V), (0, V / 2) with hawks first. When the cost of a fight
C exceeds the value V, hawks and doves coexist with V / C hawks, and otherwise hawks take over. A payoff
matrix gives any other game, such as the prisoner's dilemma or rock, paper, scissors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
Sequence[float] | None
|
The initial shares of the strategies, or |
None
|
payoff
|
Sequence[Sequence[float]] | None
|
The payoff matrix of another game, one row per strategy, or |
None
|
V
|
float
|
The value of the resource contested by hawks and doves. |
2.0
|
C
|
float
|
The cost of a fight between hawks. |
3.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the shares |
Examples:
>>> from skcomplex.models.biology.evolution import replicator_dynamics
>>> replicator_dynamics(payoff=((0, -1, 1), (1, 0, -1), (-1, 1, 0))).elements[0].check().prepare().size_
3
Source code in src/skcomplex/models/biology/evolution/_games.py
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 | |
rock_paper_scissors(shape=(60, 60), *, random_state=0)
Return rock, paper, and scissors on a lattice, whose cyclic invasions keep the three strategies coexisting.
Starting from random strategies, the strategies chase each other in domains and fronts, and each keeps about a third of the lattice.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shape
|
Sequence[int]
|
The number of rows and columns of the periodic lattice. |
(60, 60)
|
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.biology.evolution import rock_paper_scissors
>>> rock_paper_scissors((10, 10)).elements[0].check().prepare().size_
100
Source code in src/skcomplex/models/biology/evolution/_games.py
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 134 135 136 137 138 139 140 141 142 143 | |
sole_manrubia(n=100, k=5, *, noise=0.05, seed=1)
Return the ecosystem of Solé and Manrubia, whose species go extinct when their dependencies turn against them.
Every species depends on k species through couplings drawn from [-1, 1], and its field is the sum of these
couplings. The couplings drift at random. A species whose field turns negative goes extinct, the species that
depend on it lose a coupling, and their fields may turn negative in turn, so extinctions come in avalanches with a
broad distribution of sizes. A new species with k random dependencies replaces every extinct one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
The number of species. |
100
|
k
|
int
|
The number of dependencies of every species. |
5
|
noise
|
float
|
The standard deviation of the drift of every coupling at a step. |
0.05
|
seed
|
int | None
|
The seed of the network and of the initial couplings. |
1
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the fields |
Examples:
>>> from skcomplex.models.biology.evolution import sole_manrubia
>>> [component.label for component in sole_manrubia(n=20).elements]
['species', 'couplings']
Source code in src/skcomplex/models/biology/evolution/_networks.py
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 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 | |
tangled_nature(organisms=100, *, k=5.0, mu=0.01, p_mut=0.01, p_kill=0.2, length=8, seed=0, random_state=0)
Return the Tangled Nature model, where organisms whose types interact through random couplings coevolve.
Organisms of one random type start the run. Mutants spread through the space of genomes, and the population
settles into quasi-stable configurations of a few dominant types, the q-ESS, that end in abrupt transitions, a
punctuated equilibrium. The trait of an organism holds the bits of its genome. A generation is N / p_kill
visits to organisms drawn with replacement, where N is the population at its start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
organisms
|
int
|
The initial number of organisms. |
100
|
k
|
float
|
The strength of the couplings. |
5.0
|
mu
|
float
|
The limit of resources, which lowers reproduction in large populations. |
0.01
|
p_mut
|
float
|
The probability that a bit of an offspring's genome flips. |
0.01
|
p_kill
|
float
|
The probability that a chosen organism dies. |
0.2
|
length
|
int
|
The number of bits of a genome. |
8
|
seed
|
int
|
The seed of the couplings. |
0
|
random_state
|
int | Generator | None
|
The seed or generator of the initial type. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Examples:
>>> from skcomplex.models.biology.evolution import tangled_nature
>>> tangled_nature(20).elements[0].check().prepare().size_
20
Source code in src/skcomplex/models/biology/evolution/_finite_populations.py
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 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 160 161 162 163 164 165 166 | |