playground.meisterk.org.matsim.run.westumfahrung.CompareScenarios.java Source code

Java tutorial

Introduction

Here is the source code for playground.meisterk.org.matsim.run.westumfahrung.CompareScenarios.java

Source

/* *********************************************************************** *
 * project: org.matsim.*
 *                                                                         *
 * *********************************************************************** *
 *                                                                         *
 * copyright       : (C) 2010 by the members listed in the COPYING,        *
 *                   LICENSE and WARRANTY file.                            *
 * email           : info at matsim dot org                                *
 *                                                                         *
 * *********************************************************************** *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *   See also COPYING, LICENSE and WARRANTY file                           *
 *                                                                         *
 * *********************************************************************** */

package playground.meisterk.org.matsim.run.westumfahrung;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.matsim.analysis.CalcAverageTripLength;
import org.matsim.analysis.CalcLegTimes;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Activity;
import org.matsim.api.core.v01.population.Person;
import org.matsim.api.core.v01.population.PlanElement;
import org.matsim.api.core.v01.population.Population;
import org.matsim.contrib.analysis.filters.population.PersonFilter;
import org.matsim.contrib.analysis.filters.population.RouteLinkFilter;
import org.matsim.contrib.analysis.filters.population.SelectedPlanFilter;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.events.EventsUtils;
import org.matsim.core.network.MatsimNetworkReader;
import org.matsim.core.population.MatsimPopulationReader;
import org.matsim.core.population.PopulationImpl;
import org.matsim.core.population.PopulationReader;
import org.matsim.core.scenario.ScenarioImpl;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.core.utils.misc.Time;

import playground.balmermi.world.World;
import playground.meisterk.org.matsim.run.facilities.ShopsOf2005ToFacilities;

/**
 * Compare two scenarios (network, plans, events) with each other.
 * Contains several analyses that were performed for the Westumfahrung Zurich study.
 *
 * @author meisterk
 *
 */
public class CompareScenarios {

    static class CaseStudyResult {

        private final String name;
        private final Population plans;
        private final CalcLegTimes calcLegTimes;
        private final PlanAverageScore planAverageScore;
        private final CalcAverageTripLength calcAverageTripLength;

        public CaseStudyResult(final String name, final Population plans, final CalcLegTimes calcLegTimes,
                final PlanAverageScore planAverageScore, final CalcAverageTripLength calcAverageTripLength) {
            super();
            this.name = name;
            this.plans = plans;
            this.calcLegTimes = calcLegTimes;
            this.planAverageScore = planAverageScore;
            this.calcAverageTripLength = calcAverageTripLength;
        }

        public String getName() {
            return this.name;
        }

        public Population getRouteSwitchers() {
            return this.plans;
        }

        public CalcLegTimes getRouteSwitchersLegTimes() {
            return this.calcLegTimes;
        }

        public PlanAverageScore getRouteSwitchersAverageScore() {
            return this.planAverageScore;
        }

        public CalcAverageTripLength getCalcAverageTripLength() {
            return this.calcAverageTripLength;
        }

    }

    private static final Logger log = Logger.getLogger(ShopsOf2005ToFacilities.class);

    // transit agents have ids > 1'000'000'000
    private static final String TRANSIT_PERSON_ID_PATTERN = "[0-9]{10}";
    private static final String NON_TRANSIT_PERSON_ID_PATTERN = "[0-9]{1,9}";

    // compare 2 scenarios
    private String scenarioNameBefore = "before";
    private String scenarioNameAfter = "after";
    private final String[] scenarioNames = new String[] { this.scenarioNameBefore, this.scenarioNameAfter };

    // analyses
    private static final int TRANSIT_AGENTS_ANALYSIS_NAME = 0;
    private static final int NON_TRANSIT_AGENTS_ANALYSIS_NAME = 1;
    private static final int ROUTE_SWITCHERS_ANALYSIS_NAME = 2;
    private static final int WESTSTRASSE_NEIGHBORS_ANALYSIS_NAME = 3;
    private final TreeMap<Integer, String> analysisNames = new TreeMap<Integer, String>();

    // analysisRegions
    private final HashSet<Id<Link>> weststrasseLinkIds = new HashSet<>();

    private final TreeMap<String, String> plansInputFilenames = new TreeMap<String, String>();
    private final TreeMap<String, String> eventsInputFilenames = new TreeMap<String, String>();
    private final TreeMap<String, String> networkInputFilenames = new TreeMap<String, String>();
    private final TreeMap<String, String> linkSetFilenames = new TreeMap<String, String>();
    private final TreeMap<String, HashSet<Id<Link>>> linkSets = new TreeMap<>();
    private final TreeMap<String, String> linkSetNames = new TreeMap<String, String>();

    private String scenarioComparisonFilename = null;
    private final ArrayList<String> scenarioComparisonLines = new ArrayList<String>();

    private String routeSwitchersListFilename = null;
    private final ArrayList<String> routeSwitchersLines = new ArrayList<String>();

    /**
     * @param args
     */
    public static void main(final String[] args) {

        CompareScenarios compareScenarios = new CompareScenarios();
        compareScenarios.run(args);

    }

    private void run(final String[] args) {

        ScenarioImpl scenario = (ScenarioImpl) ScenarioUtils.createScenario(ConfigUtils.createConfig());
        Config config = scenario.getConfig();

        log.info("Processing command line parameters...");
        this.processArgs(args);
        log.info("Processing command line parameters...done.");
        System.out.flush();
        log.info("Init...");
        this.init();
        log.info("Init...done.");
        System.out.flush();
        log.info("Performing analyses...");
        this.doAnalyses(null);
        log.info("Performing analyses...done.");
        System.out.flush();
        log.info("Writing out results...");
        this.writeResults();
        log.info("Writing out results...done.");
        System.out.flush();

    }

    private void writeResults() {

        File scenarioComparisonFile = new File(this.scenarioComparisonFilename);
        File routeSwitchersFile = new File(this.routeSwitchersListFilename);
        try {
            FileUtils.writeLines(scenarioComparisonFile, "UTF-8", this.scenarioComparisonLines);
            FileUtils.writeLines(routeSwitchersFile, "UTF-8", this.routeSwitchersLines);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private void processArgs(final String[] args) {

        List<String> lines = new ArrayList<String>();
        File scenarioNameInputFile = null;

        final int NUMBER_OF_SCENARIOS = 2;

        if (args.length != 10) {
            System.out.println("Usage:");
            System.out.println("java CompareScenarios args");
            System.out.println("");
            System.out.println("args[0]: name_before.txt");
            System.out.println("args[1]: network_before.xml");
            System.out.println("args[2]: plans_before.xml.gz");
            System.out.println("args[3]: events_before.dat");
            System.out.println("args[4]: linkset_before.txt");
            System.out.println("args[5]: name_after.txt");
            System.out.println("args[6]: network_after.xml");
            System.out.println("args[7]: plans_after.xml.gz");
            System.out.println("args[8]: events_after.dat");
            System.out.println("args[9]: linkset_after.txt");
            System.out.println("");
            throw new RuntimeException();
        } else {
            int argsIndex = 0;
            for (int scenarioCounter = 0; scenarioCounter < NUMBER_OF_SCENARIOS; scenarioCounter++) {
                scenarioNameInputFile = new File(args[argsIndex]);
                try {
                    lines = FileUtils.readLines(scenarioNameInputFile, "UTF-8");
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                switch (scenarioCounter) {
                case 0:
                    this.scenarioNameBefore = lines.get(0);
                    this.scenarioNames[scenarioCounter] = lines.get(0);
                    break;
                case 1:
                    this.scenarioNameAfter = lines.get(0);
                    this.scenarioNames[scenarioCounter] = lines.get(0);
                    break;
                }
                argsIndex++;
                this.networkInputFilenames.put(this.scenarioNames[scenarioCounter], args[argsIndex]);
                argsIndex++;
                this.plansInputFilenames.put(this.scenarioNames[scenarioCounter], args[argsIndex]);
                argsIndex++;
                this.eventsInputFilenames.put(this.scenarioNames[scenarioCounter], args[argsIndex]);
                argsIndex++;
                this.linkSetFilenames.put(this.scenarioNames[scenarioCounter], args[argsIndex]);
                argsIndex++;
            }
        }

    }

    private void init() {

        this.analysisNames.put(Integer.valueOf(TRANSIT_AGENTS_ANALYSIS_NAME), "transit");
        this.analysisNames.put(Integer.valueOf(NON_TRANSIT_AGENTS_ANALYSIS_NAME), "non transit");
        this.analysisNames.put(Integer.valueOf(ROUTE_SWITCHERS_ANALYSIS_NAME), "route switchers");
        this.analysisNames.put(Integer.valueOf(WESTSTRASSE_NEIGHBORS_ANALYSIS_NAME), "weststrasse neighbors");

        List<String> lines = new ArrayList<String>();

        File linkSetFile = null;
        HashSet<Id<Link>> linkSet = null;

        for (String scenarioName : this.scenarioNames) {

            linkSetFile = new File(this.linkSetFilenames.get(scenarioName));
            try {
                lines = FileUtils.readLines(linkSetFile, "UTF-8");
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            linkSet = new HashSet<Id<Link>>();
            for (String line : lines) {
                try {
                    linkSet.add(Id.create(Integer.parseInt(line, 10), Link.class));
                } catch (NumberFormatException e) {
                    log.info("Reading in " + line + " link set...");
                    this.linkSetNames.put(scenarioName, line);
                }
            }
            this.linkSets.put(scenarioName, linkSet);
        }

        // build up weststrasse
        linkSetFile = new File("input/linksets/weststrasse.txt");
        try {
            lines = FileUtils.readLines(linkSetFile, "UTF-8");
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        //      linkSet = new HashSet<Id>();
        for (String line : lines) {
            try {
                this.weststrasseLinkIds.add(Id.create(Integer.parseInt(line), Link.class));
            } catch (NumberFormatException e) {
                log.info("Reading in " + line + " link set...");
            }
        }

        // output file names
        this.scenarioComparisonFilename = "output/" + this.scenarioNameBefore + "_vs_" + this.scenarioNameAfter
                + "__" + this.linkSetNames.get(this.scenarioNameBefore) + "_to_"
                + this.linkSetNames.get(this.scenarioNameAfter) + "__summary" + ".txt";
        this.routeSwitchersListFilename = "output/" + this.scenarioNameBefore + "_vs_" + this.scenarioNameAfter
                + "__" + this.linkSetNames.get(this.scenarioNameBefore) + "_to_"
                + this.linkSetNames.get(this.scenarioNameAfter) + "__routeswitchers" + ".txt";

    }

    /**
     * Gets all agents that use a set of links in one plans file and use another set in another plans file.
     * For example: Find all agents that use the Westtangente in a scenario without the Westumfahrung, that
     * switch to the Westumfahrung in a case study where the Westumfahrung was included in the scenario.
     *
     * Summarize their average trip travel times, the scores of their selected plans, and their home locations.
     */
    private void doAnalyses(World world) {

        TreeMap<Integer, TreeMap<String, PersonIdRecorder>> personIdRecorders = new TreeMap<Integer, TreeMap<String, PersonIdRecorder>>();

        for (Integer analysis : this.analysisNames.keySet()) {
            personIdRecorders.put(analysis, new TreeMap<String, PersonIdRecorder>());
        }
        TreeMap<String, Population> scenarioPlans = new TreeMap<String, Population>();
        TreeMap<String, Network> scenarioNetworks = new TreeMap<String, Network>();

        PersonIdRecorder personIdRecorder = null;
        PersonFilter filterAlgorithm = null;

        for (String scenarioName : this.scenarioNames) {

            ScenarioImpl scenario = (ScenarioImpl) ScenarioUtils.createScenario(ConfigUtils.createConfig());
            Network network = scenario.getNetwork();
            new MatsimNetworkReader(scenario).readFile(this.networkInputFilenames.get(scenarioName));
            scenarioNetworks.put(scenarioName, network);

            //Plans plans = playground.meisterk.MyRuns.initMatsimAgentPopulation(plansInputFilenames.get(scenarioName), false, null, network);
            PopulationImpl plans = (PopulationImpl) scenario.getPopulation();
            PopulationReader plansReader = new MatsimPopulationReader(scenario);
            plansReader.readFile(this.plansInputFilenames.get(scenarioName));
            plans.printPlansCount();

            scenarioPlans.put(scenarioName, plans);

            for (Integer analysis : this.analysisNames.keySet()) {

                personIdRecorder = new PersonIdRecorder();

                // distinguish person filtering by analysis type
                switch (analysis.intValue()) {
                case TRANSIT_AGENTS_ANALYSIS_NAME:
                    filterAlgorithm = new PersonIdFilter(TRANSIT_PERSON_ID_PATTERN, personIdRecorder);
                    break;
                case NON_TRANSIT_AGENTS_ANALYSIS_NAME:
                    filterAlgorithm = new PersonIdFilter(NON_TRANSIT_PERSON_ID_PATTERN, personIdRecorder);
                    break;
                case ROUTE_SWITCHERS_ANALYSIS_NAME:
                    RouteLinkFilter routeLinkFilter = new RouteLinkFilter(personIdRecorder);
                    filterAlgorithm = new SelectedPlanFilter(routeLinkFilter);

                    for (Id linkId : this.linkSets.get(scenarioName)) {
                        routeLinkFilter.addLink(linkId);
                    }
                    break;
                case WESTSTRASSE_NEIGHBORS_ANALYSIS_NAME:
                    ActLinkFilter homeAtTheWeststrasseFilter = new ActLinkFilter(".*h.*", personIdRecorder);
                    filterAlgorithm = new SelectedPlanFilter(homeAtTheWeststrasseFilter);

                    for (Id linkId : this.weststrasseLinkIds) {
                        homeAtTheWeststrasseFilter.addLink(linkId);
                    }
                    break;
                default:
                    break;
                }

                personIdRecorders.get(analysis).put(scenarioName, personIdRecorder);
                plans.addAlgorithm(filterAlgorithm);
            }
            plans.runAlgorithms();

        }

        // make this nicer, because all analyses are of the same kind :-)
        HashSet<Id> routeSwitchersPersonIds = (HashSet<Id>) personIdRecorders.get(ROUTE_SWITCHERS_ANALYSIS_NAME)
                .get(this.scenarioNameAfter).getIds().clone();
        routeSwitchersPersonIds.retainAll(
                personIdRecorders.get(ROUTE_SWITCHERS_ANALYSIS_NAME).get(this.scenarioNameBefore).getIds());

        HashSet<Id> neighborsPersonIds = personIdRecorders.get(WESTSTRASSE_NEIGHBORS_ANALYSIS_NAME)
                .get(this.scenarioNameBefore).getIds();
        HashSet<Id> transitAgentsIds = personIdRecorders.get(TRANSIT_AGENTS_ANALYSIS_NAME)
                .get(this.scenarioNameBefore).getIds();
        HashSet<Id> nonTransitAgentsIds = personIdRecorders.get(NON_TRANSIT_AGENTS_ANALYSIS_NAME)
                .get(this.scenarioNameBefore).getIds();

        log.info("Agents before: " + personIdRecorders.get(ROUTE_SWITCHERS_ANALYSIS_NAME)
                .get(this.scenarioNameBefore).getIds().size());
        log.info("Agents after: "
                + personIdRecorders.get(ROUTE_SWITCHERS_ANALYSIS_NAME).get(this.scenarioNameAfter).getIds().size());
        log.info("Route switchers: " + routeSwitchersPersonIds.size());
        log.info("number of neighbors: " + neighborsPersonIds.size());
        log.info("number of transit agents: " + transitAgentsIds.size());
        log.info("number of non transit agents: " + nonTransitAgentsIds.size());

        Iterator<Id> personIterator = null;
        //      HashSet<Id> subPop = new HashSet<Id>();
        for (Integer analysis : this.analysisNames.keySet()) {

            ArrayList<CaseStudyResult> results = new ArrayList<CaseStudyResult>();
            for (String scenarioName : this.scenarioNames) {

                ScenarioImpl subScenario = (ScenarioImpl) ScenarioUtils.createScenario(ConfigUtils.createConfig());
                subScenario.setNetwork(scenarioNetworks.get(scenarioName));
                Population plansSubPop = subScenario.getPopulation();
                switch (analysis.intValue()) {
                case TRANSIT_AGENTS_ANALYSIS_NAME:
                    personIterator = transitAgentsIds.iterator();
                    break;
                case NON_TRANSIT_AGENTS_ANALYSIS_NAME:
                    personIterator = nonTransitAgentsIds.iterator();
                    break;
                case ROUTE_SWITCHERS_ANALYSIS_NAME:
                    personIterator = routeSwitchersPersonIds.iterator();
                    break;
                case WESTSTRASSE_NEIGHBORS_ANALYSIS_NAME:
                    personIterator = neighborsPersonIds.iterator();
                    break;
                default:
                    break;
                }

                while (personIterator.hasNext()) {
                    try {
                        plansSubPop
                                .addPerson(scenarioPlans.get(scenarioName).getPersons().get(personIterator.next()));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                Activity homeActivity = null;
                if (analysis.intValue() == ROUTE_SWITCHERS_ANALYSIS_NAME) {
                    if (scenarioName.equals(this.scenarioNames[0])) {
                        this.routeSwitchersLines.add("person\thome_link\thome_x\thome_y");
                        for (Person person : plansSubPop.getPersons().values()) {
                            for (PlanElement pe : person.getSelectedPlan().getPlanElements()) {
                                if (pe instanceof Activity) {
                                    homeActivity = (Activity) pe;
                                    if (Pattern.matches(".*h.*", homeActivity.getType())) {
                                        continue;
                                    }
                                }
                            }
                            this.routeSwitchersLines
                                    .add(person.getId().toString() + "\t" + homeActivity.getLinkId().toString()
                                            + "\t" + Double.toString(homeActivity.getCoord().getX()) + "\t"
                                            + Double.toString(homeActivity.getCoord().getY()));

                            //                     routeSwitchersLines.add(new String(
                            //                           person.getId() + "\t" +
                            //                           homeActivity.getLinkId().toString() + "\t" +
                            //                           homeActivity.getCoord().getX() + "\t" +
                            //                           homeActivity.getCoord().getY()
                            //                     ));
                        }
                    }
                }

                PlanAverageScore planAverageScore = new PlanAverageScore();
                planAverageScore.run(plansSubPop);
                CalcAverageTripLength calcAverageTripLength = new CalcAverageTripLength(
                        scenarioNetworks.get(scenarioName));
                calcAverageTripLength.run(plansSubPop);

                EventsManager events = EventsUtils.createEventsManager();

                CalcLegTimes calcLegTimes = new CalcLegTimes();
                events.addHandler(calcLegTimes);

                results.add(new CaseStudyResult(scenarioName, plansSubPop, calcLegTimes, planAverageScore,
                        calcAverageTripLength));

                //            EventsReaderDEQv1 eventsReader = new EventsReaderDEQv1(events);
                //            log.info("events filename: " + this.eventsInputFilenames.get(scenarioName));
                //            eventsReader.readFile(this.eventsInputFilenames.get(scenarioName));
                throw new RuntimeException("reading binary events is no longer supported.");

            }
            this.scenarioComparisonLines.add("Analysis: " + this.analysisNames.get(analysis));
            this.writeComparison(results);
            this.scenarioComparisonLines.add("");

        }

    }

    private void writeComparison(final List<CaseStudyResult> results) {

        this.scenarioComparisonLines.add("casestudy\tn_{agents}\tscore_{avg}\tt_{trip, avg}\td_{trip, avg}[m]");

        for (CaseStudyResult result : results) {

            this.scenarioComparisonLines
                    .add(result.getName() + "\t" + result.getRouteSwitchers().getPersons().size() + "\t"
                            + result.getRouteSwitchersAverageScore().getAverage() + "\t"
                            + Time.writeTime(result.calcLegTimes.getAverageTripDuration()) + "\t"
                            + result.getCalcAverageTripLength().getAverageTripLength());

        }

    }
}