So I'm aware of the lack of Null values in Netlogo. I'm not sure how to handle that in my code.
I'm building a search model where turtles go from one patch to another according to different criteria. The way I want to do that is by having a turtle variable target that is the next patch they'll go to , which is taken from a turtle variable itinerary that is an order list of patches returned by the reporter below.
turtles-own
[
target
itinerary
]
to-report most
; sets turtle target toward patch with max space
; let place-list list patches with [space > 0]
let list-a sort-on [space] (patches with [space > 0] )
report list-a
end
Coming from R and python my psuedocode simply checks if target is Null, and if it is, checks if itinerary is Null and if it is calls the reporter procedure to build the ordered list.
Should I just use:
ifelse empty? target
[
;go to target
]
[
ifelse empty? itinerary
[
set itinerary most
[
[
set target item 0 itinerary
set itinerary remove-item 0 itinerary
]
]
or is there a best practice for this type of thing that I haven't found?
Thanks
Related
My model involves one turtle surveying the area and it should keep track of the ID/ 'who' of the turtles it bumps into. Importantly, the surveyor could potentially record the same ID/ 'who' twice but I'm not sure how to implement that memory side of things.
breed[boats boat]
boats-own [
my-neighbors
num-neighbors
count-neighbors]
to setup
clear-all
crt 100 [
move-to one-of patches with [ not any? turtles-here ]
]
crt 1 [set breed boats
set count-neighbors 0
]
reset-ticks
end
to go
ask turtles [
fd 1
]
ask boats [
survey
]
tick
end
to survey
set my-neighbors (other turtles) in-radius 3
set num-neighbors count my-neighbors
set count-neighbors [who] of my-neighbors
end
UPDATE
In light of the answer below I came up with the following which also records when the interaction took place by creating a new time variable.
breed[boats boat]
boats-own [
my-neighbors
num-neighbors
id-neighbors
survey-time]
turtles-own [
time
]
to setup
clear-all
crt 10 [
move-to one-of patches with [ not any? turtles-here ]
]
crt 1 [
set breed boats
set shape "circle"
set id-neighbors []
set survey-time []
]
reset-ticks
end
to go
ask turtles [
fd 1
set time ticks
]
ask boats [
survey
]
tick
end
to survey
set my-neighbors (other turtles-here )
set num-neighbors count my-neighbors
set id-neighbors (sentence id-neighbors [who] of my-neighbors )
set survey-time (sentence survey-time [time] of my-neighbors )
end
Currently, you are always setting count-neighbors to the list of all its current neighbors, but this list is cleared and made anew with each tick. Instead of that, you can use primitives like sentence to combine the old list of count-neighbors with the new list you are generating this iteration and set the new list of count-neighbors to be this combined list.
set count-neighbors (sentence count-neighbors [who] of my-neighbors )
I also initialised your count-neighbors as an empty list rather than as 0, since 0 is already a turtle who so that would give you false information
crt 1 [set breed boats
set count-neighbors []
]
To check if the memory is working as intended, you can use inspect one-of boats in the command center and see how each new entry gets added to the end of the list.
Edit for followup question
Your solution here definitely works. Allow me a few suggestions for it as well:
There is not need to create the time variable, each turtle can already access the ticks global variable
set id-neighbors (sentence id-neighbors [who] of my-neighbors )
set survey-time (sentence survey-time [ticks] of my-neighbors )
As an alternative, this one creates a list of lists, with each item containing the turtle that was encountered and the time when it was encountered. Slightly harder to work with but clear at a glance which values belong together.
set id-neighbors (sentence id-neighbors [list who ticks] of my-neighbors )
I have several turtles each with three variables opinion1, opinion2 and opinion3. I need them to:
identify which of these three variables has the highest value
find another turtle in their network with a value at least as high
as the one found in 1.
update its own value found in 1. with
respect to that of the turtle found in 2.
What I have done doesn't really work because it only updates looking at o1 without really having a look at which of the tree (opinion1, opinion2 or opinion3) is the highest and THEN looking for a neighbour.
to update-opinion
ask turtles [
let my-nearby-turtles nw:turtles-in-radius 1
let my-opinion1 opinion1
set neighbour one-of my-nearby-turtles with [ opinion1 > my-opinion1 ]
if neighbour != nobody [
let opinion_n [opinion1] of neighbour
set opinion1 ((opinion1 + opinion_n) / (2))
]
]
end
I don't know a simple way to do this with unique variables like opinion1 etc, but maybe having a list of opinions instead of individual variables for each opinion will work. For example, with this setup:
extensions [ nw ]
turtles-own [
opinions
]
to setup
ca
resize-world -5 5 -5 5
set-patch-size 30
crt 30 [
set shape "dot"
set opinions n-values 3 [ precision random-float 10 2]
set color scale-color blue sum opinions -5 35
while [ any? other turtles-here ] [
move-to one-of neighbors4
]
]
ask turtles [
create-links-with turtles-on neighbors4
]
reset-ticks
end
You get something like this:
Where each turtle has an opinions list variable that is three items long. Now, you can have each turtle determine its highest opinion value using max, get that maximum values index position in the list using position, and then query that turtle's neighbors to see if any of them have a higher value in the same index position. If they do, modify your asking turtles opinions list using replace-item to be the average of the two values:
to go
ask turtles [
; Get adjacent turtles
let my-nearby-turtles nw:turtles-in-radius 1
; Identify the highest highest value variable of
; the current turtle, and get its list position
let my-opinion max opinions
let my-op-ind position my-opinion opinions
; Pick one of the turtles whose value in the same indexed
; position is higher than my-opinion
let influence one-of my-nearby-turtles with [
item my-op-ind opinions > my-opinion
]
; If that turtle exists, update my own opinions list as appropriate
if influence != nobody [
let new-opinion precision (
( [ item my-op-ind opinions ] of influence + my-opinion ) / 2
) 2
set opinions replace-item my-op-ind opinions new-opinion
]
set color scale-color blue sum opinions -5 35
]
tick
end
Hopefully that is sort of on the right track, not sure if a list will work for what you need. If you must have the variables as standalone values at each tick, I suppose you could convert them to a list then follow the procedure above. If you only need them for output, you could just update your unique variables as needed based on the values in the list (as long as you are consistent with the order).
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 have a model that keeps turtles in several patches each. I would like to select a turtle with the lowest ID for each stagnant turtle in each specified patch in the world.
For example, the answer is as follows. At patch coordinates (1, 0), five turtles stayed. And the ID of the turtle with the smallest ID was ID = 5 within the patch coordinates (1, 0).
The following is a sample program. But this program is not intended. Is there something good syntax instead of the syntax "min-one-of turtles [who]"? I want your advice. Thank you.
ask (turtles-on patch 1 0) [
ask min-one-of turtles [who] [
set flag-1 TRUE
]
I'm not sure what you mean by 'program is not intended'. Your problem is that you ask each of the turtles on patch 1 0 to identify the minimum who over all turtles. What you want is:
let targets (turtles-on patch 1 0)
[ ask min-one-of targets [who]
[ set flag-1 TRUE
]
]
If the only thing you are going to do with the turtles on that patch is to select the lowest who, you don't need to set up the agentset explicitly. Instead:
ask min-one-of (turtles-on patch 1 0) [who]
[ set flag-1 TRUE
]
I would like to put a flag called "min-id" for the turtle with the smallest ID. And I want to flag other turtles as "not-min-id". However the following sample syntax has errors. The error message is as follows.
" error while turtle 0 running >
called by procedure GO
called by button 'go' "
I probably to need your advice. Thank you.
globals [ min-id not-min-id count-up ID ]
to go
reset-ticks
ask patch 0 0
[
sprout 1 ;;This model needs to use sprout.
]
ask (turtles-on patch 0 0)
[
set ID who
setxy min-pxcor 0
set heading 90
]
if (count turtles > 0)
[
ask min-one-of turtles [who]
[
set min-id TRUE
]
]
if (count turtles > 0)
[
ask (turtles-on patch 0 0)
[
if ID > min-one-of turtles [who] ;;This syntax has errors.
[
set not-min-id TRUE
]
]
]
ask (turtles-on patch 0 0) with [not-min-id]
[
set count-up count-up + 1
]
if (count turtles > 0) [
ask (turtles-on patch 0 0) with [min-id]
[
die
]
tick
end
You have some confusion in your code. From your description, I believe you want each turtle to have a flag for whether or not it has the minimum who number. This means you need a flag for each turtle. However, you have set up min-id as a global variable instead of a turtle variable. Furthermore, you only need the flag variable once (that is, you need min-id but not not-min-id) and you set it to TRUE or FALSE.
Replace
globals [ min-id not-min-id count-up ID ]
with
globals [ count-up ID ]
turtles-own [ min-id ]
and see if that fixes it. Also initialise min-id to FALSE as part of the sprout.
Having said all that, I strongly agree with Alan, if you ever use the who variable for anything except print statements in debug, you probably need to rethink your code. In your case, what is special about the turtle with the lowest who number that makes you want to keep track of it? Do you simply want a random turtle that happens to be at a particular location? Then select a random turtle at that location to do the TRUE/FALSE without going through who.