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.
Related
I'm trying to count the number of times an agent appears in a list in netlogo. I have a list of agents (it's an output from running draws of a multinomial distribution) and I want to save the number of times an agent appears in the output list. The output is not an agentset given that agents can appear multiple times within a list. The main error that I am running into is that when I try to filter the list, it says "expected a literal value."
Note: output is the name of the list and it is saved as a patch variable. For example, "show output" gives the following:
(patch 0 0): [(turtle 44) (turtle 44) (turtle 6) (turtle 19) (turtle 33) (turtle 33)]
Not every turtle appears in the list but some turtles appear multiple times.
First, I tried the below code to get turtles to filter the output list to exclude non-self:
ask turtles-here [
show filter [i -> [i != who of myself]] [output]
let output-me-only show filter [i -> [i != who of myself]] [output] ;to create subsetted list
set number-me-appears length [output-me-only] ;to save number of times the turtle appears in the original list ("output")
show number-me-appears
]
Because that didn't work, as it gave the "expected a literal value" error, I tried the below code:
ask turtles-here [
show filter [i -> [i != self]] [output]
]
Both attempts resulted in the "expected a literal value" error.
I thought the "literal value" error may be coming up because the list is made up of turtle IDs that are not simple numbers, but are also not recognized as agents given that it is not technically an agentset. I tried converting the list to literal ID numbers using the "who" primitive, but was not successful. See below:
let converted-output []
show map [ x -> who] [output]
let converted-new-infections insert-item x
This did not work because of the "expected a literal value" again.
Thank you for your help on this!
The solution quite simple: you remove the brackets from [output]. Output is already a list so you are turning the input for your anonymous procedure into a list containing a list. As such, the anonymous procedure tries to use the entire output list as value for i.
I am currently working on sample-pooling methods, and right now, I am stuck on how to sort a group by pre-determined sizes.
So far, I was able to
1) make a list of desired group sizes and
2) sort the group with "one-of" the group sizes
, which was written as follows:
`to assign-by-size
ask hardticks [ set my-group -1]
let unassigned hardticks
let current 0
let groupsize (list 4 9 13 20 20)
while [any? unassigned]
[ask n-of (min (list one-of groupsize (count unassigned))) unassigned
[set my-group current]
set current current + 1
set unassigned unassigned with [my-group = -1]
]
end`
However, since one-of only allows you to pick a random number within the group, it does not quite perform as I wish, which is to sort the group in the order of the list, or at least use all of the predetermined groupsize in the list once.
Which function or codes should I use to make it work as I want to?
I think something like this might work. I may have a syntax error. The idea is to
first pull the next item off the groupsize list using the index you already have of "counter", and then when that's exhausted, fall back on your old test.
By the way I was very confused by your use of the word "sort" as I'm American and to me to "sort" means to put into a sequence, but I suspect you mean the slang UK meaning, what I'd call to "populate a group."
while [any? unassigned]
[
if-else current < length groupsize [
ask n-of (min (list (item current groupsize) (count unassigned))) unassigned
[set my-group current]
]
[
ask n-of (min (list one-of groupsize (count unassigned))) unassigned
[set my-group current]
]
set current current + 1
set unassigned unassigned with [my-group = -1]
]
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
I have to do some operations in netlogo using Lists. While i can do simple tasks with them i am not yet proficient enough to code my current requirements.
I have a scenario where turtles have variables called Current-Age and Previous-Age. And turtles can be born and die if they don't meet a certain threshold.
I want to implement the following formula for each patch.
Best-list = (-1/Previous-Age) * (Distance between Patch & Turtle) for all the turtles
Best = Min [ Best-list]
I know the steps involved but have been unsuccessful in coding them. Following are the steps:
Create a list with all the current turtles that are alive
Create a second list which contains the Previous-Age
Create a third list with the distance between an individual patch and each of the live turtles
Then create another list with the output from the the Best-List formula for all the turtles in the list
Finally find the Min value in the list and store the name/who# of turtle with the minimum value in a separate variable called Best-Turtle
This is the code that i tried but didn't work.
set turtle-list (list turtles)
set turtle-age-list n-values length(turtle-list) [0]
set turtle-patch-dist-list n-values length(turtle-list) [0]
set best-list n-values length(turtle-list) [0]
ask patches[
foreach turtle-list(
set turtle-age-list replace-item ?1 turtle-age-list Previous-Age of turtles with [turtle= ?1]
)
]
I couldn't proceed to the next steps since the above code itself was not correct.
Would appreciate help with the code, thanks in advance.
Regards
First, lists are probably not the simplest way to do this. However, if you must use lists for some reason, I think what you're asking for is possible. I'm not exactly sure what you mean with best- are you trying to have each patch assess which turtle is the best turtle for that patch, and store that variable in a global list? I'm going to assume that's what you mean, but if I'm misunderstanding I think you can adapt what I do here to what you need.
First, any list passed to foreach must be the same length. So, since you mean to do this per-patch, make sure that every patch calls the procedure of list creation, not just for checking the lists. Next, review the dictionary for n-values- the syntax for the reporter means you need to use the reporter you're trying to receive- using n-values length(turtle-list) [0] will just give you a list of zeroes that is the same length as the number of turtles.
So each patch needs to create these lists- make sure you either define the patches-own for the list variables, or just use let to define the lists inside the procedure. You would need a list of ordered turtles, their previous ages, and the distance from the patch calling the procedure to each turtle. Next, you can create a list that generates a value according to your formula. Then, you can use the position primitive to find the location of the minimum value in your formula-generated list and use that to index the turtle with that value.
It might look something like
to numerical
set best-turtle []
ask patches [
let turtle-list (sort turtles) ;;; list of sorted turtles
let turtle-prev-age-list n-values length(turtle-list) [ [i] -> [pre_age] of turtle i ] ;;; list of previous ages of turtles, in same order as above
let turtle-patch-dist n-values length(turtle-list) [ [i] -> distance turtle i ] ;;; list of distance from this patch to each turtle, in same order
set best-list n-values length(turtle-list) [ [i] -> ( ( -1 / ( item i turtle-prev-age-list ) ) * ( item i turtle-patch-dist ) ) ] ;;; list of calculated values for each turtle
let best-position position (min best-list) best-list ;;; gets the index of minimum value
set best-turtle lput item best-position turtle-list best-turtle ;;; adds the best turtle for this patch to the global list of best turtles
]
end
The above procedure assumes that your turtles have a pre_age variable, patches have a best-list variable, and the list of each patches 'best turtle' is held in the global variable best-turtle. From there, you can use foreach to ask turtles in the list to do something. Note that if a turtle's previous age is 0, you will get a divide by zero error.
turtles-own [age previous-age]
to-report evalfrom [_patch]
report (- distance _patch) / previous-age
end
to test
ca
crt 25 [
set age (10 + random 75)
set previous-age age - random 10
]
print min-one-of turtles [evalfrom (patch 0 0)]
end
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.