I would like to know how to add attributes for each element of a list.
In particular, I have a list made by adding items at each tick. Each item has two attributes. These attributes are important to me, as I want to select an item based on the value of its attribute.
I did something like this:
ask one-of turtles ;; turtles have cars
[ set attribute_1 ;; cars' attribute
set attribute_2 ;; cars' attribute
set mylist fput car mylist
]
I would like something like this [car1 attribute_1 attribute_2, car2 attribute_1 attribute_2, car3...].
At the moment I have [car1 car2 car3...].
Once associated the attributes to the items, I would need to pick the item with highest value from the list. The user Omarito provided me a possible solution: How to select the item with highest value in a list, but it is not completely clear to me how to pick an item up.
What I would like to ask you is if it is possible to have something like [car1 attribute_1 attribute_2, car2 attribute_1 attribute_2, car3...] or if I can only have something like
[car1 car2 car3...]
or
[[attribute_1 attribute_2] [attribute_1 attribute_2] ...].
If I write set mylist fput [(list attribute_1 attribute_2)], I receive the error message: expected a literal value.
I hope you can help me. Thanks
UPDATE: After Nicolas' answer, I edited the code as follows:
ask one-of turtles
[
hatch-cars 1[ ;; buy a new car
set attribute_1 random-float 1
set attribute_2 random-float 1
]
let this-car self
set my-list fput this-car my-list
; ask turtles [show my-list]
set new_car? true
set old_car? false
set new_car new_car + 1 ;; how could I update it after the change?
]
Am I missing something?
There are many ways to approach this problem, but I will just give you two.
Let's start with the one closest to the way you're currently trying to do things.
turtles-own [ my-list ]
to setup
clear-all
create-turtles 3 [
set my-list [] ; start with empty list
foreach range 5 [ car -> ; let's pretend cars are just numbers
let attribute-1 precision (random-float 1) 2
let attribute-2 precision (random-float 1) 2
set my-list fput (list car attribute-1 attribute-2) my-list
]
]
ask turtles [
show my-list
print " Best car by attribute 1:"
let best-by-1 last sort-by [ [a b] -> item 1 a < item 1 b ] my-list
print word " Sublist: " best-by-1
print word " Car number: " item 0 best-by-1
print " Best car by attribute 2:"
let best-by-2 last sort-by [ [a b] -> item 2 a < item 2 b ] my-list
print word " Sublist: " best-by-2
print word " Car number: " item 0 best-by-2
print "--------"
]
end
Most of this code is for creating the turtles and displaying the result, but the two key lines are:
set my-list fput (list car attribute-1 attribute-2) my-list
for adding sublists to the main list, and:
let best-by-1 last sort-by [ [a b] -> item 1 a < item 1 b ] my-list
for sorting the main list by a specific attribute taken from the sublist. You can then use item 0 best-by-1 to get the car itself.
That being said, if you want to use NetLogo to its full potential, you should probably create a car breed:
breed [ cars car ]
cars-own [
attribute-1
attribute-2
]
breed [ agents an-agent ]
agents-own [ my-list ]
to setup
clear-all
create-agents 3 [
set my-list [] ; start with empty list
hatch-cars 5 [
set attribute-1 precision (random-float 1) 2
set attribute-2 precision (random-float 1) 2
let this-car self
ask myself [ set my-list fput this-car my-list ]
]
]
ask agents [
show my-list
print " Best car by attribute 1:"
let best-by-1 max-one-of turtle-set my-list [ attribute-1 ]
print (word " " best-by-1 ", attribute-1 = " [ attribute-1 ] of best-by-1)
print " Best car by attribute 2:"
let best-by-2 max-one-of turtle-set my-list [ attribute-2 ]
print (word " " best-by-2 ", attribute-1 = " [ attribute-2 ] of best-by-2)
]
end
The max-one-of primitive makes it easy to pick the best car and everything else will also probably be easier if you're working with agents instead of lists.
Related
I would like to remove a doubt and have some help.
I have a closed world of 600X600 patches. Each patch spawns a turtle (using the sprout command). Each turtle makes a series of moves and returns a value for its home patch. I would like to have the following result: know which turtle was in each patch in the world and export this result in table form in .csv
I created a list for this. But, NetLogo is running for a while and then it closes and doesn't finish the model. And so I think if I create a table it should work. The question is: will creating a table solve the problem of the model not running? And if so, how can I create a table by generating an output from that table in .csv? But, I haven't found a NetLogo command that I can create a table to adjust my code to.
Any tip is very welcome. I thank the attention
globals [ edge-size output-turtle-visits ]
patches-own [ turtle-visits ]
to setup
ca
random-seed 1
set edge-size 599
set-patch-size 1.2
resize-world 0 edge-size 0 edge-size
let pcolors []
set pcolors [ 85 95 ]
ask patches [ sprout 1 ]
ask patches [
set turtle-visits n-values count turtles [0]
set pcolor item (random 2) pcolors
]
reset-ticks
end
to go
ask turtles [
rt random 360
fd 1
]
ask patches [
foreach [who] of turtles-here [ id ->
let current-num-visits item id turtle-visits
set turtle-visits replace-item id turtle-visits (current-num-visits + 1)
]
]
end
to output
file-open ( output-turtle-visits )
file-print ( word "id_turtle;my_xcor;my_ycor;turtle_visits" )
foreach sort patches
[
t ->
ask t
[
file-print ( word self " ; " xcor " ; " ycor " ; " turtle-visits )
]
]
file-print "" ;; blank line
file-close
end
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:
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.
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 ]
my model
of netlogo
globals [ mejor-recorrido
coste-mejor-recorrido ]
breed [ nodos nodo ]
breed [ hormigas hormiga ]
links-own [ coste
feromona ]
hormigas-own [ recorrido
coste-recorrido ]
to setup
__clear-all-and-reset-ticks
set-default-shape nodos "circle"
ask patches [set pcolor white]
crea-nodos
crea-aristas
crea-hormigas
set mejor-recorrido camino-aleatorio
set coste-mejor-recorrido longitud-recorrido mejor-recorrido
end
to crea-nodos
ask n-of num-nodos patches
[
sprout-nodos 1
[
set color blue + 2
set size 2
set label-color black
set label (word "Ciudad-" who)
]
]
end
to crea-aristas
ask nodos
[
create-links-with other nodos
[
; hide-link
set color red
set coste link-length
set feromona random-float 0.1
]
]
ask links [
if(feromona < 0.05) [die] ]
let max-coste max [coste] of links
ask links
[
set coste coste / max-coste
]
end
to crea-hormigas
create-hormigas num-hormigas [
hide-turtle
set recorrido []
set coste-recorrido 0
]
end
to reset
ask hormigas [die]
ask links [
hide-link
set feromona random-float 0.1
]
crea-hormigas
set mejor-recorrido camino-aleatorio
set coste-mejor-recorrido longitud-recorrido mejor-recorrido
clear-all-plots
end
to go
no-display
ask hormigas [
set recorrido generar-recorrido
set coste-recorrido longitud-recorrido recorrido
if coste-recorrido < coste-mejor-recorrido [
set mejor-recorrido recorrido
set coste-mejor-recorrido coste-recorrido
]
]
actualiza-feromona
tick
display
end
to-report camino-aleatorio
let resp [self] of nodos
report lput (first resp) resp
end
to-report generar-recorrido
let origen one-of nodos
let nuevo-recorrido (list origen)
let resto-nodos [self] of nodos with [self != origen]
let nodo-actual origen
while [not empty? resto-nodos] [
if (self = origen) [
ask hormigas [die]
]
let siguiente-nodo elige-siguiente-nodo nodo-actual resto-nodos
set nuevo-recorrido lput siguiente-nodo nuevo-recorrido
set resto-nodos remove siguiente-nodo resto-nodos
set nodo-actual siguiente-nodo
]
set nuevo-recorrido lput origen nuevo-recorrido
report nuevo-recorrido
end
to-report elige-siguiente-nodo [nodo-actual resto-nodos]
let probabilidades calcula-probabilidades nodo-actual resto-nodos
let rand-num random-float 1
report last first filter [first ? >= rand-num] probabilidades
end
to-report calcula-probabilidades [nodo-actual resto-nodos]
let pt map [([feromona] of ? ^ alpha) * ((1 / [coste] of ?) ^ beta)]
(map [arista nodo-actual ?] resto-nodos)
let denominador sum pt
set pt map [? / denominador] pt
let probabilidades sort-by [first ?1 < first ?2]
(map [(list ?1 ?2)] pt resto-nodos)
let probabilidad-normalizada []
let ac 0
foreach probabilidades [
set ac (ac + first ?)
set probabilidad-normalizada lput (list ac last ?) probabilidad-normalizada
]
report probabilidad-normalizada
end
to actualiza-feromona
;; Evapora la feromona del grafo
ask links [
set feromona (feromona * (1 - rho))
]
ask hormigas [
let inc-feromona (100 / coste-recorrido)
foreach aristas-recorrido recorrido [
ask ? [ set feromona (feromona + inc-feromona) ]
]
]
end
to-report aristas-recorrido [nodos-recorrido]
report map [arista (item ? nodos-recorrido)
(item (? + 1) nodos-recorrido)] (n-values num-nodos [?])
end
to-report arista [n1 n2]
report (link [who] of n1 [who] of n2)
end
to-report longitud-recorrido [nodos-recorrido]
report reduce [?1 + ?2] map [[coste] of ?] (aristas-recorrido nodos-recorrido)
end
I added
print aristas-recorrido nodos-recorrido
as the first line after to-report longitud-recorrido [nodos-recorrido]. This shows that aristas-recorrido nodos-recorrido returns a list in which some of the elements are nobody. That's what's processed by one of the lines that is generating the error you mentioned.
I believe that the problem is that in the definition of aristas-recorrido,
to-report aristas-recorrido [nodos-recorrido]
report map [arista (item ? nodos-recorrido)
(item (? + 1) nodos-recorrido)]
(n-values num-nodos [?])
end
arista attempts to report the link between subsequent nodo turtles in the list nodos-recorrido, but some of the pairs of nodos are not linked.
It looks to me like the procedure crea-aristas links every nodo with every other nodo, but then removes links with feromona < 0.05. After that, not all nodos are linked. Since nodos-recorrido above is just a randomly-ordered list of nodos (is this right?), some of the pairs of nodos are not linked, and thus arista returns nobody rather than a link for some pairs. Then this leads to the error in longitud-recorrido.
(I didn't investigate the other line that's generating the error, but I think you'll have enough information to track down that error now.)