diff --git a/src/main/java/de/tum/bgu/msm/MitoModelGermany.java b/src/main/java/de/tum/bgu/msm/MitoModelGermany.java new file mode 100644 index 00000000..ca8745ec --- /dev/null +++ b/src/main/java/de/tum/bgu/msm/MitoModelGermany.java @@ -0,0 +1,125 @@ +package de.tum.bgu.msm; + +import de.tum.bgu.msm.data.DataSet; +import de.tum.bgu.msm.data.travelTimes.SkimTravelTimes; +import de.tum.bgu.msm.io.input.readers.*; +import de.tum.bgu.msm.resources.Properties; +import de.tum.bgu.msm.resources.Resources; +import de.tum.bgu.msm.util.ImplementationConfig; +import de.tum.bgu.msm.util.MitoUtil; +import org.apache.log4j.Logger; + +import java.util.Random; + +/** + * Implements the Microsimulation Transport Orchestrator (MITO) + * + * @author Rolf Moeckel + * Created on Sep 18, 2016 in Munich, Germany + *

+ * To run MITO, the following data need either to be passed in from another program or + * need to be read from files and passed in (using method initializeStandAlone): + * - zones + * - autoTravelTimes + * - transitTravelTimes + * - timoHouseholds + * - retailEmplByZone + * - officeEmplByZone + * - otherEmplByZone + * - totalEmplByZone + * - sizeOfZonesInAcre + */ +public final class MitoModelGermany { + + private static final Logger logger = Logger.getLogger(MitoModelGermany.class); + private final String scenarioName; + + private DataSet dataSet; + + private MitoModelGermany(DataSet dataSet, String scenarioName) { + this.dataSet = dataSet; + this.scenarioName = scenarioName; + MitoUtil.initializeRandomNumber(); + } + + public static MitoModelGermany standAloneModel(String propertiesFile, ImplementationConfig config) { + logger.info(" Creating standalone version of MITO "); + Resources.initializeResources(propertiesFile); + MitoModelGermany model = new MitoModelGermany(new DataSet(), Resources.instance.getString(Properties.SCENARIO_NAME)); + model.readStandAlone(config); + return model; + } + + public static MitoModelGermany initializeModelFromSilo(String propertiesFile, DataSet dataSet, String scenarioName) { + logger.info(" Initializing MITO from SILO"); + Resources.initializeResources(propertiesFile); + MitoModelGermany model = new MitoModelGermany(dataSet, scenarioName); + new OmxSkimsReader(dataSet).readOnlyTransitTravelTimes(); + new OmxSkimsReader(dataSet).readSkimDistancesNMT(); + new OmxSkimsReader(dataSet).readSkimDistancesAuto(); + model.readAdditionalData(); + return model; + } + + public void run() { + long startTime = System.currentTimeMillis(); + logger.info("Started the Microsimulation Transport Orchestrator (MITO)"); + + TravelDemandGeneratorGermany ttd = new TravelDemandGeneratorGermany.Builder(dataSet).build(); + ttd.generateTravelDemand(scenarioName); + printOutline(startTime); + } + + private void readStandAlone(ImplementationConfig config) { + dataSet.setYear(Resources.instance.getInt(Properties.SCENARIO_YEAR)); + new ZonesReader(dataSet).read(); + if (Resources.instance.getBoolean(Properties.REMOVE_TRIPS_AT_BORDER)) { + new BorderDampersReader(dataSet).read(); + } + //new JobReader(dataSet, config.getJobTypeFactory()).read(); + new SchoolsReader(dataSet).read(); + new HouseholdsReaderGermany(dataSet).read(); + //new HouseholdsCoordReader(dataSet).read(); + //new PersonsReader(dataSet).read(); + //the class called Synthetic population reader: could it be renamed to PersonJobReader? + new SyntheticPopulationReaderGermany(dataSet, config.getJobTypeFactory()).read(); + dataSet.setTravelTimes(new SkimTravelTimes()); + new OmxSkimsReader(dataSet).read(); + readAdditionalData(); + } + + private void readAdditionalData() { + new TripAttractionRatesReader(dataSet).read(); + new ModeChoiceInputReader(dataSet).read(); + new EconomicStatusReader(dataSet).read(); + new TimeOfDayDistributionsReader(dataSet).read(); + new CalibrationDataReader(dataSet).read(); + new CalibrationRegionMapReader(dataSet).read(); + + } + + private void printOutline(long startTime) { + String trips = MitoUtil.customFormat(" " + "###,###", dataSet.getTrips().size()); + logger.info("A total of " + trips.trim() + " microscopic trips were generated"); + logger.info("Completed the Microsimulation Transport Orchestrator (MITO)"); + float endTime = MitoUtil.rounder(((System.currentTimeMillis() - startTime) / 60000.f), 1); + int hours = (int) (endTime / 60); + int min = (int) (endTime - 60 * hours); + logger.info("Runtime: " + hours + " hours and " + min + " minutes."); + } + + public DataSet getData() { + return dataSet; + } + + public String getScenarioName() { + return scenarioName; + } + + public void setRandomNumberGenerator(Random random) { + MitoUtil.initializeRandomNumber(random); + } + + + +} diff --git a/src/main/java/de/tum/bgu/msm/TravelDemandGeneratorGermany.java b/src/main/java/de/tum/bgu/msm/TravelDemandGeneratorGermany.java new file mode 100644 index 00000000..a2f4c7d8 --- /dev/null +++ b/src/main/java/de/tum/bgu/msm/TravelDemandGeneratorGermany.java @@ -0,0 +1,276 @@ +package de.tum.bgu.msm; + +import de.tum.bgu.msm.data.DataSet; +import de.tum.bgu.msm.data.Purpose; +import de.tum.bgu.msm.io.output.SummarizeData; +import de.tum.bgu.msm.io.output.SummarizeDataToVisualize; +import de.tum.bgu.msm.io.output.TripGenerationWriter; +import de.tum.bgu.msm.modules.Module; +import de.tum.bgu.msm.modules.modeChoice.ModeChoice; +import de.tum.bgu.msm.modules.plansConverter.MatsimPopulationGenerator; +import de.tum.bgu.msm.modules.scaling.TripScaling; +import de.tum.bgu.msm.modules.timeOfDay.TimeOfDayChoice; +import de.tum.bgu.msm.modules.travelTimeBudget.TravelTimeBudgetModule; +//import de.tum.bgu.msm.modules.tripDistribution.DestinationUtilityCalculatorFactoryImpl2; +import de.tum.bgu.msm.modules.tripDistribution.DestinationUtilityCalculatorFactoryImplGermany; +import de.tum.bgu.msm.modules.tripDistribution.TripDistribution; +import de.tum.bgu.msm.modules.tripGeneration.TripGeneration; +import de.tum.bgu.msm.modules.tripGeneration.TripsByPurposeGeneratorFactoryPersonBasedHurdle; +import de.tum.bgu.msm.resources.Properties; +import de.tum.bgu.msm.resources.Resources; +import org.apache.log4j.Logger; + +import java.util.List; + +/** + * Generates travel demand for the Microscopic Transport Orchestrator (MITO) + * + * @author Rolf Moeckel + * Created on Sep 18, 2016 in Munich, Germany + */ +public final class TravelDemandGeneratorGermany { + + private static final Logger logger = Logger.getLogger(TravelDemandGeneratorGermany.class); + private final DataSet dataSet; + + private final Module tripGenerationMandatory; + private final Module personTripAssignmentMandatory; + private final Module travelTimeBudgetMandatory; + private final Module distributionMandatory; + private final Module modeChoiceMandatory; + private final Module tripGenerationDiscretionary; + private final Module personTripAssignmentDiscretionary; + private final Module travelTimeBudgetDiscretionary; + private final Module distributionDiscretionary; + private final Module modeChoiceDiscretionary; + private final Module timeOfDayChoiceMandatory; + private final Module timeOfDayChoiceDiscretionary; + private final Module tripScaling; + private final Module matsimPopulationGenerator; + private final Module longDistanceTraffic; + + private TravelDemandGeneratorGermany( + DataSet dataSet, + Module tripGenerationMandatory, + Module personTripAssignmentMandatory, + Module travelTimeBudgetMandatory, + Module distributionMandatory, + Module modeChoiceMandatory, + Module timeOfDayChoiceMandatory, + Module tripGenerationDiscretionary, + Module personTripAssignmentDiscretionary, + Module travelTimeBudgetDiscretionary, + Module distributionDiscretionary, + Module modeChoiceDiscretionary, + Module timeOfDayChoiceDiscretionary, + Module tripScaling, + Module matsimPopulationGenerator, + Module longDistanceTraffic) { + + this.dataSet = dataSet; + this.tripGenerationMandatory = tripGenerationMandatory; + this.personTripAssignmentMandatory = personTripAssignmentMandatory; + this.travelTimeBudgetMandatory = travelTimeBudgetMandatory; + this.distributionMandatory = distributionMandatory; + this.modeChoiceMandatory = modeChoiceMandatory; + this.timeOfDayChoiceMandatory = timeOfDayChoiceMandatory; + this.tripGenerationDiscretionary = tripGenerationDiscretionary; + this.personTripAssignmentDiscretionary = personTripAssignmentDiscretionary; + this.travelTimeBudgetDiscretionary = travelTimeBudgetDiscretionary; + this.distributionDiscretionary = distributionDiscretionary; + this.modeChoiceDiscretionary = modeChoiceDiscretionary; + this.timeOfDayChoiceDiscretionary = timeOfDayChoiceDiscretionary; + this.tripScaling = tripScaling; + this.matsimPopulationGenerator = matsimPopulationGenerator; + this.longDistanceTraffic = longDistanceTraffic; + } + + + public static class Builder { + + private final DataSet dataSet; + + private Module tripGenerationMandatory; + private Module personTripAssignmentMandatory; + private Module travelTimeBudgetMandatory; + private Module distributionMandatory; + private Module modeChoiceMandatory; + private Module timeOfDayChoiceMandatory; + + private Module tripGenerationDiscretionary; + private Module personTripAssignmentDiscretionary; + private Module travelTimeBudgetDiscretionary; + private Module distributionDiscretionary; + private Module modeChoiceDiscretionary; + private Module timeOfDayChoiceDiscretionary; + + private Module tripScaling; + private Module matsimPopulationGenerator; + private Module longDistanceTraffic; + + public Builder(DataSet dataSet) { + this.dataSet = dataSet; + //from here + List purposes = Purpose.getAllPurposes(); + tripGenerationMandatory = new TripGeneration(dataSet, new TripsByPurposeGeneratorFactoryPersonBasedHurdle(), Purpose.getMandatoryPurposes()); + //personTripAssignmentMandatory = new PersonTripAssignment(dataSet, Purpose.getMandatoryPurposes()); + travelTimeBudgetMandatory = new TravelTimeBudgetModule(dataSet, Purpose.getMandatoryPurposes()); + distributionMandatory = new TripDistribution(dataSet, Purpose.getMandatoryPurposes(), false, + new DestinationUtilityCalculatorFactoryImplGermany()); + modeChoiceMandatory = new ModeChoice(dataSet, Purpose.getMandatoryPurposes()); + timeOfDayChoiceMandatory = new TimeOfDayChoice(dataSet, Purpose.getMandatoryPurposes()); + + tripGenerationDiscretionary = new TripGeneration(dataSet, new TripsByPurposeGeneratorFactoryPersonBasedHurdle(), Purpose.getDiscretionaryPurposes()); + //personTripAssignmentDiscretionary = new PersonTripAssignment(dataSet, Purpose.getDiscretionaryPurposes()); + travelTimeBudgetDiscretionary = new TravelTimeBudgetModule(dataSet, Purpose.getDiscretionaryPurposes()); + distributionDiscretionary = new TripDistribution(dataSet, Purpose.getDiscretionaryPurposes(), false, + new DestinationUtilityCalculatorFactoryImplGermany()); + modeChoiceDiscretionary = new ModeChoice(dataSet, Purpose.getDiscretionaryPurposes()); + timeOfDayChoiceDiscretionary = new TimeOfDayChoice(dataSet, Purpose.getDiscretionaryPurposes()); + //until here it must be divided into two blocks - mandatory and discretionary + + tripScaling = new TripScaling(dataSet, purposes); + matsimPopulationGenerator = new MatsimPopulationGenerator(dataSet, purposes); + } + + public TravelDemandGeneratorGermany build() { + return new TravelDemandGeneratorGermany(dataSet, + tripGenerationMandatory, + personTripAssignmentMandatory, + travelTimeBudgetMandatory, + distributionMandatory, + modeChoiceMandatory, + timeOfDayChoiceMandatory, + tripGenerationDiscretionary, + personTripAssignmentDiscretionary, + travelTimeBudgetDiscretionary, + distributionDiscretionary, + modeChoiceDiscretionary, + timeOfDayChoiceDiscretionary, + tripScaling, + matsimPopulationGenerator, + longDistanceTraffic); + } + + public void setTripGeneration(Module tripGeneration) { + this.tripGenerationMandatory = tripGeneration; + } + + public void setPersonTripAssignment(Module personTripAssignment) { + this.personTripAssignmentMandatory = personTripAssignment; + } + + public void setTravelTimeBudget(Module travelTimeBudget) { + this.travelTimeBudgetMandatory = travelTimeBudget; + } + + public void setDistribution(Module distribution) { + this.distributionMandatory = distribution; + } + + public void setModeChoice(Module modeChoice) { + this.modeChoiceMandatory = modeChoice; + } + + public void setTimeOfDayChoiceMandatory(Module timeOfDayChoiceMandatory) { + this.timeOfDayChoiceMandatory = timeOfDayChoiceMandatory; + } + + public void setTripScaling(Module tripScaling) { + this.tripScaling = tripScaling; + } + + public void setMatsimPopulationGenerator(Module matsimPopulationGenerator) { + this.matsimPopulationGenerator = matsimPopulationGenerator; + } + + public void setLongDistanceTraffic(Module longDistanceTraffic) { + this.longDistanceTraffic = longDistanceTraffic; + } + + public DataSet getDataSet() { + return dataSet; + } + + public Module getTripGeneration() { + return tripGenerationMandatory; + } + + public Module getPersonTripAssignment() { + return personTripAssignmentMandatory; + } + + public Module getTravelTimeBudget() { + return travelTimeBudgetMandatory; + } + + public Module getDistribution() { + return distributionMandatory; + } + + public Module getModeChoice() { + return modeChoiceMandatory; + } + + public Module getTimeOfDayChoiceMandatory() { + return timeOfDayChoiceMandatory; + } + + public Module getTripScaling() { + return tripScaling; + } + + public Module getMatsimPopulationGenerator() { + return matsimPopulationGenerator; + } + + public Module getLongDistanceTraffic() { + return longDistanceTraffic; + } + } + + + + public void generateTravelDemand(String scenarioName) { + + logger.info("Running Module: Microscopic Trip Generation"); + + tripGenerationMandatory.run(); + logger.info("Running Module: Travel Time Budget Calculation"); + travelTimeBudgetMandatory.run(); + logger.info("Running Module: Microscopic Trip Distribution"); + distributionMandatory.run(); + logger.info("Running Module: Trip to Mode Assignment (Mode Choice)"); + modeChoiceMandatory.run(); + logger.info("Running time of day choice"); + timeOfDayChoiceMandatory.run(); + + tripGenerationDiscretionary.run(); + logger.info("Running Module: Travel Time Budget Calculation"); + travelTimeBudgetDiscretionary.run(); + ((TravelTimeBudgetModule) travelTimeBudgetDiscretionary).adjustDiscretionaryPurposeBudgets(); + logger.info("Running Module: Microscopic Trip Distribution"); + distributionDiscretionary.run(); + logger.info("Running Module: Trip to Mode Assignment (Mode Choice)"); + modeChoiceDiscretionary.run(); + logger.info("Running time of day choice"); + timeOfDayChoiceDiscretionary.run(); + + + logger.info("Running trip scaling"); + tripScaling.run(); + + matsimPopulationGenerator.run(); + + TripGenerationWriter.writeTripsByPurposeAndZone(dataSet, scenarioName); + SummarizeDataToVisualize.writeFinalSummary(dataSet, scenarioName); + + if (Resources.instance.getBoolean(Properties.PRINT_MICRO_DATA, true)) { + SummarizeData.writeOutSyntheticPopulationWithTrips(dataSet); + SummarizeData.writeOutTrips(dataSet, scenarioName); + } + if (Resources.instance.getBoolean(Properties.CREATE_CHARTS, true)) { + SummarizeData.writeCharts(dataSet, scenarioName); + } + } +} diff --git a/src/main/java/de/tum/bgu/msm/data/MitoGender.java b/src/main/java/de/tum/bgu/msm/data/MitoGender.java index c322d2a7..f1debcc3 100644 --- a/src/main/java/de/tum/bgu/msm/data/MitoGender.java +++ b/src/main/java/de/tum/bgu/msm/data/MitoGender.java @@ -1,9 +1,12 @@ package de.tum.bgu.msm.data; +import java.util.Random; + public enum MitoGender { MALE, FEMALE; + public static MitoGender valueOf(int code) { if(code == 2) { return FEMALE; @@ -14,4 +17,67 @@ public static MitoGender valueOf(int code) { } } + //// added by Alona, to assign drivers license + public static Random rand; // was private + public static double getRandomNumberAsDouble() { + return rand.nextDouble(); + } + + public static boolean obtainLicense(MitoGender gender, int age){ + boolean license = true; // true - to assign license to everyone + int row = 1; + int threshold = 0; + if (age > 17) { + if (age < 29) { + if (gender == MitoGender.MALE) { + threshold = 86; + } else { + threshold = 87; + } + } else if (age < 39) { + if (gender == MitoGender.MALE) { + threshold = 95; + } else { + threshold = 94; + } + } else if (age < 49) { + if (gender == MitoGender.MALE) { + threshold = 97; + } else { + threshold = 95; + } + } else if (age < 59) { + if (gender == MitoGender.MALE) { + threshold = 96; + } else { + threshold = 89; + } + } else if (age < 64) { + if (gender == MitoGender.MALE) { + threshold = 95; + } else { + threshold = 86; + } + } else if (age < 74) { + if (gender == MitoGender.MALE) { + threshold = 95; + } else { + threshold = 71; + } + } else { + if (gender == MitoGender.MALE) { + threshold = 88; + } else { + threshold = 44; + } + } + //if (getRandomNumberAsDouble() * 100 < threshold) { + //license = true; + //} + } + return license; + } + + // + } diff --git a/src/main/java/de/tum/bgu/msm/data/Mode.java b/src/main/java/de/tum/bgu/msm/data/Mode.java index 077a10da..441f7b3b 100644 --- a/src/main/java/de/tum/bgu/msm/data/Mode.java +++ b/src/main/java/de/tum/bgu/msm/data/Mode.java @@ -2,6 +2,9 @@ import org.matsim.api.core.v01.TransportMode; +import java.util.Arrays; +import java.util.Collection; + public enum Mode implements Id { autoDriver, autoPassenger, diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/BorderDampersReader.java b/src/main/java/de/tum/bgu/msm/io/input/readers/BorderDampersReader.java index 304f06f0..03f24f18 100644 --- a/src/main/java/de/tum/bgu/msm/io/input/readers/BorderDampersReader.java +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/BorderDampersReader.java @@ -37,5 +37,6 @@ protected void processRecord(String[] record) { } else { logger.warn("Damper of " + damper + " refers to non-existing zone " + zone + ". Ignoring it."); } + //return null; } } diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/CalibrationDataReader.java b/src/main/java/de/tum/bgu/msm/io/input/readers/CalibrationDataReader.java index 4abdbd6b..cfc83383 100644 --- a/src/main/java/de/tum/bgu/msm/io/input/readers/CalibrationDataReader.java +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/CalibrationDataReader.java @@ -6,7 +6,6 @@ import de.tum.bgu.msm.resources.Resources; import de.tum.bgu.msm.util.MitoUtil; -import java.nio.file.Paths; import java.util.HashMap; public class CalibrationDataReader extends AbstractCsvReader { @@ -48,6 +47,7 @@ protected void processRecord(String[] record) { dataSet.getModeChoiceCalibrationData().getCalibrationFactors().get(region).putIfAbsent(purpose, new HashMap<>()); dataSet.getModeChoiceCalibrationData().getCalibrationFactors().get(region).get(purpose).put(mode, factor); + //return null; } @Override diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/CalibrationRegionMapReader.java b/src/main/java/de/tum/bgu/msm/io/input/readers/CalibrationRegionMapReader.java index 9c22f3d1..647fd247 100644 --- a/src/main/java/de/tum/bgu/msm/io/input/readers/CalibrationRegionMapReader.java +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/CalibrationRegionMapReader.java @@ -5,8 +5,6 @@ import de.tum.bgu.msm.resources.Resources; import de.tum.bgu.msm.util.MitoUtil; -import java.nio.file.Paths; - public class CalibrationRegionMapReader extends AbstractCsvReader { private int zoneIndex; @@ -28,6 +26,7 @@ protected void processRecord(String[] record) { String region = record[regionIndex]; dataSet.getModeChoiceCalibrationData().getZoneToRegionMap().put(zone, region); + //return null; } @Override diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/EconomicStatusReader.java b/src/main/java/de/tum/bgu/msm/io/input/readers/EconomicStatusReader.java index f998e228..ef4900fc 100644 --- a/src/main/java/de/tum/bgu/msm/io/input/readers/EconomicStatusReader.java +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/EconomicStatusReader.java @@ -96,6 +96,7 @@ protected void processRecord(String[] record) { economicStatusDefinition.put(hhSizeFactor + "_Inc6000-6600", codeInc6000_6600); economicStatusDefinition.put(hhSizeFactor + "_Inc6600-7000", codeInc6600_7000); economicStatusDefinition.put(hhSizeFactor + "_Inc7000+", codeInc7000plus); + //return null; } private int getEconomicStatus(MitoHousehold hh) { diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/ExternalZonesReader.java b/src/main/java/de/tum/bgu/msm/io/input/readers/ExternalZonesReader.java index ee780217..e1a05633 100644 --- a/src/main/java/de/tum/bgu/msm/io/input/readers/ExternalZonesReader.java +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/ExternalZonesReader.java @@ -63,6 +63,7 @@ protected void processRecord(String[] record) { feature = null; } zones.put(id, new ExternalFlowZone(id, coordinates, type, feature)); + //return null; } @Override diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/GenericCsvReader.java b/src/main/java/de/tum/bgu/msm/io/input/readers/GenericCsvReader.java index 2a025866..52dc75cc 100644 --- a/src/main/java/de/tum/bgu/msm/io/input/readers/GenericCsvReader.java +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/GenericCsvReader.java @@ -37,6 +37,7 @@ protected void processRecord(String[] record) { table.put(currentRow, i, record[i]); } currentRow++; + //return null; } @Override diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/HouseholdsCoordReader.java b/src/main/java/de/tum/bgu/msm/io/input/readers/HouseholdsCoordReader.java index dfbc2b4c..32725ac9 100644 --- a/src/main/java/de/tum/bgu/msm/io/input/readers/HouseholdsCoordReader.java +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/HouseholdsCoordReader.java @@ -8,8 +8,13 @@ import de.tum.bgu.msm.util.MitoUtil; import org.apache.log4j.Logger; import org.locationtech.jts.geom.Coordinate; +import org.matsim.api.core.v01.network.Node; +import org.opengis.feature.simple.SimpleFeature; import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Created by Qin on 02.07.2018. @@ -20,6 +25,9 @@ public class HouseholdsCoordReader extends AbstractCsvReader { private int posCoordX = -1; private int posCoordY = -1; private int posTAZId = -1; + private final Map> nodesByZone = new ConcurrentHashMap<>(); + + private SimpleFeature shapeFeature; // Alona added private static final Logger logger = Logger.getLogger(HouseholdsCoordReader.class); @@ -46,6 +54,7 @@ protected void processHeader(String[] header) { protected void processRecord(String[] record) { int hhId = Integer.parseInt(record[posHHId]); + //vacant dwellings if (hhId > 0) { MitoHousehold hh = dataSet.getHouseholds().get(hhId); @@ -58,6 +67,8 @@ protected void processRecord(String[] record) { if(zone == null) { logger.warn(String.format("Household %d is supposed to live in zone %d but this zone does not exist.", hhId, taz)); } + + Coordinate homeLocation = new Coordinate( Double.parseDouble(record[posCoordX]), Double.parseDouble(record[posCoordY])); hh.setHomeLocation(homeLocation); @@ -65,4 +76,5 @@ protected void processRecord(String[] record) { zone.addHousehold(); } } + } diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/HouseholdsReaderGermany.java b/src/main/java/de/tum/bgu/msm/io/input/readers/HouseholdsReaderGermany.java new file mode 100644 index 00000000..f5880f6b --- /dev/null +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/HouseholdsReaderGermany.java @@ -0,0 +1,86 @@ +package de.tum.bgu.msm.io.input.readers; + +import de.tum.bgu.msm.data.DataSet; +import de.tum.bgu.msm.data.MitoHousehold; +import de.tum.bgu.msm.data.MitoZone; +import de.tum.bgu.msm.io.input.AbstractCsvReader; +import de.tum.bgu.msm.resources.Resources; +import de.tum.bgu.msm.util.MitoUtil; +import org.apache.log4j.Logger; +import org.locationtech.jts.geom.Coordinate; + +import java.nio.file.Path; + +/** + * Created by Nico on 17.07.2017. + */ +public class HouseholdsReaderGermany extends AbstractCsvReader { + + private int posId = -1; + private int posTaz = -1; + private int posHHSize = -1; + private int posAutos = -1; + private int posCoordX = -1; + private int posCoordY = -1; + + private static final Logger logger = Logger.getLogger(HouseholdsReaderGermany.class); + + public HouseholdsReaderGermany(DataSet dataSet) { + super(dataSet); + } + + public int getPosTaz () { + return this.posTaz; + } + + @Override + public void read() { + logger.info(" Reading household micro data from ascii file"); + Path filePath = Resources.instance.getHouseholdsFilePath(); + super.read(filePath, ","); + } + + @Override + protected void processHeader(String[] header) { + posId = MitoUtil.findPositionInArray("hhid", header); + posTaz = MitoUtil.findPositionInArray("zone", header); + posHHSize = MitoUtil.findPositionInArray("hhSize", header); + posAutos = MitoUtil.findPositionInArray("autos", header); + posCoordX = MitoUtil.findPositionInArray("coordX", header); + posCoordY = MitoUtil.findPositionInArray("coordY", header); + } + + @Override + protected void processRecord(String[] record) { + int id = Integer.parseInt(record[posId]); + int autos = Integer.parseInt(record[posAutos]); + MitoHousehold hh = new MitoHousehold(id, 0, autos); + dataSet.addHousehold(hh); + + //int hhId = Integer.parseInt(record[posHHId]); + + + //vacant dwellings + if (id > 0) { + //MitoHousehold hh = dataSet.getHouseholds().get(id); + if (hh == null) { + logger.warn(String.format("Household %d does not exist in mito.", id)); + return; + } + int taz = Integer.parseInt(record[posTaz]); + MitoZone zone = dataSet.getZones().get(taz); + if(zone == null) { + logger.warn(String.format("Household %d is supposed to live in zone %d but this zone does not exist.", id, taz)); + } + + //Coordinate homeLocation = new Coordinate().getRandomCoord(); + //Coordinate homeLocation = zone.getRandomCoord(MitoUtil.getRandomObject()); + + Coordinate homeLocation = new Coordinate( + Double.parseDouble(record[posCoordX]), Double.parseDouble(record[posCoordY])); + hh.setHomeLocation(homeLocation); + hh.setHomeZone(zone); + zone.addHousehold(); + } + } +} diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/JobReader.java b/src/main/java/de/tum/bgu/msm/io/input/readers/JobReader.java index 1209bd50..72747534 100644 --- a/src/main/java/de/tum/bgu/msm/io/input/readers/JobReader.java +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/JobReader.java @@ -59,14 +59,15 @@ protected void processRecord(String[] record) { MitoZone zone = dataSet.getZones().get(zoneId); if (zone == null) { logger.warn(String.format("Job %d refers to non-existing zone %d! Ignoring it.", id, zoneId)); - return; + //return null; } try { zone.addEmployeeForType(factory.getType(type.toUpperCase().replaceAll("\"",""))); } catch (IllegalArgumentException e) { - logger.error("Job Type " + type + " used in job microdata but is not defined"); + //logger.error("Job Type " + type + " used in job microdata but is not defined"); } + Coordinate coordinate = (new Coordinate(Double.parseDouble(record[posJobCoordX]), Double.parseDouble(record[posJobCoordY]))); diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/OmxSkimsReader.java b/src/main/java/de/tum/bgu/msm/io/input/readers/OmxSkimsReader.java index aa998dde..b1788390 100644 --- a/src/main/java/de/tum/bgu/msm/io/input/readers/OmxSkimsReader.java +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/OmxSkimsReader.java @@ -44,16 +44,16 @@ public void readOnlyTransitTravelTimes(){ } private void readTravelTimeSkims() { - ((SkimTravelTimes) dataSet.getTravelTimes()).readSkim("car", Resources.instance.getRelativePath(Properties.AUTO_PEAK_SKIM).toString(), "timeByTime", 1/60.); + ((SkimTravelTimes) dataSet.getTravelTimes()).readSkim("car", Resources.instance.getRelativePath(Properties.AUTO_PEAK_SKIM).toString(), "mat1", 1/60.); ((SkimTravelTimes) dataSet.getTravelTimes()).readSkim("bus", Resources.instance.getRelativePath(Properties.BUS_TRAVEL_TIME_SKIM).toString(), "mat1", 1/60.); ((SkimTravelTimes) dataSet.getTravelTimes()).readSkim("tramMetro", Resources.instance.getRelativePath(Properties.TRAM_METRO_TRAVEL_TIME_SKIM).toString(), "mat1", 1/60.); ((SkimTravelTimes) dataSet.getTravelTimes()).readSkim("train", Resources.instance.getRelativePath(Properties.TRAIN_TRAVEL_TIME_SKIM).toString(), "mat1", 1/60.); } private void readTravelDistances(){ - IndexedDoubleMatrix2D distanceSkimAuto = AbstractOmxReader.readAndConvertToDoubleMatrix(Resources.instance.getRelativePath(Properties.AUTO_TRAVEL_DISTANCE_SKIM).toString(),"distanceByTime", 1. / 1000.); + IndexedDoubleMatrix2D distanceSkimAuto = AbstractOmxReader.readAndConvertToDoubleMatrix(Resources.instance.getRelativePath(Properties.AUTO_TRAVEL_DISTANCE_SKIM).toString(),"mat1", 1. / 1000.); dataSet.setTravelDistancesAuto(new MatrixTravelDistances(distanceSkimAuto)); - IndexedDoubleMatrix2D distanceSkimNMT = AbstractOmxReader.readAndConvertToDoubleMatrix(Resources.instance.getRelativePath(Properties.NMT_TRAVEL_DISTANCE_SKIM).toString(),"distanceByDistance", 1. / 1000.); + IndexedDoubleMatrix2D distanceSkimNMT = AbstractOmxReader.readAndConvertToDoubleMatrix(Resources.instance.getRelativePath(Properties.NMT_TRAVEL_DISTANCE_SKIM).toString(),"mat1", 1. / 1000.); dataSet.setTravelDistancesNMT(new MatrixTravelDistances(distanceSkimNMT)); } } diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/PersonsReader.java b/src/main/java/de/tum/bgu/msm/io/input/readers/PersonsReader.java index c19e880a..8e539518 100644 --- a/src/main/java/de/tum/bgu/msm/io/input/readers/PersonsReader.java +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/PersonsReader.java @@ -69,7 +69,7 @@ public void processRecord(String[] record) { if(!dataSet.getHouseholds().containsKey(hhid)) { logger.warn("Person " + id + " refers to non-existing household " + hhid + ". Ignoring this person."); - return; + //return null; } MitoHousehold hh = dataSet.getHouseholds().get(hhid); @@ -84,7 +84,11 @@ public void processRecord(String[] record) { final int workplace = Integer.parseInt(record[posWorkplaceId]); final int school = Integer.parseInt(record[posSchoolId]); - final boolean driversLicense = Boolean.parseBoolean(record[posLicence]); + //final boolean driversLicense = Boolean.parseBoolean(record[posLicence]); + final boolean driversLicense = MitoGender.obtainLicense(mitoGender, age); // new, added by Alona, Quick fix for drivers license + + + //mito uses monthly income, while SILO uses annual income int monthlyIncome_EUR = Integer.parseInt(record[posIncome])/12; @@ -97,14 +101,14 @@ public void processRecord(String[] record) { if(dataSet.getJobs().containsKey(workplace)) { occupation = (dataSet.getJobs().get(workplace)); } else { - logger.warn("Person " + id + " declared as student does not have a valid school!"); + logger.warn("Person " + id + " declared as worker does not have a valid job!"); } break; case STUDENT: if(dataSet.getSchools().containsKey(school)) { occupation = (dataSet.getSchools().get(school)); } else { - logger.warn("Person " + id + " declared as student does not have a valid school!"); + //logger.warn("Person " + id + " declared as student does not have a valid school!"); } break; case UNEMPLOYED: diff --git a/src/main/java/de/tum/bgu/msm/io/input/readers/SyntheticPopulationReaderGermany.java b/src/main/java/de/tum/bgu/msm/io/input/readers/SyntheticPopulationReaderGermany.java new file mode 100644 index 00000000..17013e38 --- /dev/null +++ b/src/main/java/de/tum/bgu/msm/io/input/readers/SyntheticPopulationReaderGermany.java @@ -0,0 +1,189 @@ +package de.tum.bgu.msm.io.input.readers; + +import de.tum.bgu.msm.data.*; +import de.tum.bgu.msm.data.jobTypes.JobTypeFactory; +import de.tum.bgu.msm.io.input.AbstractCsvReader; +import de.tum.bgu.msm.resources.Resources; +import org.apache.log4j.Logger; +import org.locationtech.jts.geom.Coordinate; + +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + + +public class SyntheticPopulationReaderGermany extends AbstractCsvReader { + + private static final Logger logger = Logger.getLogger(SyntheticPopulationReaderGermany.class); + private final JobTypeFactory factory; + + // Person + private int posId = -1; + private int posHhId = -1; + private int posAge = -1; + private int posSex = -1; + private int posOccupation = -1; + private int posWorkplaceId = -1; + private int posLicence = -1; + private int posIncome = -1; + private int posType = -1; + private int posSchoolId = -1; + private int posJobId = -1; + private int posZone = -1; + private int posJobCoordX = -1; + private int posJobCoordY = -1; + //private int posWorker = -1; // question + + private int occupationCounter = 0; + + + // constructor + public SyntheticPopulationReaderGermany(DataSet dataSet, JobTypeFactory factory) { + super(dataSet); + this.factory = factory; + } + + + @Override + public void read() { + logger.info(" Reading person micro data from ascii file"); + Path filePath = Resources.instance.getPersonsFilePath(); + super.read(filePath, ","); + int noIncomeHouseholds = 0; + for(MitoHousehold household: dataSet.getHouseholds().values()) { + if(household.getMonthlyIncome_EUR() == 0) { + noIncomeHouseholds++; + } + } + if(noIncomeHouseholds > 0) { + logger.warn("There are " + noIncomeHouseholds + " households with no income after reading all persons."); + } + logger.info("There are " + occupationCounter + " persons without occupation (student or worker)."); + } + + @Override + public void processHeader(String[] header) { + List headerList = Arrays.asList(header); + posId = headerList.indexOf("id"); + //posWorker = headerList.indexOf("id"); // + posHhId = headerList.indexOf("hhid"); + posAge = headerList.indexOf("age"); + posSex = headerList.indexOf("gender"); + posOccupation = headerList.indexOf("occupation"); + posLicence = headerList.indexOf("driversLicense"); + posWorkplaceId = headerList.indexOf("JobId"); + posIncome = headerList.indexOf("income"); + //jobType + posType = headerList.indexOf("jobType"); + posSchoolId = headerList.indexOf("schoolId"); + //jobId + posJobId = headerList.indexOf("JobId"); + //jobZone + posZone = headerList.indexOf("zone"); + //jobCoordX & jobCoordY + posJobCoordX = headerList.indexOf("jobCoordX"); + posJobCoordY = headerList.indexOf("jobCoordY"); + + + } + + @Override + public void processRecord(String[] record) { + + final int id = Integer.parseInt(record[posId]); + final int hhid = Integer.parseInt(record[posHhId]); + + if(!dataSet.getHouseholds().containsKey(hhid)) { + logger.warn("Person " + id + " refers to non-existing household " + hhid + ". Ignoring this person."); + //return null; + } + MitoHousehold hh = dataSet.getHouseholds().get(hhid); + + final int age = Integer.parseInt(record[posAge]); + + final int genderCode = Integer.parseInt(record[posSex]); + MitoGender mitoGender = MitoGender.valueOf(genderCode); + + final int occupationCode = Integer.parseInt(record[posOccupation]); + MitoOccupationStatus mitoOccupationStatus = MitoOccupationStatus.valueOf(occupationCode); + + + //int workplace = -1; + //try{ + // workplace = Integer.parseInt(record[posWorkplaceId]); + // } catch (Exception e ){ + //logger.warn("No Work ID"); + //} + + //final int workplace = Integer.parseInt(record[posWorkplaceId]); + final int school = Integer.parseInt(record[posSchoolId]); + + final boolean driversLicense = Boolean.parseBoolean(record[posLicence]); + //final boolean driversLicense = MitoGender.obtainLicense(mitoGender, age); // new, added by Alona, Quick fix for drivers license + + + //mito uses monthly income, while SILO uses annual income + int monthlyIncome_EUR = Integer.parseInt(record[posIncome])/12; + hh.addIncome(monthlyIncome_EUR); + + MitoOccupation occupation = null; + + switch (mitoOccupationStatus) { + case WORKER: + //if(dataSet.getJobs().containsKey(workplace)) { + int jobId = Integer.parseInt(record[posJobId]); + int zoneId = Integer.parseInt(record[posZone]); + String type = record[posType]; + MitoZone zone = dataSet.getZones().get(zoneId); + if (zone == null) { + logger.warn(String.format("Job %d refers to non-existing zone %d! Ignoring it.",jobId, zoneId)); + //return null; + } + try { + zone.addEmployeeForType(factory.getType(type.toUpperCase().replaceAll("\"",""))); + } catch (IllegalArgumentException e) { + //logger.error("Job Type " + type + " used in job microdata but is not defined"); + } + + //Coordinate coordinate = zone.getRandomCoord(MitoUtil.getRandomObject()); + Coordinate coordinate = (new Coordinate(Double.parseDouble(record[posJobCoordX]), + Double.parseDouble(record[posJobCoordY]))); + + //Coordinate coordinate = new Coordinate(Double.parseDouble(record[posJobCoordX]), Double.parseDouble(record[posJobCoordY])); + + MitoJob job = new MitoJob(zone, coordinate, jobId); + dataSet.addJob(job); + + int workplace = Integer.parseInt(record[posWorkplaceId]); + occupation = (dataSet.getJobs().get(workplace)); + + /*} else { + logger.warn("Person " + id + " declared as worker does not have a valid job!"); + }*/ + break; + case STUDENT: + if(dataSet.getSchools().containsKey(school)) { + occupation = (dataSet.getSchools().get(school)); + } else { + //logger.warn("Person " + id + " declared as student does not have a valid school!"); + } + break; + case UNEMPLOYED: + default: + logger.debug("Person " + id + " does not have an occupation."); + occupationCounter++; + break; + } + MitoPerson pp = new MitoPerson(id, mitoOccupationStatus, occupation, age, mitoGender, driversLicense); + + //int worker = Integer.parseInt(record[posOccupation]); //int worker = Integer.parseInt(record[posWorker]); + + //if (worker == 1) { + + + //MitoPerson pp = new MitoPerson(id, mitoOccupationStatus, occupation, age, mitoGender, driversLicense); + + hh.addPerson(pp); + dataSet.addPerson(pp); + } +} diff --git a/src/main/java/de/tum/bgu/msm/modules/tripDistribution/DestinationUtilityCalculatorFactoryImplGermany.java b/src/main/java/de/tum/bgu/msm/modules/tripDistribution/DestinationUtilityCalculatorFactoryImplGermany.java new file mode 100644 index 00000000..02957ab4 --- /dev/null +++ b/src/main/java/de/tum/bgu/msm/modules/tripDistribution/DestinationUtilityCalculatorFactoryImplGermany.java @@ -0,0 +1,11 @@ +package de.tum.bgu.msm.modules.tripDistribution; + +import de.tum.bgu.msm.data.Purpose; + +public class DestinationUtilityCalculatorFactoryImplGermany implements DestinationUtilityCalculatorFactory { + + @Override + public DestinationUtilityCalculator createDestinationUtilityCalculator(Purpose purpose, double travelDistanceCalibrationK, double impendanceCalibrationK){ + return new DestinationUtilityCalculatorImplGermany(purpose,travelDistanceCalibrationK, impendanceCalibrationK); + } +} diff --git a/src/main/java/de/tum/bgu/msm/modules/tripDistribution/DestinationUtilityCalculatorImplGermany.java b/src/main/java/de/tum/bgu/msm/modules/tripDistribution/DestinationUtilityCalculatorImplGermany.java new file mode 100644 index 00000000..22e82376 --- /dev/null +++ b/src/main/java/de/tum/bgu/msm/modules/tripDistribution/DestinationUtilityCalculatorImplGermany.java @@ -0,0 +1,91 @@ +package de.tum.bgu.msm.modules.tripDistribution; + +import de.tum.bgu.msm.data.Purpose; + +public class DestinationUtilityCalculatorImplGermany implements DestinationUtilityCalculator { + + private final static double TRAVEL_DISTANCE_PARAM_HBW = -0.01 * 0.545653257377378; + private final static double IMPEDANCE_PARAM_HBW = 20; + + private final static double TRAVEL_DISTANCE_PARAM_HBE = -0.01 * 1.09211334287783; + private final static double IMPEDANCE_PARAM_HBE = 20; + + private final static double TRAVEL_DISTANCE_PARAM_HBS = -0.01 * 1.382831732; + private final static double IMPEDANCE_PARAM_HBS = 20; + + private final static double TRAVEL_DISTANCE_PARAM_HBO = -0.01 * 1.02679034779653; + private final static double IMPEDANCE_PARAM_HBO = 20; + + private final static double TRAVEL_DISTANCE_PARAM_HBR = -0.01 * 0.874195571671594; + private final static double IMPEDANCE_PARAM_HBR = 20; + + private final static double travelDistanceParamNhbw = -0.01 * 0.993491317833469; + private final static double impedanceParamNhbw = 20; + + private final static double travelDistanceParamNhbo = -0.01 * 0.853890986777326; + private final static double impedanceParamNhbo = 20; + + private double distanceParam; + private double impedanceParam; + private double maxDistance_km; + private double attractionParam = 1.; + + DestinationUtilityCalculatorImplGermany(Purpose purpose, double travelDistanceCalibrationK, double impendanceCalibrationK) { + switch (purpose) { + case HBW: + distanceParam = TRAVEL_DISTANCE_PARAM_HBW; + impedanceParam = IMPEDANCE_PARAM_HBW; + //maxDistance_km = 200.0; + break; + case HBE: + distanceParam = TRAVEL_DISTANCE_PARAM_HBE; + impedanceParam = IMPEDANCE_PARAM_HBE; + //maxDistance_km = 200.0; + break; + case HBS: + distanceParam = TRAVEL_DISTANCE_PARAM_HBS; + impedanceParam = IMPEDANCE_PARAM_HBS; + //maxDistance_km = 40.; + break; + case HBO: + distanceParam = TRAVEL_DISTANCE_PARAM_HBO; + impedanceParam = IMPEDANCE_PARAM_HBO; + //maxDistance_km = 40.; + break; + case HBR: + distanceParam = TRAVEL_DISTANCE_PARAM_HBR; + impedanceParam = IMPEDANCE_PARAM_HBR; + //maxDistance_km = 40.; + break; + case NHBW: + distanceParam = travelDistanceParamNhbw; + impedanceParam = impedanceParamNhbw; + //maxDistance_km = 40.; + break; + case NHBO: + distanceParam = travelDistanceParamNhbo; + impedanceParam = impedanceParamNhbo; + //maxDistance_km = 40.; + break; + case AIRPORT: + default: + throw new RuntimeException("not implemented!"); + } + + distanceParam = distanceParam * travelDistanceCalibrationK; + impedanceParam = impedanceParam * impendanceCalibrationK; + + } + + @Override + public double calculateUtility(double attraction, double travelDistance) { + if(attraction == 0) { + return 0.; + } + //if(travelDistance > maxDistance_km){ + // return 0.; + //} + double impedance = impedanceParam * Math.exp(distanceParam * travelDistance); + return Math.exp(impedance) * Math.pow(attraction, attractionParam); + } +} diff --git a/src/main/java/de/tum/bgu/msm/modules/tripDistribution/TripDistributionCalibration.java b/src/main/java/de/tum/bgu/msm/modules/tripDistribution/TripDistributionCalibration.java index 256b3865..7e45874a 100644 --- a/src/main/java/de/tum/bgu/msm/modules/tripDistribution/TripDistributionCalibration.java +++ b/src/main/java/de/tum/bgu/msm/modules/tripDistribution/TripDistributionCalibration.java @@ -1,24 +1,18 @@ package de.tum.bgu.msm.modules.tripDistribution; -import com.google.common.math.Quantiles; import de.tum.bgu.msm.data.DataSet; import de.tum.bgu.msm.data.MitoOccupationStatus; import de.tum.bgu.msm.data.MitoTrip; import de.tum.bgu.msm.data.Purpose; import de.tum.bgu.msm.modules.Module; import de.tum.bgu.msm.resources.Resources; -import org.apache.commons.math.exception.MathIllegalNumberException; -import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; -import java.security.Principal; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.DoubleStream; public class TripDistributionCalibration extends Module { diff --git a/src/main/java/de/tum/bgu/msm/modules/tripDistribution/TripDistributionCalibrationGermany.java b/src/main/java/de/tum/bgu/msm/modules/tripDistribution/TripDistributionCalibrationGermany.java new file mode 100644 index 00000000..b97df95b --- /dev/null +++ b/src/main/java/de/tum/bgu/msm/modules/tripDistribution/TripDistributionCalibrationGermany.java @@ -0,0 +1,132 @@ +package de.tum.bgu.msm.modules.tripDistribution; + +import de.tum.bgu.msm.data.DataSet; +import de.tum.bgu.msm.data.MitoOccupationStatus; +import de.tum.bgu.msm.data.MitoTrip; +import de.tum.bgu.msm.data.Purpose; +import de.tum.bgu.msm.modules.Module; +import de.tum.bgu.msm.resources.Resources; + +import java.io.FileNotFoundException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class TripDistributionCalibrationGermany extends Module { + + private Map observedAverageDistances = new HashMap<>(); + private Map simulatedAverageDistances = new HashMap<>(); + private Map travelDistanceParameters; + private Map impendanceParameters; + private PrintWriter pw = null; + private int iteration; + + public TripDistributionCalibrationGermany(DataSet dataSet, List purposes, + Map travelDistanceParameters, + Map impendanceParameters) { + + super(dataSet, purposes); + iteration = 0; + observedAverageDistances.put(Purpose.HBE, 7.29); + observedAverageDistances.put(Purpose.HBW, 18.1); + observedAverageDistances.put(Purpose.HBO, 7.96); + observedAverageDistances.put(Purpose.HBR, 9.76); + observedAverageDistances.put(Purpose.HBS, 6.46); + observedAverageDistances.put(Purpose.NHBO, 7.47); + observedAverageDistances.put(Purpose.NHBW, 9.54); + + String purposesString = ""; + for (Purpose purpose : purposes) { + purposesString += "_" + purpose.toString(); + } + + this.impendanceParameters = impendanceParameters; + this.travelDistanceParameters = travelDistanceParameters; + + String path = Resources.instance.getBaseDirectory().toString() + "/scenOutput/"; + + try { + pw = new PrintWriter(path + "dc_calibration" + purposesString + ".csv"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + pw.println("iteration,purpose,observed,simulated,factorDistance,factorImpedance"); + + } + + + public void update(int iteration) { + + for (Purpose purpose : purposes) { + + int count = 0; + double sum = 0; + List tripsThisPurpose = + dataSet.getTrips().values().stream().filter(t -> t.getTripPurpose().equals(purpose)).collect(Collectors.toList()); + + if (Purpose.getMandatoryPurposes().contains(purpose)) { + tripsThisPurpose.removeIf(trip -> trip.getPerson().getMitoOccupationStatus().equals(MitoOccupationStatus.WORKER) || + trip.getPerson().getMitoOccupationStatus().equals(MitoOccupationStatus.STUDENT)); + } + + + for (MitoTrip trip : tripsThisPurpose) { + if (dataSet.getTravelDistancesAuto(). + getTravelDistance(trip.getTripOrigin().getZoneId(), trip.getTripDestination().getZoneId()) < 2000) { + count++; + sum += dataSet.getTravelDistancesAuto(). + getTravelDistance(trip.getTripOrigin().getZoneId(), trip.getTripDestination().getZoneId()); + } + } + + double avg = sum / count; + + //double[] distances = tripsThisPurpose.stream().mapToDouble(this::getDistanceOfThisTrip).toArray(); + + + //double avg = Quantiles.median().compute(distances); + + + simulatedAverageDistances.put(purpose, avg); + double ratio = avg / observedAverageDistances.get(purpose); //greater than 1 if the model simulates too long trips + // - in this case, the parameter of distance needs to be larger (more negative) + ratio = Math.max(ratio, 0.5); + ratio = Math.min(ratio, 2); + + + travelDistanceParameters.put(purpose, travelDistanceParameters.get(purpose) * ratio); + pw.println(iteration + "," + + purpose + "," + + observedAverageDistances.get(purpose) + "," + + simulatedAverageDistances.get(purpose) + "," + + travelDistanceParameters.get(purpose) + "," + + impendanceParameters.get(purpose)); + + } + + } + + private double getDistanceOfThisTrip(MitoTrip trip) { + return dataSet.getTravelDistancesAuto(). + getTravelDistance(trip.getTripOrigin().getZoneId(), trip.getTripDestination().getZoneId()); + } + + + @Override + public void run() { + } + + public Map getTravelDistanceParameters() { + return travelDistanceParameters; + } + + public Map getImpendanceParameters() { + return impendanceParameters; + } + + public void close() { + pw.close(); + } +} diff --git a/src/main/java/de/tum/bgu/msm/modules/tripDistribution/destinationChooser/HbeHbwDistribution.java b/src/main/java/de/tum/bgu/msm/modules/tripDistribution/destinationChooser/HbeHbwDistribution.java index d5d71b76..7a987c1d 100644 --- a/src/main/java/de/tum/bgu/msm/modules/tripDistribution/destinationChooser/HbeHbwDistribution.java +++ b/src/main/java/de/tum/bgu/msm/modules/tripDistribution/destinationChooser/HbeHbwDistribution.java @@ -69,13 +69,14 @@ public Void call() { private void findDestination(MitoHousehold household, MitoTrip trip) { if (isFixedByOccupation(trip)) { - trip.setTripDestination(trip.getPerson().getOccupation()); + trip.setTripDestination(trip.getPerson().getOccupation()); } else { TripDistribution.randomOccupationDestinationTrips.incrementAndGet(); IndexedDoubleMatrix1D probabilities = baseProbabilities.viewRow(household.getHomeZone().getId()); final int internalIndex = MitoUtil.select(probabilities.toNonIndexedArray(), random, probabilities.zSum()); final MitoZone destination = zonesCopy.get(probabilities.getIdForInternalIndex(internalIndex)); trip.setTripDestination(destination); + } } diff --git a/src/main/java/de/tum/bgu/msm/modules/tripGeneration/TripsByPurposeGeneratorSampleEnumeration.java b/src/main/java/de/tum/bgu/msm/modules/tripGeneration/TripsByPurposeGeneratorSampleEnumeration.java index d022a9b9..e09858a0 100644 --- a/src/main/java/de/tum/bgu/msm/modules/tripGeneration/TripsByPurposeGeneratorSampleEnumeration.java +++ b/src/main/java/de/tum/bgu/msm/modules/tripGeneration/TripsByPurposeGeneratorSampleEnumeration.java @@ -63,7 +63,7 @@ private void generateTripsForHousehold(MitoHousehold hh, double scaleFactorForGe return; } if (MitoUtil.getSum(tripFrequencies) == 0) { - logger.info("No trips for this hhType/Purpose: " + hhType.getId() + "/" + purpose); + //logger.info("No trips for this hhType/Purpose: " + hhType.getId() + "/" + purpose); return; } diff --git a/src/main/java/de/tum/bgu/msm/run/MitoGermany.java b/src/main/java/de/tum/bgu/msm/run/MitoGermany.java new file mode 100644 index 00000000..6abe340d --- /dev/null +++ b/src/main/java/de/tum/bgu/msm/run/MitoGermany.java @@ -0,0 +1,57 @@ +package de.tum.bgu.msm.run; + +import de.tum.bgu.msm.MitoModelGermany; +import de.tum.bgu.msm.data.DataSet; +import de.tum.bgu.msm.resources.Properties; +import de.tum.bgu.msm.resources.Resources; +import de.tum.bgu.msm.trafficAssignment.CarSkimUpdater; +import de.tum.bgu.msm.trafficAssignment.ConfigureMatsim; +import de.tum.bgu.msm.util.munich.MunichImplementationConfig; +import org.apache.log4j.Logger; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.Controler; +import org.matsim.core.scenario.MutableScenario; +import org.matsim.core.scenario.ScenarioUtils; + +public class MitoGermany { + + private static final Logger logger = Logger.getLogger(MitoGermany.class); + + public static void main(String[] args) { + logger.info("Started the Microsimulation Transport Orchestrator (MITO) based on 2017 models"); + MitoModelGermany model = MitoModelGermany.standAloneModel(args[0], MunichImplementationConfig.get()); + model.run(); + final DataSet dataSet = model.getData(); + + boolean runAssignment = Resources.instance.getBoolean(Properties.RUN_TRAFFIC_ASSIGNMENT, false); + + if (runAssignment) { + logger.info("Running traffic assignment in MATsim"); + + Config config; + if (args.length > 1 && args[1] != null) { + config = ConfigUtils.loadConfig(args[1]); + ConfigureMatsim.setDemandSpecificConfigSettings(config); + } else { + logger.warn("Using a fallback config with default values as no initial config has been provided."); + config = ConfigureMatsim.configureMatsim(); + } + + String outputSubDirectory = "scenOutput/" + model.getScenarioName() + "/" + dataSet.getYear(); + config.controler().setOutputDirectory(Resources.instance.getBaseDirectory().toString() + "/" + outputSubDirectory + "/trafficAssignment"); + + MutableScenario matsimScenario = (MutableScenario) ScenarioUtils.loadScenario(config); + matsimScenario.setPopulation(dataSet.getPopulation()); + + Controler controler = new Controler(matsimScenario); + controler.run(); + + if (Resources.instance.getBoolean(Properties.PRINT_OUT_SKIM, false)) { + CarSkimUpdater skimUpdater = new CarSkimUpdater(controler, model.getData(), model.getScenarioName()); + skimUpdater.run(); + } + } + } +} + diff --git a/src/main/java/de/tum/bgu/msm/run/calibration/CalibrateDestinationChoiceGermany.java b/src/main/java/de/tum/bgu/msm/run/calibration/CalibrateDestinationChoiceGermany.java new file mode 100644 index 00000000..7374b477 --- /dev/null +++ b/src/main/java/de/tum/bgu/msm/run/calibration/CalibrateDestinationChoiceGermany.java @@ -0,0 +1,249 @@ +package de.tum.bgu.msm.run.calibration; + +import de.tum.bgu.msm.data.DataSet; +import de.tum.bgu.msm.data.Purpose; +import de.tum.bgu.msm.data.travelTimes.SkimTravelTimes; +import de.tum.bgu.msm.io.input.readers.*; +import de.tum.bgu.msm.modules.Module; +import de.tum.bgu.msm.modules.modeChoice.ModeChoice; +import de.tum.bgu.msm.modules.timeOfDay.TimeOfDayChoice; +import de.tum.bgu.msm.modules.travelTimeBudget.TravelTimeBudgetModule; +import de.tum.bgu.msm.modules.tripDistribution.DestinationUtilityCalculatorFactoryImplGermany; +import de.tum.bgu.msm.modules.tripDistribution.TripDistribution; +import de.tum.bgu.msm.modules.tripDistribution.TripDistributionCalibrationGermany; +import de.tum.bgu.msm.modules.tripGeneration.TripGeneration; +import de.tum.bgu.msm.modules.tripGeneration.TripsByPurposeGeneratorFactoryPersonBasedHurdle; +import de.tum.bgu.msm.resources.Properties; +import de.tum.bgu.msm.resources.Resources; +import de.tum.bgu.msm.util.ImplementationConfig; +import de.tum.bgu.msm.util.MitoUtil; +import de.tum.bgu.msm.util.munich.MunichImplementationConfig; +import org.apache.log4j.Logger; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +/** + * Implements the Microsimulation Transport Orchestrator (MITO) + * + * @author Rolf Moeckel + * Created on Sep 18, 2016 in Munich, Germany + *

+ * To run MITO, the following data need either to be passed in from another program or + * need to be read from files and passed in (using method initializeStandAlone): + * - zones + * - autoTravelTimes + * - transitTravelTimes + * - timoHouseholds + * - retailEmplByZone + * - officeEmplByZone + * - otherEmplByZone + * - totalEmplByZone + * - sizeOfZonesInAcre + */ +public final class CalibrateDestinationChoiceGermany { + + private static final Logger logger = Logger.getLogger(CalibrateDestinationChoiceGermany.class); + private final String scenarioName; + + private DataSet dataSet; + + public static void main(String[] args) { + CalibrateDestinationChoiceGermany model = CalibrateDestinationChoiceGermany.standAloneModel(args[0], MunichImplementationConfig.get()); + model.run(); + } + + private CalibrateDestinationChoiceGermany(DataSet dataSet, String scenarioName) { + this.dataSet = dataSet; + this.scenarioName = scenarioName; + MitoUtil.initializeRandomNumber(); + } + + public static CalibrateDestinationChoiceGermany standAloneModel(String propertiesFile, ImplementationConfig config) { + logger.info(" Creating standalone version of MITO "); + Resources.initializeResources(propertiesFile); + CalibrateDestinationChoiceGermany model = new CalibrateDestinationChoiceGermany(new DataSet(), Resources.instance.getString(Properties.SCENARIO_NAME)); + model.readStandAlone(config); + return model; + } + + public static CalibrateDestinationChoiceGermany initializeModelFromSilo(String propertiesFile, DataSet dataSet, String scenarioName) { + logger.info(" Initializing MITO from SILO"); + Resources.initializeResources(propertiesFile); + CalibrateDestinationChoiceGermany model = new CalibrateDestinationChoiceGermany(dataSet, scenarioName); + new OmxSkimsReader(dataSet).readOnlyTransitTravelTimes(); + new OmxSkimsReader(dataSet).readSkimDistancesNMT(); + new OmxSkimsReader(dataSet).readSkimDistancesAuto(); + model.readAdditionalData(); + return model; + } + + public void run() { + long startTime = System.currentTimeMillis(); + logger.info("Started the Microsimulation Transport Orchestrator (MITO)"); + Module tripGenerationMandatory; + Module personTripAssignmentMandatory; + Module travelTimeBudgetMandatory; + Module distributionMandatory; + Module modeChoiceMandatory; + Module timeOfDayChoiceMandatory; + + Module tripGenerationDiscretionary; + Module personTripAssignmentDiscretionary; + Module travelTimeBudgetDiscretionary; + Module distributionDiscretionary; + Module modeChoiceDiscretionary; + Module timeOfDayChoiceDiscretionary; + + List purposes = Purpose.getAllPurposes(); + tripGenerationMandatory = new TripGeneration(dataSet, new TripsByPurposeGeneratorFactoryPersonBasedHurdle(), Purpose.getMandatoryPurposes()); + tripGenerationMandatory.run(); + + travelTimeBudgetMandatory = new TravelTimeBudgetModule(dataSet, Purpose.getMandatoryPurposes()); + travelTimeBudgetMandatory.run(); + + Map travelDistanceCalibrationParameters = new HashMap<>(); + Map impedanceCalibrationParameters = new HashMap<>(); + + Purpose.getMandatoryPurposes().forEach(p -> { + travelDistanceCalibrationParameters.put(p, 1.0); + impedanceCalibrationParameters.put(p, 1.0); + }); + + distributionMandatory = new TripDistribution(dataSet, Purpose.getMandatoryPurposes(), + travelDistanceCalibrationParameters, + impedanceCalibrationParameters, false, new DestinationUtilityCalculatorFactoryImplGermany()); + distributionMandatory.run(); + + TripDistributionCalibrationGermany tripDistributionCalibrationMandatory = + new TripDistributionCalibrationGermany(dataSet, Purpose.getMandatoryPurposes(), + travelDistanceCalibrationParameters, impedanceCalibrationParameters); + + int iterations = 20; + for (int iteration = 0; iteration < iterations; iteration++) { + tripDistributionCalibrationMandatory.update(iteration); + distributionMandatory = new TripDistribution(dataSet, Purpose.getMandatoryPurposes(), + tripDistributionCalibrationMandatory.getTravelDistanceParameters(), + tripDistributionCalibrationMandatory.getImpendanceParameters(), false, new DestinationUtilityCalculatorFactoryImplGermany()); + distributionMandatory.run(); + } + + tripDistributionCalibrationMandatory.close(); + + modeChoiceMandatory = new ModeChoice(dataSet, Purpose.getMandatoryPurposes()); + modeChoiceMandatory.run(); + + timeOfDayChoiceMandatory = new TimeOfDayChoice(dataSet, Purpose.getMandatoryPurposes()); + timeOfDayChoiceMandatory.run(); + + tripGenerationDiscretionary = new TripGeneration(dataSet, new TripsByPurposeGeneratorFactoryPersonBasedHurdle(), Purpose.getDiscretionaryPurposes()); + //personTripAssignmentDiscretionary = new PersonTripAssignment(dataSet, Purpose.getDiscretionaryPurposes()); + travelTimeBudgetDiscretionary = new TravelTimeBudgetModule(dataSet, Purpose.getDiscretionaryPurposes()); + + modeChoiceDiscretionary = new ModeChoice(dataSet, Purpose.getDiscretionaryPurposes()); + timeOfDayChoiceDiscretionary = new TimeOfDayChoice(dataSet, Purpose.getDiscretionaryPurposes()); + + + tripGenerationDiscretionary.run(); + //logger.info("Running Module: Person to Trip Assignment"); + //personTripAssignmentDiscretionary.run(); + logger.info("Running Module: Travel Time Budget Calculation"); + travelTimeBudgetDiscretionary.run(); + ((TravelTimeBudgetModule) travelTimeBudgetDiscretionary).adjustDiscretionaryPurposeBudgets(); + logger.info("Running Module: Microscopic Trip Distribution"); + + + Map travelDistanceCalibrationParametersDisc = new HashMap<>(); + Map impedanceCalibrationParametersDisc = new HashMap<>(); + + Purpose.getDiscretionaryPurposes().forEach(p -> { + travelDistanceCalibrationParametersDisc.put(p, 1.0); + impedanceCalibrationParametersDisc.put(p, 1.0); + }); + + distributionDiscretionary = new TripDistribution(dataSet, Purpose.getDiscretionaryPurposes(), + travelDistanceCalibrationParametersDisc, + impedanceCalibrationParametersDisc, false, + new DestinationUtilityCalculatorFactoryImplGermany()); + distributionDiscretionary.run(); + + + TripDistributionCalibrationGermany tripDistributionCalibrationDiscretionary = + new TripDistributionCalibrationGermany(dataSet, Purpose.getDiscretionaryPurposes(), + travelDistanceCalibrationParametersDisc, impedanceCalibrationParametersDisc); + + for (int iteration = 0; iteration < iterations; iteration++) { + tripDistributionCalibrationDiscretionary.update(iteration); + distributionDiscretionary = new TripDistribution(dataSet, Purpose.getDiscretionaryPurposes(), + tripDistributionCalibrationDiscretionary.getTravelDistanceParameters(), + tripDistributionCalibrationDiscretionary.getImpendanceParameters(), false, + new DestinationUtilityCalculatorFactoryImplGermany()); + distributionDiscretionary.run(); + } + + tripDistributionCalibrationDiscretionary.close(); + + + + logger.info("Running Module: Trip to Mode Assignment (Mode Choice)"); + modeChoiceDiscretionary.run(); + logger.info("Running time of day choice"); + timeOfDayChoiceDiscretionary.run(); + + + } + + private void readStandAlone(ImplementationConfig config) { + dataSet.setYear(Resources.instance.getInt(Properties.SCENARIO_YEAR)); + new ZonesReader(dataSet).read(); + if (Resources.instance.getBoolean(Properties.REMOVE_TRIPS_AT_BORDER)) { + new BorderDampersReader(dataSet).read(); + } + //new JobReader(dataSet, config.getJobTypeFactory()).read(); + new SchoolsReader(dataSet).read(); + new HouseholdsReaderGermany(dataSet).read(); + //new HouseholdsCoordReader(dataSet).read(); + //new PersonsReader(dataSet).read(); + //the class called Synthetic population reader: could it be renamed to PersonJobReader? + new SyntheticPopulationReaderGermany(dataSet, config.getJobTypeFactory()).read(); + dataSet.setTravelTimes(new SkimTravelTimes()); + new OmxSkimsReader(dataSet).read(); + readAdditionalData(); + } + + private void readAdditionalData() { + new TripAttractionRatesReader(dataSet).read(); + new ModeChoiceInputReader(dataSet).read(); + new EconomicStatusReader(dataSet).read(); + new TimeOfDayDistributionsReader(dataSet).read(); + new CalibrationDataReader(dataSet).read(); + new CalibrationRegionMapReader(dataSet).read(); + + } + + private void printOutline(long startTime) { + String trips = MitoUtil.customFormat(" " + "###,###", dataSet.getTrips().size()); + logger.info("A total of " + trips.trim() + " microscopic trips were generated"); + logger.info("Completed the Microsimulation Transport Orchestrator (MITO)"); + float endTime = MitoUtil.rounder(((System.currentTimeMillis() - startTime) / 60000.f), 1); + int hours = (int) (endTime / 60); + int min = (int) (endTime - 60 * hours); + logger.info("Runtime: " + hours + " hours and " + min + " minutes."); + } + + public DataSet getData() { + return dataSet; + } + + public String getScenarioName() { + return scenarioName; + } + + public void setRandomNumberGenerator(Random random) { + MitoUtil.initializeRandomNumber(random); + } + + +} diff --git a/src/main/java/de/tum/bgu/msm/trafficAssignment/TripCSVToMATSimPlan.java b/src/main/java/de/tum/bgu/msm/trafficAssignment/TripCSVToMATSimPlan.java index 9f79c25c..d18beec0 100644 --- a/src/main/java/de/tum/bgu/msm/trafficAssignment/TripCSVToMATSimPlan.java +++ b/src/main/java/de/tum/bgu/msm/trafficAssignment/TripCSVToMATSimPlan.java @@ -1,6 +1,10 @@ package de.tum.bgu.msm.trafficAssignment; +import de.tum.bgu.msm.data.MitoTrip; import de.tum.bgu.msm.data.Purpose; +import de.tum.bgu.msm.resources.Properties; +import de.tum.bgu.msm.resources.Resources; +import de.tum.bgu.msm.util.MitoUtil; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; @@ -17,180 +21,295 @@ import java.io.FileReader; import java.io.IOException; import java.util.HashSet; +import java.util.Random; import java.util.Set; public class TripCSVToMATSimPlan { - // This class will read trip lists in CSV from MITO and creates a MATSim XML - // plan file - private static String delimiter = ","; - - private static String filename; - private static PopulationFactory factory; - private static Network carNetwork; - - public static void main(String[] args) { - // TODO add logging - filename = args[0]; - String networkFile = args[1]; - - Config config = ConfigUtils.createConfig(); - config.network().setInputFile(networkFile); - - Scenario scenario = ScenarioUtils.loadScenario(config); - TransportModeNetworkFilter filter = new TransportModeNetworkFilter(scenario.getNetwork()); - Set modesCar = new HashSet<>(); - modesCar.add("car"); - carNetwork = NetworkUtils.createNetwork(); - filter.filter(carNetwork, modesCar); - - Population population = PopulationUtils.createPopulation(config); - factory = population.getFactory(); - - try { - FileReader in = null; - BufferedReader br = null; - try { - in = new FileReader(filename); - br = new BufferedReader(in); - - String line; - int i = 0; - br.readLine(); // skip CSV header - while ((line = br.readLine()) != null) { - Person p = createPersonFromTrip(i++, line); - if (p != null) { - population.addPerson(p); - } - } - } finally { - if (br != null) { - br.close(); - } - - if (in != null) { - in.close(); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - - PopulationWriter popwriter = new PopulationWriter(population); - popwriter.write(filename + ".xml.gz"); - - System.out.println("done."); - } - - private static Person createPersonFromTrip(int i, String line) { - Trip t = new Trip(line); - - String mode = decodeMode(t.mode); - Id matsimId = Id.createPersonId(t.person + "_" + i); - - Person p = factory.createPerson(Id.createPersonId(matsimId)); - Plan plan = factory.createPlan(); - - Purpose purpose = Purpose.valueOf(t.purpose); - boolean roundTrip = !(purpose.equals(Purpose.NHBW) || purpose.equals(Purpose.NHBO)); - - String firstActivityType = getOriginActivity(purpose); - Coord firstCoord = new Coord(t.originX, t.originY); - - Activity firstAct = factory.createActivityFromCoord(firstActivityType, firstCoord); - firstAct.setLinkId(NetworkUtils.getNearestLink(carNetwork, firstCoord).getId()); - - firstAct.setEndTime(t.departure_time); - plan.addActivity(firstAct); - - Leg firstLeg = factory.createLeg(mode); - firstLeg.setDepartureTime(t.departure_time); - plan.addLeg(firstLeg); - - String secondActivityType = getDestinationActivity(purpose); - Coord secondCoord = new Coord(t.destinationX, t.destinationY); - - Activity secondAct = factory.createActivityFromCoord(secondActivityType, secondCoord); - secondAct.setLinkId(NetworkUtils.getNearestLink(carNetwork, secondCoord).getId()); - secondAct.setStartTime(t.departure_time + 1); // TODO include MITO's travel time estimations - - if (roundTrip) { - secondAct.setEndTime(t.departure_time_return); - plan.addActivity(secondAct); - } - - if (roundTrip) { - Leg secondLeg = factory.createLeg(mode); - secondLeg.setDepartureTime(t.departure_time_return); - plan.addLeg(secondLeg); - - Activity thirdAct = factory.createActivityFromCoord(firstActivityType, firstCoord); - thirdAct.setLinkId(NetworkUtils.getNearestLink(carNetwork, firstCoord).getId()); - thirdAct.setStartTime(t.departure_time_return + 1); // TODO include MITO's travel time estimations - plan.addActivity(thirdAct); - } - - p.addPlan(plan); - p.setSelectedPlan(plan); - return p; - } - - private static String getDestinationActivity(Purpose purpose) { - return ""; - } - - private static String getOriginActivity(Purpose purpose) { - return ""; - } - - private static String decodeMode(String encodedMode) { - switch (encodedMode) { - case "autoDriver": - return "car"; - case "autoPassenger": - return "car_passenger"; - case "train": - case "bus": - case "tramOrMetro": - return "pt"; - case "bicycle": - return "bike"; - default: - return encodedMode; - } - } - - public final static class Trip { - public final double originX; - public final double originY; - public final double destinationX; - public final double destinationY; - public final String purpose; - public final String person; - public final double distance; - public final String mode; - public final double departure_time; - public final double departure_time_return; - - public Trip(String line) { - String[] data = line.split(delimiter); - this.originX = Double.parseDouble(data[2]); - this.originY = Double.parseDouble(data[3]); - this.destinationX = Double.parseDouble(data[5]); - this.destinationY = Double.parseDouble(data[6]); - this.purpose = data[7]; - this.person = data[8]; - this.distance = Double.parseDouble(data[9]); - this.mode = data[14]; - // departure time comes in minutes, needed as seconds - this.departure_time = Double.parseDouble(data[15]) * 60; - - if (data.length >= 17) { - this.departure_time_return = Double.parseDouble(data[16]) * 60; - } - else { - this.departure_time_return = -1; - } - } - } + private static final double SPEED_WALK_KMH = 5.; + private static final double SPEED_BICYCLE_KMH = 12.; + // This class will read trip lists in CSV from MITO and creates a MATSim XML + // plan file + private static String delimiter = ","; + + private static String filename; + private static PopulationFactory factory; + private static Network carNetwork; + + private static double scaleFactor = 0.20; + private static Random random = new Random(0); + + private static int posId; + private static int posOriginX; + private static int posOriginY; + private static int posDestinationX; + private static int posDestinationY; + private static int posPurpose; + private static int posPersonId; + private static int posMode; + private static int posDistance; + private static int posTimeCar; + private static int posTimeTrain; + private static int posTimeMetroTram; + private static int posTimeBus; + private static int posDepartureTime; + private static int posDepartureTimeReturn; + + private static Set modesCar = new HashSet<>(); + private static Set modesAssignment = new HashSet<>(); + + public static void main(String[] args) { + // TODO add logging + filename = args[0]; + //String networkFile = args[1]; + + Config config = ConfigUtils.createConfig(); + //config.network().setInputFile(networkFile); + + + + Scenario scenario = ScenarioUtils.loadScenario(config); + TransportModeNetworkFilter filter = new TransportModeNetworkFilter(scenario.getNetwork()); + + modesCar.add("car"); + modesAssignment.add("car"); + carNetwork = NetworkUtils.createNetwork(); + filter.filter(carNetwork, modesCar); + + Population population = PopulationUtils.createPopulation(config); + factory = population.getFactory(); + + try { + FileReader in = null; + BufferedReader br = null; + try { + in = new FileReader(filename); + br = new BufferedReader(in); + + String line; + int i = 0; + String[] header = br.readLine().split(delimiter); // read CSV header to find names and positions + + posId = MitoUtil.findPositionInArray("id", header); + posOriginX = MitoUtil.findPositionInArray("originX", header); + posOriginY = MitoUtil.findPositionInArray("originY", header); + posDestinationX = MitoUtil.findPositionInArray("destinationX", header); + posDestinationY = MitoUtil.findPositionInArray("destinationY", header); + posPurpose = MitoUtil.findPositionInArray("purpose", header); + posPersonId = MitoUtil.findPositionInArray("person", header); + posMode = MitoUtil.findPositionInArray("mode", header); + posDistance = MitoUtil.findPositionInArray("distance", header); + posTimeCar = MitoUtil.findPositionInArray("time_auto", header); + posTimeTrain = MitoUtil.findPositionInArray("time_train", header); + posTimeMetroTram = MitoUtil.findPositionInArray("time_tram_metro", header); + posTimeBus = MitoUtil.findPositionInArray("time_bus", header); + posDepartureTime = MitoUtil.findPositionInArray("departure_time", header); + posDepartureTimeReturn = MitoUtil.findPositionInArray("departure_time_return", header); + + + while ((line = br.readLine()) != null) { + Person p = createPersonFromTrip(i++, line); + if (p != null) { + population.addPerson(p); + } + } + } finally { + if (br != null) { + br.close(); + } + + if (in != null) { + in.close(); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + + PopulationWriter popwriter = new PopulationWriter(population); + popwriter.write("externalDemand/sd_trips" + ".xml.gz"); + + System.out.println("done."); + } + + private static Person createPersonFromTrip(int i, String line) { + + Trip t = new Trip(line); + + String mode = decodeMode(t.mode); + + if (mode.equals("null")) { + return null; + //not a valid trip record + } + + if (random.nextDouble() > scaleFactor){ + return null; + } + + if (!modesAssignment.contains(mode)){ + return null; + } + + Id matsimId = Id.createPersonId(t.person + "_" + i); + + Person p = factory.createPerson(Id.createPersonId(matsimId)); + Plan plan = factory.createPlan(); + + Purpose purpose = Purpose.valueOf(t.purpose); + boolean roundTrip = !(purpose.equals(Purpose.NHBW) || purpose.equals(Purpose.NHBO)); + + String firstActivityType = getOriginActivity(purpose); + Coord firstCoord = new Coord(t.originX, t.originY); + + Activity firstAct = factory.createActivityFromCoord(firstActivityType, firstCoord); + //firstAct.setLinkId(NetworkUtils.getNearestLink(carNetwork, firstCoord).getId()); + + firstAct.setEndTime(t.departure_time); + plan.addActivity(firstAct); + + Leg firstLeg = factory.createLeg(mode); + firstLeg.setDepartureTime(t.departure_time); + plan.addLeg(firstLeg); + + String secondActivityType = getDestinationActivity(purpose); + Coord secondCoord = new Coord(t.destinationX, t.destinationY); + + Activity secondAct = factory.createActivityFromCoord(secondActivityType, secondCoord); + //secondAct.setLinkId(NetworkUtils.getNearestLink(carNetwork, secondCoord).getId()); + double arrivalTime = t.departure_time + Math.min(getEstimatedTravelTime(t), 3600 * 4); + secondAct.setStartTime(arrivalTime); + plan.addActivity(secondAct); + + if (roundTrip) { + double departure_time_return = t.departure_time_return; + //make sure the arrival time is earlier than the departure time + departure_time_return = Math.min(departure_time_return, arrivalTime + 1); + + secondAct.setEndTime(departure_time_return); + Leg secondLeg = factory.createLeg(mode); + secondLeg.setDepartureTime(departure_time_return); + plan.addLeg(secondLeg); + + Activity thirdAct = factory.createActivityFromCoord(firstActivityType, firstCoord); + //thirdAct.setLinkId(NetworkUtils.getNearestLink(carNetwork, firstCoord).getId()); + thirdAct.setStartTime(departure_time_return + Math.min(getEstimatedTravelTime(t), 3600 * 4)); + plan.addActivity(thirdAct); + } + + p.addPlan(plan); + p.setSelectedPlan(plan); + return p; + } + + private static String getOriginActivity(Purpose purpose){ + + if (purpose.equals(Purpose.NHBW)){ + return "work"; + } else if (purpose.equals(Purpose.NHBO)){ + return "other"; + } else { + return "home"; + } + } + + private static String getDestinationActivity(Purpose purpose){ + + if (purpose.equals(Purpose.HBW)){ + return "work"; + } else if (purpose.equals(Purpose.HBE)){ + return "education"; + } else if (purpose.equals(Purpose.HBS)){ + return "shopping"; + } else { + return "other"; + } + } + + private static String decodeMode(String encodedMode) { + switch (encodedMode) { + case "autoDriver": + case "auto": + return "car"; + case "autoPassenger": + return "car_passenger"; + case "train": + case "bus": + case "tramOrMetro": + return "pt"; + case "bicycle": + return "bike"; + default: + return encodedMode; + } + } + + private static double getEstimatedTravelTime(Trip trip) { + switch (trip.mode) { + case "autoDriver": + case "auto": + case "autoPassenger": + return trip.timeCar_s; + case "train": + return trip.timeTrain_s; + case "tramOrMetro": + return trip.timeTramMetro_s; + case "bus": + return trip.timeBus_s; + case "walk": + return trip.distance / SPEED_WALK_KMH * 3600; + case "bicycle": + return trip.distance / SPEED_BICYCLE_KMH * 3600; + default: + throw new RuntimeException("The mode " + trip.mode + " is not recognized"); + } + } + + public final static class Trip { + public final long id; + public final double originX; + public final double originY; + public final double destinationX; + public final double destinationY; + public final String purpose; + public final String person; + public final double distance; + public final String mode; + public final double timeCar_s; + public final double timeBus_s; + public final double timeTramMetro_s; + public final double timeTrain_s; + public double departure_time; + public double departure_time_return; + + + public Trip(String line) { + String[] data = line.split(delimiter); + this.originX = Double.parseDouble(data[posOriginX]); + this.originY = Double.parseDouble(data[posOriginY]); + this.destinationX = Double.parseDouble(data[posDestinationX]); + this.destinationY = Double.parseDouble(data[posDestinationY]); + this.purpose = data[posPurpose]; + this.person = data[posPersonId]; + this.distance = Double.parseDouble(data[posDistance]); + this.mode = data[posMode]; + try { + this.departure_time = Double.parseDouble(data[posDepartureTime]) * 60; + } catch (NumberFormatException e) { + this.departure_time = 0.; + } + try { + this.departure_time_return = Double.parseDouble(data[posDepartureTimeReturn]) * 60; + } catch (NumberFormatException e) { + this.departure_time_return = -1.; + } + this.timeCar_s = Double.parseDouble(data[posTimeCar]) * 60; + this.timeTrain_s = Double.parseDouble(data[posTimeTrain]) * 60; + this.timeTramMetro_s = Double.parseDouble(data[posTimeMetroTram]) * 60; + this.timeBus_s = Double.parseDouble(data[posTimeBus]) * 60; + this.id = Long.parseLong(data[posId]); + } + + + } } diff --git a/src/main/resources/de/tum/bgu/msm/modules/modeChoice/ModeChoiceShortDistance b/src/main/resources/de/tum/bgu/msm/modules/modeChoice/ModeChoiceShortDistance new file mode 100644 index 00000000..b50c3a6b --- /dev/null +++ b/src/main/resources/de/tum/bgu/msm/modules/modeChoice/ModeChoiceShortDistance @@ -0,0 +1,874 @@ +nestingCoefficient = 0.25; + +fuelCostEurosPerKm = 0.07; +transitFareEurosPerKm = 0.12; + +TNCCostEurosPerKm = 1.20; + +VOT1500_HBW_HBE_autoD = 4.63 / 60; +VOT5600_HBW_HBE_autoD = 8.94 / 60; +VOT7000_HBW_HBE_autoD = 12.15 / 60; +VOT1500_HBW_HBE_autoP = 7.01 / 60; +VOT5600_HBW_HBE_autoP = 13.56 / 60; +VOT7000_HBW_HBE_autoP = 18.43 / 60; +VOT1500_HBW_HBE_transit = 8.94 / 60; +VOT5600_HBW_HBE_transit = 17.30 / 60; +VOT7000_HBW_HBE_transit = 23.50 / 60; + +VOT1500_HBW_HBE_TNC = 7.98 / 60; +VOT5600_HBW_HBE_TNC = 15.43 / 60; +VOT7000_HBW_HBE_TNC = 20.97 / 60; + +VOT1500_other_autoD = 3.26 / 60; +VOT5600_other_autoD = 6.30 / 60; +VOT7000_other_autoD = 8.56 / 60; +VOT1500_other_autoP = 4.30 / 60; +VOT5600_other_autoP = 8.31 / 60; +VOT7000_other_autoP = 11.30 / 60; +VOT1500_other_transit = 5.06 / 60; +VOT5600_other_transit = 9.78 / 60; +VOT7000_other_transit = 13.29 / 60; + +VOT1500_other_TNC = 4.68 / 60; +VOT5600_other_TNC = 9.05 / 60; +VOT7000_other_TNC = 12.30 / 60; + +///////////////////////////////////////////////// HBW Mode Choice ///////////////////////////////////////////////////// + +// Beta coefficients for modes in the order:[AutoD, AutoP, Bicycle, Bus, Train, TramMetro, Walk] +interceptHBW = [0.0, 0.53, 2.78, 3.12, 3.11, 3.06, 6.30]; +ageHBW = [0.0, -0.0037, 0.0, -0.016, -0.017, -0.014, 0.0]; +maleHBW = [0.0, -0.16, 0.22, -0.28, -0.25, -0.18, 0.0]; +driversLicenseHBW = [0.0, -1.03, -1.86, -2.25, -2.09, -2.14, -2.16]; +hhSizeHBW = [0.0, 0.063, 0.25, 0.17, 0.18, 0.15, 0.0]; +hhAutosHBW = [0.0, -0.16, -1.11, -1.27, -1.26, -1.29, -0.73]; +distToRailStopHBW = [0.0, 0.0, 0.0, -0.36, -0.39, -0.40, 0.0]; +coreCityHBW = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; +mediumSizedCityHBW = [0.0, 0.0, -0.29, -0.70, -0.75, -1.05, -0.59]; +townOrRuralCommunityHBW = [0.0, 0.071, -0.39, -0.86, -0.88, -1.22, -0.89]; +generalizedCostHBW = [-0.0088, -0.0088, 0.0, -0.0088, -0.0088, -0.0088, 0.0]; +tripLengthHBW = [0.0, 0.0, -0.32, 0.0, 0.0, 0.0, -2.02]; +isMunichTripHBW = [0.0, 0.04, 0.63, 0.77, 0.76, 0.77, 2.32]; + + +var calculateHBWProbabilities = function (hh, person, originZone, destinationZone, travelTimes, accessTimes, travelDistanceAuto, travelDistanceNMT, peakHour) { + + timeAutoD = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "car"); + timeAutoP = timeAutoD; + timeBus = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "bus"); + timeTrain = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "train"); + timeTramMetro = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "tramMetro"); + + monthlyIncome_EUR = hh.getMonthlyIncome_EUR(); + age = person.getAge(); + gender = person.getMitoGender(); + driversLicense = person.hasDriversLicense(); + hhSize = hh.getHhSize(); + hhAutos = hh.getAutos(); + distToRailStop = originZone.getDistanceToNearestRailStop(); + areaType = originZone.getAreaTypeSG(); + isMunichTrip = originZone.isMunichZone(); + + + if (monthlyIncome_EUR <= 1500) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_HBW_HBE_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_HBW_HBE_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_HBW_HBE_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_HBW_HBE_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_HBW_HBE_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT1500_HBW_HBE_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 1500 && monthlyIncome_EUR <= 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_HBW_HBE_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_HBW_HBE_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_HBW_HBE_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_HBW_HBE_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_HBW_HBE_transit; + gcSTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT5600_HBW_HBE_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_HBW_HBE_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_HBW_HBE_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_HBW_HBE_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_HBW_HBE_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_HBW_HBE_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT7000_HBW_HBE_TNC; // change in VOT and cost + } + + utilityAutoD = interceptHBW[0] + ageHBW[0] * age + maleHBW[0] * (gender.name().equals("MALE")) + + driversLicenseHBW[0] * driversLicense + hhSizeHBW[0] * hhSize + hhAutosHBW[0] * hhAutos + + distToRailStopHBW[0] * distToRailStop + coreCityHBW[0] * (areaType.name().equals("CORE_CITY")) + + mediumSizedCityHBW[0] * (areaType.name().equals("MEDIUM_SIZE_CITY")) + + townOrRuralCommunityHBW[0] * (areaType.name().equals("TOWN") || areaType.name().equals("RURAL")) + + generalizedCostHBW[0] * gcAutoD + isMunichTripHBW[0] * isMunichTrip; + + utilityAutoP = interceptHBW[1] + ageHBW[1] * age + maleHBW[1] * (gender.name().equals("MALE")) + + driversLicenseHBW[1] * driversLicense + hhSizeHBW[1] * hhSize + hhAutosHBW[1] * hhAutos + + distToRailStopHBW[1] * distToRailStop + coreCityHBW[1] * (areaType.name().equals("CORE_CITY")) + + mediumSizedCityHBW[1] * (areaType.name().equals("MEDIUM_SIZE_CITY")) + + townOrRuralCommunityHBW[1] * (areaType.name().equals("TOWN") || areaType.name().equals("RURAL")) + + generalizedCostHBW[1] * gcAutoP + isMunichTripHBW[1] * isMunichTrip; + + utilityBicycle = interceptHBW[2] + ageHBW[2] * age + maleHBW[2] * (gender.name().equals("MALE")) + + driversLicenseHBW[2] * driversLicense + hhSizeHBW[2] * hhSize + hhAutosHBW[2] * hhAutos + + distToRailStopHBW[2] * distToRailStop + coreCityHBW[2] * (areaType.name().equals("CORE_CITY")) + + mediumSizedCityHBW[2] * (areaType.name().equals("MEDIUM_SIZE_CITY")) + + townOrRuralCommunityHBW[2] * (areaType.name().equals("TOWN") || areaType.name().equals("RURAL")) + + tripLengthHBW[2] * travelDistanceNMT + isMunichTripHBW[2] * isMunichTrip; + + utilityBus = interceptHBW[3] + ageHBW[3] * age + maleHBW[3] * (gender.name().equals("MALE")) + + driversLicenseHBW[3] * driversLicense + hhSizeHBW[3] * hhSize + hhAutosHBW[3] * hhAutos + + distToRailStopHBW[3] * distToRailStop + coreCityHBW[3] * (areaType.name().equals("CORE_CITY")) + + mediumSizedCityHBW[3] * (areaType.name().equals("MEDIUM_SIZE_CITY") || areaType.name().equals("RURAL")) + + townOrRuralCommunityHBW[3] * (areaType.name().equals("TOWN")) + + generalizedCostHBW[3] * gcBus + isMunichTripHBW[3] * isMunichTrip; + + utilityTrain = interceptHBW[4] + ageHBW[4] * age + maleHBW[4] * (gender.name().equals("MALE")) + + driversLicenseHBW[4] * driversLicense + hhSizeHBW[4] * hhSize + hhAutosHBW[4] * hhAutos + + distToRailStopHBW[4] * distToRailStop + coreCityHBW[4] * (areaType.name().equals("CORE_CITY")) + + mediumSizedCityHBW[4] * (areaType.name().equals("MEDIUM_SIZE_CITY") || areaType.name().equals("RURAL")) + + townOrRuralCommunityHBW[4] * (areaType.name().equals("TOWN")) + + generalizedCostHBW[4] * gcTrain + isMunichTripHBW[4] * isMunichTrip; + + utilityTramMetro = interceptHBW[5] + ageHBW[5] * age + maleHBW[5] * (gender.name().equals("MALE")) + + driversLicenseHBW[5] * driversLicense + hhSizeHBW[5] * hhSize + hhAutosHBW[5] * hhAutos + + distToRailStopHBW[5] * distToRailStop + coreCityHBW[5] * (areaType.name().equals("CORE_CITY")) + + mediumSizedCityHBW[5] * (areaType.name().equals("MEDIUM_SIZE_CITY")) + + townOrRuralCommunityHBW[5] * (areaType.name().equals("TOWN") || areaType.name().equals("RURAL")) + + generalizedCostHBW[5] * gcTramMetro + isMunichTripHBW[5] * isMunichTrip; + + utilityWalk = interceptHBW[6] + ageHBW[6] * age + maleHBW[6] * (gender.name().equals("MALE")) + + driversLicenseHBW[6] * driversLicense + hhSizeHBW[6] * hhSize + hhAutosHBW[6] * hhAutos + + distToRailStopHBW[6] * distToRailStop + coreCityHBW[6] * (areaType.name().equals("CORE_CITY")) + + mediumSizedCityHBW[6] * (areaType.name().equals("MEDIUM_SIZE_CITY")) + + townOrRuralCommunityHBW[6] * (areaType.name().equals("TOWN") || areaType.name().equals("RURAL")) + + tripLengthHBW[6] * travelDistanceNMT + isMunichTripHBW[6] * isMunichTrip; + + utilityTNC = utilityBus + generalizedCostHBW[3] * (gcTNC - gcBus); + + expsumNestAuto = Math.exp(utilityAutoD / nestingCoefficient) + Math.exp(utilityAutoP / nestingCoefficient); + expsumNestTransit = Math.exp(utilityBus / nestingCoefficient) + Math.exp(utilityTrain / nestingCoefficient) + Math.exp(utilityTramMetro / nestingCoefficient); + expsumNestNMT = Math.exp(utilityBicycle / nestingCoefficient) + Math.exp(utilityWalk / nestingCoefficient); + expsumTopLevel = Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) + Math.exp(utilityTNC) + Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) + Math.exp(nestingCoefficient * Math.log(expsumNestTransit)); + + if (expsumNestAuto > 0) { + probabilityAutoD = (Math.exp(utilityAutoD / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + probabilityAutoP = (Math.exp(utilityAutoP / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + } else { + probabilityAutoD = 0.0; + probabilityAutoP = 0.0; + } + + if (expsumNestTransit > 0) { + probabilityBus = (Math.exp(utilityBus / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTrain = (Math.exp(utilityTrain / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTramMetro = (Math.exp(utilityTramMetro / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + } else { + probabilityBus = 0.0; + probabilityTrain = 0.0; + probabilityTramMetro = 0.0; + } + + if (expsumNestNMT > 0) { + probabilityBicycle = (Math.exp(utilityBicycle / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) / expsumTopLevel); + probabilityWalk = (Math.exp(utilityWalk / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestWalk)) / expsumTopLevel); + } else { + probabilityBicycle = 0.0; + probabilityWalk = 0.0; + } + + probabilityTNC = Math.exp(utilityTNC) / expsumTopLevel; + + return Java.to([probabilityAutoD, probabilityAutoP, probabilityBicycle, probabilityBus, probabilityTrain, probabilityTramMetro, probabilityWalk, probabilityTNC], "double[]"); + +} + + +///////////////////////////////////////////////// HBE Mode Choice ///////////////////////////////////////////////////// + +// Beta coefficients for modes in the order - [AutoD, AutoP, Bicycle, Bus, Train, TramMetro, Walk] +interceptHBE = [0.0, 1.41, 2.15, 3.00, 2.72, 3.02, 4.23]; +maleHBE = [0.0, -0.17, 0.0, -0.14, -0.15, -0.15, 0.0]; +driversLicenseHBE = [0.0, -1.26, -0.43, -1.23, -0.75, -0.77, -0.55]; +hhAutosHBE = [0.0, -0.11, -0.56, -0.52, -0.56, -0.70, -0.68]; +distToRailStopHBE = [0.0, 0.0, 0.0, -0.28, -0.26, -0.46, 0.0]; +generalizedCostHBE = [-0.0025, -0.0025, 0.0, -0.0025, -0.0025, -0.0025, 0.0]; +tripLengthHBE = [0.0, 0.0, -0.42, 0.0, 0.0, 0.0, -1.71]; +isMunichTripHBE = [0.0, 0.02, 0.25, 0.07, 0.08, 0.06, -0.49]; + +var calculateHBEProbabilities = function (hh, person, originZone, destinationZone, travelTimes, accessTimes, travelDistanceAuto, travelDistanceNMT, peakHour) { + timeAutoD = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "car"); + timeAutoP = timeAutoD; + timeBus = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "bus"); + timeTrain = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "train"); + timeTramMetro = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "tramMetro"); + + monthlyIncome_EUR = hh.getMonthlyIncome_EUR(); + gender = person.getMitoGender(); + driversLicense = person.hasDriversLicense(); + hhAutos = hh.getAutos(); + distToRailStop = originZone.getDistanceToNearestRailStop(); + isMunichTrip = originZone.isMunichZone(); + + if (monthlyIncome_EUR <= 1500) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_HBW_HBE_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_HBW_HBE_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_HBW_HBE_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_HBW_HBE_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_HBW_HBE_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT1500_HBW_HBE_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 1500 && monthlyIncome_EUR <= 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_HBW_HBE_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_HBW_HBE_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_HBW_HBE_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_HBW_HBE_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_HBW_HBE_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT5600_HBW_HBE_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_HBW_HBE_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_HBW_HBE_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_HBW_HBE_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_HBW_HBE_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_HBW_HBE_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT7000_HBW_HBE_TNC; // change in VOT and cost + } + + utilityAutoD = interceptHBE[0] + maleHBE[0] * (gender.name().equals("MALE")) + driversLicenseHBE[0] * driversLicense + + hhAutosHBE[0] * hhAutos + distToRailStopHBE[0] * distToRailStop + generalizedCostHBE[0] * gcAutoD + isMunichTripHBE[0] * isMunichTrip; + + utilityAutoP = interceptHBE[1] + maleHBE[1] * (gender.name().equals("MALE")) + driversLicenseHBE[1] * driversLicense + + hhAutosHBE[1] * hhAutos + distToRailStopHBE[1] * distToRailStop + generalizedCostHBE[1] * gcAutoP + isMunichTripHBE[1] * isMunichTrip; + + utilityBicycle = interceptHBE[2] + maleHBE[2] * (gender.name().equals("MALE")) + driversLicenseHBE[2] * driversLicense + + hhAutosHBE[2] * hhAutos + distToRailStopHBE[2] * distToRailStop + tripLengthHBE[2] * travelDistanceNMT + isMunichTripHBE[2] * isMunichTrip; + + utilityBus = interceptHBE[3] + maleHBE[3] * (gender.name().equals("MALE")) + driversLicenseHBE[3] * driversLicense + + hhAutosHBE[3] * hhAutos + distToRailStopHBE[3] * distToRailStop + generalizedCostHBE[3] * gcBus + isMunichTripHBE[3] * isMunichTrip; + + utilityTrain = interceptHBE[4] + maleHBE[4] * (gender.name().equals("MALE")) + driversLicenseHBE[4] * driversLicense + + hhAutosHBE[4] * hhAutos + distToRailStopHBE[4] * distToRailStop + generalizedCostHBE[4] * gcTrain + isMunichTripHBE[4] * isMunichTrip; + + utilityTramMetro = interceptHBE[5] + maleHBE[5] * (gender.name().equals("MALE")) + driversLicenseHBE[5] * driversLicense + + hhAutosHBE[5] * hhAutos + distToRailStopHBE[5] * distToRailStop + generalizedCostHBE[5] * gcTramMetro + isMunichTripHBE[5] * isMunichTrip; + + utilityWalk = interceptHBE[6] + maleHBE[6] * (gender.name().equals("MALE")) + driversLicenseHBE[6] * driversLicense + + hhAutosHBE[6] * hhAutos + distToRailStopHBE[6] * distToRailStop + tripLengthHBE[6] * travelDistanceNMT + isMunichTripHBE[6] * isMunichTrip; + + utilityTNC = utilityBus + generalizedCostHBE[3] * (gcTNC - gcBus); + + expsumNestAuto = Math.exp(utilityAutoD / nestingCoefficient) + Math.exp(utilityAutoP / nestingCoefficient); + expsumNestTransit = Math.exp(utilityBus / nestingCoefficient) + Math.exp(utilityTrain / nestingCoefficient) + Math.exp(utilityTramMetro / nestingCoefficient); + expsumNestNMT = Math.exp(utilityBicycle / nestingCoefficient) + Math.exp(utilityWalk / nestingCoefficient); + expsumTopLevel = Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) + Math.exp(utilityTNC) + Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) + Math.exp(nestingCoefficient * Math.log(expsumNestTransit)); + + if (expsumNestAuto > 0) { + probabilityAutoD = (Math.exp(utilityAutoD / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + probabilityAutoP = (Math.exp(utilityAutoP / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + } else { + probabilityAutoD = 0.0; + probabilityAutoP = 0.0; + } + + if (expsumNestTransit > 0) { + probabilityBus = (Math.exp(utilityBus / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTrain = (Math.exp(utilityTrain / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTramMetro = (Math.exp(utilityTramMetro / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + } else { + probabilityBus = 0.0; + probabilityTrain = 0.0; + probabilityTramMetro = 0.0; + } + + if (expsumNestNMT > 0) { + probabilityBicycle = (Math.exp(utilityBicycle / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) / expsumTopLevel); + probabilityWalk = (Math.exp(utilityWalk / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestWalk)) / expsumTopLevel); + } else { + probabilityBicycle = 0.0; + probabilityWalk = 0.0; + } + + probabilityTNC = Math.exp(utilityTNC) / expsumTopLevel; + + return Java.to([probabilityAutoD, probabilityAutoP, probabilityBicycle, probabilityBus, probabilityTrain, probabilityTramMetro, probabilityWalk, probabilityTNC], "double[]"); + +} +//print(utilityAutoD + ";" + utilityAutoP + ";" + +//utilityBicycle + ";" + utilityBus + ";" + utilityTramMetro + ";" +//+ utilityTrain + ";" + utilityWalk + ";" + utilityAVP + ";" + utilityAVS + ";" + +//utilityUAM + ";" ); + +//print(probabilityPrivateAV + ";" + probabilityAutoD + ";" + +//probabilityAutoP + ";" + probabilitySharedAV + ";" + probabilityBus + ";" +//+ probabilityTrain + ";" + probabilityTramMetro + ";" + probabilityBicycle + ";" + probabilityWalk + ";" + +//probabilityUAM + ";" ); + + +///////////////////////////////////////////////// HBS Mode Choice ///////////////////////////////////////////////////// + +// Beta coefficients for modes in the order: [AutoD, AutoP, Bicycle, Bus, Train, TramMetro, Walk] +interceptHBS = [0.0, 0.92, 2.50, 1.61, 1.17, 1.67, 6.35]; +maleHBS = [0.0, -0.47, -0.14, -0.62, -0.47, -0.53, -0.15]; +driversLicenseHBS = [0.0, -1.43, -1.86, -2.43, -2.46, -2.39, -2.10]; +hhAutosHBS = [0.0, -0.03, -0.81, -1.88, -1.73, -1.88, -0.86]; +distToRailStopHBS = [0.0, 0.0, 0.0, -0.87, -0.68, -1.02, 0.0]; +hhChildrenHBS = [0.0, -0.051, 0.0, 0.0, 0.0, 0.0, -0.17]; +generalizedCostHBS_Sq = [-0.0000068, -0.0000068, 0.0, -0.0000068, -0.0000068, -0.0000068, 0.0]; +tripLengthHBS = [0.0, 0.0, -0.42, 0.0, 0.0, 0.0, -1.46]; +isMunichTripHBS = [0.0, 0.05, 1.16, 1.35, 1.32, 1.36, 1.942]; + +var calculateHBSProbabilities = function (hh, person, originZone, destinationZone, travelTimes, accessTimes, travelDistanceAuto, travelDistanceNMT, peakHour) { + + var dataSet = Java.type('de.tum.bgu.msm.data.DataSet'); + hhChildren = dataSet.getChildrenForHousehold(hh); + timeAutoD = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "car"); + timeAutoP = timeAutoD; + timeBus = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "bus"); + timeTrain = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "train"); + timeTramMetro = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "tramMetro"); + + monthlyIncome_EUR = hh.getMonthlyIncome_EUR(); + gender = person.getMitoGender(); + driversLicense = person.hasDriversLicense(); + hhAutos = hh.getAutos(); + distToRailStop = originZone.getDistanceToNearestRailStop(); + isMunichTrip = originZone.isMunichZone(); + + if (monthlyIncome_EUR <= 1500) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT1500_other_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 1500 && monthlyIncome_EUR <= 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT5600_other_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT7000_other_TNC; // change in VOT and cost + } + + utilityAutoD = interceptHBS[0] + maleHBS[0] * (gender.name().equals("MALE")) + driversLicenseHBS[0] * driversLicense + + hhAutosHBS[0] * hhAutos + distToRailStopHBS[0] * distToRailStop + hhChildrenHBS[0] * hhChildren + + generalizedCostHBS_Sq[0] * Math.pow(gcAutoD, 2) + isMunichTripHBS[0] * isMunichTrip; + + utilityAutoP = interceptHBS[1] + maleHBS[1] * (gender.name().equals("MALE")) + driversLicenseHBS[1] * driversLicense + + hhAutosHBS[1] * hhAutos + distToRailStopHBS[1] * distToRailStop + hhChildrenHBS[1] * hhChildren + + generalizedCostHBS_Sq[1] * Math.pow(gcAutoP, 2) + isMunichTripHBS[1] * isMunichTrip; + + utilityBicycle = interceptHBS[2] + maleHBS[2] * (gender.name().equals("MALE")) + driversLicenseHBS[2] * driversLicense + + hhAutosHBS[2] * hhAutos + distToRailStopHBS[2] * distToRailStop + hhChildrenHBS[2] * hhChildren + + tripLengthHBS[2] * travelDistanceNMT + isMunichTripHBS[2] * isMunichTrip; + + utilityBus = interceptHBS[3] + maleHBS[3] * (gender.name().equals("MALE")) + driversLicenseHBS[3] * driversLicense + + hhAutosHBS[3] * hhAutos + distToRailStopHBS[3] * distToRailStop + hhChildrenHBS[3] * hhChildren + + generalizedCostHBS_Sq[3] * Math.pow(gcBus, 2) + isMunichTripHBS[3] * isMunichTrip; + + utilityTrain = interceptHBS[4] + maleHBS[4] * (gender.name().equals("MALE")) + driversLicenseHBS[4] * driversLicense + + hhAutosHBS[4] * hhAutos + distToRailStopHBS[4] * distToRailStop + hhChildrenHBS[4] * hhChildren + + generalizedCostHBS_Sq[4] * Math.pow(gcTrain, 2) + isMunichTripHBS[4] * isMunichTrip; + + utilityTramMetro = interceptHBS[5] + maleHBS[5] * (gender.name().equals("MALE")) + driversLicenseHBS[5] * driversLicense + + hhAutosHBS[5] * hhAutos + distToRailStopHBS[5] * distToRailStop + hhChildrenHBS[5] * hhChildren + + generalizedCostHBS_Sq[5] * Math.pow(gcTramMetro, 2) + isMunichTripHBS[5] * isMunichTrip; + + utilityWalk = interceptHBS[6] + maleHBS[6] * (gender.name().equals("MALE")) + driversLicenseHBS[6] * driversLicense + + hhAutosHBS[6] * hhAutos + distToRailStopHBS[6] * distToRailStop + hhChildrenHBS[6] * hhChildren + + tripLengthHBS[6] * travelDistanceNMT + isMunichTripHBS[6] * isMunichTrip; + + utilityTNC = utilityBus + generalizedCostHBS_Sq[3] * (Math.pow(gcTNC, 2) - Math.pow(gcBus, 2)); + + expsumNestAuto = Math.exp(utilityAutoD / nestingCoefficient) + Math.exp(utilityAutoP / nestingCoefficient); + expsumNestTransit = Math.exp(utilityBus / nestingCoefficient) + Math.exp(utilityTrain / nestingCoefficient) + Math.exp(utilityTramMetro / nestingCoefficient); + expsumNestNMT = Math.exp(utilityBicycle / nestingCoefficient) + Math.exp(utilityWalk / nestingCoefficient); + expsumTopLevel = Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) + Math.exp(utilityTNC) + Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) + Math.exp(nestingCoefficient * Math.log(expsumNestTransit)); + + if (expsumNestAuto > 0) { + probabilityAutoD = (Math.exp(utilityAutoD / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + probabilityAutoP = (Math.exp(utilityAutoP / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + } else { + probabilityAutoD = 0.0; + probabilityAutoP = 0.0; + } + + if (expsumNestTransit > 0) { + probabilityBus = (Math.exp(utilityBus / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTrain = (Math.exp(utilityTrain / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTramMetro = (Math.exp(utilityTramMetro / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + } else { + probabilityBus = 0.0; + probabilityTrain = 0.0; + probabilityTramMetro = 0.0; + } + + if (expsumNestNMT > 0) { + probabilityBicycle = (Math.exp(utilityBicycle / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) / expsumTopLevel); + probabilityWalk = (Math.exp(utilityWalk / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestWalk)) / expsumTopLevel); + } else { + probabilityBicycle = 0.0; + probabilityWalk = 0.0; + } + + probabilityTNC = Math.exp(utilityTNC) / expsumTopLevel; + + return Java.to([probabilityAutoD, probabilityAutoP, probabilityBicycle, probabilityBus, probabilityTrain, probabilityTramMetro, probabilityWalk, probabilityTNC], "double[]"); + +} + +///////////////////////////////////////////////// HBO Mode Choice ///////////////////////////////////////////////////// + +// Beta coefficients for modes in the order: [AutoD, AutoP, Bicycle, Bus, Train, TramMetro, Walk] +interceptHBO = [0.0, 1.04, 1.25, 1.47, 1.22, 1.59, 4.09]; +maleHBO = [0.0, -0.27, 0.17, -0.13, 0.0, -0.063, -0.13]; +driversLicenseHBO = [0.0, -1.34, -1.51, -1.91, -1.66, -1.74, -1.30]; +hhAutosHBO = [0.0, -0.029, -0.57, -1.54, -1.56, -1.72, -0.30]; +hhSizeHBO = [0.0, 0.0, 0.0, -0.11, -0.11, -0.15, -0.19]; +distToRailStopHBO = [0.0, 0.0, 0.0, -0.61, -0.57, -0.58, -0.065]; +generalizedCostHBO = [-0.0012, -0.0012, 0.0, -0.0012, -0.0012, -0.0012, 0.0]; +tripLengthHBO = [0.0, 0.0, -0.15, 0.0, 0.0, 0.0, -0.68]; +isMunichTripHBO = [0.0, 0.14, 0.61, 1.25, 1.23, 1.25, 0.34]; + +var calculateHBOProbabilities = function (hh, person, originZone, destinationZone, travelTimes, accessTimes, travelDistanceAuto, travelDistanceNMT, peakHour) { + + timeAutoD = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "car"); + timeAutoP = timeAutoD; + timeBus = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "bus"); + timeTrain = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "train"); + timeTramMetro = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "tramMetro"); + + monthlyIncome_EUR = hh.getMonthlyIncome_EUR(); + gender = person.getMitoGender(); + driversLicense = person.hasDriversLicense(); + hhAutos = hh.getAutos(); + hhSize = hh.getHhSize(); + distToRailStop = originZone.getDistanceToNearestRailStop(); + isMunichTrip = originZone.isMunichZone(); + + if (monthlyIncome_EUR <= 1500) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT1500_other_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 1500 && monthlyIncome_EUR <= 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT5600_other_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT7000_other_TNC; // change in VOT and cost + } + + utilityAutoD = interceptHBO[0] + maleHBO[0] * (gender.name().equals("MALE")) + driversLicenseHBO[0] * driversLicense + + hhAutosHBO[0] * hhAutos + hhSizeHBO[0] * hhSize + distToRailStopHBO[0] * distToRailStop + + generalizedCostHBO[0] * gcAutoD + isMunichTripHBO[0] * isMunichTrip; + + utilityAutoP = interceptHBO[1] + maleHBO[1] * (gender.name().equals("MALE")) + driversLicenseHBO[1] * driversLicense + + hhAutosHBO[1] * hhAutos + hhSizeHBO[1] * hhSize + distToRailStopHBO[1] * distToRailStop + + generalizedCostHBO[1] * gcAutoP + isMunichTripHBO[1] * isMunichTrip; + + utilityBicycle = interceptHBO[2] + maleHBO[2] * (gender.name().equals("MALE")) + driversLicenseHBO[2] * driversLicense + + hhAutosHBO[2] * hhAutos + hhSizeHBO[2] * hhSize + distToRailStopHBO[2] * distToRailStop + + tripLengthHBO[2] * travelDistanceNMT + isMunichTripHBO[2] * isMunichTrip; + + utilityBus = interceptHBO[3] + maleHBO[3] * (gender.name().equals("MALE")) + driversLicenseHBO[3] * driversLicense + + hhAutosHBO[3] * hhAutos + hhSizeHBO[3] * hhSize + distToRailStopHBO[3] * distToRailStop + + generalizedCostHBO[3] * gcBus + isMunichTripHBO[3] * isMunichTrip; + + utilityTrain = interceptHBO[4] + maleHBO[4] * (gender.name().equals("MALE")) + driversLicenseHBO[4] * driversLicense + + hhAutosHBO[4] * hhAutos + hhSizeHBO[4] * hhSize + distToRailStopHBO[4] * distToRailStop + + generalizedCostHBO[4] * gcTrain + isMunichTripHBO[4] * isMunichTrip; + + utilityTramMetro = interceptHBO[5] + maleHBO[5] * (gender.name().equals("MALE")) + driversLicenseHBO[5] * driversLicense + + hhAutosHBO[5] * hhAutos + hhSizeHBO[5] * hhSize + distToRailStopHBO[5] * distToRailStop + + generalizedCostHBO[5] * gcTramMetro + isMunichTripHBO[5] * isMunichTrip; + + utilityWalk = interceptHBO[6] + maleHBO[6] * (gender.name().equals("MALE")) + driversLicenseHBO[6] * driversLicense + + hhAutosHBO[6] * hhAutos + hhSizeHBO[6] * hhSize + distToRailStopHBO[6] * distToRailStop + + tripLengthHBO[6] * travelDistanceNMT + isMunichTripHBO[6] * isMunichTrip; + + utilityTNC = utilityBus + generalizedCostHBO[3] * (gcTNC - gcBus); + + expsumNestAuto = Math.exp(utilityAutoD / nestingCoefficient) + Math.exp(utilityAutoP / nestingCoefficient); + expsumNestTransit = Math.exp(utilityBus / nestingCoefficient) + Math.exp(utilityTrain / nestingCoefficient) + Math.exp(utilityTramMetro / nestingCoefficient); + expsumNestNMT = Math.exp(utilityBicycle / nestingCoefficient) + Math.exp(utilityWalk / nestingCoefficient); + expsumTopLevel = Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) + Math.exp(utilityTNC) + Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) + Math.exp(nestingCoefficient * Math.log(expsumNestTransit)); + + if (expsumNestAuto > 0) { + probabilityAutoD = (Math.exp(utilityAutoD / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + probabilityAutoP = (Math.exp(utilityAutoP / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + } else { + probabilityAutoD = 0.0; + probabilityAutoP = 0.0; + } + + if (expsumNestTransit > 0) { + probabilityBus = (Math.exp(utilityBus / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTrain = (Math.exp(utilityTrain / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTramMetro = (Math.exp(utilityTramMetro / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + } else { + probabilityBus = 0.0; + probabilityTrain = 0.0; + probabilityTramMetro = 0.0; + } + + if (expsumNestNMT > 0) { + probabilityBicycle = (Math.exp(utilityBicycle / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) / expsumTopLevel); + probabilityWalk = (Math.exp(utilityWalk / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestWalk)) / expsumTopLevel); + } else { + probabilityBicycle = 0.0; + probabilityWalk = 0.0; + } + + probabilityTNC = Math.exp(utilityTNC) / expsumTopLevel; + + return Java.to([probabilityAutoD, probabilityAutoP, probabilityBicycle, probabilityBus, probabilityTrain, probabilityTramMetro, probabilityWalk, probabilityTNC], "double[]"); + +} + +///////////////////////////////////////////////// NHBW Mode Choice ///////////////////////////////////////////////////// + +// Beta coefficients for modes in the order: [AutoD, AutoP, Bicycle, Bus, Train, TramMetro, Walk] +interceptNHBW = [0.0, 0.58, 1.99, 0.72, 1.11, 1.02, 7.22]; +ageNHBW = [0.0, -0.0045, 0.0, 0.0, -0.0059, 0.0, -0.011]; +driversLicenseNHBW = [0.0, -0.94, -1.56, -1.61, -1.67, -1.37, -1.43]; +hhAutosNHBW = [0.0, -0.11, -1.12, -1.23, -1.44, -1.52, -0.47]; +distToRailStopNHBW = [0.0, 0.0, 0.0, -0.24, 0.0, -0.16, -0.37]; +generalizedCostNHBW = [-0.0034, -0.0034, 0.0, -0.0034, -0.0034, -0.0034, 0.0]; +tripLengthNHBW = [0.0, 0.0, -0.28, 0.0, 0.0, 0.0, -1.54]; + +var calculateNHBWProbabilities = function (hh, person, originZone, destinationZone, travelTimes, accessTimes, travelDistanceAuto, travelDistanceNMT, peakHour) { + + timeAutoD = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "car"); + timeAutoP = timeAutoD; + timeBus = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "bus"); + timeTrain = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "train"); + timeTramMetro = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "tramMetro"); + + monthlyIncome_EUR = hh.getMonthlyIncome_EUR(); + age = person.getAge(); + driversLicense = person.hasDriversLicense(); + hhAutos = hh.getAutos(); + distToRailStop = originZone.getDistanceToNearestRailStop(); + + if (monthlyIncome_EUR <= 1500) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT1500_other_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 1500 && monthlyIncome_EUR <= 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT5600_other_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT7000_other_TNC; // change in VOT and cost + } + + utilityAutoD = interceptNHBW[0] + ageNHBW[0] * age + driversLicenseNHBW[0] * driversLicense + + hhAutosNHBW[0] * hhAutos + distToRailStopNHBW[0] * distToRailStop + generalizedCostNHBW[0] * gcAutoD; + + utilityAutoP = interceptNHBW[1] + ageNHBW[1] * age + driversLicenseNHBW[1] * driversLicense + + hhAutosNHBW[1] * hhAutos + distToRailStopNHBW[1] * distToRailStop + generalizedCostNHBW[1] * gcAutoP; + + utilityBicycle = interceptNHBW[2] + ageNHBW[2] * age + driversLicenseNHBW[2] * driversLicense + + hhAutosNHBW[2] * hhAutos + distToRailStopNHBW[2] * distToRailStop + tripLengthNHBW[2] * travelDistanceNMT; + + utilityBus = interceptNHBW[3] + ageNHBW[3] * age + driversLicenseNHBW[3] * driversLicense + + hhAutosNHBW[3] * hhAutos + distToRailStopNHBW[3] * distToRailStop + generalizedCostNHBW[3] * gcBus; + + utilityTrain = interceptNHBW[4] + ageNHBW[4] * age + driversLicenseNHBW[4] * driversLicense + + hhAutosNHBW[4] * hhAutos + distToRailStopNHBW[4] * distToRailStop + generalizedCostNHBW[4] * gcTrain; + + utilityTramMetro = interceptNHBW[5] + ageNHBW[5] * age + driversLicenseNHBW[5] * driversLicense + + hhAutosNHBW[5] * hhAutos + distToRailStopNHBW[5] * distToRailStop + generalizedCostNHBW[5] * gcTramMetro; + + utilityWalk = interceptNHBW[6] + ageNHBW[6] * age + driversLicenseNHBW[6] * driversLicense + + hhAutosNHBW[6] * hhAutos + distToRailStopNHBW[6] * distToRailStop + tripLengthNHBW[6] * travelDistanceNMT; + + utilityTNC = utilityBus + generalizedCostNHBW[3] * (gcTNC - gcBus); + + expsumNestAuto = Math.exp(utilityAutoD / nestingCoefficient) + Math.exp(utilityAutoP / nestingCoefficient); + expsumNestTransit = Math.exp(utilityBus / nestingCoefficient) + Math.exp(utilityTrain / nestingCoefficient) + Math.exp(utilityTramMetro / nestingCoefficient); + expsumNestNMT = Math.exp(utilityBicycle / nestingCoefficient) + Math.exp(utilityWalk / nestingCoefficient); + expsumTopLevel = Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) + Math.exp(utilityTNC) + Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) + Math.exp(nestingCoefficient * Math.log(expsumNestTransit)); + + if (expsumNestAuto > 0) { + probabilityAutoD = (Math.exp(utilityAutoD / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + probabilityAutoP = (Math.exp(utilityAutoP / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + } else { + probabilityAutoD = 0.0; + probabilityAutoP = 0.0; + } + + if (expsumNestTransit > 0) { + probabilityBus = (Math.exp(utilityBus / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTrain = (Math.exp(utilityTrain / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTramMetro = (Math.exp(utilityTramMetro / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + } else { + probabilityBus = 0.0; + probabilityTrain = 0.0; + probabilityTramMetro = 0.0; + } + + if (expsumNestNMT > 0) { + probabilityBicycle = (Math.exp(utilityBicycle / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) / expsumTopLevel); + probabilityWalk = (Math.exp(utilityWalk / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestWalk)) / expsumTopLevel); + } else { + probabilityBicycle = 0.0; + probabilityWalk = 0.0; + } + + probabilityTNC = Math.exp(utilityTNC) / expsumTopLevel; + + return Java.to([probabilityAutoD, probabilityAutoP, probabilityBicycle, probabilityBus, probabilityTrain, probabilityTramMetro, probabilityWalk, probabilityTNC], "double[]"); + +} + + +///////////////////////////////////////////////// NHBO Mode Choice ///////////////////////////////////////////////////// + +// Beta coefficients for modes in the order: [AutoD, AutoP, Bicycle, Bus, Train, TramMetro, Walk] +interceptNHBO = [0.0, 1.21, 0.93, 0.68, 0.64, 0.84, 2.99]; +maleNHBO = [0.0, -0.24, 0.0, -0.20, -0.23, -0.18, -0.073]; +driversLicenseNHBO = [0.0, -1.40, -1.49, -2.02, -1.74, -1.77, -1.44]; +hhAutosNHBO = [0.0, -0.029, -0.73, -0.80, -0.85, -0.86, -0.40]; +distToRailStopNHBO = [0.0, 0.0, 0.0, -0.40, -0.44, -0.48, 0.0]; +agglomerationUrbanNHBO = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; +ruralNHBO = [0.0, 0.0, 0.0, -0.70, -0.91, -1.12, 0.0]; +generalizedCostNHBO_Sq = [-0.000017, -0.000017, 0.0, -0.000017, -0.000017, -0.000017, 0.0]; +tripLengthNHBO = [0.0, 0.0, -0.15, 0.0, 0.0, 0.0, -0.57]; + +var calculateNHBOProbabilities = function (hh, person, originZone, destinationZone, travelTimes, accessTimes, travelDistanceAuto, travelDistanceNMT, travelCostUAM, peakHour) { + + timeAutoD = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "car"); + timeAutoP = timeAutoD; + timeBus = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "bus"); + timeTrain = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "train"); + timeTramMetro = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "tramMetro"); + + monthlyIncome_EUR = hh.getMonthlyIncome_EUR(); + gender = person.getMitoGender(); + driversLicense = person.hasDriversLicense(); + hhAutos = hh.getAutos(); + distToRailStop = originZone.getDistanceToNearestRailStop(); + areaType = originZone.getAreaTypeR(); + + if (monthlyIncome_EUR <= 1500) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT1500_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT1500_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT1500_other_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 1500 && monthlyIncome_EUR <= 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT5600_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT5600_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT5600_other_TNC; // change in VOT and cost + } else if (monthlyIncome_EUR > 5600) { + gcAutoD = timeAutoD + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_other_autoD; + gcAutoP = timeAutoP + (travelDistanceAuto * fuelCostEurosPerKm) / VOT7000_other_autoP; + gcBus = timeBus + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTrain = timeTrain + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTramMetro = timeTramMetro + (travelDistanceAuto * transitFareEurosPerKm) / VOT7000_other_transit; + gcTNC = timeAutoD + (travelDistanceAuto * TNCCostEurosPerKm) / VOT7000_other_TNC; // change in VOT and cost + } + + utilityAutoD = interceptNHBO[0] + maleNHBO[0] * (gender.name().equals("MALE")) + driversLicenseNHBO[0] * driversLicense + + hhAutosNHBO[0] * hhAutos + distToRailStopNHBO[0] * distToRailStop + + agglomerationUrbanNHBO[0] * (areaType.name().equals("AGGLOMERATION") + areaType.name().equals("URBAN")) + + ruralNHBO[0] * (areaType.name().equals("RURAL")) + generalizedCostNHBO_Sq[0] * Math.pow(gcAutoD, 2); + + utilityAutoP = interceptNHBO[1] + maleNHBO[1] * (gender.name().equals("MALE")) + driversLicenseNHBO[1] * driversLicense + + hhAutosNHBO[1] * hhAutos + distToRailStopNHBO[1] * distToRailStop + + agglomerationUrbanNHBO[1] * (areaType.name().equals("AGGLOMERATION") + areaType.name().equals("URBAN")) + + ruralNHBO[1] * (areaType.name().equals("RURAL")) + generalizedCostNHBO_Sq[1] * Math.pow(gcAutoP, 2); + + utilityBicycle = interceptNHBO[2] + maleNHBO[2] * (gender.name().equals("MALE")) + driversLicenseNHBO[2] * driversLicense + + hhAutosNHBO[2] * hhAutos + distToRailStopNHBO[2] * distToRailStop + + agglomerationUrbanNHBO[2] * (areaType.name().equals("AGGLOMERATION") + areaType.name().equals("URBAN")) + + ruralNHBO[2] * (areaType.name().equals("RURAL")) + tripLengthNHBO[2] * travelDistanceNMT; + + utilityBus = interceptNHBO[3] + maleNHBO[3] * (gender.name().equals("MALE")) + driversLicenseNHBO[3] * driversLicense + + hhAutosNHBO[3] * hhAutos + distToRailStopNHBO[3] * distToRailStop + + agglomerationUrbanNHBO[3] * (areaType.name().equals("AGGLOMERATION") + areaType.name().equals("URBAN")) + + ruralNHBO[3] * (areaType.name().equals("RURAL")) + generalizedCostNHBO_Sq[3] * Math.pow(gcBus, 2); + + utilityTrain = interceptNHBO[4] + maleNHBO[4] * (gender.name().equals("MALE")) + driversLicenseNHBO[4] * driversLicense + + hhAutosNHBO[4] * hhAutos + distToRailStopNHBO[4] * distToRailStop + + agglomerationUrbanNHBO[4] * (areaType.name().equals("AGGLOMERATION") + areaType.name().equals("URBAN")) + + ruralNHBO[4] * (areaType.name().equals("RURAL")) + generalizedCostNHBO_Sq[4] * Math.pow(gcTrain, 2); + + utilityTramMetro = interceptNHBO[5] + maleNHBO[5] * (gender.name().equals("MALE")) + driversLicenseNHBO[5] * driversLicense + + hhAutosNHBO[5] * hhAutos + distToRailStopNHBO[5] * distToRailStop + + agglomerationUrbanNHBO[5] * (areaType.name().equals("AGGLOMERATION") + areaType.name().equals("URBAN")) + + ruralNHBO[5] * (areaType.name().equals("RURAL")) + generalizedCostNHBO_Sq[5] * Math.pow(gcTramMetro, 2); + + utilityWalk = interceptNHBO[6] + maleNHBO[6] * (gender.name().equals("MALE")) + driversLicenseNHBO[6] * driversLicense + + hhAutosNHBO[6] * hhAutos + distToRailStopNHBO[6] * distToRailStop + + agglomerationUrbanNHBO[6] * (areaType.name().equals("AGGLOMERATION") + areaType.name().equals("URBAN")) + + ruralNHBO[6] * (areaType.name().equals("RURAL")) + tripLengthNHBO[6] * travelDistanceNMT; + + utilityTNC = utilityBus + generalizedCostNHBO_Sq[3] * (Math.pow(gcTNC, 2) - Math.pow(gcBus, 2)); + + expsumNestAuto = Math.exp(utilityAutoD / nestingCoefficient) + Math.exp(utilityAutoP / nestingCoefficient); + expsumNestTransit = Math.exp(utilityBus / nestingCoefficient) + Math.exp(utilityTrain / nestingCoefficient) + Math.exp(utilityTramMetro / nestingCoefficient); + expsumNestNMT = Math.exp(utilityBicycle / nestingCoefficient) + Math.exp(utilityWalk / nestingCoefficient); + expsumTopLevel = Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) + Math.exp(utilityTNC) + Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) + Math.exp(nestingCoefficient * Math.log(expsumNestTransit)); + + if (expsumNestAuto > 0) { + probabilityAutoD = (Math.exp(utilityAutoD / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + probabilityAutoP = (Math.exp(utilityAutoP / nestingCoefficient) / expsumNestAuto) * (Math.exp(nestingCoefficient * Math.log(expsumNestAuto)) / expsumTopLevel); + } else { + probabilityAutoD = 0.0; + probabilityAutoP = 0.0; + } + + if (expsumNestTransit > 0) { + probabilityBus = (Math.exp(utilityBus / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTrain = (Math.exp(utilityTrain / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + probabilityTramMetro = (Math.exp(utilityTramMetro / nestingCoefficient) / expsumNestTransit) * (Math.exp(nestingCoefficient * Math.log(expsumNestTransit)) / expsumTopLevel); + } else { + probabilityBus = 0.0; + probabilityTrain = 0.0; + probabilityTramMetro = 0.0; + } + + if (expsumNestNMT > 0) { + probabilityBicycle = (Math.exp(utilityBicycle / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestNMT)) / expsumTopLevel); + probabilityWalk = (Math.exp(utilityWalk / nestingCoefficient) / expsumNestNMT) * (Math.exp(nestingCoefficient * Math.log(expsumNestWalk)) / expsumTopLevel); + } else { + probabilityBicycle = 0.0; + probabilityWalk = 0.0; + } + + probabilityTNC = Math.exp(utilityTNC) / expsumTopLevel; + + return Java.to([probabilityAutoD, probabilityAutoP, probabilityBicycle, probabilityBus, probabilityTrain, probabilityTramMetro, probabilityWalk, probabilityTNC], "double[]"); + +} + + + +//AIRPORT + +/*var calculateAIRPORTUtilities = function (hh, person, originZone, destinationZone, travelTimes, travelDistanceAuto, travelDistanceNMT, peakHour) { + + asc_autoDriver = 0.; + asc_autoPassenger = 0.706154; + asc_bus = 1.890414; + asc_train = 2.028797; + asc_sharedAV = 1.282504; + + //times are in minutes + beta_time = -0.0002 * 60; + exp_time_autoDriver = 0; + exp_time_autoPassenger = 0; + exp_time_bus = 0; + exp_time_train = 0; + exp_time_sharedAV = 0; + + //distance is in minutes + beta_distance = -0.00002; + exp_distance_autoDriver = 0; + exp_distance_autoPassenger = 0; + exp_distance_bus = 0; + exp_distance_train = 0; + exp_distance_sharedAV = 0; + + //generalized cost in minutes and values of time + b_gcost_all = -0.018834; + VOT_AIRPORT_autoDriver = 63./60; + VOT_AIRPORT_autoPassengerAndOther = 83.1 / 60; + VOT_AIRPORT_publicTransport = 97.8 / 60; + + //Order of variables in the return variable autoDriver, autoPassenger bus, train, sharedAV + + travelTimeCar = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "car"); + u_autoDriver = asc_autoDriver + + exp_time_autoDriver * Math.exp(beta_time * travelTimeCar) + + exp_distance_autoDriver * Math.exp(beta_distance * travelDistanceAuto) + + b_gcost_all * (travelTimeCar + travelDistanceAuto * fuelCostEurosPerKm / VOT_AIRPORT_autoDriver); + + u_autoPassenger = asc_autoPassenger + + exp_time_autoPassenger * Math.exp(beta_time * travelTimeCar) + + exp_distance_autoPassenger * Math.exp(beta_distance * travelDistanceAuto) + + b_gcost_all * (travelTimeCar + travelDistanceAuto * fuelCostEurosPerKm / VOT_AIRPORT_autoPassengerAndOther); + + travelTimeBus = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "bus"); + u_bus = asc_bus + + exp_time_bus * Math.exp(beta_time * travelTimeBus) + + exp_distance_bus * Math.exp(beta_distance * travelDistanceAuto) + + b_gcost_all * (travelTimeBus + travelDistanceAuto * transitFareEurosPerKm / VOT_AIRPORT_publicTransport); + + travelTimeTrain = travelTimes.getTravelTime(originZone, destinationZone, peakHour, "train"); + u_train = asc_train + + exp_time_train * Math.exp(beta_time * travelTimeTrain) + + exp_distance_train * Math.exp(beta_distance * travelDistanceAuto) + + b_gcost_all * (travelTimeTrain + travelDistanceAuto * transitFareEurosPerKm / VOT_AIRPORT_publicTransport); + + u_sharedAV = asc_sharedAV + + exp_time_sharedAV * Math.exp(beta_time * travelTimeCar) + + exp_distance_sharedAV * Math.exp(beta_distance * travelDistanceAuto) + + b_gcost_all * (travelTimeCar + travelDistanceAuto*sharedAVCostEurosPerKm / VOT_AIRPORT_autoPassengerAndOther); + + return [Math.exp(u_autoDriver), Math.exp(u_autoPassenger), Math.exp(u_bus), Math.exp(u_train), Math.exp(u_sharedAV)]; +} + + +var calculateAIRPORTProbabilities = function (hh, person, originZone, destinationZone, travelTimes, accessTimes, + travelDistanceAuto, travelDistanceNMT, peakHour) { + + + //Order of variables in the return variable [AutoD, AutoP, Bicycle, Bus, Train, TramMetro, Walk, sharedAV] + //calculate utilities for each mode + utilities = calculateAIRPORTUtilities(hh, person, originZone, destinationZone, travelTimes, travelDistanceAuto, travelDistanceNMT, peakHour); + + sum_u = utilities[0] + utilities[1] + utilities[2] + utilities[3] + utilities[4]; + + probabilityAutoD = utilities[0] / sum_u; + probabilityAutoP = utilities[1] / sum_u; + probabilityBus = utilities[2] / sum_u; + probabilityTrain = utilities[3] / sum_u; + probabilitySharedAV = utilities[4] / sum_u; + + return Java.to([probabilityAutoD, probabilityAutoP, 0., probabilityBus, probabilityTrain, 0., 0., probabilitySharedAV], "double[]"); + +} + +var returnLogsumAIRPORT = function (hh, person, originZone, destinationZone, travelTimes, accessTimes, + travelDistanceAuto, travelDistanceNMT, travelCostUAM, peakHour, handlingTime, uamFareEurosPerKm) { + + //Order of variables in the return variable [AutoD, AutoP, Bicycle, Bus, Train, TramMetro, Walk, privateAV, sharedAV, UAM] + utilities = calculateAIRPORTUtilities(hh, person, originZone, destinationZone, travelTimes, travelDistanceAuto, travelDistanceNMT, peakHour); + + sum_u = utilities[0] + utilities[1] + utilities[2] + utilities[3] + utilities[4]; + + return Math.log(sum_u); +}*/ \ No newline at end of file