diff --git a/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/MatsimData.java b/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/MatsimData.java index 19965bc06..b47549239 100644 --- a/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/MatsimData.java +++ b/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/MatsimData.java @@ -33,26 +33,26 @@ public final class MatsimData { private MutableScenario scenario; private LeastCostPathCalculatorFactory leastCostPathCalculatorFactory; - private final LeastCostPathCalculatorFactory multiNodeFactory = new FastMultiNodeDijkstraFactory(true); + private final LeastCostPathCalculatorFactory multiNodeFactory = new FastMultiNodeDijkstraFactory(true); - private SwissRailRaptorData raptorData; - private SwissRailRaptorData raptorDataOneToAll; + private SwissRailRaptorData raptorData; + private SwissRailRaptorData raptorDataOneToAll; - private final int nThreads; + private final int nThreads; private Network carNetwork; - private Network ptNetwork; + private Network ptNetwork; private RaptorParameters raptorParameters; - private DefaultRaptorParametersForPerson parametersForPerson; - private LeastCostRaptorRouteSelector routeSelector; - private DefaultRaptorStopFinder defaultRaptorStopFinder; + private DefaultRaptorParametersForPerson parametersForPerson; + private LeastCostRaptorRouteSelector routeSelector; + private DefaultRaptorStopFinder defaultRaptorStopFinder; - private TravelDisutility travelDisutility; - private TravelTime travelTime; + private TravelDisutility travelDisutility; + private TravelTime travelTime; - private final ZoneConnectorManager zoneConnectorManager; - private final static int NUMBER_OF_CALC_POINTS = 1; + private final ZoneConnectorManager zoneConnectorManager; + private final static int NUMBER_OF_CALC_POINTS = 1; // yyyyyy The TripRouter needs the vehicles container to work properly. This is provided to the TripRouter via the Scenario. In consequence, we need to maintain a somewhat // consistent scenario. @@ -68,144 +68,127 @@ public MatsimData( Properties properties, ZoneConnectorManager.ZoneConnectorMeth * @deprecated -- use {@link MatsimData#MatsimData(Properties, ZoneConnectorManager.ZoneConnectorMethod, DataContainer, MutableScenario)} */ @Deprecated - public MatsimData(Config config, Properties properties, ZoneConnectorManagerImpl.ZoneConnectorMethod method, DataContainer dataContainer, Network network, TransitSchedule schedule) { + public MatsimData(Config config, Properties properties, ZoneConnectorManagerImpl.ZoneConnectorMethod method, DataContainer dataContainer, Network network, TransitSchedule schedule) { this.scenario = ScenarioUtils.createMutableScenario( config ); this.scenario.setTransitSchedule( schedule ); - int threads = properties.main.numberOfThreads; - final Collection zones = dataContainer.getGeoData().getZones().values(); - ZoneConnectorManager zoneConnectorManager; - switch (method) { - case RANDOM: - zoneConnectorManager = ZoneConnectorManagerImpl.createRandomZoneConnectors(zones, NUMBER_OF_CALC_POINTS); - break; - case WEIGHTED_BY_POPULATION: - zoneConnectorManager = ZoneConnectorManagerImpl.createWeightedZoneConnectors(zones, - dataContainer.getRealEstateDataManager(), - dataContainer.getHouseholdDataManager()); - break; - default: - throw new RuntimeException("No valid zone connector method defined!"); - } - - ConfigUtils.setVspDefaults(config); // Needs to be done before config becomes locked for those changes + int threads = properties.main.numberOfThreads; + final Collection zones = dataContainer.getGeoData().getZones().values(); + ZoneConnectorManager zoneConnectorManager = switch( method ){ + case RANDOM -> ZoneConnectorManagerImpl.createRandomZoneConnectors( zones, NUMBER_OF_CALC_POINTS ); + case WEIGHTED_BY_POPULATION -> ZoneConnectorManagerImpl.createWeightedZoneConnectors( zones, + dataContainer.getRealEstateDataManager(), + dataContainer.getHouseholdDataManager() ); + default -> throw new RuntimeException( "No valid zone connector method defined!" ); + }; + + ConfigUtils.setVspDefaults(config); // Needs to be done before config becomes locked for those changes this.raptorParameters = RaptorUtils.createParameters(config); - this.nThreads = threads; + this.nThreads = threads; this.zoneConnectorManager = zoneConnectorManager; - filterNetwork(network); - } + filterNetwork(network); + } /** * @deprecated -- use {@link MatsimData#MatsimData(Properties, ZoneConnectorManager.ZoneConnectorMethod, DataContainer, MutableScenario)} */ @Deprecated - public MatsimData(Config config, Properties properties, ZoneConnectorManagerImpl.ZoneConnectorMethod method, DataContainer dataContainer, Network network) { + public MatsimData(Config config, Properties properties, ZoneConnectorManagerImpl.ZoneConnectorMethod method, DataContainer dataContainer, Network network) { this.scenario = ScenarioUtils.createMutableScenario( config ); // yyyyyy MatsimData needs the scenario, everything else is stupid. kai - int threads = properties.main.numberOfThreads; - final Collection zones = dataContainer.getGeoData().getZones().values(); - ZoneConnectorManager zoneConnectorManager; - switch (method) { - case RANDOM: - zoneConnectorManager = ZoneConnectorManagerImpl.createRandomZoneConnectors(zones, NUMBER_OF_CALC_POINTS); - break; - case WEIGHTED_BY_POPULATION: - zoneConnectorManager = ZoneConnectorManagerImpl.createWeightedZoneConnectors(zones, - dataContainer.getRealEstateDataManager(), - dataContainer.getHouseholdDataManager()); - break; - default: - throw new RuntimeException("No valid zone connector method defined!"); - } - - ConfigUtils.setVspDefaults(config); // Needs to be done before config becomes locked for those changes + int threads = properties.main.numberOfThreads; + final Collection zones = dataContainer.getGeoData().getZones().values(); + ZoneConnectorManager zoneConnectorManager = switch( method ){ + case RANDOM -> ZoneConnectorManagerImpl.createRandomZoneConnectors( zones, NUMBER_OF_CALC_POINTS ); + case WEIGHTED_BY_POPULATION -> ZoneConnectorManagerImpl.createWeightedZoneConnectors( zones, + dataContainer.getRealEstateDataManager(), + dataContainer.getHouseholdDataManager() ); + default -> throw new RuntimeException( "No valid zone connector method defined!" ); + }; + + ConfigUtils.setVspDefaults(config); // Needs to be done before config becomes locked for those changes this.nThreads = threads; this.zoneConnectorManager = zoneConnectorManager; - filterNetwork(network); - } + filterNetwork(network); + } /** * @deprecated -- use {@link MatsimData#MatsimData(Properties, ZoneConnectorManager.ZoneConnectorMethod, DataContainer, MutableScenario)} */ @Deprecated - public MatsimData(Config config, int threads,Network network, TransitSchedule schedule, ZoneConnectorManager zoneConnectorManager) { + public MatsimData(Config config, int threads,Network network, TransitSchedule schedule, ZoneConnectorManager zoneConnectorManager) { this.scenario = ScenarioUtils.createMutableScenario( config ); this.scenario.setTransitSchedule( schedule ); - ConfigUtils.setVspDefaults(config); // Needs to be done before config becomes locked for those changes + ConfigUtils.setVspDefaults(config); // Needs to be done before config becomes locked for those changes this.raptorParameters = RaptorUtils.createParameters(config); - this.nThreads = threads; + this.nThreads = threads; this.zoneConnectorManager = zoneConnectorManager; - filterNetwork(network); - } - - public void filterNetwork(Network network) { - TransportModeNetworkFilter filter = new TransportModeNetworkFilter(network); + filterNetwork(network); + } - Set car = Sets.newHashSet(TransportMode.car); - Set pt = Sets.newHashSet(TransportMode.pt, TransportMode.train, "bus", - "artificial", "subway", "tram", "rail"); + public void filterNetwork(Network network) { + TransportModeNetworkFilter filter = new TransportModeNetworkFilter(network); - Network carNetwork = NetworkUtils.createNetwork(); - filter.filter(carNetwork, car); + Set car = Sets.newHashSet(TransportMode.car); + Set pt = Sets.newHashSet(TransportMode.pt, TransportMode.train, "bus", + "artificial", "subway", "tram", "rail"); - Network ptNetwork = NetworkUtils.createNetwork(); - filter.filter(ptNetwork, pt); + Network carNetwork = NetworkUtils.createNetwork(); + filter.filter(carNetwork, car); - this.carNetwork = carNetwork; - this.ptNetwork = ptNetwork; - } + Network ptNetwork = NetworkUtils.createNetwork(); + filter.filter(ptNetwork, pt); - ZoneConnectorManager getZoneConnectorManager() { - return zoneConnectorManager; - } + this.carNetwork = carNetwork; + this.ptNetwork = ptNetwork; + } - public Network getCarNetwork() { - return carNetwork; - } + ZoneConnectorManager getZoneConnectorManager() { + return zoneConnectorManager; + } -// Network getPtNetwork() { -// return ptNetwork; -// } - // never used + public Network getCarNetwork() { + return carNetwork; + } - public void update(TravelDisutility travelDisutility, TravelTime travelTime) { - this.travelDisutility = travelDisutility; - this.travelTime = travelTime; + public void update(TravelDisutility travelDisutility, TravelTime travelTime) { + this.travelDisutility = travelDisutility; + this.travelTime = travelTime; - this.leastCostPathCalculatorFactory = new AStarLandmarksFactory(nThreads); + this.leastCostPathCalculatorFactory = new AStarLandmarksFactory(nThreads); - if ( this.scenario.getConfig().transit().isUseTransit() && this.scenario.getTransitSchedule() != null) { - RaptorStaticConfig raptorConfig = RaptorUtils.createStaticConfig( this.scenario.getConfig() ); - Vehicles ptVehicles = null; - OccupancyData occupancyData = null; - raptorData = SwissRailRaptorData.create( this.scenario.getTransitSchedule(), ptVehicles, raptorConfig, ptNetwork, occupancyData ); + if ( this.scenario.getConfig().transit().isUseTransit() && this.scenario.getTransitSchedule() != null) { + RaptorStaticConfig raptorConfig = RaptorUtils.createStaticConfig( this.scenario.getConfig() ); + Vehicles ptVehicles = null; + OccupancyData occupancyData = null; + raptorData = SwissRailRaptorData.create( this.scenario.getTransitSchedule(), ptVehicles, raptorConfig, ptNetwork, occupancyData ); - RaptorStaticConfig raptorConfigOneToAll = RaptorUtils.createStaticConfig( this.scenario.getConfig() ); - raptorConfigOneToAll.setOptimization(RaptorStaticConfig.RaptorOptimization.OneToAllRouting); - raptorDataOneToAll = SwissRailRaptorData.create( this.scenario.getTransitSchedule(), ptVehicles, raptorConfig, ptNetwork, occupancyData ); + RaptorStaticConfig raptorConfigOneToAll = RaptorUtils.createStaticConfig( this.scenario.getConfig() ); + raptorConfigOneToAll.setOptimization(RaptorStaticConfig.RaptorOptimization.OneToAllRouting); + raptorDataOneToAll = SwissRailRaptorData.create( this.scenario.getTransitSchedule(), ptVehicles, raptorConfig, ptNetwork, occupancyData ); - parametersForPerson = new DefaultRaptorParametersForPerson( this.scenario.getConfig() ); - defaultRaptorStopFinder = new DefaultRaptorStopFinder( + parametersForPerson = new DefaultRaptorParametersForPerson( this.scenario.getConfig() ); + defaultRaptorStopFinder = new DefaultRaptorStopFinder( this.scenario.getConfig(), - new DefaultRaptorIntermodalAccessEgress(), - null); - routeSelector = new LeastCostRaptorRouteSelector(); - } - } - - MultiNodePathCalculator createMultiNodePathCalculator() { - return (MultiNodePathCalculator) multiNodeFactory.createPathCalculator(carNetwork, travelDisutility, travelTime); - } - - MultiNodePathCalculator createFreeSpeedMultiNodePathCalculator() { - FreespeedTravelTimeAndDisutility freespeed = new FreespeedTravelTimeAndDisutility( this.scenario.getConfig().scoring()); - return (MultiNodePathCalculator) multiNodeFactory.createPathCalculator(carNetwork, freespeed, freespeed); - } - - TripRouter createTripRouter() { + new DefaultRaptorIntermodalAccessEgress(), + null); + routeSelector = new LeastCostRaptorRouteSelector(); + } + } + + MultiNodePathCalculator createMultiNodePathCalculator() { + return (MultiNodePathCalculator) multiNodeFactory.createPathCalculator(carNetwork, travelDisutility, travelTime); + } + + MultiNodePathCalculator createFreeSpeedMultiNodePathCalculator() { + FreespeedTravelTimeAndDisutility freespeed = new FreespeedTravelTimeAndDisutility( this.scenario.getConfig().scoring()); + return (MultiNodePathCalculator) multiNodeFactory.createPathCalculator(carNetwork, freespeed, freespeed); + } + + TripRouter createTripRouter() { // Scenario scenario = ScenarioUtils.loadScenario(config); com.google.inject.Injector injector = Injector.createMinimalMatsimInjector( this.scenario.getConfig(), scenario ); @@ -246,56 +229,58 @@ TripRouter createTripRouter() { // bd.setRoutingModule(TransportMode.car, carRoutingModule); // bd.setRoutingModule(TransportMode.pt, ptRoutingModule); // return bd.build(); - } - - SwissRailRaptor createSwissRailRaptor(RaptorStaticConfig.RaptorOptimization optimitzaion) { - - - switch (optimitzaion) { - case OneToAllRouting: - return new SwissRailRaptor(raptorDataOneToAll, parametersForPerson, routeSelector, defaultRaptorStopFinder, - new DefaultRaptorInVehicleCostCalculator(), new DefaultRaptorTransferCostCalculator()); - case OneToOneRouting: - return new SwissRailRaptor(raptorData, parametersForPerson, routeSelector, defaultRaptorStopFinder, - new DefaultRaptorInVehicleCostCalculator(), new DefaultRaptorTransferCostCalculator()); - default: - throw new RuntimeException("Unrecognized raptor optimization!"); - } - } - - LeastCostPathCalculator createLeastCostPathCalculator() { - return leastCostPathCalculatorFactory.createPathCalculator(carNetwork, travelDisutility, travelTime); - } - - RoutingModule getTeleportationRouter(String mode) { - Scenario scenario = ScenarioUtils.loadScenario( this.scenario.getConfig() ); - return DefaultRoutingModules.createTeleportationRouter( + } + + SwissRailRaptor createSwissRailRaptor(RaptorStaticConfig.RaptorOptimization optimitzaion) { + + + switch (optimitzaion) { + case OneToAllRouting: + return new SwissRailRaptor(raptorDataOneToAll, parametersForPerson, routeSelector, defaultRaptorStopFinder, + new DefaultRaptorInVehicleCostCalculator(), new DefaultRaptorTransferCostCalculator()); + case OneToOneRouting: + return new SwissRailRaptor(raptorData, parametersForPerson, routeSelector, defaultRaptorStopFinder, + new DefaultRaptorInVehicleCostCalculator(), new DefaultRaptorTransferCostCalculator()); + default: + throw new RuntimeException("Unrecognized raptor optimization!"); + } + } + +// LeastCostPathCalculator createLeastCostPathCalculator() { +// return leastCostPathCalculatorFactory.createPathCalculator(carNetwork, travelDisutility, travelTime); +// } + // never used + + RoutingModule getTeleportationRouter(String mode) { + Scenario scenario = ScenarioUtils.loadScenario( this.scenario.getConfig() ); + return DefaultRoutingModules.createTeleportationRouter( // mode, PopulationUtils.getFactory(), config.plansCalcRoute().getOrCreateModeRoutingParams(mode)); - mode, scenario, this.scenario.getConfig().routing().getModeRoutingParams().get(mode ) ); - } - - SwissRailRaptorData getRaptorData(RaptorStaticConfig.RaptorOptimization optimization) { - switch (optimization) { - case OneToAllRouting: - return raptorDataOneToAll; - case OneToOneRouting: - return raptorData; - default: - throw new RuntimeException("Unrecognized raptor optimization!"); - } - } - - RaptorParameters getRaptorParameters() { - return raptorParameters; - } - - public void updateMatsimPopulation(Population matsimPopulation) { + mode, scenario, this.scenario.getConfig().routing().getModeRoutingParams().get(mode ) ); + } + + SwissRailRaptorData getRaptorData(RaptorStaticConfig.RaptorOptimization optimization) { + switch (optimization) { + case OneToAllRouting: + return raptorDataOneToAll; + case OneToOneRouting: + return raptorData; + default: + throw new RuntimeException("Unrecognized raptor optimization!"); + } + } + + RaptorParameters getRaptorParameters() { + return raptorParameters; + } + + public void updateMatsimPopulation(Population matsimPopulation) { this.scenario.setPopulation( matsimPopulation ); - } + } // public void updateMatsimVehicles( Vehicles vehicles ) { // this.scenario.setVehicles( vehicles ); // } // yyyyyy forgotten method in matsim api :-( + // added here: https://github.com/matsim-org/matsim-libs/pull/5034 . Uncomment once available. kai, jun'26 // === only pure getters below here @@ -308,9 +293,5 @@ public Scenario getScenario(){ public Population getMatsimPopulation() { return this.scenario.getPopulation(); } -// public TransitSchedule getSchedule() { -// // where is this needed? The router is plugged together in the present class ... -// return this.scenario.getTransitSchedule(); -// } } diff --git a/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/SimpleCommuteModeChoiceMatsimScenarioAssembler.java b/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/SimpleCommuteModeChoiceMatsimScenarioAssembler.java index bff93bf65..5da1888cd 100644 --- a/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/SimpleCommuteModeChoiceMatsimScenarioAssembler.java +++ b/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/SimpleCommuteModeChoiceMatsimScenarioAssembler.java @@ -119,8 +119,8 @@ public Scenario assembleScenario(Config matsimConfig, int year, TravelTimes trav PopulationFactory pf = matsimPopulation.getFactory(); - final int noHHAUtos = (int) household.getVehicles().stream().filter( vv -> vv.getType().equals( VehicleType.CAR ) ).count(); - org.matsim.api.core.v01.population.Person matsimAlterEgo = SiloMatsimUtils.createMatsimAlterEgo(pf, person, noHHAUtos ); + final int nHhCars = (int) household.getVehicles().stream().filter( vv -> vv.getType().equals( VehicleType.CAR ) ).count(); + org.matsim.api.core.v01.population.Person matsimAlterEgo = SiloMatsimUtils.createMatsimAlterEgo(pf, person, nHhCars ); matsimPopulation.addPerson(matsimAlterEgo); Dwelling dwelling = realEstateDataManager.getDwelling(household.getDwellingId()); diff --git a/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/SimpleMatsimCommuteModeChoice.java b/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/SimpleMatsimCommuteModeChoice.java index e4c748414..079ce9ae2 100644 --- a/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/SimpleMatsimCommuteModeChoice.java +++ b/extensions/matsim2silo/src/main/java/de/tum/bgu/msm/matsim/SimpleMatsimCommuteModeChoice.java @@ -21,6 +21,8 @@ import java.util.*; +import static org.matsim.api.core.v01.TransportMode.*; + /** * Copy of SimpleCommuteModeChoice, but with person in argument of travel time request */ @@ -32,8 +34,7 @@ public class SimpleMatsimCommuteModeChoice implements CommuteModeChoice { private final GeoData geoData; private final Random random; - public SimpleMatsimCommuteModeChoice(DataContainer dataContainer, - Properties properties, Random random) { + public SimpleMatsimCommuteModeChoice(DataContainer dataContainer, Properties properties, Random random) { this.properties = properties; this.commutingTimeProbability = dataContainer.getCommutingTimeProbability(); this.jobDataManager = dataContainer.getJobDataManager(); @@ -50,25 +51,27 @@ public CommuteModeChoiceMapping assignCommuteModeChoice(Location from, TravelTim Map> commuteModesByPerson = new LinkedHashMap<>(); TreeMap personByProbability = new TreeMap<>(); + // I think that the following assigns, for each member of the hh, logit probabilities based on travel time for pt and, if available, car. for (Person pp : household.getPersons().values()) { if (pp.getOccupation() == Occupation.EMPLOYED && pp.getJobId() != -2) { + // (yy what is encoded by "-2"?) Job job = jobDataManager.getJobFromId(pp.getJobId()); // TODO clean up the following line - int ptMinutes = (int) ((MatsimTravelTimesAndCosts) travelTimes).getTravelTime(from, job, job.getStartTimeInSeconds().orElse((int) properties.transportModel.peakHour_s), TransportMode.pt, pp); - double ptUtility = commutingTimeProbability.getCommutingTimeProbability(ptMinutes, TransportMode.pt); + int ptMinutes = (int) ((MatsimTravelTimesAndCosts) travelTimes).getTravelTime(from, job, job.getStartTimeInSeconds().orElse((int) properties.transportModel.peakHour_s), pt, pp); + double ptUtility = commutingTimeProbability.getCommutingTimeProbability(ptMinutes, pt); if (!pp.hasDriverLicense() || (int) household.getVehicles().stream().filter(vv -> vv.getType().equals(VehicleType.CAR)).count() == 0) { - CommuteModeChoiceMapping.CommuteMode ptCommuteMode = new CommuteModeChoiceMapping.CommuteMode(TransportMode.pt, ptUtility); + CommuteModeChoiceMapping.CommuteMode ptCommuteMode = new CommuteModeChoiceMapping.CommuteMode( pt, ptUtility); commuteModeChoiceMapping.assignMode(ptCommuteMode, pp); } else { // TODO clean up the following line - int carMinutes = (int) ((MatsimTravelTimesAndCosts) travelTimes).getTravelTime(from, job, job.getStartTimeInSeconds().orElse((int) properties.transportModel.peakHour_s), TransportMode.car, pp); - double carUtility = commutingTimeProbability.getCommutingTimeProbability(carMinutes, TransportMode.car); + int carMinutes = (int) ((MatsimTravelTimesAndCosts) travelTimes).getTravelTime(from, job, job.getStartTimeInSeconds().orElse((int) properties.transportModel.peakHour_s), car, pp); + double carUtility = commutingTimeProbability.getCommutingTimeProbability(carMinutes, car); Map utilityByMode = new LinkedHashMap<>(); - utilityByMode.put(TransportMode.car, carUtility); - utilityByMode.put(TransportMode.pt, ptUtility); + utilityByMode.put( car, carUtility ); + utilityByMode.put( pt, ptUtility ); commuteModesByPerson.put(pp.getId(), utilityByMode); double probabilityAsKey; if (carUtility == 0 && ptUtility == 0) { @@ -78,6 +81,8 @@ public CommuteModeChoiceMapping assignCommuteModeChoice(Location from, TravelTim } while (personByProbability.containsKey(probabilityAsKey)) { //more than one hh member has exactly the same probability, so it would be replaced in the treemap + // (forcing the carMinutes to (int) much increases the risk that this happens!! kai, apr'26) + // (random.nextDouble() is quite large to alleviate this problem. kai, apr'26) probabilityAsKey += random.nextDouble(); } personByProbability.put(probabilityAsKey, pp); @@ -87,17 +92,18 @@ public CommuteModeChoiceMapping assignCommuteModeChoice(Location from, TravelTim int counter = (int) household.getVehicles().stream().filter(vv -> vv.getType().equals(VehicleType.CAR)).count(); + // The following goes through the hh members in decreasing proba, and assigns car with the logit proba as long as cars are available in the HH: for (Map.Entry personForProbability : personByProbability.descendingMap().entrySet()) { Person person = personForProbability.getValue(); CommuteModeChoiceMapping.CommuteMode commuteMode; if (counter == 0) { - commuteMode = new CommuteModeChoiceMapping.CommuteMode(TransportMode.pt, commuteModesByPerson.get(person.getId()).get(TransportMode.pt)); + commuteMode = new CommuteModeChoiceMapping.CommuteMode( pt, commuteModesByPerson.get(person.getId() ).get( pt )); } else { if (random.nextDouble() < personForProbability.getKey()) { - commuteMode = new CommuteModeChoiceMapping.CommuteMode(TransportMode.car, commuteModesByPerson.get(person.getId()).get(TransportMode.car)); + commuteMode = new CommuteModeChoiceMapping.CommuteMode( car, commuteModesByPerson.get(person.getId() ).get( car )); counter--; } else { - commuteMode = new CommuteModeChoiceMapping.CommuteMode(TransportMode.pt, commuteModesByPerson.get(person.getId()).get(TransportMode.pt)); + commuteMode = new CommuteModeChoiceMapping.CommuteMode( pt, commuteModesByPerson.get(person.getId() ).get( pt )); } } commuteModeChoiceMapping.assignMode(commuteMode, person); @@ -122,18 +128,18 @@ public CommuteModeChoiceMapping assignRegionalCommuteModeChoice(Region region, T Zone jobZone = geoData.getZones().get(job.getZoneId()); - int ptMinutes = (int) travelTimes.getTravelTimeFromRegion(region, jobZone, job.getStartTimeInSeconds().orElse((int) properties.transportModel.peakHour_s), TransportMode.pt); - double ptUtility = commutingTimeProbability.getCommutingTimeProbability(ptMinutes, TransportMode.pt); + int ptMinutes = (int) travelTimes.getTravelTimeFromRegion(region, jobZone, job.getStartTimeInSeconds().orElse((int) properties.transportModel.peakHour_s), pt); + double ptUtility = commutingTimeProbability.getCommutingTimeProbability(ptMinutes, pt); if (!pp.hasDriverLicense() || (int) household.getVehicles().stream().filter(vv -> vv.getType().equals(VehicleType.CAR)).count() == 0) { - CommuteModeChoiceMapping.CommuteMode ptCommuteMode = new CommuteModeChoiceMapping.CommuteMode(TransportMode.pt, ptUtility); + CommuteModeChoiceMapping.CommuteMode ptCommuteMode = new CommuteModeChoiceMapping.CommuteMode( pt, ptUtility); commuteModeChoiceMapping.assignMode(ptCommuteMode, pp); } else { - int carMinutes = (int) travelTimes.getTravelTimeFromRegion(region, jobZone, job.getStartTimeInSeconds().orElse((int) properties.transportModel.peakHour_s), TransportMode.car); - double carUtility = commutingTimeProbability.getCommutingTimeProbability(carMinutes, TransportMode.car); + int carMinutes = (int) travelTimes.getTravelTimeFromRegion(region, jobZone, job.getStartTimeInSeconds().orElse((int) properties.transportModel.peakHour_s), car); + double carUtility = commutingTimeProbability.getCommutingTimeProbability(carMinutes, car); Map utilityByMode = new LinkedHashMap<>(); - utilityByMode.put(TransportMode.car, carUtility); - utilityByMode.put(TransportMode.pt, ptUtility); + utilityByMode.put( car, carUtility ); + utilityByMode.put( pt, ptUtility ); commuteModesByPerson.put(pp.getId(), utilityByMode); double probabilityAsKey; if (carUtility == 0 && ptUtility == 0) { @@ -156,13 +162,13 @@ public CommuteModeChoiceMapping assignRegionalCommuteModeChoice(Region region, T Person person = personForProbability.getValue(); CommuteModeChoiceMapping.CommuteMode commuteMode; if (counter == 0) { - commuteMode = new CommuteModeChoiceMapping.CommuteMode(TransportMode.pt, commuteModesByPerson.get(person.getId()).get(TransportMode.pt)); + commuteMode = new CommuteModeChoiceMapping.CommuteMode( pt, commuteModesByPerson.get(person.getId() ).get( pt )); } else { if (random.nextDouble() < personForProbability.getKey()) { - commuteMode = new CommuteModeChoiceMapping.CommuteMode(TransportMode.car, commuteModesByPerson.get(person.getId()).get(TransportMode.car)); + commuteMode = new CommuteModeChoiceMapping.CommuteMode( car, commuteModesByPerson.get(person.getId() ).get( car )); counter--; } else { - commuteMode = new CommuteModeChoiceMapping.CommuteMode(TransportMode.pt, commuteModesByPerson.get(person.getId()).get(TransportMode.pt)); + commuteMode = new CommuteModeChoiceMapping.CommuteMode( pt, commuteModesByPerson.get(person.getId() ).get( pt )); } } commuteModeChoiceMapping.assignMode(commuteMode, person); diff --git a/siloCore/src/main/java/de/tum/bgu/msm/data/accessibility/CommutingTimeProbability.java b/siloCore/src/main/java/de/tum/bgu/msm/data/accessibility/CommutingTimeProbability.java index b75454c94..adfde8aae 100644 --- a/siloCore/src/main/java/de/tum/bgu/msm/data/accessibility/CommutingTimeProbability.java +++ b/siloCore/src/main/java/de/tum/bgu/msm/data/accessibility/CommutingTimeProbability.java @@ -3,5 +3,10 @@ import de.tum.bgu.msm.models.ModelUpdateListener; public interface CommutingTimeProbability extends ModelUpdateListener { + /** + * @param minutes + * @param mode + * @return Presumably, this returns a (non-normalized) weight and not a (normalized) probability. + */ float getCommutingTimeProbability(int minutes, String mode); } diff --git a/siloCore/src/main/java/de/tum/bgu/msm/models/realEstate/demolition/DemolitionModelImpl.java b/siloCore/src/main/java/de/tum/bgu/msm/models/realEstate/demolition/DemolitionModelImpl.java index 6687e62d3..b68e3f5c5 100644 --- a/siloCore/src/main/java/de/tum/bgu/msm/models/realEstate/demolition/DemolitionModelImpl.java +++ b/siloCore/src/main/java/de/tum/bgu/msm/models/realEstate/demolition/DemolitionModelImpl.java @@ -7,6 +7,7 @@ import de.tum.bgu.msm.events.impls.realEstate.DemolitionEvent; import de.tum.bgu.msm.models.AbstractModel; import de.tum.bgu.msm.models.relocation.migration.InOutMigration; +import de.tum.bgu.msm.models.relocation.moves.MovesModel; import de.tum.bgu.msm.models.relocation.moves.MovesModelImpl; import de.tum.bgu.msm.properties.Properties; import de.tum.bgu.msm.utils.SiloUtil; @@ -28,14 +29,14 @@ public class DemolitionModelImpl extends AbstractModel implements DemolitionMode private final static Logger logger = LogManager.getLogger(DemolitionModelImpl.class); - private final MovesModelImpl moves; + private final MovesModel moves; private final InOutMigration inOutMigration; private final DemolitionStrategy strategy; private int currentYear = -1; private int forcedOutmigrationByDemolition; - public DemolitionModelImpl(DataContainer dataContainer, MovesModelImpl moves, + public DemolitionModelImpl(DataContainer dataContainer, MovesModel moves, InOutMigration inOutMigration, Properties properties, DemolitionStrategy strategy, Random rnd) { super(dataContainer, properties, rnd); diff --git a/siloCore/src/main/java/de/tum/bgu/msm/models/relocation/moves/SimpleCommuteModeChoiceHousingStrategyImpl.java b/siloCore/src/main/java/de/tum/bgu/msm/models/relocation/moves/SimpleCommuteModeChoiceHousingStrategyImpl.java index 48a4b16b0..bf1ccbe54 100644 --- a/siloCore/src/main/java/de/tum/bgu/msm/models/relocation/moves/SimpleCommuteModeChoiceHousingStrategyImpl.java +++ b/siloCore/src/main/java/de/tum/bgu/msm/models/relocation/moves/SimpleCommuteModeChoiceHousingStrategyImpl.java @@ -27,7 +27,10 @@ import static de.tum.bgu.msm.data.dwelling.RealEstateUtils.RENT_CATEGORIES; -public class SimpleCommuteModeChoiceHousingStrategyImpl implements HousingStrategy { +public class SimpleCommuteModeChoiceHousingStrategyImpl implements HousingStrategy { + // this used to be without . Which, in consequence, violated the generics contract. The only place where this is + // used is isHouseholdEligibleToLiveHere(Household household, Dwelling dd) below, which means that the present implementation + // used the hardcoded "Dwelling" type. So we can as well specify it. kai, jun'26 private final static Logger logger = LogManager.getLogger(SimpleCommuteModeChoiceHousingStrategyImpl.class); diff --git a/useCases/fabiland/src/main/java/run/DataBuilderFabiland.java b/useCases/fabiland/src/main/java/run/DataBuilderFabiland.java index 8ac07a4c6..8767e815b 100644 --- a/useCases/fabiland/src/main/java/run/DataBuilderFabiland.java +++ b/useCases/fabiland/src/main/java/run/DataBuilderFabiland.java @@ -52,9 +52,11 @@ public static DataContainer buildDataContainer(Properties properties, Config con } CommutingTimeProbability commutingTimeProbability = new OnTheFlyCommutingTimeProbability(); + // (This returns Math.exp(beta * minutes)). //TODO: revise this! new JobType(properties.jobData.jobTypes); + // (this is indeed quite odd ... uses a constructor to initialize some static variables.) RealEstateDataManager realEstateManager = new RealEstateDataManagerImpl( new SandboxDwellingTypes(), diff --git a/useCases/fabiland/src/main/java/run/ModelBuilderFabiland.java b/useCases/fabiland/src/main/java/run/ModelBuilderFabiland.java index a555c8186..80e7ad1b5 100644 --- a/useCases/fabiland/src/main/java/run/ModelBuilderFabiland.java +++ b/useCases/fabiland/src/main/java/run/ModelBuilderFabiland.java @@ -8,6 +8,7 @@ import de.tum.bgu.msm.data.person.PersonFactory; import de.tum.bgu.msm.matsim.*; import de.tum.bgu.msm.models.autoOwnership.CreateCarOwnershipModel; +import de.tum.bgu.msm.models.demography.birth.BirthModel; import de.tum.bgu.msm.models.demography.birth.BirthModelImpl; import de.tum.bgu.msm.models.demography.birth.DefaultBirthStrategy; import de.tum.bgu.msm.models.demography.birthday.BirthdayModel; @@ -33,6 +34,7 @@ import de.tum.bgu.msm.models.demography.marriage.MarriageModelImpl; import de.tum.bgu.msm.models.jobmography.JobMarketUpdate; import de.tum.bgu.msm.models.jobmography.JobMarketUpdateImpl; +import de.tum.bgu.msm.models.modeChoice.CommuteModeChoice; import de.tum.bgu.msm.models.realEstate.construction.*; import de.tum.bgu.msm.models.realEstate.demolition.DefaultDemolitionStrategy; import de.tum.bgu.msm.models.realEstate.demolition.DemolitionModel; @@ -68,30 +70,84 @@ public static ModelContainer getModelContainer(DataContainer dataContainer, Prop HouseholdFactory hhFactory = dataContainer.getHouseholdDataManager().getHouseholdFactory(); DwellingFactory ddFactory = dataContainer.getRealEstateDataManager().getDwellingFactory(); - final BirthModelImpl birthModel = new BirthModelImpl(dataContainer, ppFactory, properties, new DefaultBirthStrategy(), SiloUtil.provideNewRandom()); + final BirthModel birthModel = new BirthModelImpl(dataContainer, ppFactory, properties, new DefaultBirthStrategy(), SiloUtil.provideNewRandom()); BirthdayModel birthdayModel = new BirthdayModelImpl(dataContainer, properties, SiloUtil.provideNewRandom()); DeathModel deathModel = new DeathModelImpl(dataContainer, properties, new DefaultDeathStrategy(), SiloUtil.provideNewRandom()); - MovesModelImpl movesModel = new MovesModelImpl( - dataContainer, properties, - new DefaultMovesStrategy(), - new SimpleCommuteModeChoiceHousingStrategyImpl(dataContainer, - properties, - dataContainer.getTravelTimes(), - new DwellingUtilityStrategyImpl(), - new DefaultDwellingProbabilityStrategy(), - new RegionUtilityStrategyImpl(), - new RegionProbabilityStrategyImpl() , - new SimpleMatsimCommuteModeChoice(dataContainer, properties, SiloUtil.provideNewRandom()) - ), SiloUtil.provideNewRandom()); + MovesModel movesModel; + { + + final DwellingUtilityStrategy dwellingUtilityStrategy = new DwellingUtilityStrategyImpl(); + // (This is something like + // [alpha * sizeUtility + beta * autoAccessibilityUtility + gamma * transitAccessibilityUtility + (1.0 - alpha - beta - gamma) * qualityUtility]^delta * priceUtl^eps * workDistanceUtl^{1-delta-eps} + // That is, some kind of Cobbs Douglas function with contributions + // * workDistanceUtil + // * priceUtl + // * a weighted sum of sizeUtl, autoAccUtl, transitAccUtl, qualityUtl. + // All of the params depend on income and hh size, and are given for corresponding categories. + // ) + + final DwellingProbabilityStrategy dwellingProbabilityStrategy = new DefaultDwellingProbabilityStrategy(); + // (is just exp(beta*util); should be called "weight" instead of "probability" since it is not normalized. kai, apr'26) + + final RegionUtilityStrategy regionUtilityStrategy = new RegionUtilityStrategyImpl(); + // (This is something like (1 - alpha) * price + alpha * accessibility, with alpha depending on the income category.) + + final RegionProbabilityStrategy regionProbabilityStrategy = new RegionProbabilityStrategyImpl(); + //( same as DefaultDwellingProbabilityStrategy, see above. kai, apr'26) + + final CommuteModeChoice commuteModeChoice1 = new SimpleMatsimCommuteModeChoice( dataContainer, properties, SiloUtil.provideNewRandom() ); + // (there is a comment in SimpleCommuteModeChoiceHousingStrategyImpl that the constructor should actually work w/o providing the CommuteChoiceModel. It then provides + // CommuteModeChoice internally, as SimpleCommuteModeChoice. That model looks similar; presumably some of the lookups (e.g. travel time) used to have different arguments. + // kai, apr'26) + // (I think that the existing implementations do the following: compute the logit probas for car and pt if car is an option; then go from HH member with largest car + // proba down and select car with logit proba as long as another car is available in the HH.) + // (yy this implies, as long as nothing else comes in, that moves consider new residencies under the assumption that they will not change the number of vehicles) + + final HousingStrategy housingStrategy = new SimpleCommuteModeChoiceHousingStrategyImpl( dataContainer, + properties, + dataContainer.getTravelTimes(), + dwellingUtilityStrategy, + dwellingProbabilityStrategy, + regionUtilityStrategy, + regionProbabilityStrategy, + commuteModeChoice1 + ); + /// (If I see this right, this is computing the necessary inputs to {@link DwellingUtilityStrategy} using all the other dependencies, and then computing the dwelling + /// probabilities using the {@link DwellingUtilityStrategy}. + + final MovesStrategy movesStrategy = new DefaultMovesStrategy(); + // (This says that the moving proba is 1 - 1/(1+0.03 * Math.exp(10*(householdSatisfaction - currentDwellingUtility))) + + movesModel = new MovesModelImpl( dataContainer, properties, movesStrategy, housingStrategy, SiloUtil.provideNewRandom() ); + } + // (Overall, I think that life events are not explicitly triggering a move. They will, however, shift the respective utilities, and so a move becomes more probable.) + + // (For our own issue, which (only) is to "age" the population, this seems like a lot of overhead. On the other hand, it is not immediately clear how else this should be + // resolved; location choice needs to be something like logit based on location utility. What might end up being a bit of a problem is (commute) mode choice ... we would + // need to say that maybe the commute mode choice to make a residence decision is based on what is defined above, but the final mode choice may be different once people + // optimize into their new environment. kai, apr'26) + + // (Also, the MatsimScenarioAssembler takes the commute mode from the Silo mode choice model (although I am not sure that it will give the same results are for housing + // choice, since the random numbers are different--????). Evidently, we can override this in MATSim. Clearly, this will be two models pull into different directions. + // Unfortunately, I fail to see how we calibrade mode choice on the MATSim side if we rely on upstream mode choice. Maybe possible in principle, but will not be sensitive + // to (the details of) many transport policies. kai, apr'26) + + // (As we have known for some time now, this is two competing modelling paradigms: mode (and time) choice as part of the DTA vs mode (and time?) choice as part of the + // upstream model. Rolf seems to have been a proponent of the former. However, from a MATSim side and MATSim research side, this is not something we can continue since we + // have experience with mode choice in MATSim but not in upstream models, and this is also a path that we do not want to take (would need to be done by someone else). + // We should consider to re-code the commute mode choice for our purposes, i.e. always allow for car and pt during housing search, using income-dependent utilities and + // fixed costs for cars (and pt), etc., and then sort out the actual choice later. However, this may end up not so different from the current approach, so why not leave + // the current approach in place, but change as follows: Only if a silo person has moved residency or job, then we use the mode choice from silo as an initial suggestion; + // otherwise we keep the plan (including mode) from previous iterations. -- Such an approach would make a lot of sense anyways; it was already encoded as "hot start" in + // both matsim-urbansim couplings (by KN and by TN); and it would be far enough downstream of SILO, i.e. only in the adapter class. -- A bit disappointing that 20 year + // later we are not any further here. :-( kai, apr'26) CreateCarOwnershipModel carOwnershipModel = new FabilandCarOwnership(); - DivorceModel divorceModel = new DivorceModelImpl( - dataContainer, movesModel, carOwnershipModel, hhFactory, - properties, new DefaultDivorceStrategy(), SiloUtil.provideNewRandom()); + DivorceModel divorceModel = new DivorceModelImpl( dataContainer, movesModel, carOwnershipModel, hhFactory, properties, new DefaultDivorceStrategy(), SiloUtil.provideNewRandom()); DriversLicenseModel driversLicenseModel = new DriversLicenseModelImpl(dataContainer, properties, new DefaultDriversLicenseStrategy(), SiloUtil.provideNewRandom()); @@ -137,7 +193,12 @@ public static ModelContainer getModelContainer(DataContainer dataContainer, Prop // SimpleCommuteModeChoice commuteModeChoice = new SimpleCommuteModeChoice(dataContainer, properties, SiloUtil.provideNewRandom()); SimpleMatsimCommuteModeChoice commuteModeChoice = new SimpleMatsimCommuteModeChoice(dataContainer, properties, SiloUtil.provideNewRandom()); // (yyyy is also instantiated above. why not re-use?) + // --> fails the regression test. Which is no wonder, since it changes the random number sequence. + scenarioAssembler = new SimpleCommuteModeChoiceMatsimScenarioAssembler(dataContainer, properties, commuteModeChoice, HandlingOfRandomness.localInstanceFromMatsimWithAlwaysSameSeed); + // yyyyyy the above needs to be re-coded from a MATSim perspective ... i.e. (1) select the same agents, and (2) take the mode "suggestion" from silo only if home or + // job location has changed, otherwise keep existing plan with existing mode. kai, apr'26 + transportModel = new MatsimTransportModel(dataContainer, config, properties, scenarioAssembler, matsimData); break; case NONE: diff --git a/useCases/fabiland/src/main/java/run/ModelBuilderFabilandSimplified.java b/useCases/fabiland/src/main/java/run/ModelBuilderFabilandSimplified.java new file mode 100644 index 000000000..5a29bc9d8 --- /dev/null +++ b/useCases/fabiland/src/main/java/run/ModelBuilderFabilandSimplified.java @@ -0,0 +1,193 @@ +package run; + +import de.tum.bgu.msm.container.DataContainer; +import de.tum.bgu.msm.container.ModelContainer; +import de.tum.bgu.msm.data.Region; +import de.tum.bgu.msm.data.dwelling.Dwelling; +import de.tum.bgu.msm.data.dwelling.DwellingFactory; +import de.tum.bgu.msm.data.household.Household; +import de.tum.bgu.msm.data.household.HouseholdFactory; +import de.tum.bgu.msm.data.person.PersonFactory; +import de.tum.bgu.msm.events.impls.household.MoveEvent; +import de.tum.bgu.msm.matsim.*; +import de.tum.bgu.msm.models.autoOwnership.CreateCarOwnershipModel; +import de.tum.bgu.msm.models.demography.birth.BirthModel; +import de.tum.bgu.msm.models.demography.birth.BirthModelImpl; +import de.tum.bgu.msm.models.demography.birth.DefaultBirthStrategy; +import de.tum.bgu.msm.models.demography.birthday.BirthdayModel; +import de.tum.bgu.msm.models.demography.birthday.BirthdayModelImpl; +import de.tum.bgu.msm.models.demography.death.DeathModel; +import de.tum.bgu.msm.models.demography.death.DeathModelImpl; +import de.tum.bgu.msm.models.demography.death.DefaultDeathStrategy; +import de.tum.bgu.msm.models.demography.divorce.DefaultDivorceStrategy; +import de.tum.bgu.msm.models.demography.divorce.DivorceModel; +import de.tum.bgu.msm.models.demography.divorce.DivorceModelImpl; +import de.tum.bgu.msm.models.demography.driversLicense.DefaultDriversLicenseStrategy; +import de.tum.bgu.msm.models.demography.driversLicense.DriversLicenseModel; +import de.tum.bgu.msm.models.demography.driversLicense.DriversLicenseModelImpl; +import de.tum.bgu.msm.models.demography.education.EducationModel; +import de.tum.bgu.msm.models.demography.education.EducationModelImpl; +import de.tum.bgu.msm.models.demography.employment.EmploymentModel; +import de.tum.bgu.msm.models.demography.employment.EmploymentModelImpl; +import de.tum.bgu.msm.models.demography.leaveParentalHousehold.DefaultLeaveParentalHouseholdStrategy; +import de.tum.bgu.msm.models.demography.leaveParentalHousehold.LeaveParentHhModel; +import de.tum.bgu.msm.models.demography.leaveParentalHousehold.LeaveParentHhModelImpl; +import de.tum.bgu.msm.models.demography.marriage.DefaultMarriageStrategy; +import de.tum.bgu.msm.models.demography.marriage.MarriageModel; +import de.tum.bgu.msm.models.demography.marriage.MarriageModelImpl; +import de.tum.bgu.msm.models.jobmography.JobMarketUpdate; +import de.tum.bgu.msm.models.jobmography.JobMarketUpdateImpl; +import de.tum.bgu.msm.models.realEstate.construction.*; +import de.tum.bgu.msm.models.realEstate.demolition.DefaultDemolitionStrategy; +import de.tum.bgu.msm.models.realEstate.demolition.DemolitionModel; +import de.tum.bgu.msm.models.realEstate.demolition.DemolitionModelImpl; +import de.tum.bgu.msm.models.realEstate.pricing.DefaultPricingStrategy; +import de.tum.bgu.msm.models.realEstate.pricing.PricingModel; +import de.tum.bgu.msm.models.realEstate.pricing.PricingModelImpl; +import de.tum.bgu.msm.models.realEstate.renovation.DefaultRenovationStrategy; +import de.tum.bgu.msm.models.realEstate.renovation.RenovationModel; +import de.tum.bgu.msm.models.realEstate.renovation.RenovationModelImpl; +import de.tum.bgu.msm.models.relocation.migration.InOutMigration; +import de.tum.bgu.msm.models.relocation.migration.InOutMigrationImpl; +import de.tum.bgu.msm.models.relocation.moves.*; +import de.tum.bgu.msm.models.transportModel.TransportModel; +import de.tum.bgu.msm.properties.Properties; +import de.tum.bgu.msm.utils.SiloUtil; +import models.FabilandConstructionLocationStrategy; +import org.matsim.api.core.v01.Scenario; +import org.matsim.core.config.Config; +import org.matsim.core.scenario.ScenarioUtils; + +import java.util.Collection; +import java.util.Collections; +import java.util.Random; + +import static de.tum.bgu.msm.matsim.SimpleCommuteModeChoiceMatsimScenarioAssembler.HandlingOfRandomness; +import static de.tum.bgu.msm.matsim.ZoneConnectorManagerImpl.*; + +public class ModelBuilderFabilandSimplified{ + + public static ModelContainer getModelContainer(DataContainer dataContainer, Properties properties, Config config) { + + final PersonFactory ppFactory = dataContainer.getHouseholdDataManager().getPersonFactory(); + final HouseholdFactory hhFactory = dataContainer.getHouseholdDataManager().getHouseholdFactory(); + final DwellingFactory ddFactory = dataContainer.getRealEstateDataManager().getDwellingFactory(); + + final BirthModel birthModel = new BirthModelImpl(dataContainer, ppFactory, properties, new DefaultBirthStrategy(), SiloUtil.provideNewRandom()); + + final BirthdayModel birthdayModel = new BirthdayModelImpl(dataContainer, properties, SiloUtil.provideNewRandom()); + + final DeathModel deathModel = new DeathModelImpl(dataContainer, properties, new DefaultDeathStrategy(), SiloUtil.provideNewRandom()); + + final MovesModel movesModel = new MovesModel(){ + @Override public int searchForNewDwelling( Household household ){ + return -1; // means no dwelling was found + } + @Override public void moveHousehold( Household hh, int idOldDD, int idNewDD ){ + // do nothing + } + @Override public Collection getEventsForCurrentYear( int year ){ + return Collections.emptyList(); + } + @Override public boolean handleEvent( MoveEvent event ){ + // this should not happen. Maybe test? + // If this is needed, one cold use MovesModelImpl as a delegate and then go from there. + return false; + } + @Override public void setup(){ + // do nothing + } + @Override public void prepareYear( int year ){ + // do nothing + } + @Override public void endYear( int year ){ + // do nothing + } + @Override public void endSimulation(){ + // do nothing + } + }; + + final CreateCarOwnershipModel carOwnershipModel = new FabilandCarOwnership(); + // yy (for VSP purposes, car ownership could also be done by matsim) + + final DivorceModel divorceModel = new DivorceModelImpl( + dataContainer, movesModel, carOwnershipModel, hhFactory, + properties, new DefaultDivorceStrategy(), SiloUtil.provideNewRandom()); + + final DriversLicenseModel driversLicenseModel = new DriversLicenseModelImpl(dataContainer, properties, new DefaultDriversLicenseStrategy(), SiloUtil.provideNewRandom()); + // yy for VSP purposes, this might not be needed + + final EducationModel educationModel = new EducationModelImpl(dataContainer, properties, SiloUtil.provideNewRandom()); + + final EmploymentModel employmentModel = new EmploymentModelImpl(dataContainer, properties, SiloUtil.provideNewRandom()); + + final LeaveParentHhModel leaveParentsModel = new LeaveParentHhModelImpl(dataContainer, movesModel, + carOwnershipModel, hhFactory, properties, new DefaultLeaveParentalHouseholdStrategy(), SiloUtil.provideNewRandom()); + + final JobMarketUpdate jobMarketUpdateModel = new JobMarketUpdateImpl(dataContainer, properties, SiloUtil.provideNewRandom()); + + final PricingModel pricing = new PricingModelImpl(dataContainer, properties, new DefaultPricingStrategy(), SiloUtil.provideNewRandom()); + + final ConstructionOverwrite constructionOverwrite = new ConstructionOverwriteImpl(dataContainer, ddFactory, properties, SiloUtil.provideNewRandom()); + + final InOutMigration inOutMigration = new InOutMigrationImpl(dataContainer, employmentModel, movesModel, + carOwnershipModel, driversLicenseModel, properties, SiloUtil.provideNewRandom()); + + final MarriageModel marriageModel = new MarriageModelImpl(dataContainer, movesModel, inOutMigration, + carOwnershipModel, hhFactory, properties, new DefaultMarriageStrategy(), SiloUtil.provideNewRandom()); + + TransportModel transportModel; + MatsimScenarioAssembler scenarioAssembler; + + MatsimData matsimData = null; + if (config != null) { + final Scenario scenario = ScenarioUtils.loadScenario(config); + matsimData = new MatsimData(config, properties, ZoneConnectorMethod.WEIGHTED_BY_POPULATION, dataContainer, scenario.getNetwork(), scenario.getTransitSchedule()); + // (only the constructor is deprecated) + } + switch (properties.transportModel.transportModelIdentifier) { + case MATSIM: +// SimpleCommuteModeChoice commuteModeChoice = new SimpleCommuteModeChoice(dataContainer, properties, SiloUtil.provideNewRandom()); + SimpleMatsimCommuteModeChoice commuteModeChoice = new SimpleMatsimCommuteModeChoice(dataContainer, properties, SiloUtil.provideNewRandom()); + // (for VSP purposes, this might not be needed) + + scenarioAssembler = new SimpleCommuteModeChoiceMatsimScenarioAssembler(dataContainer, properties, commuteModeChoice, HandlingOfRandomness.localInstanceFromMatsimWithAlwaysSameSeed); + transportModel = new MatsimTransportModel(dataContainer, config, properties, scenarioAssembler, matsimData); + break; + case NONE: + default: + transportModel = null; + } + + final ModelContainer modelContainer = new ModelContainer( + birthModel, birthdayModel, + deathModel, marriageModel, + divorceModel, driversLicenseModel, + educationModel, employmentModel, + leaveParentsModel, jobMarketUpdateModel, + null, null, pricing, null, + constructionOverwrite, inOutMigration, movesModel, transportModel); + + return modelContainer; + } + + private static class FabilandCarOwnership implements CreateCarOwnershipModel { + + private final Random random; + + FabilandCarOwnership() { + this.random = SiloUtil.provideNewRandom(); + } + + @Override + public void run() { + + } + + @Override + public void simulateCarOwnership(Household hh) { + hh.setAutos(random.nextInt(3)+1); + } + } +} diff --git a/useCases/fabiland/src/main/java/run/RunFabiland.java b/useCases/fabiland/src/main/java/run/RunFabiland.java index 1fd3c331a..ebe039970 100644 --- a/useCases/fabiland/src/main/java/run/RunFabiland.java +++ b/useCases/fabiland/src/main/java/run/RunFabiland.java @@ -23,8 +23,7 @@ public class RunFabiland { private final static Logger logger = LogManager.getLogger(RunFabiland.class); public static void main(String[] args) { - // yyyy This does not run out of the box. Presumably, it needs an argument. Could you please add a comment that explains to make this here run? Thanks ... kai, jun'23 - // yyyyyy Also, there should be a regression test running this method. kai, jun'23 + // see regression test Properties properties = SiloUtil.siloInitialization(args[0]);