NetLogo: select neighboring patches to a patch-set - netlogo

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

Related

How can I record the identity of turtles another turtle interacts with?

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 )

Delete links between turtles with different breeds

I would like to drop links between one turtle and another one with different breed if a condition is satisfied.
I am using the following code to do this:
ask one-of turtle1 [
if any? my-out-links with [breed = turtle2]
[ask one-of out-link-neighbors with [breed = turtle2 and value < 0.7] ;; value should refer to a neighbour's characteristics and it represents my condition
[die]
]
]
But the links seems to be kept. No link has been deleted.
Could you please tell me what it is wrong in my code and how to fix it accordingly?
I'm assuming that turtle1 and turtle2 are two breeds of turtles. If so,
if any? my-out-links with [breed = turtle2]
will never find any such out-links as you are checking to see if any of my-out-links are of breed turtle2, and of course no links are of that breed. What you want is to know if the turtle at the other end of the link is of breed turtle2. Since these are directed links, the turtle you want to check is at end2.
if any? my-out-links with [[breed] of end2 = turtle2]
will let you know if the any of the turtles at the other end of my-out-links are of breed turtle2.
The line
ask one-of out-link-neighbors with [breed = turtle2 and value < 0.7] [die]
may do more than you intend. It asks a link-neighbor turtle of breed turtle2 and with value < 0.7 to die. That will indeed kill the link as well (since it has lost its end2), but if you want to kill the link and not the turtle at the other end you could do all this in a single line
ask one-of turtle1 [
ask one-of my-out-links with [[breed = turtle2 and value < 0.7] of end2] [die]
]
If there are no such out-links, then you will be asking nobody and the ask will do nothing.

NetLogo: calculate perimeter of a patch-set

I'm modeling territory selection in NetLogo, and would like my turtles to calculate the perimeter of their territory once established. I've been trying to come up with ideas for how to do this, but haven't found a good means yet. Any ideas?
patches-own
[ owner ] ;; patches know who owns them
turtles-own
[ territory ;; agentset of patches I own
food ;; food acquired in my territory
threshold ] ;; food required, will build territory until meet this
to go
tick
ask turtles [ build-territory ]
end
to build-territory
if food > threshold [ calculate-perimeter ] ;; stop building when enough food
pick-patch ;; keep picking patches until meet threshold.
end
to calculate-perimeter
;; what could I use to add up the perimeter of the territory?
end
Thanks in advance for any suggestions!
A modification of my last answer to you:
to setup
ca
ask patches with [pxcor > 0 ] [
set pcolor white
]
crt 1
end
to go
ask turtles [
let blacklist patches with [ pcolor = black ]
let northpatches patches with [ pycor > 0 ]
let northred ( northpatches with [ member? self blacklist = false ] )
ask northred [ set pcolor red ]
let border northred with [ any? neighbors4 with [ pcolor != red ] ]
ask border [
set pcolor blue
]
print count border
]
end
You can designate border/perimeter patches as any of you territory patches with neighbors that are not territory. For you it might look something like:
ask turtles [
print count territory with [ any? neighbors4 with [owner != myself ]
]
]
Again, I can't test it without your setup so you would have to modify.
Edited below
To count the edges of patches that are on the border, you could have them count their neighbors4 that belong to another turtle. Then, they can add them to that turtle's perimeter length. For example:
to assess-perimeter ;;; must be called by a turtle
print ("Assessing perimeter")
let current-turtle who
let temp-per-len 0
let border-patches patches with [ owner = current-turtle and any? neighbors4 with [ owner != current-turtle ] ]
show (word "I have " count border-patches " border patches")
ask border-patches [
;; One way to get each border patch to check each of its neighbors
let nobodies 4 - count neighbors4 ;; if any patches are on the edge of the world, returns the number of those edges
let non-territory-edges count neighbors4 with [ owner != current-turtle ]
let border-edges nobodies + non-territory-edges
set temp-per-len temp-per-len + border-edges
]
show (word "My perimeter length: " temp-per-len )
set perimeter-length temp-per-len
end
If that is called after all turtles have chosen their entire home range, the idea is that each turtle assesses the border of its home range. Then, it has each of those border patches count its neighbors4 that have a different owner. I used "temp-per-len" as a summing variable within the loop, which is then used to set the turtles-own "perimeter-length". Full model code, including setup and definitions, here. Note- you'll have to download or copy the code, the model is too bulky to run well in the HTML format.
Also, I didn't actually count to make sure this worked perfectly- I did a quick version and crossed my fingers, but I think the idea makes sense and hopefully gets you started.

Netlogo: ask turtle to reproduce after it completes a procedure, and ask new turtle to repeat that procedure for itself

I'm new to NetLogo and am attempting to model home range selection of subsequent colonizers. The model should follow simple steps:
Individual 1 picks a home range (a subset of patches).
When individual 1 is done picking its home range, it hatches new
individual 2.
Individual 2 picks a home range, then hatches individual 3.
Individual 3 picks a home range, and so on.
I'm having trouble figuring out how to get this to work. I can get the first turtle to pick a home range. But the offspring do not. Writing the code numerous ways has only accomplished two unintended outcomes. Either endless new individuals are hatched simultaneously, before the first turtle has a home range, and the new turtles fail to pick a home range. Or, the first turtle picks its home range and hatches a new turtle, but that new turtle doesn't pick a home range. Neither outcome is what I want.
How do I set this up to run as intended, so that hatchlings pick home ranges too? Here is one simplified version of my code:
to setup-turtles
crt 1
[setxy random-xcor random-ycor]
end
to go
ask turtles [pick-homerange]
tick
end
to pick-homerange
while [food-mine < food-required] ;; if not enough food, keep picking patches for home range
[;; code to pick home range until it has enough food; this is working okay
]
[;; when enough food, stop picking home range
hatch 1 fd 20 ;; now hatch 1, move new turtle slightly away
]
end
So it is at this last part, once the home range is built, that I want a new turtle to hatch from its parent. I then want that turtle to repeat the pick-homerange procedure. How could that be coded to happen? I've tried writing this every way I can think of; nothing is working. Thanks in advance for any assistance!
One way to do this is to have each patch equal one "food value", and have turtles grow their home range until their home range supplies them with enough food. I would set this up so that patches "know" to which turtle they belong, and so that turtles know how much food they need, which patches are part of their home range, and the food supplied by their homerange. Example patch and turtle variables would then be:
patches-own [
owned_by
]
turtles-own [
food_required
my_homerange
homerange_food
]
Then, your turtles can add patches into their home range until they hit their "food_required", whatever you set that as. For simplicity, in this example I assume that turtles are territorial and so won't "share" home ranges. Further explanation of steps is commented in the code below. This is intended just to get you started- for example, it will hang if you run pick-homerange too many times.
to setup-turtles
crt 1 [
set size 1.5
setxy random-xcor random-ycor
set food_required 5 + random 5
set homerange_food 0
set my_homerange []
]
end
to pick-homerange
ask turtles [
;; Check if the current patch is owned by anyone other than myself
if ( [owned_by] of patch-here != self ) and ( [owned_by] of patch-here != nobody ) [
;; if it is owned by someone else, move to a new patch that is not owned
let target one-of patches in-radius 10 with [ owned_by = nobody ]
if target != nobody [
move-to target
]
]
;; Now add the current patch into my homerange
ask patch-here [
set owned_by myself
]
set my_homerange patches with [ owned_by = myself ]
;; calculate the number of patches currently in my homerange
set homerange_food count patches with [owned_by = myself]
;; Now grow the homerange until there are enough patches in the homerange
;; to fulfill the "food_required" variable
while [ homerange_food < food_required ] [
let expander one-of my_homerange with [ any? neighbors with [ owned_by = nobody ] ]
if expander != nobody [
ask expander [
let expand_to one-of neighbors4 with [ owned_by = nobody ]
if expand_to != nobody[
ask expand_to [
set owned_by [owned_by] of myself
]
]
]
]
;; Reassess homerange food worth
set my_homerange patches with [ owned_by = myself ]
set homerange_food count patches with [owned_by = myself]
]
ask my_homerange [
set pcolor [color] of myself - 2
]
;; Now that my homerange has been defined, I will hatch a new turtle
hatch 1 [
set color ([color] of myself + random 4 - 2)
]
]
end

Moving turtles to specific coordinates of other agents in NetLogo

I have individuals (turtles) and I have households (turtles with fixed xy)
I have a variable address stored at households. I have a number of a family attached to individuals. The households has the same number.
How can I ATTACH or MOVE the individuals to their corresponding household?
I tried something like:
ask individuals
[ if family = [family-place] of household
[
move-to [address] of household
]
]
Since it is a slow monday morning, here is how I would do it.
I assume familiy-number to be the name of the common number in both moving and sessile turtles. I would use let to create a local variable that only works within the procedure. (See the procedure go-home for this)
breed [walkers walker]
breed [houses house]
houses-own [family-number]
walkers-own [family-number]
to setup
clear-all
set-default-shape houses "house"
create-houses 10 [
setxy random-xcor random-ycor
set family-number random 10000
]
reset-ticks
end
to leave-home
ask houses [
hatch-walkers 1 [
set family-number [family-number] of myself
set color [color] of myself
set heading random 360
fd 1
]
]
end
to go
ask walkers [
rt random 120
lt random 120
fd 1
]
tick
end
to go-home
ask walkers [
let family-place one-of houses with [family-number = [family-number] of myself]
move-to family-place
fd 1 ;; walker will step away one step so we can see him.
]
end
Just copy it into NetLogo, make a button for each procedure and play. Works best if in the order
setup
leave-home
go
go-home
Hope this helps!
move-to household should do it.
I'm having trouble understanding your question, so I've having to guess at what you want, but with the help of your comment on Bryan's answer, maybe I've guessed right?
ask individuals [
move-to one-of households with [address = [family-place] of myself]
]
if this seems confusing because of the myself, you could also write it as:
ask individuals [
let f family-place
move-to one-of households with [address = f]
]