Skip to content

Commit

Permalink
add initializer and change to injection during tests
Browse files Browse the repository at this point in the history
  • Loading branch information
paulheinr committed Feb 11, 2025
1 parent 8e6172f commit 42ae66d
Show file tree
Hide file tree
Showing 12 changed files with 311 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
import org.matsim.prepare.drt.CreateDrtVehicles;
import org.matsim.prepare.facilities.CreateMATSimFacilities;
import org.matsim.prepare.facilities.ExtractFacilityGeoPkg;
import org.matsim.prepare.network.NetworkAddParkingSpots;
import org.matsim.prepare.opt.ExtractPlanIndexFromType;
import org.matsim.prepare.network.NetworkAddParkingSpots;
import org.matsim.prepare.opt.RunCountOptimization;
import org.matsim.prepare.opt.SelectPlansFromIndex;
import org.matsim.prepare.population.*;
Expand Down Expand Up @@ -95,7 +97,7 @@
GenerateSmallScaleCommercialTrafficDemand.class, CreateDataDistributionOfStructureData.class,
RunCountOptimization.class, SelectPlansFromIndex.class, ExtractPlanIndexFromType.class, AssignReferencePopulation.class,
ExtractRelevantFreightTrips.class, CheckCarAvailability.class, FixSubtourModes.class, ComputeTripChoices.class, ComputePlanChoices.class,
ApplyNetworkParams.class, SetCarAvailabilityByAge.class, CreateDrtVehicles.class, EndlessCircleLineScheduleModifier.class
ApplyNetworkParams.class, SetCarAvailabilityByAge.class, CreateDrtVehicles.class, EndlessCircleLineScheduleModifier.class, NetworkAddParkingSpots.class
})
public class RunOpenBerlinCalibration extends MATSimApplication {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class NetworkAddParkingSpots implements MATSimAppCommand {
@CommandLine.Option(names = "--network", description = "Path to input network", required = true)
private Path network;

@CommandLine.Option(names = "--parking-sports", description = "Path to parking spots csv", required = true)
@CommandLine.Option(names = "--parking-spots", description = "Path to parking spots csv", required = true)
private Path parkingSpots;

@CommandLine.Option(names = "--output", description = "Desired output path", required = true)
Expand Down Expand Up @@ -53,15 +53,22 @@ private List<ParkingSpotEntry> readParkingSpots() throws IOException {
try (BufferedReader reader = Files.newBufferedReader(parkingSpots)) {
CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT.withHeader());
for (CSVRecord csvRecord : csvParser) {
String linkId = csvRecord.get("linkId");
double onStreet = Double.parseDouble(csvRecord.get("onStreet"));
double offStreet = Double.parseDouble(csvRecord.get("offStreet"));
String linkId = csvRecord.get("id");
double onStreet = catchNa(csvRecord.get("onstreet_spots"));
double offStreet = catchNa(csvRecord.get("offstreet_spots"));
parkingSpotEntries.add(new ParkingSpotEntry(linkId, onStreet, offStreet));
}
}
return parkingSpotEntries;
}

private Double catchNa(String string) {
if (string.equals("NA")) {
return 0.0;
}
return Double.parseDouble(string);
}

private record ParkingSpotEntry(String linkId, double onStreet, double offStreet) {
}
}
39 changes: 39 additions & 0 deletions src/main/java/org/matsim/run/OpenBerlinParkingScenario.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.matsim.run;

import org.matsim.core.config.Config;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.controler.Controler;
import org.matsim.run.scoring.parking.*;


/**
* This class extends the Berlin scenario by parking search times. Currently, only one iteration is run based on that, scoring is performed.
* By default, it uses the Belloche parking search model with a kernel of 500m distance.
*/
public class OpenBerlinParkingScenario extends OpenBerlinScenario {
@Override
protected Config prepareConfig(Config config) {
super.prepareConfig(config);

config.controller().setLastIteration(1);
config.network().setInputFile("with-parking");
config.controller().setOutputDirectory(config.controller().getOutputDirectory() + "-parking");
config.controller().setRunId(config.controller().getRunId() + "-parking");

return config;
}

@Override
protected void prepareControler(Controler controler) {
super.prepareControler(controler);

controler.addOverridingModule(new AbstractModule() {
@Override
public void install() {
bind(KernelFunction.class).to(ConstantKernelFunction.class);
bind(PenaltyFunction.class).toInstance(new BellochePenaltyFunction(0.4, -6));
addEventHandlerBinding().to(ParkingObserver.class);
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public double calculatePenalty(Map<Id<Link>, ParkingCount> parkingCount) {
Tuple<Double, Double> weightedOccK = getWeightedOccK(parkingCount);

if (weightedOccK.getSecond() == 0) {
log.warn("The total capacity of parking spots is 0. As fallback, we assume that the occupancy rate is 1, so each link is full.");
// The total capacity of parking spots is 0. As fallback, we assume that the occupancy rate is 1, so each link is full.
return alpha * Math.exp(-beta);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.matsim.run.scoring.parking;

import com.google.inject.Inject;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
Expand All @@ -12,8 +13,10 @@
* A kernel function that assigns a constant weight to all links within a certain distance. Takes the middle of the link as the center of the disk.
*/
public class ConstantKernelFunction implements KernelFunction {
// this might be replaced by a LinkQuadTree from the network, but the getDisk method would have to be implemented there.
QuadTree<Id<Link>> quadTree;

@Inject
public ConstantKernelFunction(Network network) {
double xMin = network.getNodes().values().parallelStream().mapToDouble(node -> node.getCoord().getX()).min().orElse(Double.POSITIVE_INFINITY);
double yMin = network.getNodes().values().parallelStream().mapToDouble(node -> node.getCoord().getY()).min().orElse(Double.POSITIVE_INFINITY);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.matsim.run.scoring.parking;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;

import java.util.Map;

public interface ParkingCapacityInitializer {
Map<Id<Link>, InitialParkingCapacity> initialize();

record InitialParkingCapacity(int capacity, int initial) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.matsim.run.scoring.parking;

import org.matsim.api.core.v01.events.TransitDriverStartsEvent;
import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent;
import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent;
import org.matsim.api.core.v01.events.handler.TransitDriverStartsEventHandler;
import org.matsim.api.core.v01.events.handler.VehicleEntersTrafficEventHandler;
import org.matsim.api.core.v01.events.handler.VehicleLeavesTrafficEventHandler;

public class ParkingEventsHandler implements VehicleEntersTrafficEventHandler, VehicleLeavesTrafficEventHandler, TransitDriverStartsEventHandler {


@Override
public void handleEvent(TransitDriverStartsEvent event) {

}

@Override
public void handleEvent(VehicleEntersTrafficEvent event) {

}

@Override
public void handleEvent(VehicleLeavesTrafficEvent event) {

}
}
31 changes: 21 additions & 10 deletions src/main/java/org/matsim/run/scoring/parking/ParkingObserver.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Person;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.modechoice.estimators.ActivityEstimator;
import org.matsim.modechoice.estimators.LegEstimator;
import org.matsim.vehicles.Vehicle;

import java.util.HashMap;
Expand All @@ -24,12 +26,12 @@ public class ParkingObserver implements VehicleEntersTrafficEventHandler, Vehicl
static final String LINK_ON_STREET_SPOTS = "onstreet_spots";
static final String LINK_OFF_STREET_SPOTS = "offstreet_spots";

//injected
Network network;
KernelFunction kernelFunction;
PenaltyFunction penaltyFunction;
EventsManager eventsManager;

ActivityEstimator activityEstimator;
LegEstimator legEstimator;

//state
Set<Id<Vehicle>> knownPtVehicles = new HashSet<>();
Expand All @@ -38,32 +40,40 @@ public class ParkingObserver implements VehicleEntersTrafficEventHandler, Vehicl
int[] capacity;

//TODO
double kernelDistance = 0;
double kernelDistance = 500;

@Inject
public ParkingObserver(Network network, KernelFunction kernelFunction, PenaltyFunction penaltyFunction, EventsManager eventsManager) {
public ParkingObserver(Network network, KernelFunction kernelFunction, PenaltyFunction penaltyFunction, EventsManager eventsManager,
ParkingCapacityInitializer parkingCapacityInitializer, ActivityEstimator activityEstimator, LegEstimator legEstimator) {
this.indexByLinkId = new HashMap<>(network.getLinks().size());
this.network = network;
this.kernelFunction = kernelFunction;
this.penaltyFunction = penaltyFunction;
this.eventsManager = eventsManager;
initCapacity(network);
this.activityEstimator = activityEstimator;
this.legEstimator = legEstimator;

initCapacity(network, parkingCapacityInitializer);
}

private void initCapacity(Network network) {
private void initCapacity(Network network, ParkingCapacityInitializer parkingCapacityInitializer) {
int counter = 0;
for (Id<Link> id : network.getLinks().keySet()) {
indexByLinkId.put(id, counter++);
}

int linkCount = network.getLinks().size();
capacity = new int[linkCount];
parkingCount = new int[linkCount];

Map<Id<Link>, ParkingCapacityInitializer.InitialParkingCapacity> initialize = parkingCapacityInitializer.initialize();
for (Link link : network.getLinks().values()) {
int onStreet = (int) link.getAttributes().getAttribute(LINK_ON_STREET_SPOTS);
int offStreet = (int) link.getAttributes().getAttribute(LINK_OFF_STREET_SPOTS);
capacity[indexByLinkId.get(link.getId())] = onStreet + offStreet;
ParkingCapacityInitializer.InitialParkingCapacity initialParkingCapacity = initialize.get(link.getId());
int index = indexByLinkId.get(link.getId());

capacity[index] = initialParkingCapacity.capacity();
parkingCount[index] = initialParkingCapacity.initial();
}
parkingCount = new int[linkCount];
}

@Override
Expand Down Expand Up @@ -114,6 +124,7 @@ private Map<Id<Link>, ParkingCount> applyWeights(Map<Id<Link>, Double> weightedL

private void applyPenalty(double time, Id<Person> personId, double penaltyInSec, Id<Link> linkId) {
//TODO convert penalty to money

double score = 0.0;

PersonScoreEvent personScoreEvent = new PersonScoreEvent(time, personId, score, "parking");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.matsim.run.scoring.parking;

import com.google.inject.Inject;
import org.matsim.api.core.v01.Id;
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.Population;
import org.matsim.core.router.TripStructureUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static org.matsim.run.scoring.parking.ParkingObserver.LINK_OFF_STREET_SPOTS;
import static org.matsim.run.scoring.parking.ParkingObserver.LINK_ON_STREET_SPOTS;

public class PlanBasedParkingCapacityInitializer implements ParkingCapacityInitializer {
private Network network;
private Population population;

@Inject
PlanBasedParkingCapacityInitializer(Network network, Population population) {
this.network = network;
this.population = population;
}

@Override
public Map<Id<Link>, InitialParkingCapacity> initialize() {
Map<Id<Link>, Long> initialParkingByPlans = getInitialParkingByPlans();

Map<Id<Link>, InitialParkingCapacity> res = new HashMap<>(network.getLinks().size());
for (Link link : network.getLinks().values()) {
int onStreet = (int) Optional.ofNullable(link.getAttributes().getAttribute(LINK_ON_STREET_SPOTS)).orElse(0);
int offStreet = (int) Optional.ofNullable(link.getAttributes().getAttribute(LINK_OFF_STREET_SPOTS)).orElse(0);

int initialParking = initialParkingByPlans.getOrDefault(link.getId(), 0L).intValue();
res.put(link.getId(), new InitialParkingCapacity(onStreet + offStreet, initialParking));
}
return res;
}

// Returns the number of parking spots on the link where the first car trip starts
private Map<Id<Link>, Long> getInitialParkingByPlans() {
return population.getPersons().values().stream().map(p -> p.getSelectedPlan())
.map(p -> TripStructureUtils.findAccessWalksWithPreviousActivity(p, TransportMode.car).stream().findFirst())
.filter(Optional::isPresent)
.map(Optional::get)
.map(lap -> lap.act.getLinkId())
.collect(Collectors.groupingBy(l -> l, Collectors.counting()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.matsim.run.scoring.parking;

import com.google.inject.Inject;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import static org.matsim.run.scoring.parking.ParkingObserver.LINK_OFF_STREET_SPOTS;
import static org.matsim.run.scoring.parking.ParkingObserver.LINK_ON_STREET_SPOTS;

public class ZeroParkingCapacityInitializer implements ParkingCapacityInitializer {
private Network network;

@Inject
ZeroParkingCapacityInitializer(Network network) {
this.network = network;
}

@Override
public Map<Id<Link>, InitialParkingCapacity> initialize() {
Map<Id<Link>, InitialParkingCapacity> res = new HashMap<>(network.getLinks().size());
for (Link link : network.getLinks().values()) {
int onStreet = (int) Optional.ofNullable(link.getAttributes().getAttribute(LINK_ON_STREET_SPOTS)).orElse(0);
int offStreet = (int) Optional.ofNullable(link.getAttributes().getAttribute(LINK_OFF_STREET_SPOTS)).orElse(0);
res.put(link.getId(), new InitialParkingCapacity(onStreet + offStreet, 0));
}
return res;
}
}
Loading

0 comments on commit 42ae66d

Please sign in to comment.