I am building a model for a predator prey system and I am incorporating a small basic machine learning internal model in the predator.
Predators have 4 strategies (strat is the variable), at the start of the day they select a strat and at the end of each day they check if they had a successful hunt with that strat.
I have another variable that predators own called best-strat which I want to be copied from the last successful strat
my code is the following
to recall-hunts
if ticks = 98 [ifelse hunt-today = 1 [set last-hunt "success"] [set last-hunt "failure"]]
end
to evaluate-hunt
if ticks = 99 [if last-hunt = "success" [set best-strat best-strat = strat]
if last-hunt != "success" [set strat one-of strategies]
stop]
end
to strategy
if ticks = 1 [ifelse best-strat = "NA" [set strat one-of strategies] [set strat strat = best-strat]]
stop
end
I want the predator to evaluate if they had a good hunt with a given strat and then select the strat which worked best for them previously, if no best strat then simply pick a random one.
strat is a variable which selects from the strategies list ("strat1" "strat2" "strat3" "strat4")
every thing is working except my code to copy the current strat into best-strat at the end of the day if a hunt was successful. At the moment it sets to "false" so something is breaking i guess.
The problem is here:
[set best-strat best-strat = strat]
The line should be
[set best-strat strat]
To explain the error you are getting, best-strat = strat is a logical expression that yields true or false. Thus set best-strat (best-strat = strat) (parentheses added) will set best-strat to true or false, depending on whether or not best-strat equals strat.
Related
I'm still trying to extract the coordinates of the path taken by every turtle in the world. For example, I would like to know the path taken by turtle 0 was patch 00 patch 0 5 patch 0 2 and patch 1 4 and save this information in a .csv file. In this way, I would like to extract the coordinates of the path taken by all the turtles in the world. I'm thinking about creating a list that gives me this information and then saving it.
The problem is that I cannot create an empty list for each turtle created and then, before every move, add the current patch location to the lists. And finally, generate the file of this information in .csv
That is, when inspecting the turtle I don't see the list and when creating the file in .csv it is not generated. Can anyone help me with the code?
Thanks in advance
turtles-own [ mypathx mypathy mytimer]
to setup
ca
reset-ticks
crt 5
ask turtles [
setxy random-xcor random-ycor
let i [ ]
pen-down
]
end
to go
move
let n count turtles
if n = 0 and output? = true [output] ;; ouput? is an switch on interface
if n = 0 [ stop ]
tick
end
to move
ask turtles [
rt random 360
fd 1
if ticks >= 10
[
die
]
]
end
To output
file-open "test.txt"
ask turtles [
set mypathx lput pxcor mypathx
set mypathy lput pycor mypathy
let maxer length mypathx
let i 0
repeat maxer
[
file-print (word item i mypathx " " item i mypathy " " item i mytimer)
let x ( i + 1 )
]
]
file-close
end
There are a number of things to note here, so I hope I understood what you inteded to do.
First of all, note that your code goes to output only after all the turtles died (that is infact one of the conditions to go to output: if n = 0). Therefore, it is normal that there is no data to be exported: in output you ask turtles, but when output is executed all turtles already left the simulation.
However, there is also something that Filip rightly noticed in the comment to the question: it seems logical to ask turtles to save the coordinates of their journey as they move - as opposed to asking them to do so at the end of the simulation.
Based on the current code, turtles simply move in the simulation, and only at the end (e.g. when output is called) they are are asked to save their current location. It would be ideal to include a piece of code where you ask turtles, after each move, to record their location in the list.
To combine this point and the previous one, I would do something like:
to setup
clear-all
reset-ticks
create-turtles 5 [
; I talk about this piece in point 3.
]
end
to go
move
tick
end
to move
ask turtles [
right random 360
forward 1
register-coordinates
]
end
to register-coordinates
set mypathx lput pxcor mypathx
set mypathy lput pycor mypathy
set mytimer lput ticks mytimer ; This is what I assumed you want mytimer to do.
end
And here comes the other problem. You are not initiating the turtles-own variables as lists.
If you run your piece of code now, nothing happens because all turtles are dead by the time you ask them to output. But if you just remove the die command, or if you ask turtles to output before they die, you would get an error - saying that lput expected a list but got something else instead.
From the NetLogo Dictionary you can see that the list primitive is used to create a list with two values.
If you want to create a list containing any other amount of values, you have to use (list ...). This includes the case in which you want to create an empty list. To do that, I would therefore do:
create-turtles 5 [
setxy random-xcor random-ycor
set mypathx (list)
set mypathy (list)
set mytimer (list)
pen-down
]
Now, mypathx, mypathy and mytimer are legal inputs to the lput procedure.
Finally, you can include the output at the end of your simulation (note how I changed go compared to the previous code example):
to go
if ticks = 11 [
ask turtles [output]
stop
]
move
tick
end
...
to output
file-open "test.csv"
file-print (word who "," mypathx "," mypathy "," mytimer)
file-close
end
So, overall, improtant adjustments are: initiate variables as lists if you want to treat them as such; ask your turtles to save their coordinates at every step in their turtles-own list variables; only at the end, ask them to write their list variables in the output file; do not kill your turtles before you ask them to output information.
Integrating all of the above, the code would look like:
turtles-own [mypathx mypathy mytimer]
to setup
clear-all
reset-ticks
create-turtles 5 [
setxy random-xcor random-ycor
set mypathx (list)
set mypathy (list)
set mytimer (list)
pen-down
]
end
to go
if ticks = 11 [
ask turtles [output]
stop
]
move
tick
end
to move
ask turtles [
right random 360
forward 1
register-coordinates
]
end
to register-coordinates
set mypathx lput pxcor mypathx
set mypathy lput pycor mypathy
set mytimer lput ticks mytimer
end
to output
file-open "test.csv"
file-print (word who "," mypathx "," mypathy "," mytimer)
file-close
end
Final notes on the code above:
I am not sure which exact format you want your output to be, but this example code works fine in saving the lists in the .csv file - so you can take it from there and play around to make it fit your needs.
I removed the pcolor part because it seemed unnecessary for the purpose of the question.
I am not sure what you wanted i to do in setup, but it seemed unnecessary for the purpose of the question so I removed that too from my exemplar code. Be careful at how you use item: I don't know what you wanted to do, but the way you included it in your question was often giving runtime errors.
I created a .csv as per the title of the question, instead of a .txt as per the code you provided.
I am trying to implement a timer for each turtle in Netlogo
so I can take the minimum value, maximum and average time taken for each turtle.
Can anyone help
You haven't said what you actually want timed (or given any code attempt). Any time you need a turtle to remember anything from one tick to the next, you need a variable. The simplest code for a timer is to have a variable that you set to the current value of ticks when the process starts and subtract that start time from the current value of ticks when the process stops. Here is a complete model example:
turtles-own
[ start-time
time-taken
]
to setup
clear-all
create-turtles 20
[ set start-time 2 + random 10
set time-taken -1
]
reset-ticks
end
to go
let movers turtles with [time-taken = -1 and start-time <= ticks]
ask movers
[ set heading random 360
forward 1 + random 3
if random-float 1 < 0.05 [ set time-taken ticks - start-time ]
]
tick
end
And check out the new Time extension if you want your timers to use real time units (seconds, minutes, years...) and have non-integer values.
https://github.com/NetLogo/Time-Extension
Look at primitives such as time:difference-between
For example, you could do this coding that flags the turtle you want to monitor and increments the flag variable when an event occurs. You can then monitor it in the BehaviorSpace and analyses the results output in a csv file. For example, the following codes:
globals [ID]
turtles-own [special-turtle]
to create-turtle
crt 1 [
setxy min-pxcor 0
set heading 90
set special-turtle false
set ID who]
end
to go
;omitted
special-turtles
tick
end
to special-turtles
ask turtles-on patch 0 0 [set ID who]
ask max-one-of turtles [who] [set special-turtle true]
ask turtles with [special-turtle = true][set special-turtle (special-turtle + 1)]
end
I think there is something that none of the previous answers considered: the way you implement your timer depends on how you want to use the measurement.
1 - If you want to read the measurement only after the measurement is completed
The expression "after the measurement is completed" can mean both that you want to read it at some point later during the model, or maybe even just from some model's output.
The approach I'd take in this case is similar to what JenB suggested, but I believe you can put it a bit simpler because here I only use one extra turtle variable (apart from my-variable, that is there only to represent something that you already have in your model):
turtles-own [
my-variable ; This represents something you have in your model, to be used as a condition for the timer
my-timer
]
to setup
clear-all
reset-ticks
create-turtles 10
end
to go
; Here you have your normal code. When you need, just include
; 'start-timer' and 'stop-timer'. For simplicity, let's
; say you want to count how long does each turtle take
; to get from a value of 1 to a value of 5 for my-variable.
; You can just do:
ask turtles [
if (random 10 < 2) [
set my-variable (my-variable + 1)
]
if (my-variable = 1) [
start-timer
]
if (my-variable = 5) [
stop-timer
type "I am turtle " type who type " and it took me " type my-timer print " ticks."
die
]
]
tick
if (not any? turtles) [stop]
end
to start-timer
set my-timer ticks
end
to stop-timer
set my-timer (ticks - my-timer)
end
Note that most of the code is there only to make a full reproducible example, but the actual implementation only consists of my-timer, to start-timer and to stop-timer.
You can take this approach because the hypothesis here is that you will be interested in reading the measurement only after to stop-timer happened.
Otherwise, see point 2.
2 - If you want to be able to read the measurement at any moment during the simulation
In this case, you need to make the timer progress as time progresses (as opposed to point 1, where you could just take the initial and final time, and make the difference between the two).
I guess the easiest way to do this is to conditionally increment the timer every time there is a tick.
Taking the same example as before, it would be something like:
turtles-own [
my-variable ; This represents something you have in your model, to be used as a condition for the timer
timer-active?
my-timer
]
to setup
clear-all
reset-ticks
create-turtles 10 [
set timer-active? FALSE
]
end
to go
ask turtles [
if (random 10 < 2) [
set my-variable (my-variable + 1)
]
if (my-variable = 1) [
set timer-active? TRUE
]
if (my-variable = 5) [
set timer-active? FALSE
]
]
tick
ask turtles with [timer-active?] [
set my-timer (my-timer + 1)
]
if (count turtles with [my-variable < 5] = 0) [stop]
end
This way, you will be able to see at any moment what is the current value of my-timer for each turtle.
I was able to include the recovery or die but now I'm having trouble getting the standard deviation and of the turtles that died. I think I got the standard deviation but can't get the mean
if random-float 1 < recover-or-die [
set epi-state recovered-code
set color green
ifelse random-float 1 < 0.90[
]
]
]
I tried this for the mean and it kept saying "Expected Command"
Your problem is ifelse recovery-prob < 0.1 = true. I don't know what your recovery-prob is set to, but this line is always true or always false. What you probably want to do (and what is in your comment) is:
ask turtles with [epi-state = infectious-code]
[ ifelse random-float 1 < recovery-prob
[ set epi-state recovered-code
set color green
]
[ die
]
]
Note that you don't need to actually have the = true part.
If you have recover-prob set to 0.05 (for example), the condition is true for all turtles and they all recover. If it's set to 0.2 (for example), it is false for all turtles and they all die.
This block still has a logic problem I think. The way you have it written, any infectious turtle will either recover or die immediately. What about the turtles who stay infectious for more than one tick?
I am creating a simulation which copies shoplifter behaviour. Turtles are split between "professional" and "novice" shoplifters and if "professionals" are apprehended by store security they might (1/2) want to select a new store to target "new-store-required".
"professional" shoplifters target the store with the lowest "security" value in a certain radius, all values are set as they are created.
I am trying to set a new "target-store", a "store" in-radius 10 with the second lowest "security", i.e. excluding the current "target-store" but I am having difficulty.
So far I have attempted to made several additions to the following code to exclude the current target store, this includes variations of "member? my patches" as the "store" where the shoplifter has been apprehended is added to this "patch-set" which will inform a later command. Also I have made a list of ascending "security" values to tell the "shoplifter" to target the "store" with "security" (the value which determines store vulnerability) the same as item 1 on the list, but I fear this might not work because their original target-store might not necessarily be item 0 as they target the store with the lowest "security" in a 10 unit radius.
These are the lines of code I am working with at the moment, any suggestions would be greatly appreciated.
***Edit: I could ideally like the code to make use of "mypatches" so each time a professional shoplifter is apprehended at a store that store can be added to mypatches and the subsequent target-store can exclude all stores which are members of mypatches.
to new-target-store
ask turtles [ if
new-store-required = 1 and professional = 1 and (random-float 1 < 0.5) [
set target-store min-one-of store in-radius 10 [security]
]
]
end
Edit 2: I've fixed what was wrong.
You may want to include your setup code, or a stripped-down version of it if it's really long, to make sure that answers conform to the structure you've used. I would approach this by having a turtles-own variable to store their current target, which they can try to fill if it is empty (rather than using an extra boolean for that purpose). Also, you may want to convert your 1/0 options to true/false for cleaner code. Check out this example setup:
globals [ stores ]
patches-own [ security ]
turtles-own [
current-target
professional?
mypatches
]
to setup
ca
ask n-of 20 patches [
set pcolor green
set security 1 + random 10
]
set stores patches with [ pcolor = green ]
crt 5 [
setxy random-xcor random-ycor
pd
set professional? one-of [ true false ]
set current-target nobody
set mypatches ( patch-set )
]
reset-ticks
end
This sets up a world with some green patches that are grouped into the patch-set called stores. Also, you have some turtles that have the boolean professional? set to either true or false. They initialize with no current-target store, and an empty mypatches patch-set variable.
Now, you can have turtles check if their current-target exists. If it does not, they can assign a store to that variable from the set of stores (possible-targets, here) that are not equal to the patch-here of the asking turtle. Professional thieves can further refine possible-targets to exclude any stores at which they have been apprehended, by excluding any stores that are a member of their mypatches patch-set variable. More details in comments:
to go
ask turtles [
; if you have no target currently
if current-target = nobody [
; Create a temporary patch set made up of all stores except for
; the one that I'm currently in
let possible-targets stores with [ self != [patch-here] of myself ]
ifelse professional? [
; Have professional thieves revise their possible targets to exclude
; any in the patchset mypatches, then choose a possible target
set possible-targets possible-targets with [ not member? self [mypatches] of myself ]
set current-target min-one-of possible-targets in-radius 10 [ security ]
] [
; Have amateur thieves choose randomly from the possible targets
set current-target one-of possible-targets
]
]
; move closer to your current target, or
; move to it exactly if you're near enough
ifelse current-target != nobody [
face current-target
ifelse distance current-target > 1 [
fd 1
] [
move-to current-target
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; *** do your shoplifting attempt/check here ***
; For this example, just have professional thieves sometimes
; add this patch to their mypatches patchset
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if professional? and random-float 1 < 0.5 [
set mypatches ( patch-set mypatches patch-here )
]
; Reset current-target to nobody
set current-target nobody
]
] [
; if no suitable nearby targets, wander randomly
rt random 61 - 30
fd 1
]
]
tick
end
If you run that long enough, eventually your professional thieves will stop being able to find target stores as they have added all stores to their mypatches variable.
I'm modeling home range selection in NetLogo. I'd like a turtle to identify the subset of patches that are neighbors to its current home range. The turtle should then identify which neighboring patch is best (defined for now as the patch with highest food benefit) and move to that patch to claim it. It continues these steps (identify available patches neighboring the home range, select best option, add to homerange, repeat) until it has enough food within the home range.
Part of the code is as follows, but I get the error that "FACE expected input to be an agent but got NOBODY instead." I think something is off with the reporter or my use of it (I'm new to reporters; I'm trying to make the code modular to minimize procedure length).
Any idea where I'm going wrong? Thanks!
patches-own [
owner
benefit
used?
]
to-report edge-patches-of [my-homerange] ;; reporter to find patches along edge of homerange
report my-homerange with [
any? neighbors with [
owner = [owner] of myself
]
with [used? = false] ;; (only want neighboring patches not already owned)
]
end
to pick-homerange
ifelse food < food-needed ;; (turtle builds homerange until it has enough food)
[ let my-homerange patches with [owner = myself]
ask edge-patches-of my-homerange [set pcolor red ] ;; (this to just see the options)
;; now that we know the options, pick the best:
let available-destinations edge-patches-of my-homerange
set destination max-one-of available-destinations [([benefit] of patches)]
face destination
forward 1
if patch-here = destination
[ add-destination ]
]
[stop]
end
You have not included enough code or description to be sure, but it seems that your logic is overcomplicated and contains conceptual errors. Try this as a starting point. Note in particular the test for a nonempty set of candidate edge patches.
globals [food-needed]
patches-own [owner capacity]
turtles-own [homerange]
to setup ;make sure all turtles have an initial homerange
ca
ask patches [set owner nobody]
crt 10 [
set-initial-ownership
;do the following just once, not over and over
set homerange (patches with [owner = myself])
]
;etc
end
to-report benefit [_t] ;patch proc
;patch reports benefit to turtle _t
report 1 ;or whatever
end
to-report food ;turtle proc
report sum [capacity] of homerange
end
to pick-homerange ;turtle proc
;; (turtle builds homerange until it has enough food)
if (food >= food-needed) [stop]
let _candidates edge-patches
if any? _candidates [ ;you almost certainly need to add this
let _destination max-one-of _candidates [benefit myself]
face _destination forward 1
if (patch-here = _destination) [augment-homerange _destination]
]
end
to augment-homerange [_p] ;turtle proc
ask _p [set owner myself]
;just add to the homerange as needed; don't keep recreating it
set homerange (patch-set homerange _p)
end
to-report edge-patches ;turtle proc
;; (only want neighboring patches not already owned)
report (patch-set [neighbors] of homerange) with [owner = nobody]
]
end