MATSIM
AbstractController.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * *
4  * *********************************************************************** *
5  * *
6  * copyright : (C) 2012 by the members listed in the COPYING, *
7  * LICENSE and WARRANTY file. *
8  * email : info at matsim dot org *
9  * *
10  * *********************************************************************** *
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * See also COPYING, LICENSE and WARRANTY file *
17  * *
18  * *********************************************************************** */
19 
20 package org.matsim.core.controler;
21 
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.Logger;
25 import org.matsim.core.config.Config;
30 
31 import java.io.UncheckedIOException;
32 
33 /*package*/ abstract class AbstractController {
34  // we already had one case where a method of this was removed, causing downstream failures; better just not
35  // offer it at all; framework with injector should now be flexible enough. kai, mar'18
36 
37  private static final Logger log = LogManager.getLogger(AbstractController.class);
38 
39  private OutputDirectoryHierarchy controlerIO;
40 
41  private final IterationStopWatch stopwatch;
42 
43 
47  private ControlerListenerManagerImpl controlerListenerManagerImpl;
48 
49 
50  private Integer thisIteration = null;
51 
52  protected AbstractController() {
53  this(new ControlerListenerManagerImpl(), new IterationStopWatch(), null);
54  }
55 
56  AbstractController(ControlerListenerManagerImpl controlerListenerManager, IterationStopWatch stopWatch, MatsimServices matsimServices) {
57  log.info("Used Controler-Class: " + this.getClass().getCanonicalName());
58  this.controlerListenerManagerImpl = controlerListenerManager;
59  this.controlerListenerManagerImpl.setControler(matsimServices);
60  this.stopwatch = stopWatch;
61  }
62 
63  private void resetRandomNumbers(long seed, int iteration) {
64  MatsimRandom.reset(seed + iteration);
65  MatsimRandom.getRandom().nextDouble(); // draw one because of strange
66  // "not-randomness" is the first draw...
67  // Fixme [kn] this should really be ten thousand draws instead of just one
68  }
69 
70  final void setupOutputDirectory(OutputDirectoryHierarchy controlerIO) {
71  this.controlerIO = controlerIO;
72  OutputDirectoryLogging.initLogging(this.getControlerIO()); // logging needs to be early
73  }
74 
75  protected final void run(final Config config) {
77  MatsimRuntimeModifications.MyRunnable runnable = new MatsimRuntimeModifications.MyRunnable() {
78  @Override
79  public void run() throws MatsimRuntimeModifications.UnexpectedShutdownException {
80  loadCoreListeners();
81  controlerListenerManagerImpl.fireControlerStartupEvent();
82  ControllerUtils.checkConfigConsistencyAndWriteToLog(config, "config dump before iterations start" );
83  prepareForSim();
84  doIterations(config);
85  }
86 
87  @Override
88  public void shutdown(boolean unexpected) {
89  controlerListenerManagerImpl.fireControlerShutdownEvent(unexpected, thisIteration == null ? -1 : thisIteration);
90  }
91  };
92  MatsimRuntimeModifications.run(runnable);
95  }
96 
97  protected abstract void loadCoreListeners();
98 
99  protected abstract void runMobSim();
100 
101  protected abstract void prepareForSim();
102 
103  protected abstract void prepareForMobsim() ;
104 
113  protected abstract boolean mayTerminateAfterIteration(int iteration);
114  protected abstract boolean shouldTerminate(int iteration);
115 
116  private void doIterations(Config config) throws MatsimRuntimeModifications.UnexpectedShutdownException {
117  int iteration = config.controller().getFirstIteration();
118 
119  // Special case if lastIteration == -1 -> Do not run any Mobsim
120  boolean doTerminate = config.controller().getLastIteration() < iteration;
121 
122  while (!doTerminate) {
123  boolean isLastIteration = mayTerminateAfterIteration(iteration);
124  iteration(config, iteration, isLastIteration);
125  doTerminate = isLastIteration && shouldTerminate(iteration);
126  iteration++;
127  }
128  }
129 
130  final String MARKER = "### ";
131 
132  private void iteration(final Config config, final int iteration, boolean isLastIteration) throws MatsimRuntimeModifications.UnexpectedShutdownException {
133  this.thisIteration = iteration;
134  this.getStopwatch().beginIteration(iteration);
135 
136  log.info(Controler.DIVIDER);
137  log.info(MARKER + "ITERATION " + iteration + " BEGINS");
138  this.getControlerIO().createIterationDirectory(iteration);
139  resetRandomNumbers(config.global().getRandomSeed(), iteration);
140 
141  iterationStep("iterationStartsListeners", new Runnable() {
142  @Override
143  public void run() {
144  controlerListenerManagerImpl.fireControlerIterationStartsEvent(iteration, isLastIteration);
145  }
146  });
147 
148  if (iteration > config.controller().getFirstIteration()) {
149  iterationStep("replanning", new Runnable() {
150  @Override
151  public void run() {
152  controlerListenerManagerImpl.fireControlerReplanningEvent(iteration, isLastIteration);
153  }
154  });
155  }
156 
157  mobsim(config, iteration, isLastIteration);
158 
159  iterationStep("scoring", new Runnable() {
160  @Override
161  public void run() {
162  log.info(MARKER + "ITERATION " + iteration + " fires scoring event");
163  controlerListenerManagerImpl.fireControlerScoringEvent(iteration, isLastIteration);
164  }
165  });
166 
167  iterationStep("iterationEndsListeners", new Runnable() {
168  @Override
169  public void run() {
170  log.info(MARKER + "ITERATION " + iteration + " fires iteration end event");
171  controlerListenerManagerImpl.fireControlerIterationEndsEvent(iteration, isLastIteration);
172  }
173  });
174 
175  this.getStopwatch().endIteration();
176  try {
177  this.getStopwatch().writeSeparatedFile(this.getControlerIO().getOutputFilename("stopwatch.csv"), config.global().getDefaultDelimiter());
178  } catch (UncheckedIOException e) {
179  log.error("Could not write stopwatch file.", e);
180  }
181  if (config.controller().getCreateGraphsInterval() > 0 && iteration % config.controller().getCreateGraphsInterval() == 0) {
182  this.getStopwatch().writeGraphFile(this.getControlerIO().getOutputFilename("stopwatch.png", ControllerConfigGroup.CompressionType.none));
183  }
184  log.info(MARKER + "ITERATION " + iteration + " ENDS");
185  log.info(Controler.DIVIDER);
186  }
187 
188  private void mobsim(final Config config, final int iteration, boolean isLastIteration) throws MatsimRuntimeModifications.UnexpectedShutdownException {
189  // ControlerListeners may create managed resources in
190  // beforeMobsim which need to be cleaned up in afterMobsim.
191  // Hence the finally block.
192  // For instance, ParallelEventsManagerImpl leaves Threads waiting if we don't do this
193  // and an Exception occurs in the Mobsim.
194  try {
195  iterationStep("beforeMobsimListeners", new Runnable() {
196  @Override
197  public void run() {
198  controlerListenerManagerImpl.fireControlerBeforeMobsimEvent(iteration, isLastIteration);
199  }
200  });
201 
202  iterationStep( "prepareForMobsim", new Runnable(){
203  @Override
204  public void run() {
205  prepareForMobsim() ;
206  // todo: make replacable
207  }
208  }) ;
209 
210  iterationStep("mobsim", new Runnable() {
211  @Override
212  public void run() {
213  resetRandomNumbers(config.global().getRandomSeed(), iteration);
214  runMobSim();
215  }
216  });
217  }
218  catch ( Throwable t ) {
219  // I had problems with an exception being thrown in my MobsimFactory: when the after mobsim
220  // listeners were called from the finally block, the finishProcessing() method of the events
221  // manager also resulted in an exception (because the mobsim crashed before initProcessing() was
222  // ever called), "hidding" the actual source of the problem.
223  // To avoid this, we log anything thrown during mobsim before executing after mobsim listeners.
224  // td, oct'14
225  log.error( "Mobsim did not complete normally! afterMobsimListeners will be called anyway." , t );
226 
227  // Java 7 seems able to detect which throwables this can be, thus no
228  // need to wrap or anything... Nice!
229  // If an exception occurs in the finally-block, this exception will be
230  // suppressed, but at least we logged it.
231  throw t;
232  }
233  finally {
234  iterationStep("afterMobsimListeners", new Runnable() {
235  @Override
236  public void run() {
237  log.info(MARKER + "ITERATION " + iteration + " fires after mobsim event");
238  controlerListenerManagerImpl.fireControlerAfterMobsimEvent(iteration, isLastIteration);
239  }
240  });
241  }
242  }
243 
244  private void iterationStep(String iterationStepName, Runnable iterationStep) throws MatsimRuntimeModifications.UnexpectedShutdownException {
245  this.getStopwatch().beginOperation(iterationStepName);
246  iterationStep.run();
247  this.getStopwatch().endOperation(iterationStepName);
248  if (Thread.interrupted()) {
249  throw new MatsimRuntimeModifications.UnexpectedShutdownException();
250  }
251  }
252 
253 
259  public final void addControlerListener(ControlerListener l) {
260  this.controlerListenerManagerImpl.addControlerListener(l);
261  }
262 
263  protected final void addCoreControlerListener(ControlerListener l) {
264  this.controlerListenerManagerImpl.addCoreControlerListener(l);
265  }
266 
267 
268  public final OutputDirectoryHierarchy getControlerIO() {
269  return controlerIO;
270  }
271 
272 
273  public final Integer getIterationNumber() {
274  return this.thisIteration;
275  }
276 
277  public IterationStopWatch getStopwatch() {
278  return stopwatch;
279  }
280 
281 }
void fireControlerBeforeMobsimEvent(final int iteration, boolean isLastIteration)
static final void checkConfigConsistencyAndWriteToLog(Config config, final String message)
void fireControlerReplanningEvent(final int iteration, boolean isLastIteration)
void fireControlerScoringEvent(final int iteration, boolean isLastIteration)
void fireControlerIterationEndsEvent(final int iteration, boolean isLastIteration)
static void start(int interval_seconds)
void fireControlerIterationStartsEvent(final int iteration, boolean isLastIteration)
void fireControlerShutdownEvent(final boolean unexpected, int iteration)
final ControllerConfigGroup controller()
Definition: Config.java:399
void fireControlerAfterMobsimEvent(final int iteration, boolean isLastIteration)
final GlobalConfigGroup global()
Definition: Config.java:395
static final void initLogging(OutputDirectoryHierarchy outputDirectoryHierarchy)