NetLogo: Adding and removing items from a list - list

Every time an agent gets a new value for some action they're performing, I want them to add it to the end of a list. If the list has ten or more items on it, I want them to remove the first item on the list, so that the list has the ten most recent values an agent has seen, in order. How might I do that? (Edit: forgot to ask an actual question.)
I want to be able to apply mathematical operations to each item on the list, so I don't want a list of cons cell-like lists, unless there's some easy way to apply mathematical operations to each item in such a list that I don't know about.

Let's build a simple example, where each turtle makes a slight right turn at a random angle at every tick, and stores the history of these angles in a list:
turtles-own [ history ]
to setup
clear-all
create-turtles 3 [
set history [] ; initialize history to an empty list
]
reset-ticks
end
to go
ask turtles [
let angle random 5
right angle
; add the angle of the most recent turn
; at the end of the list
set history lput angle history
if length history > 10 [
; remove the first item from the list
set history but-first history
]
forward 0.1
]
tick
end
I don't want a list of cons cell-like lists, unless there's some easy way to apply mathematical operations to each item in such a list that I don't know about.
I don't know what you mean by "a list of cons cell-like lists", but a simple list like the one we built here is by far the best thing you can use if you want to do math.
To apply an operation to each item, use map. And then you can use functions like sum or mean to operate on the whole list. For example:
to do-math
ask turtles [
let doubled-history map [ a -> a * 2 ] history
show history
show doubled-history
show mean doubled-history
]
end
(Note that this uses NetLogo 6.0.1 syntax.)
Let's see a demonstration:
observer> setup repeat 5 [ go ] do-math
(turtle 2): [4 3 2 1 2]
(turtle 2): [8 6 4 2 4]
(turtle 2): 4.8
(turtle 1): [4 0 1 1 4]
(turtle 1): [8 0 2 2 8]
(turtle 1): 4
(turtle 0): [2 0 4 1 0]
(turtle 0): [4 0 8 2 0]
(turtle 0): 2.8

Related

I need to get the sum of each element from a list

I have a list like that:
[[0 1 2] [4 6 9] ... [-1 0 3]]
and I need to get [3 19 ... 2], I mean sum of first element, second and .... n - element.
I´m gonna really appreciate your help.
Update: I tried with that:
to sum-first-item
let out []
ask turtles[
let sum-elem sum map first data-train
set out lput sum-elem out
]
end
Each list's item (in your case: each inner list) can be accessed by using item (see here, but also know about first and last) or as the current element of foreach (see here).
Here a bunch of ways with which you can accomplish your goal. First showing simply how to operate on each inner list, then showing how to directly build a list containing each inner list's sum:
to play-with-lists
print "The original list:"
let list-of-lists [[0 1 2] [4 6 9] [-1 0 3]]
print list-of-lists
print "Manually reporting sums:"
print sum item 0 list-of-lists
print sum item 1 list-of-lists
print sum item 2 list-of-lists
print "Building a list of sums with while loop using 'while':"
let list-of-sums []
let i 0
while [i < length list-of-lists] [
set list-of-sums lput (sum item i list-of-lists) (list-of-sums)
set i i + 1
]
print list-of-sums
print "Building a list of sums with for loop using 'foreach':"
set list-of-sums []
foreach list-of-lists [
inner-list ->
set list-of-sums lput (sum inner-list) (list-of-sums)
]
print list-of-sums
print "Building a list of sums using 'map':"
print map sum list-of-lists
end
Edit: Matteo's version with map sum the-list is the simpler solution so I suggest sticking with that. Still, it is useful to get to know reduce for when you need to do more complex calculations than summing.
Netlogo offers a few very powerful primitives to work with lists. I see you already use map, which runs a reporter for each item of a list and reports the resulting list.
Another one of those is reduce, which combines all items from a list into a single value by applying a reporter to them in turn. I suggest reading up on reduce in the dictionary and playing around with it a bit since it is not immediately obvious how it works (https://ccl.northwestern.edu/netlogo/docs/dictionary.html#reduce).
Combining these two gives you this elegant piece of code:
to try
let the-list[[0 1 2] [4 6 9] [-1 0 3]]
show map [ x -> reduce + x] the-list
;observer: [3 19 2]
end

Netlogo adding to list of lists

I am looking to add patch variable values to a list of empty lists. The patches are divided into different zones, and I'm trying to see how certain patch variables differ by zone.
I have an empty list of lists (actually contains 12 lists, but for simplicity):
set mylist [[] [] [] []]
And a list corresponding to the different zones:
set zone-list [1 2 3 4]
Here's how I'm trying to build the lists:
(foreach mylist zone-list [set ?1 lput (sum-zone-variable ?2) ?1])
to-report sum-zone-variable [ n ]
report (sum [patch-variable] of patches with [zone = n])
end
When I run this, mylist stays empty (ie unchanged). I think the problem is with the foreach statement, but I can't figure out what it is. Any help?
I can see the thinking behind foreach mylist [ set ?1 ... ], but NetLogo doesn't work that way. set ?1 ... has no effect on the original list. NetLogo lists are immutable, and ?1 is not a reference to an updatable location in a list — it's just a temporary variable into which a value has been copied. So set ?1 ... is something you will basically never write.
If I understand your question correctly, the relevant primitive here is map. This should do the job:
set mylist (map [lput (sum-zone-variable ?2) ?1] mylist zonelist)
Your basic approach is ok except that you must assign to a name. E.g.,
globals [mylist zone-list n-zones]
patches-own [zone zone-variable]
to setup
set n-zones 4
set zone-list n-values n-zones [?]
ask patches [set zone one-of zone-list]
set mylist n-values n-zones [[]]
end
to go
ask patches [set zone-variable random-float 1]
foreach zone-list [
let total sum [zone-variable] of patches with [zone = ?]
let oldvals item ? mylist
set mylist replace-item ? mylist (lput total oldvals)
]
end
However, you might want to use the table extension for this.

Ask turtles with a lot of who do something in Netlogo

now i have the next problem. Suppose i have a list with diferent numbers for example :
let mylist [3 7 12 24 32 54 21 19]
And i want to use this list of numbers like the who of turtles. More accurately , i want that only the turtles that his who is equal to of any of the numbers of the list, do a procedure. I tried to applying directly the "with" command like this: ask turtles with [who = mylist] but is not working and i think that the problem is that i am working with a list not a specific value. Any suggestions?
You can use the foreach statement and then ask every turtle with that number. Example
let mylist [1 2 3]
foreach mylist [ ask turtle ?1 [to do some stuff] ]

Netlogo: How to create a link with every turtle of a list?

I'm trying to link a recently hatched turtle from a breed (a) with the top N turtles of another breed (b). I tried many things but now I'm stuck... My last idea was to create a link from my hatched turtle to every turtle in a list, but it's not working... Here's some of my trial codes:
(I)
set rank (sort-by [[feat] of ?1 > [feat] of ?2] breed-b)
;;; creates a concatenated list of turtles from breed-b on
;;; descending order of [feat] like: [[(turtle 6) (turtle 2) (turtle 0)]]
hatch-breed-a 1 [
let n 3
;;; I want to create-link-with the top n turtles of rank
repeat n [
ask self [ create-link-with item 0 (item 0 rank) ]
set rank remove-item 1 rank
] ]
;;; my idea was to create a link with the first turtle of the list,
;;; then remove that turtle form the list before the next iteration
;;; so that the next link would be created with the turtle
;;; that was originally the second, but I receive an error message:
;;; ITEM expected input to be a string or list
;;; but got the turtle (turtle 6) instead.
(II)
set rank (sort-by [[feat] of ?1 > [feat] of ?2] breed-b)
;;; creates a concatenated list of turtles from breed-b
;;; on descending order of [feat] like: [[(turtle 6) (turtle 2) (turtle 0)]]
hatch-breed-a 1 [
let n 3
;;; I want to create-link-with the top n turtles of rank
let i 0
while [i < n] [
ask self [ create-link-with item i rank ]
set i i + 1
] ]
;;; my idea here was to create an index (i) so that the while
;;; would only take the first n items of rank, but apparently
;;; item don't accept a variable (i) only numbers.
I appreciate any help with this, thanks!
It sounds like you want the hatched to
create-links-with max-n-of n breed-b [feat]
I have found a way for code (I) to work:
repeat n [
ask self [
create-share-with (first rank) ]
set rank but-first rank
]

Error when putting variable in table, only constants allowed?

Currently I am working on a Netlogo program where I need to use nodes and links for vehicle routing problem. (links are called streets in the program)
Here I have some practical problems of how to input variable linkspeed in a table with another node. Constants like 200 etc are fine. Online I found some examples where variables are used, but I do not know why I keep getting the following error:
Expected a constant.
(or why netlogo expects a constant)
Here is the relevant piece of code:
extensions [table]
streets-own [linkspeed linktoll]
nodes-own [netw]
;; In another piece of code linkspeed is assigned successfully to the links
to cheapcalc
;; start conditions set costs very high 300000
;; state 3 unsearched state 2 searching state 1 searched (for later purposes)
ask nodes [
set i 0 set j count nodes set netw table:make
while [i < j][
table:put netw (i) [3000000 3] set i (i + 1)]]
set i 0 let k 0
ask node 35 ;; here i use node 35 as an example.
;; node 35 is connected to node 34, 36, 20 and 50
[table:put netw (35) [0 1] ;; node need to search costs to travel to itself
;; putting constants is ok.
while [i < j]
[ask my-links
[ask both-ends
[if (who != 35) [set color blue
;; set temp ([linkspeed] of street 35 who) ;; here my real goal is to put this in stat of i. but i is easier than linkspeed.
table:put netw (who) [ i 2 ]
]
] ]
set i (i + 1)] ] ;; next node for later, no it is just repetition of the same.
end
I hope somebody knows what is going on...
The problem is most likely not putting a variable in a table, but putting a variable in a list (which you're then putting in a table).
Change the line below:
table:put netw (who) [ i 2 ]
to:
table:put netw (who) (list i 2)
This - (list i 2) - allows you to generate a list with variables in it, you can't do it the other way - [i 2].
Hope this helps.