I am trying to create a list to be collected with the behaviorspace that reports the color of a turtle's neighbor.
to-report north-color1
set north-color []
foreach sort turtles [the-turtle -> set north-color lput [color] of neighbors4 north-color]
report north-color
end
the "foreach" line is to ensure that the order of the list follows turtle 0, turtle 1, turtle 2, etc in sequential order. However, I want my list to output the color of their neighbor above like [10, 20, 10, 20, 30...] How can I achieve this?
This is a complete model. Just change the print north-color-map to print north-color to try out the foreach version.
to testme
clear-all
ask patches [if random-float 1 < 0.8 [sprout 1]]
print north-color-map
end
to-report north-color
let outlist []
foreach sort-on [who] turtles
[ this-turtle -> ifelse any? turtles-on [patch-at 0 1] of this-turtle
[ set outlist lput [color] of one-of turtles-on [patch-at 0 1] of this-turtle outlist ]
[ set outlist lput "none" outlist ]
]
report outlist
end
to-report north-color-map
report map
[ this-turtle -> ifelse-value any? turtles-on [patch-at 0 1] of this-turtle
[ [color] of one-of turtles-on [patch-at 0 1] of this-turtle ]
[ "none" ]
]
sort-on [who] turtles
end
The foreach version is probably easier to understand. It follows fairly closely what you were trying to do - start with an empty list and then run through a list of all the turtles in who order (the sort-on [who] turtles creates that list) and calculates the colour of the turtle on the north patch. Finding north is done with patch-at 0 1 but you also have to say north of what - hence [patch-at 0 1] of this-turtle. And the one-of is to select one turtle from the set of all turtles on that patch - NetLogo can't tell that it will always have one or none so you would get an error essentially saying 'I don't know which turtle to find the colour of'.
The second version uses map. It does exactly the same but applies the function to all the members of a list without explicitly constructing the loop. The code is a little simpler because you don't need the empty list and the various lput statements. You also need to present everything as a reporter rather than a command. But map can be a little trickier to get your head around.
Related
I have a list of cells destination_cells, and am trying to loop through each cell and count the number of turtles and the average weight of the turtles in each. For each cell, I want to write the cell's ID (which I am assuming is just destination_cells as coordinates) and the two variables to a list cell_list. I think my confusion stems from not understanding how to use anonymous reporters in foreach. If I replace 'next cell' with destination_cells in the foreach block, I get, for example, the same total_turtle_in_destination_cells value for every single cell in destination_cells. The same occurs with using next_cells in the block. Where am I making a mistake?
set destination_cells [self] of patches with [ any? turtles-here]
foreach destination_cells [next_cell -> ask next_cell
[
; Counts number of turtles in each cell
set total_turtle_in_destination count turtles-on destination_cells
; Finds average weight of turtles in each cell
set avg_weight_turtle_in_destination mean [mass] of turtles-on destination_cells
]
set cell_list lput (csv:to-row (list
destination_cells
total_turtle_in_destination
avg_weight_turtle_in_destination
)) cell_events_list
]
Here is an alternative that:
Makes a reporter to get the info desired (the patch info as patch x and y, the total turtles on a patch, the mean weight of present turtles) from whatever patch that calls the reporter
Updates the info list directly by querying the destination_cells
turtles-own [ weight ]
globals [ destination_cells cell_info_list]
to setup
ca
resize-world 0 5 0 5
set-patch-size 30
reset-ticks
crt 20 [
set weight random 10 + 1
move-to one-of patches
]
end
to-report report-self-info
let n_turtles_here count turtles-here
let mean_weight mean [weight] of turtles-here
report (list self n_turtles_here mean_weight)
end
to create-info-list
set destination_cells patches with [ any? turtles-here]
set cell_info_list [report-self-info] of destination_cells
print cell_info_list
end
In response to your question "how can the patch call the reporter? I tried ask destination_cell [report-self-info], but a command is expected":
When you make a to-report procedure with the structure like the above that uses self, it's somewhat like a turtles-own or patches-own variable. In this case, you can call it just as you would have a turtle variable like color or xcor or a patch variable like pcolor or pxcor- if you run something like:
ask one-of patches [ print report-self-info ]
You should get something like
[(patch 5 2) 2 7.5]
This is why the set cell_info_list [report-self-info] of destination_cells above works- because you could do something like set cell_info_list [pcolor] of destination_cells in a similar way.
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 want my forager turtles to follow a path laid down by leader turtles, and this path consists of a turtle breed called trail-markers. The forager turtles also lay down trail-markers (to reinforce the trail), so I would like them to check for leader trail-markers on some patch/patches. I know Netlogo includes breeds-on to check for the presence of members of a breed, but I need the foragers to check for blue leader trail-markers. Is there a way to do this?
Here is what I had in mind:
if count (trail-markers with [color = blue]) on patch-ahead 1 > 0 [fd 1]
But I got, error:nothing named on has been defined, which makes sense, since the Netlogo primitive is breeds-on, so I modified it to:
if any? (trail-markers with [color = blue])-on patch-ahead 1 [fd 1]
However, I simply received: error:nothing named -on has been defined instead.
See the code below. I think you just want to use trail-markers-on, but you can simplify by using any? a bit. And you might want to have the custom reporter so you can just check for blue-markers-on if you find that simpler.
breed [ trail-markers trail-marker ]
to example
; I think this is what you want
if count ((trail-markers-on patch-ahead 1) with [color = blue]) > 0 [ forward 1 ]
; this is slightly simpler, using `any?` instead of `count ... > 0`
if any? (trail-markers-on patch-ahead 1) with [color = blue] [ forward 1 ]
; you could also write a custom reporter if you'll need to get this info a lot
if any? blue-markers-on patch-ahead 1 [ forward 1 ]
end
to-report blue-markers-on [p]
report (trail-markers-on p) with [ color = blue ]
end
I use the nw extension in NetLogo to create a network.
My aim is the following:
Check if any turtles are close by
If any turtles are close by (I tried with next 3 patches, but that might change), connect to them + there is an upper limit of possible links
I tried (and, I think, succeeded) to implement the approach, described here. Which means that the upper limit works. However, I am not able to only link to the turtles close by. I also need something to catch the error if no turtle is close by. I tried to use the in-radius command but for some reasons, it doesn't do what I want.
extensions [nw]
breed [ AT1s AT1]
turtles-own [ friends ]
to setup
ca
create-AT1s 20 [
setxy random-xcor random-ycor
set friends 3
set color green
get-radius-friends friends AT1s
]
end
to get-radius-friends [ x AgentT]
let lonely AgentT with [count my-links < x]
let candidates other AgentT with [ any? AgentT in-radius 3 AND count my-links < x ]
let new-links x - count my-links
if new-links > 0 AND any? AgentT in-radius 3
[ let chosen n-of min (list new-links count other candidates) other candidates
create-links-with chosen [ hide-link ]
set candidates other candidates
ask chosen [ if my-links = x [ set candidates other candidates ] ]
]
end
I also found the neighbors and the distance commands but these only consider the immediate surroundings which isn't what I need.
Actually, that's not the best question to pull from if you want to spatially restrict the turtles. And there's a serious problem with having the connection within the turtle creation block because there are no potential friends for the turtles created first. Unless you have a very large number of turtles, you probably don't need to worry about efficiency.
I also think the variable 'x' is unnecessary because you have the variable 'friends' available (which appears to be the number of links you want the turtle to have). And there is a new reporter up-to-n-of which makes the whole list and min unnecessary.
I think this does what you want. You may want to test is without the hide-link so you can see what it does.
breed [ AT1s AT1]
turtles-own [ friends ]
to setup
clear-all
create-AT1s 100
[ setxy random-xcor random-ycor
set friends 3
set color green
]
get-radius-friends 10 AT1s
end
to get-radius-friends [ #radius #breed ]
let linkers turtles with [breed = #breed ]
ask linkers
[ let new-links friends - count my-links
if new-links > 0
[ let candidates other linkers with [ count my-links < friends ] in-radius #radius
let chosen up-to-n-of new-links candidates
create-links-with chosen [ hide-link ]
]
]
end
I am trying to create links from agents (in my case, towers) with a certain property to other towers with another set of properties. Only some of them should be linked, yet when I ask the observer, it says they all seem to have that link.
to setup-links
print count towers with [ any? tower-communications ]
ask towers with [ heading = 0 ] [ ; first consider the communications between different areas
create-tower-communications-with other towers with [ heading = 0 ] ; between two towers that are still standing
in-radius tower-communication-radius ; and link towers to each other if they are close enough
with [ heading = 0 ]
[set color green]
end
print count( tower-communications with [ color = green ])
print count( towers with [ any? tower-communications ])
The first print statement gives as expected, the number of links between these pairs. The second should print out the number of towers that have a link between them, but it gives me the full number of towers in the system instead. What is going wrong? I only want the set of agents that have tower-communications with at least one other agent.
I think the problem is the way you are counting the turtles with links, not the way you are creating the links. Here is a full example (note that I took out the second with [heading = 0].
globals [tower-communication-radius]
to setup
clear-all
create-turtles 25
[ setxy random-xcor random-ycor
set heading 0
]
set tower-communication-radius 5
setup-links
end
to setup-links
print count turtles with [ any? links ]
ask turtles with [ heading = 0 ]
[ create-links-with other turtles with [ heading = 0 ]
in-radius tower-communication-radius
[set color green]
]
print count turtles
print count turtles with [ any? links ]
print count turtles with [ any? my-links ]
end
Your count is print count turtles with [ any? links ]. However, the test you are asking is whether there are any links in the model, not whether there are any links attached to the turtle (or tower). You need my-links or link-neighbors to apply to the specific turtle.