public static void main(String[] args) {
    Config config = new Config();
    config.addCoreModules();
    Controler controler = new Controler(config);

    // controler settings
    controler
        .getConfig()
        .controler()
        .setOverwriteFileSetting(
            true
                ? OutputDirectoryHierarchy.OverwriteFileSetting.overwriteExistingFiles
                : OutputDirectoryHierarchy.OverwriteFileSetting.failIfDirectoryExists);
    controler.getConfig().controler().setCreateGraphs(false);

    // controlerConfigGroup
    ControlerConfigGroup ccg = controler.getConfig().controler();
    ccg.setOutputDirectory(outputPath);
    ccg.setFirstIteration(0);
    ccg.setLastIteration(0);
    ccg.setMobsim("qsim");
    Set set = new HashSet();
    set.add(EventsFileFormat.xml);
    ccg.setEventsFileFormats(set);
    //		ccg.setRunId("321");

    // qsimConfigGroup
    QSimConfigGroup qcg = controler.getConfig().qsim();
    qcg.setStartTime(0 * 3600.);
    qcg.setEndTime(30 * 3600.);
    qcg.setFlowCapFactor(0.1);
    qcg.setStorageCapFactor(0.3);
    //		qcg.setFlowCapFactor(0.01);
    //		qcg.setStorageCapFactor(0.03);
    qcg.setNumberOfThreads(1);
    qcg.setRemoveStuckVehicles(false);
    qcg.setStuckTime(10.0);

    // planCalcScoreConfigGroup
    PlanCalcScoreConfigGroup pcs = controler.getConfig().planCalcScore();
    Set<String> activities = new HashSet<String>();
    activities.add("unknown");
    activities.add("work");
    activities.add("pickup");
    activities.add("with adult");
    activities.add("other");
    activities.add("pvWork");
    activities.add("pvHome");
    activities.add("gvHome");
    activities.add("education");
    activities.add("business");
    activities.add("shopping");
    activities.add("private");
    activities.add("leisure");
    activities.add("sports");
    activities.add("home");
    activities.add("friends");

    for (String activity : activities) {
      ActivityParams params = new ActivityParams(activity);
      params.setTypicalDuration(30 * 3600);
      pcs.addActivityParams(params);
    }

    // strategy
    StrategyConfigGroup scg = controler.getConfig().strategy();
    StrategySettings strategySettings =
        new StrategySettings(Id.create("1", StrategySettings.class));
    strategySettings.setStrategyName("ChangeExpBeta");
    strategySettings.setWeight(1.0);
    scg.addStrategySettings(strategySettings);

    // network
    NetworkConfigGroup ncg = controler.getConfig().network();
    ncg.setInputFile(networkFile);

    // plans
    PlansConfigGroup pcg = controler.getConfig().plans();
    pcg.setInputFile(plansFile);

    // define emission tool input files

    EmissionsConfigGroup ecg = new EmissionsConfigGroup();
    controler.getConfig().addModule(ecg);
    ecg.setEmissionRoadTypeMappingFile(roadTypeMappingFile);
    ecg.setEmissionVehicleFile(emissionVehicleFile);

    ecg.setAverageWarmEmissionFactorsFile(averageFleetWarmEmissionFactorsFile);
    ecg.setAverageColdEmissionFactorsFile(averageFleetColdEmissionFactorsFile);

    ecg.setUsingDetailedEmissionCalculation(isUsingDetailedEmissionCalculation);
    ecg.setDetailedWarmEmissionFactorsFile(detailedWarmEmissionFactorsFile);
    ecg.setDetailedColdEmissionFactorsFile(detailedColdEmissionFactorsFile);

    // TODO: the following does not work yet. Need to force controler to always write events in the
    // last iteration.
    VspExperimentalConfigGroup vcg = controler.getConfig().vspExperimental();
    vcg.setWritingOutputEvents(false);

    controler.addControlerListener(new EmissionControlerListener());
    controler.run();
  }
  public static void main(String[] args) {
    // see an example with detailed explanations -- package
    // opdytsintegration.example.networkparameters.RunNetworkParameters
    Config config = ConfigUtils.loadConfig(EQUIL_DIR + "/config.xml");

    config.controler().setOutputDirectory(OUT_DIR);
    config.controler().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists);

    //		config.plans().setInputFile("relaxed_plans.xml.gz");
    config.plans().setInputFile("plans2000.xml.gz");

    // == default config has limited inputs
    StrategyConfigGroup strategies = config.strategy();
    strategies.clearStrategySettings();

    config.changeMode().setModes(new String[] {"car", "pt"});
    StrategySettings modeChoice = new StrategySettings();
    modeChoice.setStrategyName(
        DefaultPlanStrategiesModule.DefaultStrategy.ChangeSingleTripMode.name());
    modeChoice.setWeight(0.1);
    config.strategy().addStrategySettings(modeChoice);

    StrategySettings expChangeBeta = new StrategySettings();
    expChangeBeta.setStrategyName(DefaultPlanStrategiesModule.DefaultSelector.ChangeExpBeta.name());
    expChangeBeta.setWeight(0.9);
    config.strategy().addStrategySettings(expChangeBeta);

    for (PlanCalcScoreConfigGroup.ActivityParams params :
        config.planCalcScore().getActivityParams()) {
      params.setTypicalDurationScoreComputation(
          PlanCalcScoreConfigGroup.TypicalDurationScoreComputation.relative);
    }

    //		config.qsim().setTrafficDynamics( QSimConfigGroup.TrafficDynamics.withHoles );
    //
    //		if ( config.qsim().getTrafficDynamics()== QSimConfigGroup.TrafficDynamics.withHoles ) {
    //			config.qsim().setInflowConstraint(QSimConfigGroup.InflowConstraint.maxflowFromFdiag);
    //		}

    config.qsim().setUsingFastCapacityUpdate(true);

    // ==

    Scenario scenario = KNBerlinControler.prepareScenario(true, false, config);

    double time = 6 * 3600.;
    for (Person person : scenario.getPopulation().getPersons().values()) {
      Plan plan = person.getSelectedPlan();
      Activity activity = (Activity) plan.getPlanElements().get(0);
      activity.setEndTime(time);
      time++;
    }

    // ==

    // this is something like time bin generator
    int startTime = 0;
    int binSize = 3600; // can this be scenario simulation end time.
    int binCount = 24; // to me, binCount and binSize must be related
    TimeDiscretization timeDiscretization = new TimeDiscretization(startTime, binSize, binCount);

    Set<String> modes2consider = new HashSet<>();
    modes2consider.add("car");
    modes2consider.add("bike");

    OpdytsModalStatsControlerListener stasControlerListner =
        new OpdytsModalStatsControlerListener(modes2consider, EQUIL);

    // following is the  entry point to start a matsim controler together with opdyts
    MATSimSimulator<ModeChoiceDecisionVariable> simulator =
        new MATSimSimulator<>(new MATSimStateFactoryImpl<>(), scenario, timeDiscretization);
    simulator.addOverridingModule(
        new AbstractModule() {

          @Override
          public void install() {
            // add here whatever should be attached to matsim controler
            // some stats
            addControlerListenerBinding().toInstance(stasControlerListner);

            // from KN
            addControlerListenerBinding().to(KaiAnalysisListener.class);
            bind(CharyparNagelScoringParametersForPerson.class)
                .to(EveryIterationScoringParameters.class);
          }
        });

    // this is the objective Function which returns the value for given SimulatorState
    // in my case, this will be the distance based modal split
    ObjectiveFunction objectiveFunction =
        new ModeChoiceObjectiveFunction(
            EQUIL); // in this, the method argument (SimulatorStat) is not used.

    // search algorithm
    int maxIterations =
        10; // this many times simulator.run(...) and thus controler.run() will be called.
    int maxTransitions = Integer.MAX_VALUE;
    int populationSize =
        10; // the number of samples for decision variables, one of them will be drawn randomly for
    // the simulation.

    boolean interpolate = true;
    boolean includeCurrentBest = false;

    // randomize the decision variables (for e.g.\ utility parameters for modes)
    DecisionVariableRandomizer<ModeChoiceDecisionVariable> decisionVariableRandomizer =
        new ModeChoiceRandomizer(scenario, RandomizedUtilityParametersChoser.ONLY_ASC, EQUIL);

    // what would be the decision variables to optimize the objective function.
    ModeChoiceDecisionVariable initialDecisionVariable =
        new ModeChoiceDecisionVariable(scenario.getConfig().planCalcScore(), scenario, EQUIL);

    // what would decide the convergence of the objective function
    final int iterationsToConvergence = 200; //
    final int averagingIterations = 10;
    ConvergenceCriterion convergenceCriterion =
        new FixedIterationNumberConvergenceCriterion(iterationsToConvergence, averagingIterations);

    RandomSearch<ModeChoiceDecisionVariable> randomSearch =
        new RandomSearch<>(
            simulator,
            decisionVariableRandomizer,
            initialDecisionVariable,
            convergenceCriterion,
            maxIterations, // this many times simulator.run(...) and thus controler.run() will be
            // called.
            maxTransitions,
            populationSize,
            MatsimRandom.getRandom(),
            interpolate,
            objectiveFunction,
            includeCurrentBest);

    // probably, an object which decide about the inertia
    SelfTuner selfTuner = new SelfTuner(0.95);

    randomSearch.setLogPath(OUT_DIR);

    // run it, this will eventually call simulator.run() and thus controler.run
    randomSearch.run(selfTuner);
  }