Making undirected links from an agent to an agentset - netlogo

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.

Related

Linking turtles to another turtle with highest value in NetLogo. Limit the number of links

I am a beginner with NetLogo and I am trying to ask some turtles (students from different social classes) to link to other turtles (schools). What I would like is for the working class students to look for the school with the highest achievement which is at the same not expensive and has not reached the max number of links allowed. If the desired school has reached the max number of links allowed I want the student to look for the next school with the highest achievement which has not reached the max number of links allowed and so on.
This is the code. I get the following message "ANY? expected input to be an agentset but got the turtle (school 1) instead."
breed [schools school]
breed [upperclass upperclass-student]
breed [workingclass workingclass-student]
upperclass-own [achievement enrolled? target]
workingclass-own [achievement enrolled? target]
schools-own [schoolachievement expensive? ]
to setup
clear-all
set-default-shape schools "house"
set-default-shape upperclass "person"
set-default-shape workingclass "person"
ask patches [ set pcolor 8 ]
create-schools num-of-schools [ setxy random-xcor random-ycor set schoolachievement random-normal 5 1
set expensive? one-of [ true false ] ]
create-upperclass num-of-upperclass [ set color white setxy random-xcor random-ycor set achievement
random-normal 5 1 ] ;Students from upper class have higher achievement
create-workingclass num-of-workingclass [ set color red setxy random-xcor random-ycor set achievement
random-normal 4 1 ]
end
to go
ask workingclass [
choose-school ]
end
to choose-school
if breed = workingclass [
set target one-of schools with-max [ schoolachievement ] with [ expensive? = false ] ]
if any? target with [ count link-neighbors < max-link-count ] [
create-link-with target ]
set enrolled? TRUE
end
Your problem is the difference between an agent and an agentset, which is a somewhat subtle problem. The with-max returns an agentset - a set of agents (in this case turtles). That agentset can have 0 members, 1 member, 2+ members but is a set even if it is empty. However, the one-of selects one agent from the agentset and returns it as an agent, not an agentset. That is, NetLogo knows anything that is returned by one-of must be exactly one agent. At this point, primitives that are for agentsets (like any?) will throw an error unless they can also be used on individual agents.
So, back to your code. I like the readability of checking whether there are viable schools and then selecting one, which is what I think you meant to do. That would be:
to choose-school
if breed = workingclass
[ set targets schools with-max [ schoolachievement ] with [ expensive? = false ]
set candidates targets with [ count link-neighbors < max-link-count ]
if any? candidates
[ create-link-with one-of candidates
set enrolled? TRUE
]
]
end
Note that I also changed to targets instead of target, which is one way to keep track of whether something is an agent or an agentset.
The other way you could do this and keep it as an agent is:
to choose-school
if breed = workingclass [
set target one-of schools with-max [ schoolachievement ] with [ expensive? = false ] ]
if target != nobody and [count link-neighbors] of target < max-link-count [
create-link-with target ]
set enrolled? TRUE
end
So you can use nobody instead of any? but you can't also use with in that line because the with is really a filter on a set.
I also think you have a bracketing issue - I assume you want set enrolled? TRUE inside the brackets. I left it in the second fix, but changed in the first error (as well as changing bracket position convention to make the code block structure more visible)

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

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: 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