I want to set my code so that each forager (a breed of turtle) will have a 10% chance of dying for each tick it is vulnerable. I am building off of a code called Ants in the Netlogo models library.
When I use use [if random 100 > 98 [ die ]] (or anything below 98) nearly all of my turtles will die at the beginning and survive more after a hundred or so ticks have passed. However if I use [if random 100 > 98 [ die ]] no turtles will die. It's very weird.
to go ;; forever button
ask foragers
[ if who >= ticks [ stop ]
ifelse color = red
[ look-for-food ]
[ return-to-nest ]
check-death
wiggle
fd 1 ]
to check-death
ask foragers [
if vulnerable?
[if random 100 > 99
[ die ]]]
end
I expected [if random 100 > 98 [ die ]] to make it so that a vulnerable turtle would only have a 2% chance of dying per tick rather than an immediate wipeout.
The issue here is due to nested ask statements. You have an ask foragers [ ... statement that contains check-death, which contains another ask foragers statement. So, every single forager will be asking all foragers (including itself) to check-death. So, if you have 10 foragers, each forager will be running check-death 10 times per tick.
You should just be able to remove the ask foragers block from within your check-death procedure to solve your issue- have a look at this toy model example:
turtles-own [ vulnerable? ]
to setup
ca
crt 100 [ set vulnerable? one-of [ true false ] ]
reset-ticks
end
to go
ask turtles [
rt random 61 - 30
fd 1
check-death
]
if not any? turtles with [ vulnerable? ] [
print count turtles
stop
]
tick
end
to check-death
if vulnerable? and random-float 1 > 0.90 [
die
]
end
That will randomly assign vulnerable? to the turtles, then have vulnerable turtles die if a randomly generated float value is greater than 0.90 (for the 10% chance mentioned in your question). Once there are no more turtles left, the model will stop.
Related
I have turtles (patients), and they can only use only one bed each (white patch). Since patients are randomly generated in a waiting room (green patches), sometimes two or more of them get at the same distance and therefore they find the same patch as its target. I tried to add an attribute to the patch with the purpose of assigning that particular bed to a specific patient. The idea is something like this (please indulge on the ugly code, I'm learning :P):
globals [
waitxmax
waitxmin
waitymax
waitymin
box
]
breed [ patients patient ]
patients-own [ target ]
patches-own [ assigned ]
to setup-wait-room
set waitxmax -15
set waitxmin 15
set waitymax 11
set waitymin 15
ask patches with [
pxcor >= waitxmax and
pxcor <= waitxmin and
pycor >= waitymax and
pycor <= waitymin
] [ set pcolor green ]
end
to setup-beds
let cmy 7
let cmx 15
let dst 3
let nbox 7
ask patch cmx cmy [ set pcolor white ]
let i 1
while [ i < nbox ] [
ask patch (cmx - dst) cmy [ set pcolor white ]
set i i + 1
set cmx cmx - dst
]
ask patches with [ pcolor = white ] [ set assigned false ]
set box patches with [ pcolor = white ]
end
to setup-patients
create-patients start-patients [
set shape "person"
set target nobody
move-to one-of patches with [ pcolor = green ] ]
end
to setup [
clear-all
setup-wait-room
setup-beds
reset-ticks
]
to go
ask patients [ go-to-bed ]
tick
end
to go-to-bed
let _p box with [ self != [ patch-here ] of myself ]
if target = nobody [
set target min-one-of _p [ distance myself ]
ask target [ set assigned myself ]
]
;;; FIXME
if ([ assigned ] of target) != self [ show "not true" ]
if target != nobody [
face target
fd 1
]
end
When I print the two sides of the comparison below FIXME, from the command center I actually get the expected result. For example: both patient 0 and patient 1 have the same target (patch -3 7), but that patch is assigned to (patient 0). I would have expected that comparison to force patient 1 to get a new target since the bed doesn't have his name (I haven't written that code yet), but it always evaluates to true. This is more notorious as more patients I add over available beds (if no beds available, they should wait as soon as one gets free).
When inspecting trough the interface I also see that the patch -3 7 says (patient 0), so I don't know what's happening. Command center example:
observer> show [ assigned ] of patch -3 7
observer: (patient 0)
observer> if ([ assigned ] of patch -3 7) = [self] of patient 0 [ show "true" ]
observer: "true"
observer> if ([ assigned ] of patch -3 7) = [self] of patient 1 [ show "true" ]
;;;; SETUP AND GO
(patient 0): (patch -3 7)
(patient 0): (patient 0)
(patient 0): "true"
(patient 2): (patch 12 7)
(patient 2): (patient 2)
(patient 2): "true"
(patient 1): (patch -3 7)
(patient 1): (patient 1)
(patient 1): "true"
Maybe I'm just overthinking this and there are is a simpler way to assign a bed to a patient and vice versa?
There seems to be a chunk or two missing from your code above (I can't copy-paste and run it), so please have a look at the option below.
This version works by having a single place to store the 'claimed' beds- in the turtle variable. Since the turtle variables can be queried as a list using of, a bed-less turtle can check if there are any beds that are not already present in that list and, if so, claim one.
turtles-own [ owned-bed ]
to setup
ca
ask n-of 5 patches [
set pcolor green
]
crt 10 [
set owned-bed nobody
claim-unclaimed-bed
if owned-bed != nobody [
print word "I own the bed " owned-bed
]
]
reset-ticks
end
to claim-unclaimed-bed
; If I have no bed
if owned-bed = nobody [
; Pull the current owned beds for comparison
let all-owned-beds [owned-bed] of turtles
; Pull those beds that are green AND are not found in 'all-owned-beds'
let available-beds patches with [
pcolor = green and not member? self all-owned-beds
]
; If there are any beds available, claim one
ifelse any? available-beds [
set owned-bed one-of available-beds
] [
; If there are none available, print so
print "There are no available beds."
]
]
end
Edit: Forgot the actual question title- to actually move to their owned-bed (if they have one) in the example above, they simply face it and move how you like- for example:
to go
ask turtles with [ owned-bed != nobody ] [
ifelse distance owned-bed > 1 [
face owned-bed
fd 1
] [
move-to owned-bed
]
]
tick
end
Edit: added complexity
Ok, for an added element of severity, you will likely want to avoid using multiple with [ ... = x statements, and instead to use a primitive called min-one-of which returns the agent with the minimum value of some reporter. Then, you want to tell NetLogo to keep asking the next most severe and the next most severe, etc. One way to do this is with a while loop, which basically says "While this condition is met, continue evaluating the following code." Be careful with while loops- if you forget to write your code such that eventually the condition is no longer true, the while loop will just continue running until you will eventually Tools > Halt your model (or, as has happened to me with a large model, NetLogo crashes).
I've reworked the code (much of what was above is unchanged) to include such a while loop. Note as well that, since the model needs to check which beds are available multiple times, I've made that code into a to-report chunk to condense / simplify.
turtles-own [ owned-bed severity ]
to setup
ca
ask n-of 5 patches [
set pcolor green
]
crt 10 [
set owned-bed nobody
set severity random-float 10
]
let current-available-beds report-available-beds
while [any? current-available-beds] [
; From the turtles with no bed, ask the one with the lowest severity number to
; claim an unclaimed bed. Then, reset the current-available-beds
ask min-one-of ( turtles with [owned-bed = nobody] ) [ severity ] [
claim-unclaimed-bed
if owned-bed != nobody [
show ( word "I have a severity of " severity " so I am claiming the bed " owned-bed )
]
]
set current-available-beds report-available-beds
]
reset-ticks
end
to-report report-available-beds
let all-owned-beds [owned-bed] of turtles
report patches with [
pcolor = green and not member? self all-owned-beds
]
end
to claim-unclaimed-bed
; If I have no bed
if owned-bed = nobody [
let available-beds report-available-beds
; If there are any beds available, claim one
ifelse any? available-beds [
set owned-bed one-of available-beds
] [
; If there are none available, print so
print "There are no available beds."
]
]
end
I've got the following code, but when trying to run it I get a message saying "expected a literal value", and it highlights calidad...
I'm guessing it is because there is a problem with how i am writting the brackets?
to check-if-dead
if habitat = "escarabajo" [
ask escarabajos [
if count escarabajos-here > capacidad-de-carga-bosques [die] ; beetles that reach patches that already have a # above the carrying capacity die
if patch-here = [calidad "baja"] [
if random 100 > probabilidad-de-supervivencia-calidad-baja [die]
]
if patch-here = [calidad "alta" ] [
if random 100 > probabilidad-de-supervivencia-calidad-alta [die]
]
]
]
There is patches of high quality and patches with low quality in my universe, and I want the turtles to die with a certain probability (determined by a slider), depending on which patch they land...
You probably want if [calidad] of patch-here = "baja":
to check-if-dead
if habitat = "escarabajo" [
ask escarabajos [
if count escarabajos-here > capacidad-de-carga-bosques [die] ; beetles that reach patches that already have a # above the carrying capacity die
if [calidad] of patch-here = "baja" [
if random 100 > probabilidad-de-supervivencia-calidad-baja [die]
]
if [calidad] of patch-here = "alta" [
if random 100 > probabilidad-de-supervivencia-calidad-alta [die]
]
]
]
end
But note that turtles always live on a patch, so you are allowed to just reference the patches-own variable directly as a short-cut for this situation (same way you can use pcolor in a turtle context, too):
to check-if-dead
if habitat = "escarabajo" [
ask escarabajos [
if count escarabajos-here > capacidad-de-carga-bosques [die] ; beetles that reach patches that already have a # above the carrying capacity die
if calidad = "baja" [
if random 100 > probabilidad-de-supervivencia-calidad-baja [die]
]
if calidad = "alta" [
if random 100 > probabilidad-de-supervivencia-calidad-alta [die]
]
]
]
end
Im very new to Netlogo and trying to learn the basic. Therefore, I'm trying to extend an example code Netlogo provided. Im trying to make the pollution rate dependent upon the number of people from the Urban Site Pollution example.
Is there also a way to introduce reinforced learning (Q-learning) to improve the simulation?
Sincerly,
Victor
Do I need to create a new function that updates pollution when population increased?
Below is the example code:
breed [ people person ]
breed [ trees tree ]
turtles-own [ health ]
patches-own [
pollution
is-power-plant?
]
to setup
clear-all
set-default-shape people "person"
set-default-shape trees "tree"
ask patches [
set pollution 0
set is-power-plant? false
]
create-power-plants
ask patches [ pollute ]
create-people initial-population [
set color black
setxy random-pxcor random-pycor
set health 5
]
reset-ticks
end
to go
if not any? people [ stop ]
ask people [
wander
reproduce
maybe-plant
eat-pollution
maybe-die
]
diffuse pollution 0.8
ask patches [ pollute ]
ask trees [
cleanup
maybe-die
]
tick
end
to create-power-plants
ask n-of power-plants patches [
set is-power-plant? true
]
end
to pollute ;; patch procedure
if is-power-plant? [
set pcolor red
set pollution polluting-rate
]
set pcolor scale-color red (pollution - .1) 5 0
end
to cleanup ;; tree procedure
set pcolor green + 3
set pollution max (list 0 (pollution - 1))
ask neighbors [
set pollution max (list 0 (pollution - .5))
]
set health health - 0.1
end
to wander ;; person procedure
rt random-float 50
lt random-float 50
fd 1
set health health - 0.1
end
to reproduce ;; person procedure
if health > 4 and random-float 1 < birth-rate [
hatch-people 1 [
set health 5
]
]
end
to maybe-plant ;; person procedure
if random-float 1 < planting-rate [
hatch-trees 1 [
set health 5
set color green
]
]
end
to eat-pollution ;; person procedure
if pollution > 0.5 [
set health (health - (pollution / 10))
]
end
to maybe-die ;; die if you run out of health
if health <= 0 [ die ]
end
; Copyright 2007 Uri Wilensky.
; See Info tab for full copyright and license.
I'm trying to program turtles finding jobs. They are separated in age groups.
The patches are the jobs, with two variables called "salary-here" and "hours-worked" generated randomly.
I'm trying to make my turtles (people) to stop moving (looking) when they find the patch (job) with the highest salary-here/hours-worked, but they always keep moving.
patches-own
[salary-here ; amount of salary paid in one specific job (patch)
hours-worked ; time working and leisure
reward-ratio ; ratio between salary and hours ]
turtles-own [age]
to search-job ; they can only find jobs according to age "zones"
if age = 1 [ move-to one-of patches with [ pxcor > 10 and pxcor < 40 ] ]
if age = 2 [ move-to one-of patches with [ pxcor > 40 and pxcor < 70 ] ]
if age = 3 [ move-to one-of patches with [ pxcor > 70 and pxcor < 100 ] ]
end
to go
ask turtles [ search-job ]
ask turtles [ keep-job ]
tick
end'
The idea is to: keep-job (stay in patch) if condition (reward-ratio is maximum in the surrounding area), if not, search job.
Thanks in advance for any help.
The idea is to not move a turtle if they should stay.
In your go,
ask turtles with [should-stay = false] [search-job]
I would then write a function called should-stay and insert your stay logic there.
to-report should-stay
report [reward-ratio] of patch-here >= max [reward-ration] of neighbors4
end
There are alternative ways which include storing a turtle variable that could help improve speed if performance is an issue.
I would like to know the numbers of all turtles died in my pseudo model. How can I do that? I would appreciate very much a simply and fast running solution for that problem, like count dead turtles.
I was thinking of a routine like this (but do not know how to implement it):
if turtle is dead % checking all turtles if dead or alive
set death_count death_count + 1 % set counter
tick % go one step ahead in model
This is my code sample (without any check so far):
breed [ humans human ]
humans-own [ age ]
to setup
ca
create-humans(random 100)
[
setxy random-xcor random-ycor
set age (random 51)
]
reset-ticks
end
to death
ask humans [
if floor (ticks mod 1) = 0 [
set age age + 1 ]
if age > 85 [ die ]
]
end
to go
death
tick
if ticks > 20 [ stop ]
end
I'm afraid you have to keep track of it yourself in a global variable. So, add
globals [ number-dead ]
to the top of your model. Then, change death like so:
to death
ask humans [
if floor (ticks mod 1) = 0 [
set age age + 1 ]
if age > 85 [
set number-dead number-dead + 1
die
]
]
end
Then number-dead will always be equal to the number of turtles that have died.
This is really simple:
to setup
let total-population count turtles
end
to go
let current-population count turtles
let dead-people total-population - current-population
ticks
end