Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
luchengqi7 committed Feb 26, 2024
1 parent baf3fa4 commit 19ddedf
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ void test1() {

DrtConfigGroup drtConfigGroup = DrtConfigGroup.getSingleModeDrtConfig(config);

drtConfigGroup.simulationType = DrtConfigGroup.SimulationType.estimateAndTeleport;

DrtEstimatorParams params = new DrtEstimatorParams();
params.teleport=true;
drtConfigGroup.addParameterSet(params);

System.out.println(config);
Expand All @@ -68,90 +69,7 @@ void test1() {
// this would be more general, could be useful for other use cases?
// but we only need it for DRT for now?

/*
controler.addOverridingModule( new AbstractModule(){
@Override public void install(){
this.addRoutingModuleBinding( "drt" ).to( DrtEstimatingRoutingModule.class );
}
} );
*/

controler.run();

}


public record EstimatedDrtTeleportationInfo(double estTotalTravelTime, double estWaitTime, double estRideTime, double estRideDistance) {
// The teleportation info refers to the main DRT leg (accessLink -> egressLink, departing at departureTime)
// The info teleportation engine can make use of this data to generate a teleport leg
// wait time and ride time are specified, such that we can score them differently (if required)
}

public record DrtRouteInfoEstimator(LeastCostPathCalculator router, TravelTime travelTime, DistributionGenerator distributionGenerator) {
// This record/class is to be created before (each?) MobSim/QSim.
public EstimatedDrtTeleportationInfo estimateDrtRoute(Link accessLink, Link egressLink, double departureTime) {
double waitTime = distributionGenerator.generateWaitTime();
double directRideTime = VrpPaths.calcAndCreatePath(accessLink, egressLink, departureTime + waitTime, router, travelTime).getTravelTime();
double rideTime = distributionGenerator.generateRideTime(directRideTime);

// since VrpPath does not contain Path information. We need to calculate this manually.
// VRP path logic: toNode of fromLink -> fromNode of toLink -> toNode of toLink
LeastCostPathCalculator.Path path = router.calcLeastCostPath(accessLink.getToNode(), egressLink.getFromNode(),
departureTime + waitTime, null, null);
path.links.add(egressLink);

double directRideDistance = path.links.stream().mapToDouble(Link::getLength).sum();
double rideDistance = distributionGenerator.generateRideDistance(rideTime, directRideTime, directRideDistance);

return new EstimatedDrtTeleportationInfo(waitTime + rideTime, waitTime, rideTime, rideDistance);
}
}

public static class DistributionGenerator {
private final Random random = new Random(4711);
private final double estRideTimeAlpha;
private final double estRideTimeBeta;
private final double rideTimeStd;
private final double estMeanWaitTime;
private final double waitTimeStd;
private final double probabilityRejection;

public DistributionGenerator(double estRideTimeAlpha, double estRideTimeBeta, double rideTimeStd, double estMeanWaitTime,
double waitTimeStd, double probabilityRejection) {
this.estRideTimeAlpha = estRideTimeAlpha;
this.estRideTimeBeta = estRideTimeBeta;
this.rideTimeStd = rideTimeStd;
this.estMeanWaitTime = estMeanWaitTime;
this.waitTimeStd = waitTimeStd;
this.probabilityRejection = probabilityRejection;
}

public DistributionGenerator generateExampleDistributionGenerator() {
return new DistributionGenerator(1.5, 300, 0.2, 300, 0.4, 0.0);
}

public double generateRideTime(double directRideTime) {
// TODO improve this distribution
double estMeanRideTime = estRideTimeAlpha * directRideTime + estRideTimeBeta;
return Math.max(directRideTime, estMeanRideTime * (1 + random.nextGaussian() * rideTimeStd));
}

public double generateRideDistance(double estRideTime, double directRideTime, double directRideDistance) {
// TODO Currently, same ratio is used as in the ride time estimation; improve this distribution
double ratio = estRideTime / directRideTime;
return ratio * directRideDistance;
}

public double generateWaitTime() {
// TODO improve this distribution
return Math.max(estMeanWaitTime * (1 + random.nextGaussian() * waitTimeStd), 0);
}

public boolean generateIsTripAccepted() {
// TODO maybe incorporate this into the estimated wait time, ride time and ride distance
return random.nextDouble() >= probabilityRejection;
}
}


}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.matsim.contrib.drt.estimator;

import com.google.inject.Binder;
import com.google.inject.Singleton;
import com.google.inject.multibindings.MapBinder;
import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector;
Expand All @@ -9,6 +10,7 @@
import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule;
import org.matsim.contrib.dvrp.run.DvrpMode;
import org.matsim.contrib.dvrp.run.DvrpModes;
import org.matsim.core.modal.ModalProviders;

/**
* Main module that needs to be installed if any estimator is to be used.
Expand All @@ -24,24 +26,22 @@ public DrtEstimatorModule(String mode, DrtConfigGroup drtCfg, DrtEstimatorParams
this.params = params;
}

public static Object bindEstimator(Binder binder, String mode){

// TODO create helper method for binding

// DvrpMode key = DvrpModes.mode(mode);
// binder.bind(key)
// ModalProviders.createProvider(mode, DvrpModes::mode);
return null;
}

@Override
public void install() {

// try with default injections and overwrite
if (params.estimator == DrtEstimatorParams.EstimatorType.BASIC) {
bindModal(DrtEstimator.class).toProvider(modalProvider(
getter -> new BasicDrtEstimator(
getter.getModal(DrtEventSequenceCollector.class),
getter.getModal(DrtInitialEstimator.class),
params, drtCfg
)
)).in(Singleton.class);
} else if (params.estimator == DrtEstimatorParams.EstimatorType.INITIAL) {
bindModal(DrtEstimator.class).to(modalKey(DrtInitialEstimator.class));
}

// TODO decide how initial estimators are defined
bindModal(DrtInitialEstimator.class).toInstance(new PessimisticDrtEstimator(drtCfg));
bindModal(DrtEstimator.class).toInstance(new PessimisticDrtEstimator(drtCfg));

// DRT Estimators will be available as Map<DvrpMode, DrtEstimator>
MapBinder.newMapBinder(this.binder(), DvrpMode.class, DrtEstimator.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,12 @@

public class DrtEstimatorParams extends ReflectiveConfigGroup {

/**
* Type of estimator, which will be installed in {@link DrtEstimatorModule}.
*/
public enum EstimatorType {
BASIC,

/**
* Will use the bound initial estimator, without any updates.
*/
INITIAL,

/**
* Custom estimator, that needs to provided via binding.
*/
CUSTOM
}

public static final String SET_NAME = "estimator";

public DrtEstimatorParams() {
super(SET_NAME);
}

@Parameter
@Comment("Estimator typed to be used. In case of 'CUSTOM', guice bindings needs to be provided.")
@NotNull
public EstimatorType estimator = EstimatorType.BASIC;

@Parameter
@Comment("Decay of the exponential moving average.")
Expand All @@ -45,18 +24,5 @@ public DrtEstimatorParams() {
@PositiveOrZero
public double randomization = 0.1;

// TODO think about enum, or different place / name for this option
@Parameter
@Comment("Whether drt passengers should be teleported based on estimation")
@Deprecated
public boolean teleport = false;

/**
* Set estimator type and return same instance.
*/
public DrtEstimatorParams withEstimator(EstimatorType estimator) {
this.estimator = estimator;
return this;
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.matsim.contrib.drt.estimator;

import org.matsim.api.core.v01.population.Leg;
import org.matsim.api.core.v01.population.PlanElement;
import org.matsim.contrib.drt.routing.DrtRoute;
import org.matsim.contrib.dvrp.router.DvrpRoutingModule;
import org.matsim.core.router.RoutingModule;
import org.matsim.core.router.RoutingRequest;
Expand All @@ -12,16 +14,26 @@
* */
public class EstimationRoutingModule implements RoutingModule {
private final DvrpRoutingModule delegate;
private final DrtEstimator estimator;

public EstimationRoutingModule(DvrpRoutingModule delegate) {
public EstimationRoutingModule(DvrpRoutingModule delegate, DrtEstimator estimator) {
this.delegate = delegate;
this.estimator = estimator;
}

@Override
public List<? extends PlanElement> calcRoute(RoutingRequest request) {

List<? extends PlanElement> route = delegate.calcRoute(request);

Leg mainDrtLeg = (Leg) route.get(2);
DrtRoute drtRoute = (DrtRoute) mainDrtLeg.getRoute();
DrtEstimator.Estimate estimate = estimator.estimate(drtRoute, mainDrtLeg.getDepartureTime());

mainDrtLeg.getAttributes().putAttribute("travel_time", estimate.travelTime());
mainDrtLeg.getAttributes().putAttribute("travel_distance", estimate.distance());
mainDrtLeg.getAttributes().putAttribute("wait_time", estimate.waitingTime());

return route;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@
import java.util.Map;
import java.util.Objects;

/**
* @author Michal Maciejewski (michalm)
*/

public class EstimationRoutingModuleProvider extends ModalProviders.AbstractProvider<DvrpMode, EstimationRoutingModule> {

@Inject
Expand All @@ -48,6 +46,9 @@ public class EstimationRoutingModuleProvider extends ModalProviders.AbstractProv
@Inject
private TimeInterpretation timeInterpretation;

@Inject
private Map<DvrpMode, DrtEstimator> estimators;

public EstimationRoutingModuleProvider(String mode) {
super(mode, DvrpModes::mode);
}
Expand All @@ -63,6 +64,6 @@ public EstimationRoutingModule get() {

DvrpRoutingModule routingModule = new DvrpRoutingModule(mainRouter, accessRouter, egressRouter,
getModalInstance(DvrpRoutingModule.AccessEgressFacilityFinder.class), getMode(), timeInterpretation);
return new EstimationRoutingModule(routingModule);
return new EstimationRoutingModule(routingModule, estimators.get(DvrpModes.mode(getMode())));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.matsim.contrib.drt.estimator.impl;

import org.matsim.contrib.drt.estimator.DrtInitialEstimator;
import org.matsim.contrib.drt.routing.DrtRoute;
import org.matsim.core.utils.misc.OptionalTime;

import java.util.Random;

public class RealisticDrtEstimator implements DrtInitialEstimator {

private final DistributionGenerator distributionGenerator;

public RealisticDrtEstimator(DistributionGenerator distributionGenerator) {
this.distributionGenerator = distributionGenerator;
}

@Override
public Estimate estimate(DrtRoute route, OptionalTime departureTime) {
double directRideTIme = route.getDirectRideTime();
double directDistance = route.getDistance();
double waitTime = distributionGenerator.generateWaitTime();
double rideTime = distributionGenerator.generateRideTime(directRideTIme);
double rideDistance = distributionGenerator.generateRideDistance(rideTime, directRideTIme, directDistance);
double acceptanceRate = distributionGenerator.generateAcceptanceRate();

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


public static class DistributionGenerator {
private final Random random = new Random(4711);
private final double estRideTimeAlpha;
private final double estRideTimeBeta;
private final double rideTimeStd;
private final double estMeanWaitTime;
private final double waitTimeStd;

public DistributionGenerator(double estRideTimeAlpha, double estRideTimeBeta, double rideTimeStd, double estMeanWaitTime,
double waitTimeStd) {
this.estRideTimeAlpha = estRideTimeAlpha;
this.estRideTimeBeta = estRideTimeBeta;
this.rideTimeStd = rideTimeStd;
this.estMeanWaitTime = estMeanWaitTime;
this.waitTimeStd = waitTimeStd;
}

public DistributionGenerator generateExampleDistributionGenerator() {
return new DistributionGenerator(1.5, 300, 0.2, 300, 0.4);
}

public double generateRideTime(double directRideTime) {
// TODO improve this distribution
double estMeanRideTime = estRideTimeAlpha * directRideTime + estRideTimeBeta;
return Math.max(directRideTime, estMeanRideTime * (1 + random.nextGaussian() * rideTimeStd));
}

public double generateRideDistance(double estRideTime, double directRideTime, double directRideDistance) {
// TODO Currently, same ratio is used as in the ride time estimation; improve this distribution
double ratio = estRideTime / directRideTime;
return ratio * directRideDistance;
}

public double generateWaitTime() {
// TODO improve this distribution
return Math.max(estMeanWaitTime * (1 + random.nextGaussian() * waitTimeStd), 0);
}

public double generateAcceptanceRate() {
return random.nextDouble();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.units.qual.C;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystemParams;
import org.matsim.contrib.drt.estimator.DrtEstimatorParams;
Expand Down Expand Up @@ -217,6 +218,15 @@ public enum OperationalScheme {
@Comment("Store planned unshared drt route as a link sequence")
public boolean storeUnsharedPath = false; // If true, the planned unshared path is stored and exported in plans


public enum SimulationType {
fullSimulation, estimateAndTeleport
}

@Parameter
@Comment("Whether full simulation drt is employed")
public SimulationType simulationType = SimulationType.fullSimulation;

@NotNull
private DrtInsertionSearchParams drtInsertionSearchParams;

Expand Down Expand Up @@ -333,6 +343,9 @@ protected void checkConsistency(Config config) {
if (useModeFilteredSubnetwork) {
DvrpModeRoutingNetworkModule.checkUseModeFilteredSubnetworkAllowed(config, mode);
}


// TODO if we teleport we need to check if estimates are present
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,6 @@ public void install() {

if (drtCfg.getDrtEstimatorParams().isPresent()) {
install(new DrtEstimatorModule(getMode(), drtCfg, drtCfg.getDrtEstimatorParams().get()));

if (drtCfg.getDrtEstimatorParams().get().teleport) {
addRoutingModuleBinding(getMode()).toProvider(new EstimationRoutingModuleProvider(getMode()));// not singleton
}

}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ protected void configureQSim() {
boolean teleportSpeedup = drtCfg.getDrtSpeedUpParams().isPresent() && DrtSpeedUp.isTeleportDrtUsers(
drtCfg.getDrtSpeedUpParams().get(), getConfig().controller(), getIterationNumber());

boolean teleportEstimate = drtCfg.getDrtEstimatorParams().isPresent() && drtCfg.getDrtEstimatorParams().get().teleport;
boolean teleportEstimate = drtCfg.getDrtEstimatorParams().isPresent() && drtCfg.simulationType == DrtConfigGroup.SimulationType.estimateAndTeleport;

if (teleportSpeedup) {
install(new PassengerEngineQSimModule(getMode(),
Expand Down
Loading

0 comments on commit 19ddedf

Please sign in to comment.