Commit 945fed90 authored by Sebastian Hörl's avatar Sebastian Hörl
Browse files

Make av+parameters configurable

parent fdabf4c6
import pandas as pd
import geopandas as gpd
df = gpd.read_file("scenarios/Gemeinden_fuer_Raumtypen.shp")
df.crs = {"init": "EPSG:2056"}
df = df[["geometry", "Gebietstyp"]]
scenarios = {
"scenario_sa": ("S", "A"),
"scenario_lu": ("LU",),
"scenario_lg": ("LG",)
}
for scenario, types in scenarios.items():
df.loc[df["Gebietstyp"].isin(types), "scenario"] = scenario
df = df.dissolve(by = "scenario").reset_index()[["scenario", "geometry"]]
for scenario in scenarios.keys():
shape = df[df["scenario"] == scenario].to_file("scenarios/%s.shp" % scenario)
......@@ -5,6 +5,7 @@ import org.matsim.core.config.ReflectiveConfigGroup;
public class ASTRAConfigGroup extends ReflectiveConfigGroup {
public final static String GROUP_NAME = "astra";
private final static String ENABLE_AVS = "enableAvs";
private final static String TAXI_FLEET_SIZE = "taxiFleetSize";
private final static String POOLED_FLEET_SIZE = "pooledFleetSize";
private final static String SERVICE_AREA_ATTRIBUTE = "serviceAreaAttribute";
......@@ -13,6 +14,8 @@ public class ASTRAConfigGroup extends ReflectiveConfigGroup {
private final static String WAITING_TIME_ZONE_SHAPEFILE = "waitingTimeZoneShapefile";
private final static String WAITING_TIME_ZONE_IDENTIFIER_ATTRIBUTE = "waitingTimeZoneIdentifierAttribute";
private boolean enableAVs = false;
private int taxiFleetSize = 100;
private int pooledFleetSize = 0;
......@@ -27,6 +30,16 @@ public class ASTRAConfigGroup extends ReflectiveConfigGroup {
super(GROUP_NAME);
}
@StringGetter(ENABLE_AVS)
public boolean getEnableAVs() {
return enableAVs;
}
@StringSetter(ENABLE_AVS)
public void setEnableAVs(boolean enableAVs) {
this.enableAVs = enableAVs;
}
@StringGetter(TAXI_FLEET_SIZE)
public int getTaxiFleetSize() {
return taxiFleetSize;
......
package ch.ethz.matsim.projects.astra_2018_002;
import org.matsim.api.core.v01.Scenario;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.contrib.dvrp.trafficmonitoring.DvrpTravelTimeModule;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.controler.Controler;
import org.matsim.core.scenario.ScenarioUtils;
import ch.ethz.matsim.av.framework.AVConfigGroup;
import ch.ethz.matsim.av.framework.AVModule;
import ch.ethz.matsim.baseline_scenario.config.CommandLine;
import ch.ethz.matsim.baseline_scenario.config.CommandLine.ConfigurationException;
import ch.ethz.matsim.baseline_scenario.transit.BaselineTransitModule;
import ch.ethz.matsim.baseline_scenario.transit.routing.DefaultEnrichedTransitRoute;
import ch.ethz.matsim.baseline_scenario.transit.routing.DefaultEnrichedTransitRouteFactory;
import ch.ethz.matsim.projects.astra_2018_002.av.ASTRAAVModule;
import ch.ethz.matsim.projects.astra_2018_002.av.AVConfigurator;
import ch.ethz.matsim.projects.astra_2018_002.flow_efficiency.FlowEfficiencyConfigurator;
import ch.ethz.matsim.projects.astra_2018_002.mode_choice.SwissDiscreteModeChoiceModule;
......@@ -28,20 +23,20 @@ public class RunASTRA2018002 {
CommandLine cmd = new CommandLine.Builder(args) //
.requireOptions("config-path", "model") //
.allowOptions("use-route-choice", "use-only-significant") //
.allowPrefixes(SwissDiscreteModeChoiceModule.COMMAND_LINE_PREFIX) //
.build();
ASTRAConfigGroup astraConfig = new ASTRAConfigGroup();
astraConfig.setActiveServiceArea("zurich");
astraConfig.setPooledFleetSize(0);
astraConfig.setTaxiFleetSize(100);
astraConfig.setServiceAreaShapefile("gis/operating_areas.shp");
astraConfig.setServiceAreaAttribute("OAREA");
astraConfig.setWaitingTimeZoneShapefile("gis/waiting_time_areas.shp");
astraConfig.setWaitingTimeZoneIdentifierAttribute("WZONE");
// ASTRAConfigGroup astraConfig = new ASTRAConfigGroup();
// astraConfig.setActiveServiceArea("zurich");
// astraConfig.setPooledFleetSize(0);
// astraConfig.setTaxiFleetSize(100);
// astraConfig.setServiceAreaShapefile("gis/operating_areas.shp");
// astraConfig.setServiceAreaAttribute("OAREA");
// astraConfig.setWaitingTimeZoneShapefile("gis/waiting_time_areas.shp");
// astraConfig.setWaitingTimeZoneIdentifierAttribute("WZONE");
// Load config
Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path"), new DvrpConfigGroup(),
new AVConfigGroup(), astraConfig);
Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path"));
// Adjust config
SwissModeChoiceConfigurator.configure(config);
......@@ -61,21 +56,18 @@ public class RunASTRA2018002 {
FlowEfficiencyConfigurator.defineVehicleTypes(scenario);
// Set up controller
Controler controler = new Controler(scenario);
controler.addOverridingModule(new SwissRailRaptorModule());
controler.addOverridingModule(new DvrpTravelTimeModule());
controler.addOverridingModule(new AVModule());
controler.addOverridingModule(new ASTRAAVModule());
controler.addOverridingModule(new BaselineTransitModule());
controler.addOverridingModule(new ASTRAQSimModule());
Controler controller = new Controler(scenario);
controller.addOverridingModule(new SwissRailRaptorModule());
controller.addOverridingModule(new BaselineTransitModule());
AVConfigurator.configureController(controller);
UtilitySet utilitySet = Enum.valueOf(UtilitySet.class, cmd.getOptionStrict("model"));
boolean useRouteChoice = cmd.getOption("use-route-choice").map(Boolean::parseBoolean).orElse(true);
boolean useOnlySignificant = cmd.getOption("use-only-significant").map(Boolean::parseBoolean).orElse(false);
controler
.addOverridingModule(new SwissDiscreteModeChoiceModule(utilitySet, useRouteChoice, useOnlySignificant));
controller.addOverridingModule(
new SwissDiscreteModeChoiceModule(utilitySet, useRouteChoice, useOnlySignificant, cmd));
// Run
controler.run();
controller.run();
}
}
......@@ -4,15 +4,35 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.contrib.dvrp.trafficmonitoring.DvrpTravelTimeModule;
import org.matsim.core.config.Config;
import org.matsim.core.config.groups.PlanCalcScoreConfigGroup.ModeParams;
import org.matsim.core.controler.Controler;
import ch.ethz.matsim.av.framework.AVConfigGroup;
import ch.ethz.matsim.av.framework.AVModule;
import ch.ethz.matsim.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup;
import ch.ethz.matsim.projects.astra_2018_002.ASTRAConfigGroup;
import ch.ethz.matsim.projects.astra_2018_002.ASTRAQSimModule;
public class AVConfigurator {
static public void configure(Config config) {
DvrpConfigGroup dvrpConfig = (DvrpConfigGroup) config.getModules().get(DvrpConfigGroup.GROUP_NAME);
if (dvrpConfig == null) {
dvrpConfig = new DvrpConfigGroup();
config.addModule(dvrpConfig);
}
AVConfigGroup avConfig = (AVConfigGroup) config.getModules().get("av");
if (avConfig == null) {
avConfig = new AVConfigGroup();
config.addModule(avConfig);
avConfig.setParallelRouters(config.global().getNumberOfThreads());
}
ASTRAConfigGroup astraConfig = (ASTRAConfigGroup) config.getModules().get(ASTRAConfigGroup.GROUP_NAME);
if (astraConfig == null) {
......@@ -20,32 +40,46 @@ public class AVConfigurator {
config.addModule(astraConfig);
}
ModeParams avParams = new ModeParams(AVModule.AV_MODE);
config.planCalcScore().addModeParams(avParams);
if (astraConfig.getEnableAVs()) {
ModeParams avParams = new ModeParams(AVModule.AV_MODE);
config.planCalcScore().addModeParams(avParams);
ModeParams poolParams = new ModeParams(ASTRAAVModule.AV_POOL);
config.planCalcScore().addModeParams(poolParams);
ModeParams poolParams = new ModeParams(ASTRAAVModule.AV_POOL);
config.planCalcScore().addModeParams(poolParams);
ModeParams taxiParams = new ModeParams(ASTRAAVModule.AV_TAXI);
config.planCalcScore().addModeParams(taxiParams);
ModeParams taxiParams = new ModeParams(ASTRAAVModule.AV_TAXI);
config.planCalcScore().addModeParams(taxiParams);
DiscreteModeChoiceConfigGroup dmcConfig = (DiscreteModeChoiceConfigGroup) config.getModules()
.get(DiscreteModeChoiceConfigGroup.GROUP_NAME);
DiscreteModeChoiceConfigGroup dmcConfig = (DiscreteModeChoiceConfigGroup) config.getModules()
.get(DiscreteModeChoiceConfigGroup.GROUP_NAME);
Set<String> availableModes = new HashSet<>(dmcConfig.getCarModeAvailabilityConfig().getAvailableModes());
Set<String> availableModes = new HashSet<>(dmcConfig.getCarModeAvailabilityConfig().getAvailableModes());
if (astraConfig.getTaxiFleetSize() > 0) {
availableModes.add(ASTRAAVModule.AV_TAXI);
}
if (astraConfig.getTaxiFleetSize() > 0) {
availableModes.add(ASTRAAVModule.AV_TAXI);
}
if (astraConfig.getPooledFleetSize() > 0) {
availableModes.add(ASTRAAVModule.AV_POOL);
}
Collection<String> tripConstraints = new HashSet<>(dmcConfig.getTripConstraints());
tripConstraints.add(ASTRAAVModule.CONSTRAINT_NAME);
dmcConfig.setTripConstraints(tripConstraints);
if (astraConfig.getPooledFleetSize() > 0) {
availableModes.add(ASTRAAVModule.AV_POOL);
dmcConfig.getCarModeAvailabilityConfig().setAvailableModes(availableModes);
}
}
Collection<String> tripConstraints = new HashSet<>(dmcConfig.getTripConstraints());
tripConstraints.add(ASTRAAVModule.CONSTRAINT_NAME);
dmcConfig.setTripConstraints(tripConstraints);
static public void configureController(Controler controller) {
ASTRAConfigGroup astraConfig = (ASTRAConfigGroup) controller.getConfig().getModules()
.get(ASTRAConfigGroup.GROUP_NAME);
dmcConfig.getCarModeAvailabilityConfig().setAvailableModes(availableModes);
if (astraConfig.getEnableAVs()) {
controller.addOverridingModule(new DvrpTravelTimeModule());
controller.addOverridingModule(new AVModule());
controller.addOverridingModule(new ASTRAAVModule());
controller.addOverridingModule(new ASTRAQSimModule());
}
}
}
......@@ -8,6 +8,7 @@ import org.matsim.pt.transitSchedule.api.TransitSchedule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import ch.ethz.matsim.baseline_scenario.config.CommandLine;
import ch.ethz.matsim.discrete_mode_choice.modules.AbstractDiscreteModeChoiceExtension;
import ch.ethz.matsim.discrete_mode_choice.modules.DiscreteModeChoiceModule;
import ch.ethz.matsim.projects.astra_2018_002.mode_choice.SwissUtilityParameters.UtilitySet;
......@@ -15,16 +16,21 @@ import ch.ethz.matsim.projects.astra_2018_002.mode_choice.cost.CostModel;
import ch.ethz.matsim.projects.astra_2018_002.mode_choice.cost.CostParameters;
public class SwissDiscreteModeChoiceModule extends AbstractDiscreteModeChoiceExtension {
public final static String COMMAND_LINE_PREFIX = "utility";
public static final String SWISS_ESTIMATOR_NAME = "Swiss";
private final UtilitySet utilitySet;
private final boolean useRouteChoice;
private final boolean onlySignificant;
public SwissDiscreteModeChoiceModule(UtilitySet utilitySet, boolean useRouteChoice, boolean onlySignificant) {
private final CommandLine cmd;
public SwissDiscreteModeChoiceModule(UtilitySet utilitySet, boolean useRouteChoice, boolean onlySignificant,
CommandLine cmd) {
this.utilitySet = utilitySet;
this.useRouteChoice = useRouteChoice;
this.onlySignificant = onlySignificant;
this.cmd = cmd;
}
@Override
......@@ -34,7 +40,7 @@ public class SwissDiscreteModeChoiceModule extends AbstractDiscreteModeChoiceExt
}
@Provides
public SwissUtilityEstimator provideLinearWithoutSociodemographicsEstimator(TripRouter tripRouter, Network network,
public SwissUtilityEstimator provideSwissUtilityEstimator(TripRouter tripRouter, Network network,
ActivityFacilities facilities, CostModel costModel, TransitSchedule transitSchedule,
SwissUtilityParameters parameters) {
return new SwissUtilityEstimator(tripRouter, network, facilities, costModel, transitSchedule, parameters);
......@@ -43,11 +49,9 @@ public class SwissDiscreteModeChoiceModule extends AbstractDiscreteModeChoiceExt
@Provides
@Singleton
public SwissUtilityParameters provideSwissUtilityParameters() {
/*
* TODO: We can make this configurable in a better way.
*/
return SwissUtilityParameters.build(utilitySet, useRouteChoice, onlySignificant);
SwissUtilityParameters parameters = SwissUtilityParameters.build(utilitySet, useRouteChoice, onlySignificant);
SwissUtilityParameters.adaptFromCommandLine(parameters, cmd);
return parameters;
}
@Provides
......
package ch.ethz.matsim.projects.astra_2018_002.mode_choice;
import java.lang.reflect.Field;
import org.apache.log4j.Logger;
import ch.ethz.matsim.baseline_scenario.config.CommandLine;
import ch.ethz.matsim.baseline_scenario.config.CommandLine.ConfigurationException;
/**
* Gives utility parameters based on
*
......@@ -15,6 +22,8 @@ package ch.ethz.matsim.projects.astra_2018_002.mode_choice;
* </ul>
*/
public class SwissUtilityParameters {
private final static Logger logger = Logger.getLogger(SwissUtilityParameters.class);
private SwissUtilityParameters() {
}
......@@ -527,6 +536,8 @@ public class SwissUtilityParameters {
}
static public SwissUtilityParameters build(UtilitySet set, boolean useRouteChoice, boolean onlySignificant) {
logger.info("Preparing utility parameters: " + set.toString());
switch (set) {
case CHAPTER_3_2_1:
return buildLinearWithoutSociodemographics(useRouteChoice, onlySignificant);
......@@ -540,4 +551,36 @@ public class SwissUtilityParameters {
throw new IllegalStateException();
}
}
static public void adaptFromCommandLine(SwissUtilityParameters parameters, CommandLine cmd) {
for (String option : cmd.getAvailableOptions()) {
try {
if (option.startsWith(SwissDiscreteModeChoiceModule.COMMAND_LINE_PREFIX + ":")) {
String accessor = option.split(":")[1];
String[] parts = accessor.split("\\.");
Object activeObject = parameters;
for (int i = 0; i < parts.length - 1; i++) {
Field field = activeObject.getClass().getField(parts[i]);
activeObject = field.get(activeObject);
}
Field field = activeObject.getClass().getField(parts[parts.length - 1]);
if (field.getType().equals(double.class)) {
double value = Double.parseDouble(cmd.getOptionStrict(option));
logger.info(String.format("Set %s = %f", accessor, value));
field.set(activeObject, value);
} else {
throw new IllegalStateException(
String.format("Option %s does not refer to a double field", option));
}
}
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException
| ConfigurationException e) {
throw new IllegalStateException("Error while processing option " + option);
}
}
}
}
......@@ -21,7 +21,7 @@ public class TestUtility {
CostParameters costParameters = new CostParameters();
CostModel costModel = new CostModel(costParameters);
SwissUtilityParameters parameters = SwissUtilityParameters.build(UtilitySet.CHAPTER_3_2_3, true, true);
SwissUtilityParameters parameters = SwissUtilityParameters.build(UtilitySet.CHAPTER_3_2_3, true, false);
SwissUtilityEstimator estimator = new SwissUtilityEstimator(null, null, null, costModel, null, parameters);
......
package ch.ethz.matsim.projects.astra_2018_002.scenarios.long_distance;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import org.apache.log4j.Logger;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Person;
import org.matsim.api.core.v01.population.Population;
import org.matsim.api.core.v01.population.PopulationFactory;
import org.matsim.core.router.StageActivityTypes;
import org.matsim.core.router.TripStructureUtils;
import org.matsim.core.router.costcalculators.OnlyTimeDependentTravelDisutility;
import org.matsim.core.router.util.LeastCostPathCalculator;
import org.matsim.core.router.util.LeastCostPathCalculator.Path;
import org.matsim.core.router.util.LeastCostPathCalculatorFactory;
import org.matsim.core.router.util.TravelDisutility;
import org.matsim.core.router.util.TravelTime;
import org.matsim.core.trafficmonitoring.FreeSpeedTravelTime;
public class LinkInteractionFinder {
private final Logger logger = Logger.getLogger(LinkInteractionFinder.class);
private StageActivityTypes stageActivityTypes;
private LeastCostPathCalculatorFactory routerFactory;
private int numberOfThreads;
private int batchSize = 100;
public LinkInteractionFinder(int numberOfThreads, int batchSize, StageActivityTypes stageActivityTypes,
PopulationFactory populationFactory, LeastCostPathCalculatorFactory routerFactory) {
this.numberOfThreads = numberOfThreads;
this.batchSize = batchSize;
this.stageActivityTypes = stageActivityTypes;
this.routerFactory = routerFactory;
}
public Collection<Id<Person>> findInteractingPersons(Population population, Network network,
Function<Link, Boolean> filter) throws InterruptedException {
Collection<Id<Person>> interactionIds = new ArrayList<>(population.getPersons().size());
Iterator<? extends Person> personIterator = population.getPersons().values().iterator();
TravelTime travelTime = new FreeSpeedTravelTime();
TravelDisutility travelDisutility = new OnlyTimeDependentTravelDisutility(travelTime);
List<Thread> threads = new ArrayList<>(numberOfThreads);
long totalNumberOfPersons = population.getPersons().size();
AtomicLong processedNumberOfPersons = new AtomicLong(0);
for (int index = 0; index < numberOfThreads; index++) {
Thread thread = new Thread(() -> {
Collection<Id<Person>> batchInteractionIds = new ArrayList<>(batchSize);
Collection<Person> batch = new ArrayList<>(batchSize);
LeastCostPathCalculator router = routerFactory.createPathCalculator(network, travelDisutility,
travelTime);
do {
batch.clear();
batchInteractionIds.clear();
synchronized (personIterator) {
while (personIterator.hasNext() && batch.size() < batchSize) {
batch.add(personIterator.next());
}
}
for (Person person : batch) {
boolean hasInteraction = false;
for (TripStructureUtils.Trip trip : TripStructureUtils.getTrips(person.getSelectedPlan(),
stageActivityTypes)) {
Link originLink = network.getLinks().get(trip.getOriginActivity().getLinkId());
Link destinationLink = network.getLinks().get(trip.getDestinationActivity().getLinkId());
Path path = router.calcLeastCostPath(originLink.getToNode(), destinationLink.getFromNode(),
0.0, null, null);
for (Link link : path.links) {
if (filter.apply(link)) {
hasInteraction = true;
break;
}
}
}
if (hasInteraction) {
batchInteractionIds.add(person.getId());
}
}
processedNumberOfPersons.addAndGet(batch.size());
synchronized (interactionIds) {
interactionIds.addAll(batchInteractionIds);
}
} while (batch.size() > 0);
});
threads.add(thread);
thread.start();
}
Thread progressThread = new Thread(() -> {
try {
long previousNumberOfPersons = 0;
do {
long currentNumberOfPersons = processedNumberOfPersons.get();
if (currentNumberOfPersons > previousNumberOfPersons) {
logger.info(String.format("Finding link interactions... %d/%d (%.2f%%)", currentNumberOfPersons,
totalNumberOfPersons, 100.0 * currentNumberOfPersons / totalNumberOfPersons));
}
previousNumberOfPersons = currentNumberOfPersons;
Thread.sleep(100);
} while (previousNumberOfPersons < totalNumberOfPersons);
} catch (InterruptedException e) {
}
});
progressThread.start();
for (Thread thread : threads) {
thread.join();
}
progressThread.join();
return interactionIds;
}
}
package ch.ethz.matsim.projects.astra_2018_002.scenarios.run;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
import org.apache.log4j.Logger;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Person;
import org.matsim.api.core.v01.population.PopulationFactory;
import org.matsim.api.core.v01.population.PopulationWriter;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.network.NetworkUtils;
import org.matsim.core.network.algorithms.TransportModeNetworkFilter;
import org.matsim.core.network.io.MatsimNetworkReader;
import org.matsim.core.population.io.PopulationReader;
import org.matsim.core.router.DijkstraFactory;
import org.matsim.core.router.StageActivityTypes;
import org.matsim.core.router.StageActivityTypesImpl;
import org.matsim.core.router.util.LeastCostPathCalculatorFactory;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.pt.PtConstants;
import ch.ethz.matsim.baseline_scenario.config.CommandLine;
import ch.ethz.matsim.baseline_scenario.config.CommandLine.ConfigurationException;
import ch.ethz.matsim.projects.astra_2018_002.scenarios.long_distance.LinkInteractionFinder;
public class MakeLongDistanceScenario {
private final static Logger logger = Logger.getLogger(MakeLongDistanceScenario.class);
static public void main(String[] args) throws ConfigurationException, InterruptedException {
CommandLine cmd = new CommandLine.Builder(args) //
.requireOptions("network-path", "population-path", "output-path") //
.allowOptions("threads", "batch-size") //
.build();
Config config = ConfigUtils.createConfig();
Scenario scenario = ScenarioUtils.createScenario(config);
new MatsimNetworkReader(scenario.getNetwork()).readFile(cmd.getOptionStrict("network-path"));
new PopulationReader(scenario).readFile(cmd.getOptionStrict("population-path"));
for (Link link : scenario.getNetwork().getLinks().values()) {
link.setLength(Math.max(1.0, link.getLength()));
}
Network roadNetwork = NetworkUtils.createNetwork();
new TransportModeNetworkFilter(scenario.getNetwork()).filter(roadNetwork,