Commit 3dc7b0bf authored by Sebastian Hörl's avatar Sebastian Hörl
Browse files

Distribute costs over taxi and pooled

parent 929bcaf8
......@@ -12,7 +12,7 @@ public class SharedAVConfigGroup extends ReflectiveConfigGroup {
private final static String POOLED_FLEET_SIZE = "pooledFleetSize";
private final static String MINIMUM_TRIP_DISTANCE_KM = "minimumTripDistance_km";
private final static String POOLING_THRESHOLD_MIN = "poolingThreadol_min";
private final static String POOLING_THRESHOLD_MIN = "poolingThreshold_min";
private final static String SERVICE_AREA_ATTRIBUTE = "serviceAreaAttribute";
private final static String ACTIVE_SERVICE_AREA = "activeServiceArea";
......@@ -24,6 +24,7 @@ public class SharedAVConfigGroup extends ReflectiveConfigGroup {
private final static String COST_CALCULATOR_SCALING_FACTOR = "costCalculatorScalingFactor";
private final static String COST_CALCULATOR_HORIZON = "costCalculatorHorizon";
private final static String COST_CALCULATOR_INITIAL_PRICE = "costCalculatorInitialPrice";
private final static String DISTRIBUTE_COSTS = "distributeCosts";
private final static String WAITING_TIME_ESTIMATOR_START_TIME = "waitingTimeEstimatorStartTime";
private final static String WAITING_TIME_ESTIMATOR_END_TIME = "waitingTimeEstimatorEndTime";
......@@ -50,6 +51,7 @@ public class SharedAVConfigGroup extends ReflectiveConfigGroup {
private double costCalculatorScalingFactor = 1.0;
private int costCalculatorHorizon = 10;
private double costCalculatorInitialPrice = 0.4;
private boolean distributeCosts = true;
private double waitingTimeEstimatorStartTime = 6.0 * 3600.0;
private double waitingTimeEstimatorEndTime = 22.0 * 3600.0;
......@@ -201,6 +203,16 @@ public class SharedAVConfigGroup extends ReflectiveConfigGroup {
this.costCalculatorInitialPrice = costCalculatorInitialPrice;
}
@StringGetter(DISTRIBUTE_COSTS)
public boolean getDistributeCosts() {
return distributeCosts;
}
@StringSetter(DISTRIBUTE_COSTS)
public void setDistributeCosts(boolean distributeCosts) {
this.distributeCosts = distributeCosts;
}
@StringGetter(WAITING_TIME_ESTIMATOR_START_TIME)
public double getWaitingTimeEstimatorStartTime() {
return waitingTimeEstimatorStartTime;
......
......@@ -56,7 +56,9 @@ public class SharedAVModule extends AbstractDiscreteModeChoiceExtension {
public static final String WAITING_TIME_GROUP_ATTRIBUTE = "waitingTimeGroup";
public static final long POOLED_NUMBER_OF_SEATS = 4;
public static final String POOLED_COST_TYPE = "Midsize";
public static final String TAXI_CC_TYPE = "Solo";
public static final String POOLED_CC_TYPE = "Midsize";
@Override
protected void installExtension() {
......
......@@ -15,39 +15,50 @@ import org.matsim.core.controler.listener.IterationEndsListener;
import ch.ethz.matsim.av_cost_calculator.CostCalculatorExecutor;
import ch.ethz.matsim.av_cost_calculator.run.ParameterBuilder;
import ch.ethz.matsim.av_cost_calculator.run.PricingAnalysisHandler;
import ch.ethz.matsim.projects.astra_2018_002.shared_av.SharedAVModule;
public class AVPricingListener implements IterationEndsListener {
private final PricingAnalysisHandler handler;
private final PricingAnalysisHandler taxiHandler;
private final PricingAnalysisHandler pooledHandler;
private final CostCalculatorExecutor executor;
private final BufferedWriter writer;
private final double scenarioScale;
private final int horizon;
private List<Double> history = new LinkedList<>();
private List<Double> taxiHistory = new LinkedList<>();
private List<Double> pooledHistory = new LinkedList<>();
private List<Double> jointHistory = new LinkedList<>();
private final BufferedWriter writer;
private double activeTaxiPrice = 0.0;
private double activePooledPrice = 0.0;
private double activeJointPrice = 0.0;
private double activePrice = 0.0;
private final String taxiVehicleType = SharedAVModule.TAXI_CC_TYPE;
private final String pooledVehicleType = SharedAVModule.POOLED_CC_TYPE;
private final String vehicleType;
public AVPricingListener(String operator, String vehicleType, double scenarioScale, int horizon,
PricingAnalysisHandler handler, CostCalculatorExecutor executor, OutputDirectoryHierarchy output, double initialPrice)
throws IOException {
public AVPricingListener(double scenarioScale, int horizon, PricingAnalysisHandler taxiHandler,
PricingAnalysisHandler pooledHandler, CostCalculatorExecutor executor, OutputDirectoryHierarchy output,
double initialPrice) throws IOException {
this.scenarioScale = scenarioScale;
this.horizon = horizon;
this.handler = handler;
this.taxiHandler = taxiHandler;
this.pooledHandler = pooledHandler;
this.executor = executor;
this.vehicleType = vehicleType;
writer = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(output.getOutputFilename("prices_" + operator + ".csv"))));
writer.write("iteration;active_price;computed_price\n");
new OutputStreamWriter(new FileOutputStream(output.getOutputFilename("prices.csv"))));
writer.write(
"iteration;active_taxi_price;computed_taxi_price;active_pooled_price;computed_pooled_price;active_joint_price;computed_joint_price\n");
writer.flush();
for (int i = 0; i < horizon; i++) {
history.add(initialPrice);
taxiHistory.add(initialPrice);
pooledHistory.add(initialPrice);
jointHistory.add(initialPrice);
}
}
......@@ -55,26 +66,81 @@ public class AVPricingListener implements IterationEndsListener {
public void notifyIterationEnds(IterationEndsEvent event) {
double totalTime = 24.0 * 3600.0;
Map<String, String> parameters = new ParameterBuilder(scenarioScale, totalTime, vehicleType).build(handler);
double price = executor.computePricePerPassengerKm(parameters);
handler.resetHandler();
// Calculate taxi price
Map<String, String> taxiParameters = new ParameterBuilder(scenarioScale, totalTime, taxiVehicleType)
.build(taxiHandler);
double taxiPrice = executor.computePricePerPassengerKm(taxiParameters);
double taxiDistance = taxiHandler.getTotalPassengerDistance();
taxiHandler.resetHandler();
// Update taxi history
if (!Double.isNaN(taxiPrice)) {
taxiHistory.remove(0);
taxiHistory.add(taxiPrice);
}
activeTaxiPrice = taxiHistory.stream().mapToDouble(d -> d).sum() / (double) horizon;
// Calculate pooled price
Map<String, String> pooledParameters = new ParameterBuilder(scenarioScale, totalTime, pooledVehicleType)
.build(pooledHandler);
double pooledPrice = executor.computePricePerPassengerKm(pooledParameters);
double pooledDistance = pooledHandler.getTotalPassengerDistance();
pooledHandler.resetHandler();
// Update pooled history
if (!Double.isNaN(pooledPrice)) {
pooledHistory.remove(0);
pooledHistory.add(pooledPrice);
}
activePooledPrice = pooledHistory.stream().mapToDouble(d -> d).sum() / (double) horizon;
// Calculate joint price
double jointPrice = Double.NaN;
if (Double.isNaN(taxiPrice)) {
jointPrice = pooledPrice;
} else if (Double.isNaN(pooledPrice)) {
jointPrice = taxiPrice;
} else {
double totalDistance = taxiDistance + pooledDistance;
jointPrice = (taxiPrice * taxiDistance + pooledPrice * pooledDistance) / totalDistance;
}
if (!Double.isNaN(price)) {
history.remove(0);
history.add(price);
// Update joint history
if (!Double.isNaN(jointPrice)) {
jointHistory.remove(0);
jointHistory.add(jointPrice);
}
activePrice = history.stream().mapToDouble(d -> d).sum() / (double) horizon;
activeJointPrice = jointHistory.stream().mapToDouble(d -> d).sum() / (double) horizon;
// Write out result
try {
writer.write(String.format("%d;%f;%f\n", event.getIteration(), activePrice, price));
writer.write(String.format("%d;%f;%f;%f;%f;%f;%f\n", event.getIteration(), activeTaxiPrice, taxiPrice,
activePooledPrice, pooledPrice, activeJointPrice, jointPrice));
writer.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public double getPricePerKm() {
return activePrice;
public enum PriceType {
TAXI, POOLED, JOINT
}
public double getPricePerKm(PriceType priceType) {
switch (priceType) {
case JOINT:
return activeJointPrice;
case POOLED:
return activePooledPrice;
case TAXI:
return activeTaxiPrice;
default:
throw new IllegalStateException();
}
}
}
......@@ -37,29 +37,18 @@ public class AVPricingModule extends AbstractModule {
@Override
public void install() {
addEventHandlerBinding().to(Key.get(PricingAnalysisHandler.class, Names.named(SharedAVModule.AV_TAXI)));
addControlerListenerBinding().to(Key.get(AVPricingListener.class, Names.named(SharedAVModule.AV_TAXI)));
addEventHandlerBinding().to(Key.get(PricingAnalysisHandler.class, Names.named(SharedAVModule.AV_POOL)));
addControlerListenerBinding().to(Key.get(AVPricingListener.class, Names.named(SharedAVModule.AV_POOL)));
}
@Provides
@Singleton
@Named(SharedAVModule.AV_TAXI)
public AVPricingListener provideTaxiPricingListener(@Named(SharedAVModule.AV_TAXI) PricingAnalysisHandler handler,
CostCalculatorExecutor executor, OutputDirectoryHierarchy output, SharedAVConfigGroup savConfig)
throws IOException {
return new AVPricingListener(SharedAVModule.AV_TAXI, "Solo", scenarioScale, horizon, handler, executor, output,
savConfig.getCostCalculatorInitialPrice());
addControlerListenerBinding().to(AVPricingListener.class);
}
@Provides
@Singleton
@Named(SharedAVModule.AV_POOL)
public AVPricingListener providePoolPricingListener(@Named(SharedAVModule.AV_POOL) PricingAnalysisHandler handler,
CostCalculatorExecutor executor, OutputDirectoryHierarchy output, SharedAVConfigGroup savConfig)
throws IOException {
return new AVPricingListener(SharedAVModule.AV_POOL, SharedAVModule.POOLED_COST_TYPE, scenarioScale, horizon,
handler, executor, output, savConfig.getCostCalculatorInitialPrice());
public AVPricingListener provideAVPricingListener(@Named(SharedAVModule.AV_TAXI) PricingAnalysisHandler taxiHandler,
@Named(SharedAVModule.AV_POOL) PricingAnalysisHandler pooledHandler, CostCalculatorExecutor executor,
OutputDirectoryHierarchy output, SharedAVConfigGroup savConfig) throws IOException {
return new AVPricingListener(scenarioScale, horizon, taxiHandler, pooledHandler, executor, output,
savConfig.getCostCalculatorInitialPrice());
}
@Provides
......@@ -93,8 +82,7 @@ public class AVPricingModule extends AbstractModule {
@Singleton
@Provides
public SharedAVTravelCost provideTravelCost(@Named(SharedAVModule.AV_TAXI) AVPricingListener taxiListener,
@Named(SharedAVModule.AV_POOL) AVPricingListener pooledListener) {
return new OnlineSharedAVTravelCost(taxiListener, pooledListener);
public SharedAVTravelCost provideTravelCost(AVPricingListener pricingListener, SharedAVConfigGroup config) {
return new OnlineSharedAVTravelCost(pricingListener, config.getDistributeCosts());
}
}
package ch.ethz.matsim.projects.astra_2018_002.shared_av.pricing;
import ch.ethz.matsim.projects.astra_2018_002.shared_av.pricing.AVPricingListener.PriceType;
public class OnlineSharedAVTravelCost implements SharedAVTravelCost {
private final AVPricingListener taxiListener;
private final AVPricingListener pooledListener;
private final AVPricingListener pricingListener;
private final boolean isJoint;
public OnlineSharedAVTravelCost(AVPricingListener taxiListener, AVPricingListener pooledListener) {
this.taxiListener = taxiListener;
this.pooledListener = pooledListener;
public OnlineSharedAVTravelCost(AVPricingListener pricingListener, boolean isJoint) {
this.pricingListener = pricingListener;
this.isJoint = isJoint;
}
@Override
public double getTravelCost(double distance_km, boolean isPooled) {
if (isPooled) {
return pooledListener.getPricePerKm() * distance_km;
if (isJoint) {
return pricingListener.getPricePerKm(PriceType.JOINT);
} else if (isPooled) {
return pricingListener.getPricePerKm(PriceType.POOLED);
} else {
return taxiListener.getPricePerKm() * distance_km;
return pricingListener.getPricePerKm(PriceType.TAXI);
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment