MATSIM
Controler.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * *********************************************************************** *
4  * *
5  * copyright : (C) 2007, 2008 by the members listed in the COPYING, *
6  * LICENSE and WARRANTY file. *
7  * email : info at matsim dot org *
8  * *
9  * *********************************************************************** *
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * See also COPYING, LICENSE and WARRANTY file *
16  * *
17  * *********************************************************************** */
18 
19 package org.matsim.core.controler;
20 
21 import com.google.inject.Key;
22 import com.google.inject.Provider;
23 import com.google.inject.TypeLiteral;
24 import com.google.inject.name.Names;
25 import org.apache.logging.log4j.LogManager;
26 import org.apache.logging.log4j.Logger;
27 import org.apache.logging.log4j.core.layout.PatternLayout;
32 import org.matsim.api.core.v01.Scenario;
36 import org.matsim.core.config.Config;
43 import org.matsim.core.gbl.Gbl;
58 
59 import java.util.*;
60 
69  // yyyy Design thoughts:
70  // * Seems to me that we should try to get everything here final. Flexibility is provided by the ability to set or add factories. If this is
71  // not sufficient, people should use AbstractController. kai, jan'13
72 
73  public static final String DIRECTORY_ITERS = "ITERS";
74 
75  public enum DefaultFiles {
76  config("config.xml"),
77  configReduced("config_reduced.xml"),
78  network("network.xml"),
79  lanes("lanes.xml"),
80  changeEvents("change_events.xml"),
81  counts("counts.xml"),
82  population("plans.xml"),
83  experiencedPlans("experienced_plans.xml"),
84  households("households.xml"),
85  facilities("facilities.xml"),
86  events("events.xml"),
87  eventsPb("events.pb"),
88  eventsJson("events.ndjson"),
89  transitSchedule("transitSchedule.xml"),
90  transitVehicles("transitVehicles.xml"),
91  vehicles("vehicles.xml"),
92  allVehicles("allVehicles.xml"),
93  linkstats("linkstats.txt"),
94  tripscsv("trips.csv"),
95  personscsv("persons.csv"),
96  legscsv("legs.csv"),
97  linkscsv("links.csv"),
98  activitiescsv("activities.csv")
99  ;
100 
101  final String filename;
102 
103  DefaultFiles(String filename) {
104  this.filename = filename;
105  }
106  }
107 
108  static final String OUTPUT_PREFIX = "output_";
109 
110  public static final String DIVIDER = "###################################################";
111 
112  private static final Logger log = LogManager.getLogger(Controler.class);
113 
114  public static final PatternLayout DEFAULTLOG4JLAYOUT = PatternLayout.newBuilder().withPattern("%d{ISO8601} %5p %C{1}:%L %m%n").build();
115 
116  private final Config config;
118 
119  private com.google.inject.Injector injector;
120  private boolean injectorCreated = false;
121 
122  @Override
124  return injector.getInstance(IterationStopWatch.class);
125  }
126 
127  // DefaultControlerModule includes submodules. If you want less than what the Controler does
128  // by default, you can leave ControlerDefaultsModule out, look at what it does,
129  // and only include what you want.
130  private List<AbstractModule> modules = Collections.singletonList(new ControlerDefaultsModule());
131 
132  // The module which is currently defined by the sum of the setXX methods called on this Controler.
134 
135  private List<AbstractQSimModule> overridingQSimModules = new LinkedList<>();
136 
137  public static void main(final String[] args) {
138  if ((args == null) || (args.length == 0)) {
139  System.out.println("No argument given!");
140  System.out.println("Usage: Controler config-file [dtd-file]");
141  System.out.println();
142  } else {
143  final Controler controler = new Controler(args);
144  controler.run();
145  }
146  System.exit(0);
147  }
148 
159  public Controler(final String[] args) {
160  this(args.length > 0 ? args[0] : null, null, null);
161  }
162 
163  public Controler(final String configFileName) {
164  this(configFileName, null, null);
165  }
166 
167  public Controler(final Config config) {
168  this(null, config, null);
169  }
170 
171  public Controler(final Scenario scenario) {
172  this(null, null, scenario);
173  }
174 
175  private Controler(final String configFileName, final Config config, Scenario scenario) {
176  if (scenario != null) {
177  // scenario already loaded (recommended):
178  this.config = scenario.getConfig();
180  } else {
181  if (configFileName == null) {
182  // config should already be loaded:
183  if (config == null) {
184  throw new IllegalArgumentException("Either the config or the filename of a configfile must be set to initialize the Controler.");
185  }
186  this.config = config;
187  } else {
188  // else load config:
189  this.config = ConfigUtils.loadConfig(configFileName);
190  }
192 
193  // load scenario:
194  //scenario = ScenarioUtils.createScenario(this.config);
195  //ScenarioUtils.loadScenario(scenario) ;
196  }
197  this.config.eventsManager().makeLocked();
198  this.scenario = scenario;
199  this.overrides = scenario == null ?
200  new ScenarioByConfigModule() :
201  new ScenarioByInstanceModule(this.scenario);
202 
203  this.config.qsim().setLocked();
204  // yy this is awfully ad-hoc. kai, jul'18
205  // yy should probably come even earlier, before the scenario is generated. kai, jul'18
206  }
207 
208  private void createInjector() {
209  if (!injectorCreated) {
210  this.injectorCreated = true;
211 
212  this.overrides = AbstractModule.override(Collections.singletonList(this.overrides), new AbstractModule() {
213  @Override
214  public void install() {
215  bind(Key.get(new TypeLiteral<List<AbstractQSimModule>>() {
216  }, Names.named("overrides"))).toInstance(overridingQSimModules);
217  }
218  });
219 
220  // check config consistency just before creating injector; sometimes, we can provide better error messages there:
222  config.checkConsistency();
224 
225  final Set<AbstractModule> standardModules = Collections.singleton(
226  new AbstractModule(){
227  @Override
228  public void install(){
229  install( new NewControlerModule() );
230  install( new ControlerDefaultCoreListenersModule() );
231  for( AbstractModule module : modules ){
232  install( module );
233  }
234  // should not be necessary: created in the controler
235  //install(new ScenarioByInstanceModule(scenario));
236  }
237  }
238  );
239  this.injector = Injector.createInjector( config, AbstractModule.override( standardModules, overrides ) );
240  }
241  }
242 
246  @Override
247  public final void run() {
248  // It is better to keep this line before actually creating the injector, because:
249  // - it actually means "fail if adding new Guice modules"
250  // - adding Guice modules to the Controler from other Guice modules is too late.
251  // This might sound silly, but might, in some cases, happen, through code that
252  // - transformed a StartupListener to a Guice module
253  // - that called methods such as setScoringFunctionFactory(), that redirects to addOverridingModule()
254  // And this happens silently, leading to lots of time and hair lost.
255  // td, nov 16
256  createInjector();
257 
258  ControlerI controler = injector.getInstance(ControlerI.class);
259  controler.run();
260  }
261 
262 
263  // ******** --------- *******
264  // The following is the internal interface of the Controler, which
265  // is meant to be called while the Controler is running (not before)..
266  // ******** --------- *******
267 
268  @Override
270  return this.injector.getInstance(com.google.inject.Injector.class).getInstance(Key.get(new TypeLiteral<Map<String, TravelTime>>() {}))
271  .get(TransportMode.car);
272  }
273 
285  @Override
286  public final Provider<TripRouter> getTripRouterProvider() {
287  return this.injector.getProvider(TripRouter.class);
288  }
289 
290  @Override
292  return getTravelDisutilityFactory().createTravelDisutility(this.injector.getInstance(TravelTime.class));
293  }
294 
295  @Override
297  return this.injector.getInstance(LeastCostPathCalculatorFactory.class);
298  }
299 
300  @Override
302  return this.injector.getInstance(ScoringFunctionFactory.class);
303  }
304 
305  @Override
306  public final Config getConfig() {
307  return config;
308  }
309 
310  @Override
311  public final Scenario getScenario() {
312  if (this.injectorCreated) {
313  Gbl.assertNotNull(this.injector);
314  return this.injector.getInstance(Scenario.class);
315  } else {
316  if ( scenario == null ) {
317  log.error( "Trying to get Scenario before it was instanciated.");
318  log.error( "When passing a config file or a config file path to the Controler constructor," );
319  log.error( "Scenario will be loaded first when the run() method is invoked." );
320  throw new IllegalStateException( "Trying to get Scenario before is was instanciated." );
321  }
322  return this.scenario;
323  }
324  }
325 
326 
327  @Override
328  public final EventsManager getEvents() {
329  if (this.injector != null) {
330  return this.injector.getInstance(EventsManager.class);
331  } else {
332  return new EventsManager() {
333  @Override
334  public void processEvent(Event event) {
335  Controler.this.injector.getInstance(EventsManager.class).processEvent(event);
336  }
337 
338  @Override
339  public void addHandler(final EventHandler handler) {
341  @Override
342  public void install() {
343  addEventHandlerBinding().toInstance(handler);
344  }
345  });
346  }
347 
348  @Override
349  public void removeHandler(EventHandler handler) {
350  throw new UnsupportedOperationException();
351  }
352 
353  @Override
354  public void resetHandlers(int iteration) {
355  throw new UnsupportedOperationException();
356  }
357 
358  @Override
359  public void initProcessing() {
360  throw new UnsupportedOperationException();
361  }
362 
363  @Override
364  public void afterSimStep(double time) {
365  throw new UnsupportedOperationException();
366  }
367 
368  @Override
369  public void finishProcessing() {
370  throw new UnsupportedOperationException();
371  }
372  };
373  }
374  }
375 
376  @Override
377  public final com.google.inject.Injector getInjector() {
378  createInjector();
379  return this.injector;
380  }
381 
385  public final void resetInjector() {
386  this.injectorCreated = false;
387  }
388 
393  @Override
394  @Deprecated
395  public final CalcLinkStats getLinkStats() {
396  return this.injector.getInstance(CalcLinkStats.class);
397  }
398 
399  @Override
400  public final VolumesAnalyzer getVolumes() {
401  return this.injector.getInstance(VolumesAnalyzer.class);
402  }
403 
404  @Override
405  public final ScoreStats getScoreStats() {
406  return this.injector.getInstance(ScoreStats.class);
407  }
408 
409  @Override
411  return this.injector.getInstance(com.google.inject.Injector.class).getInstance(Key.get(new TypeLiteral<Map<String, TravelDisutilityFactory>>(){}))
412  .get(TransportMode.car);
413  }
414 
423  @Override
424  @Deprecated // see javadoc above
426  return this.injector.getInstance(StrategyManager.class);
427  }
428 
429  @Override
431  return injector.getInstance(OutputDirectoryHierarchy.class);
432  }
433 
434  @Override
435  public Integer getIterationNumber() {
436  return injector.getInstance(ReplanningContext.class).getIteration();
437  }
438  // ******** --------- *******
439  // The following methods are the outer interface of the Controler. They are used
440  // to set up infrastructure from the outside, before calling run().
441  // ******** --------- *******
442 
443  @Override
444  public void addControlerListener(final ControlerListener controlerListener) {
446  @Override
447  public void install() {
448  addControlerListenerBinding().toInstance(controlerListener);
449  }
450  });
451  }
452 
453  public final void setScoringFunctionFactory(
454  final ScoringFunctionFactory scoringFunctionFactory) {
456  @Override
457  public void install() {
458  this.bindScoringFunctionFactory().toInstance(scoringFunctionFactory);
459  }
460  });
461  }
462 
463  public final void setTerminationCriterion(final TerminationCriterion terminationCriterion) {
465  @Override
466  public void install() {
467  bind(TerminationCriterion.class).toInstance(terminationCriterion);
468  }
469  });
470  }
471 
472  @Override
473  public final Controler addOverridingModule( AbstractModule abstractModule ) {
474  if (this.injectorCreated) {
475  throw new RuntimeException("Too late for configuring the Controler. This can only be done before calling run.");
476  }
477  this.overrides = AbstractModule.override(Collections.singletonList(this.overrides), abstractModule);
478  return this ;
479  }
480 
481  public final void setModules(AbstractModule... modules) {
482  if (this.injectorCreated) {
483  throw new RuntimeException("Too late for configuring the Controler. This can only be done before calling run.");
484  }
485  this.modules = Arrays.asList(modules);
486  }
487 
488  @Override
490  if (this.injectorCreated) {
491  throw new RuntimeException("Too late for configuring the Controler. This can only be done before calling run.");
492  }
493  overridingQSimModules.add(qsimModule);
494  return this ;
495  }
496  @Override
497  public final Controler addQSimModule(AbstractQSimModule qsimModule) {
499  @Override
500  public void install() {
501  installQSimModule(qsimModule);
502  }
503  });
504  return this ;
505  }
506 
510  @Override
513  @Override
514  public void install() {
515  QSimComponentsConfig components = new QSimComponentsConfig();
516  new StandardQSimComponentConfigurator(config).configure(components);
517  configurator.configure(components);
518  bind(QSimComponentsConfig.class).toInstance(components);
519  }
520  });
521  return this ;
522  }
523 }
final Controler addOverridingModule(AbstractModule abstractModule)
Definition: Controler.java:473
final void setScoringFunctionFactory(final ScoringFunctionFactory scoringFunctionFactory)
Definition: Controler.java:453
static final PatternLayout DEFAULTLOG4JLAYOUT
Definition: Controler.java:114
void removeConfigConsistencyChecker(final Class clazz)
Definition: Config.java:507
final EventsManager getEvents()
Definition: Controler.java:328
static Config loadConfig(final String filename, ConfigGroup... customModules)
Controler(final Scenario scenario)
Definition: Controler.java:171
List< AbstractModule > modules
Definition: Controler.java:130
TravelDisutility createTravelDisutility(TravelTime timeCalculator)
final void setModules(AbstractModule... modules)
Definition: Controler.java:481
final TravelTime getLinkTravelTimes()
Definition: Controler.java:269
EventsManagerConfigGroup eventsManager()
Definition: Config.java:467
final TravelDisutilityFactory getTravelDisutilityFactory()
Definition: Controler.java:410
final TravelDisutility createTravelDisutilityCalculator()
Definition: Controler.java:291
Controler(final Config config)
Definition: Controler.java:167
final com.google.inject.Injector getInjector()
Definition: Controler.java:377
List< AbstractQSimModule > overridingQSimModules
Definition: Controler.java:135
final CalcLinkStats getLinkStats()
Definition: Controler.java:395
final Provider< TripRouter > getTripRouterProvider()
Definition: Controler.java:286
static void main(final String[] args)
Definition: Controler.java:137
void addConfigConsistencyChecker(final ConfigConsistencyChecker checker)
Definition: Config.java:493
Controler(final String configFileName, final Config config, Scenario scenario)
Definition: Controler.java:175
final VolumesAnalyzer getVolumes()
Definition: Controler.java:400
QSimConfigGroup qsim()
Definition: Config.java:447
final ScoringFunctionFactory getScoringFunctionFactory()
Definition: Controler.java:301
static void assertNotNull(Object obj)
Definition: Gbl.java:212
final StrategyManager getStrategyManager()
Definition: Controler.java:425
final void setTerminationCriterion(final TerminationCriterion terminationCriterion)
Definition: Controler.java:463
Controler(final String[] args)
Definition: Controler.java:159
static com.google.inject.Injector createInjector(final Config config, Module... modules)
Definition: Injector.java:58
final Controler configureQSimComponents(QSimComponentsConfigurator configurator)
Definition: Controler.java:511
static final String DIRECTORY_ITERS
Definition: Controler.java:73
void addControlerListener(final ControlerListener controlerListener)
Definition: Controler.java:444
Controler(final String configFileName)
Definition: Controler.java:163
IterationStopWatch getStopwatch()
Definition: Controler.java:123
final LeastCostPathCalculatorFactory getLeastCostPathCalculatorFactory()
Definition: Controler.java:296
final Controler addQSimModule(AbstractQSimModule qsimModule)
Definition: Controler.java:497
final Controler addOverridingQSimModule(AbstractQSimModule qsimModule)
Definition: Controler.java:489
static AbstractModule override(final Iterable<? extends AbstractModule > modules, final AbstractModule abstractModule)
com.google.inject.Injector injector
Definition: Controler.java:119
OutputDirectoryHierarchy getControlerIO()
Definition: Controler.java:430