I just started to learn Netlogo. I followed the code written by Lynne Hamill and Nigel Gilbert
when I finished, it reminded me that "nothing named ? has been defined".
foreach xs [
create-traders 1 [
set shape "house"
setxy ? 0
set color red
; give each trader some knids of produce to sell
set stock n-of n-items-stocked fruit-and-veg
]
]
Any ideas?
As Jasper notes in the comments, the ? is outdated syntax. Something like this should work - instead of an implicit ?, you iterate with an explicit variable (named this-x in the example below) and use that variable name wherever relevant.
foreach xs [ this-x -> ; name the variable here and add the arrow
create-traders 1 [
set shape "house"
setxy this-x 0 ; use that variable name
set color red
; give each trader some knids of produce to sell
set stock n-of n-items-stocked fruit-and-veg
]
]
You can think about it as equivalent to the conceptual loop "for each item in the list, call it 'this-x' and do something (everything after ->), replacing the 'this-x' in the code with whatever item is in the list at the moment".
Related
The following might be a basic programming question for Netlogo.
I'd like to write generic reporters that I can supply arguments for what they should report on. Suppose the following program:
turtles-own [
houses
cars
]
to setup
clear-all
create-turtles 10
reset-ticks
end
to go
ask turtles [
set houses houses + random 2
set cars cars + random 5
]
tick
end
I can write a reporter on the mean of houses as such:
to-report mean-houses
report mean [ houses ] of turtles
end
But I'd like to have a generic reporter that I can also use to report the mean of cars, like so:
to-report means [ param ]
report mean [ param ] of turtles
end
However this does not work as intended:
setup
repeat 15 [go]
show means houses
> ERROR: You can't use HOUSES in an observer context, because HOUSES is turtle-only.*
How can I have Netlogo evealuate param in the context of turtles in such an instance? I am familiar with how to do this in R (e.g., via tidy evaluation masking with {{ x }}, or the earlier quoting mechanism), but unfamiliar with how to translate this to Netlogo.
As the error states, you are trying to pass a turtle-only variable (houses) to a procedure that is being used in observer context which doesn't work because Netlogo will try passing the variable to the procedure before actually running the procedure.
Instead, you could use the following code. With this example, you first use the "of"-primitive to extract the houses/cars variables as a list. Only then do you pass them to the "means"-procedure, which is being run by the observer.
to-report means [ param ]
report mean param
end
show means [houses] of turtles
show means [cars] of turtles
The NetLogo Way
<reporter> [ <expression> ] of <agentset>
Note: I use "agents" below, since this answer applies to any NetLogo agent, be it turtles, turtle breeds, patches, or links.
Rather than passing an agent variable (or expression) to a procedure and then somehow make the agents make a list and then act on the list, NetLogo makes it easy to first make the list from an expression evaluated individually by every agent in an agentset, so you can pass that list to some reporter. The syntax (as you know) is:
;; return list of <expression>
;; calculated by each member of agentset
[ expression ] of agentset
So, if this is your reporter:
to-report gini [ samples ]
;; samples will be sorted here, don't pre-sort!
;; best guess -- please correct if wrong
;; source:
;; https://en.wikipedia.org/wiki/Gini_coefficient#Calculation
let n length samples
let indexes (range 1 (n + 1))
let s1 2 * sum (map [[i y] -> i * y] indexes sort samples)
let s2 n * sum samples
let G (s1 / s2) - ((n + 1) / n)
report G
end
Then you might calculate the gini for your various measures like this:
print gini [ measure-1 ] of turtles
print gini [ measure-2 ] of turtles
print gini [ measure-3 ] of turtles
Which makes sense, since gini is a function that takes a set of samples. And this lets you easily use other sub-populations or breeds or whatever.
"Abbreviated" Syntax
I am about to lead you "down the garden path," so if you like what you've seen so far, you can stop here. If you want a little chuckle, read on.
Perhaps the above is just too verbose for you, and you really, really, want to get rid of "of turtles?" (even though you might later want to apply the generic function even more generically to sub-populations?)
Well, you could. We could write it using an "anonymous reporter":
print gini [-> houses ]
And then gini might look like this:
to-report gini [ sample-expression ]
let samples sort [ run-result sample-expression ] of turtles
;;; ... the rest of your gini function here
report G
end
OK, but you've embedded "of turtles" in your function. But what if later you want to evaluate this function for some sub-population or perhaps use patches instead of turtles?
You might fix that by taking the agentset as an input, as well.
to-report gini [ anon-reporter source ]
let samples [ run-result anon-reporter ] of source
;; etc
end
and then write:
print gini [-> measure-1 ] turtles
print gini [-> measure-2 ] turtles
print gini [-> measure-3 ] turtles
Ugh, a bit awkward. Let's add a little syntax candy:
to-report of_ [ agents ] report agents end
NOW we can write:
print gini [-> measure-1 ] of_ turtles
print gini [-> measure-2 ] of_ turtles
print gini [-> measure-3 ] of_ turtles
Oh, Dear. That looks rather familiar, doesn't it? But rather more verbose than when we started.
So now we are back to:
print gini [ measure-1 ] of turtles
You can use runresult, provided you are happy to pass the procedure's argument as a string:
to-report means [varname]
report mean [runresult varname] of turtles
end
Trying it in the Command Center:
observer> setup
observer> repeat 15 [go]
observer> show means "houses"
observer: 7.4
I'm currently building a multi level ABM using Levelspace. I am also using the extrawidget extension as a frontend GUI for entering and capturing user information. The extrawidget GUI is a stand alone Netlogo model and serves as the parent model in Levelspace. Some of the captured information is stored as lists in the parent models global variables.
I am trying pass the content of the extrawidget parent model global variables (particularly the lists) to the child model's global variables. I cannot seem to find a way to accomplish this. I've tried "ls:let" in conjunction with "ls:ask" to set the child models global variable but that did not work. I used "ls:assign" but that was unsuccessful also.
I believe some kind of reporter in both the parent and child model may be the answer but I am unable to determine how to code something like that.
Could someone please assist me in solving this problem.
Thanks
Rudy
--------------------------------------------------------Follow-Up---------------------------------------------------
I discovered that ls:assign did work, "clear-all" in the child model's setup command wiped out the information in global variables. I removed the "clear-all" and can see the lists in monitors I added for the global variables but even though the lists are there I'm still getting this error message when the child model attempts to run "setup"
" Extension exception: Model 0 (Scaled Agile Simulator1.nlogo) encountered an error: ITEM expected input to be a string or list but got the number 0 instead.
error while observer running LS:ASK
called by procedure SETUP
called by procedure __EVALUATOR"
I have included the child model setup code below:
to setup
ls:reset
;clear-all
let n length TotEpics
foreach n-values n [ [i] -> i ] [ [i] ->
create-Epics 1 [
setxy -20 20
set label item i TotEpics
set Complex item i EpicCmplx
set Stories item i EpicStories
set ETime [ ]
set Tasks1 EpicTasks1
set Tasks2 EpicTasks2
set Tasks3 EpicTasks3
set Tasks4 EpicTasks4
set shape "box"
set size 8
]
]
let o length ScrumTN1
foreach n-values o [ [i] -> i ] [ [i] ->
create-Scrum-Teams 1 [
set label item i ScrumTN1
set shape "Scrum"
set color color
set Members item i ScrumTM1
set Strat item i ScrumStrt1
set AsgnEpic item i ScrmEpic1
set S-Stories 0
set Cost item i ScrumCst1
set Value [ ]
set Time [ ]
set S-Story-Size 0
set xcor -16
set ycor 12 + i * -7
set size 4.5
ls:create-interactive-models 1 "Problem_Solving_in_Networks WIP.nlogo"
set model-id last ls:models
ls:hide model-id
]
]
let b length ScrumTN2
foreach n-values b [ [i] -> i ] [ [i] ->
create-Scrum-Teams 1 [
set label item i ScrumTN2
set shape "Scrum"
set color item i Color1
set Members item i ScrumTM2
set Strat item i ScrumStrt2
set AsgnEpic item i ScrmEpic2
set S-Stories 0
set Cost item i ScrumCst2
set Value [ ]
set Time [ ]
set S-Story-Size 0
set xcor -4.5
set ycor 12 + i * -7
set size 4.5
ls:create-interactive-models 1 "Problem_Solving_in_Networks WIP.nlogo"
set model-id last ls:models
ls:hide model-id
]
]
let p length KanbanTN3
foreach n-values p [ [i] -> i ] [ [i] ->
create-Kanban-Teams 1 [
set label item i KanbanTN3
set shape "Kanban"
set color color
set xcor -18 + i * 9
set ycor -20
set size 4.5
ls:create-interactive-models 1 "Kanban3_v5_2.nlogo"
set model-id last ls:models
ls:hide model-id
]
]
All the "variables" in "set variable-name item i variables" are lists so I'm not expecting to see the error message stating "ITEM expected input to be a string or list but got the number 0 instead"
Anyone have any insights?
Thanks
Rudy
---------------------------------------------Please Disregard until further notice-----------------------------------
I've discovered some missing code in my setup command causing this "ERROR". Please disregard my question. If I run into any serious roadblocks I'll reach out.
Thanks
Very basic question, I can't see why my foreach code doesn't do anything (no error message but no effect whatsoever). So my turtles have a 3-dimensionnal variable (intention) that is preset to [0 0 0]. My final problem is much more complex than this, but in simple terms I am now trying to get every dimension of this vector to change to one, that is [1 1 1].
I have created a procedure called change-intention that uses foreach to produce this, to no effect:
to change-intention
ask turtles [
(foreach intention [ x -> set x 1])
]
end
I have tried this on the observer & turtle command line as well as on individual turtles' to no results nor errors..
Thanks!
Several problems. The first is that lists are not mutable - if you want to change the value in a list, you have to create a new list with that value. The second is that you can't use set to do that, you have to use replace-item.
The code is self contained - open a new model and try it out, changing the call in the testme procedure to different implementations. The procedure change-intention1 is the way you are currently thinking about it (my interpretation anyway). The procedure change-interpretation2 is the way to implement your approach, replacing each item and creating the new list (addressing the problems identified).
However, a better way to do this is with the map procedure instead of foreach because all the values are changed at once rather than looping through the list and dealing with each. Of course, that may not be so easy to implement in your real model.
turtles-own [intention]
to testme
clear-all
create-turtles 1
[ set intention [0 0 0]
]
ask turtles [ type "before call:" print intention ]
change-intention2
ask turtles [ type "after call:" print intention ]
reset-ticks
end
to change-intention1
ask turtles
[ foreach intention
[ x ->
print "here"
set intention 1
]
]
end
to change-intention2
ask turtles
[ foreach intention
[ x ->
let pp position x intention
type "here:" print pp
set intention replace-item pp intention 1
]
]
end
to change-intention3
ask turtles
[ set intention map [ x -> 1 ] intention
]
end
Is it possible to have enumerated data types in NetLogo?
Let's say that I have a model of marital status change.
An agent can have 3 marital status states: single, married, divorced.
I would like to map those states into numbers so that it takes less memory when executed.
single = 1
married = 2
divorced = 3
so that I can just do
ask agents with [ marital-status = single ][ get-married ]
I have found a trick to do that with "to-report"
eg:
to-report single
report 1
end
But this means I have to create many to report functions if I were to have many categories in many variables. Is there a better workaround than this?
Thanks :)
How big is your model? My understanding is that an agent attribute is minimum 8 bytes anyway (see https://github.com/NetLogo/NetLogo/wiki/Optimizing-NetLogo-Runs)
I can't think of a natural way to do this. However, if you really wanted to, this workaround would work: store the marital status as 0, 1, 2. Also store a global variable called marriage-status-map and use the item primitive. So it would look like this:
globals [ marriage-status-map]
turtles-own [ marriage-status ]
to testme
clear-all
set marriage-status-map ["single" "married" "divorced"]
create-turtles 10
[ set marriage-status random 3
setxy random-xcor random-ycor
set color blue
]
ask turtles with [item marriage-status marriage-status-map = "single"] [set color red]
end
I have small issue with a NetLogo tutorial.
I have the following situation:
to-report get-best-action
let x xcor
let y ycor
let dir heading
let best-action 0
let best-utility -100000
foreach actions[
set heading dir
run ?
let utility-of-action get-utility xcor ycor heading
if (utility-of-action > best-utility) [
set best-action ?
set best-utility utility-of-action
]
setxy x y
set heading dir
]
report (list best-action best-utility)
end
AND...
ask patches [
foreach headings [
let x pxcor
let y pycor
let dir ?
.......
In any of the presented case, the identifier '?' is considered not defined. It should work because the identifier is used the same way even in the examples of foreach. Check https://ccl.northwestern.edu/netlogo/docs/programming.html .
Did I do something wrong? Does anybody know another solution, because I tried to use an item i and the behavior of the project has been modified. (Check the project: https://www.youtube.com/watch?v=dBDVkPjyYF4 )
I would appreciate your help. Thank you!
In NetLogo before version 6, the symbols ? ?1 ?1 and so on were used as placeholders in some primitives, especially those that processed list items.
In version 6 a new syntax was introduced using "anonymous" procedures. You can make your old code using ? or ?1, etc work with few changes by adding the new syntax elements to the statement block.
Title
Code
Single ? placeholder
Extra space added to emphasize changes
Old syntax
foreach [ 1 2 3 4 ] [ show ? ]
New syntax
foreach [ 1 2 3 4 ] [ ? -> show ? ]
Multiple ?1 ?1 placeholders
Extra space added to emphasize changes
Old syntax
(foreach [1 2] ["a" "b"][ show (word ?1 ?2)]
New syntax
(foreach [1 2] ["a" "b"][ [?1 ?2] -> show (word ?1 ?2)]