Skip to content

Commit

Permalink
Merge branch 'master' into activity-dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
rakow committed Dec 18, 2024
2 parents 9af38a9 + 426d78c commit a40e004
Show file tree
Hide file tree
Showing 155 changed files with 3,200 additions and 1,288 deletions.
2 changes: 1 addition & 1 deletion contribs/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
<dependency>
<groupId>com.github.matsim-org</groupId>
<artifactId>gtfs2matsim</artifactId>
<version>47b0802a29</version>
<version>19f1676fc6</version>
<exclusions>
<!-- Exclude unneeded dependencies and these with known CVE -->
<exclusion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.matsim.core.utils.io.IOUtils;
import org.matsim.pt.transitSchedule.api.*;
import org.matsim.pt.utils.CreatePseudoNetwork;
import org.matsim.pt.utils.CreatePseudoNetworkWithLoopLinks;
import org.matsim.pt.utils.TransitScheduleValidator;
import org.matsim.vehicles.*;
import picocli.CommandLine;
Expand Down Expand Up @@ -85,8 +86,8 @@ public class CreateTransitScheduleFromGtfs implements MATSimAppCommand {
@CommandLine.Option(names = "--transform-schedule", description = "Fully qualified class name to a Consumer<TransitSchedule> to be executed after the schedule was created", arity = "0..*", split = ",")
private List<Class<?>> transformSchedule;

@CommandLine.Option(names = "--merge-stops", description = "Whether stops should be merged by coordinate")
private boolean mergeStops;
@CommandLine.Option(names = "--merge-stops", description = "Whether stops should be merged by coordinate", defaultValue = "doNotMerge")
private GtfsConverter.MergeGtfsStops mergeStops;

@CommandLine.Option(names = "--prefix", description = "Prefixes to add to the gtfs ids. Required if multiple inputs are used and ids are not unique.", split = ",")
private List<String> prefixes = new ArrayList<>();
Expand All @@ -100,10 +101,29 @@ public class CreateTransitScheduleFromGtfs implements MATSimAppCommand {
@CommandLine.Option(names = "--shp-crs", description = "Overwrite coordinate system of the shape file")
private String shpCrs;

@CommandLine.Option(names = "--pseudo-network", description = "Define how the pseudo network should be created", defaultValue = "singleLinkBetweenStops")
private PseudoNetwork pseudoNetwork;


public static void main(String[] args) {
System.exit(new CommandLine(new CreateTransitScheduleFromGtfs()).execute(args));
}

private static void addHbefaMapping(VehicleType vehicleType, HbefaVehicleCategory category) {
EngineInformation carEngineInformation = vehicleType.getEngineInformation();
VehicleUtils.setHbefaVehicleCategory(carEngineInformation, String.valueOf(category));
VehicleUtils.setHbefaTechnology(carEngineInformation, "average");
VehicleUtils.setHbefaSizeClass(carEngineInformation, "average");
VehicleUtils.setHbefaEmissionsConcept(carEngineInformation, "average");
vehicleType.setNetworkMode(TransportMode.pt);
}

private static void increaseLinkFreespeedIfLower(Link link, double newFreespeed) {
if (link.getFreespeed() < newFreespeed) {
link.setFreespeed(newFreespeed);
}
}

@Override
public Integer call() throws Exception {

Expand Down Expand Up @@ -183,6 +203,13 @@ public Integer call() throws Exception {

Scenario ptScenario = getScenarioWithPseudoPtNetworkAndTransitVehicles(network, scenario.getTransitSchedule(), "pt_");

for (TransitLine line : new ArrayList<>(scenario.getTransitSchedule().getTransitLines().values())) {
if (line.getRoutes().isEmpty()) {
log.warn("Line {} with no routes removed.", line.getId());
scenario.getTransitSchedule().removeTransitLine(line);
}
}

if (validate) {
//Check schedule and network
TransitScheduleValidator.ValidationResult checkResult = TransitScheduleValidator.validateAll(ptScenario.getTransitSchedule(), ptScenario.getNetwork());
Expand Down Expand Up @@ -237,14 +264,19 @@ private Predicate<Stop> createFilter(int i) throws Exception {
/**
* Creates the pt scenario and network.
*/
private static Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network network, TransitSchedule schedule, String ptNetworkIdentifier) {
private Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network network, TransitSchedule schedule, String ptNetworkIdentifier) {
ScenarioUtils.ScenarioBuilder builder = new ScenarioUtils.ScenarioBuilder(ConfigUtils.createConfig());
builder.setNetwork(network);
builder.setTransitSchedule(schedule);
Scenario scenario = builder.build();

// add pseudo network for pt
new CreatePseudoNetwork(scenario.getTransitSchedule(), scenario.getNetwork(), ptNetworkIdentifier, 0.1, 100000.0).createNetwork();
switch (pseudoNetwork) {
case singleLinkBetweenStops ->
new CreatePseudoNetwork(scenario.getTransitSchedule(), scenario.getNetwork(), ptNetworkIdentifier, 0.1, 100000.0).createNetwork();
case withLoopLinks ->
new CreatePseudoNetworkWithLoopLinks(scenario.getTransitSchedule(), scenario.getNetwork(), ptNetworkIdentifier, 0.1, 100000.0).createNetwork();
}

// create TransitVehicle types
// see https://svn.vsp.tu-berlin.de/repos/public-svn/publications/vspwp/2014/14-24/ for veh capacities
Expand Down Expand Up @@ -449,8 +481,12 @@ private static Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network
// so we need to add time for passengers to board and alight
double minStopTime = 30.0;

List<Id<Link>> routeIds = new LinkedList<>();
routeIds.add(route.getRoute().getStartLinkId());
routeIds.addAll(route.getRoute().getLinkIds());
routeIds.add(route.getRoute().getEndLinkId());

for (int i = 1; i < routeStops.size(); i++) {
// TODO cater for loop link at first stop? Seems to just work without.
TransitRouteStop routeStop = routeStops.get(i);
// if there is no departure offset set (or infinity), it is the last stop of the line,
// so we don't need to care about the stop duration
Expand All @@ -462,8 +498,23 @@ private static Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network
// Math.max to avoid negative values of travelTime
double travelTime = Math.max(1, routeStop.getArrivalOffset().seconds() - lastDepartureOffset - 1.0 -
(stopDuration >= minStopTime ? 0 : (minStopTime - stopDuration)));
Link link = network.getLinks().get(routeStop.getStopFacility().getLinkId());
increaseLinkFreespeedIfLower(link, link.getLength() / travelTime);


Id<Link> stopLink = routeStop.getStopFacility().getLinkId();
List<Id<Link>> subRoute = new LinkedList<>();
do {
Id<Link> linkId = routeIds.removeFirst();
subRoute.add(linkId);
} while (!subRoute.contains(stopLink));

List<? extends Link> links = subRoute.stream().map(scenario.getNetwork().getLinks()::get)
.toList();

double length = links.stream().mapToDouble(Link::getLength).sum();

for (Link link : links) {
increaseLinkFreespeedIfLower(link, length / travelTime);
}
lastDepartureOffset = routeStop.getDepartureOffset().seconds();
}

Expand All @@ -481,20 +532,15 @@ private static Scenario getScenarioWithPseudoPtNetworkAndTransitVehicles(Network
return scenario;
}

private static void addHbefaMapping(VehicleType vehicleType, HbefaVehicleCategory category) {
EngineInformation carEngineInformation = vehicleType.getEngineInformation();
VehicleUtils.setHbefaVehicleCategory(carEngineInformation, String.valueOf(category));
VehicleUtils.setHbefaTechnology(carEngineInformation, "average");
VehicleUtils.setHbefaSizeClass(carEngineInformation, "average");
VehicleUtils.setHbefaEmissionsConcept(carEngineInformation, "average");
vehicleType.setNetworkMode(TransportMode.pt);
}

private static void increaseLinkFreespeedIfLower(Link link, double newFreespeed) {
if (link.getFreespeed() < newFreespeed) {
link.setFreespeed(newFreespeed);
}
public enum PseudoNetwork {
/**
* Create links between all stops and possibly duplicate stops.
*/
singleLinkBetweenStops,
/**
* Create a pseudo network with loop links at each stop.
*/
withLoopLinks,
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -590,9 +590,12 @@ public void run(Person person) {
}

// Remove all unselected plans because these are not handled
person.getPlans().stream()
.filter(p -> p != person.getSelectedPlan())
.forEach(person::removePlan);
List<Plan> plans = new ArrayList<>(person.getPlans());
for(Plan p : plans){
if (p != person.getSelectedPlan()){
person.removePlan(p);
}
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(5000);
start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 1800.);
start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5000.);
AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 1800.0);
AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 5000.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
Expand All @@ -295,8 +295,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(5000);
start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 900.);
start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5005.);
AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 900.0);
AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 5005.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
Expand All @@ -310,8 +310,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(5000);
start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.);
start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5000.);
AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 4000.0);
AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 5000.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
Expand All @@ -325,8 +325,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(8000);
start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.);
start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 11000.);
AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 4000.0);
AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 11000.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
Expand All @@ -340,8 +340,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(6000.);
start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.);
start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 6000.);
AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 4000.0);
AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 6000.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
Expand All @@ -355,8 +355,8 @@ private void preparePopulation(Scenario scenario) {
Plan plan = factory.createPlan();
Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1));
start.setEndTime(6500.);
start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.);
start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 6500.);
AttributeBasedPrebookingLogic.setSubmissionTime("drt", start, 4000.0);
AttributeBasedPrebookingLogic.setPlannedDepartureTime("drt", start, 6500.0);
plan.addActivity(start);
plan.addLeg(factory.createLeg("drt"));
plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,35 @@ public class DefaultDrtOptimizationConstraintsSet extends DrtOptimizationConstra

@Parameter
@Comment(
"Defines the maximum allowed absolute detour in seconds. Note that the detour is computed from the latest promised pickup time. " +
"To enable the max detour constraint, maxAllowedPickupDelay has to be specified. maxAbsoluteDetour should not be smaller than 0, "
"Defines the maximum allowed absolute detour in seconds. maxAbsoluteDetour should not be smaller than 0, "
+ "and should be higher than the offset maxDetourBeta. By default, this limit is disabled (i.e. set to Inf)")
@PositiveOrZero
public double maxAbsoluteDetour = Double.POSITIVE_INFINITY;// [s]

@Parameter
@Comment(
"Defines the maximum allowed absolute detour based on the unsharedRideTime. Note that the detour is computed from the latest promised "
+ "pickup time. To enable the max detour constraint, maxAllowedPickupDelay has to be specified. A linear combination similar to travel "
"Defines the maximum allowed absolute detour based on the unsharedRideTime. A linear combination similar to travel "
+ "time constrain is used. This is the ratio part. By default, this limit is disabled (i.e. set to Inf, together with maxDetourBeta).")
@DecimalMin("1.0")
public double maxDetourAlpha = Double.POSITIVE_INFINITY;

@Parameter
@Comment(
"Defines the maximum allowed absolute detour based on the unsharedRideTime. Note that the detour is computed from the latest promised "
+ "pickup time. To enable the max detour constraint, maxAllowedPickupDelay has to be specified. A linear combination similar to travel "
"Defines the maximum allowed absolute detour based on the unsharedRideTime. A linear combination similar to travel "
+ "time constrain is used. This is the constant part. By default, this limit is disabled (i.e. set to Inf, together with maxDetourAlpha).")
@PositiveOrZero
public double maxDetourBeta = Double.POSITIVE_INFINITY;// [s]

@Parameter
@Comment(
"Defines the minimum allowed absolute detour in seconds. By default, this bound is disabled (i.e. set to 0.)")
@PositiveOrZero
public double minimumAllowedDetour = 0;

@Override
protected void checkConsistency(Config config) {
super.checkConsistency(config);
if ((maxDetourAlpha != Double.POSITIVE_INFINITY && maxDetourBeta != Double.POSITIVE_INFINITY) || maxAbsoluteDetour != Double.POSITIVE_INFINITY) {
Verify.verify(maxAllowedPickupDelay != Double.POSITIVE_INFINITY, "Detour constraints are activated, " +
"maxAllowedPickupDelay must be specified! A value between 0 and 240 seconds can be a good choice for maxAllowedPickupDelay.");
}
Verify.verify(maxAbsoluteDetour > minimumAllowedDetour, "The minimum allowed detour must" +
"be lower than the maximum allowed detour.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
*/
public class MinCostFlowRebalancingStrategy implements RebalancingStrategy {

public static final String REBALANCING_ZONAL_TARGET_ALPHA = "rebalalpha";
public static final String REBALANCING_ZONAL_TARGET_BETA = "rebalbeta";

private final RebalancingTargetCalculator rebalancingTargetCalculator;
private final ZoneSystem zonalSystem;
private final Fleet fleet;
Expand Down Expand Up @@ -68,18 +71,37 @@ public List<Relocation> calcRelocations(Stream<? extends DvrpVehicle> rebalancab
return calculateMinCostRelocations(time, rebalancableVehiclesPerZone, soonIdleVehiclesPerZone);
}

private List<Relocation> calculateMinCostRelocations(double time,
List<Relocation> calculateMinCostRelocations(double time,
Map<Zone, List<DvrpVehicle>> rebalancableVehiclesPerZone,
Map<Zone, List<DvrpVehicle>> soonIdleVehiclesPerZone) {
ToDoubleFunction<Zone> targetFunction = rebalancingTargetCalculator.calculate(time,
rebalancableVehiclesPerZone);
var minCostFlowRebalancingStrategyParams = (MinCostFlowRebalancingStrategyParams)params.getRebalancingStrategyParams();
double alpha = minCostFlowRebalancingStrategyParams.targetAlpha;
double beta = minCostFlowRebalancingStrategyParams.targetBeta;

List<DrtZoneVehicleSurplus> vehicleSurpluses = zonalSystem.getZones().values().stream().map(z -> {
List<DrtZoneVehicleSurplus> vehicleSurpluses = zonalSystem.getZones().values().stream().map(z -> {
double alpha;
double beta;
int rebalancable = rebalancableVehiclesPerZone.getOrDefault(z, List.of()).size();
int soonIdle = soonIdleVehiclesPerZone.getOrDefault(z, List.of()).size();

switch (minCostFlowRebalancingStrategyParams.targetCoefficientSource) {
case Static -> {
alpha = minCostFlowRebalancingStrategyParams.targetAlpha;
beta = minCostFlowRebalancingStrategyParams.targetBeta;
}
case FromZoneAttribute -> {
alpha = (Double) z.getAttributes().getAttribute(REBALANCING_ZONAL_TARGET_ALPHA);
beta = (Double) z.getAttributes().getAttribute(REBALANCING_ZONAL_TARGET_BETA);
}
case FromZoneAttributeOrStatic -> {
Object alphaAttribute = z.getAttributes().getAttribute(REBALANCING_ZONAL_TARGET_ALPHA);
alpha = alphaAttribute == null ? minCostFlowRebalancingStrategyParams.targetAlpha : (Double) alphaAttribute;
Object betaAttribute = z.getAttributes().getAttribute(REBALANCING_ZONAL_TARGET_BETA);
beta = betaAttribute == null ? minCostFlowRebalancingStrategyParams.targetBeta : (Double) betaAttribute;
}
default -> throw new IllegalStateException("Unknown target coefficient source " + minCostFlowRebalancingStrategyParams.targetCoefficientSource);
}

int target = (int)Math.floor(alpha * targetFunction.applyAsDouble(z) + beta);
int surplus = Math.min(rebalancable + soonIdle - target, rebalancable);
return new DrtZoneVehicleSurplus(z, surplus);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ public enum RebalancingTargetCalculatorType {
@NotNull
public RebalancingTargetCalculatorType rebalancingTargetCalculatorType = RebalancingTargetCalculatorType.EstimatedDemand;


public enum TargetCoefficientSource {
Static, FromZoneAttribute, FromZoneAttributeOrStatic
}

@Parameter
@Comment("Defines whether the alpha and beta of the target function should be"
+ " [Static] or [FromZoneAttribute] in which case alpha and beta can be provided per zone as an attribute."
+ " [FromZoneAttributeOrStatic] will fall back to the static coefficients if no attribute is found for a given zone."
+ " Use " + MinCostFlowRebalancingStrategy.REBALANCING_ZONAL_TARGET_ALPHA + " and " + MinCostFlowRebalancingStrategy.REBALANCING_ZONAL_TARGET_BETA
+ " to set values accordingly.")
public TargetCoefficientSource targetCoefficientSource = TargetCoefficientSource.Static;

public enum ZonalDemandEstimatorType {PreviousIterationDemand, None}

@Parameter
Expand Down
Loading

0 comments on commit a40e004

Please sign in to comment.