matsim-org / matsim-code-examples

A repository containing code examples around MATSim
GNU General Public License v3.0
84 stars 180 forks source link

Hand-cranking MATSim externally (maybe with PlayPauseSimulationControl?) #220

Open robfitzgerald opened 5 years ago

robfitzgerald commented 5 years ago

Hello,

I have an application from which I would like to be able to boot up a MATSim simulation and then manually advance it, step by step. Something like this:

// load MATSimConfig, initialize controler, scenario; pause simulation
// store in a wrapper class which contains the controler and some
// other objects tracking simulation state
MATSimSimulation matsimSimulation = initializedSimulation()
for (simTime : AllTimes) {

  // advance MATSim by one second, triggering all events within this time window
  matsimSimulation.advance(simTime + 1)

  // take a second and do something, possibly mutating matsim state, maybe
  // involving a service that's not local
  doSomething(matsimSimulation)
}
finallyDoSomethingElse(matsimSimulation)

I expected I might be able to make this happen using PlayPauseSimulationControl, but my implementation doesn't work as expected, and I can't seem to find documentation on using PlayPauseSimulationControl. Are there examples or documentation of using PlayPauseSimulationControl to write a wrapper application which controls the advancement of a MATSim simulation externally? I saw the OnTheFlyServer/OTFLiveServer code which uses PlayPauseSimulationControl but I don't see anywhere where the control flow would 1) start a simulation (in a "paused" state), 2) advance it.

Thanks!

kainagel commented 5 years ago

Dear Rob, you are already on the right track. OnTheFlyServer has "doStep(...)", "pause()", and "play()" towards the end. Note that you need to start MATSim in a separate thread. Here: https://github.com/agentsoz/bdi-abm-integration/blob/master/integrations/bdi-matsim/src/main/java/io/github/agentsoz/bdimatsim/MATSimModel.java is another example that uses this. Please feel free to write some useful documentation and put it somewhere (preferably as a pull request for javadoc of PlayPauseSimulationControlI). Best wishes, Kai

robfitzgerald commented 5 years ago

Kai,

Thank you for the ultra-quick response! I will implement it, and once I have it working, I'll submit a PR closing this issue, with javadoc changes for PlayPauseSimulationControlI (the interface) following the style of comments I've seen in the MATSim repo.

kainagel commented 5 years ago

Thank you so much ...

robfitzgerald commented 5 years ago

is this the correct idiom for block waiting for doStep to finish (in the thread with the MATSim controler)?

int myTimeStep = 1;
playPauseSimulationControl.doStep(myTimeStep);
Semaphore access = playPauseSimulationControl.getAccess();
// blocks until doStep is completed.
access.tryAcquire(1, TimeUnit.SECONDS);
access.release();

in this way, i am relying on the PlayPauseMobsimListener in the MATSim thread to release the PlayPauseSimulationControl semaphore, so i know that MATSim is back to PAUSEing.

kainagel commented 5 years ago

Hm, that reads to technical. I am fairly sure that the "doStep(...)" does not return until the simulation has moved forward to the desired time.

If you need to run something else concurrently, and you are not too constrained in your design, I would rather put the "something else" into a separate thread and put that one into the background. If possible.

robfitzgerald commented 5 years ago

i agree it exposes too much implementation (a bit of a dive for me in fact), but, the reason i brought it up, is that PlayPauseSimulationControl doesn't seem to be offering me guarantees on how many steps it will take.

when calling doStep(time=1), i have seen two things fairly regularly:

  1. it jumps from time -1 to 08:06:00am (seems reasonable - nothing happens until then in my plans)
  2. it takes 2 time steps, i.e., moves from 08:06:9am to 08:06:11am
    • one seems to happen within the context of doStep
    • one seems to happen afterward and is not synchronized

as you can see here:

15:41:28.383 [matsim] DEBUG e.c.f.s.m.e.LocalMATSimRoutingExperiment - [MobsimBeforeSimStepListener] finding agents for routing at time 08:06:25
15:41:28.383 [matsim] DEBUG e.c.f.s.m.e.LocalMATSimRoutingExperiment - [MobsimBeforeSimStepListener] at time 08:06:25 has no route requests
15:41:28.384 [matsim] DEBUG e.c.f.s.m.e.LocalMATSimRoutingExperiment - [MobsimBeforeSimStepListener] finding agents for routing at time 08:06:26
15:41:28.384 [main] DEBUG e.c.f.s.m.e.LocalMATSimRoutingExperiment - trying to acquire
15:41:28.384 [main] DEBUG e.c.f.s.m.e.LocalMATSimRoutingExperiment - releasing access as done=true

my code overwrites agent routes using WithinDayAgentUtils. my research problem looks at gains from solving multiple routes simultaneously to capture their route externalities, which is why i am doing custom listeners instead of simply writing my own MATSim Router (which is scoped to a single agent).

i am using MATSim from the master branch about 1 month ago (I can try and track down the commit if that's important).

this may have just turned into a bug report for the matsim-org/matsim repo. or, i'm just doing it all wrong 😸.

robfitzgerald commented 5 years ago

If you need to run something else concurrently, and you are not too constrained in your design, I would rather put the "something else" into a separate thread and put that one into the background. If possible.

yes, that was my initial implementation. but i was hoping to make my "something else" the first-class citizen, if possible, as i am making the underlying simulation engine abstract.

kainagel commented 4 years ago

Dear Rob, this is too far away from anything that we currently have funding for, and in consequence I cannot help you beyond what I have already said. Hopefully you can sort it out yourself, or others will chip on. Please keep us posted, best wishes, Kai

robfitzgerald commented 4 years ago

Absolutely. I am having some success. If I get my implementation to the point that I find it worthy of sharing, I will update with a PR as discussed.

kainagel commented 4 years ago

Thanks ...