-
Notifications
You must be signed in to change notification settings - Fork 452
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/freight_eventsReaderTest' into f…
…reight_eventsReaderTest
- Loading branch information
Showing
61 changed files
with
2,864 additions
and
1,467 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1,121 changes: 561 additions & 560 deletions
1,121
...decongestion/src/test/java/org/matsim/contrib/decongestion/DecongestionPricingTestIT.java
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
172 changes: 172 additions & 0 deletions
172
...xtensions/src/main/java/org/matsim/contrib/drt/extension/estimator/BasicDrtEstimator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
package org.matsim.contrib.drt.extension.estimator; | ||
|
||
import org.apache.commons.math3.stat.descriptive.SummaryStatistics; | ||
import org.apache.commons.math3.stat.regression.RegressionResults; | ||
import org.apache.commons.math3.stat.regression.SimpleRegression; | ||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.matsim.api.core.v01.events.PersonMoneyEvent; | ||
import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; | ||
import org.matsim.contrib.drt.extension.estimator.run.DrtEstimatorConfigGroup; | ||
import org.matsim.contrib.drt.fare.DrtFareParams; | ||
import org.matsim.contrib.drt.routing.DrtRoute; | ||
import org.matsim.contrib.drt.run.DrtConfigGroup; | ||
import org.matsim.contrib.drt.speedup.DrtSpeedUp; | ||
import org.matsim.core.controler.events.IterationEndsEvent; | ||
import org.matsim.core.controler.listener.IterationEndsListener; | ||
import org.matsim.core.utils.misc.OptionalTime; | ||
|
||
import java.util.SplittableRandom; | ||
|
||
/** | ||
* Estimates drt trips based only daily averages. No spatial or temporal differentiation is taken into account for the estimate. | ||
* This estimator is suited for small scenarios with few vehicles and trips and consequently few data points. | ||
*/ | ||
public class BasicDrtEstimator implements DrtEstimator, IterationEndsListener { | ||
|
||
private static final Logger log = LogManager.getLogger(BasicDrtEstimator.class); | ||
|
||
private final DrtEventSequenceCollector collector; | ||
private final DrtEstimatorConfigGroup config; | ||
private final DrtConfigGroup drtConfig; | ||
|
||
private final SplittableRandom rnd = new SplittableRandom(); | ||
/** | ||
* Currently valid estimates. | ||
*/ | ||
private GlobalEstimate currentEst; | ||
private RegressionResults fare; | ||
|
||
public BasicDrtEstimator(DrtEventSequenceCollector collector, DrtEstimatorConfigGroup config, | ||
DrtConfigGroup drtConfig) { | ||
//zones = injector.getModal(DrtZonalSystem.class); | ||
this.collector = collector; | ||
this.config = config; | ||
this.drtConfig = drtConfig; | ||
} | ||
|
||
@Override | ||
public void notifyIterationEnds(IterationEndsEvent event) { | ||
|
||
// Speed-up iteration need to be ignored for the estimates | ||
if (drtConfig.getDrtSpeedUpParams().isPresent() && | ||
DrtSpeedUp.isTeleportDrtUsers(drtConfig.getDrtSpeedUpParams().get(), | ||
event.getServices().getConfig().controller(), event.getIteration())) { | ||
return; | ||
} | ||
|
||
GlobalEstimate est = new GlobalEstimate(); | ||
|
||
int n = 0; | ||
|
||
int nRejections = collector.getRejectedRequestSequences().size(); | ||
int nSubmitted = collector.getRequestSubmissions().size(); | ||
|
||
for (DrtEventSequenceCollector.EventSequence seq : collector.getPerformedRequestSequences().values()) { | ||
|
||
if (seq.getPickedUp().isPresent() && seq.getDroppedOff().isPresent()) { | ||
|
||
double waitTime = seq.getPickedUp().get().getTime() - seq.getSubmitted().getTime(); | ||
est.waitTime.addValue(waitTime); | ||
|
||
double unsharedTime = seq.getSubmitted().getUnsharedRideTime(); | ||
double travelTime = seq.getDroppedOff().get().getTime() - seq.getPickedUp().get().getTime(); | ||
|
||
est.detour.addValue(travelTime / unsharedTime); | ||
|
||
double fare = seq.getDrtFares().stream().mapToDouble(PersonMoneyEvent::getAmount).sum(); | ||
est.fare.addData(seq.getSubmitted().getUnsharedRideDistance(), fare); | ||
n++; | ||
} | ||
} | ||
|
||
// At least some data points are required | ||
if (n <= 3) | ||
return; | ||
|
||
fare = est.fare.regress(); | ||
|
||
double rejectionRate = (double) nRejections / nSubmitted; | ||
|
||
if (currentEst == null) { | ||
est.meanWait = est.waitTime.getMean(); | ||
est.stdWait = est.waitTime.getStandardDeviation(); | ||
est.meanDetour = est.detour.getMean(); | ||
est.stdDetour = est.detour.getStandardDeviation(); | ||
est.rejectionRate = rejectionRate; | ||
} else { | ||
est.meanWait = config.decayFactor * est.waitTime.getMean() + (1 - config.decayFactor) * currentEst.waitTime.getMean(); | ||
est.stdWait = config.decayFactor * est.waitTime.getStandardDeviation() + (1 - config.decayFactor) * currentEst.waitTime.getStandardDeviation(); | ||
est.meanDetour = config.decayFactor * est.detour.getMean() + (1 - config.decayFactor) * currentEst.detour.getMean(); | ||
est.stdDetour = config.decayFactor * est.detour.getStandardDeviation() + (1 - config.decayFactor) * currentEst.detour.getStandardDeviation(); | ||
est.rejectionRate = config.decayFactor * rejectionRate + (1 - config.decayFactor) * currentEst.rejectionRate; | ||
} | ||
|
||
log.info("Calculated {}", est); | ||
currentEst = est; | ||
} | ||
|
||
@Override | ||
public Estimate estimate(DrtRoute route, OptionalTime departureTime) { | ||
|
||
if (currentEst == null) { | ||
// If not estimates are present, use travel time alpha as detour | ||
// beta is not used, because estimates are supposed to be minimums and not worst cases | ||
double travelTime = Math.min(route.getDirectRideTime() + drtConfig.maxAbsoluteDetour, | ||
route.getDirectRideTime() * drtConfig.maxTravelTimeAlpha); | ||
|
||
double fare = 0; | ||
if (drtConfig.getDrtFareParams().isPresent()) { | ||
DrtFareParams fareParams = drtConfig.getDrtFareParams().get(); | ||
fare = fareParams.distanceFare_m * route.getDistance() | ||
+ fareParams.timeFare_h * route.getDirectRideTime() / 3600.0 | ||
+ fareParams.baseFare; | ||
|
||
fare = Math.max(fare, fareParams.minFarePerTrip); | ||
} | ||
|
||
// for distance, also use the max travel time alpha | ||
return new Estimate(route.getDistance() * drtConfig.maxTravelTimeAlpha, travelTime, drtConfig.maxWaitTime, fare, 0); | ||
} | ||
|
||
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); | ||
} | ||
|
||
/** | ||
* Helper class to hold statistics. | ||
*/ | ||
private static final class GlobalEstimate { | ||
|
||
private final SummaryStatistics waitTime = new SummaryStatistics(); | ||
private final SummaryStatistics detour = new SummaryStatistics(); | ||
private final SimpleRegression fare = new SimpleRegression(true); | ||
|
||
private double meanWait; | ||
private double stdWait; | ||
private double meanDetour; | ||
private double stdDetour; | ||
private double rejectionRate; | ||
|
||
@Override | ||
public String toString() { | ||
return "GlobalEstimate{" + | ||
"meanWait=" + meanWait + | ||
", stdWait=" + stdWait + | ||
", meanDetour=" + meanDetour + | ||
", stdDetour=" + stdDetour + | ||
", rejectionRate=" + rejectionRate + | ||
'}'; | ||
} | ||
} | ||
} |
126 changes: 126 additions & 0 deletions
126
...ensions/src/main/java/org/matsim/contrib/drt/extension/estimator/DrtEstimateAnalyzer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package org.matsim.contrib.drt.extension.estimator; | ||
|
||
import org.apache.commons.csv.CSVFormat; | ||
import org.apache.commons.csv.CSVPrinter; | ||
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; | ||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.matsim.api.core.v01.events.PersonMoneyEvent; | ||
import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; | ||
import org.matsim.contrib.drt.extension.estimator.run.DrtEstimatorConfigGroup; | ||
import org.matsim.contrib.drt.routing.DrtRoute; | ||
import org.matsim.core.controler.events.AfterMobsimEvent; | ||
import org.matsim.core.controler.events.ShutdownEvent; | ||
import org.matsim.core.controler.events.StartupEvent; | ||
import org.matsim.core.controler.listener.AfterMobsimListener; | ||
import org.matsim.core.controler.listener.ShutdownListener; | ||
import org.matsim.core.controler.listener.StartupListener; | ||
import org.matsim.core.utils.misc.OptionalTime; | ||
|
||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.List; | ||
|
||
/** | ||
* Analyzes and outputs drt estimates errors metrics based on daily requests. | ||
*/ | ||
public final class DrtEstimateAnalyzer implements StartupListener, ShutdownListener, AfterMobsimListener { | ||
|
||
private static final Logger log = LogManager.getLogger(DrtEstimateAnalyzer.class); | ||
|
||
// Might be useful but not needed currently | ||
//private final DefaultMainLegRouter.RouteCreator creator; | ||
private final DrtEstimator estimator; | ||
private final DrtEventSequenceCollector collector; | ||
private final DrtEstimatorConfigGroup config; | ||
|
||
private CSVPrinter csv; | ||
|
||
public DrtEstimateAnalyzer(DrtEstimator estimator, DrtEventSequenceCollector collector, DrtEstimatorConfigGroup config) { | ||
this.estimator = estimator; | ||
this.collector = collector; | ||
this.config = config; | ||
} | ||
|
||
@Override | ||
public void notifyStartup(StartupEvent event) { | ||
|
||
String filename = event.getServices().getControlerIO().getOutputFilename("drt_estimates_" + config.getMode() + ".csv"); | ||
|
||
try { | ||
csv = new CSVPrinter(Files.newBufferedWriter(Path.of(filename), StandardCharsets.UTF_8), CSVFormat.DEFAULT); | ||
csv.printRecord("iteration", | ||
"wait_time_mae", "wait_time_err_q5", "wait_time_err_q50", "wait_time_err_q95", | ||
"travel_time_mae", "travel_time_err_q5", "travel_time_err_q50", "travel_time_err_q95", | ||
"fare_mae", "fare_err_q5", "fare_err_q50", "fare_err_q95" | ||
); | ||
|
||
} catch (IOException e) { | ||
throw new UncheckedIOException("Could not open output file for estimates.", e); | ||
} | ||
} | ||
|
||
@Override | ||
public void notifyShutdown(ShutdownEvent event) { | ||
try { | ||
csv.close(); | ||
} catch (IOException e) { | ||
log.warn("Could not close drt estimate file", e); | ||
} | ||
} | ||
|
||
/** | ||
* Needs to run before any estimators updates. | ||
*/ | ||
@Override | ||
public void notifyAfterMobsim(AfterMobsimEvent event) { | ||
|
||
try { | ||
csv.printRecord(calcMetrics(event.getIteration())); | ||
csv.flush(); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
/** | ||
* Return row of metrics for the csv file. | ||
*/ | ||
private Iterable<Number> calcMetrics(int iteration) { | ||
|
||
DescriptiveStatistics waitTime = new DescriptiveStatistics(); | ||
DescriptiveStatistics travelTime = new DescriptiveStatistics(); | ||
DescriptiveStatistics fare = new DescriptiveStatistics(); | ||
|
||
for (DrtEventSequenceCollector.EventSequence seq : collector.getPerformedRequestSequences().values()) { | ||
if (seq.getPickedUp().isPresent() && seq.getDroppedOff().isPresent()) { | ||
|
||
// many attributes are not filled, when using the constructor | ||
DrtRoute route = new DrtRoute(seq.getSubmitted().getFromLinkId(), seq.getSubmitted().getToLinkId()); | ||
route.setDirectRideTime(seq.getSubmitted().getUnsharedRideTime()); | ||
route.setDistance(seq.getSubmitted().getUnsharedRideDistance()); | ||
|
||
double valWaitTime = seq.getPickedUp().get().getTime() - seq.getSubmitted().getTime(); | ||
double valTravelTime = seq.getDroppedOff().get().getTime() - seq.getPickedUp().get().getTime(); | ||
double valFare = seq.getDrtFares().stream().mapToDouble(PersonMoneyEvent::getAmount).sum(); | ||
|
||
DrtEstimator.Estimate estimate = estimator.estimate(route, OptionalTime.defined(seq.getSubmitted().getTime())); | ||
|
||
waitTime.addValue(Math.abs(estimate.waitingTime() - valWaitTime)); | ||
travelTime.addValue(Math.abs(estimate.travelTime() - valTravelTime)); | ||
fare.addValue(Math.abs(estimate.fare() - valFare)); | ||
} | ||
} | ||
|
||
return List.of( | ||
iteration, | ||
waitTime.getMean(), waitTime.getPercentile(5), waitTime.getPercentile(50), waitTime.getPercentile(95), | ||
travelTime.getMean(), travelTime.getPercentile(5), travelTime.getPercentile(50), travelTime.getPercentile(95), | ||
fare.getMean(), fare.getPercentile(5), fare.getPercentile(50), fare.getPercentile(95) | ||
); | ||
} | ||
|
||
} |
Oops, something went wrong.