NetLogo: calculate perimeter of a patch-set - netlogo

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.

Related

Connect turtles who are within a certain radius

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

How does one report the distance between links and use those values reported for other calculations in code?

I'm trying to calculate and report the distance (link-length) between specific agentsets in NetLogo? Is there a way to calculate link length into a list?
The movement of the agents is based on whether the distance(connection) value is below/above a threshold. However, I'm having difficulty setting the values of the link length to variable connection. (preferably in a list). I'd appreciate any help.
globals[hourly-wage connection]
breed[offices office]
breed[employees employee]
offices-own [
pay-high ;; 7 offices pay well
pay-low ;; 3 offices dont pay well
]
to setup
clear-all
create-offices 10 [
set size 1.0
set color blue
set shape "house"
setxy random-xcor random-ycor
ask offices [create-link-with one-of other offices] ;; undirected links
ask links [set color red]
]
create-employees 2 [
set size 1
set color brown
set shape "person"
]
set hourly-wage 20
end
;;;;
to go
cal-dist
ask employees [
if connection > 15
move-to one-of high-pay office
if connection <= 15
move-to one-of low-pay office
]
end
to cal-dist
set connection [list print link-length] ;;
ask links [show link-length]
set salary (hourly-wage * connection) ;;; salary printed in a list
end
Not exactly sure what you're trying to do here with connection etc, but you can put any link variables into a list using of- for example:
to setup
ca
; First create the agents
crt 5 [
while [ any? other turtles in-radius 5 ] [
move-to one-of neighbors
]
set color blue
set shape "house"
]
; Once they're created, have them link with
; one of the other agents
ask turtles [
create-link-with one-of other turtles [
set color red
]
]
let link-lengths [ link-length ] of links
print link-lengths
reset-ticks
end
I don't know that this actually answers your question, so you may want to provide more detail as to what you're trying to accomplish with these links.

Making undirected links from an agent to an agentset

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.

Copy the link breed variable in the patch below

I have a network of nodes and links. This figure
is a capture of the world. The graph represents streets of a city. I have imported a shapefile with the gis extension. The gray lines are links, black dots are nodes and red dots represent people. The people move heading to the next node. In a street corner, the red dot chooses next street by examining the variable popularity owned by the link.
The links breed has a variable, popularity, whose value I would like to copy in the patches that are below.
If I try, for example, something like this to access patches under links will produce an error
ask links [show [(list pxcor pycor)] of patch-here]
Another approach can be to access links variable popularity from patches, but I do not know how to do it.
The reason why I want this is because I want to write in a file a matrix of popularity values and its position in the matrix should correspond with the position of the link in the world. Thus, the patches below the links would give me the matrix form. I have a procedure that for each patch writes the value of the patch in a file. However, I do not know how to pass the popularityvalue from the link to the patch below it.
Is there any way to copy a link owned variable to its patch?
Regards
If someone has a better way of doing this (or can simplify my code), feel free. Here is a complete working example. Copy it into an empty NetLogo model and run it to see it work.
The setup procedure just creates some nodes and links with appropriate test values and then calls the transfer-link-values procedure, which does what I think you want. The setup procedure then puts the values into the patch labels to display them and see the results.
The way the transfer-link-values procedure works is to create a turtle at one end of the link, and that turtle moves toward the other end of the link transferring the value as it goes. When it gets to the other end, the turtle dies.
patches-own [patch-popularity]
links-own [link-popularity]
to setup
clear-all
create-turtles 10 [ setxy random-xcor random-ycor]
while [ any? turtles with [not any? my-links] ]
[ let to-pair turtles with [not any? my-links]
let thisNode one-of to-pair
ask thisNode
[ create-link-with one-of other to-pair
[ set link-popularity 5 + random 5 ]
]
]
transfer-link-values
ask patches [ if patch-popularity != 0 [set plabel patch-popularity ] ]
end
to transfer-link-values
ask links
[ let start-node one-of both-ends
let this-link self
let end-node nobody
ask start-node [ set end-node [other-end] of this-link ]
let transfer-value link-popularity
ask start-node
[ hatch 1
[ face end-node
if transfer-value > patch-popularity
[ ask patch-here [ set patch-popularity transfer-value ] ]
while [ not member? end-node turtles-here ]
[ forward 1
if transfer-value > patch-popularity
[ ask patch-here [ set patch-popularity transfer-value ] ]
]
if transfer-value > patch-popularity
[ ask patch-here [ set patch-popularity transfer-value ] ]
die
]
]
]
end

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