Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/maven/com.fasterxml.jackson-jac…
Browse files Browse the repository at this point in the history
…kson-bom-2.17.1
  • Loading branch information
jfbischoff authored Jun 13, 2024
2 parents 24d54d3 + abbfc70 commit 3ee9596
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
package org.matsim.contrib.drt.extension.operations.shifts.analysis.efficiency;

import com.google.inject.Inject;
import jakarta.inject.Provider;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
Expand All @@ -27,7 +28,7 @@
import org.matsim.core.controler.listener.IterationEndsListener;
import org.matsim.core.utils.io.IOUtils;

import jakarta.inject.Provider;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
Expand All @@ -44,6 +45,10 @@ public final class ShiftEfficiencyAnalysisControlerListener implements Iteration
private final ShiftEfficiencyTracker shiftEfficiencyTracker;

private final String delimiter;
private final String runId;
private boolean headerWritten = false;
private static final String notAvailableString = "NA";


@Inject
public ShiftEfficiencyAnalysisControlerListener(DrtConfigGroup drtConfigGroup,
Expand All @@ -55,21 +60,65 @@ public ShiftEfficiencyAnalysisControlerListener(DrtConfigGroup drtConfigGroup,
this.drtShiftsSpecification = drtShiftsSpecification;
this.matsimServices = matsimServices;
this.delimiter = matsimServices.getConfig().global().getDefaultDelimiter();
this.runId = Optional.ofNullable(matsimServices.getConfig().controller().getRunId()).orElse(notAvailableString);
}

@Override
public void notifyIterationEnds(IterationEndsEvent event) {
int createGraphsInterval = event.getServices().getConfig().controller().getCreateGraphsInterval();
boolean createGraphs = createGraphsInterval >0 && event.getIteration() % createGraphsInterval == 0;

writeAndPlotShiftEfficiency(
shiftEfficiencyTracker.getCurrentRecord().getRevenueByShift(),
shiftEfficiencyTracker.getCurrentRecord().getRequestsByShift(),
shiftEfficiencyTracker.getCurrentRecord().getFinishedShifts(),
ShiftEfficiencyTracker.Record record = shiftEfficiencyTracker.getCurrentRecord();
writeAndPlotShiftEfficiency(
record.getRevenueByShift(),
record.getRequestsByShift(),
record.getFinishedShifts(),
filename(event, "shiftRevenue", ".png"),
filename(event, "shiftRidesPerVrh", ".png"),
filename(event, "shiftEfficiency", ".csv"),
createGraphs);

List<DrtShiftSpecification> finishedShifts = record.finishedShifts()
.keySet()
.stream()
.map(id -> drtShiftsSpecification.get().getShiftSpecifications().get(id))
.toList();

double earliestShiftStart = finishedShifts.stream().map(DrtShiftSpecification::getStartTime).mapToDouble(d -> d).min().orElse(Double.NaN);
double latestShiftEnd = finishedShifts.stream().map(DrtShiftSpecification::getEndTime).mapToDouble(d -> d).min().orElse(Double.NaN);

double numberOfShifts = finishedShifts.size();
double numberOfShiftHours = finishedShifts.
stream()
.map(s -> (s.getEndTime() - s.getStartTime()) - (s.getBreak().isPresent() ? s.getBreak().get().getDuration() : 0.))
.mapToDouble(d -> d)
.sum() / 3600.;

long uniqueVehicles = record.getFinishedShifts().values().stream().distinct().count();

double totalRevenue = record.revenueByShift().values().stream().mapToDouble(d -> d).sum();
double meanRevenuePerShift = record.revenueByShift().values().stream().mapToDouble(d -> d).average().orElse(Double.NaN);
double meanRevenuePerShiftHour = totalRevenue / numberOfShiftHours;

double totalRides = record.getRequestsByShift().values().stream().mapToDouble(List::size).sum();
double meanRidesPerShift = record.getRequestsByShift().values().stream().mapToDouble(List::size).average().orElse(Double.NaN);
double meanRidesPerShiftHour = totalRides / numberOfShiftHours;

StringJoiner stringJoiner = new StringJoiner(delimiter);
stringJoiner
.add(earliestShiftStart + "")
.add(latestShiftEnd + "")
.add(numberOfShifts + "")
.add(numberOfShiftHours + "")
.add(uniqueVehicles + "")
.add(meanRevenuePerShift + "")
.add(meanRevenuePerShiftHour + "")
.add(totalRevenue + "")
.add(meanRidesPerShift + "")
.add(meanRidesPerShiftHour + "")
.add(totalRides + "");
writeIterationShiftEfficiencyStats(stringJoiner.toString(), event.getIteration());

}

private void writeAndPlotShiftEfficiency(Map<Id<DrtShift>, Double> revenuePerShift,
Expand Down Expand Up @@ -129,6 +178,32 @@ private void writeAndPlotShiftEfficiency(Map<Id<DrtShift>, Double> revenuePerShi
}
}

private void writeIterationShiftEfficiencyStats(String summarizeShiftEfficiency, int it) {
try (var bw = getAppendingBufferedWriter("drt_shift_efficiency_metrics", ".csv")) {
if (!headerWritten) {
headerWritten = true;
StringJoiner stringJoiner = new StringJoiner(delimiter);
stringJoiner
.add("earliestShiftStart")
.add("latestShiftEnd")
.add("numberOfShifts")
.add("numberOfShiftHours")
.add("uniqueVehicles")
.add("meanRevenuePerShift")
.add("meanRevenuePerShiftHour")
.add("totalRevenue")
.add("meanRidesPerShift")
.add("meanRidesPerShiftHour")
.add("totalRides");
bw.write(line("runId", "iteration", stringJoiner.toString()));
}
bw.write(runId + delimiter + it + delimiter + summarizeShiftEfficiency);
bw.newLine();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private String filename(IterationEndsEvent event, String prefix, String extension) {
return matsimServices.getControlerIO()
.getIterationFilename(event.getIteration(), prefix + "_" + drtConfigGroup.getMode() + extension);
Expand All @@ -137,4 +212,8 @@ private String filename(IterationEndsEvent event, String prefix, String extensio
private String line(Object... cells) {
return Arrays.stream(cells).map(Object::toString).collect(Collectors.joining(delimiter, "", "\n"));
}

private BufferedWriter getAppendingBufferedWriter(String prefix, String extension) {
return IOUtils.getAppendingBufferedWriter(matsimServices.getControlerIO().getOutputFilename(prefix + "_" + drtConfigGroup.getMode() + extension));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public final class ShiftEfficiencyTracker implements PersonMoneyEventHandler,

private Record currentRecord;

public static record Record(Map<Id<DrtShift>, Double> revenueByShift,
public record Record(Map<Id<DrtShift>, Double> revenueByShift,
Map<Id<Request>, Id<DrtShift>> shiftByRequest,
Map<Id<DrtShift>, Id<DvrpVehicle>> finishedShifts){
public Map<Id<DrtShift>, Double> getRevenueByShift() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.matsim.contrib.drt.extension.operations.DrtWithOperationsConfigGroup;
import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesParams;
import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams;
import org.matsim.contrib.drt.fare.DrtFareParams;
import org.matsim.contrib.drt.optimizer.DrtOptimizationConstraintsSet;
import org.matsim.contrib.drt.optimizer.insertion.extensive.ExtensiveInsertionSearchParams;
import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams;
Expand Down Expand Up @@ -142,6 +143,11 @@ void test() {
shiftsParams.allowInFieldChangeover = true;
drtWithShiftsConfigGroup.addParameterSet(operationsParams);

DrtFareParams drtFareParams = new DrtFareParams();
drtFareParams.baseFare = 1.;
drtFareParams.distanceFare_m = 1. / 1000;
drtWithShiftsConfigGroup.addParameterSet(drtFareParams);

final Controler run = DrtOperationsControlerCreator.createControler(config, false);
run.run();
}
Expand Down

0 comments on commit 3ee9596

Please sign in to comment.