powered by NetLogo
view/download model file: EMS_ecology_model.nlogo
This is a model of different ecoologies developing with evolution. This is an experimental model that combines elements of a meta-population model with a “McKane” style of simulated evolution (but with individuals rather than populations represented).
Each patch has a set of characteristics composed of a binary vector and a level of resources (energy) that is replenished each simulation tick.
Each individual of a species has the same gene composed of a vector of fixed length. It also has an energy level and an age. Each iteration a life-tax is subtracted from its energy. If its energy falls below 0 it dies. If its energy level exceeds a set level it reproduces into the same patch (with a possible mutation) - the energy of the offspring is subtracted from the parent. If its age exceeds the maximum age it also dies (unless maximum age is set to 0). There is a small probability of migrating to another patch (there are two settings for this - either to another random patch or only neighboring patches).
Energy is gained in one of two ways:
by extraction from the environment by comparing its gene against the vector of characteristics for the patch it is on. In this case the scores of individuals that are achieve value > 0 determine the distribution of the fixed pot of energy for the patch.
by eating other individuals. Each individual tries to eat a set number of random others on their patch. The success of this is determined by comparing its gene against the gene of the other. If the score is greater than a threshold (currently 0) then it eats the other, adsorbing a percentage of the other’s energy and the other dying.
Method of “comparison” in (1) and (2) above:
During initialisate a random square matrix with dimension of the same length as a gene is generated (this can be optionally forced to be anti-symmetric). This matrix determines the score of one gene against another gene or patch characteristic vextor. All the entries indicated by a “1” in both are summed, the first indicating the selected columns, the second the rows.
New species arise due to a mutation occuring during propagation or the introduction of a new random species from outside.
The world is divided into patches the background colouring indicates its characteristics.
Individuals are small stars (if never eaten another individual) or circles (getting bigger for each other they eat) if they have. Colouring indicates species. Position within patches is not significant and randomised.
Energy Distribnution is a histogram of the energy levels of individuals.
Tropic Level Distribution is a histogram of the trophic levels. This is of individuals not species, so if an individual has eaten another that has eaten a ‘herbivore’ then it has a trophic level of at least 2.
pi-t and pi-d is (an estimate of) the average hamming distance between pairs of indiviuduals in the whole simulation and within patches respectively.
F-st is (pi-t - pi-d) / pi-t and is a measure of the amount of variety between patches.
F-st, pi-t and pi-d are only calculated at the end of simulations or when the button is pressed since it takes a while to calculate them.
L0, L1, L2+ are the number of individuals at trophic levels 0, 1 and above 1.
Patches are initialised with a random set of characteristics depending on num-env-chars.
At the start a population of efficiency * food-rate / life-tax individuals is created with the an energy distibution of init-energy + random-normal 0 (init-energy / 4) and a genetic distribution depending on the initial-species-variety setting (see above).
There are two sensible sets of settings for this simulation:
With initial-species-variety=1, new-species-prob=0 – so the initial variety ensures that some species are viable, resulting in a slow initial decline in number of species.
With initial-species-variety=0, new-species-prob>0 – in this case species are introduced (McKane fashion) one by one until a viable one is discovered. In this case the stop-new-species-once-established? might be used to stop the introduction of random species after a viable population is established.
gene-size - the number of bits in an individual’s gene
num-env-chars - the number of (effective) bits in the characteristics of a patch (functions similar to an individual’s gene)
migration-prob - the probability that any individual will move to another patch each time click
mut-prob - the probability that a newly born individual will have its gene mutated
food-rate - how much energy is put into the patches each time click (evenly divided among patches)
life-tax - how much energy subtracted from each individual each time click (dies if energy is 0 or below)
init-energy - the energy of a new born (this is subtracted from the parent at birth)
efficiency - what proportion of energy of something eaten goes to predator (or to herbivore from patch)
reproduce-level - if an individual’s energy gets to this point it gives birth once (new born’s energy being then ssubtracted from it)
eating-tries - each tick each individual tries to eat this number of others on the same patch, but this only happens if they dominate them via the interaction matrix
max-age - if > 0 individuals die when they reach this age in simulation ticks (otherwise no age ceiling)
max-store - if > 0 this is the upper bound on what energy individuals can accumulate (rest is lost to system)
init-new-species-prob - probability of a new individual with a random geneome being introduced each time click
stop-new-species-once-established? - if set stops new individuals with new genomes being introduced into the simulation once a viable population is established
initial-species-variety - 0/1 - if 0 simulation starts with a single individual (if this is not successful relies on a new individual being intyroduced via init-new-species-prob), if 1 starts with a full population with random genes
rand-death-prob - the probability an individual dies each time click (apart from other reasons)
anti-sym-mat? - forces the interaction matrix generated at start to be anti-symmetric
migrate-near? - if true then individuals migrate (if they do) to a neighbouring patch if false to a random other patch
allow-cannibals? - if true individuals of the same species can eat each other, if not can only eat those of another species
neutral? - if true then all individuals on a patch get the same amount of energy from the patch regardless of their geneome (otherwise they have to dominate the patch via the interaction matrix)
max-time - if > 0 the time at which the simulation is halted
At any point the state of the world can be saved to disk or retrieved (using the Save and Load buttons). When this happens the filename uses that in the “title” input box.
affected-char - if > 0 this prevents the numbered characteristic being taken into acount during dominance calculations using the interaction matrix. In other words this characteristic is supressed in terms of its efficacy.
The the Start-A, Do-A and End-A buttons initialise, do and calculate final stats from this point (up to max-time) with the affected-char intervention in place
In current tick:
Eats - how many are eaten
Deaths - total systematic deaths (eaten, starve, got too old)
Births - number of new individuals born due to parent reaching required energy
Pop - number of live individuals
Species - how many distinct genomes there are in living individuals
Starve - how many died of lack of energy
Old - how many died due to reaching max-age
Migr - how many migrated to another patch
Rand Die - how many died randomly (due to rand-death-prob)
secs/tick - how long current simulation tick took to compute (in seconds)
L0 - proportion of individuals that have not eated anyone ever (herbivores)
L1 - proportion of individuals that have ever eaten a herbivore
L2 - proportion of individuals that have ever eaten a carnivore
CummS - how many distinct geneomes have been created in current simulation
Only calculated when press Calc button or at end of simulation. All are about diversity measured as the average hamming distance between pairs of distinct individuals (estimated using random sample of 10000)
pi-t - the overall diversity
pi-d - diversity within patches
F-st - (pi-t - pi-d) / pi-t i.e. how much diversity is inter-patch
pi-env - diversity within all patches with same characteristics
F-env - (pi-t - pi-env) / pi-t how much diversity is inter-ptach-type
F-denv (pi-env - pi-d) / pi-env how much within patch diversity is due to variation between patches with same characteristics
Energy Distribution - histogram of the energy levels of individuals
Tropic Level Distribution - a histogram of number of individuals at each tropic level
Population - graph of number of living individuals
Number of Species - graph of number of distinct geneomes in current population
Log Population Types - graph of the number of individuals at different tropic levels (on a logarithmic scale)
This model relates to the McKane series of models to simulation the evolution of food webs, to meta-population models and to the “Patterns of genetic variation in populations of infectious agents” paper by Isabel Gordo and Paulo RA Campos in BMC Evoilutionary Biology.
Bruce Edmonds
7/11/12
extensions [table matrix]
breed [entities entity]
breed [people person]
globals [any-change? no-change-for end-tick dom-matrix init-pop-size num-patches num-empty-env
col-thresh trace? num-death-entitys num-starve num-eat num-born cumm-num-species new-species-prob
num-death-entitys-disp num-starve-disp num-eat-disp num-born-disp num-migrate num-migrate-disp
max-size dom-floor num-extinctions time-per-tick num-die-old num-die-old-disp bit-mutate-prob
num-ticks-with-non-zero-pop survival-threshold col-incr dom-matrix-list species-col-entity-list species-num-entity-list dv-vals-list
filename species-col-entity species-num-entity species-col-people species-num-people dv-vals
pi-t pi-d F-st pi-env F-env F-denv num-species l0 l1 l2+ patch-set-list list-patch-chars
analysis-phase? sample-size death-entity-threshold num-die-rand
s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 s16 pi1 pi2 pi3 pi4 pi5 pi6 pi7 pi8 pi9 pi10 pi11 pi12 pi13 pi14 pi15 pi16
num-born-people num-starve-people num-die-old-people num-die-rand-people num-die-old-people-disp num-starve-people-disp
num-species-people num-species-people-cumm between-people-count num-variants species-col-people-list species-num-people-list
life-tax init-energy num-entities num-people av-tolerance sd-tolerance av-sharing sd-sharing av-learning sd-learning
pi-t-people pi-d-people F-st-people pi-env-people F-env-people F-denv-people
]
entities-own [gene energy level age]
people-own [gene tag tolerance energy level age num-sharing num-learning generation]
patches-own [chars resource]
to setup
clear-all
resize-world 0 (world-size - 1) 0 (world-size - 1)
set life-tax 0.05
set init-energy 1.0
ifelse (strip-spaces title) = "" [set filename "iEMS Model + social"] [set filename strip-spaces title]
;; set filename (word filename "-" (substring date-and-time 16 length date-and-time) "-" behaviorspace-run-number)
ifelse initial-species-variety = 0
[set init-pop-size 1]
[set init-pop-size (2 / 3) * efficiency * food-rate / life-tax]
set num-patches (max-pxcor + 1) * (max-pycor + 1)
set survival-threshold 2 * food-rate / (life-tax * num-patches)
set death-entity-threshold 0
set col-incr 30
set num-empty-env gene-size - num-env-chars
set col-thresh 20
set max-size 0.25
set sample-size 10000
set new-species-prob init-new-species-prob
set trace? false
set analysis-phase? false
set dom-floor 0
set num-ticks-with-non-zero-pop max (list 200 max-age (2 * init-energy / life-tax))
set cumm-num-species 0
set num-species-people-cumm 0
set num-variants 0
set species-col-entity table:make
set species-num-entity table:make
set species-col-people table:make
set species-num-people table:make
set dv-vals table:make
clear-save-lists
set dom-matrix matrix:from-row-list n-values gene-size [n-values gene-size [rand-val]]
if anti-sym-mat? [set dom-matrix a-sym dom-matrix]
set list-patch-chars []
let n 0
ask patches [
set resource 0
set chars sentence n-values num-env-chars [rand-bin] n-values num-empty-env [0]
if not member? chars list-patch-chars [set list-patch-chars fput chars list-patch-chars]
set pcolor (list (col-thresh * (1 + first chars)) (col-thresh * (1 + second chars)) (col-thresh * (1 + third chars)))
]
set patch-set-list map [patches with [chars = ?]] list-patch-chars
let temp-gene n-values gene-size [rand-bin]
create-entities init-pop-size [
set age 0 + random (max-age / 3)
set energy init-energy + random-normal 0 (init-energy / 3)
ifelse initial-species-variety = 1
[set gene n-values gene-size [rand-bin]]
[set gene temp-gene]
set color new-gene-entity gene
setxy random (max-pxcor + 1) random (max-pycor + 1)
set shape "star"
set size 0.1
set level 0
show-turtle
place
]
reset-ticks
end
to place
set xcor [pxcor] of patch-here + random-float 0.9 - 0.45
set ycor [pycor] of patch-here + random-float 0.9 - 0.45
end
to-report a-sym [mat]
let m2 matrix:plus mat matrix:transpose mat
report m2
end
to-report rand-val
;; report (random-float 2) - 1
report random-normal 0 0.3333
end
to-report rand-bin
report random 2
end
to-report hamming-dist [vec1 vec2]
report sum (map [ifelse-value (?1 = ?2) [0] [1]] vec1 vec2)
end
to-report name
report (word self)
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to go
reset-timer
;; if time is done stop simulation
;; if max-time > 0 and ticks > max-time [
;; stop
;; ]
set end-tick ticks
set any-change? false
if new-species-prob > 0 [
if count entities > 0
[set num-ticks-with-non-zero-pop num-ticks-with-non-zero-pop + 1]
if num-ticks-with-non-zero-pop > survival-threshold [set new-species-prob 0]
]
;; distribute resources to patches
ask patches [set resource resource + food-rate / num-patches]
;; entities
set num-starve 0
set num-die-old 0
set num-die-rand 0
;; life tax, aging and death-entity
ask entities [
set energy energy - life-tax
set age age + 1
if energy < death-entity-threshold [set num-starve num-starve + 1 death-entity]
if max-age > 0 and age > max-age [set num-die-old num-die-old + 1 death-entity]
if prob rand-death-entity-prob [set num-die-rand num-die-rand + 1 death-entity]
]
set num-die-old-disp num-die-old
set num-starve-disp num-starve
;; people dying
;; people
set num-starve-people 0
set num-die-old-people 0
set num-die-rand-people 0
ask people [
set num-learning 0
set num-sharing 0
]
;; life tax, aging and death-entity
ask people [
set energy energy - life-tax
set age age + 1
if energy < death-entity-threshold [set num-starve-people num-starve-people + 1 death-people]
if max-age-people > 0 and age > max-age-people [set num-die-old-people num-die-old-people + 1 death-people]
if prob rand-death-entity-prob [set num-die-rand-people num-die-rand-people + 1 death-people]
]
set num-die-old-people-disp num-die-old-people
set num-starve-people-disp num-starve-people
;; new entrants from outside
if prob new-species-prob or (initial-species-variety = 0 and count entities = 0) [
create-entities 1 [
set age 0
set energy init-energy + random-normal 0 (init-energy / 4)
set gene n-values gene-size [rand-bin]
set color new-gene-entity gene
setxy random (max-pxcor + 1) random (max-pycor + 1)
set shape "star"
set size 0.1
set level 0
show-turtle
place
]
]
;; extracting energy from the patch
;; at the moment the energy is shared by any > dom-floor proportionately
;; entities only unless people-f-env? is on
ask patches [
let distributees no-turtles
ifelse people-f-env?
[set distributees (turtle-set entities-here people-here)]
[set distributees entities-here]
if not any? distributees [stop]
let tl sort distributees
let nt (length tl) - 1
let rl []
ifelse neutral?
[set rl map [0.01] tl]
[set rl map [? - dom-floor] map [max list dom-floor dv ([gene] of ?) chars] tl]
let sumrl sum rl
if sumrl = 0 [stop]
let lf resource / sumrl
let i 0
foreach seq 0 nt 1 [
set i item ? rl
if i > 0 [
ask item ? tl [set energy energy + efficiency * lf * i]
set resource resource - lf * i
]
]
]
;; predation
;; both entities and people
set num-eat 0
ask turtles [
foreach safeSubList (shuffle sort other entities-here) 0 eating-tries [
if dom? gene [gene] of ? [
set level 1 + [level] of ?
set energy energy + efficiency * [energy] of ?
ask ? [ifelse breed = entities [death-entity] [death-people]]
set num-eat num-eat + 1
ifelse breed = entities
[set shape "circle"]
[set shape "face happy"]
set size min list max-size size + 0.05
]
]
]
set num-eat-disp num-eat
;; reduce all stores to max-store if this is > 0
if max-store > 0 [
ask entities [
set energy min list energy max-store
]
]
if max-people-store > 0 [
ask people [
set energy min list energy max-people-store
]
]
;; people bits here
;; initial people
if ticks = people-enter [init-people]
ifelse not any? people
[set between-people-count between-people-count + 1]
[set between-people-count 0]
if ticks > people-enter and between-people-count >= time-between-invasions and not any? people [init-people]
;; people births
set num-born-people 0
let old-gen 0
ask people [
if energy >= reproduce-level-people [
set old-gen generation
hatch 1 [
let col [0 0 0]
set age 0
set generation old-gen + 1
set energy init-energy
set size 0.2
set shape "face neutral"
set level 0
set color mutated-gene-people gene
set tag (mutate-sd tag tag-mut-sd) mod 1
ifelse tol-on?
[set tolerance min list max-tolerance max list 0 (mutate-sd tolerance tol-mut-sd)]
[set tolerance 2]
place
]
set energy energy - 2 * init-energy
]
]
;; people learning, innovating, sharing
let poss-people no-turtles
let poss-people-better no-turtles
let my-tag 0
let my-tol 0
let my-energy 0
let oth nobody
let old-gene []
ask people [
if prob innovation-prob [
set gene mutate gene (1 / gene-size)
set color mutated-gene-people gene
]
set my-tag tag
set my-tol tolerance
set my-energy energy
set old-gene gene
if coop-radius = 1 [set poss-people other people-here with [(tag-dist tag my-tag) < my-tol]]
if coop-radius = 5 [set poss-people other people-here5 with [(tag-dist tag my-tag) < my-tol]]
if coop-radius = 9 [set poss-people other people-here9 with [(tag-dist tag my-tag) < my-tol]]
if any? poss-people [
if prob learn-prob [
set poss-people-better (poss-people with [energy > my-energy])
if any? poss-people-better [
set gene learn-from gene ([gene] of one-of poss-people-better)
if gene != old-gene [
set color mutated-gene-people gene
remove-one old-gene
set num-learning num-learning + 1
]
]
]
;; people sharing
repeat share-tries [
if energy > min-share-level [
set num-sharing num-sharing + 1
set oth one-of poss-people
set energy energy - 1
ask oth [set energy energy + share-efficiency]
]
]
]
]
;; entity births
set num-born 0
ask entities [
if energy >= reproduce-level [
hatch 1 [
let col [0 0 0]
set age 0
set energy init-energy
set size 0.1
set shape "star"
set level 0
if prob mut-prob [
;; Note!! a prob of each bit being flipped of mut-prob as well as chance for this to happen
set gene mutate gene (1 / gene-size)
]
set color mutated-gene-entity gene
place
]
set num-born num-born + 1
set energy energy - init-energy
]
]
set num-born-disp num-born
;; migrations
;; all
set num-migrate 0
ifelse migrate-near? [
ask entities [if prob migration-prob [move-near]]
] [
ask entities [
if prob migration-prob [
setxy random (max-pxcor + 1) random (max-pycor + 1)
place
set num-migrate num-migrate + 1
]
]
]
;; people
ifelse migrate-near? [
ask people [if prob migration-prob-people [move-near]]
] [
ask people [
if prob migration-prob-people [
setxy random (max-pxcor + 1) random (max-pycor + 1)
place
set num-migrate num-migrate + 1
]
]
]
set num-migrate-disp num-migrate
set num-variants
ifelse-value any? people
[length remove-duplicates [gene] of people]
[0]
set num-species table:length species-num-entity
if any? people [set num-species-people table:length species-num-people]
set l0 safeDiv count entities with [level = 0] count entities
set l1 safeDiv count entities with [level = 1] count entities
set l2+ safeDiv count entities with [level > 1] count entities
set num-people count people
set num-entities count entities
set av-tolerance ifelse-value any? people [mean [tolerance] of people] [0]
set sd-tolerance ifelse-value (count people > 1) [standard-deviation [tolerance] of people] [0]
set av-sharing ifelse-value any? people [mean [num-sharing] of people] [0]
set sd-sharing ifelse-value (count people > 1) [standard-deviation [num-sharing] of people] [0]
set av-learning ifelse-value any? people [mean [num-learning] of people] [0]
set sd-learning ifelse-value (count people > 1) [standard-deviation [num-learning] of people] [0]
set time-per-tick timer
if max-time > 0 and ticks >= max-time [
show "finished"
calc-stats
calc-stats-people
end-analysis
stop
]
tick
end
to-report dv [g1 g2]
let op 0
ifelse table:has-key? dv-vals list g1 g2
[set op table:get dv-vals list g1 g2]
[set op calc-dv g1 g2
table:put dv-vals list g1 g2 op]
report op
end
to clear-dv-cache
table:clear dv-vals
end
to-report calc-dv [g1 g2]
;; if affected-char > 0 [
if affected-char > 0 [
set g1 replace-item (affected-char - 1) g1 0
set g2 replace-item (affected-char - 1) g2 0
]
let op 0
let i 0
foreach (seq 0 (gene-size - 1) 1) [
set i ?
if (item i g1) != 0 [
foreach seq 0 (gene-size - 1) 1 [
set op op + (item ? g2) * (matrix:get dom-matrix i ?)
]
]
]
report op
end
to move-near
let ns neighbors
if not any? ns [stop]
let next-patch one-of ns
setxy [pxcor] of next-patch [pycor] of next-patch
place
set num-migrate num-migrate + 1
end
to-report rand-plus-minus
report (2 * random 2) - 1
end
to-report dom? [g1 g2]
if not allow-cannibals? and g1 = g2 [report false]
report dv g1 g2 > dom-floor
end
to-report sel-pos [pl vl]
if empty? pl [report []]
ifelse first pl > 0
[report fput first vl (sel-pos but-first pl but-first vl)]
[report sel-pos but-first pl but-first vl]
end
to-report shade [cl]
report (list chc first cl chc second cl chc last cl)
end
to-report rand-col
report (list rand-rbg-val rand-rbg-val rand-rbg-val)
end
to-report rand-rbg-val
report col-thresh + random-float (255 - col-thresh)
end
to-report chc [v]
report min list 255 max list col-thresh ch-val v
end
to-report ch-val [v]
if v >= 255 [report v - col-incr - random col-incr]
if v <= col-thresh [report v + col-incr + random col-incr]
ifelse 0 = random 2
[report v + col-incr + random col-incr]
[report v - col-incr - random col-incr]
end
to-report mutate [g p]
;; report flip-bit random gene-size g
let op []
repeat length g [
ifelse prob p
[set op fput (1 - first g) op]
[set op fput first g op]
set g but-first g
]
report reverse op
end
to-report flip-bit [p g]
report replace-item p g (1 - item p g)
end
to calc-stats
set pi-t 0
set pi-t 0
set pi-d 0
set F-st 0
set pi-env 0
set F-env 0
let ot nobody
let my-gene []
let ps nobody
let p nobody
let p1 nobody
let p2 nobody
if any? entities [
repeat sample-size [
ask one-of entities [
set my-gene gene
if any? other entities
[ask one-of other entities [set pi-t pi-t + hamming-dist my-gene gene]]
]
]
repeat sample-size [
ask one-of entities [
set my-gene gene
if any? other entities-here
[ask one-of other entities-here [set pi-d pi-d + hamming-dist my-gene gene]]
]
]
set ps map [entities-from ?] patch-set-list
repeat sample-size [
set p random-member ps
if any? p [
set p1 one-of p
ask p1 [set p2 one-of other (turtle-set ps)]
if p2 != nobody [
set pi-env pi-env + hamming-dist [gene] of p1 [gene] of p2
]
]
]
set pi-d safeDiv pi-d sample-size
set pi-t safeDiv pi-t sample-size
set pi-env safeDiv pi-env sample-size
set F-st safeDiv (pi-t - pi-d) pi-t
set F-env safeDiv (pi-t - pi-env) pi-t
set F-denv safeDiv (pi-env - pi-d) pi-env
]
end
to calc-stats-people
set pi-t-people 0
set pi-t-people safeDiv pi-t-people sample-size
set pi-d-people 0
set F-st-people 0
set pi-env-people 0
set F-env-people 0
let ot nobody
let my-gene []
let ps nobody
let p nobody
let p1 nobody
let p2 nobody
if any? people [
repeat sample-size [
ask one-of people [
set my-gene gene
if any? other people
[ask one-of other people [set pi-t-people pi-t-people + hamming-dist my-gene gene]]
]
]
repeat sample-size [
ask one-of people [
set my-gene gene
if any? other people-here
[ask one-of other people-here [set pi-d-people pi-d-people + hamming-dist my-gene gene]]
]
]
set ps map [people-from ?] patch-set-list
repeat sample-size [
set p random-member ps
if any? p [
set p1 one-of p
ask p1 [set p2 one-of other (turtle-set ps)]
if p2 != nobody [
set pi-env-people pi-env-people + hamming-dist [gene] of p1 [gene] of p2
]
]
]
set pi-d-people safeDiv pi-d-people sample-size
set pi-t-people safeDiv pi-t-people sample-size
set pi-env-people safeDiv pi-env-people sample-size
set F-st-people safeDiv (pi-t-people - pi-d-people) pi-t-people
set F-env-people safeDiv (pi-t-people - pi-env-people) pi-t-people
set F-denv-people safeDiv (pi-env-people - pi-d-people) pi-env-people
]
end
to-report ecology-state
if count entities < 10 [report "non-viable"]
if num-species < 2 [report "one-species"]
if l1 = 0 [report "hebivore"]
report "mixed"
end
to-report people-state
if not any? people [report "none"]
if not any? people with [level > 0] [report "starving"]
if not any? people with [generation > 0] [report "barren"]
report "viable"
end
to-report entities-from [ps]
report entities with [member? patch-here ps]
end
to-report people-from [ps]
report people with [member? patch-here ps]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to a-a-PEOPLE-STUFF end
to init-people
let a-random-gene n-values gene-size [rand-bin]
let a-rand-x random (max-pxcor + 1)
let a-rand-y random (max-pycor + 1)
create-people num-people-enter [
set age 0
set generation 0
set energy init-energy + random-normal 0 (init-energy / 4)
ifelse (init-variety = 0)
[set gene a-random-gene]
[set gene n-values gene-size [rand-bin]]
set color new-gene-people gene
setxy random (max-pxcor + 1) random (max-pycor + 1)
set shape "face neutral"
set size 0.2
set level 0
set tag random-float 1
ifelse tol-on?
[set tolerance random-float max-tolerance]
[set tolerance 2]
setxy a-rand-x a-rand-y
show-turtle
place
]
end
to-report learn-from [mg og]
let ps random gene-size
report replace-item ps mg (item ps og)
end
to-report mutate-sd [vl sd]
report (vl + random-normal 0 sd) mod 1
end
to-report tag-dist [t1 t2]
let mn min list t1 t2
let mx max list t1 t2
report min list (mx - mn) (1 + mn - mx)
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to a-a-GENE-STUFF end
to-report new-gene-entity [g]
ifelse table:has-key? species-num-entity g [
table:put species-num-entity g 1 + table:get species-num-entity g
set color table:get species-col-entity g
] [
set color rand-col
table:put species-col-entity g color
table:put species-num-entity g 1
set cumm-num-species cumm-num-species + 1
]
report color
end
to-report mutated-gene-entity [g]
ifelse table:has-key? species-num-entity g [
table:put species-num-entity g 1 + table:get species-num-entity g
set color table:get species-col-entity g
] [
set color shade color
table:put species-col-entity g color
table:put species-num-entity g 1
set cumm-num-species cumm-num-species + 1
]
report color
end
to-report new-gene-people [g]
ifelse table:has-key? species-num-people g [
table:put species-num-people g 1 + table:get species-num-people g
set color table:get species-col-people g
] [
set color rand-col
table:put species-col-people g color
table:put species-num-people g 1
]
report color
end
to-report mutated-gene-people [g]
ifelse table:has-key? species-num-people g [
table:put species-num-people g 1 + table:get species-num-people g
set color table:get species-col-people g
] [
set color shade color
table:put species-col-people g color
table:put species-num-people g 1
]
report color
end
to death-entity
let num-of-this (table:get species-num-entity gene) - 1
table:put species-num-entity gene num-of-this
if num-of-this < 1 [
table:remove species-col-entity gene
table:remove species-num-entity gene
]
die
end
to death-people
remove-one gene
die
end
to remove-one [g]
let num-of-this (table:get species-num-people g) - 1
table:put species-num-people g num-of-this
if num-of-this < 1 [
table:remove species-col-people g
table:remove species-num-people g
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to a-a-SAVE-LOAD end
to save-world
set dom-matrix-list matrix:to-row-list dom-matrix
set species-col-entity-list table:to-list species-col-entity
set species-num-entity-list table:to-list species-num-entity
set species-col-people-list table:to-list species-col-people
set species-num-people-list table:to-list species-num-people
export-world (word title "-state.csv")
end
to load-world
let fn (word title "-state.csv")
if not file-exists? fn
[set fn user-file]
import-world fn
set dom-matrix matrix:from-row-list dom-matrix-list
set species-col-entity table:from-list species-col-entity-list
set species-num-entity table:from-list species-num-entity-list
set species-col-people table:from-list species-col-people-list
set species-num-people table:from-list species-num-entity-list
set dv-vals-list []
table:clear dv-vals
set analysis-phase? true
end
to clear-save-lists
set dom-matrix-list []
set species-col-entity-list []
set species-num-entity-list []
set species-col-people-list []
set species-num-people-list []
set dv-vals-list []
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to a-a-ANALYSIS end
to start-analysis
set analysis-phase? true
clear-dv-cache
random-seed new-seed
;; stuff for running sim with params
;; set learn-prob learn-prob-p
;; set init-variety init-variety-p
;; set num-people-enter num-people-enter-p
;; set num-env-chars num-env-chars-p
;; set init-variety init-variety-p
;; set tag-mut-sd tag-mut-sd-p
;; set max-age-people max-age-people-p
;; set migrate-near? migrate-near?-p
;; set reproduce-level reproduce-level-p
;; set innovation-prob innovation-prob-p
;; set rand-death-entity-prob rand-death-entity-prob-p
;; set title title-p
;; set max-people-store max-people-store-p
;; set migration-prob migration-prob-p
;; set eating-tries eating-tries-p
;; set share-tries share-tries-p
;; set max-store max-store-p
;; set time-between-invasions time-between-invasions-p
;; set mut-prob mut-prob-p
;; set max-tolerance max-tolerance-p
;; set reproduce-level-people reproduce-level-people-p
;; set max-time max-time-p
;; set min-share-level min-share-level-p
;; set max-age max-age-p
;; set people-enter people-enter-p
;; set efficiency efficiency-p
;; set neutral? neutral?-p
;; set share-efficiency share-efficiency-p
;; set tol-mut-sd tol-mut-sd-p
;; set food-rate food-rate-p
;; set tol-on? tol-on-p?
;; set coop-radius coop-radius-p
;; set people-f-env? people-f-env-p?
end
to end-analysis
calc-niche-stats
end
to calc-niche-stats
let p 0 let ps nobody let as nobody let char-num 0
let list-patch-nums map [num-from-binvec ? num-env-chars] list-patch-chars
if num-env-chars < 1 [stop]
set char-num 1
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s1 calc-ns as
set pi1 calc-pi as
]
set char-num 2
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s2 calc-ns as
set pi2 calc-pi as
]
if num-env-chars < 2 [stop]
set char-num 3
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s3 calc-ns as
set pi3 calc-pi as
]
set char-num 4
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s4 calc-ns as
set pi4 calc-pi as
]
if num-env-chars < 3 [stop]
set char-num 5
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s5 calc-ns as
set pi5 calc-pi as
]
set char-num 6
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s6 calc-ns as
set pi6 calc-pi as
]
set char-num 7
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s7 calc-ns as
set pi7 calc-pi as
]
set char-num 8
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s8 calc-ns as
set pi8 calc-pi as
]
if num-env-chars < 4 [stop]
set char-num 9
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s9 calc-ns as
set pi9 calc-pi as
]
set char-num 10
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s10 calc-ns as
set pi10 calc-pi as
]
set char-num 11
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s11 calc-ns as
set pi11 calc-pi as
]
set char-num 12
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s12 calc-ns as
set pi12 calc-pi as
]
set char-num 13
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s13 calc-ns as
set pi13 calc-pi as
]
set char-num 14
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s14 calc-ns as
set pi14 calc-pi as
]
set char-num 15
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s15 calc-ns as
set pi15 calc-pi as
]
set char-num 16
set p position (char-num - 1) list-patch-nums
if p != false [
set ps item p patch-set-list
set as entities-from ps
set s16 calc-ns as
set pi16 calc-pi as
]
end
to-report calc-pi [ts]
if count ts <= 1 [report 0]
let op 0 let t1 nobody let t2 nobody
repeat sample-size [
set t1 one-of ts
ask t1 [set t2 one-of other ts]
set op op + hamming-dist [gene] of t1 [gene] of t2
]
report op / sample-size
end
to-report calc-ns [ts]
report length remove-duplicates [gene] of ts
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to a-a-GEN-UTILS end
to-report people-here5
report (turtle-set people-here people-on neighbors4)
end
to-report people-here9
report (turtle-set people-here people-on neighbors)
end
to-report sign [num]
if num = 0 [report 0]
ifelse num > 0
[report 1]
[report -1]
end
to-report num-from-binvec [binvec numplaces]
let op 0
foreach seq 0 (numplaces - 1) 1 [
set op op + (2 ^ ?) * item ? binvec
]
report op
end
to-report second [l]
report first but-first l
end
to-report num-links
report count my-links
end
to-report set-pos [pos lis]
report replace-item pos lis 1
end
to-report clear-pos [pos lis]
report replace-item pos lis 0
end
to-report safe-item [pos lis]
if pos > (length lis - 1) [report 0]
report item pos lis
end
to-report remove-list [remlis lis]
let opl lis
foreach remlis [
set opl remove ? lis
]
report opl
end
to-report n-colours [n]
;; produces a list of n random visible colurs (not too near black)
report n-values n [(list (10 + random 245) (10 + random 245) (10 + random 245))]
end
to-report poss-of-len [dim]
if dim <= 0 [report [[]]]
let poss-minus1 poss-of-len (dim - 1)
report sentence (map [fput 0 ?] poss-minus1) (map [fput 1 ?] poss-minus1)
end
to pause
if not user-yes-or-no? (word "Continue?") [error "User halted simulation!!"]
end
to-report showpause [inp]
if not user-yes-or-no? (word "Value is: " inp " -- Continue?") [error "User halted simulation!!"]
report inp
end
to ipat [p1 p2]
inspect patch p1 p2
end
to ith
ask entities-here [inspect self]
end
to-report link-breed [p1 p2]
let pl []
ask p1 [set pl sort my-links]
ask p2 [
let p2l sort my-links
set pl filter [member? ? p2l] pl
]
if empty? pl [report "none"]
report [breed] of (random-member pl)
end
to-report random-member [ls]
report item (random length ls) ls
end
to-report prob [p]
report random-float 1 < p
end
to-report subtract-list [lis1 lis2]
report filter [not member? ? lis2] lis1
end
to-report safeSubList [lis srt en]
let len length lis
if en < 1 or srt > len [report []]
report subList lis max list 0 srt min list en len
end
to-report safe-n-of [nm lis]
if is-list? lis [if length lis >= nm [report n-of nm lis]]
if is-agentset? lis [if count lis >= nm [report n-of nm lis]]
report lis
end
to-report safe-one-of [lis]
report safe-n-of 1 lis
end
to-report flatten-once [lis]
let op-list []
foreach lis [
foreach ? [set op-list fput ? op-list]
]
report op-list
end
to-report minList [lis1 lis2]
report (map [min list ?1 ?2] lis1 lis2)
end
to-report maxList [lis1 lis2]
report (map [max list ?1 ?2] lis1 lis2)
end
to-report sumList [lis1 lis2]
report (map [?1 + ?2] lis1 lis2)
end
to-report sdList [sqLis sumLis numLis]
report (map [sqrt max (list 0 ((?1 / numLis) - ((?2 / numLis) ^ 2)))] sqLis sumLis)
end
to-report fputIfNew [exLisLis newLis]
report (map [ifelse-value (member? ?2 ?1) [?1] [fput ?2 ?1]] exLisLis newLis)
end
to-report csv-string-to-list [str]
let lis []
while [not empty? str] [
set lis fput next-value str lis
set str after-next str
]
report reverse lis
end
to-report after-next [str]
let pos-comma position "," str
if pos-comma != false [report subString str (pos-comma + 1) length str]
report ""
end
to-report next-value [str]
let pos-comma position "," str
if pos-comma != false [
report read subString str 0 pos-comma
]
report read str
end
to-report read [str]
set str strip-spaces str
if empty? str [report nobody]
ifelse is-string-a-number? str
[report read-from-string str]
[report str]
end
to-report strip-spaces [str]
report strip-leading-spaces strip-trailing-spaces str
end
to-report strip-leading-spaces [str]
if empty? str [report str]
if first str != " " [report str]
report strip-leading-spaces but-first str
end
to-report is-string-a-number? [str]
if empty? str
[report false]
report is-nonempty-string-a-number? str
end
to-report is-nonempty-string-a-number? [str]
if empty? str [report true]
let ch first str
if ch = "." [report is-string-digits? but-first str]
if not is-str-digit? ch [report false]
report is-nonempty-string-a-number? but-first str
end
to-report is-string-digits? [str]
if empty? str [report true]
let ch first str
if not is-str-digit? ch [report false]
report is-string-digits? but-first str
end
to-report is-str-digit? [ch]
ifelse ch >= "0" and ch <= "9"
[report true]
[report false]
end
to-report strip-trailing-spaces [str]
if empty? str [report str]
if last str != " " [report str]
report strip-trailing-spaces but-last str
end
to-report insert [itm ps lis]
report (sentence sublist lis 0 ps (list itm) sublist lis ps (length lis))
end
to-report insertAfter [itm ps lis]
report insert itm (ps + 1) lis
end
to-report num-nodes [lis]
report length nodes-in lis
end
to-report nodes-in [lis]
if not is-list? lis [report (list lis)]
let op-list []
foreach lis [set op-list append op-list nodes-in ?]
report op-list
end
to-report third [lis]
report item 2 lis
end
to XXX
let tt 1
set tt tt - 1
set tt 1 / tt
end
to-report showPass [arg]
show arg
report arg
end
to-report posBiggest [lis]
report position (reduce [ifelse-value (?1 >= ?2) [?1] [?2]] lis) lis
end
to-report allPos [expr]
let oplis [[]]
foreach but-first (n-values (length expr) [?]) [
let ps ?
let posLis allPos (item ps expr)
set opLis append (map [fput ps ?1] posLis) opLis
]
report opLis
end
to-report replaceAtPos [posList baseExpr insExpr]
if posList = [] [report insExpr]
report replace-item (first posList) baseExpr (replaceAtPos (but-first posList) (item first posList baseExpr) insExpr)
end
to-report atPos [posList expr]
if empty? posList [report expr]
report atPos but-first posList item (first poslist) expr
end
to-report append [list1 list2]
if empty? list1 [report list2]
report fput (first list1) (append (but-first list1) list2)
end
to-report selectProbilistically [charList numList]
report item (chooseProbilistically numList) charList
end
to-report chooseProbilistically [numList]
report findPos (random-float 1) cummulateList scaleList numList
end
to-report chooseReverseProbilistically [numList]
if length numList = 1 [report 0]
report findPos (random-float 1) cummulateList reverseProbList scaleList numList
end
to-report reverseProbList [numList]
report map [1 - ?1] numList
end
to-report cummulateList [numList]
report cummulateListR numList 0
end
to-report cummulateListR [numList cumm]
if empty? numList [report []]
let newCumm cumm + first numList
report fput newCumm cummulateListR but-first numList newCumm
end
to-report scaleList [numLis]
if empty? numLis [report numLis]
let sumLis sum numLis
if sumLis = 0 [report numLis]
report map [?1 / sumLis] numLis
end
to-report findPos [vl numList]
report findPosR vl numList 0
end
to-report findPosR [vl numList ps]
if empty? numList [report ps]
if vl <= (first numList) [report ps]
report findPosR vl but-first numList (1 + ps)
end
to-report freqOfIn [lis allList]
report reduce [fput (numOfIn ?2 lis) ?1 ] (fput [] allList)
end
to-report freqOf [lis]
if empty? lis [report []]
let sort-lis sort lis
let red-lis sort remove-duplicates lis
let op-lis red-lis
let num-lis []
let cnt 0
foreach sort-lis [
ifelse ? = first red-lis
[set cnt cnt + 1]
[set num-lis fput cnt num-lis
set cnt 1
set red-lis but-first red-lis]
]
set num-lis fput cnt num-lis
report pair-list (reverse num-lis) op-lis
;; report pair-list reverse num-lis red-lis
;; report fput (list (numOfIn first lis lis) (first lis)) (freqOf remove first lis lis)
end
to-report freqRep [lis]
report sort-by [first ?1 > first ?2] filter [first ? > 1] freqOf lis
end
to-report numOfIn [itm lis]
report length (filter [itm = ?] lis)
end
to-report patchesToDist [dist]
if dist = 0 [report self]
let patchList []
foreach seq (-1 * dist) dist 1 [
let xc ?
foreach seq (-1 * dist) dist 1 [
set patchList fput patch-at xc ? patchList
]
]
report patch-set patchList
end
to-report individualsToDist [dist]
report entities-on patchesToDist dist
end
to-report distBetween [x1 y1 x2 y2]
report (max list abs (x1 - x2) abs (y1 - y2))
;; report sqrt (((x1 - x2) ^ 2) + ((y1 - y2) ^ 2))
end
to-report seq [from upto stp]
report n-values (1 + ceiling ((upto - from) / stp)) [from + ? * stp]
end
to-report safeDiv [numer denom]
if denom = 0 and numer = 0 [report 1]
if denom = 0 [report 0]
report numer / denom
end
;;to-report flip-bit [ps bitList]
;; report replace-item ps bitList (1 - (item ps bitList))
;;end
to showList [lis]
foreach but-last lis [type ? type " "]
print last lis
end
to-report is-divisor-of [num den]
report (0 = (num mod den))
end
to-report pair-list [lis1 lis2]
report (map [list ?1 ?2] lis1 lis2)
end
to-report depth [lis]
if not is-list? lis [report 0]
if empty? lis [report 0]
report 1 + max map [depth ?] lis
end
to-report empty-as
report no-turtles
end
to-report exists [obj]
if is-turtle-set? obj [report any? obj]
report obj != nobody
end
to-report pick-at-random-from-list [lis]
report item random length lis lis
end
to tv [str val]
if trace? [output-print (word str "=" val)]
end
to-report normal-dist [x mn sd]
report exp (-0.5 * ((x - mn) / sd) ^ 2) / (sd * sqrt (2 * pi))
end
to-report careful-item [ps lis str]
let rs 0
carefully
[set rs item ps lis]
[output-print (word "str" ": no position " ps " in: " lis)]
report rs
end