NetLogo does not have a native SWITCH, SWITCH-CASE, or SELECT-CASE type of multiple condition, how do I do the same thing without having a giant mess of nested IF-ELSE statements?
Since NetLogo 6.1, NetLogo has supported multi-case ifelse, which can be used similarly to other languages' switch statements. Here is an example from the docs:
ask patches [
let choice random 4
(ifelse
choice = 0 [
set pcolor red
set plabel "r"
]
choice = 1 [
set pcolor blue
set plabel "b"
]
choice = 2 [
set pcolor green
set plabel "g"
]
; elsecommands
[
set pcolor yellow
set plabel "y"
])
]
And here is the example from the other answer rewritten to use it:
;; example of SWITCH style conditional block
(ifelse
(criteria-1) [ action-1 ]
(criteria-2) [ action-2 ]
(criteria-3) [ action-3 ]
[ default-action ]
)
This does not need to have the "multi-close" of the ] on the last line, so it overall seems cleaner to me.
We can simulate a SWITCH statement with a chain of nested IF-ELSE statements, formatted so it's not a big mess, and actually easy to read and edit.
We will format the chain of IF-ELSE statement with the following goals:
avoid excessive indenting,
avoid overly long code lines
make it look more like switch in other languages
rearranging the cases does not break the syntax
there is a default case
A SWITCH Statement
Here's how it looks:
;; example of SWITCH style conditional block
if-else [ criteria 1 ] [ action-1 ][
if-else [ criteria 2 ] [ action-2 ][
if-else [ criteria 3 ] [ action-3 ][
if-else [ true ] [ default-action ][
]]]]
Other considerations
Some programmers may find it offensive to have a default action that tests for true, and leaves the "else block" if the final "IF" empty. You can do what you like. I find making the default case explicit, makes all the actions formatted exactly the same, and avoids an awkward cluster of punctuation at the end.
Avoid overly long lines--it makes it harder to read
Keep conditions short--wrap them in reporter if needed.
Keep actions short--wrap them in procedures if needed.
This helps the code read more like a story and less like code.
Related
The following doesn't work (there must also be a more succinct way of doing it):
ask turtles
[
ifelse return > 0
[
set tot-demand-contrarians (-(tot-demand-contrarians))
set tot-demand-followers ((tot-demand-followers))
]
[
set tot-demand-contrarians ((tot-demand-contrarians))
set tot-demand-followers (-(tot-demand-followers))
]
]
Half of your clauses set a variable to itself anyway so they're not needed. I suspect NetLogo is reading the '-' as an instruction to subtract, but you haven't said what to subtract it from. You could do something like:
set x (0 - x) ; the brackets are optional, for clarity
But personally I feel that it is more readable to multiply by -1
ask turtles
[ ifelse return > 0
[ set tot-demand-contrarians (-1 * tot-demand-contrarians) ]
[ set tot-demand-followers (-1 * tot-demand-followers) ]
]
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
I am working with quite a lot of runs and most of them will be aborted. Can I write a Final Command that deletes aborted runs in order to speed up the process and/or make my csv files smaller?
There is nothing allowing you to do that in a straightforward way. And it wouldn't really speed things up anyway.
Unless the size of your csv files is really a problem, the easiest thing is just to filter out aborted runs in whichever data analysis program you use.
The only alternative I can think of is to write your own experiment code. Assuming you have a stop-condition? reporter and you set aborted? true when a run is aborted, you could do something along the lines of:
extensions [ csv ]
globals [ aborted? ]
to experiment
let run-number 1
let file-name "experiment.csv"
if file-exists? file-name [ file-delete file-name ]
file-open file-name
foreach [ 1 2 3 ] [ ; vary x
set x ?
foreach [ "a" "b" "c" ] [ ; vary y
set y ?
set run-number run-number + 1
setup
while [ not stop-condition? ] [ go ]
if not aborted? [
file-print csv:to-row (list
run-number
x
y
(count turtles)
; whatever else you want to measure...
)
]
if run-number mod 10 = 0 [ file-flush ]
]
]
file-close-all
end
This assumes that x and y are, respectively, a slider and a chooser widget. If you want to vary global variables, you'll have to be careful not to override them with a call to clear-all in setup.
As you can see, all of this is far from ideal and probably error-prone.
My first netlogo program was working well, but now is failing since 'tick' in the 'go' method is not in a valid context.
Please see the attached code, line 99, which generates:
You can't use tick in a turtle/patch context, because it is observer only.
Code is here:
http://jpark.us/temp/CSSS.v1.nlogo
Problem solved...
I was trying to 'set number.sparrows...' down in other methods, but not within a proper patches context.
So this works:
if all? patches [ eggs.laid = true ] [
ask patches [ set number.sparrows count sparrows-here ]
whereas this does not:
if all? patches [ eggs.laid = true ] [
set number.sparrows count sparrows-here
The compiler posts " If expected 2 inputs , a true/false and a command block". How should this code be changed to avoid this?
if EDIT_TOOL = "Road" ask patches[set pcolor black]
end
if EDIT_TOOL = "Road"
[
ask patches[set pcolor black]
]
A block is defined by "[" and "]". In netlogo unlike in 'c' like languages they are not optional even for single expressions.
"End" is only used at the end of procedures.