Skip to content

Commit

Permalink
Merge branch 'develop' into feat/car-departure-access
Browse files Browse the repository at this point in the history
  • Loading branch information
sebhoerl authored Dec 5, 2023
2 parents 8363c31 + 71b8e47 commit 2c9839f
Show file tree
Hide file tree
Showing 17 changed files with 310 additions and 44 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ This change log is written in descending order. Changes that happen after versio
included in the (note yet determined) next version number.

**Development version**


- Updated to MATSim 14
- Isolated the mode choice model in a standalone runnable script
- Fixed LegIndex count between iterations in legs analysis
- Improved batch routing tools
- Allow boolean values in parameter definition
- Added stop area to transit leg analysis output
- Improve functionality of routing tools to set utilities in detail
- Fix bug in EqasimTransitQSimModule: first check if EqasimConfigGroup has TransitEngineModule before removing it
- Updated config option from `eqasim.tripAnalysisInterval` to `eqasim.analysisInterval`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public void reset(int iteration) {
ongoing.clear();
passengers.clear();
tripIndex.clear();
legIndex.clear();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.List;

import org.matsim.facilities.Facility;
import org.matsim.utils.objectattributes.attributable.Attributes;

import ch.sbb.matsim.routing.pt.raptor.RaptorRoute;
import ch.sbb.matsim.routing.pt.raptor.RaptorRoute.RoutePart;
Expand All @@ -25,7 +26,7 @@ public double calculateHeadway_min(Facility originFacility, Facility destination
double latestDepartureTime = departureTime + afterDepartureOffset;

List<RaptorRoute> routes = raptor.calcRoutes(originFacility, destinationFacilty, earliestDepartureTime,
departureTime, latestDepartureTime, null);
departureTime, latestDepartureTime, null, new Attributes());

int numberOfPtRoutes = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.core.utils.timing.TimeInterpretationModule;

import com.google.inject.Injector;

Expand Down Expand Up @@ -100,6 +101,7 @@ static public void main(String[] args)
.addOverridingModule(
new PopulationCutterModule(extent, numberOfThreads, 40, cmd.getOption("events-path"))) //
.addOverridingModule(new CutterTravelTimeModule(travelTime)) //
.addOverridingModule(new TimeInterpretationModule()) //
.build();

PopulationCutter populationCutter = populationCutterInjector.getInstance(PopulationCutter.class);
Expand Down Expand Up @@ -151,6 +153,7 @@ static public void main(String[] args)
.addOverridingModules(configurator.getModules()) //
.addOverridingModule(new PopulationRouterModule(numberOfThreads, 100, false)) //
.addOverridingModule(new CutterTravelTimeModule(travelTime)) //
.addOverridingModule(new TimeInterpretationModule()) //
.build();

PopulationRouter router = routingInjector.getInstance(PopulationRouter.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void run(Plan plan, boolean replaceExistingRoutes, Set<String> modes) {
Facility toFacility = FacilitiesUtils.toFacility(trip.getDestinationActivity(), facilities);

List<? extends PlanElement> newElements = tripRouter.calcRoute(mainMode, fromFacility, toFacility,
departureTime.seconds(), plan.getPerson());
departureTime.seconds(), plan.getPerson(), trip.getTripAttributes());

TripRouter.insertTrip(plan, trip.getOriginActivity(), newElements, trip.getDestinationActivity());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.population.io.PopulationWriter;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.core.utils.timing.TimeInterpretationModule;
import org.matsim.facilities.ActivityFacility;

import com.google.inject.Injector;
Expand Down Expand Up @@ -53,6 +54,7 @@ static public void main(String[] args) throws ConfigurationException, Interrupte
Injector injector = new InjectorBuilder(scenario) //
.addOverridingModules(configurator.getModules()) //
.addOverridingModule(new PopulationRouterModule(numberOfThreads, batchSize, true, modes)) //
.addOverridingModule(new TimeInterpretationModule())
.build();

PopulationRouter populationRouter = injector.getInstance(PopulationRouter.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
import org.matsim.contribs.discrete_mode_choice.components.utils.home_finder.HomeFinder;
import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup;
import org.matsim.contribs.discrete_mode_choice.modules.config.VehicleTourConstraintConfigGroup;
import org.matsim.contribs.discrete_mode_choice.replanning.time_interpreter.TimeInterpreter;
import org.matsim.core.router.TripRouter;
import org.matsim.core.utils.timing.TimeInterpretation;
import org.matsim.facilities.ActivityFacilities;

import com.google.inject.Provider;
Expand Down Expand Up @@ -87,7 +87,7 @@ protected void installEqasimExtension() {
@Provides
public ModalUtilityEstimator provideModularUtilityEstimator(TripRouter tripRouter, ActivityFacilities facilities,
Map<String, Provider<UtilityEstimator>> factory, EqasimConfigGroup config,
TimeInterpreter.Factory timeInterpreterFactory, DiscreteModeChoiceConfigGroup dmcConfig) {
TimeInterpretation timeInterpretation, DiscreteModeChoiceConfigGroup dmcConfig) {
Map<String, UtilityEstimator> estimators = new HashMap<>();

for (Map.Entry<String, String> entry : config.getEstimators().entrySet()) {
Expand All @@ -101,7 +101,7 @@ public ModalUtilityEstimator provideModularUtilityEstimator(TripRouter tripRoute
}
}

return new ModalUtilityEstimator(tripRouter, facilities, estimators, timeInterpreterFactory,
return new ModalUtilityEstimator(tripRouter, facilities, estimators, timeInterpretation,
Collections.emptySet()); // Here we may add "pt" etc. as pre-routed modes.
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
import org.matsim.contribs.discrete_mode_choice.components.estimators.AbstractTripRouterEstimator;
import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip;
import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate;
import org.matsim.contribs.discrete_mode_choice.replanning.time_interpreter.TimeInterpreter;
import org.matsim.core.router.TripRouter;
import org.matsim.core.utils.timing.TimeInterpretation;
import org.matsim.facilities.ActivityFacilities;

public class ModalUtilityEstimator extends AbstractTripRouterEstimator {
private final Map<String, UtilityEstimator> estimators;

public ModalUtilityEstimator(TripRouter tripRouter, ActivityFacilities facilities,
Map<String, UtilityEstimator> estimators, TimeInterpreter.Factory timeInterpreterFactory,
Map<String, UtilityEstimator> estimators, TimeInterpretation timeInterpretation,
Collection<String> preroutedModes) {
super(tripRouter, facilities, timeInterpreterFactory, preroutedModes);
super(tripRouter, facilities, timeInterpretation, preroutedModes);
this.estimators = estimators;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.tuple.Pair;
Expand All @@ -13,7 +12,9 @@
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Leg;
import org.matsim.api.core.v01.population.PlanElement;
import org.matsim.core.network.NetworkUtils;
import org.matsim.core.router.DefaultRoutingRequest;
import org.matsim.core.router.LinkWrapperFacility;
import org.matsim.facilities.Facility;
import org.matsim.pt.router.TransitRouter;
Expand All @@ -36,19 +37,16 @@ public class BatchPublicTransportRouter {
private final int numberOfThreads;
private final double interval;

private final Set<String> transitModes;

public BatchPublicTransportRouter(Provider<TransitRouter> routerProvider,
Provider<HeadwayCalculator> headwayCalculatorProvider, TransitSchedule schedule, Network network,
int batchSize, int numberOfThreads, double interval, Set<String> transitModes) {
int batchSize, int numberOfThreads, double interval) {
this.routerProvider = routerProvider;
this.headwayCalculatorProvider = headwayCalculatorProvider;
this.batchSize = batchSize;
this.numberOfThreads = numberOfThreads;
this.schedule = schedule;
this.network = network;
this.interval = interval;
this.transitModes = transitModes;
}

public Pair<Collection<TripInformation>, Collection<LegInformation>> run(Collection<Task> tasks)
Expand Down Expand Up @@ -121,9 +119,9 @@ public void run() {
Facility fromFacility = new LinkWrapperFacility(NetworkUtils.getNearestLink(network, fromCoord));
Facility toFacility = new LinkWrapperFacility(NetworkUtils.getNearestLink(network, toCoord));

List<Leg> legs = router.calcRoute(fromFacility, toFacility, task.departureTime, null);
List<? extends PlanElement> planElements = router.calcRoute(DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, task.departureTime, null));

if (legs != null) {
if (planElements != null) {
boolean isFirstVehicularLeg = true;
tripInformation.isOnlyWalk = 1;

Expand All @@ -136,22 +134,30 @@ public void run() {

int currentIndex = 0;

for (Leg leg : legs) {
for (PlanElement planElement : planElements) {
if(!(planElement instanceof Leg)) {
continue;
}
Leg leg = (Leg) planElement;
boolean isFirstLeg = currentIndex == 0;
boolean isLastLeg = currentIndex == legs.size() - 1;
boolean isLastLeg = currentIndex == planElements.size() - 1;

if (leg.getMode().contains("walk") && isFirstLeg) {
tripInformation.accessTravelTime_min += leg.getTravelTime().seconds() / 60.0;
tripInformation.accessDistance_km += leg.getRoute().getDistance() * 1e-3;
} else if (leg.getMode().contains("walk") && isLastLeg) {
tripInformation.egressTravelTime_min += leg.getTravelTime().seconds() / 60.0;
tripInformation.egressDistance_km += leg.getRoute().getDistance() * 1e-3;
} else if (leg.getMode().contains("walk") && !isFirstLeg && !isLastLeg) {
} else if (leg.getMode().contains("walk")) {
tripInformation.transferTravelTime_min += leg.getTravelTime().seconds() / 60.0;
tripInformation.transferDistance_km += leg.getRoute().getDistance() * 1e-3;
} else if (transitModes.contains(leg.getMode())) {
} else if (leg.getRoute() instanceof TransitPassengerRoute) {
TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute();

TransitLine transitLine = schedule.getTransitLines().get(route.getLineId());
TransitRoute transitRoute = transitLine.getRoutes().get(route.getRouteId());
String transitMode = transitRoute.getTransportMode();

double waitingTime = route.getBoardingTime().seconds()
- leg.getDepartureTime().seconds();

Expand All @@ -163,10 +169,6 @@ public void run() {
tripInformation.transferWaitingTime_min += waitingTime / 60.0;
}

TransitLine transitLine = schedule.getTransitLines().get(route.getLineId());
TransitRoute transitRoute = transitLine.getRoutes().get(route.getRouteId());
String transitMode = transitRoute.getTransportMode();

double inVehicleTime = route.getTravelTime().seconds() - waitingTime;

switch (transitMode) {
Expand Down Expand Up @@ -210,7 +212,7 @@ public void run() {
localLegResults.add(legInformation);
}
} else {
throw new IllegalStateException();
throw new IllegalStateException("Don't know what to do with mode: " + leg.getMode());
}

currentIndex++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.eqasim.core.misc.ParallelProgress;
Expand All @@ -28,13 +29,15 @@ public class BatchRoadRouter {

private final int batchSize;
private final int numberOfThreads;
private final boolean writePaths;

public BatchRoadRouter(Provider<LeastCostPathCalculatorFactory> routerFactoryProvider, Network network,
int batchSize, int numberOfThreads) {
int batchSize, int numberOfThreads, boolean writePaths) {
this.routerFactoryProvider = routerFactoryProvider;
this.batchSize = batchSize;
this.numberOfThreads = numberOfThreads;
this.network = network;
this.writePaths = writePaths;
}

public Collection<Result> run(Collection<Task> tasks) throws InterruptedException {
Expand Down Expand Up @@ -115,6 +118,10 @@ public void run() {
result.egressEuclideanDistance_km = CoordUtils.calcEuclideanDistance(toCoord,
toLink.getFromNode().getCoord()) * 1e-3;

if (writePaths) {
path.links.forEach(link -> result.path.add(link.getId().toString()));
}

localResults.add(result);
progress.update();
}
Expand Down Expand Up @@ -162,6 +169,9 @@ static public class Result {
@JsonProperty("in_vehicle_distance_km")
public double inVehicleDistance_km;

@JsonProperty("path")
public List<String> path = new LinkedList<>();

Result(Task task) {
this.identifier = task.identifier;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera
Network network = injector.getInstance(Network.class);

BatchPublicTransportRouter batchRouter = new BatchPublicTransportRouter(routerProvider,
headwayCalculatorProvider, schedule, network, batchSize, numberOfThreads, interval, transitModes);
headwayCalculatorProvider, schedule, network, batchSize, numberOfThreads, interval);

CsvMapper mapper = new CsvMapper();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.matsim.core.scenario.ScenarioUtils;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.SequenceWriter;
Expand All @@ -42,7 +43,7 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera
IOException, InterruptedException {
CommandLine cmd = new CommandLine.Builder(args) //
.requireOptions("config-path", "input-path", "output-path") //
.allowOptions("threads", "batch-size", "modes") //
.allowOptions("threads", "batch-size", "modes", "write-paths") //
.build();

EqasimConfigurator configurator = new EqasimConfigurator();
Expand All @@ -57,6 +58,8 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera
.orElse(Runtime.getRuntime().availableProcessors());
int batchSize = cmd.getOption("batch-size").map(Integer::parseInt).orElse(100);

boolean writePaths = cmd.getOption("write-paths").map(Boolean::parseBoolean).orElse(false);

Set<String> modes = new HashSet<>();
for (String mode : cmd.getOption("modes").orElse("car").split(",")) {
modes.add(mode);
Expand All @@ -83,25 +86,43 @@ public Network provideCarNetwork(Network network) {
Network network = injector.getInstance(Key.get(Network.class, Names.named("car")));

BatchRoadRouter batchRouter = new BatchRoadRouter(injector.getProvider(LeastCostPathCalculatorFactory.class),
network, batchSize, numberOfThreads);
network, batchSize, numberOfThreads, writePaths);

CsvMapper mapper = new CsvMapper();
CsvMapper taskMapper = new CsvMapper();

File inputFile = new File(cmd.getOptionStrict("input-path"));
CsvSchema taskSchema = mapper.typedSchemaFor(Task.class).withHeader().withColumnSeparator(',').withComments()
.withColumnReordering(true);
CsvSchema taskSchema = taskMapper.typedSchemaFor(Task.class).withHeader().withColumnSeparator(',')
.withComments().withColumnReordering(true);

MappingIterator<Task> taskIterator = mapper.readerWithTypedSchemaFor(Task.class).with(taskSchema)
MappingIterator<Task> taskIterator = taskMapper.readerWithTypedSchemaFor(Task.class).with(taskSchema)
.readValues(inputFile);
List<Task> tasks = taskIterator.readAll();

Collection<Result> results = batchRouter.run(tasks);

CsvSchema.Builder builder = new CsvSchema.Builder() //
.setColumnSeparator(',') //
.setArrayElementSeparator(" ") //
.setUseHeader(true) //
.addColumn("identifier") //
.addColumn("access_euclidean_distance_km") //
.addColumn("egress_euclidean_distance_km") //
.addColumn("in_vehicle_time_min") //
.addColumn("in_vehicle_distance_km");

if (writePaths) {
builder.addArrayColumn("path");
}

CsvSchema schema = builder.build();

File outputFile = new File(cmd.getOptionStrict("output-path"));
CsvSchema resultSchema = mapper.typedSchemaFor(Result.class).withHeader().withColumnSeparator(',');

SequenceWriter writer = mapper.writerWithTypedSchemaFor(Result.class).with(resultSchema)
CsvMapper resultMapper = new CsvMapper();
resultMapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true);
SequenceWriter writer = resultMapper.writerWithTypedSchemaFor(Result.class).with(schema)
.writeValues(outputFile);

writer.writeAll(results);
}
}
Loading

0 comments on commit 2c9839f

Please sign in to comment.