On Oct 5, 2004, at 7:53 AM, Tony Bigbee wrote:
> Is there a recommended way to dynamically remove specific Steppable
> objects from the schedule?
>
> Right now, I simply check a boolean to see whether a steppable
> instance is alive or not at the beginning of the step(). For low
> numbers of steppables and time steps, this is reasonable solution, but
> for long runs and large numbers of steppables it may add undesirable
> overhead via the main model, graphs/charts, etc. I am dynamically
> removing Steppables from a SparseGrid2D.
While leaving dead agents in the schedule until they're flushed uses up
memory, we do it the way we do because it's likely significantly faster
than manually removing them. Ordinarily a remove() from a heap is O(lg
n), but the remove requires that you know the *key*, not the *object*
being removed. In our schedule, many things can be scheduled for the
same time (the key). Without some bookeeping (which adds cost
elsewhere), removing objects from heaps is O(n) -- expensive.
If you have a very large number of objects in the heap, so many that
it's causing problems memory-wise, we can figure out some way to remove
objects from the heap. But I'd be surprised: you'd need to be looking
at millions of agents probably.
Instead, as you've said you're already doing, you should "turn off" the
Steppable so that when step() is called it it is simply ignored. If
the Steppable is being repeated, it's easy: just call stop() on the
Stoppable returned. Otherwise you have to roll your own. Perhaps you
might make up a stop() method (or name it as you like) like this:
boolean stopped = false;
public void stop() { stopped = true; }
public void step(SimState state)
{
if (!stopped)
{
// do my stuff here
}
}
...then you just call stop() and forget about the Steppable.
Hmmmm, maybe I could make a class to do that. Try this:
package sim.engine;
/**
Wraps a steppable in an easy-to-stop wrapper. This is intended for those rare
cases when you feel the need to prevent a scheduled ones-shot Steppable from firing. To
do so, wrap the Steppable in a OneShotStoppable, and schedule the OneShotStoppable.
Everything will work according to plan unless you call stop(), in which case the
Steppable will not be stepped and will instead just drop out of the schedule when
its time comes up
<p>If you need to undo the effect of stop(), you can do so with restart(). Note that
this does not reschedule the steppable or anything like that: if the Steppable's step()
method has already passted, calling restart() does not give it another chance. However,
it's reasonable to stop() a Steppable, wait for its step() time to pass, then call
restart() and reschedule the OneShotStoppable in the schedule again.
<p>OneShotSchedule is synchronized, so the stop() and step() methods can be called
in different threads (from a ParallelSequence, for example).
<p>If you're trying to stop a repeated Steppable, use the Stoppable provided by
the schedule instead.
*/
public class OneShotStoppable
{
final Steppable step;
boolean stopped = false;
public OneShotStoppable(Steppable step)
{
this.step = step;
}
public synchronized void stop()
{
stopped = true;
}
public synchronized void restart()
{
stopped = false;
}
public synchronized void step(SimState state)
{
step.step(state);
}
}
This version is synchronized; perhaps that's not necessary.
> Web tutorial 1 (how to use JFree) is excellent and got me off the
> ground quickly. Perhaps you could update the tutorial to reflect a
> newer release and the fact that the class hierarchy has changed a
> little. For example, the import statement in the section "Adding a
> line chart to the model" should now read:
>
> import org.jfree.data.xy.XYSeries;
I will ask Liviu to look at this (he wrote WebTutorial 1) when he gets
back from (dang him) Hawaii... :-)
Sean
|