📄 ---compete.nlogo
字号:
;; vim: comments=\:\;\;
;; -----------------------------------------------------------------------------
;;
;; NetLogo simulation of the COMPETE model in a three-species environment
;;
;; put forth in Johnson & Seinen (2002), "Selection for restraint in
;; competitive ability in spatial competition systems"
;;
;; implemented are both, the Standard and the Catalyst rulesets.
;;
;; Written in November 2002 by Martin F. Krafft <krafft@ifi.unizh.ch>
;; for the Insitute of Information Technologies
;; at the University of Zurich.
;;
;; Feel free to do with this what you like. Give credit where credit is due!
;;
;; $Id:$
;;
;; -----------------------------------------------------------------------------
;; we have three species, conveniently named one, two, and three this is,
;; unfortunately, hard-coded due to NetLogo's limitations.
breeds [ one two three ]
;; we need to store these additional attributes per individual.
turtles-own [
species ;; an index into the vectors (one = 0, two = 1, three = 2)
growth-rate ;; the individual's growth-rate
;; the following needs explanation: 'item <index> <vector>' returns the
;; <index>'th item of the vector. we store the win, lose, and standoff
;; chances per individual, relative to the individual. indexing into this
;; vector is done by opposite species. whatever, here is an example to make
;; this clear:
;;
;; assume the following table of win chances:
;;
;; | one | two |three|
;; -----+-----+-----+-----+
;; one| 0 | 0.4 | 0.7 |
;; -----+-----+-----+-----+
;; two| 0.5 | 0 | 0.2 |
;; -----+-----+-----+-----+
;; three| 0.6 | 0.3 | 0 |
;; -----+-----+-----+-----+
;;
;; the winvec stored in an instantiation of species one is the row labeled
;; 'one'. the same applies to the other two breeds. now, to ask a member of
;; species one for it's chance to win against a member of three (whose
;; species value of three is 2 since indexing starts at 0) we'd do this:
;;
;; ask one-of one [ show item 2 winvec ]
;; "tell one member of the one breed to show the third item (2) of
;; it's vector of winning chances."
;;
;; ---> 0.7
;;
;; this method is nice, as it automatically deals with the case when we
;; compare two members of the same species. since the corresponding entry in
;; the vector is always 0.
winvec ;; the vector of relative winning chances
losevec ;; the vector of relative losing chances
standoffvec ;; the vector of relative standoff chances
]
globals [
ticks ;; time counter
n-one ;; number of instantiations of species one
n-two ;; number of instantiations of species two
n-three ;; number of instantiations of species three
]
;; -----------------------------------------------------------------------------
to setup
locals [
area ;; area of world
p-sum ;; sum of popularity
]
;; initialization: clear-all and reset time
ca
set ticks 0
ifelse not update-display? [ no-display ] [ display ]
;; use the relative p-* values to populate all the patches in
;; the world accordingly.
set p-sum p-one + p-two + p-three + p-empty
set area screen-size-x * screen-size-y
set n-one floor ((p-one / p-sum) * area)
set n-two floor ((p-two / p-sum) * area)
set n-three floor ((p-three / p-sum) * area)
;; create all members of a all species, coloring them accordingly, placing
;; them in a random yet free spot on the map and initializing their
;; attibrutes according to the species' global values.
create-custom-one n-one [
set color red
set species 0 ;; one == 0 because computer indexing starts at 0
set growth-rate growth-rate-one
;; you have to love this notation!
set winvec sentence 0 sentence win-1-2 win-1-3 ;; [ 0 w12 w13 ]
set losevec sentence 0 sentence lose-1-2 lose-1-3 ;; [ 0 l12 l13 ]
set standoffvec sentence 0 sentence standoff-1-2 standoff-1-3
;; [ 0 s12 s13 ]
place-turtle-randomly
]
create-custom-two n-two [
set color blue
set species 1 ;; two == 1 because computer indexing starts at 0
set growth-rate growth-rate-two
;; i mean, if you don't love it, you might not understand it ...
set winvec sentence win-2-1 sentence 0 win-2-3 ;; [ w21 0 w23 ]
set losevec sentence lose-2-1 sentence 0 lose-2-3 ;; [ l21 0 l23 ]
set standoffvec sentence standoff-2-1 sentence 0 standoff-2-3
;; [ s21 0 s23 ]
place-turtle-randomly
]
create-custom-three n-three [
set color 53
set species 2 ;; three == 2 because computer indexing starts at 0
set growth-rate growth-rate-three
;; ... or just be disgusted as i am ;^>
set winvec sentence win-3-1 sentence win-3-2 0 ;; [ w31 w32 0 ]
set losevec sentence lose-3-1 sentence lose-3-2 0 ;; [ l31 l32 0 ]
set standoffvec sentence standoff-3-1 sentence standoff-3-2 0
;; [ s31 s32 0 ]
place-turtle-randomly
]
end
;; -----------------------------------------------------------------------------
to place-turtle-randomly
;; this uses a quick 'n' dirty way to place turtles onto random positions on
;; the map, such that no other turtle already occupies the same space.
;; because it's really easy to shoot oneself in the foot that way, we bork
;; out after 10000 tries.
locals [ cnt x y ]
set cnt 10000 ;; maximum tries.
set x random screen-size-x
set y random screen-size-y
while [ any turtles-at x y or cnt = 0 ] [ ;; the selected patch is occupied
set x random screen-size-x
set y random screen-size-y
set cnt cnt - 1
]
;; we reach here when there's no turtle at (x,y) ...
setxy x y ;; ... so we move the current turtle there
end
;; -----------------------------------------------------------------------------
to go
no-display ;; or else: yawn!
iterate-once ;; just once, remember we are being called in a loop
;; step the timer
set ticks ticks + 1
if update-display? [
display ;; keep the user posted
]
end
;; -----------------------------------------------------------------------------
to iterate-once
ask patches [ ;; tell all patches to asynchronously execute:
;; okay, we basically have two cases to deal with:
;; - the particular patch we are inspecting is empty
;; --> see if a neighbour grows to fill the space
;; - the particular patch is occupied
;; --> see if a neighbour overgrows the current species
ifelse not any turtles-at 0 0
[ handle-unoccupied-patch ] ;; then
[ handle-occupied-patch ] ;; else
]
update-population ;; update the n-* displays
if update-plot? [
update-plot
]
end
;; -----------------------------------------------------------------------------
to update-population
set n-one count one
set n-two count two
set n-three count three
end
;; -----------------------------------------------------------------------------
to update-plot
set-current-plot "population"
set-current-plot-pen "one"
plot count one
set-current-plot-pen "two"
plot count two
set-current-plot-pen "three"
plot count three
end
;; -----------------------------------------------------------------------------
to handle-unoccupied-patch
locals [
px py ;; patch coordinates
]
;; since handle-occupied-patch does the same, i would rather move them to
;; a superfunction. however, NetLogo can't deal with that, as we need to be
;; in a patch context before declaring locals that are to be stored for each
;; patch individually. oh well, nobody said i have to write *nice* code.
;; store the patch cooordinates
set px pxcor
set py pycor
;; end stuff for the superfunction
;; we pick a random neighbouring patch and if it's occupied, we see if the
;; turtle there is lucky enough to grow.
ask random-one-of neighbors4 [ ;; pick a random neighbour
if any turtles-at 0 0 [ ;; alright, a candidate for growing...
ask turtles-at 0 0 [
;; roll the dice and see if it grows over
if random 1.0 < growth-rate [
hatch 1 [ setxy px py ] ;; clone and move it to the free patch
] ;; no luck with the dice
]
] ;; we don't do anything if there isn't a turtle there
]
end
;; -----------------------------------------------------------------------------
to handle-occupied-patch
locals [
px py ;; patch coordinates
sp ;; species of the local turtle
]
;; since handle-occupied-patch does the same, i would rather move them to
;; a superfunction. however, NetLogo can't deal with that, as we need to
;; be in a patch context before declaring locals that are to be stored for
;; each patch individually. oh well, nobody said i have to write *nice* code.
;; store the patch cooordinates
set px pxcor
set py pycor
ask turtles-at 0 0 [
set sp species ;; we need that for later
]
;; end stuff for the superfunction
ifelse catalyst? [
compete-catalyst px py sp
] [ ;; else
compete-standard px py sp
]
end
;; -----------------------------------------------------------------------------
to compete-standard [ px py sp ]
;; this is the standard case. we know that there's a turtle at (px,py) with
;; species (index) sp.
;;
;; we pick a random neighbour and see if the chances are good enough for it
;; to win. if that's not the case, then we don't do anything. if it is,
;; however, the case, then we check if the growth-rate allows us to spread,
;; in which case we kill the turtle at (px,py) and replace it with a clone
;; of the random neighbour we picked.
ask random-one-of neighbors4 [
if any turtles-at 0 0 [
ask turtles-at 0 0 [
;; we switched perspective to the random neighbouring turtle.
;; are we strong enough?
if random 1.0 < item sp winvec [
;; remember: we only spread if the growth-rate allows. if we don't
;; spread, nothing happens.
if random 1.0 < growth-rate [
kill-turtle (px - xcor) (py - ycor) ;; bye bye
;; to all who actually read along: if you think that px and xcor
;; (and similarly for y) are reversed, i agree! nevertheless, it
;; seems to be the way NetLogo works. so either turn them around
;; and see for yourself how it doesn't work, or just take it for
;; granted and stop asking.
hatch 1 [ setxy px py ] ;; clone it and move it over the carcass
] ;; if we don't grow, nothing happens.
] ;; and neither if we aren't strong enough
]
] ;; we don't do anything if there isn't a turtle there
]
end
;; -----------------------------------------------------------------------------
to compete-catalyst [ px py sp ]
locals [
n-neigh ;; the number of specific neighbours
p-north ;; the probability of overgrowth from the north
p-east ;; the probability of overgrowth from the east
p-south ;; the probability of overgrowth from the south
p-west ;; the probability of overgrowth from the west
dice ;; a random number
found ;; a winner was found
wdx wdy ;; the winner designate's relative coordinates
myweakness ;; my weakness (loss chance) against the other turtle
]
;; this is the catalyst case. we know that there's a turtle at (px,py),
;; which is weaker than we are. now we have to determine the growth-rate,
;; which is catalyzed by the presence of other species on surrounding
;; patches.
;;
;; for this, we are going to be using all three chance vectors. first, we
;; have to see if overgrowth happens at all. the following is an important
;; step to ensure that one species cannot overgrow another faster than it
;; overgrows empty space. it is the first of the five steps in the catalyst
;; model:
set n-neigh count neighbors4 with [ (count turtles-at 0 0) > 0 ]
if random 1.0 >= n-neigh / 4 [ stop ]
;; we skip step two for two reasons:
;; - we can elegantly integrate that into step 3
;; - NetLogo can't do both step 2 and 3 separately anyway.
;; step 3: we identify the winner from the list of potential winners. we
;; move the "complicated" math to a function.
set p-north get-overgrowth-probability px py sp 0 1
set p-east get-overgrowth-probability px py sp 1 0
set p-south get-overgrowth-probability px py sp 0 -1
set p-west get-overgrowth-probability px py sp -1 0
set dice random (p-north + p-east + p-south + p-west)
;; okay, get the winner designate. this is done with the 'broken stick'
;; model:
;;
;; <--p-north--><----p-east----><-p-south-><------p-west------> random
;; -dice-------------> |
;;
;; we get a random position on that 'stick' and use the winner obtained.
;;
;; oh how i wish there was a switch statement in NetLogo...
if dice < p-north
[ set wdx 0 set wdy 1 set found 1 ]
if found = 0 and dice < (p-north + p-east)
[ set wdx 1 set wdy 0 set found 1 ]
if found = 0 and dice < (p-north + p-east + p-south)
[ set wdx 0 set wdy -1 set found 1 ]
if found = 0 ;; else: west
[ set wdx -1 set wdy 0 ]
;; phew. so much work.
;;
;; we know that the winner designate is at coordinates wdx,wdy relative to the
;; current patch. now in step 4 we figure out, whether the turtle at that
;; patch is stronger than the local one.
ask one-of turtles-at wdx wdy [
;; but first: maybe this turtle's lazy and will stand back this time
;; around...
if random 1.0 < item sp standoffvec [ stop ]
;; nope, that turtle wants to smell blood...
;; store my loss chance against that species.
set myweakness item species value-from one-of turtles-at (0 - wdx) (0 - wdy)
[ losevec ]
;; roll a dice against the average of that loss chance and the other
;; turtle's winning chance. remember how the vector structure prevents
;; members of the same species from annihilating each other.
if random 2.0 < (myweakness + item sp winvec) [ ;; she's stronger
;; step 4 complete. we determined that the winner designate is the
;; actual winner. we'll give the poor weak turtle in the middle one more
;; chance: according to step 5, does it actually grow over, now that
;; we've determined that the other turtle is actually stronger?
if random 1.0 < growth-rate [ ;; yes
kill-turtle (px - xcor) (py - ycor) ;; bye bye
hatch 1 [ setxy px py ] ;; clone it and move it over the carcass
]
]
]
end
;; -----------------------------------------------------------------------------
to-report get-overgrowth-probability [ px py sp dtx dty ]
if any turtles-at dtx dty [
report 1.0
]
report 0.0
end
;; -----------------------------------------------------------------------------
to kill-turtle [ px py ]
;; i don't need to comment this, right?
ask turtles-at px py [ die ]
end
@#$#@#$#@
GRAPHICS-WINDOW
669
10
997
338
20
20
8.0
1
10
0
0
CC-WINDOW
669
348
997
650
Command Center
BUTTON
10
10
66
43
NIL
setup
NIL
1
T
OBSERVER
BUTTON
68
10
124
43
NIL
go
T
1
T
OBSERVER
MONITOR
126
10
182
59
NIL
ticks
0
1
SWITCH
194
10
300
43
catalyst?
catalyst?
1
1
-1000
SWITCH
302
10
445
43
update-plot?
update-plot?
0
1
-1000
SWITCH
447
10
612
43
update-display?
update-display?
1
1
-1000
SLIDER
10
60
182
93
p-empty
p-empty
0
100
50
1
1
NIL
SLIDER
10
98
182
131
p-one
p-one
0
100
50
1
1
NIL
MONITOR
10
133
60
182
NIL
n-one
0
1
SLIDER
10
199
182
232
p-two
p-two
0
100
50
1
1
NIL
MONITOR
10
234
60
283
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -