⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ---compete.nlogo

📁 NETLOGO
💻 NLOGO
📖 第 1 页 / 共 2 页
字号:
;; 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 + -