Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
luchengqi7 committed Mar 5, 2024
1 parent 3efb442 commit 0bd74b0
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ public double estimate(EstimatorContext context, String mode, Leg leg, ModeAvail
params.marginalUtilityOfDistance_m * est.rideDistance() +
params.marginalUtilityOfTraveling_s * est.rideTime() +
params.marginalUtilityOfTraveling_s * est.waitingTime() +
context.scoring.marginalUtilityOfMoney * params.monetaryDistanceCostRate * est.rideDistance() +
context.scoring.marginalUtilityOfMoney * est.fare();
context.scoring.marginalUtilityOfMoney * params.monetaryDistanceCostRate * est.rideDistance();
// TODO: add a new fare estimator?
// context.scoring.marginalUtilityOfMoney * est.fare();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.matsim.contrib.drt.estimator.DrtEstimator;
import org.matsim.contrib.drt.estimator.DrtEstimatorParams;
import org.matsim.contrib.drt.estimator.impl.PessimisticDrtEstimator;
import org.matsim.contrib.drt.estimator.impl.RealisticDrtEstimator;
import org.matsim.contrib.drt.fare.DrtFareParams;
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.contrib.drt.run.DrtControlerCreator;
Expand All @@ -13,7 +13,9 @@
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.config.groups.ReplanningConfigGroup;
import org.matsim.core.controler.Controler;
import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule;
import org.matsim.core.utils.io.IOUtils;
import org.matsim.examples.ExamplesUtils;
import org.matsim.testcases.MatsimTestUtils;
Expand All @@ -38,12 +40,11 @@ void testPessimisticEstimator() {
// install the drt routing stuff, but not the mobsim stuff!
Controler controler = DrtControlerCreator.createControler(config, false);
DrtConfigGroup drtConfigGroup = DrtConfigGroup.getSingleModeDrtConfig(config);
drtConfigGroup.maxTravelTimeAlpha = 1.1;
drtConfigGroup.maxTravelTimeAlpha = 1.2;
drtConfigGroup.maxTravelTimeBeta = 600;
drtConfigGroup.maxWaitTime = 300;
drtConfigGroup.simulationType = DrtConfigGroup.SimulationType.estimateAndTeleport;

// DrtEstimatorParams params = new DrtEstimatorParams();
// drtConfigGroup.addParameterSet(params);

DrtFareParams fareParams = new DrtFareParams();
fareParams.baseFare = 1.0;
fareParams.distanceFare_m = 0.001;
Expand All @@ -56,23 +57,41 @@ public void install() {
}
});


System.out.println(config);
controler.run();
}

// TODO
// We want to use DRT infrastructure (routing) so we need to integrate into drt teleportation
// Write our own TeleportingPassengerEngine
// this engine can either calc estimates beforehand or during departure (using information of drt router)
@Test
void testRealisticEstimator() {
URL url = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_drt_config.xml");
Config config = ConfigUtils.loadConfig(url, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(), new OTFVisConfigGroup());
config.network().setInputFile("network.xml");
config.plans().setInputFile("plans_only_drt_1.0.xml.gz");
config.controller().setOutputDirectory(utils.getOutputDirectory());
config.controller().setLastIteration(3);

// install the drt routing stuff, but not the mobsim stuff!
Controler controler = DrtControlerCreator.createControler(config, false);
DrtConfigGroup drtConfigGroup = DrtConfigGroup.getSingleModeDrtConfig(config);
drtConfigGroup.maxTravelTimeAlpha = 1.2;
drtConfigGroup.maxTravelTimeBeta = 600;
drtConfigGroup.maxWaitTime = 300;
drtConfigGroup.simulationType = DrtConfigGroup.SimulationType.estimateAndTeleport;

// alternative: implement our own router
// do nothing drt specific -> calculate travel time information during routing
// can use standard teleportation engines given route information
// we need to update routes ourself, we have no drt access egress, no waiting times, no drt output or requests
// this would be more general, could be useful for other use cases?
// but we only need it for DRT for now?
DrtFareParams fareParams = new DrtFareParams();
fareParams.baseFare = 1.0;
fareParams.distanceFare_m = 0.001;
drtConfigGroup.addParameterSet(fareParams);

controler.run();
controler.addOverridingModule(new AbstractDvrpModeModule(drtConfigGroup.mode) {
@Override
public void install() {
bindModal(DrtEstimator.class).toInstance(new RealisticDrtEstimator(
new RealisticDrtEstimator.DistributionGenerator(1.2, 150, 0.1, 180, 0.2)));
}
});

System.out.println(config);
controler.run();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.matsim.contrib.drt.teleportation;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.contrib.drt.estimator.DrtEstimator;
import org.matsim.contrib.drt.estimator.impl.PessimisticDrtEstimator;
import org.matsim.contrib.drt.estimator.impl.RealisticDrtEstimator;
import org.matsim.contrib.drt.fare.DrtFareParams;
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.contrib.drt.run.DrtControlerCreator;
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.config.groups.ReplanningConfigGroup;
import org.matsim.core.config.groups.ScoringConfigGroup;
import org.matsim.core.controler.Controler;
import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule;
import org.matsim.core.utils.io.IOUtils;
import org.matsim.examples.ExamplesUtils;
import org.matsim.testcases.MatsimTestUtils;
import org.matsim.vis.otfvis.OTFVisConfigGroup;

import java.net.URL;

public class DrtTeleportationWithModeChoiceTest {

@RegisterExtension
public MatsimTestUtils utils = new MatsimTestUtils();

@Test
void testModeChoice() {
URL url = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_drt_config.xml");
Config config = ConfigUtils.loadConfig(url, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(), new OTFVisConfigGroup());
config.network().setInputFile("network.xml");
config.plans().setInputFile("plans_only_drt_4.0.xml.gz");
config.controller().setOutputDirectory(utils.getOutputDirectory());
config.controller().setLastIteration(100);

config.replanning().setFractionOfIterationsToDisableInnovation(0.8);
config.replanning().setMaxAgentPlanMemorySize(3);
config.replanning().clearStrategySettings();

ReplanningConfigGroup.StrategySettings changeSingleTripMode = new ReplanningConfigGroup.StrategySettings();
changeSingleTripMode.setStrategyName(DefaultPlanStrategiesModule.DefaultStrategy.ChangeSingleTripMode);
changeSingleTripMode.setWeight(0.1);
config.replanning().addStrategySettings(changeSingleTripMode);

ReplanningConfigGroup.StrategySettings changeExpBeta = new ReplanningConfigGroup.StrategySettings();
changeExpBeta.setStrategyName(DefaultPlanStrategiesModule.DefaultSelector.ChangeExpBeta);
changeExpBeta.setWeight(0.9);
config.replanning().addStrategySettings(changeExpBeta);

// Introduce a dummy alternative mode: bike (also teleported)
ScoringConfigGroup.ModeParams bikeModeParams = new ScoringConfigGroup.ModeParams(TransportMode.bike);
bikeModeParams.setConstant(1.);
bikeModeParams.setMarginalUtilityOfTraveling(-6.);
config.scoring().addModeParams(bikeModeParams);

// Update change mode
config.changeMode().setModes( new String[] { TransportMode.drt, TransportMode.bike });

Controler controler = DrtControlerCreator.createControler(config, false);
DrtConfigGroup drtConfigGroup = DrtConfigGroup.getSingleModeDrtConfig(config);
drtConfigGroup.maxTravelTimeAlpha = 1.1;
drtConfigGroup.maxTravelTimeBeta = 200;
drtConfigGroup.maxWaitTime = 180;
drtConfigGroup.simulationType = DrtConfigGroup.SimulationType.estimateAndTeleport;

controler.addOverridingModule(new AbstractDvrpModeModule(drtConfigGroup.mode) {
@Override
public void install() {
bindModal(DrtEstimator.class).toInstance(new RealisticDrtEstimator(
new RealisticDrtEstimator.DistributionGenerator(1.2, 200,
0.2, 180, 0.3)));
}

// public void install() {
// bindModal(DrtEstimator.class).toInstance(new PessimisticDrtEstimator(drtConfigGroup));
// }
});

System.out.println(config);
controler.run();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ private Iterable<Number> calcMetrics(int iteration) {

waitTime.addValue(Math.abs(estimate.waitingTime() - valWaitTime));
travelTime.addValue(Math.abs(estimate.rideTime() - valTravelTime));
fare.addValue(Math.abs(estimate.fare() - valFare));
// TODO add fare estimator?
// fare.addValue(Math.abs(estimate.fare() - valFare));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,20 @@ public interface DrtEstimator extends ControlerListener {
* @param rideDistance travel distance in meter
* @param rideTime ride time in seconds
* @param waitingTime waiting time in seconds
* @param fare money, which is negative if the customer needs to pay it
// * @param fare money, which is negative if the customer needs to pay it
* @param rejectionRate probability of a trip being rejected
*/
record Estimate(double rideDistance, double rideTime, double waitingTime, double fare, double rejectionRate) {
record Estimate(double rideDistance, double rideTime, double waitingTime, double rejectionRate) {

}

/**
* Write estimate information into the leg attributes.
*/
static void setEstimateAttributes(Leg leg, Estimate estimate) {
leg.getAttributes().putAttribute("ride_time", estimate.rideTime());
leg.getAttributes().putAttribute("ride_distance", estimate.rideDistance());
leg.getAttributes().putAttribute("wait_time", estimate.waitingTime());
// TODO: fare might not be needed
leg.getAttributes().putAttribute("fare", estimate.fare());
leg.getAttributes().putAttribute("est_ride_time", estimate.rideTime());
leg.getAttributes().putAttribute("est_ride_distance", estimate.rideDistance());
leg.getAttributes().putAttribute("est_wait_time", estimate.waitingTime());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ public class BasicDrtEstimator implements DrtOnlineEstimator, IterationEndsListe
* Currently valid estimates.
*/
private GlobalEstimate currentEst;
private RegressionResults fare;

public BasicDrtEstimator(DrtEventSequenceCollector collector, DrtEstimator initial,
DrtEstimatorParams config, DrtConfigGroup drtConfig) {
Expand Down Expand Up @@ -92,8 +91,6 @@ public void notifyIterationEnds(IterationEndsEvent event) {
if (n <= 3)
return;

fare = est.fare.regress();

double rejectionRate = (double) nRejections / nSubmitted;

if (currentEst == null) {
Expand Down Expand Up @@ -122,18 +119,10 @@ public Estimate estimate(DrtRoute route, OptionalTime departureTime) {
return initial.estimate(route, departureTime);
}

double fare = 0;
if (this.fare != null)
fare = this.fare.getParameterEstimate(0) + this.fare.getParameterEstimate(1) * route.getDistance();

if (drtConfig.getDrtFareParams().isPresent()) {
fare = Math.max(fare, drtConfig.getDrtFareParams().get().minFarePerTrip);
}

double detour = Math.max(1, rnd.nextGaussian(currentEst.meanDetour, config.randomization * currentEst.stdDetour));
double waitTime = Math.max(0, rnd.nextGaussian(currentEst.meanWait, config.randomization * currentEst.stdWait));

return new Estimate(route.getDistance() * detour, route.getDirectRideTime() * detour, waitTime, fare, currentEst.rejectionRate);
return new Estimate(route.getDistance() * detour, route.getDirectRideTime() * detour, waitTime, currentEst.rejectionRate);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.matsim.contrib.drt.estimator.impl;

import org.matsim.contrib.drt.estimator.DrtEstimator;
import org.matsim.contrib.drt.fare.DrtFareParams;
import org.matsim.contrib.drt.routing.DrtRoute;
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.core.utils.misc.OptionalTime;
Expand Down Expand Up @@ -31,20 +30,8 @@ public ConstantDrtEstimator(DrtConfigGroup drtConfig, double detourFactor, doubl

@Override
public Estimate estimate(DrtRoute route, OptionalTime departureTime) {

double distance = route.getDistance() * detourFactor;
double travelTime = route.getDirectRideTime() * detourFactor;

double fare = 0;
if (drtConfig.getDrtFareParams().isPresent()) {
DrtFareParams fareParams = drtConfig.getDrtFareParams().get();
fare = fareParams.distanceFare_m * distance
+ fareParams.timeFare_h * travelTime / 3600.0
+ fareParams.baseFare;

fare = Math.max(fare, fareParams.minFarePerTrip);
}

return new Estimate(distance, travelTime, waitingTime, fare, 0);
return new Estimate(distance, travelTime, waitingTime, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public Estimate estimate(DrtRoute route, OptionalTime departureTime) {
}

// for distance, also use the max travel time alpha
return new Estimate(route.getDistance() * drtConfig.maxTravelTimeAlpha, travelTime, drtConfig.maxWaitTime, fare, 0);
return new Estimate(route.getDistance() * drtConfig.maxTravelTimeAlpha, travelTime, drtConfig.maxWaitTime, 0);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public Estimate estimate(DrtRoute route, OptionalTime departureTime) {
double rideDistance = distributionGenerator.generateRideDistance(rideTime, directRideTIme, directDistance);
double acceptanceRate = distributionGenerator.generateAcceptanceRate();

return new Estimate(rideDistance, waitTime + rideTime, waitTime, 0, acceptanceRate);
return new Estimate(rideDistance, waitTime + rideTime, waitTime, acceptanceRate);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import org.matsim.api.core.v01.population.Leg;
import org.matsim.api.core.v01.population.Person;
import org.matsim.api.core.v01.population.Population;
import org.matsim.api.core.v01.population.Route;
import org.matsim.contrib.drt.estimator.DrtEstimator;
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.contrib.dvrp.router.DefaultMainLegRouter.RouteCreator;
import org.matsim.contrib.util.ExecutorServiceWithResource;
Expand All @@ -50,13 +52,15 @@ public class DefaultDrtRouteUpdater implements ShutdownListener, DrtRouteUpdater
private final DrtConfigGroup drtCfg;
private final Network network;
private final Population population;
private final DrtEstimator drtEstimator;
private final ExecutorServiceWithResource<? extends RouteCreator> executorService;

public DefaultDrtRouteUpdater(DrtConfigGroup drtCfg, Network network, Population population, Config config,
Supplier<RouteCreator> drtRouteCreatorSupplier) {
Supplier<RouteCreator> drtRouteCreatorSupplier, DrtEstimator drtEstimator) {
this.drtCfg = drtCfg;
this.network = network;
this.population = population;
this.drtEstimator = drtEstimator;

// XXX uses the global.numberOfThreads, not drt.numberOfThreads, as this is executed in the replanning phase
executorService = new ExecutorServiceWithResource<>(IntStream.range(0, config.global().getNumberOfThreads())
Expand Down Expand Up @@ -86,8 +90,16 @@ private void updateDrtRoute(RouteCreator drtRouteCreator, Person person, Attribu
Link fromLink = network.getLinks().get(drtLeg.getRoute().getStartLinkId());
Link toLink = network.getLinks().get(drtLeg.getRoute().getEndLinkId());
RouteFactories routeFactories = population.getFactory().getRouteFactories();
drtLeg.setRoute(drtRouteCreator.createRoute(drtLeg.getDepartureTime().seconds(), fromLink, toLink, person,
tripAttributes, routeFactories));

Route drtRoute = drtRouteCreator.createRoute(drtLeg.getDepartureTime().seconds(), fromLink, toLink, person,
tripAttributes, routeFactories);
drtLeg.setRoute(drtRoute);

// update DRT estimate
if (drtEstimator != null) {
DrtEstimator.Estimate estimate = drtEstimator.estimate((DrtRoute) drtRoute, drtLeg.getDepartureTime());
DrtEstimator.setEstimateAttributes(drtLeg, estimate);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Population;
import org.matsim.contrib.drt.estimator.DrtEstimator;
import org.matsim.contrib.drt.estimator.EstimationRoutingModuleProvider;
import org.matsim.contrib.drt.routing.DefaultDrtRouteUpdater;
import org.matsim.contrib.drt.routing.DrtRouteCreator;
Expand Down Expand Up @@ -124,7 +125,9 @@ public void install() {
public DefaultDrtRouteUpdater get() {
var network = getModalInstance(Network.class);
var routeCreatorProvider = getModalProvider(DefaultMainLegRouter.RouteCreator.class);
return new DefaultDrtRouteUpdater(drtCfg, network, population, config, routeCreatorProvider::get);
DrtEstimator drtEstimator = drtCfg.simulationType == DrtConfigGroup.SimulationType.estimateAndTeleport?
getModalInstance(DrtEstimator.class) : null;
return new DefaultDrtRouteUpdater(drtCfg, network, population, config, routeCreatorProvider::get, drtEstimator);
}
}).asEagerSingleton();

Expand Down
Loading

0 comments on commit 0bd74b0

Please sign in to comment.