When I run this code:
to myself1
create-turtles 1
let a "a"
ask turtle 0 [
show a
show self
ask patch-here [
show a
show self
show myself
]
]
end
I get this output:
(turtle 0): "a"
(turtle 0): (turtle 0)
(patch 0 0): "a"
(patch 0 0): (patch 0 0)
(patch 0 0): (turtle 0)
So inside the ask patch code block self refers to the patch, and myself refers to turtle 0.
This is what the NetLogo user manual (and example code) lead you to expect.
It's not clear to me why self should refer to the patch rather than to turtle 0.
Admittedly it's been a long time since I've written any Java, but my understanding is that this in an anonymous function refers to the object in which the function is embedded. In contrast, self in the code above refers to whichever patch is running the code -- rather than to the turtle in which self appears lexically. In addition, the local variable a is accessible from within the code block.
The decision to make self local to the code block, presumably to provide a way to refer to the agent that is executing the block, required that NetLogo define another way to refer to the calling context. That is the function of myself, as the example output shows.
More generally, it seems that myself refers to the calling turtle even when used in a separate function.
to myself2
let a "a"
ask turtle 0 [
show a
show self
ask patch-here [ myself2' ]
]
end
to myself2'
; show a
show self
show myself
end
The output is:
(turtle 0): "a"
(turtle 0): (turtle 0)
(patch 0 0): (patch 0 0)
(patch 0 0): (turtle 0)
So myself is accessible from a separate function and refers back to the calling turtle. But the variable a, which would seem to be similar is not accessible. If show a were not commented out, NetLogo would issue an error message saying that a is not defined in myself2'. (In other words, NetLogo does not implement dynamic scoping in general even though these examples seem to suggest it does for self and myself.)
So, sorry for the long preliminary. My question is about the best way to explicate the quasi-dynamic scoping used for self and myself but not for local variables like a. Is it fair to say that self and myself are simply ad hoc special cases, or is there a better way to talk about it?
Great question.
The concepts that self and myself represent simply don't exist in other programming languages. Other programming languages just don't have the concept of "the agent executing this code", because the languages are not agent-based in the first place.
Any analogy with this in OO languages is distant at best and actively misleading at worst.
self and myself are both extremely useful as defined and if they weren't present in the language, with the definitions they have, you'd be in big trouble trying to code all sorts of things. That's the best short answer I can give to why they're defined as they are: they're useful.
As for the scoping behavior of local variables such as a, I think that's a separate question. You could certainly imagine trying to come up with some kind of agent-based definition of local variables, where a would be analogous to temporarily creating an agent variable. It isn't obvious to me whether such a design might be workable or even desirable, but in any case, we didn't do it that way and I don't think we ever even seriously explored the possibility.
Local variables in NetLogo work exactly the same as local variables in other lexically scoped languages. They don't participate in the agent-based nature of the language.
Related
I switched gears from yesterday and now have a workable solution to the pairs problem I posted. However, now I am being defeated by the simplest of issues. I keep getting a mixture of errors. 1)Maketerrain is the first module that runs on setup. It errors saying I can't use maketerrain in an observer context because it patch/turtle only. I've never had a module give such an error, and I use modular code-writing routinely. So this is completely flummoxing me. 2)Wherever I put "tick" (end of go, start of go, middle of go, in some other procedure) further breaks the code, with the same error--"tick is observer and thus will not run because this is X context." I have checked brackets and parentheses more than a dozen times--taking a break and coming back at it fresh to see if I missed something. No errors there that I have been able to find. I am using Netlogo 6.1.1. I am now dizzyingly confused.
Rather than post another lengthy set of code at this juncture, I want to take another few cracks at it myself. So I am asking, can anyone possibly offer a principle or two I can use to try to debug this? Like, what establishes context? What can I do to make the context be what I want and not what gets "implied" by earlier commands? How can I use a module in which patches and turtles do something to set themselves up and still have it run on setup? (Note--moving stuff to the interface did not solve the problem.) What sets the "go" procedure context, what should it be to run, and what can someone do to make it be what it needs to be? What do I do to place tick--a command I have never had problems with before--correctly?
I have scoured stackoverflow, netlogo manual pages and programming guide, books I have, and still cannot debug what seems to be a very very very simple issue.
Have a look at the first few lines of the Maketerrain procedure. NetLogo interprets the context from the primitives used. If the first line is something like:
set color red
then NetLogo 'knows' that this is a procedure to be run by turtles (that is, it is turtle context) because only turtles can set color because color is a turtle variable. If, however, it starts:
ask turtles
[ set color red
then it is observer context because the external 'observer' instructs turtles to do things (roughly).
Context is actually an incredibly important concept in NetLogo programming - as you do something like the following, you are constantly changing context:
to demo
ask patches
[ ask one-of turtles-here
[ set color red
]
]
end
It starts in the observer context, then iterates through the patches doing something. In a sense, it is thinking like a patch (and is in patch context). Then you open the next code block with [ and switch to the turtle context so that 'I' (a randomly selected turtle on the current patch) can change colour. Then each ] to end a code block backs out of the layers of context.
I'm trying to create a variable in Netlogo that changes based on its value last tick. I've followed this question thread in how to create such a variable, but I'm having a bit of trouble creating the initial conditions, because at tick=0, there is no myvar-last-tick because there was no last tick, so Netlogo autosets myvar-last-tick to 0. How can I create myvar and myvar-last-tick such that when tick=0, myvar-last-tick is the same as myvar only at tick 0? To be clear I would like to program the variables such that they follow a pattern like
this, although for my actual program the rate of decline would not be constant like in this example.
Before you call your go procedure (i.e., your schedule), you should call a setup procedure. Usually, the very first thing your setup procedure should do is all of your global-variable initializations (perhaps by calling a setup-globals procedure). You can initialize myvar-last-tick and myvar to anything you like. Just make sure the the result of your first call to go will produce the starting outcome you want.
.nlogo file
I am getting this error while running iterations using behavior space
The tick counter has not been started yet. Use RESET-TICKS.
error while observer running TICKS
called by procedure __EVALUATOR
I am not sure why this is happening. I have included reset-ticks in the "set" routine.
In addition in the behavior space dialog wizard, i also included reset-ticks as the final command to be executed. Yet i am getting this error.
Below is my setup and go code:
to setup
clear-all
setup-citizens
setup-parties
update-support
reset-ticks
end
to go
ask parties [ adapt set my-old-size my-size ]
update-support
election
plot-voter-turnout
plot-volatility
if (Turnout-100%? = false) [plot-citizen-comparison]
tick
end
You are using ticks in your BehaviorSpace experiment's "stop condition", so I think it's nearly certain that's where the "error while observer running TICKS" error must be coming from, given that the stack trace doesn't refer to a procedure name.
Here's my best guess at what's going on here: under some conditions, your setup procedure fails, and therefore never reaches the call to reset-ticks at the end of setup. Then BehaviorSpace tries to run your stop condition, resulting in the error you see.
This guess has some problems:
Why BehaviorSpace would only be showing you the eventual ticks error, and not the error causing setup to fail, I don't know.
I have no idea why your setup procedure would be failing.
Nonetheless, that's the best I can offer you without doing a more in-depth investigation.
I was facing the same issue not too long ago. I'm pretty sure that the issue goes back to how Netlogo shares the global variables/states among the threads. I suspect that one thread starts the go procedure while another thread hasn't called the reset-ticks yet.
A temporary fix to this is to call reset-ticks if it hasn't been called already at the beginning of your go procedure.
carefully [let t ticks][reset-ticks]
For those people who found this question by searching for the error "The tick counter has not been started yet. Use RESET-TICKS." but are not actually using BehaviorSpace - the question (and therefore the accepted answer) does not apply to your situation. Instead, you have almost certainly forgotten to initialise the model before trying to run it, probably by hitting the go button without first hitting the setup button.
The reset-ticks command starts the tick counter (makes the internal clock available) so that the tick command can advance the clock. By convention, a procedure named setup has all the commands to initialise the model, including reset-ticks, creating turtles etc. Similarly, a procedure called go contains all the commands to actually run the model like moving turtles around, including tick. Also by convention, these procedures are run by pressing buttons named setup and go respectively.
I have a *.shp file that I've upload and i'm using as part of my model (calculating shortest paths). This is quite a big shape file with thousands of road links and intersections and bridges represented by nodes. I was hoping to speed up the running of behavior space by not loading this map every time, and so created a separate procedure for loading the map and defining link weights etc. In this procedure I have clear-all - reset ticks so everything is effectively wiped if i load a new map. In the setup i define turtle attributes for each run. Between each run I use clear-all-plots and clear-output, and reset-ticks. When i run this model behavior space starts to run slowly after a few setups, even with a table output. However, if i combine the load-map and setup-files together i.e. the map is load for every new behavior space run, then the speed is maintained throughout.
Example - runs slow, but the maps is not reloaded everytime
to-load-map
Clear-all
... code for loading map
reset-ticks
end
to-setup-model
clear-all-plots
clear-outputs
... code for setting up turtle variables
reset-ticks
end
Example (maintains speed - but has to load map)
To-setup
clear-all
...code for loading map
...code for setting up turtle variables
reset-ticks
end
My question: am i missing something that would help to speed things up while not having to reload the map?
Not knowing anything else about your model, I wonder if you essentially have a "memory leak" with lots of information accumulating in global variables that are not getting purged every time by the to-setup-model procedure. Are there perhaps other global variables you can explicitly reinitialize in to-setup-model that might help free up some of this space? For instance, do you have large tables hanging around between runs that only gain more key-value pairs and never get trimmed back down? Just a thought.
I almost always define a clear-most procedure that clears everything out except the big data I don't want to load/compute every time. Unfortunately, that means I must list the variables to initialize out in detail, but I like to free as much as possible between runs to keep things speedy.
-- Glenn
I've recently learned Haskell, and am trying to carry the pure functional style over to my other code when possible. An important aspect of this is treating all variables as immutable, i.e. constants. In order to do so, many computations that would be implemented using loops in an imperative style have to be performed using recursion, which typically incurs a memory penalty due to the allocation a new stack frame for each function call. In the special case of a tail call (where the return value of a called function is immediately returned to the callee's caller), however, this penalty can be bypassed by a process called tail call optimization (in one method, this can be done by essentially replacing a call with a jmp after setting up the stack properly). Does MATLAB perform TCO by default, or is there a way to tell it to?
If I define a simple tail-recursive function:
function tailtest(n)
if n==0; feature memstats; return; end
tailtest(n-1);
end
and call it so that it will recurse quite deeply:
set(0,'RecursionLimit',10000);
tailtest(1000);
then it doesn't look as if stack frames are eating a lot of memory. However, if I make it recurse much deeper:
set(0,'RecursionLimit',10000);
tailtest(5000);
then (on my machine, today) MATLAB simply crashes: the process unceremoniously dies.
I don't think this is consistent with MATLAB doing any TCO; the case where a function tail-calls itself, only in one place, with no local variables other than a single argument, is just about as simple as anyone could hope for.
So: No, it appears that MATLAB does not do TCO at all, at least by default. I haven't (so far) looked for options that might enable it. I'd be surprised if there were any.
In cases where we don't blow out the stack, how much does recursion cost? See my comment to Bill Cheatham's answer: it looks like the time overhead is nontrivial but not insane.
... Except that Bill Cheatham deleted his answer after I left that comment. OK. So, I took a simple iterative implementation of the Fibonacci function and a simple tail-recursive one, doing essentially the same computation in both, and timed them both on fib(60). The recursive implementation took about 2.5 times longer to run than the iterative one. Of course the relative overhead will be smaller for functions that do more work than one addition and one subtraction per iteration.
(I also agree with delnan's sentiment: highly-recursive code of the sort that feels natural in Haskell is typically likely to be unidiomatic in MATLAB.)
There is a simple way to check this. Create this function tail_recursion_check:
function r = tail_recursion_check(n)
if n > 1
r = tail_recursion_check(n - 1);
else
error('error');
end
end
and run tail_recursion_check(10), for example. You are going to see a very long stack trace with 10 items that says error at line 3. If there were tail call optimization, you would only see one.