NetLogo: How to create links with a defined number of other turtles - netlogo

I want to create a (scale-free) network where each turtle is connected to a specific number, say four, of other turtles. To allow some turtles to have many connections while others have few (but not less than four), my thought was to let each turtle have four out-links and let in-links would necessarily vary. Using the code for building a Barabasi-Albert scale-free network available on pg. 131 in Scott and Koehler's "A Field Guide to NetLogo" as a starting point, my code is included below.
My question is how to make each turtle connnect to four other turtles.
breed [liberals liberal]
breed [conservatives conservative]
to setup
clear-all
set-default-shape turtles "circle"
create-liberals 5 [
set adopt? false
let n count turtles
set color blue
]
create-conservatives 20 [
set adopt? false
let n count turtles
set color red
]
let m 4
let p .05
set my-threshold my-threshold
ask turtles[
let me self
let degrees max-n-of m turtles [count link-neighbors]
foreach (sort degrees) [ [?] ->
let chance random-float 1.0
if ( ? != self) and (chance < p ) [
ask self [ create-link-to ? ]
]
]
]
ask turtles with [(count out-link-neighbors) = 0 ] [
let degrees max-n-of m turtles [ count link-neighbors ]
let t one-of degrees
foreach (sort degrees) [
ask self [ if ( t != self) [ create-link-to t] ]
]
]
reset-ticks
end
The code above is part of my attempt to recreate Paul Ormerod's model, available at https://onlinelibrary.wiley.com/doi/abs/10.1111/j.1468-0270.2006.00611.x

Since you are doing a directed network, you won't have any issues with simply telling each turtle to select 4 other turtles and connect to them. The code for that would be:
ask turtles
[ create-links-to n-of 4 other turtles
]
Note that this is much more difficult in undirected networks because the links they 'receive' lead to too many links overall. Then you need to do something like NetLogo Efficient way to create fixed number of links
However, this will not get to your stated goal of a preferential attachment (scale-free, Barabasi-Albert or whatever you want to call it) degree distribution. The mechanism that generates that outcome is that the turtles select the turtles to make links with using weighted random selection, with the weight a normalised degree. You need the rnd extension and that gets you the weighted-n-of primitive.
I also noted some general issues with your code that are related to (I think) confusion about how the preferential attachment algorithm works and/or how NetLogo works. The weighted-n-of primitive will get rid of your need to look at random numbers and should simplify your code a lot. However, I am not clear what let degrees max-n-of m turtles [count link-neighbors] is supposed to do, but it appears to be creating a list of the four highest degree turtles. But the preferential attachment algorithm allows links to be created with even low degree nodes, just with lower probability.

Related

Using link-own variable to transfer resources between specific turtles

Say we have two turtles with a link between them, and that link owns a variable that represents the age of the link, "tenure". For turtle 1 to send resources to turtle 2, there is a conversion cost related to the age of the link between them. How do I refer to the tenure value of the specific link between these two turtles?
In context, I have turtles linked into "households" and as they start each day they assess how much energy they have. If they have more than some threshold of energy, they share the surplus with fellow housemates. To elect how they will share the energy, I have them looping through each housemate to determine who has low health. Surplus energy can be transferred to a housemate, but the conversion rate depends upon the tenure of the link between them. A longer tenure results in a better conversion rate of energy into health. But I don't know how to refer to the specific value of the linked-owned variable between each turtle and each of their housemates.
Right now, I have this approach of the shared-link being something like [link = [link] of myself] but that doesn't work:
turtles-own [energy health age]
links-own [tenure]
to go
tick
ask links
[
set tenure tenure + 1]
ask turtles
[
ifelse energy > 3 [supply] [rest]]
end
to supply
let surplus energy - 3
loop
[ask one-of link-neighbors
[
let shared-link link = [link] of myself
if health < 3 [set health health + 1 * [log [tenure] of shared-link]
set surplus surplus-1]
]]
end
Try running this snippet. it illustrates what I think you need.
links-own [ weight ]
to setup
clear-all
random-seed 12345
create-turtles 4 [setxy random-xcor random-ycor set label who set size 3]
ask turtles [ create-links-with other turtles [ set weight random 100 set label weight ]]
ask turtle 1 [ ask link-with turtle 2 [ set color red set thickness 0.5 ]]
ask turtle 1 [
let myweight [weight ] of link-with turtle 2
print ( word "Turtle 1 says, my link weight with turtle 2 is " myweight )
]
ask turtles [ ask link-neighbors [
let myweight [weight ] of link-with myself
print ( word myself " says, my link weight with " self " is " myweight )
]]
reset-ticks
end

Turtles in sub-samples which make different actions

I would need to let my agents/turtles to make some actions. Specifically I would like to select, let's say, 40 turtles and let make randomly some actions, for instance:
25 turtles action1;
15 turtles action2.
25, 15 should be randomly chosen.
I wrote the following
ask up-to-n-of num_of_turtles_per_tick turtles with [breed = M] [
ifelse random-float 1 < prob
[
action1]
[action2]
]
prob is set to 0.5. I think that my code let 40 turtles to do either action1 or action2, with no possibility to distinguish between two sub-sample of turtles (25,15 in the example, or 20,20, or 12 and 18...).
I should probably add a new parameter to determine this randomly numbers and let them make separately actions.
Could you please give me some advice on how to do this?
Thanks
You want the subsets to be mutually exclusive, so you need some construction that has an if-else type logic. But you can do either as a group or individually.
Individually is easier to understand, so let's start there (not tested so may have syntax errors). Basically you draw a random number and do one action if it's low and the other if it's high.
to testme
clear-all
create-turtles 40 [setxy random-xcor random-ycor]
ask turtles
[ ifelse random-float 1 < 15 / 40
[ set color blue ]
[ set color red ]
]
end
For the group approach, you need some way to remember the group that does the first action so you can identify all the others to be in the group that does the second action. The member? reporter checks whether a turtle is a member of the specified turtleset.
to testme
clear-all
create-turtles 40 [setxy random-xcor random-ycor]
let type1 n-of 15 turtles ; assigns some to a temporary agentset
ask type1 [ set color blue ]
ask turtles with not member? self type1 [ set color red ] ; gets the others
end

Variables in different breeds

i'm trying to make an archaeological model, in which hunters are making paintings in shelters, depending on their quality.
breed [shelters shelter]
breed [hunters hunter]
shelters-own [quality paintings]
The value of each shelter quality is set in the setup (with a slider for the actual number of shelters).
create-shelters number-shelters [set quality random 100]
The action of painting-or-not is then defined by random against the quality of each shelter:
to make-painting
ask shelters [
if any? hunters-on patch-here [
if random 100 < quality [set paintings paintings + 1]
]
]
end
Now, I would like to complexify it a bit more: the quality wouldn't be defined by the shelter itself (and thus be the same for every hunter), but by the hunters: each of them would attribute a different quality for each shelter. The action of painting-or-not would still be a test against random, but with this new variable defined by each individual hunter...
But I can't find a way to code it down properly.
Does anyone have a suggestion?
I think I got it right. Basically, I had every hunter to create a matrix filled with random numbers. The size is 33x33, so it goes all over the world (had to set it to start in a corner, or it gets negative coordinates).
create-hunters number-hunters [
set color white
set size 1
setxy random-xcor random-ycor
set hunter-matrix matrix:make-constant 33 33 random 10
]
ask n-of number-shelters patches [
sprout-shelters 1 [
set color one-of base-colors
set size 1
set xpatch xcor set ypatch ycor
]
Then, when they would reach a shelter, the value corresponding to that patch location would be extracted and used to paint-or-not.
ask patches [
ask hunters-here [set quality matrix:get hunter-matrix xpatch ypatch]
let paintings-here sum [paintings] of shelters-here
if any? hunters-here and any? shelters-here [
if random 10 < quality [
ask shelters-here [
set paintings paintings + 1]
]
]
]
I'm still not completely sure it actually does what I think it's doing, tho.

How can I get an agent to decay as multiple agents feed on it?

In my model I have some agents which act as food items with a set energy. These are fed upon by a number of turtle breeds who each have their own food-energy which is less than the energy of the food item.
The code for the feeding agents is as follows:
to eat
ifelse [food-energy] of myfood > 1.5 [
set food-energy 1.5]
end
and the associated code for the food item to decay is:
to decay
if any? turtles-here [set food-energy
(1.5 * count feeders-here with [myfood = myself]
end
The problem occurs if the energy of the food is not an exact multiple of the amount of energy the feeders can consume. So for example it can go down to 1 and this results in the feeders taking 1.5 units which should be impossible. This is exacerbated when I have different breeds with different food energies (i.e. < or > 1.5).
So my question is how can I get this things to balance?
You need to study the Wolf-Sheep Predation model. This is the first NetLogo tutorial: http://ccl.northwestern.edu/netlogo/docs/tutorial1.html There are five versions of increasing complexity in the NetLogo Models Library, which are covered in chapter 4 of Wilensky and Rand (2015), which you should read.
See some related material here:
http://jasss.soc.surrey.ac.uk/14/2/5.html
Some hints follow, but many details need filling in.
breed [feeders feeder]
patches-own [ food-energy ]
feeders-own [ myfood ]
to setup
ca
ask patches [set food-energy random 50]
create-feeders 500 [
move-to one-of patches
set myfood one-of patches
]
end
to go
ask feeders [move]
ask feeders [feed]
ask patches [growback]
end
to move ;how shd they move?
rt random 20
left random 40
fd 1
;shd movement cost energy?
end
to feed
if (patch-here = myfood) [
let _extracted min (list food-energy 1.5)
set food-energy (food-energy - _extracted)
]
end
to growback
;do you want growback?
end
thanks for your responses. I'll try to implement them. This is one inelegant workaround that worked for me:
to eat
ifelse (food-energy / capacity) < 1 and [meat] of myfood > capacity [
set food-energy 1.5] [set food-energy [meat] of myfood
ask myfood [set shape "square"]]
if (food-energy / capacity) = 1 [
set color white]
if (food-energy > 0 and food-energy / capacity < 1)
[ set color white ]
end
This was initially causing a problem such that when the food energy went down to 0 and I asked it to die any animal looking at the [meat] of myfood lost it's target and I got an error. So I made the animals break this connection once their colour was white.
to ignore
set myfood nobody
set food-energy food-energy * 1
end

NetLogo - Distributing grains of sand in sandpile model to random neighbours

This code relates to an adaption of the NetLogo sandpile model. When the count go grains in each patch exceeds the threshold which in this case is 3, the grains are re-distributed to the surrounding neighbors. I am trying to re-distribute one grain to 4 random neighbour patches.
The code returns a run time error because patches at the edge will not have all the 8 neighbors, so when asking for 4 random neighbours it returns an errors stating can't request 4 ransom agents from 3 etc.
I am trying to find a piece of code that will resolve this problem.
****Code Below*****
to-report stabilize [animate?]
let active-patches patches with [ n > threshold ]
;; The number iterations the avalanche has gone for. Use to calculate lifetimes.
let iters 0
;; we want to count how many patches became overloaded at some point
;; during the avalanche, and also flash those patches. so as we go, we'll
;; keep adding more patches to to this initially empty set.
let avalanche-patches no-patches
while [ any? active-patches ] [
let overloaded-patches active-patches with [ n > threshold ]
if any? overloaded-patches [
set iters iters + 1
]
ask overloaded-patches [
set base-color fired-color
;; subtract 'threshold' amount from this patch
update-n -4
if animate? [ recolor ]
;; edge patches have less than four neighbors, so some sand may fall off the edge
ask n-of 4 neighbors [
update-n 1
if animate? [ recolor ]
]
]
if animate? [ display ]
;; add the current round of overloaded patches to our record of the avalanche
;; the patch-set primitive combines agentsets, removing duplicates
set avalanche-patches (patch-set avalanche-patches overloaded-patches)
;; find the set of patches which *might* be overloaded, so we will check
;; them the next time through the loop
set active-patches patch-set [ neighbors ] of overloaded-patches
]
report (list avalanche-patches iters)
end
Instead of asking 4 neighbors, ask min list 4 count neighbors:
ask n-of (min list 4 count neighbors) neighbors [
...
]
But from the model point of view, there will be different redistribution on the edge of the table, so this is not a good idea. Maybe it is better to have a wrapped world and then manually "push" the grains off the table: select 4 neighbours and call just the ones with close pxcor and pycor. The rest is off the table.
If the world is wrapped (horizontally and vertically), we can always select 4 neighbors:
let selected-neighbors n-of 4 neighbors
Among these 4 neighbors only real neighbors are on the table
set selected-neighbors selected-neighbors with [
(abs (pxcor - [ pxcor ] of myself) < 2)
and
(abs (pycor - [ pycor ] of myself) < 2)
]
ask selected-neighbors [
....
]