Perspective based ranking? - netlogo

I have a program where each peer has their own ranking system of other peers, what is the best way to implement this is NetLogo?
Normally, I would solve this with a 2D list:
[[turtle 1, score], [turtle 2, score], ...]
But this seems very troubling in NetLogo. This is my code for creating and modifying a 2D list:
to test
clear-all
crt 10
;Create a list of turtles
let agents-list [self] of turtles
;Create empty list, which will be the top level of the TwoD list
let TwoD-list []
;Populate the TwoD-list: [[turtle 0, 0], [turtle 1, 0], ...]
foreach agents-list [
set TwoD-list (lput (list ? 0) TwoD-list)
]
show TwoD-list
repeat 5 [
;Change a value in the TwoD-list
let rand-index random (length TwoD-list) ;select a random index
;The next line is what makes it a huge headache, basically you have to select a list at the top level to replace, and then select the list at the lower level to replace it.
;This entire line of code is just adding one to an element
set TwoD-list (replace-item rand-index TwoD-list (replace-item 1 (item rand-index TwoD-list) (item 1 (item rand-index TwoD-list) + 1)))
show TwoD-list
]
end
What else can I do? Or is there a better way to implement this method?

If you want to model relations between agents, NetLogo has the perfect thing for that: links!
Having each turtle assign a score to all other turtles can be quite naturally expressed as:
directed-link-breed [ rankings ranking ]
rankings-own [ score ]
to setup
clear-all
create-turtles 10
ask turtles [ create-rankings-to other turtles ]
; increment 5 random rankings by one:
ask n-of 5 rankings [ set score score + 1 ]
; display the rankings of each turtle:
ask turtles [ show [ (word end2 " " score) ] of my-out-rankings ]
end
If you don't want the links to show up in the view, you can hide them with:
ask links [ set hidden? true ]

Related

To do a netlogo model with several patch layers (think floors of a building) do I need to go to Netlogo 3D?

I have a netlogo application in mind which involves multiple non interacting layers. Think floors of a building. Would I need to go to netlogo 3D or is there a suggested way to handle in regular netlogo?
This was an interesting enough question that I decided to make a simple sample.
The method I use is to have a global variable to track the number-of-floors we'll have in our building, as well as the active-floor that we are currently working with. Then all our agents, walls and workers, have a floor-num that tracks which they are on. We have a set-active-floor procedure that handles switching our currently active floor that we want to see and work with, making the patches a certain color (active-color) if they have a wall agent present and swapping which workers are hidden?. In this way, most of the magic happens in the setup-floor and set-active-floor procedures, and the real work of our model in go can be pretty typical NetLogo code asking the active-workers to do whatever we want.
While the model is running you can call set-active-floor n to any value 0 to 4 to change the current workers and walls. I also included a show-all procedure that'll un-hide all the walls and workers and let you see where they are at; you'll need to run that with the model stopped.
globals [colors active-color number-of-floors active-floor]
turtles-own [floor-num]
breed [walls wall]
breed [workers worker]
to setup
clear-all
set colors (list red blue green orange violet)
set number-of-floors 5
foreach (range 0 number-of-floors) setup-floor
reset-ticks
set-active-floor 0
end
to setup-floor [num]
set active-floor num
set active-color (item num colors)
ask patches [ set pcolor black ]
; make some random walls
create-walls (count patches * 0.2) [
set floor-num num
set hidden? true
set size 0.5
setxy random-pxcor random-pycor
set pcolor active-color
]
; only one wall per patch
ask patches [
let patch-walls floor-walls-here
let wall-count count patch-walls
if (wall-count > 1) [
ask n-of (wall-count - 1) patch-walls [ die ]
]
]
; make some workes
create-workers 10 [
set floor-num num
set hidden? true
set shape "person"
set color active-color - 2
move-to one-of patches with [pcolor != active-color]
]
end
to go
; this only "runs" the active floor, but you could run all of them
; using the same `foreach (range 0 number-of-floors) ...` code as
; in the `setup` procedure.
set-active-floor active-floor
ask active-workers [
; this code can be about the same as you'd write in a normal model...
move-to one-of patches with [pcolor != active-color]
]
tick
end
to set-active-floor [num]
set active-floor num
set active-color (item num colors)
; after the `pcolor` is set, we can use that to determine if a wall
; exists or not for an `active-worker`, we don't have to check the
; floor number at all while we do our work.
ask walls [ set hidden? true ]
ask patches [
set pcolor ifelse-value no-walls-here [ black ] [ active-color ]
]
ask workers [
set hidden? floor-num != active-floor
]
end
to-report active-workers
report workers with [floor-num = active-floor]
end
to-report floor-walls-here
report walls-here with [floor-num = active-floor]
end
to-report no-walls-here
report (count floor-walls-here = 0)
end
to show-all
foreach (range 0 number-of-floors) [ num ->
ask patches [
set pcolor ifelse-value any? walls-here [ red - 3 ] [ black ]
]
ask turtles with [floor-num = num] [
set color item num colors
set hidden? false
]
]
end
Finally, if things got much more complicated than this, I would probably choose to move to NetLogo 3D instead.

How to access the first turtle of a code sequence in NetLogo 6.2?

I have the following doubts:
I have several individuals of 9 turtle codes.
The turtle codes are: R1M1 R2M1 R3M1 R1M2 R2M2 R3M2 R1M3 R2M3 R3M3. And I have 10 individuals of each code.
As the code is structured in a loop sequence and the order that the code exits in the result exported in .csv, I would like to ask the first individual of the first code (R1M1) to print the output header. But, I'm only getting it using one-of, and then the header often doesn't come out in the first line of the output. And I don't know how I can access the first turtle from the R1M1 code. Does anyone have any ideas?
What I thought of is calling turtle 0 which has the code R1M1. But, I still don't know how to do this in NetLogo.
OBS.: I tried to use only turtle 0, but in the other codes, too, there is turtle 0 and then the header appears.
Thanks in advance
let n count turtles with [ profiles-code = "R1M1" ]
if n > 0
[
ask one-of turtles with [ profiles-code = "R1M1" ]
[
prepare-header-output;; CALL A PROCEDURE
]
]
An example of how the header is coming out (has 3 individuals from each of the 9 codes)
I would use a flag / semaphore variable to indicate if a header is needed. You'll need to adapt the below if you have your turtles outputting the data, but hopefully this will get you pointed in the right direction- more details in comments:
globals [ need-headers? ]
turtles-own [ class ]
to setup
ca
random-seed 1
set need-headers? true
if file-exists? "test_output.csv" [ file-delete "test_output.csv" ]
crt 10 [
set class item random 5 "ABCDE"
]
reset-ticks
end
to go
if count turtles < 1 [ stop ]
ask turtles [
if random-float 1 < 0.25 [ die ]
]
; Toy output example
file-open "test_output.csv"
foreach range length "ABCDE" [ i ->
; Output headers if needed
if need-headers? [
file-print "turtle-type, count, ticks"
; Change the need-headers? to false so this step will only happen once
set need-headers? false
]
let ltr item i "ABCDE"
let n-type count turtles with [ class = ltr ]
file-print ( word ltr "," n-type "," ticks )
]
file-close
tick
end
Output here looks something like:
but if I don't change need-headers? to false, it looks like:

How to separate values from a list using commas in netlogo?

Situation: I have a code that exports turtle coordinates according to the code below:
to path
file-open (word fileName ".csv")
file-print (word self xcor " " ycor)
file-close
end
The result is something like:
(turtle 1)[1 1 1 1 1 2] [4 4 4 2 1 5]
Question: How can I export this same list, but with its items separated by commas?
From [1 2 1 1 1] to [1,2,1,1,1], for example.
Thanks in advance
If you are trying to process this in R or something after the fact, I'd recommend potentially reporting in long format (ie, each line indicates a turtle, a tick [or similar], and the coordinates)- I find it simpler to process.
To answer your actual question- one way would be to manually collapse each list of coordinates into a string separated by commas. For example, see the toy model below.
Simple setup:
extensions [csv]
globals [ test ]
turtles-own [ xcor-list ycor-list ]
to setup
ca
crt 10 [
set xcor-list []
set ycor-list []
]
repeat 5 [
ask turtles [
rt random 90 - 45
fd 1
set xcor-list lput pxcor xcor-list
set ycor-list lput pycor ycor-list
]
]
reset-ticks
end
This reporter is what's actually doing the work of collapsing the list into a simple string for output:
to-report collapse-string-list [str-list]
report reduce word ( sentence map [ str -> word str ", " ] but-last str-list last str-list )
end
And this chunk pulls the desired turtle variables into a list of lists, calls the collapse-string-list reporter on them, then exports to a csv:
to output-coord-file
let all-turtles sort turtles
; Pull coordinates from each turtle
let who-coord-list map [
current-turtle ->
(list
[who] of current-turtle
collapse-string-list [xcor-list] of current-turtle
collapse-string-list [ycor-list] of current-turtle
)] all-turtles
; Add headers
set who-coord-list fput ["who" "x" "y"] who-coord-list
; Export
csv:to-file "toy.csv" (map [ row -> (map [i -> (word i)] row ) ] who-coord-list)
end
Output:

Netlogo: How to ask link-neighbor to do something

I am simulating a classroom. In a classroom there are about 90 seats, 20 lights, 20 fans and 4 ACs. I create num-of-students where each student has an assigned random entry-time. When each student enters after a random time and sits on a seat the corresponding (in-radius)light or fan or ac turn on and a link is established between the the student and the in-radius appliance. Each appliance (e,g light, fan and AC) has their own wattage value. After all the students sits down the total energy consumption (in KWh) will be calculated for all the fans, lights and ACs.
How can I store the on-time of each appliance e.g (time minus entry-time), where time is the total class time. So that afterwards I can sum all the on-time of each appliance(e.g fan) and multiply it with its watt value. This is the part of the code.
globals[
temp1 simulation-timer number-of-seats number-of-lights number-
of-fans number-of-acs ]
breed [lights light]
breed [fans fan]
breed [acs ac ]
breed [students student ]
to setup
...
...
place-seats-students
place-lights
place-fans
place-acs
create-students-classroom
end
to create-students-classroom
create-students number-of-students [
set entry-time random threshold + 1
let stu-no sort-on [who] students
foreach stu-no [x -> ask x [ show (word x " -> " entry-time )
] ]
ask students [
set shape "person"
set color 3
] ]
end
to go
set simulation-timer 0
output-show (word "timer = "simulation-timer )
tick
move-students
while [simulation-timer < time ] [
set simulation-timer simulation-timer + 1
output-show (word "timer = "simulation-timer )
end
to move-students
let s sort [who] of seats
let a first s
let l length s
while [ l > (number-of-seats - number-of-students )] [
set temp1 simulation-timer
tick
tick
ask students [ if ( entry-time = temp1 ) [
move-to seat a
set color red
ask students
[create-links-with lights in-radius 5
create-links-with fans in-radius 5
create-links-with acs in-radius 9 ]
show (word "number of links is" count links)
appliance-on
store-on-time
show (word temp1 "," l "," a)
set s remove a s
set a a + 1
set l length s
]
]
set simulation-timer simulation-timer + 1
output-show (word "timer = "simulation-timer )]
end
to appliance-on
ask students with [color = red ]
[ask my-links
[ask other-end [set color green] ] ]
stop
end
to store-on-time
ask students [
ask link-neighbor fan ifelse it is on [
let on-time [ time - entry-time ]
[do nothing]
ask students [
ask link-neighbor light ifelse it is on [
let on-time [ time - entry-time ]
[do nothing]
end
How can I write the store-on-time procedure, so that later I will be able sum to all the on-times for all the appliance to calculate the KWh consumed. Any help will be greatly appreciated.
If you need to store something, then you need to create a variable for it. Since they might turn on, off, on etc, I would personally have two variables for each appliance (eg lights-own and fans-own etc). For lights, they could be named light-on-time, light-on-duration and similarly for others.
The way this works in code is add
set light-on-time ticks
whenever you turn the light on. And have
set light-on-duration light-on-duration + ticks - light-on-time + 1
whenever you turn the light off. The reporter ticks is just the current state of the clock.

Controlling lives of turtles in NetLogo

For a project, I'm developping a simulation in NetLogo dealing with rabies diseases in dogs and humans. I have some turtles-humans with dogs that can be vaccinated or not. At the beginning I create a dog with rabie and, in according to the fase (1 or 2) of the disease, it can spread the disease to other dogs with a probability. At the end the dog can die either for paralysis (if a probability is higher than 75%) or for other complications. Here's the code:
http://pastebin.com/esR75G3T
In the end you can see that a dog not dying for paralysis will die after some days (between 4 or 6). In other words when the days_infected are equal to end-life.
To check if everything is ok at the beginning I tried to set that NONE of the dog is vaccinated so everyone is supposed to get the disease. In fact when the dog is in phase 2 it will bite anyone. The problem is that if I delete the last line of the code, everything works and some dogs die of paralysis and the other remain alive. If I enable also the last line to let the other dogs die too, nothing works...no dog is infected. why?
This is not a problem with your code: this is a problem with the dynamics of your model. What's happening is that your initial sick dog dies before actually infecting another dog. This is why removing the if (days_infected = end-life) [die] "fixes" the problem.
When I tried your model with a huge population (e.g., 5000 people) so that encounters are more frequent, the infection does spread. You could also increase the probability of infection, or increase the duration of the "furious" phase, I guess.
Another unrelated suggestion, if I may: you should have distinct persons and dogs breeds. Trying to cram everything inside regular turtles makes your code much more complicated than it should be. The way I would approach this would be to create a link from the person to her dog, and then use tie so that the dog is automatically moved when you move the person.
Edit:
OK, here is a version of your code slightly modified to use breeds:
globals [
total_dogs_infected
total_dogs
dead_humans
dead_dogs
]
breed [ persons person ]
persons-own [
sick?
]
breed [ dogs dog ]
dogs-own [
sick?
vaccinated?
rabies_phase
days_infected
end-incubator
end-furious
end-life
]
to setup
clear-all
initialize-globals
setup-turtles
reset-ticks
end
to initialize-globals
set dead_humans 0
set dead_dogs 0
set total_dogs_infected 0
end
to setup-turtles
set-default-shape persons "person"
set-default-shape dogs "wolf"
create-persons people [
setxy random-xcor random-ycor
set size 1.5
set sick? false
ifelse random 100 < 43 [
set color green
hatch-dogs 1 [
set color brown
set heading 115 fd 1
create-link-from myself [ tie ]
set days_infected 0
set vaccinated? (random 100 > %_not_vaccinated)
if not vaccinated? [ set color orange ]
]
]
[
set color blue ;umano sano senza cane
]
]
set total_dogs count dogs
ask one-of dogs [ get_sick ]
end
to get_sick
set sick? true
set color white
set rabies_phase 1
set end-incubator 14 + random 57
set end-furious (end-incubator + random 5)
set end-life (end-furious + 4 + random 2)
set total_dogs_infected total_dogs_infected + 1
end
to go
move
infect
get-older-sick-dog
tick
end
to move
ask persons [
rt random 180
lt random 180
fd 1
]
end
to infect
ask dogs with [ sick? ] [
if (rabies_phase = 1 and (random 100) <= 2) or rabies_phase = 2 [
ask other dogs-here with [ not sick? and not vaccinated? ] [ get_sick ]
]
]
end
to get-older-sick-dog
ask dogs with [ sick? ] [
set days_infected days_infected + 1
;the incubator phase ends after at least 14 days + random(57) and then we have phase 2 (furious)
if (days_infected = end-incubator) [ set rabies_phase 2 ]
;when the main furious phase finishes we have 75% of probability that a secondary furious phase continues for other 4 - 6 days until death ;or we have a probability of 25% that the disease end in paralysis with a fast death
if (days_infected = end-furious and (random 100 > 75)) [
set dead_dogs dead_dogs + 1
die
]
if (days_infected = end-life) [
die
]
]
end
; These last reporters are not used,
; they just illustrate how to get the
; dog from the owner or vice-versa:
to-report my-dog ; person reporter
report one-of out-link-neighbors
end
to-report has-dog? ; person reporter
report any? out-link-neighbors
end
to-report my-owner ; dog reporter
report one-of in-link-neighbors
end
Not only does it simplify some expressions (e.g., ask dogs with [ sick? ] instead of ask turtles with [ has_dog? and sick_dog? ]), it opens up all sorts of possibilities: a dog could run away from its owner, the owner could die without the dog dying, an owner could have two dogs, etc.