diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigGroup.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigGroup.java index 69197bd..b547dda 100644 --- a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigGroup.java +++ b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigGroup.java @@ -1,10 +1,8 @@ package org.matsim.alonso_mora; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.function.Supplier; -import java.util.stream.Collectors; import org.matsim.alonso_mora.algorithm.assignment.CbcMpsAssignmentSolver; import org.matsim.alonso_mora.algorithm.assignment.GlpkMpsAssignmentSolver; @@ -20,21 +18,20 @@ import org.matsim.alonso_mora.travel_time.RoutingTravelTimeEstimator; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.util.ReflectiveConfigGroupWithConfigurableParameterSets; import org.matsim.core.config.Config; -import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ReflectiveConfigGroup; import com.google.common.base.Verify; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; /** * Config group for the dispatching extension of DRT including the algorithm by * Alonso-Mora et al. */ -public class AlonsoMoraConfigGroup extends ReflectiveConfigGroup { +public class AlonsoMoraConfigGroup extends ReflectiveConfigGroupWithConfigurableParameterSets { public final static String GROUP_NAME = "drtAlonsoMora"; public AlonsoMoraConfigGroup() { @@ -45,134 +42,32 @@ public AlonsoMoraConfigGroup() { } /* Integration */ - private final static String MODE = "mode"; - private final static String MODE_COMMENT = "The DRT mode that will use the Alonso-Mora algorithm"; - + @Parameter + @Comment("The DRT mode that will use the Alonso-Mora algorithm") @NotBlank - private String mode = "drt"; - - @StringGetter(MODE) - public String getMode() { - return mode; - } - - @StringSetter(MODE) - public void setMode(String value) { - this.mode = value; - } + public String mode = "drt"; /* General */ - private final static String LOGGING_INTERVAL = "loggingInterval"; - private final static String LOGGING_INTERVAL_COMMENT = "Frequency of logging current status of the dispatcher in [s]"; - - @PositiveOrZero - private double loggingInterval = 600; - - @StringGetter(LOGGING_INTERVAL) - public double getLoggingInterval() { - return loggingInterval; - } - - @StringSetter(LOGGING_INTERVAL) - public void setLoggingInterval(double value) { - this.loggingInterval = value; - } - - private final static String MAXIMUM_QUEUE_TIME = "maximumQueueTime"; - private final static String MAXIMUM_QUEUE_TIME_COMMENT = "Maximum time the request stays in the dispatching queue after its earliest departure time (submission without prebooking) in [s]. Note that this is capped by the latest pickup time. A value of zero means that requests need to be matched in the dispatching step that comes right after submission / earliest departure time."; - + @Parameter + @Comment("Frequency of logging current status of the dispatcher in [s]") @PositiveOrZero - private double maximumQueueTime = 0.0; - - @StringGetter(MAXIMUM_QUEUE_TIME) - public double getMaximumQueueTime() { - return maximumQueueTime; - } - - @StringSetter(MAXIMUM_QUEUE_TIME) - public void setMaximumQueueTime(double value) { - this.maximumQueueTime = value; - } - - private final static String MAXIMUM_GROUP_REQUEST_SIZE = "maximumGroupRequestSize"; - private final static String MAXIMUM_GROUP_REQUEST_SIZE_COMMENT = "For computational reasons, the implementation can group multiple individual requests with the same departure time and OD requirements into one aggregate request. This value defines the size limit for aggregation as large group requests may not fit in some vehicles (based on their capacity)."; - - @Positive - private int maximumGroupRequestSize = 6; - - @StringGetter(MAXIMUM_GROUP_REQUEST_SIZE) - public int getMaximumGroupRequestSize() { - return maximumGroupRequestSize; - } - - @StringSetter(MAXIMUM_GROUP_REQUEST_SIZE) - public void setMaximumGroupRequestSize(int value) { - this.maximumGroupRequestSize = value; - } - - private final static String USE_PLANNED_PICKUP_TIME = "usePlannedPickupTime"; - private final static String USE_PLANNED_PICKUP_TIME_COMMENT = "By default, the algorithm updates the latest pickup time for a request to the planned pickup time that has been calculated at the first assignment. Subsequent dispatching steps must adhere to that value. Using this flag, this functionality may be turned off."; - - private boolean usePlannedPickupTime = true; - - @StringGetter(USE_PLANNED_PICKUP_TIME) - public boolean getUsePlannedPickupTime() { - return usePlannedPickupTime; - } - - @StringSetter(USE_PLANNED_PICKUP_TIME) - public void setUsePlannedPickupTime(boolean value) { - this.usePlannedPickupTime = value; - } - - private final static String PLANNED_PICKUP_TIME_SLACK = "plannedPickupTimeSlack"; - private final static String PLANNED_PICKUP_TIME_SLACK_COMMENT = "See usePlannedPickupTime. When updating the required pickup time, the operator may add a little slack to provide a more pessimistic estimate. The value specified here is added to the planned pickup time on first assignment if usePlannedPickupTime is enabled."; + public double loggingInterval = 600; + @Parameter + @Comment("Maximum time the request stays in the dispatching queue after its earliest departure time (submission without prebooking) in [s]. Note that this is capped by the latest pickup time. A value of zero means that requests need to be matched in the dispatching step that comes right after submission / earliest departure time.") @PositiveOrZero - private double plannedPickupTimeSlack = 0; - - @StringGetter(PLANNED_PICKUP_TIME_SLACK) - public double getPlannedPickupTimeSlack() { - return plannedPickupTimeSlack; - } - - @StringSetter(PLANNED_PICKUP_TIME_SLACK) - public void setPlannedPickupTimeSlack(double value) { - this.plannedPickupTimeSlack = value; - } - - private final static String CHECK_DETERMINISTIC_TRAVEL_TIMES = "checkDeterministicTravelTimes"; - private final static String CHECK_DETERMINISTIC_TRAVEL_TIMES_COMMENT = "Under ideal and correctly configured freeflow conditions, the algorithm will predict exactly what the vehicles will do in simulation. If this flag is enabled, the algorithm will perform self-checks to verify that this is the case. Use to verify your freeflow condiditons."; + public double maximumQueueTime = 0.0; - private boolean checkDeterminsticTravelTimes = false; - - @StringGetter(CHECK_DETERMINISTIC_TRAVEL_TIMES) - public boolean getCheckDeterminsticTravelTimes() { - return checkDeterminsticTravelTimes; - } - - @StringSetter(CHECK_DETERMINISTIC_TRAVEL_TIMES) - public void setCheckDeterminsticTravelTimes(boolean value) { - this.checkDeterminsticTravelTimes = value; - } + @Parameter + @Comment("Under ideal and correctly configured freeflow conditions, the algorithm will predict exactly what the vehicles will do in simulation. If this flag is enabled, the algorithm will perform self-checks to verify that this is the case. Use to verify your freeflow condiditons.") + public boolean checkDeterminsticTravelTimes = false; /* Scheduling */ - private final static String REROUTE_DURING_SCHEDULING = "rerouteDuringScheduling"; - private final static String REROUTE_DURING_SCHEDULING_COMMENT = "During scheduling of the pickups and dropoffs we may find situations in which the vehicle is already on the way to its next destination on the current drive task, so not rerouting is necessary. However, it may be wanted if traffic conditions change frequently. This flag will enable rerouting for already pre-routed segments of the schedule."; - - private boolean rerouteDuringScheduling = false; - - @StringGetter(REROUTE_DURING_SCHEDULING) - public boolean getRerouteDuringScheduling() { - return rerouteDuringScheduling; - } - - @StringSetter(REROUTE_DURING_SCHEDULING) - public void setRerouteDuringScheduling(boolean value) { - this.rerouteDuringScheduling = value; - } + @Parameter + @Comment("During scheduling of the pickups and dropoffs we may find situations in which the vehicle is already on the way to its next destination on the current drive task, so not rerouting is necessary. However, it may be wanted if traffic conditions change frequently. This flag will enable rerouting for already pre-routed segments of the schedule.") + public boolean rerouteDuringScheduling = false; /* Sequence generator */ @@ -180,346 +75,110 @@ public enum SequenceGeneratorType { Extensive, Insertive, Combined, EuclideanBestResponse } - private final static String SEQUENCE_GENERATOR_TYPE = "sequenceGeneratorType"; - private final static String SEQUENCE_GENERATOR_TYPE_COMMENT = "Defines which sequence generator to use: Extensive (trying to find all arrangements of pickups and dropoff for a route), Insertive (inserting new pickups and dropoffs in the existing order along a vehicle's route), Combined (Extensive below insertionStartOccupancy, Insertive after), EuclideanBestResponse (as a very fast test generator based on stepwise adding the closest pickup and dropoff by Euclidean distnace). "; - - private SequenceGeneratorType sequenceGeneratorType = SequenceGeneratorType.Combined; - - @StringGetter(SEQUENCE_GENERATOR_TYPE) - public SequenceGeneratorType getSequenceGeneratorType() { - return sequenceGeneratorType; - } - - @StringSetter(SEQUENCE_GENERATOR_TYPE) - public void setSequenceGeneratorType(SequenceGeneratorType value) { - this.sequenceGeneratorType = value; - } - - private final static String INSERTION_START_OCCUPANCY = "insertionStartOccupancy"; - private final static String INSERTION_START_OCCUPANCY_COMMENT = "Defines the occupany at which the Combined sequence generator will switch from Extensive to Insertive mode."; + @Parameter + @Comment("Defines which sequence generator to use: Extensive (trying to find all arrangements of pickups and dropoff for a route), Insertive (inserting new pickups and dropoffs in the existing order along a vehicle's route), Combined (Extensive below insertionStartOccupancy, Insertive after), EuclideanBestResponse (as a very fast test generator based on stepwise adding the closest pickup and dropoff by Euclidean distnace).") + public SequenceGeneratorType sequenceGeneratorType = SequenceGeneratorType.Combined; + @Parameter + @Comment("Defines the occupany at which the Combined sequence generator will switch from Extensive to Insertive mode.") @PositiveOrZero - private int insertionStartOccupancy = 5; - - @StringGetter(INSERTION_START_OCCUPANCY) - public int getInsertionStartOccupancy() { - return insertionStartOccupancy; - } - - @StringSetter(INSERTION_START_OCCUPANCY) - public void setInsertionStartOccupancy(int value) { - this.insertionStartOccupancy = value; - } - - private final static String CANDIDATE_VEHICLES_PER_REQUEST = "candidateVehiclesPerRequest"; - private final static String CANDIDATE_VEHICLES_PER_REQUEST_COMMENT = "Limits the number of request-vehicle combinations that are explored when building the trip graph (III.C in paper). If set to 0, no limit is imposed."; + public int insertionStartOccupancy = 5; + @Parameter + @Comment("Limits the number of request-vehicle combinations that are explored when building the trip graph (III.C in paper). If set to 0, no limit is imposed.") @PositiveOrZero - private int candidateVehiclesPerRequest = 30; - - @StringGetter(CANDIDATE_VEHICLES_PER_REQUEST) - public int getCandidateVehiclesPerRequest() { - return candidateVehiclesPerRequest; - } - - @StringSetter(CANDIDATE_VEHICLES_PER_REQUEST) - public void setCandidateVehiclesPerRequest(int value) { - this.candidateVehiclesPerRequest = value; - } - - @Override - public Map getComments() { - Map comments = super.getComments(); - comments.put(MODE, MODE_COMMENT); - comments.put(LOGGING_INTERVAL, LOGGING_INTERVAL_COMMENT); - comments.put(MAXIMUM_QUEUE_TIME, MAXIMUM_QUEUE_TIME_COMMENT); - comments.put(MAXIMUM_GROUP_REQUEST_SIZE, MAXIMUM_GROUP_REQUEST_SIZE_COMMENT); - comments.put(USE_PLANNED_PICKUP_TIME, USE_PLANNED_PICKUP_TIME_COMMENT); - comments.put(PLANNED_PICKUP_TIME_SLACK, PLANNED_PICKUP_TIME_SLACK_COMMENT); - comments.put(CHECK_DETERMINISTIC_TRAVEL_TIMES, CHECK_DETERMINISTIC_TRAVEL_TIMES_COMMENT); - comments.put(REROUTE_DURING_SCHEDULING, REROUTE_DURING_SCHEDULING_COMMENT); - comments.put(SEQUENCE_GENERATOR_TYPE, SEQUENCE_GENERATOR_TYPE_COMMENT); - comments.put(INSERTION_START_OCCUPANCY, INSERTION_START_OCCUPANCY_COMMENT); - comments.put(RELOCATION_INTERVAL, RELOCATION_INTERVAL_COMMENT); - comments.put(USE_BINDING_RELOCATIONS, USE_BINDING_RELOCATIONS_COMMENT); - comments.put(USE_STEPWISE_RELOCATION, USE_STEPWISE_RELOCATION_COMMENT); - comments.put(TRIP_GRAPH_LIMIT_PER_VEHICLE, TRIP_GRAPH_LIMIT_PER_VEHICLE_COMMENT); - comments.put(TRIP_GRAPH_LIMIT_PER_SEQUENCE_LENGTH, TRIP_GRAPH_LIMIT_PER_SEQUENCE_LENGTH_COMMENT); - comments.put(ASSIGNMENT_INTERVAL, ASSIGNMENT_INTERVAL_COMMENT); - comments.put(REJECTION_PENALTY, REJECTION_PENALTY_COMMENT); - comments.put(UNASSIGNMENT_PENALTY, UNASSIGNMENT_PENALTY_COMMENT); - comments.put(VIOLATION_FACTOR, VIOLATION_FACTOR_COMMENT); - comments.put(VIOLATION_OFFSET, VIOLATION_OFFSET_COMMENT); - comments.put(PREFER_NON_VIOLATION, PREFER_NON_VIOLATION_COMMENT); - comments.put(CANDIDATE_VEHICLES_PER_REQUEST, CANDIDATE_VEHICLES_PER_REQUEST_COMMENT); - return comments; - } + public int candidateVehiclesPerRequest = 30; /* Congestion mitigation */ - static public class CongestionMitigationParameters extends ReflectiveConfigGroup { + static public class CongestionMitigationParameters extends ReflectiveConfigGroupWithConfigurableParameterSets { static public final String SET_NAME = "congestionMitigation"; public CongestionMitigationParameters() { super(SET_NAME); } - private final static String ALLOW_BARE_REASSIGNMENT = "allowBareReassignment"; - private final static String ALLOW_BARE_REASSIGNMENT_COMMENT = "In some dispatching steps no new request have arrived, so no reassignment is necessary. However, if congestion is involved one might want to perform a reassignment to react to changed traffic conditions."; - - private boolean allowBareReassignment = false; - - @StringGetter(ALLOW_BARE_REASSIGNMENT) - public boolean getAllowBareReassignment() { - return allowBareReassignment; - } - - @StringSetter(ALLOW_BARE_REASSIGNMENT) - public void setAllowBareReassignment(boolean value) { - this.allowBareReassignment = value; - } - - private final static String PRESERVE_VEHICLE_ASSIGNMENTS = "preserveVehicleAssignments"; - private final static String PRESERVE_VEHICLE_ASSIGNMENTS_COMMENT = "Keep current assignments of a vehicle in the shareability graph also they might otherwise be filtered out due to changed traffic conditions."; - - private boolean preserveVehicleAssignments = true; - - @StringGetter(PRESERVE_VEHICLE_ASSIGNMENTS) - public boolean getPreserveVehicleAssignments() { - return preserveVehicleAssignments; - } - - @StringSetter(PRESERVE_VEHICLE_ASSIGNMENTS) - public void setPreserveVehicleAssignments(boolean value) { - this.preserveVehicleAssignments = value; - } - - private final static String ALLOW_PICKUP_VIOLATIONS = "allowPickupViolations"; - private final static String ALLOW_PICKUP_VIOLATIONS_COMMENT = "Allows that a request that is already assigned to the current vehicle can violate the pickup constraint if it is caused by traffic."; - - private boolean allowPickupViolations = true; - - @StringGetter(ALLOW_PICKUP_VIOLATIONS) - public boolean getAllowPickupViolations() { - return allowPickupViolations; - } - - @StringSetter(ALLOW_PICKUP_VIOLATIONS) - public void setAllowPickupViolations(boolean value) { - this.allowPickupViolations = value; - } - - private final static String ALLOW_PICKUPS_WITH_DROPOFF_VIOLATIONS = "allowPickupsWithDropoffViolations"; - private final static String ALLOW_PICKUPS_WITH_DROPOFF_VIOLATIONS_COMMENT = "Allows that new pickups can be integrated into a vehicle although some requests already have dropoff violations due to congestion."; + @Parameter + @Comment("In some dispatching steps no new request have arrived, so no reassignment is necessary. However, if congestion is involved one might want to perform a reassignment to react to changed traffic conditions.") + public boolean allowBareReassignment = false; - private boolean allowPickupsWithDropoffViolations = true; + @Parameter + @Comment("Keep current assignments of a vehicle in the shareability graph also they might otherwise be filtered out due to changed traffic conditions.") + public boolean preserveVehicleAssignments = true; - @StringGetter(ALLOW_PICKUPS_WITH_DROPOFF_VIOLATIONS) - public boolean getAllowPickupsWithDropoffViolations() { - return allowPickupsWithDropoffViolations; - } + @Parameter + @Comment("Allows that a request that is already assigned to the current vehicle can violate the pickup constraint if it is caused by traffic.") + public boolean allowPickupViolations = true; - @StringSetter(ALLOW_PICKUPS_WITH_DROPOFF_VIOLATIONS) - public void setAllowPickupsWithDropoffViolations(boolean value) { - this.allowPickupsWithDropoffViolations = value; - } - - @Override - public Map getComments() { - Map comments = super.getComments(); - comments.put(ALLOW_BARE_REASSIGNMENT, ALLOW_BARE_REASSIGNMENT_COMMENT); - comments.put(PRESERVE_VEHICLE_ASSIGNMENTS, PRESERVE_VEHICLE_ASSIGNMENTS_COMMENT); - comments.put(ALLOW_PICKUP_VIOLATIONS, ALLOW_PICKUP_VIOLATIONS_COMMENT); - comments.put(ALLOW_PICKUPS_WITH_DROPOFF_VIOLATIONS, ALLOW_PICKUPS_WITH_DROPOFF_VIOLATIONS_COMMENT); - return comments; - } + @Parameter + @Comment("Allows that new pickups can be integrated into a vehicle although some requests already have dropoff violations due to congestion.") + public boolean allowPickupsWithDropoffViolations = true; } /* Violations */ - private final static String VIOLATION_FACTOR = "violationFactor"; - private final static String VIOLATION_FACTOR_COMMENT = "Violations (for pickup and dropoff) are initially expressed in seconds. This factor is added to the violations to arrive at the final value."; + @Parameter + @Comment("Violations (for pickup and dropoff) are initially expressed in seconds. This factor is added to the violations to arrive at the final value.") + public double violationFactor = 60.0; - private double violationFactor = 60.0; + @Parameter + @Comment("Constant value that is added to each solution that has any violations.") + public double violationOffset = 10000.0; - @StringGetter(VIOLATION_FACTOR) - public double getViolationFactor() { - return violationFactor; - } - - @StringSetter(VIOLATION_FACTOR) - public void setViolationFactor(double value) { - this.violationFactor = value; - } - - private final static String VIOLATION_OFFSET = "violationOffset"; - private final static String VIOLATION_OFFSET_COMMENT = "Constant value that is added to each solution that has any violations."; - - private double violationOffset = 10000.0; - - @StringGetter(VIOLATION_OFFSET) - public double getViolationOffset() { - return violationOffset; - } - - @StringSetter(VIOLATION_OFFSET) - public void setViolationOffset(double value) { - this.violationOffset = value; - } - - private final static String PREFER_NON_VIOLATION = "preferNonViolation"; - private final static String PREFER_NON_VIOLATION_COMMENT = "Always prefer solutions without violations, even if a solution with violations and lower objective has been found."; - - private boolean preferNonViolation = false; - - @StringGetter(PREFER_NON_VIOLATION) - public boolean getPreferNonViolation() { - return preferNonViolation; - } - - @StringSetter(PREFER_NON_VIOLATION) - public void setPreferNonViolation(boolean value) { - this.preferNonViolation = value; - } + @Parameter + @Comment("Always prefer solutions without violations, even if a solution with violations and lower objective has been found.") + public boolean preferNonViolation = false; /* Assignment */ - static private final String ASSIGNMENT_INTERVAL = "assignmentInterval"; - static private final String ASSIGNMENT_INTERVAL_COMMENT = "The frequency with which assignment is performed"; - + @Parameter + @Comment("The frequency with which assignment is performed") @PositiveOrZero - private double assignmentInterval = 30; - - @StringGetter(ASSIGNMENT_INTERVAL) - public double getAssignmentInterval() { - return assignmentInterval; - } - - @StringSetter(ASSIGNMENT_INTERVAL) - public void setAssignmentInterval(double value) { - this.assignmentInterval = value; - } - - static private final String REJECTION_PENALTY = "rejectionPenalty"; - static private final String REJECTION_PENALTY_COMMENT = "Penalty in the ILP problem that is added for rejecting requests (before they have been assigned)"; + public double assignmentInterval = 30; + @Parameter + @Comment("Penalty in the ILP problem that is added for rejecting requests (before they have been assigned)") @PositiveOrZero - private double rejectionPenalty = 24.0 * 3600.0; - - @StringGetter(REJECTION_PENALTY) - public double getRejectionPenalty() { - return rejectionPenalty; - } - - @StringSetter(REJECTION_PENALTY) - public void setRejectionPenalty(double value) { - this.rejectionPenalty = value; - } - - static private final String UNASSIGNMENT_PENALTY = "unassignmentPenalty"; - static private final String UNASSIGNMENT_PENALTY_COMMENT = "Penalty in the ILP problem that is added when not assigning and already assigned requests"; + public double rejectionPenalty = 24.0 * 3600.0; + @Parameter + @Comment("Penalty in the ILP problem that is added when not assigning and already assigned requests") @PositiveOrZero - private double unassignmentPenalty = 24.0 * 3600.0 * 1000; - - @StringGetter(UNASSIGNMENT_PENALTY) - public double getUnassignmentPenalty() { - return unassignmentPenalty; - } - - @StringSetter(UNASSIGNMENT_PENALTY) - public void setUnassignmentPenalty(double value) { - this.unassignmentPenalty = value; - } + public double unassignmentPenalty = 24.0 * 3600.0 * 1000; /* Relocation */ - static private final String RELOCATION_INTERVAL = "relocationInterval"; - static private final String RELOCATION_INTERVAL_COMMENT = "The frequency with which relocation is performed"; - + @Parameter + @Comment("The frequency with which relocation is performed") @PositiveOrZero - private double relocationInterval = 30; - - @StringGetter(RELOCATION_INTERVAL) - public double getRelocationInterval() { - return relocationInterval; - } - - @StringSetter(RELOCATION_INTERVAL) - public void setRelocationInterval(double value) { - this.relocationInterval = value; - } - - static private final String USE_BINDING_RELOCATIONS = "useBindingRelocations"; - static private final String USE_BINDING_RELOCATIONS_COMMENT = "Defines whether vehicles that are already relocating can be used for relocation in the next relocation step"; - - private boolean useBindingRelocations = false; - - @StringGetter(USE_BINDING_RELOCATIONS) - public boolean getUseBindingRelocations() { - return useBindingRelocations; - } - - @StringSetter(USE_BINDING_RELOCATIONS) - public void setUseBindingRelocations(boolean value) { - this.useBindingRelocations = value; - } - - static private final String USE_STEPWISE_RELOCATION = "useStepwiseRelocation"; - static private final String USE_STEPWISE_RELOCATION_COMMENT = "If enabled, vehicles are stopped that are currently relocating but are not assigned a new relocation destination. If false they will finish their previous relocation if not assigned anoter one."; + public double relocationInterval = 30; - private boolean useStepwiseRelocation = false; + @Parameter + @Comment("Defines whether vehicles that are already relocating can be used for relocation in the next relocation step") + public boolean useBindingRelocations = false; - @StringGetter(USE_STEPWISE_RELOCATION) - public boolean getUseStepwiseRelocation() { - return useStepwiseRelocation; - } - - @StringSetter(USE_STEPWISE_RELOCATION) - public void setUseStepwiseRelocation(boolean value) { - this.useStepwiseRelocation = value; - } + @Parameter + @Comment("If enabled, vehicles are stopped that are currently relocating but are not assigned a new relocation destination. If false they will finish their previous relocation if not assigned anoter one.") + public boolean useStepwiseRelocation = false; /* Graph limits */ - static private final String TRIP_GRAPH_LIMIT_PER_VEHICLE = "tripGraphLimitPerVehicle"; - static private final String TRIP_GRAPH_LIMIT_PER_VEHICLE_COMMENT = "Limits the total number of edges in the trip-vehicle graph per vehicle (0 = no limit)"; - + @Parameter + @Comment("Limits the total number of edges in the trip-vehicle graph per vehicle (0 = no limit)") @PositiveOrZero - private int tripGraphLimitPerVehicle = 0; - - @StringGetter(TRIP_GRAPH_LIMIT_PER_VEHICLE) - public int getTripGraphLimitPerVehicle() { - return tripGraphLimitPerVehicle; - } - - @StringSetter(TRIP_GRAPH_LIMIT_PER_VEHICLE) - public void setTripGraphLimitPerVehicle(int value) { - this.tripGraphLimitPerVehicle = value; - } - - static private final String TRIP_GRAPH_LIMIT_PER_SEQUENCE_LENGTH = "tripGraphLimitPerSequenceLength"; - static private final String TRIP_GRAPH_LIMIT_PER_SEQUENCE_LENGTH_COMMENT = "Limits the total number of edges in the trip-vehicle graph for each occupancy level per vehicle (0 = no limit)"; + public int tripGraphLimitPerVehicle = 0; + @Parameter + @Comment("Limits the total number of edges in the trip-vehicle graph for each occupancy level per vehicle (0 = no limit)") @PositiveOrZero - private int tripGraphLimitPerSequenceLength = 0; - - @StringGetter(TRIP_GRAPH_LIMIT_PER_SEQUENCE_LENGTH) - public int getTripGraphLimitPerSequenceLength() { - return tripGraphLimitPerSequenceLength; - } - - @StringSetter(TRIP_GRAPH_LIMIT_PER_SEQUENCE_LENGTH) - public void setTripGraphLimitPerSequenceLength(int value) { - this.tripGraphLimitPerSequenceLength = value; - } + public int tripGraphLimitPerSequenceLength = 0; /* Block handling */ - public static class AssignmentSolverParameters extends ReflectiveConfigGroup { + public static class AssignmentSolverParameters extends ReflectiveConfigGroupWithConfigurableParameterSets { static public final String SET_PREFIX = "assignmentSolver:"; - private final String solverType; + public final String solverType; public AssignmentSolverParameters(String solverType) { super(SET_PREFIX + solverType); @@ -530,49 +189,19 @@ public String getSolverType() { return solverType; } - static private final String TIME_LIMIT = "timeLimit_s"; - static private final String TIME_LIMIT_COMMENT = "Defines the runtime threshold of the assignment algorithm [s]"; - - private double timeLimit = 15; - - @StringGetter(TIME_LIMIT) - public double getTimeLimit() { - return timeLimit; - } - - @StringSetter(TIME_LIMIT) - public void setTimeLimit(double value) { - this.timeLimit = value; - } - - static private final String OPTIMALITY_GAP = "optimalityGap"; - static private final String OPTIMALITY_GAP_COMMENT = "Defines the optimality gap for the algorithm"; - - private double optimalityGap = 0.1; - - @StringGetter(OPTIMALITY_GAP) - public double getOptimalityGap() { - return optimalityGap; - } - - @StringSetter(OPTIMALITY_GAP) - public void setOptimalityGap(double value) { - this.optimalityGap = value; - } + @Parameter + @Comment("Defines the runtime threshold of the assignment algorithm [s]") + public double timeLimit = 15; - @Override - public Map getComments() { - Map comments = super.getComments(); - comments.put(TIME_LIMIT, TIME_LIMIT_COMMENT); - comments.put(OPTIMALITY_GAP, OPTIMALITY_GAP_COMMENT); - return comments; - } + @Parameter + @Comment("Defines the optimality gap for the algorithm") + public double optimalityGap = 0.1; } - public static class RelocationSolverParameters extends ReflectiveConfigGroup { + public static class RelocationSolverParameters extends ReflectiveConfigGroupWithConfigurableParameterSets { static public final String SET_PREFIX = "relocationSolver:"; - private final String solverType; + public final String solverType; public RelocationSolverParameters(String solverType) { super(SET_PREFIX + solverType); @@ -583,27 +212,9 @@ public String getSolverType() { return solverType; } - static private final String RUNTIME_THRESHOLD = "runtimeThreshold_ms"; - static private final String RUNTIME_THRESHOLD_COMMENT = "Defines the runtime threshold of the assignment algorithm [ms]"; - - private int runtimeThreshold = 3600 * 1000; - - @StringGetter(RUNTIME_THRESHOLD) - public int getRuntimeThreshold() { - return runtimeThreshold; - } - - @StringSetter(RUNTIME_THRESHOLD) - public void setRuntimeThreshold(int value) { - this.runtimeThreshold = value; - } - - @Override - public Map getComments() { - Map comments = super.getComments(); - comments.put(RUNTIME_THRESHOLD, RUNTIME_THRESHOLD_COMMENT); - return comments; - } + @Parameter + @Comment("Defines the runtime threshold of the assignment algorithm [ms]") + public int runtimeThreshold = 3600 * 1000; } public static class GlpkMpsRelocationParameters extends RelocationSolverParameters { @@ -621,7 +232,7 @@ public CbcMpsRelocationParameters() { public static class TravelTimeEstimatorParameters extends ReflectiveConfigGroup { static public final String SET_PREFIX = "travelTimeEstimator:"; - private final String estimatorType; + public final String estimatorType; public TravelTimeEstimatorParameters(String estimatorType) { super(SET_PREFIX + estimatorType); @@ -633,100 +244,96 @@ public String getEstimatorType() { } } - private final Map> availableAssignmentSolvers = new HashMap<>(); - private final Map> availableRelocationSolvers = new HashMap<>(); - private final Map> availableTravelTimeEstimators = new HashMap<>(); - - private void prepareAvailableComponents() { - availableAssignmentSolvers.put(GreedyTripFirstSolver.TYPE, () -> new GreedyTripFirstAssignmentParameters()); - availableAssignmentSolvers.put(GreedyVehicleFirstSolver.TYPE, - () -> new GreedyVehicleFirstAssignmentParameters()); - availableAssignmentSolvers.put(CbcMpsAssignmentSolver.TYPE, () -> new CbcMpsAssignmentParameters()); - availableAssignmentSolvers.put(GlpkMpsAssignmentSolver.TYPE, () -> new GlpkMpsAssignmentParameters()); - - availableRelocationSolvers.put(BestResponseRelocationSolver.TYPE, () -> new BestResponseRelocationParameters()); - availableRelocationSolvers.put(CbcMpsRelocationSolver.TYPE, () -> new CbcMpsRelocationParameters()); - availableRelocationSolvers.put(GlpkMpsRelocationSolver.TYPE, () -> new GlpkMpsRelocationParameters()); - - availableTravelTimeEstimators.put(DrtDetourTravelTimeEstimator.TYPE, () -> new DrtDetourEstimatorParameters()); - availableTravelTimeEstimators.put(EuclideanTravelTimeEstimator.TYPE, () -> new EuclideanEstimatorParameters()); - availableTravelTimeEstimators.put(RoutingTravelTimeEstimator.TYPE, () -> new RoutingEstimatorParameters()); - availableTravelTimeEstimators.put(HybridTravelTimeEstimator.TYPE, () -> new HybridEstimatorParameters()); - availableTravelTimeEstimators.put(MatrixTravelTimeEstimator.TYPE, () -> new MatrixEstimatorParameters()); - } - - private void prepareDefaultComponents() { - super.addParameterSet(new GreedyTripFirstAssignmentParameters()); - super.addParameterSet(new BestResponseRelocationParameters()); - super.addParameterSet(new EuclideanEstimatorParameters()); - super.addParameterSet(new CongestionMitigationParameters()); - } + public AssignmentSolverParameters assignmentSolver; + public RelocationSolverParameters relocationSolver; + public TravelTimeEstimatorParameters travelTimeEstimator; + public CongestionMitigationParameters congestionMitigation; public void addAssignmentSolverDefinition(String solverType, Supplier creator) { - availableAssignmentSolvers.put(solverType, creator); + addDefinition(AssignmentSolverParameters.SET_PREFIX + solverType, creator, () -> assignmentSolver, + params -> assignmentSolver = (AssignmentSolverParameters) params); } public void addRelocationSolverDefinition(String solverType, Supplier creator) { - availableRelocationSolvers.put(solverType, creator); + addDefinition(RelocationSolverParameters.SET_PREFIX + solverType, creator, () -> relocationSolver, + params -> relocationSolver = (RelocationSolverParameters) params); } public void addTravelTimeEstimatorDefinition(String estimatorType, Supplier creator) { - availableTravelTimeEstimators.put(estimatorType, creator); + addDefinition(TravelTimeEstimatorParameters.SET_PREFIX + estimatorType, creator, () -> travelTimeEstimator, + params -> travelTimeEstimator = (TravelTimeEstimatorParameters) params); } - @Override - public ConfigGroup createParameterSet(String type) { - if (type.startsWith(AssignmentSolverParameters.SET_PREFIX)) { - String solverType = type.replaceFirst(AssignmentSolverParameters.SET_PREFIX, ""); + public final Map> availableAssignmentSolvers = new HashMap<>(); + public final Map> availableRelocationSolvers = new HashMap<>(); + public final Map> availableTravelTimeEstimators = new HashMap<>(); - Verify.verify(availableAssignmentSolvers.containsKey(solverType), - "Assignment solver of type " + solverType + " is not registered."); - return availableAssignmentSolvers.get(solverType).get(); - } + public void prepareAvailableComponents() { + addAssignmentSolverDefinition(GreedyTripFirstSolver.TYPE, GreedyTripFirstAssignmentParameters::new); + addAssignmentSolverDefinition(GreedyVehicleFirstSolver.TYPE, GreedyVehicleFirstAssignmentParameters::new); + addAssignmentSolverDefinition(CbcMpsAssignmentSolver.TYPE, CbcMpsAssignmentParameters::new); + addAssignmentSolverDefinition(GlpkMpsAssignmentSolver.TYPE, GlpkMpsAssignmentParameters::new); - if (type.startsWith(RelocationSolverParameters.SET_PREFIX)) { - String solverType = type.replaceFirst(RelocationSolverParameters.SET_PREFIX, ""); + addRelocationSolverDefinition(BestResponseRelocationSolver.TYPE, BestResponseRelocationParameters::new); + addRelocationSolverDefinition(CbcMpsRelocationSolver.TYPE, CbcMpsRelocationParameters::new); + addRelocationSolverDefinition(GlpkMpsRelocationSolver.TYPE, GlpkMpsRelocationParameters::new); - Verify.verify(availableRelocationSolvers.containsKey(solverType), - "Relocation solver of type " + solverType + " is not registered."); - return availableRelocationSolvers.get(solverType).get(); - } + addTravelTimeEstimatorDefinition(DrtDetourTravelTimeEstimator.TYPE, DrtDetourEstimatorParameters::new); + addTravelTimeEstimatorDefinition(EuclideanTravelTimeEstimator.TYPE, EuclideanEstimatorParameters::new); + addTravelTimeEstimatorDefinition(RoutingTravelTimeEstimator.TYPE, RoutingEstimatorParameters::new); + addTravelTimeEstimatorDefinition(HybridTravelTimeEstimator.TYPE, HybridEstimatorParameters::new); + addTravelTimeEstimatorDefinition(MatrixTravelTimeEstimator.TYPE, MatrixEstimatorParameters::new); - if (type.startsWith(TravelTimeEstimatorParameters.SET_PREFIX)) { - String estimatorType = type.replaceFirst(TravelTimeEstimatorParameters.SET_PREFIX, ""); + for (var entry : availableAssignmentSolvers.entrySet()) { + addDefinition(AssignmentSolverParameters.SET_PREFIX + entry.getKey(), entry.getValue(), + () -> assignmentSolver, params -> assignmentSolver = (AssignmentSolverParameters) params); + } - Verify.verify(availableTravelTimeEstimators.containsKey(estimatorType), - "Travel time estimator of type " + estimatorType + " is not registered."); - return availableTravelTimeEstimators.get(estimatorType).get(); + for (var entry : availableRelocationSolvers.entrySet()) { + addDefinition(RelocationSolverParameters.SET_PREFIX + entry.getKey(), entry.getValue(), + () -> relocationSolver, params -> relocationSolver = (RelocationSolverParameters) params); } - if (type.equals(CongestionMitigationParameters.SET_NAME)) { - return new CongestionMitigationParameters(); + for (var entry : availableTravelTimeEstimators.entrySet()) { + addDefinition(RelocationSolverParameters.SET_PREFIX + entry.getKey(), entry.getValue(), + () -> travelTimeEstimator, + params -> this.travelTimeEstimator = (TravelTimeEstimatorParameters) params); } - throw new IllegalStateException("Invalid parameter set for the Alonso-Mora config group: " + type); + addDefinition(CongestionMitigationParameters.SET_NAME, CongestionMitigationParameters::new, + () -> congestionMitigation, params -> congestionMitigation = (CongestionMitigationParameters) params); } - @Override - public void addParameterSet(ConfigGroup set) { - if (set instanceof CongestionMitigationParameters) { - removeParameterSet(getCongestionMitigationParameters()); - } + public void prepareDefaultComponents() { + addParameterSet(new GreedyTripFirstAssignmentParameters()); + addParameterSet(new BestResponseRelocationParameters()); + addParameterSet(new EuclideanEstimatorParameters()); + addParameterSet(new CongestionMitigationParameters()); + } - if (set instanceof AssignmentSolverParameters) { - removeParameterSet(getAssignmentSolverParameters()); + public void clearAssignmentSolver() { + for (String name : availableAssignmentSolvers.keySet()) { + this.clearParameterSetsForType(AssignmentSolverParameters.SET_PREFIX + name); } - if (set instanceof RelocationSolverParameters) { - removeParameterSet(getRelocationSolverParameters()); + this.assignmentSolver = null; + } + + public void clearRelocationSolver() { + for (String name : availableRelocationSolvers.keySet()) { + this.clearParameterSetsForType(RelocationSolverParameters.SET_PREFIX + name); } - if (set instanceof TravelTimeEstimatorParameters) { - removeParameterSet(getTravelTimeEstimatorParameters()); + this.relocationSolver = null; + } + + public void clearTravelTimeEstimator() { + for (String name : availableTravelTimeEstimators.keySet()) { + this.clearParameterSetsForType(TravelTimeEstimatorParameters.SET_PREFIX + name); } - super.addParameterSet(set); + this.travelTimeEstimator = null; } /* Assignment parameters */ @@ -774,43 +381,13 @@ protected EuclideanEstimatorParameters(String estimatorType) { super(estimatorType); } - private final static String EUCLIDEAN_DISTANCE_FACTOR = "euclideanDistanceFactor"; - private final static String EUCLIDEAN_DISTANCE_FACTOR_COMMENT = "Factor added to the Euclidean distance to estimate the travel time."; - - private double euclideanDistanceFactor = 1.3; - - @StringGetter(EUCLIDEAN_DISTANCE_FACTOR) - public double getEuclideanDistanceFactor() { - return euclideanDistanceFactor; - } - - @StringSetter(EUCLIDEAN_DISTANCE_FACTOR) - public void setEuclideanDistanceFactor(double value) { - this.euclideanDistanceFactor = value; - } - - private final static String EUCLIDEAN_SPEED = "euclideanSpeed"; - private final static String EUCLIDEAN_SPEED_COMMENT = "Speed along the scaled crofly distance in [km/h]"; - - private double euclideanSpeed = 40.0; - - @StringGetter(EUCLIDEAN_SPEED) - public double getEuclideanSpeed() { - return euclideanSpeed; - } - - @StringSetter(EUCLIDEAN_SPEED) - public void setEuclideanSpeed(double value) { - this.euclideanSpeed = value; - } + @Parameter + @Comment("Factor added to the Euclidean distance to estimate the travel time.") + public double euclideanDistanceFactor = 1.3; - @Override - public Map getComments() { - Map comments = super.getComments(); - comments.put(EUCLIDEAN_DISTANCE_FACTOR, EUCLIDEAN_DISTANCE_FACTOR_COMMENT); - comments.put(EUCLIDEAN_SPEED, EUCLIDEAN_SPEED_COMMENT); - return comments; - } + @Parameter + @Comment("Speed along the scaled crofly distance in [km/h]") + public double euclideanSpeed = 40.0; } public static class RoutingEstimatorParameters extends TravelTimeEstimatorParameters { @@ -818,27 +395,9 @@ public RoutingEstimatorParameters() { super(RoutingTravelTimeEstimator.TYPE); } - private final static String CACHE_LIFETIME = "cacheLifetime"; - private final static String CACHE_LIFETIME_COMMENT = "Delay until which a specific OD pair needs to be rerouted again"; - - private double cacheLifetime = 1200.0; - - @StringGetter(CACHE_LIFETIME) - public double getCacheLifetime() { - return cacheLifetime; - } - - @StringSetter(CACHE_LIFETIME) - public void setCacheLifetime(double value) { - this.cacheLifetime = value; - } - - @Override - public Map getComments() { - Map comments = super.getComments(); - comments.put(CACHE_LIFETIME, CACHE_LIFETIME_COMMENT); - return comments; - } + @Parameter + @Comment("Delay until which a specific OD pair needs to be rerouted again") + public double cacheLifetime = 1200.0; } public static class HybridEstimatorParameters extends EuclideanEstimatorParameters { @@ -846,27 +405,9 @@ public HybridEstimatorParameters() { super(HybridTravelTimeEstimator.TYPE); } - private final static String CACHE_LIFETIME = "cacheLifetime"; - private final static String CACHE_LIFETIME_COMMENT = "Delay until which a specific OD pair needs to be rerouted again"; - - private double cacheLifetime = 1200.0; - - @StringGetter(CACHE_LIFETIME) - public double getCacheLifetime() { - return cacheLifetime; - } - - @StringSetter(CACHE_LIFETIME) - public void setCacheLifetime(double value) { - this.cacheLifetime = value; - } - - @Override - public Map getComments() { - Map comments = super.getComments(); - comments.put(CACHE_LIFETIME, CACHE_LIFETIME_COMMENT); - return comments; - } + @Parameter + @Comment("Delay until which a specific OD pair needs to be rerouted again") + public double cacheLifetime = 1200.0; } public static class DrtDetourEstimatorParameters extends TravelTimeEstimatorParameters { @@ -880,87 +421,9 @@ public MatrixEstimatorParameters() { super(MatrixTravelTimeEstimator.TYPE); } - private final static String LAZY = "lazy"; - private final static String LAZY_COMMENT = "Defines whether the travel time matrix is constructed step by step when routes get requested or all at once in the beginning"; - - private boolean lazy = false; - - @StringGetter(LAZY) - public boolean isLazy() { - return lazy; - } - - @StringSetter(LAZY) - public void setLazy(boolean value) { - this.lazy = value; - } - - @Override - public Map getComments() { - Map comments = super.getComments(); - comments.put(LAZY, LAZY_COMMENT); - return comments; - } - } - - /* Some convenience getters */ - - public AssignmentSolverParameters getAssignmentSolverParameters() { - List assignmentSolvers = getParameterSets() // - .values().stream() // - .flatMap(collection -> collection.stream()) // - .filter(s -> s instanceof AssignmentSolverParameters) // - .map(s -> (AssignmentSolverParameters) s) // - .collect(Collectors.toList()); - - Verify.verify(assignmentSolvers.size() > 0, "Exactly one assignment solver must be defined (currently none)"); - Verify.verify(assignmentSolvers.size() < 2, - "Exactly one assignment solver must be defined (currently multiple)"); - - return assignmentSolvers.get(0); - } - - public RelocationSolverParameters getRelocationSolverParameters() { - List relocationSolvers = getParameterSets() // - .values().stream() // - .flatMap(collection -> collection.stream()) // - .filter(s -> s instanceof RelocationSolverParameters) // - .map(s -> (RelocationSolverParameters) s) // - .collect(Collectors.toList()); - - Verify.verify(relocationSolvers.size() > 0, "Exactly one relocation solver must be defined (currently none)"); - Verify.verify(relocationSolvers.size() < 2, - "Exactly one relocation solver must be defined (currently multiple)"); - - return relocationSolvers.get(0); - } - - public TravelTimeEstimatorParameters getTravelTimeEstimatorParameters() { - List estimators = getParameterSets() // - .values().stream() // - .flatMap(collection -> collection.stream()) // - .filter(s -> s instanceof TravelTimeEstimatorParameters) // - .map(s -> (TravelTimeEstimatorParameters) s) // - .collect(Collectors.toList()); - - Verify.verify(estimators.size() > 0, "Exactly one travel time estimator must be defined (currently none)"); - Verify.verify(estimators.size() < 2, "Exactly one travel time estimator must be defined (currently multiple)"); - - return estimators.get(0); - } - - public CongestionMitigationParameters getCongestionMitigationParameters() { - List items = getParameterSets() // - .values().stream() // - .flatMap(collection -> collection.stream()) // - .filter(s -> s instanceof CongestionMitigationParameters) // - .map(s -> (CongestionMitigationParameters) s) // - .collect(Collectors.toList()); - - Verify.verify(items.size() > 0, "Exactly one congestion parameter set must be defined (currently none)"); - Verify.verify(items.size() < 2, "Exactly one congestion parameter set must be defined (currently multiple)"); - - return items.get(0); + @Parameter + @Comment("Defines whether the travel time matrix is constructed step by step when routes get requested or all at once in the beginning") + public boolean lazy = false; } @Override @@ -972,29 +435,23 @@ protected void checkConsistency(Config config) { Verify.verify(loggingInterval % assignmentInterval == 0, "Logging interval must be multiple of the assignment interval"); - if (plannedPickupTimeSlack > 0.0) { - Verify.verify(!usePlannedPickupTime, - "Non-zero value for plannedPickupTimeSlack has no effect if usePlannedPickupTime is false"); - } - - getAssignmentSolverParameters(); - getRelocationSolverParameters(); - getTravelTimeEstimatorParameters(); - getCongestionMitigationParameters(); + Verify.verifyNotNull(assignmentSolver); + Verify.verifyNotNull(travelTimeEstimator); + Verify.verifyNotNull(congestionMitigation); boolean foundDrt = false; for (DrtConfigGroup drtModeConfig : MultiModeDrtConfigGroup.get(config).getModalElements()) { - if (drtModeConfig.getMode().equals(getMode())) { + if (drtModeConfig.getMode().equals(mode)) { foundDrt = true; if (drtModeConfig.getRebalancingParams().isPresent()) { - Verify.verify(relocationInterval == 0, + Verify.verify(relocationInterval == 0 || relocationSolver == null, "If DRT rebalancing is enabled, relocationInterval should be zero (disabling Alonso-Mora relocation)"); } } } - Verify.verify(foundDrt, "Mode {} was defined for Alonso-Mora, but does not exist in DRT", getMode()); + Verify.verify(foundDrt, "Mode {} was defined for Alonso-Mora, but does not exist in DRT", mode); } } diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigurator.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigurator.java index 86b1615..7d24a03 100644 --- a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigurator.java +++ b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraConfigurator.java @@ -34,7 +34,7 @@ static private AlonsoMoraConfigGroup getAlonsoMoraConfig(Config config, String m MultiModeAlonsoMoraConfigGroup multiModeConfig = MultiModeAlonsoMoraConfigGroup.get(config); for (AlonsoMoraConfigGroup modeConfig : multiModeConfig.getModes().values()) { - if (modeConfig.getMode().equals(mode)) { + if (modeConfig.mode.equals(mode)) { return modeConfig; } } diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeModule.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeModule.java index 30d4539..4b66d43 100644 --- a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeModule.java +++ b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeModule.java @@ -19,14 +19,10 @@ public void install() { return new InformationCollector(); })).asEagerSingleton(); - bindModal(RequestAggregationHandler.class).to(RequestAggregationHandler.class).asEagerSingleton(); - addEventHandlerBinding().to(modalKey(RequestAggregationHandler.class)); - bindModal(AnalysisListener.class).toProvider(modalProvider(getter -> { return new AnalysisListener( // getter.getModal(InformationCollector.class), // - getter.get(OutputDirectoryHierarchy.class), // - getter.getModal(RequestAggregationHandler.class) // + getter.get(OutputDirectoryHierarchy.class) // ); })).asEagerSingleton(); diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeQSimModule.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeQSimModule.java index 1c9c686..e7054c5 100644 --- a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeQSimModule.java +++ b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraModeQSimModule.java @@ -38,6 +38,7 @@ import org.matsim.alonso_mora.algorithm.relocation.BestResponseRelocationSolver; import org.matsim.alonso_mora.algorithm.relocation.CbcMpsRelocationSolver; import org.matsim.alonso_mora.algorithm.relocation.GlpkMpsRelocationSolver; +import org.matsim.alonso_mora.algorithm.relocation.NoopRelocationSolver; import org.matsim.alonso_mora.algorithm.relocation.RelocationSolver; import org.matsim.alonso_mora.scheduling.AlonsoMoraScheduler; import org.matsim.alonso_mora.scheduling.DefaultAlonsoMoraScheduler; @@ -56,12 +57,15 @@ import org.matsim.contrib.drt.optimizer.DrtOptimizer; import org.matsim.contrib.drt.optimizer.QSimScopeForkJoinPoolHolder; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingStrategy; +import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; +import org.matsim.contrib.drt.prebooking.unscheduler.RequestUnscheduler; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.schedule.DrtStayTaskEndTimeCalculator; import org.matsim.contrib.drt.schedule.DrtTaskFactory; -import org.matsim.contrib.drt.schedule.StopDurationEstimator; import org.matsim.contrib.drt.scheduler.DrtScheduleInquiry; import org.matsim.contrib.drt.scheduler.EmptyVehicleRelocator; +import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; +import org.matsim.contrib.drt.stops.StopTimeCalculator; import org.matsim.contrib.dvrp.fleet.Fleet; import org.matsim.contrib.dvrp.path.VrpPaths; import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; @@ -96,9 +100,9 @@ public AlonsoMoraModeQSimModule(DrtConfigGroup drtConfig, AlonsoMoraConfigGroup @Override protected void configureQSim() { bindModal(SequenceGeneratorFactory.class).toProvider(modalProvider(getter -> { - switch (amConfig.getSequenceGeneratorType()) { + switch (amConfig.sequenceGeneratorType) { case Combined: - return new CombinedSequenceGenerator.Factory(amConfig.getInsertionStartOccupancy()); + return new CombinedSequenceGenerator.Factory(amConfig.insertionStartOccupancy); case EuclideanBestResponse: return new EuclideanSequenceGenerator.Factory(); case Extensive: @@ -127,11 +131,10 @@ protected void configureQSim() { File problemPath = new File(outputHierarchy.getTempPath(), "alonso_mora_assignment.mps"); File solutionPath = new File(outputHierarchy.getTempPath(), "alonso_mora_assignment.sol"); - CbcMpsAssignmentParameters solverParameters = (CbcMpsAssignmentParameters) amConfig - .getAssignmentSolverParameters(); + CbcMpsAssignmentParameters solverParameters = (CbcMpsAssignmentParameters) amConfig.assignmentSolver; - return new CbcMpsAssignmentSolver(amConfig.getUnassignmentPenalty(), amConfig.getRejectionPenalty(), - solverParameters.getTimeLimit(), solverParameters.getOptimalityGap(), problemPath, solutionPath, + return new CbcMpsAssignmentSolver(amConfig.unassignmentPenalty, amConfig.rejectionPenalty, + solverParameters.timeLimit, solverParameters.optimalityGap, problemPath, solutionPath, getConfig().global().getRandomSeed()); })).in(Singleton.class); @@ -144,14 +147,13 @@ protected void configureQSim() { File problemPath = new File(outputHierarchy.getTempPath(), "alonso_mora_assignment.mps"); File solutionPath = new File(outputHierarchy.getTempPath(), "alonso_mora_assignment.sol"); - GlpkMpsAssignmentParameters solverParameters = (GlpkMpsAssignmentParameters) amConfig - .getAssignmentSolverParameters(); + GlpkMpsAssignmentParameters solverParameters = (GlpkMpsAssignmentParameters) amConfig.assignmentSolver; - return new GlpkMpsAssignmentSolver(amConfig.getUnassignmentPenalty(), amConfig.getRejectionPenalty(), - solverParameters.getTimeLimit(), solverParameters.getOptimalityGap(), problemPath, solutionPath); + return new GlpkMpsAssignmentSolver(amConfig.unassignmentPenalty, amConfig.rejectionPenalty, + solverParameters.timeLimit, solverParameters.optimalityGap, problemPath, solutionPath); })).in(Singleton.class); - switch (amConfig.getAssignmentSolverParameters().getSolverType()) { + switch (amConfig.assignmentSolver.getSolverType()) { case GreedyTripFirstSolver.TYPE: bindModal(AssignmentSolver.class).to(modalKey(GreedyTripFirstSolver.class)); break; @@ -166,6 +168,10 @@ protected void configureQSim() { break; } + bindModal(NoopRelocationSolver.class).toProvider(modalProvider(getter -> { + return new NoopRelocationSolver(); + })).in(Singleton.class); + bindModal(BestResponseRelocationSolver.class).toProvider(modalProvider(getter -> { return new BestResponseRelocationSolver(); })).in(Singleton.class); @@ -179,10 +185,9 @@ protected void configureQSim() { File problemPath = new File(outputHierarchy.getTempPath(), "alonso_mora_assignment.mps"); File solutionPath = new File(outputHierarchy.getTempPath(), "alonso_mora_assignment.sol"); - CbcMpsRelocationParameters solverParameters = (CbcMpsRelocationParameters) amConfig - .getRelocationSolverParameters(); + CbcMpsRelocationParameters solverParameters = (CbcMpsRelocationParameters) amConfig.relocationSolver; - return new CbcMpsRelocationSolver(solverParameters.getRuntimeThreshold(), problemPath, solutionPath, + return new CbcMpsRelocationSolver(solverParameters.runtimeThreshold, problemPath, solutionPath, getConfig().global().getRandomSeed()); })).in(Singleton.class); @@ -195,22 +200,25 @@ protected void configureQSim() { File problemPath = new File(outputHierarchy.getTempPath(), "alonso_mora_assignment.mps"); File solutionPath = new File(outputHierarchy.getTempPath(), "alonso_mora_assignment.sol"); - GlpkMpsRelocationParameters solverParameters = (GlpkMpsRelocationParameters) amConfig - .getRelocationSolverParameters(); + GlpkMpsRelocationParameters solverParameters = (GlpkMpsRelocationParameters) amConfig.relocationSolver; - return new GlpkMpsRelocationSolver(solverParameters.getRuntimeThreshold(), problemPath, solutionPath); + return new GlpkMpsRelocationSolver(solverParameters.runtimeThreshold, problemPath, solutionPath); })).in(Singleton.class); - switch (amConfig.getRelocationSolverParameters().getSolverType()) { - case BestResponseRelocationSolver.TYPE: - bindModal(RelocationSolver.class).to(modalKey(BestResponseRelocationSolver.class)); - break; - case CbcMpsRelocationSolver.TYPE: - bindModal(RelocationSolver.class).to(modalKey(CbcMpsRelocationSolver.class)); - break; - case GlpkMpsRelocationSolver.TYPE: - bindModal(RelocationSolver.class).to(modalKey(GlpkMpsRelocationSolver.class)); - break; + if (amConfig.relocationSolver != null) { + switch (amConfig.relocationSolver.getSolverType()) { + case BestResponseRelocationSolver.TYPE: + bindModal(RelocationSolver.class).to(modalKey(BestResponseRelocationSolver.class)); + break; + case CbcMpsRelocationSolver.TYPE: + bindModal(RelocationSolver.class).to(modalKey(CbcMpsRelocationSolver.class)); + break; + case GlpkMpsRelocationSolver.TYPE: + bindModal(RelocationSolver.class).to(modalKey(GlpkMpsRelocationSolver.class)); + break; + } + } else { + bindModal(RelocationSolver.class).to(modalKey(NoopRelocationSolver.class)); } bindModal(LeastCostPathCalculatorFactory.class).to(LeastCostPathCalculatorFactory.class); @@ -244,36 +252,33 @@ protected void configureQSim() { })).in(Singleton.class); bindModal(EuclideanTravelTimeEstimator.class).toProvider(modalProvider(getter -> { - EuclideanEstimatorParameters parameters = (EuclideanEstimatorParameters) amConfig - .getTravelTimeEstimatorParameters(); + EuclideanEstimatorParameters parameters = (EuclideanEstimatorParameters) amConfig.travelTimeEstimator; - return new EuclideanTravelTimeEstimator(parameters.getEuclideanDistanceFactor(), - parameters.getEuclideanSpeed() / 3.6); + return new EuclideanTravelTimeEstimator(parameters.euclideanDistanceFactor, + parameters.euclideanSpeed / 3.6); })).in(Singleton.class); bindModal(RoutingTravelTimeEstimator.class).toProvider(modalProvider(getter -> { - RoutingEstimatorParameters parameters = (RoutingEstimatorParameters) amConfig - .getTravelTimeEstimatorParameters(); + RoutingEstimatorParameters parameters = (RoutingEstimatorParameters) amConfig.travelTimeEstimator; LeastCostPathCalculator router = getter.getModal(LeastCostPathCalculator.class); TravelTime travelTime = getter.getModal(TravelTime.class); MobsimTimer mobsimTimer = getter.get(MobsimTimer.class); - return new RoutingTravelTimeEstimator(mobsimTimer, router, travelTime, parameters.getCacheLifetime()); + return new RoutingTravelTimeEstimator(mobsimTimer, router, travelTime, parameters.cacheLifetime); })).in(Singleton.class); bindModal(HybridTravelTimeEstimator.class).toProvider(modalProvider(getter -> { - HybridEstimatorParameters parameters = (HybridEstimatorParameters) amConfig - .getTravelTimeEstimatorParameters(); + HybridEstimatorParameters parameters = (HybridEstimatorParameters) amConfig.travelTimeEstimator; LeastCostPathCalculator router = getter.getModal(LeastCostPathCalculator.class); TravelTime travelTime = getter.getModal(TravelTime.class); MobsimTimer mobsimTimer = getter.get(MobsimTimer.class); return new HybridTravelTimeEstimator( - new RoutingTravelTimeEstimator(mobsimTimer, router, travelTime, parameters.getCacheLifetime()), - new EuclideanTravelTimeEstimator(parameters.getEuclideanDistanceFactor(), - parameters.getEuclideanSpeed() / 3.6)); + new RoutingTravelTimeEstimator(mobsimTimer, router, travelTime, parameters.cacheLifetime), + new EuclideanTravelTimeEstimator(parameters.euclideanDistanceFactor, + parameters.euclideanSpeed / 3.6)); })).in(Singleton.class); bindModal(MatrixTravelTimeEstimator.class).toProvider(modalProvider(getter -> { @@ -292,7 +297,7 @@ protected void configureQSim() { return LazyMatrixTravelTimeEstimator.create(network, travelTime, new DijkstraFactory(), 8.5 * 3600.0); })).in(Singleton.class); - switch (amConfig.getTravelTimeEstimatorParameters().getEstimatorType()) { + switch (amConfig.travelTimeEstimator.getEstimatorType()) { case DrtDetourTravelTimeEstimator.TYPE: bindModal(TravelTimeEstimator.class).to(modalKey(DrtDetourTravelTimeEstimator.class)); break; @@ -303,10 +308,9 @@ protected void configureQSim() { bindModal(TravelTimeEstimator.class).to(modalKey(HybridTravelTimeEstimator.class)); break; case MatrixTravelTimeEstimator.TYPE: - MatrixEstimatorParameters estimatorParameters = (MatrixEstimatorParameters) amConfig - .getTravelTimeEstimatorParameters(); + MatrixEstimatorParameters estimatorParameters = (MatrixEstimatorParameters) amConfig.travelTimeEstimator; bindModal(TravelTimeEstimator.class) - .to(estimatorParameters.isLazy() ? modalKey(LazyMatrixTravelTimeEstimator.class) + .to(estimatorParameters.lazy ? modalKey(LazyMatrixTravelTimeEstimator.class) : modalKey(MatrixTravelTimeEstimator.class)); break; case RoutingTravelTimeEstimator.TYPE: @@ -319,21 +323,22 @@ protected void configureQSim() { SequenceGeneratorFactory sequenceGeneratorFactory = getter.getModal(SequenceGeneratorFactory.class); Objective objective = getter.getModal(Objective.class); Constraint constraint = getter.getModal(Constraint.class); + PassengerStopDurationProvider stopDurationProvider = getter.getModal(PassengerStopDurationProvider.class); - CongestionMitigationParameters congestionParameters = amConfig.getCongestionMitigationParameters(); + CongestionMitigationParameters congestionParameters = amConfig.congestionMitigation; - return new DefaultAlonsoMoraFunction(travelTimeEstimator, sequenceGeneratorFactory, - drtConfig.stopDuration, congestionParameters.getAllowPickupViolations(), - congestionParameters.getAllowPickupsWithDropoffViolations(), - amConfig.getCheckDeterminsticTravelTimes(), objective, constraint, amConfig.getViolationFactor(), - amConfig.getViolationOffset(), amConfig.getPreferNonViolation()); + return new DefaultAlonsoMoraFunction(travelTimeEstimator, sequenceGeneratorFactory, stopDurationProvider, + drtConfig.stopDuration, congestionParameters.allowPickupViolations, + congestionParameters.allowPickupsWithDropoffViolations, amConfig.checkDeterminsticTravelTimes, + objective, constraint, amConfig.violationFactor, amConfig.violationOffset, + amConfig.preferNonViolation); })); bindModal(Objective.class).toProvider(() -> new MinimumDelay()); bindModal(Constraint.class).toInstance(new NoopConstraint()); bindModal(StayTaskEndTimeCalculator.class).toProvider(modalProvider(getter -> { - return new DrtStayTaskEndTimeCalculator(getter.getModal(StopDurationEstimator.class)); + return new DrtStayTaskEndTimeCalculator(getter.getModal(StopTimeCalculator.class)); })); bindModal(AlonsoMoraScheduler.class).toProvider(modalProvider(getter -> { @@ -345,10 +350,11 @@ protected void configureQSim() { Network network = getter.getModal(Network.class); OperationalVoter operationalVoter = getter.getModal(OperationalVoter.class); + PassengerStopDurationProvider stopDurationProvider = getter.getModal(PassengerStopDurationProvider.class); - return new DefaultAlonsoMoraScheduler(taskFactory, drtConfig.stopDuration, - amConfig.getCheckDeterminsticTravelTimes(), amConfig.getRerouteDuringScheduling(), travelTime, - network, endTimeCalculator, router, operationalVoter); + return new DefaultAlonsoMoraScheduler(taskFactory, stopDurationProvider, drtConfig.stopDuration, + amConfig.checkDeterminsticTravelTimes, amConfig.rerouteDuringScheduling, travelTime, network, + endTimeCalculator, router, operationalVoter); })); bindModal(OperationalVoter.class).toInstance(new NoopOperationalVoter()); @@ -373,7 +379,8 @@ protected void configureQSim() { bindModal(AlonsoMoraAlgorithm.class).toProvider(modalProvider(getter -> { StandardRebalancer standardRebalancer = getter.getModal(StandardRebalancer.class); - if (amConfig.getRelocationInterval() > 0 && standardRebalancer.isActive()) { + if ((amConfig.relocationInterval > 0 && amConfig.relocationSolver != null) + && standardRebalancer.isActive()) { throw new IllegalStateException( "If a DRT rebalancing strategy is defined, you have to set useInternalRebalancing=false for the Alonso Mora dispatcher."); } @@ -389,14 +396,16 @@ protected void configureQSim() { getter.getModal(AlonsoMoraVehicleFactory.class), // getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool(), // getter.getModal(TravelTimeEstimator.class), // - drtConfig.stopDuration, // - new AlgorithmSettings(amConfig)); + getter.getModal(PassengerStopDurationProvider.class), // + new AlgorithmSettings(amConfig), // + getter.getModal(DrtOfferAcceptor.class), // + drtConfig.stopDuration); })); bindModal(AlonsoMoraVehicleFactory.class).toInstance(vehicle -> new DefaultAlonsoMoraVehicle(vehicle)); bindModal(AlonsoMoraRequestFactory.class).toProvider(modalProvider(getter -> { - return new DefaultAlonsoMoraRequestFactory(amConfig.getMaximumQueueTime()); + return new DefaultAlonsoMoraRequestFactory(amConfig.maximumQueueTime); })); bindModal(AlonsoMoraOptimizer.class).toProvider(modalProvider(getter -> { @@ -404,17 +413,21 @@ protected void configureQSim() { getter.getModal(AlonsoMoraRequestFactory.class), // getter.getModal(ScheduleTimingUpdater.class), // getter.getModal(Fleet.class), // - amConfig.getAssignmentInterval(), // - amConfig.getMaximumGroupRequestSize(), // + amConfig.assignmentInterval, // getter.getModal(QSimScopeForkJoinPoolHolder.class).getPool(), // getter.getModal(LeastCostPathCalculator.class), // getter.getModal(TravelTime.class), // - drtConfig.advanceRequestPlanningHorizon, // getter.getModal(InformationCollector.class) // ); })); bindModal(AlonsoMoraConfigGroup.class).toInstance(amConfig); addModalComponent(DrtOptimizer.class, modalKey(AlonsoMoraOptimizer.class)); + + bindModal(AlonsoMoraOfferAcceptor.class).toInstance(new AlonsoMoraOfferAcceptor()); + bindModal(DrtOfferAcceptor.class).to(modalKey(AlonsoMoraOfferAcceptor.class)); + + bindModal(AlonsoMoraUnscheduler.class).toInstance(new AlonsoMoraUnscheduler()); + bindModal(RequestUnscheduler.class).to(modalKey(AlonsoMoraUnscheduler.class)); } } diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOfferAcceptor.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOfferAcceptor.java new file mode 100644 index 0000000..6ffc658 --- /dev/null +++ b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOfferAcceptor.java @@ -0,0 +1,19 @@ +package org.matsim.alonso_mora; + +import java.util.Optional; + +import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; +import org.matsim.contrib.drt.passenger.DrtRequest; + +public class AlonsoMoraOfferAcceptor implements DrtOfferAcceptor { + @Override + public Optional acceptDrtOffer(DrtRequest request, double departureTime, double arrivalTime) { + return Optional.of(AcceptedDrtRequest.newBuilder() // + .request(request) // + .earliestStartTime(request.getEarliestStartTime()) // + .latestArrivalTime(request.getLatestArrivalTime()) // + .latestStartTime(departureTime) // + .build()); + } +} diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOptimizer.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOptimizer.java index 1f7de50..e3e1b50 100644 --- a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOptimizer.java +++ b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraOptimizer.java @@ -2,12 +2,9 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Optional; -import java.util.PriorityQueue; -import java.util.Queue; import java.util.concurrent.ForkJoinPool; import java.util.stream.IntStream; @@ -15,7 +12,6 @@ import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequestFactory; import org.matsim.contrib.drt.optimizer.DrtOptimizer; -import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; import org.matsim.contrib.drt.passenger.DrtRequest; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.Fleet; @@ -41,34 +37,24 @@ public class AlonsoMoraOptimizer implements DrtOptimizer { private final List submittedRequests = new LinkedList<>(); private final double assignmentInterval; - private final int maximumGroupRequestSize; - private final ForkJoinPool forkJoinPool; private final LeastCostPathCalculator router; private final TravelTime travelTime; private final InformationCollector collector; - private final Queue prebookingQueue = new PriorityQueue<>((a, b) -> { - return Double.compare(a.getEarliestPickupTime(), b.getEarliestPickupTime()); - }); - - private final double prebookingHorizon; - public AlonsoMoraOptimizer(AlonsoMoraAlgorithm algorithm, AlonsoMoraRequestFactory requestFactory, ScheduleTimingUpdater scheduleTimingUpdater, Fleet fleet, double assignmentInterval, - int maximumGroupRequestSize, ForkJoinPool forkJoinPool, LeastCostPathCalculator router, - TravelTime travelTime, double prebookingHorizon, InformationCollector collector) { + ForkJoinPool forkJoinPool, LeastCostPathCalculator router, TravelTime travelTime, + InformationCollector collector) { this.algorithm = algorithm; this.requestFactory = requestFactory; this.assignmentInterval = assignmentInterval; this.scheduleTimingUpdater = scheduleTimingUpdater; this.fleet = fleet; - this.maximumGroupRequestSize = maximumGroupRequestSize; this.forkJoinPool = forkJoinPool; this.router = router; this.travelTime = travelTime; - this.prebookingHorizon = prebookingHorizon; this.collector = collector; } @@ -77,89 +63,46 @@ public void requestSubmitted(Request request) { submittedRequests.add((DrtRequest) request); } - /** - * Goes through the submitted individual requests and tries to find those that - * should be aggregated to a collective request. - */ - private List> poolRequests(List submittedRequests) { - submittedRequests = new LinkedList<>(submittedRequests); - List> allPooledRequests = new LinkedList<>(); - - while (submittedRequests.size() > 0) { - List pooledRequests = new LinkedList<>(); - pooledRequests.add(submittedRequests.remove(0)); - DrtRequest mainRequest = pooledRequests.get(0); - - Iterator iterator = submittedRequests.iterator(); - - while (iterator.hasNext() && pooledRequests.size() < maximumGroupRequestSize) { - DrtRequest nextRequest = iterator.next(); - - if (nextRequest.getFromLink() == mainRequest.getFromLink()) { - if (nextRequest.getToLink() == mainRequest.getToLink()) { - if (nextRequest.getEarliestStartTime() == mainRequest.getEarliestStartTime()) { - pooledRequests.add(nextRequest); - iterator.remove(); - } - } - } - } - - allPooledRequests.add(pooledRequests); - } - - return allPooledRequests; - } - @Override public void notifyMobsimBeforeSimStep(@SuppressWarnings("rawtypes") MobsimBeforeSimStepEvent e) { double now = e.getSimulationTime(); - + if (now % assignmentInterval == 0) { - List newRequests = new LinkedList<>(); + List processedRequests = new LinkedList<>(); - List> pooledRequests = poolRequests(submittedRequests); - List paths = new ArrayList<>(Collections.nCopies(pooledRequests.size(), null)); + List submittedRequests = new ArrayList<>(this.submittedRequests); + this.submittedRequests.clear(); + + List paths = new ArrayList<>(Collections.nCopies(submittedRequests.size(), null)); // Here this direct routing is performed forkJoinPool.submit(() -> { - IntStream.range(0, pooledRequests.size()).parallel().forEach(i -> { - DrtRequest request = pooledRequests.get(i).get(0); - paths.set(i, VrpPaths.calcAndCreatePath(request.getFromLink(), request.getToLink(), request.getEarliestStartTime(), router, - travelTime)); + IntStream.range(0, submittedRequests.size()).parallel().forEach(i -> { + DrtRequest request = submittedRequests.get(i); + paths.set(i, VrpPaths.calcAndCreatePath(request.getFromLink(), request.getToLink(), + request.getEarliestStartTime(), router, travelTime)); }); }).join(); - // Grouped requests - for (int i = 0; i < pooledRequests.size(); i++) { - List pool = pooledRequests.get(i); - - double earliestDepartureTime = pool.get(0).getEarliestStartTime(); + for (int i = 0; i < submittedRequests.size(); i++) { + DrtRequest drtRequest = submittedRequests.get(i); + + double earliestDepartureTime = drtRequest.getEarliestStartTime(); double directArrivalTime = paths.get(i).getTravelTime() + earliestDepartureTime; double directRideDistance = VrpPaths.calcDistance(paths.get(i)); - AlonsoMoraRequest request = requestFactory.createRequest(pool, directArrivalTime, earliestDepartureTime, - directRideDistance); + AlonsoMoraRequest request = requestFactory.createRequest(drtRequest, directArrivalTime, + earliestDepartureTime, directRideDistance); - if (now >= request.getEarliestPickupTime() - prebookingHorizon) { - newRequests.add(request); - } else { - prebookingQueue.add(request); - } + processedRequests.add(request); } - while (prebookingQueue.size() > 0 - && now >= prebookingQueue.peek().getEarliestPickupTime() - prebookingHorizon) { - newRequests.add(prebookingQueue.poll()); - } - - submittedRequests.clear(); - for (DvrpVehicle v : fleet.getVehicles().values()) { scheduleTimingUpdater.updateTimings(v); } - Optional information = algorithm.run(newRequests, e.getSimulationTime()); + Optional information = algorithm.run(processedRequests, + e.getSimulationTime()); if (information.isPresent()) { collector.addInformation(e.getSimulationTime(), information.get()); diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraSubmissionEvent.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraSubmissionEvent.java deleted file mode 100644 index 1ae3683..0000000 --- a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraSubmissionEvent.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.matsim.alonso_mora; - -import java.util.Arrays; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.events.Event; -import org.matsim.contrib.dvrp.optimizer.Request; - -/** - * For computational performance, this implementation of the algorithm by - * Alonso-Mora et al. aggregates requests with the same origin and destination - * into group requests. This event is published whenever an aggregated request - * arrives at the dispatcher to allow for a post-processing analysis of - * aggregated requests. - * - * @author sebhoerl - */ -public class AlonsoMoraSubmissionEvent extends Event { - static public final String EVENT_TYPE = "alonso mora submission"; - - static public final String REQUEST_IDS = "requestIds"; - - private final Set> requestIds; - - public AlonsoMoraSubmissionEvent(double time, Set> requestIds) { - super(time); - this.requestIds = requestIds; - } - - @Override - public String getEventType() { - return EVENT_TYPE; - } - - public Set> getRequestIds() { - return requestIds; - } - - public Map getAttributes() { - Map attributes = super.getAttributes(); - attributes.put(REQUEST_IDS, requestIds.stream().map(id -> id.toString()).collect(Collectors.joining(","))); - return attributes; - } - - static public AlonsoMoraSubmissionEvent convert(Event event) { - return new AlonsoMoraSubmissionEvent(event.getTime(), - Arrays.asList(((String) event.getAttributes().get(REQUEST_IDS)).split(",")).stream() - .map(id -> Id.create(id, Request.class)).collect(Collectors.toSet())); - } -} diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraSubmissionEventHandler.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraSubmissionEventHandler.java deleted file mode 100644 index ca2e818..0000000 --- a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraSubmissionEventHandler.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.matsim.alonso_mora; - -import org.matsim.core.events.handler.EventHandler; - -/** - * Handles a submission event for the dispatcher by Alonso-Mora et al. - * - * @author sebhoerl - */ -public interface AlonsoMoraSubmissionEventHandler extends EventHandler { - public void handleEvent(AlonsoMoraSubmissionEvent event); -} diff --git a/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraUnscheduler.java b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraUnscheduler.java new file mode 100644 index 0000000..bb441f1 --- /dev/null +++ b/core/src/main/java/org/matsim/alonso_mora/AlonsoMoraUnscheduler.java @@ -0,0 +1,14 @@ +package org.matsim.alonso_mora; + +import org.matsim.api.core.v01.Id; +import org.matsim.contrib.drt.prebooking.unscheduler.RequestUnscheduler; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; +import org.matsim.contrib.dvrp.optimizer.Request; + +public class AlonsoMoraUnscheduler implements RequestUnscheduler { + @Override + public void unscheduleRequest(double now, Id vehicleId, Id requestId) { + // in AM we do not unschedule any request as the schedules are rebuilt in every + // step + } +} diff --git a/core/src/main/java/org/matsim/alonso_mora/AnalysisListener.java b/core/src/main/java/org/matsim/alonso_mora/AnalysisListener.java index b589ae6..5ddbaa0 100644 --- a/core/src/main/java/org/matsim/alonso_mora/AnalysisListener.java +++ b/core/src/main/java/org/matsim/alonso_mora/AnalysisListener.java @@ -15,7 +15,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -32,11 +31,9 @@ import org.matsim.alonso_mora.InformationCollector.RebalancingInformation; import org.matsim.alonso_mora.InformationCollector.SolverInformation; import org.matsim.alonso_mora.algorithm.assignment.AssignmentSolver.Solution.Status; -import org.matsim.api.core.v01.Id; import org.matsim.contrib.common.timeprofile.TimeProfileCharts; import org.matsim.contrib.common.timeprofile.TimeProfileCharts.ChartType; import org.matsim.contrib.common.util.ChartSaveUtils; -import org.matsim.contrib.dvrp.optimizer.Request; import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.controler.events.IterationEndsEvent; import org.matsim.core.controler.listener.IterationEndsListener; @@ -50,7 +47,6 @@ */ class AnalysisListener implements IterationEndsListener { private final InformationCollector information; - private final RequestAggregationHandler requestHandler; private final OutputDirectoryHierarchy outputHierarchy; private final List numberOfInvalidSolutions = new LinkedList<>(); @@ -58,11 +54,9 @@ class AnalysisListener implements IterationEndsListener { private final List numberOfOptimalSolutions = new LinkedList<>(); private final List numberOfReassignments = new LinkedList<>(); - public AnalysisListener(InformationCollector information, OutputDirectoryHierarchy outputHierarchy, - RequestAggregationHandler requestHandler) { + public AnalysisListener(InformationCollector information, OutputDirectoryHierarchy outputHierarchy) { this.information = information; this.outputHierarchy = outputHierarchy; - this.requestHandler = requestHandler; } @Override @@ -364,23 +358,5 @@ public void notifyIterationEnds(IterationEndsEvent event) { ChartSaveUtils.saveAsPNG(stackedChart, outputHierarchy.getIterationFilename(event.getIteration(), "am_occupancy_requests"), 1500, 1000); } - - { - List>> requests = requestHandler.consolidate(); - - try { - File path = new File( - outputHierarchy.getIterationFilename(event.getIteration(), "am_group_requests.txt")); - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path))); - - for (Set> set : requests) { - writer.write(set.stream().map(String::valueOf).collect(Collectors.joining(",")) + "\n"); - } - - writer.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } } } diff --git a/core/src/main/java/org/matsim/alonso_mora/MultiModeAlonsoMoraConfigGroup.java b/core/src/main/java/org/matsim/alonso_mora/MultiModeAlonsoMoraConfigGroup.java index 04d3403..6f590d0 100644 --- a/core/src/main/java/org/matsim/alonso_mora/MultiModeAlonsoMoraConfigGroup.java +++ b/core/src/main/java/org/matsim/alonso_mora/MultiModeAlonsoMoraConfigGroup.java @@ -28,7 +28,7 @@ public Map getModes() { for (ConfigGroup modeConfig : getParameterSets(AlonsoMoraConfigGroup.GROUP_NAME)) { AlonsoMoraConfigGroup amConfig = (AlonsoMoraConfigGroup) modeConfig; - modes.put(amConfig.getMode(), amConfig); + modes.put(amConfig.mode, amConfig); } return modes; diff --git a/core/src/main/java/org/matsim/alonso_mora/RequestAggregationHandler.java b/core/src/main/java/org/matsim/alonso_mora/RequestAggregationHandler.java deleted file mode 100644 index 8038293..0000000 --- a/core/src/main/java/org/matsim/alonso_mora/RequestAggregationHandler.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.matsim.alonso_mora; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import org.matsim.api.core.v01.Id; -import org.matsim.contrib.dvrp.optimizer.Request; - -/** - * Simple event handler used to track the requests that are aggregated for the - * dispatcher. - */ -class RequestAggregationHandler implements AlonsoMoraSubmissionEventHandler { - private final List>> requests = new LinkedList<>(); - - @Override - public void handleEvent(AlonsoMoraSubmissionEvent event) { - requests.add(event.getRequestIds()); - } - - public List>> consolidate() { - List>> returnValue = new ArrayList<>(requests); - requests.clear(); - return returnValue; - } -} diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraAlgorithm.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraAlgorithm.java index 12d97b1..5dea764 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraAlgorithm.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraAlgorithm.java @@ -21,7 +21,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.alonso_mora.AlonsoMoraConfigGroup; -import org.matsim.alonso_mora.AlonsoMoraSubmissionEvent; import org.matsim.alonso_mora.algorithm.AlonsoMoraStop.StopType; import org.matsim.alonso_mora.algorithm.assignment.AssignmentSolver; import org.matsim.alonso_mora.algorithm.assignment.AssignmentSolver.Solution; @@ -38,9 +37,11 @@ import org.matsim.alonso_mora.travel_time.TravelTimeEstimator; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.passenger.DrtOfferAcceptor; import org.matsim.contrib.drt.passenger.DrtRequest; import org.matsim.contrib.drt.schedule.DefaultDrtStopTask; import org.matsim.contrib.drt.scheduler.EmptyVehicleRelocator; +import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.Fleet; import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEvent; @@ -75,6 +76,7 @@ public class AlonsoMoraAlgorithm { private final AlonsoMoraScheduler scheduler; private final AlonsoMoraFunction function; private final ForkJoinPool forkJoinPool; + private final DrtOfferAcceptor offerAcceptor; private final EventsManager eventsManager; private final String mode; @@ -93,14 +95,16 @@ public class AlonsoMoraAlgorithm { private final int maximumOccupancy; private final TravelTimeEstimator travelTimeEstimator; - private final double stopDuration; + private final PassengerStopDurationProvider stopDurationProvider; private final AlgorithmSettings settings; + private final double vehicleStopDuration; public AlonsoMoraAlgorithm(Fleet fleet, AssignmentSolver assignmentSolver, RelocationSolver rebalancingSolver, AlonsoMoraFunction function, AlonsoMoraScheduler scheduler, EventsManager eventsManager, String mode, AlonsoMoraVehicleFactory vehicleFactory, ForkJoinPool forkJoinPool, TravelTimeEstimator travelTimeEstimator, - double stopDuration, AlgorithmSettings settings) { + PassengerStopDurationProvider stopDurationProvider, AlgorithmSettings settings, DrtOfferAcceptor offerAcceptor, + double vehicleStopDuration) { this.assignmentSolver = assignmentSolver; this.rebalancingSolver = rebalancingSolver; this.scheduler = scheduler; @@ -109,8 +113,10 @@ public AlonsoMoraAlgorithm(Fleet fleet, AssignmentSolver assignmentSolver, Reloc this.function = function; this.forkJoinPool = forkJoinPool; this.travelTimeEstimator = travelTimeEstimator; - this.stopDuration = stopDuration; + this.stopDurationProvider = stopDurationProvider; this.settings = settings; + this.offerAcceptor = offerAcceptor; + this.vehicleStopDuration = vehicleStopDuration; // Create vehicle wrappers vehicles = new ArrayList<>(fleet.getVehicles().size()); @@ -225,10 +231,10 @@ private void updateRequestsBeforeAssignment(Collection newReq if (now > request.getLatestAssignmentTime()) { iterator.remove(); - for (DrtRequest drtRequest : request.getDrtRequests()) { - eventsManager.processEvent(new PassengerRequestRejectedEvent(now, mode, drtRequest.getId(), - drtRequest.getPassengerId(), "queue time exeeded")); - } + DrtRequest drtRequest = request.getDrtRequest(); + + eventsManager.processEvent(new PassengerRequestRejectedEvent(now, mode, drtRequest.getId(), + drtRequest.getPassengerIds(), "queue time exeeded")); numberOfRejectedRequests++; } @@ -239,11 +245,6 @@ private void updateRequestsBeforeAssignment(Collection newReq * create events to notify submission.s */ queuedRequests.addAll(newRequests); - - for (AlonsoMoraRequest request : newRequests) { - eventsManager.processEvent(new AlonsoMoraSubmissionEvent(now, - request.getDrtRequests().stream().map(r -> r.getId()).collect(Collectors.toSet()))); - } } /** @@ -317,7 +318,7 @@ void updateVehicleGraphs(double now, Information information) { v.setRoute(updatedRoute); if (updatedRoute.size() > 0) { - RouteTracker congestionTracker = new RouteTracker(travelTimeEstimator, stopDuration, 0, + RouteTracker congestionTracker = new RouteTracker(v, travelTimeEstimator, stopDurationProvider, vehicleStopDuration, 0, diversion.time, Optional.of(diversion.link)); congestionTracker.setDrivingState(v); congestionTracker.update(v.getRoute()); @@ -434,11 +435,7 @@ private void processAssignedRequests(Solution solution, double now, Information for (AlonsoMoraTrip trip : solution.trips) { // Find information for each request along the sequence for (AlonsoMoraRequest request : trip.getRequests()) { - Verify.verify(newAssignedRequests.add(request), "Request is assigned twice!"); - - // Set the vehicle - request.setVehicle(trip.getVehicle()); - + // obtain times double expectedPickupTime = Double.NaN; double expectedDropoffTime = Double.NaN; @@ -450,38 +447,48 @@ private void processAssignedRequests(Solution solution, double now, Information if (stop.getType().equals(StopType.Pickup)) { // We're looking at the pickup stop - expectedPickupTime = stop.getTime(); - - if (settings.usePlannedPickupTime) { - // We have a waiting time slack, i.e. we move the pickup constraint to the - // promised value from the assignment plus a small slack, which, by default, is - // zero. So in the usual case, we require that the request be picked up at the - // time that we promise at the first assignment. - - // ... but adding the slack cannot exceed the initial pickup requirement - double plannedPickupTime = expectedPickupTime + settings.plannedPickupTimeSlack; - plannedPickupTime = Math.min(plannedPickupTime, request.getLatestPickupTime()); - - request.setPlannedPickupTime(plannedPickupTime); - } - - if (request.isAssigned() && !request.getVehicle().equals(trip.getVehicle())) { - // Just for statistics: We track whether a request is assigned to a new vehicle - information.numberOfReassignments++; - } } else if (stop.getType().equals(StopType.Dropoff)) { // We're looking at the dropoff stop expectedDropoffTime = stop.getTime(); } } } + + Verify.verify(Double.isFinite(expectedPickupTime)); + Verify.verify(Double.isFinite(expectedDropoffTime)); - /* For each DRT request, we create a scheduling event */ - for (AcceptedDrtRequest drtRequest : request.getAcceptedDrtRequests()) { - eventsManager.processEvent(new PassengerRequestScheduledEvent(now, mode, drtRequest.getId(), - drtRequest.getPassengerId(), trip.getVehicle().getVehicle().getId(), expectedPickupTime, - expectedDropoffTime)); + // check if request has already been accepted + Optional acceptedRequest = Optional.ofNullable(request.getAcceptedDrtRequest()); + + if (acceptedRequest.isEmpty()) { + // first need to check if user accepts the offer + + acceptedRequest = offerAcceptor.acceptDrtOffer(request.getDrtRequest(), + expectedPickupTime, expectedDropoffTime); + + if (acceptedRequest.isPresent()) { + request.accept(acceptedRequest.get()); + } + } + + // now proceed with the request, otherwise it is rejected + if (acceptedRequest.isPresent()) { + Verify.verify(newAssignedRequests.add(request), "Request is assigned twice!"); + + // Set the vehicle + request.setVehicle(trip.getVehicle()); + + // publish scheduling event + eventsManager.processEvent(new PassengerRequestScheduledEvent(now, mode, + request.getDrtRequest().getId(), request.getDrtRequest().getPassengerIds(), + trip.getVehicle().getVehicle().getId(), expectedPickupTime, expectedDropoffTime)); + + // statistics + if (request.isAssigned() && !request.getVehicle().equals(trip.getVehicle())) { + // Just for statistics: We track whether a request is assigned to a new vehicle + information.numberOfReassignments++; + } } } } @@ -628,14 +635,14 @@ private void performRelocation(Solution solution, double now, Information inform information.numberOfRelocations++; } - + if (settings.useStepwiseRelocation) { List stopVehicles = new ArrayList<>(relocatableVehicles); relocations.forEach(r -> stopVehicles.remove(r.vehicle)); - + for (AlonsoMoraVehicle vehicle : stopVehicles) { - vehicle.setRoute( - Collections.singletonList(new AlonsoMoraStop(StopType.Relocation, vehicle.getNextDiversion(now).link, null))); + vehicle.setRoute(Collections.singletonList( + new AlonsoMoraStop(StopType.Relocation, vehicle.getNextDiversion(now).link, null))); scheduler.schedule(vehicle, now); } } @@ -740,8 +747,6 @@ static public class AlgorithmSettings { final boolean useBindingRelocations; final boolean useStepwiseRelocation; final boolean preserveVehicleAssignments; - final boolean usePlannedPickupTime; - final double plannedPickupTimeSlack; final double relocationInterval; final boolean allowBareReassignment; final double loggingInterval; @@ -750,18 +755,15 @@ static public class AlgorithmSettings { final int tripGraphlimitPerSequenceLength; public AlgorithmSettings(AlonsoMoraConfigGroup config) { - this.useBindingRelocations = config.getUseBindingRelocations(); - this.useStepwiseRelocation = config.getUseStepwiseRelocation(); - this.preserveVehicleAssignments = config.getCongestionMitigationParameters() - .getPreserveVehicleAssignments(); - this.usePlannedPickupTime = config.getUsePlannedPickupTime(); - this.plannedPickupTimeSlack = config.getPlannedPickupTimeSlack(); - this.relocationInterval = config.getRelocationInterval(); - this.allowBareReassignment = config.getCongestionMitigationParameters().getAllowBareReassignment(); - this.loggingInterval = config.getLoggingInterval(); - this.candidateVehiclesPerRequest = config.getCandidateVehiclesPerRequest(); - this.tripGraphLimitPerVehicle = config.getTripGraphLimitPerVehicle(); - this.tripGraphlimitPerSequenceLength = config.getTripGraphLimitPerSequenceLength(); + this.useBindingRelocations = config.useBindingRelocations; + this.useStepwiseRelocation = config.useStepwiseRelocation; + this.preserveVehicleAssignments = config.congestionMitigation.preserveVehicleAssignments; + this.relocationInterval = config.relocationInterval; + this.allowBareReassignment = config.congestionMitigation.allowBareReassignment; + this.loggingInterval = config.loggingInterval; + this.candidateVehiclesPerRequest = config.candidateVehiclesPerRequest; + this.tripGraphLimitPerVehicle = config.tripGraphLimitPerVehicle; + this.tripGraphlimitPerSequenceLength = config.tripGraphLimitPerSequenceLength; } } diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequest.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequest.java index 1652b4f..f1cd8bb 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequest.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequest.java @@ -1,7 +1,5 @@ package org.matsim.alonso_mora.algorithm; -import java.util.Collection; - import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; import org.matsim.contrib.drt.passenger.DrtRequest; @@ -34,9 +32,9 @@ public interface AlonsoMoraRequest extends Comparable { double getLatestAssignmentTime(); - Collection getDrtRequests(); - - Collection getAcceptedDrtRequests(); + DrtRequest getDrtRequest(); + + AcceptedDrtRequest getAcceptedDrtRequest(); public int getSize(); @@ -59,4 +57,6 @@ public interface AlonsoMoraRequest extends Comparable { public double getDirectRideDistance(); public double getEarliestPickupTime(); + + public void accept(AcceptedDrtRequest acceptedRequest); } diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequestFactory.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequestFactory.java index e3e179e..6a00688 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequestFactory.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraRequestFactory.java @@ -1,7 +1,5 @@ package org.matsim.alonso_mora.algorithm; -import java.util.Collection; - import org.matsim.contrib.drt.passenger.DrtRequest; /** @@ -11,6 +9,6 @@ * @author sebhoerl */ public interface AlonsoMoraRequestFactory { - AlonsoMoraRequest createRequest(Collection requests, double directArrvialTime, double earliestDepartureTime, + AlonsoMoraRequest createRequest(DrtRequest request, double directArrvialTime, double earliestDepartureTime, double directRideDistance); } diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraStop.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraStop.java index f71559d..fc60d75 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraStop.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/AlonsoMoraStop.java @@ -1,7 +1,5 @@ package org.matsim.alonso_mora.algorithm; -import java.util.stream.Collectors; - import org.matsim.api.core.v01.network.Link; import org.matsim.core.utils.misc.Time; @@ -56,7 +54,6 @@ public void setTime(double time) { @Override public String toString() { return String.format("Stop[%s,%s@%s,(%s)]", stopType.toString(), Time.writeTime(time), link.getId().toString(), - request != null ? request.getDrtRequests().stream().map(r -> r.getId().toString()) - .collect(Collectors.joining(",")) : ""); + request != null ? request.getDrtRequest().getId().toString() : ""); } } diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequest.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequest.java index 6d58ee3..9e5a0d9 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequest.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequest.java @@ -1,17 +1,12 @@ package org.matsim.alonso_mora.algorithm; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; import org.matsim.contrib.drt.passenger.DrtRequest; import org.matsim.contrib.drt.schedule.DrtStopTask; import org.matsim.contrib.dvrp.schedule.Task.TaskStatus; +import com.google.common.base.Preconditions; import com.google.common.base.Verify; /** @@ -26,8 +21,8 @@ * @author sebhoerl */ public class DefaultAlonsoMoraRequest implements AlonsoMoraRequest { - private final List drtRequests; - private List acceptedDrtRequests; + private final DrtRequest drtRequest; + private AcceptedDrtRequest acceptedDrtRequest; private DrtStopTask pickupTask; private DrtStopTask dropoffTask; @@ -49,41 +44,22 @@ public class DefaultAlonsoMoraRequest implements AlonsoMoraRequest { private final double directRideDistance; - public DefaultAlonsoMoraRequest(Collection drtRequests, double latestAssignmentTime, - double directArrivalTime, double directRideDistance) { + public DefaultAlonsoMoraRequest(DrtRequest drtRequest, double latestAssignmentTime, double directArrivalTime, + double directRideDistance) { this.directArrivalTime = directArrivalTime; this.directRideDistance = directRideDistance; + this.drtRequest = drtRequest; + this.cachedHashCode = drtRequest.getId().index(); - this.drtRequests = new ArrayList<>(drtRequests); - Collections.sort(this.drtRequests, (a, b) -> Integer.compare(a.getId().index(), b.getId().index())); - - { - /* - * We need a unique has code for the aggregated requests. - */ - int hashCode = 13; - - for (int i = 0; i < this.drtRequests.size(); i++) { - DrtRequest drtRquest = this.drtRequests.get(i); - hashCode += 27 * (i + 1) * drtRquest.getId().index(); - } - - this.cachedHashCode = hashCode; - } - - this.pickupLink = this.drtRequests.get(0).getFromLink(); - this.dropoffLink = this.drtRequests.get(0).getToLink(); + this.pickupLink = this.drtRequest.getFromLink(); + this.dropoffLink = this.drtRequest.getToLink(); - this.latestPickupTime = this.drtRequests.stream().mapToDouble(r -> r.getLatestStartTime()).min().getAsDouble(); - this.latestDropoffTime = this.drtRequests.stream().mapToDouble(r -> r.getLatestArrivalTime()).min() - .getAsDouble(); - this.earliestPickupTime = this.drtRequests.stream().mapToDouble(r -> r.getEarliestStartTime()).max() - .getAsDouble(); + this.latestPickupTime = this.drtRequest.getLatestStartTime(); + this.latestDropoffTime = this.drtRequest.getLatestArrivalTime(); + this.earliestPickupTime = this.drtRequest.getEarliestStartTime(); - for (DrtRequest request : this.drtRequests) { - Verify.verify(this.pickupLink.equals(request.getFromLink())); - Verify.verify(this.dropoffLink.equals(request.getToLink())); - } + Verify.verify(this.pickupLink.equals(drtRequest.getFromLink())); + Verify.verify(this.dropoffLink.equals(drtRequest.getToLink())); this.latestAssignmentTime = Math.min(getLatestPickupTime(), latestAssignmentTime); } @@ -97,18 +73,7 @@ public int compareTo(AlonsoMoraRequest otherRequest) { return sizeComparison; } - DefaultAlonsoMoraRequest otherDefaultRequest = (DefaultAlonsoMoraRequest) otherRequest; - - for (int i = 0; i < getSize(); i++) { - int indexComparison = Integer.compare(drtRequests.get(i).getId().index(), - otherDefaultRequest.drtRequests.get(i).getId().index()); - - if (indexComparison != 0) { - return indexComparison; - } - } - - return 0; + return Integer.compare(drtRequest.getId().index(), otherRequest.getDrtRequest().getId().index()); } throw new IllegalStateException(); @@ -168,19 +133,14 @@ public double getLatestAssignmentTime() { return latestAssignmentTime; } - public Collection getDrtRequests() { - return drtRequests; + public DrtRequest getDrtRequest() { + return drtRequest; } - - public Collection getAcceptedDrtRequests() { - if (acceptedDrtRequests == null) { - acceptedDrtRequests = drtRequests.stream().map(AcceptedDrtRequest::createFromOriginalRequest) - .collect(Collectors.toList()); - } - - return acceptedDrtRequests; + + public AcceptedDrtRequest getAcceptedDrtRequest() { + return acceptedDrtRequest; } - + @Override public void setVehicle(AlonsoMoraVehicle vehicle) { this.vehicle = vehicle; @@ -208,7 +168,7 @@ public boolean isAssigned() { @Override public int getSize() { - return drtRequests.size(); + return drtRequest.getPassengerCount(); } @Override @@ -245,17 +205,6 @@ public double getPlannedPickupTime() { } } - /** - * Sets the planned pickup time. This only happens once on the first assignment, - * afterwards the pickup time has been promised and can not be changed again. - */ - @Override - public void setPlannedPickupTime(double plannedPickupTime) { - if (Double.isNaN(this.plannedPickupTime)) { - this.plannedPickupTime = plannedPickupTime; - } - } - @Override public double getDirectRideDistance() { return directRideDistance; @@ -268,6 +217,18 @@ public double getEarliestPickupTime() { @Override public String toString() { - return "{" + drtRequests.stream().map(r -> r.getId().toString()).collect(Collectors.joining(",")) + "}"; + return drtRequest.toString(); + } + + @Override + public void accept(AcceptedDrtRequest acceptedRequest) { + Preconditions.checkArgument(this.acceptedDrtRequest == null); + this.acceptedDrtRequest = acceptedRequest; + this.plannedPickupTime = acceptedRequest.getLatestStartTime(); + } + + @Override + public void setPlannedPickupTime(double plannedPickupTime) { + throw new IllegalStateException(); } } diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequestFactory.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequestFactory.java index ddf78cc..5b0127f 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequestFactory.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/DefaultAlonsoMoraRequestFactory.java @@ -1,7 +1,5 @@ package org.matsim.alonso_mora.algorithm; -import java.util.Collection; - import org.matsim.contrib.drt.passenger.DrtRequest; /** @@ -19,13 +17,12 @@ public DefaultAlonsoMoraRequestFactory(double maximumQueueTime) { } @Override - public AlonsoMoraRequest createRequest(Collection requests, double directArrvialTime, double earliestDepartureTime, + public AlonsoMoraRequest createRequest(DrtRequest request, double directArrvialTime, double earliestDepartureTime, double directRideDistance) { double latestAssignmentTime = earliestDepartureTime + maximumQueueTime; - double latestPickupTime = requests.stream().mapToDouble(r -> r.getLatestStartTime()).min() - .orElse(Double.POSITIVE_INFINITY); + double latestPickupTime = request.getLatestStartTime(); latestAssignmentTime = Math.min(latestAssignmentTime, latestPickupTime); - return new DefaultAlonsoMoraRequest(requests, latestAssignmentTime, directArrvialTime, directRideDistance); + return new DefaultAlonsoMoraRequest(request, latestAssignmentTime, directArrvialTime, directRideDistance); } } diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/function/DefaultAlonsoMoraFunction.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/function/DefaultAlonsoMoraFunction.java index 689674c..0518e87 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/function/DefaultAlonsoMoraFunction.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/function/DefaultAlonsoMoraFunction.java @@ -19,6 +19,7 @@ import org.matsim.alonso_mora.algorithm.function.sequence.SequenceGeneratorFactory; import org.matsim.alonso_mora.travel_time.TravelTimeEstimator; import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; import org.matsim.contrib.dvrp.util.LinkTimePair; import com.google.common.base.Verify; @@ -32,7 +33,9 @@ public class DefaultAlonsoMoraFunction implements AlonsoMoraFunction { private final TravelTimeEstimator travelTimeEstimator; private final SequenceGeneratorFactory generatorFactory; - private final double stopDuration; + + private final PassengerStopDurationProvider stopDurationProvider; + private final double vehicleStopDuration; private final boolean allowPickupViolations; private final boolean allowPickupsWithDropoffViolations; @@ -46,11 +49,13 @@ public class DefaultAlonsoMoraFunction implements AlonsoMoraFunction { private final boolean preferNonViolation; public DefaultAlonsoMoraFunction(TravelTimeEstimator travelTimeEstimator, SequenceGeneratorFactory generatorFactory, - double stopDuration, boolean allowPickupViolations, boolean allowPickupsWithDropoffViolations, + PassengerStopDurationProvider stopDurationProvider, double vehicleStopDuration, + boolean allowPickupViolations, boolean allowPickupsWithDropoffViolations, boolean checkDeterminsticTravelTimes, Objective objective, Constraint constraint, double violationFactor, double violationOffset, boolean preferNonViolation) { this.travelTimeEstimator = travelTimeEstimator; - this.stopDuration = stopDuration; + this.vehicleStopDuration = vehicleStopDuration; + this.stopDurationProvider = stopDurationProvider; this.generatorFactory = generatorFactory; this.allowPickupViolations = allowPickupViolations; @@ -82,13 +87,13 @@ public boolean checkShareability(AlonsoMoraRequest firstRequest, AlonsoMoraReque Map requiredPickupTimes = new HashMap<>(); Map requiredDropoffTimes = new HashMap<>(); - requiredPickupTimes.put(firstRequest, firstRequest.getLatestPickupTime()); - requiredPickupTimes.put(secondRequest, secondRequest.getLatestPickupTime()); + requiredPickupTimes.put(firstRequest, firstRequest.getPlannedPickupTime()); + requiredPickupTimes.put(secondRequest, secondRequest.getPlannedPickupTime()); requiredDropoffTimes.put(firstRequest, firstRequest.getLatestDropoffTime()); requiredDropoffTimes.put(secondRequest, secondRequest.getLatestDropoffTime()); - RouteTracker tracker = new RouteTracker(travelTimeEstimator, stopDuration, 0, now, Optional.empty(), - requiredPickupTimes, requiredDropoffTimes); + RouteTracker tracker = new RouteTracker(null, travelTimeEstimator, stopDurationProvider, vehicleStopDuration, 0, + now, Optional.empty(), requiredPickupTimes, requiredDropoffTimes); while (generator.hasNext()) { List stops = generator.get(); @@ -101,7 +106,7 @@ public boolean checkShareability(AlonsoMoraRequest firstRequest, AlonsoMoraReque switch (stop.getType()) { case Pickup: - double maximumPickupTime = stop.getRequest().getLatestPickupTime(); + double maximumPickupTime = stop.getRequest().getPlannedPickupTime(); double calculatedPickupTime = stop.getTime(); if (calculatedPickupTime > maximumPickupTime) { @@ -205,7 +210,7 @@ public Optional calculateRoute(Collection requests, A SequenceGenerator generator = generatorFactory.createGenerator(vehicle, onboardRequests, requests, now); // Set up the timing and occupancy tracker - RouteTracker tracker = new RouteTracker(travelTimeEstimator, stopDuration, + RouteTracker tracker = new RouteTracker(vehicle, travelTimeEstimator, stopDurationProvider, vehicleStopDuration, onboardRequests.stream().mapToInt(AlonsoMoraRequest::getSize).sum(), diversion.time, Optional.of(diversion.link), requiredPickupTimes, requiredDropoffTimes); @@ -312,11 +317,11 @@ public Optional calculateRoute(Collection requests, A } boolean hasViolations = totalViolations > 0.0; - + if (partialObjective > bestObjective) { boolean initiallyValid = isValid; isValid = false; // Per default invalid because worse than the one we know - + if (initiallyValid && preferNonViolation && bestHasViolations && !hasViolations) { isValid = true; // Special case: We prefer non-violating solutions even if objective is worse } @@ -336,7 +341,7 @@ public Optional calculateRoute(Collection requests, A if (isValid) { if (generator.isComplete()) { // We found a new solution that is better than the old one (see objective - // contraint above) + // constraint above) bestSolution = copySolution(stops); bestObjective = partialObjective; bestHasViolations = hasViolations; diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/function/RouteTracker.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/function/RouteTracker.java index 53ccc68..626bce3 100644 --- a/core/src/main/java/org/matsim/alonso_mora/algorithm/function/RouteTracker.java +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/function/RouteTracker.java @@ -13,6 +13,8 @@ import org.matsim.alonso_mora.travel_time.TravelTimeEstimator; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.drt.schedule.DrtDriveTask; +import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.path.VrpPaths; import org.matsim.contrib.dvrp.schedule.DriveTask; @@ -24,7 +26,10 @@ */ public class RouteTracker { private final TravelTimeEstimator estimator; - private final double stopDuration; + private final AlonsoMoraVehicle vehicle; + + private final PassengerStopDurationProvider stopDurationProvider; + private final double vehicleStopDuration; private final int initialOccupancy; private final double initialDepartureTime; @@ -37,26 +42,32 @@ public class RouteTracker { private final Map requiredPickupTimes; private final Map requiredDropoffTimes; - public RouteTracker(TravelTimeEstimator estimator, double stopDuration, int initialOccupancy, + public RouteTracker(AlonsoMoraVehicle vehicle, TravelTimeEstimator estimator, + PassengerStopDurationProvider stopDurationProvider, double vehicleStopDuration, int initialOccupancy, double initialDepartureTime, Optional initialLink) { this.estimator = estimator; - this.stopDuration = stopDuration; + this.stopDurationProvider = stopDurationProvider; this.initialDepartureTime = initialDepartureTime; this.initialOccupancy = initialOccupancy; this.initialLink = initialLink; + this.vehicleStopDuration = vehicleStopDuration; + this.vehicle = vehicle; this.requiredPickupTimes = Collections.emptyMap(); this.requiredDropoffTimes = Collections.emptyMap(); } - public RouteTracker(TravelTimeEstimator estimator, double stopDuration, int initialOccupancy, + public RouteTracker(AlonsoMoraVehicle vehicle, TravelTimeEstimator estimator, + PassengerStopDurationProvider stopDurationProvider, double vehicleStopDuration, int initialOccupancy, double initialDepartureTime, Optional initialLink, Map requiredPickupTimes, Map requiredDropoffTimes) { this.estimator = estimator; - this.stopDuration = stopDuration; + this.stopDurationProvider = stopDurationProvider; this.initialDepartureTime = initialDepartureTime; this.initialOccupancy = initialOccupancy; this.initialLink = initialLink; + this.vehicleStopDuration = vehicleStopDuration; + this.vehicle = vehicle; this.requiredPickupTimes = requiredPickupTimes; this.requiredDropoffTimes = requiredDropoffTimes; @@ -116,6 +127,11 @@ public int update(List stops) { Link toLink = stops.get(i).getLink(); + /* + * sehoerl, January 2014: Do we need this additional condition here for i == 0? + * Need to modify the else block to make it possible that persons are inserted + * into ongoing stop tasks, like it is done in DRT. + */ if (fromLink != toLink || i == 0) { double arrivalTimeThreshold = Double.POSITIVE_INFINITY; @@ -138,18 +154,38 @@ public int update(List stops) { arrivalTime = correctArrivalTime(arrivalTime, fromLink != toLink); } - double stopDepartureTime = arrivalTime + stopDuration; - double stopArrivalTime = arrivalTime; + AlonsoMoraStop stop = stops.get(i); - // The following is only relevant for pre-booked requests - // If we are too early, we add a waiting time to the vehicle until the earliest - // pickup time - if (stops.get(i).getType().equals(StopType.Pickup)) { - double earliestDepartureTime = stops.get(i).getRequest().getEarliestPickupTime(); - double vehicleWaitingTime = Math.max(0.0, earliestDepartureTime - stopDepartureTime); + final double stopArrivalTime; + if (stop.getType().equals(StopType.Pickup)) { + // The following is only relevant for pre-booked requests + // If we are too early, we add a waiting time to the vehicle until the earliest + // pickup time + + stopArrivalTime = Math.max(arrivalTime, stop.getRequest().getEarliestPickupTime()); + } else { + stopArrivalTime = arrivalTime; + } + + final double vehicleDepartureTime = stopArrivalTime + vehicleStopDuration; + + final double stopDepartureTime; + if (stop.getType().equals(StopType.Pickup)) { + double passengerPickupTime = stopArrivalTime + stopDurationProvider + .calcPickupDuration(dvrpVehicle(vehicle), stop.getRequest().getDrtRequest()); + stop.setTime(passengerPickupTime); - stopArrivalTime += vehicleWaitingTime; - stopDepartureTime += vehicleWaitingTime; + stopDepartureTime = Math.max(passengerPickupTime, vehicleDepartureTime); + } else if (stop.getType().equals(StopType.Dropoff)) { + double passengerDropoffTime = stopArrivalTime + stopDurationProvider + .calcDropoffDuration(dvrpVehicle(vehicle), stop.getRequest().getDrtRequest()); + stop.setTime(passengerDropoffTime); + + stopDepartureTime = Math.max(passengerDropoffTime, vehicleDepartureTime); + } else if (stop.getType().equals(StopType.Relocation)) { + stopDepartureTime = stopArrivalTime; // relocation + } else { + throw new IllegalStateException(); } arrivalTimes.add(stopArrivalTime); @@ -157,18 +193,30 @@ public int update(List stops) { } else { // We don't move. - double stopArrivalTime = arrivalTimes.get(i - 1); - double stopDepartureTime = departureTimes.get(i - 1); + final double stopArrivalTime = arrivalTimes.get(i - 1); + AlonsoMoraStop stop = stops.get(i); - // The following is only relevant for pre-booked requests - // If we are too early, we add another task with a new arrival time - if (stops.get(i).getType().equals(StopType.Pickup)) { - double expectedDepartureTime = stops.get(i).getRequest().getEarliestPickupTime(); + final double vehicleDepartureTime = stopArrivalTime + vehicleStopDuration; - if (expectedDepartureTime > stopDepartureTime) { - stopArrivalTime = expectedDepartureTime; - stopDepartureTime = stopArrivalTime + stopDuration; - } + final double stopDepartureTime; + if (stop.getType().equals(StopType.Pickup)) { + double passengerDepartureTime = Math.max(stopArrivalTime, + stop.getRequest().getEarliestPickupTime()); + double passengerPickupTime = passengerDepartureTime + stopDurationProvider + .calcPickupDuration(dvrpVehicle(vehicle), stop.getRequest().getDrtRequest()); + stop.setTime(passengerPickupTime); + + stopDepartureTime = Math.max(passengerPickupTime, vehicleDepartureTime); + } else if (stop.getType().equals(StopType.Dropoff)) { + double passengerDropoffTime = stopArrivalTime + stopDurationProvider + .calcDropoffDuration(dvrpVehicle(vehicle), stop.getRequest().getDrtRequest()); + stop.setTime(passengerDropoffTime); + + stopDepartureTime = Math.max(passengerDropoffTime, vehicleDepartureTime); + } else if (stop.getType().equals(StopType.Relocation)) { + stopDepartureTime = stopArrivalTime; // relocation + } else { + throw new IllegalStateException(); } arrivalTimes.add(stopArrivalTime); @@ -183,20 +231,6 @@ public int update(List stops) { } } - for (int i = 0; i < stops.size(); i++) { - /* - * In DRT, agents are dropped off right when the vehicle arrives and picked up - * after the stopDuration. The first corresponds to "arrivalTime" here and the - * latter to "departureTime". - */ - - if (stops.get(i).getType().equals(StopType.Pickup)) { - stops.get(i).setTime(departureTimes.get(i)); - } else { - stops.get(i).setTime(arrivalTimes.get(i)); - } - } - return partialIndex; } @@ -230,6 +264,10 @@ private double correctArrivalTime(double arrivalTime, boolean needsMoving) { return arrivalTime; } + private DvrpVehicle dvrpVehicle(AlonsoMoraVehicle vehicle) { + return vehicle == null ? null : vehicle.getVehicle(); + } + public double getDepartureTime(int index) { return departureTimes.get(index); } diff --git a/core/src/main/java/org/matsim/alonso_mora/algorithm/relocation/NoopRelocationSolver.java b/core/src/main/java/org/matsim/alonso_mora/algorithm/relocation/NoopRelocationSolver.java new file mode 100644 index 0000000..76a732a --- /dev/null +++ b/core/src/main/java/org/matsim/alonso_mora/algorithm/relocation/NoopRelocationSolver.java @@ -0,0 +1,17 @@ +package org.matsim.alonso_mora.algorithm.relocation; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * @author sebhoerl + */ +public class NoopRelocationSolver implements RelocationSolver { + static public final String TYPE = "Noop"; + + @Override + public Collection solve(List candidates) { + return Collections.emptySet(); + } +} diff --git a/core/src/main/java/org/matsim/alonso_mora/example/RunNewYork.java b/core/src/main/java/org/matsim/alonso_mora/example/RunNewYork.java index 2849cc8..f72d5e1 100644 --- a/core/src/main/java/org/matsim/alonso_mora/example/RunNewYork.java +++ b/core/src/main/java/org/matsim/alonso_mora/example/RunNewYork.java @@ -36,10 +36,10 @@ import org.matsim.core.config.CommandLine; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; -import org.matsim.core.config.groups.PlanCalcScoreConfigGroup.ActivityParams; -import org.matsim.core.config.groups.PlanCalcScoreConfigGroup.ModeParams; import org.matsim.core.config.groups.QSimConfigGroup.StarttimeInterpretation; -import org.matsim.core.config.groups.StrategyConfigGroup.StrategySettings; +import org.matsim.core.config.groups.ReplanningConfigGroup.StrategySettings; +import org.matsim.core.config.groups.ScoringConfigGroup.ActivityParams; +import org.matsim.core.config.groups.ScoringConfigGroup.ModeParams; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; import org.matsim.core.scenario.ScenarioUtils; @@ -165,9 +165,9 @@ static public void main(String[] args) throws CommandLine.ConfigurationException } // Set up config - config.controler().setOutputDirectory(outputPath); - config.controler().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); - config.controler().setLastIteration(0); + config.controller().setOutputDirectory(outputPath); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setLastIteration(0); config.qsim().setNumberOfThreads(Math.min(12, threads)); config.global().setNumberOfThreads(threads); @@ -181,27 +181,27 @@ static public void main(String[] args) throws CommandLine.ConfigurationException config.qsim().setEndTime(endTime); ModeParams modeParams = new ModeParams("drt"); - config.planCalcScore().addModeParams(modeParams); + config.scoring().addModeParams(modeParams); ActivityParams genericParams = new ActivityParams("generic"); genericParams.setScoringThisActivityAtAll(false); - config.planCalcScore().addActivityParams(genericParams); + config.scoring().addActivityParams(genericParams); ActivityParams interactionParams = new ActivityParams("drt interaction"); interactionParams.setScoringThisActivityAtAll(false); - config.planCalcScore().addActivityParams(interactionParams); + config.scoring().addActivityParams(interactionParams); StrategySettings keepSettings = new StrategySettings(); keepSettings.setStrategyName("BestScore"); keepSettings.setWeight(1.0); - config.strategy().addStrategySettings(keepSettings); + config.replanning().addStrategySettings(keepSettings); DvrpConfigGroup dvrpConfig = new DvrpConfigGroup(); config.addModule(dvrpConfig); MultiModeDrtConfigGroup drtConfig = new MultiModeDrtConfigGroup(); config.addModule(drtConfig); - + DrtConfigGroup modeConfig = new DrtConfigGroup(); modeConfig.mode = TransportMode.drt; modeConfig.maxTravelTimeAlpha = detourFactor; @@ -245,21 +245,19 @@ public void install() { AlonsoMoraConfigGroup amConfig = new AlonsoMoraConfigGroup(); multiModeConfig.addParameterSet(amConfig); - amConfig.setMaximumQueueTime(0.0); - - amConfig.setAssignmentInterval(30); - amConfig.setRelocationInterval(30); - - amConfig.getCongestionMitigationParameters().setAllowBareReassignment(false); - amConfig.getCongestionMitigationParameters().setAllowPickupViolations(true); - amConfig.getCongestionMitigationParameters().setAllowPickupsWithDropoffViolations(true); - amConfig.getCongestionMitigationParameters().setPreserveVehicleAssignments(true); + amConfig.maximumQueueTime = 0.0; - amConfig.setRerouteDuringScheduling(false); + amConfig.assignmentInterval = 30; + amConfig.relocationInterval = 30; - amConfig.setCheckDeterminsticTravelTimes(true); + amConfig.congestionMitigation.allowBareReassignment = false; + amConfig.congestionMitigation.allowPickupViolations = true; + amConfig.congestionMitigation.allowPickupsWithDropoffViolations = true; + amConfig.congestionMitigation.preserveVehicleAssignments = true; - amConfig.setSequenceGeneratorType(SequenceGeneratorType.Combined); + amConfig.rerouteDuringScheduling = false; + amConfig.checkDeterminsticTravelTimes = true; + amConfig.sequenceGeneratorType = SequenceGeneratorType.Combined; GlpkMpsAssignmentParameters assignmentParameters = new GlpkMpsAssignmentParameters(); amConfig.addParameterSet(assignmentParameters); @@ -270,7 +268,7 @@ public void install() { MatrixEstimatorParameters estimator = new MatrixEstimatorParameters(); amConfig.addParameterSet(estimator); - AlonsoMoraConfigurator.configure(controller, amConfig.getMode()); + AlonsoMoraConfigurator.configure(controller, amConfig.mode); } controller.run(); diff --git a/core/src/main/java/org/matsim/alonso_mora/scheduling/DefaultAlonsoMoraScheduler.java b/core/src/main/java/org/matsim/alonso_mora/scheduling/DefaultAlonsoMoraScheduler.java index f549541..5cd3298 100644 --- a/core/src/main/java/org/matsim/alonso_mora/scheduling/DefaultAlonsoMoraScheduler.java +++ b/core/src/main/java/org/matsim/alonso_mora/scheduling/DefaultAlonsoMoraScheduler.java @@ -20,6 +20,7 @@ import org.matsim.contrib.drt.schedule.DrtTaskFactory; import org.matsim.contrib.drt.schedule.DrtTaskType; import org.matsim.contrib.drt.scheduler.EmptyVehicleRelocator; +import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.path.VrpPathWithTravelData; import org.matsim.contrib.dvrp.path.VrpPaths; @@ -52,7 +53,8 @@ public class DefaultAlonsoMoraScheduler implements AlonsoMoraScheduler { private final LeastCostPathCalculator router; private final TravelTime travelTime; - private final double stopDuration; + private final PassengerStopDurationProvider stopDurationProvider; + private final double vehicleStopDuration; private final boolean checkDeterminsticTravelTimes; private final boolean reroutingDuringScheduling; @@ -60,18 +62,19 @@ public class DefaultAlonsoMoraScheduler implements AlonsoMoraScheduler { private final StayTaskEndTimeCalculator endTimeCalculator; - public DefaultAlonsoMoraScheduler(DrtTaskFactory taskFactory, double stopDuration, - boolean checkDeterminsticTravelTimes, boolean reroutingDuringScheduling, TravelTime travelTime, - Network network, StayTaskEndTimeCalculator endTimeCalculator, LeastCostPathCalculator router, - OperationalVoter operationalVoter) { + public DefaultAlonsoMoraScheduler(DrtTaskFactory taskFactory, PassengerStopDurationProvider stopDurationProvider, + double vehicleStopDuration, boolean checkDeterminsticTravelTimes, boolean reroutingDuringScheduling, + TravelTime travelTime, Network network, StayTaskEndTimeCalculator endTimeCalculator, + LeastCostPathCalculator router, OperationalVoter operationalVoter) { this.taskFactory = taskFactory; - this.stopDuration = stopDuration; + this.vehicleStopDuration = vehicleStopDuration; this.checkDeterminsticTravelTimes = checkDeterminsticTravelTimes; this.reroutingDuringScheduling = reroutingDuringScheduling; this.endTimeCalculator = endTimeCalculator; this.travelTime = travelTime; this.router = router; this.operationalVoter = operationalVoter; + this.stopDurationProvider = stopDurationProvider; } /** @@ -115,23 +118,23 @@ private void verifyActivePickupAndDropoff(AlonsoMoraVehicle vehicle, List currentTask.getEndTime()) { - currentTask = new WaitForStopTask(currentTask.getEndTime(), expectedStartTime, currentLink); - schedule.addTask(currentTask); + double earliestStartTime = stop.getRequest().getEarliestPickupTime(); + + if (earliestStartTime > currentTask.getEndTime()) { + if (currentTask instanceof DrtStayTask) { + currentTask.setEndTime(earliestStartTime); + } else { + currentTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), + earliestStartTime, currentLink); + schedule.addTask(currentTask); + } } } + // Obtain the stop duration + final double passengerStopDuration; + + if (stop.getType().equals(StopType.Pickup)) { + passengerStopDuration = stopDurationProvider.calcPickupDuration(dvrpVehicle, + stop.getRequest().getDrtRequest()); + } else if (stop.getType().equals(StopType.Dropoff)) { + passengerStopDuration = stopDurationProvider.calcDropoffDuration(dvrpVehicle, + stop.getRequest().getDrtRequest()); + } else { + throw new IllegalStateException(); + } + // Now, retrieve or create the stop task DrtStopTask stopTask = null; @@ -278,6 +298,8 @@ public void schedule(AlonsoMoraVehicle vehicle, double now) { stopTask = (DrtStopTask) currentTask; } else { // Create a new stop task as we are not at a previously created stop + double stopDuration = Math.max(vehicleStopDuration, passengerStopDuration); + stopTask = taskFactory.createStopTask(dvrpVehicle, currentTask.getEndTime(), currentTask.getEndTime() + stopDuration, stop.getLink()); @@ -288,9 +310,14 @@ public void schedule(AlonsoMoraVehicle vehicle, double now) { // Add requests to the stop task if (stop.getType().equals(StopType.Pickup)) { - stop.getRequest().getAcceptedDrtRequests().forEach(stopTask::addPickupRequest); + stopTask.addPickupRequest(stop.getRequest().getAcceptedDrtRequest()); stop.getRequest().setPickupTask(vehicle, stopTask); + double passengerDepartureTime = Math.max(stopTask.getBeginTime(), + stop.getRequest().getEarliestPickupTime()); + double passengerPickupTime = passengerDepartureTime + passengerStopDuration; + stopTask.setEndTime(Math.max(stopTask.getEndTime(), passengerPickupTime)); + if (checkDeterminsticTravelTimes) { Verify.verify(stop.getTime() == stopTask.getEndTime(), "Checking for determinstic travel times and found mismatch between expected stop time and scheduled stop time."); @@ -298,8 +325,10 @@ public void schedule(AlonsoMoraVehicle vehicle, double now) { "Checking for determinstic travel times and found mismatch between expected stop time and planned stop time."); } } else if (stop.getType().equals(StopType.Dropoff)) { - stop.getRequest().getAcceptedDrtRequests().forEach(stopTask::addDropoffRequest); + stopTask.addDropoffRequest(stop.getRequest().getAcceptedDrtRequest()); stop.getRequest().setDropoffTask(vehicle, stopTask); + stopTask.setEndTime( + Math.max(stopTask.getEndTime(), stopTask.getBeginTime() + passengerStopDuration)); if (checkDeterminsticTravelTimes) { Verify.verify(stop.getTime() == stopTask.getBeginTime(), @@ -443,9 +472,9 @@ public void schedule(AlonsoMoraVehicle vehicle, double now) { if (currentTask instanceof DrtStayTask) { currentTask.setEndTime(Math.max(currentTask.getEndTime(), vehicle.getVehicle().getServiceEndTime())); - }else if(currentTask instanceof WaitForShiftStayTask) { - if(currentTask.getEndTime() == now) { - //if the shift just started, re-create the stay task + } else if (currentTask instanceof WaitForShiftStayTask) { + if (currentTask.getEndTime() == now) { + // if the shift just started, re-create the stay task StayTask stayTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), Math.max(currentTask.getEndTime(), vehicle.getVehicle().getServiceEndTime()), currentLink); schedule.addTask(stayTask); diff --git a/core/src/main/java/org/matsim/alonso_mora/scheduling/StandardRebalancer.java b/core/src/main/java/org/matsim/alonso_mora/scheduling/StandardRebalancer.java index a0ee788..205050c 100644 --- a/core/src/main/java/org/matsim/alonso_mora/scheduling/StandardRebalancer.java +++ b/core/src/main/java/org/matsim/alonso_mora/scheduling/StandardRebalancer.java @@ -60,7 +60,7 @@ private void rebalanceFleet() { for (Relocation r : relocations) { Link currentLink = ((DrtStayTask) r.vehicle.getSchedule().getCurrentTask()).getLink(); if (currentLink != r.link) { - relocator.relocateVehicle(r.vehicle, r.link); + relocator.relocateVehicle(r.vehicle, r.link, EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE); } } } diff --git a/core/src/main/java/org/matsim/alonso_mora/scheduling/WaitForStopTask.java b/core/src/main/java/org/matsim/alonso_mora/scheduling/WaitForStopTask.java deleted file mode 100644 index fb190d4..0000000 --- a/core/src/main/java/org/matsim/alonso_mora/scheduling/WaitForStopTask.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.matsim.alonso_mora.scheduling; - -import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.STAY; - -import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.schedule.DrtTaskType; -import org.matsim.contrib.dvrp.schedule.DefaultStayTask; - -import com.google.common.base.MoreObjects; - -public class WaitForStopTask extends DefaultStayTask { - public static final DrtTaskType TYPE = new DrtTaskType("WaitForStop", STAY); - - public WaitForStopTask(double beginTime, double endTime, Link link) { - super(TYPE, beginTime, endTime, link); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this).add("super", super.toString()).toString(); - } -} diff --git a/core/src/main/java/org/matsim/alonso_mora/shifts/ShiftAlonsoMoraModule.java b/core/src/main/java/org/matsim/alonso_mora/shifts/ShiftAlonsoMoraModule.java index e760ddb..64705f3 100644 --- a/core/src/main/java/org/matsim/alonso_mora/shifts/ShiftAlonsoMoraModule.java +++ b/core/src/main/java/org/matsim/alonso_mora/shifts/ShiftAlonsoMoraModule.java @@ -16,7 +16,8 @@ import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.schedule.DrtStayTaskEndTimeCalculator; import org.matsim.contrib.drt.schedule.DrtTaskFactory; -import org.matsim.contrib.drt.schedule.StopDurationEstimator; +import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; +import org.matsim.contrib.drt.stops.StopTimeCalculator; import org.matsim.contrib.dvrp.run.AbstractDvrpModeQSimModule; import org.matsim.contrib.dvrp.schedule.ScheduleTimingUpdater; import org.matsim.contrib.dvrp.schedule.ScheduleTimingUpdater.StayTaskEndTimeCalculator; @@ -44,7 +45,7 @@ protected void configureQSim() { // TODO: This can become a general binding in DRT bindModal(StayTaskEndTimeCalculator.class).toProvider(modalProvider(getter -> { return new ShiftDrtStayTaskEndTimeCalculator(shiftConfig, - new DrtStayTaskEndTimeCalculator(getter.getModal(StopDurationEstimator.class))); + new DrtStayTaskEndTimeCalculator(getter.getModal(StopTimeCalculator.class))); })); bindModal(OperationalVoter.class).toProvider(modalProvider(getter -> { @@ -71,10 +72,11 @@ protected void configureQSim() { Network network = getter.getModal(Network.class); OperationalVoter operationalVoter = getter.getModal(OperationalVoter.class); - - return new ShiftAlonsoMoraScheduler(taskFactory, drtConfig.stopDuration, - amConfig.getCheckDeterminsticTravelTimes(), amConfig.getRerouteDuringScheduling(), travelTime, - network, endTimeCalculator, router, operationalVoter); + PassengerStopDurationProvider stopDurationProvider = getter.getModal(PassengerStopDurationProvider.class); + + return new ShiftAlonsoMoraScheduler(taskFactory, stopDurationProvider, drtConfig.stopDuration, + amConfig.checkDeterminsticTravelTimes, amConfig.rerouteDuringScheduling, travelTime, network, + endTimeCalculator, router, operationalVoter); })); } } diff --git a/core/src/main/java/org/matsim/alonso_mora/shifts/ShiftAlonsoMoraScheduler.java b/core/src/main/java/org/matsim/alonso_mora/shifts/ShiftAlonsoMoraScheduler.java index c37c2db..4ebe041 100644 --- a/core/src/main/java/org/matsim/alonso_mora/shifts/ShiftAlonsoMoraScheduler.java +++ b/core/src/main/java/org/matsim/alonso_mora/shifts/ShiftAlonsoMoraScheduler.java @@ -11,19 +11,19 @@ import org.matsim.alonso_mora.algorithm.AlonsoMoraStop.StopType; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; import org.matsim.alonso_mora.scheduling.AlonsoMoraScheduler; -import org.matsim.alonso_mora.scheduling.WaitForStopTask; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftBreakTask; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftChangeOverTask; import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftStayTask; -import org.matsim.contrib.drt.passenger.DrtRequest; +import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; import org.matsim.contrib.drt.schedule.DrtDriveTask; import org.matsim.contrib.drt.schedule.DrtStayTask; import org.matsim.contrib.drt.schedule.DrtStopTask; import org.matsim.contrib.drt.schedule.DrtTaskFactory; import org.matsim.contrib.drt.schedule.DrtTaskType; import org.matsim.contrib.drt.scheduler.EmptyVehicleRelocator; +import org.matsim.contrib.drt.stops.PassengerStopDurationProvider; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.path.VrpPathWithTravelData; import org.matsim.contrib.dvrp.path.VrpPaths; @@ -52,433 +52,462 @@ * @author sebhoerl */ public class ShiftAlonsoMoraScheduler implements AlonsoMoraScheduler { - private final DrtTaskFactory taskFactory; - private final LeastCostPathCalculator router; - private final TravelTime travelTime; - - private final double stopDuration; - private final boolean checkDeterminsticTravelTimes; - private final boolean reroutingDuringScheduling; - - private final org.matsim.alonso_mora.scheduling.DefaultAlonsoMoraScheduler.OperationalVoter operationalVoter; - - private final StayTaskEndTimeCalculator endTimeCalculator; - - public ShiftAlonsoMoraScheduler(DrtTaskFactory taskFactory, double stopDuration, - boolean checkDeterminsticTravelTimes, boolean reroutingDuringScheduling, TravelTime travelTime, - Network network, StayTaskEndTimeCalculator endTimeCalculator, LeastCostPathCalculator router, - org.matsim.alonso_mora.scheduling.DefaultAlonsoMoraScheduler.OperationalVoter operationalVoter) { - this.taskFactory = taskFactory; - this.stopDuration = stopDuration; - this.checkDeterminsticTravelTimes = checkDeterminsticTravelTimes; - this.reroutingDuringScheduling = reroutingDuringScheduling; - this.endTimeCalculator = endTimeCalculator; - this.travelTime = travelTime; - this.router = router; - this.operationalVoter = operationalVoter; - } - - /** - * This is an additional check that makes sure that the result of the travel - * function does include stops for requests that are currently on board of the - * vehicle but have not been dropped off yet. - */ - private void verifyOnboardRequestsAreDroppedOff(AlonsoMoraVehicle vehicle, List stops) { - Set onboardRequests = new HashSet<>( - vehicle.getOnboardRequests().stream().filter(r -> !r.isDroppedOff()).collect(Collectors.toSet())); - - for (AlonsoMoraStop stop : stops) { - switch (stop.getType()) { - case Dropoff: - onboardRequests.remove(stop.getRequest()); - break; - case Pickup: - Verify.verify(!vehicle.getOnboardRequests().contains(stop.getRequest()), - "Cannot pick-up onboard request"); - break; - case Relocation: - break; - default: - throw new IllegalStateException(); - } - } - - Verify.verify(onboardRequests.size() == 0, "Some onboard requests are not dropped off"); - } - - /** - * This is an additional check that makes sure that pick-ups and drop-offs which - * are currently already in progress (task is started) are not added again as a - * stop. This can happen if the travel function is not implemented properly. - */ - private void verifyActivePickupAndDropoff(AlonsoMoraVehicle vehicle, List stops) { - Task currentTask = vehicle.getVehicle().getSchedule().getCurrentTask(); - - if (currentTask instanceof DrtStopTask) { - DrtStopTask stopTask = (DrtStopTask) currentTask; - - for (AlonsoMoraStop stop : stops) { - switch (stop.getType()) { - case Dropoff: - // This means that the stop list contains a stop with a request that is - // currently being dropped off in the current task. As we don't want to add - // another task with this request to the vehicle's schedule, this should not be - // here. Most likely, this is an error in the TravelFunction. - - for (DrtRequest drtRequest : stop.getRequest().getDrtRequests()) { - Verify.verify(!stopTask.getDropoffRequests().containsKey(drtRequest.getId())); - } - - break; - case Pickup: - for (DrtRequest drtRequest : stop.getRequest().getDrtRequests()) { - Verify.verify(!stopTask.getPickupRequests().containsKey(drtRequest.getId())); - } - - break; - case Relocation: - break; - default: - throw new IllegalStateException(); - } - } - } - } - - private void verifyRelocationIsLast(List stops) { - for (AlonsoMoraStop stop : stops) { - if (stop.getType().equals(StopType.Relocation)) { - Verify.verify(stops.get(stops.size() - 1) == stop, "Relocation must be the last!"); - } - } - } - - public void schedule(AlonsoMoraVehicle vehicle, double now) { - List stops = vehicle.getRoute(); - - verifyOnboardRequestsAreDroppedOff(vehicle, stops); - verifyActivePickupAndDropoff(vehicle, stops); - verifyRelocationIsLast(stops); - - DvrpVehicle dvrpVehicle = vehicle.getVehicle(); - Schedule schedule = dvrpVehicle.getSchedule(); - - Task currentTask = schedule.getCurrentTask(); - - // Verify that we understand what is in the schedule - for (int index = currentTask.getTaskIdx(); index < schedule.getTaskCount(); index++) { - Task task = schedule.getTasks().get(index); - - boolean isStayTask = task instanceof DrtStayTask; - boolean isStopTask = task instanceof DrtStopTask; - boolean isDriveTask = task instanceof DrtDriveTask; - boolean isWaitForStopTask = task instanceof WaitForStopTask; - boolean isOperationalTask = operationalVoter.isOperationalTask(task); - - Verify.verify(isStayTask || isStopTask || isDriveTask || isWaitForStopTask || isOperationalTask, - "Don't know what to do with this task"); - } - - // Collect operational tasks that need to be re-added at the end - List operationalTasks = new LinkedList<>(); - - for (int i = schedule.getCurrentTask().getTaskIdx() + 1; i < schedule.getTaskCount(); i++) { - Task task = schedule.getTasks().get(i); - - if (operationalVoter.isOperationalTask(task)) { - operationalTasks.add(task); - } - } - - // Clean up the task chain to reconstruct it - while (schedule.getTasks().get(schedule.getTaskCount() - 1).getStatus().equals(TaskStatus.PLANNED)) { - schedule.removeLastTask(); - } - - // Start rebuilding the schedule - - Link currentLink = null; - - if (operationalVoter.isOperationalTask(currentTask)) { - currentLink = ((StayTask) currentTask).getLink(); - } else if (currentTask instanceof StayTask) { - currentLink = ((StayTask) currentTask).getLink(); - - if (currentTask instanceof DrtStayTask || currentTask instanceof WaitForStopTask) { - // If we are currently staying somewhere, end the stay task now - currentTask.setEndTime(now); - } - } else if (currentTask instanceof DriveTask) { - // Will be handled individually further below - } else { - throw new IllegalStateException(); - } - - for (int index = 0; index < stops.size(); index++) { - AlonsoMoraStop stop = stops.get(index); - - if (stop.getType().equals(StopType.Pickup) || stop.getType().equals(StopType.Dropoff)) { - // We want to add a pickup or dropoff - - if (index == 0 && currentTask instanceof DriveTask) { - // Vehicle is driving, so we may need to divert it - - DriveTask driveTask = (DriveTask) currentTask; - - if (!driveTask.getTaskType().equals(DrtDriveTask.TYPE)) { - // Not a standard drive task, so we have to abort it - - OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); - LinkTimePair diversionPoint = tracker.getDiversionPoint(); - VrpPathWithTravelData diversionPath = VrpPaths.createZeroLengthPathForDiversion(diversionPoint); - tracker.divertPath(diversionPath); - - currentLink = diversionPoint.link; - } else { - // We have a standard drive task, so we can simply divert it - - if (driveTask.getPath().getToLink() != stop.getLink() || reroutingDuringScheduling) { - OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); - LinkTimePair diversionPoint = tracker.getDiversionPoint(); - VrpPathWithTravelData diversionPath = VrpPaths.calcAndCreatePathForDiversion(diversionPoint, - stop.getLink(), router, travelTime); - tracker.divertPath(diversionPath); - } - - currentLink = stop.getLink(); - } - } - - if (currentLink != stop.getLink()) { - // Add a conventional drive (e.g. after a previous stop) - - VrpPathWithTravelData drivePath = VrpPaths.calcAndCreatePath(currentLink, stop.getLink(), - currentTask.getEndTime(), router, travelTime); - - currentTask = taskFactory.createDriveTask(dvrpVehicle, drivePath, DrtDriveTask.TYPE); - schedule.addTask(currentTask); - - currentLink = stop.getLink(); - } - - // For pre-booked requests, we may need to wait for the customer - if (stop.getType().equals(StopType.Pickup)) { - double expectedStartTime = stop.getRequest().getEarliestPickupTime() - stopDuration; - - if (expectedStartTime > currentTask.getEndTime()) { - currentTask = new WaitForStopTask(currentTask.getEndTime(), expectedStartTime, currentLink); - schedule.addTask(currentTask); - } - } - - // Now, retrieve or create the stop task - - DrtStopTask stopTask = null; - - if (currentTask instanceof DrtStopTask && index > 0) { - // We're at a stop task and the stop task is not already started, so we can add - // the requests to this stop - - stopTask = (DrtStopTask) currentTask; - } else { - // Create a new stop task as we are not at a previously created stop - stopTask = taskFactory.createStopTask(dvrpVehicle, currentTask.getEndTime(), - currentTask.getEndTime() + stopDuration, stop.getLink()); - - schedule.addTask(stopTask); - currentTask = stopTask; - } - - // Add requests to the stop task - - if (stop.getType().equals(StopType.Pickup)) { - stop.getRequest().getAcceptedDrtRequests().forEach(stopTask::addPickupRequest); - stop.getRequest().setPickupTask(vehicle, stopTask); - - if (checkDeterminsticTravelTimes) { - Verify.verify(stop.getTime() == stopTask.getEndTime(), - "Checking for determinstic travel times and found mismatch between expected stop time and scheduled stop time."); - Verify.verify(stop.getTime() <= stop.getRequest().getPlannedPickupTime(), - "Checking for determinstic travel times and found mismatch between expected stop time and planned stop time."); - } - } else if (stop.getType().equals(StopType.Dropoff)) { - stop.getRequest().getAcceptedDrtRequests().forEach(stopTask::addDropoffRequest); - stop.getRequest().setDropoffTask(vehicle, stopTask); - - if (checkDeterminsticTravelTimes) { - Verify.verify(stop.getTime() == stopTask.getBeginTime(), - "Checking for determinstic travel times and found mismatch between expected stop time and scheduled stop time."); - } - } else { - throw new IllegalStateException(); - } - } else if (stop.getType().equals(StopType.Relocation)) { - // We want to add a relocation to the schedule - - if (index == 0 && currentTask instanceof DriveTask) { - // Vehicle is driving, so we may need to divert it - - DriveTask driveTask = (DriveTask) currentTask; - - if (!driveTask.getTaskType().equals(EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE)) { - // Not a relocation drive task, so we have to abort it - - OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); - LinkTimePair diversionPoint = tracker.getDiversionPoint(); - VrpPathWithTravelData diversionPath = VrpPaths.createZeroLengthPathForDiversion(diversionPoint); - tracker.divertPath(diversionPath); - - currentLink = diversionPoint.link; - } else { - // We have a relocation drive task, so we can simply divert it - - if (driveTask.getPath().getToLink() != stop.getLink() || reroutingDuringScheduling) { - OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); - LinkTimePair diversionPoint = tracker.getDiversionPoint(); - VrpPathWithTravelData diversionPath = VrpPaths.calcAndCreatePathForDiversion(diversionPoint, - stop.getLink(), router, travelTime); - tracker.divertPath(diversionPath); - } - - currentLink = stop.getLink(); - } - } - - if (currentLink != stop.getLink()) { - // Add a relocation drive (e.g. after a stop or aborting another drive) - - VrpPathWithTravelData drivePath = VrpPaths.calcAndCreatePath(currentLink, stop.getLink(), - currentTask.getEndTime(), router, travelTime); - currentTask = taskFactory.createDriveTask(dvrpVehicle, drivePath, - EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE); - schedule.addTask(currentTask); - - currentLink = stop.getLink(); - } - } else { - throw new IllegalStateException(); - } - } - - if (stops.size() == 0 && operationalTasks.size() == 0) { - if (currentTask instanceof DriveTask) { - // We have neither stops nor relocation -> stop the drive - - DriveTask driveTask = (DriveTask) currentTask; - - OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); - LinkTimePair diversionPoint = tracker.getDiversionPoint(); - VrpPathWithTravelData diversionPath = VrpPaths.createZeroLengthPathForDiversion(diversionPoint); - tracker.divertPath(diversionPath); - - currentLink = diversionPoint.link; - } - } - - // Add operational tasks - - if (operationalTasks.size() > 0) { - for (int index = 0; index < operationalTasks.size(); index++) { - Task operationalTask = operationalTasks.get(index); - Link operationalLink = ((StayTask) operationalTask).getLink(); - - DrtTaskType driveTaskType = operationalVoter.getDriveTaskType(operationalTask); - - if (index == 0 && stops.size() == 0 && currentTask instanceof DriveTask) { - // Vehicle is driving, so we may need to divert it - - DriveTask driveTask = (DriveTask) currentTask; - - if (!driveTask.getTaskType().equals(driveTaskType)) { - // Not a standard drive task, so we have to abort it - - OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); - LinkTimePair diversionPoint = tracker.getDiversionPoint(); - VrpPathWithTravelData diversionPath = VrpPaths.createZeroLengthPathForDiversion(diversionPoint); - tracker.divertPath(diversionPath); - - currentLink = diversionPoint.link; - } else { - // We have a fitting drive task, so we can simply divert it - - if (driveTask.getPath().getToLink() != operationalLink || reroutingDuringScheduling) { - OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); - LinkTimePair diversionPoint = tracker.getDiversionPoint(); - VrpPathWithTravelData diversionPath = VrpPaths.calcAndCreatePathForDiversion(diversionPoint, - operationalLink, router, travelTime); - tracker.divertPath(diversionPath); - } - - currentLink = operationalLink; - } - } - - if (currentLink != operationalLink) { - // Add a drive - - VrpPathWithTravelData drivePath = VrpPaths.calcAndCreatePath(currentLink, operationalLink, - currentTask.getEndTime(), router, travelTime); - - currentTask = taskFactory.createDriveTask(dvrpVehicle, drivePath, driveTaskType); - schedule.addTask(currentTask); - - currentLink = operationalLink; - } - - if (operationalTask.getBeginTime() > currentTask.getEndTime()) { - if(operationalTask instanceof ShiftBreakTask) { - // We need to fill the gap with a stay task if break is not planned to start yet - double earliestBreakStartTime = ((ShiftBreakTask) operationalTask).getShiftBreak().getEarliestBreakStartTime(); - if (earliestBreakStartTime > currentTask.getEndTime()) { - if(currentTask instanceof DrtStayTask) { - currentTask.setEndTime(earliestBreakStartTime); - } else { - currentTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), - earliestBreakStartTime, operationalLink); - schedule.addTask(currentTask); - } - } - } else if (operationalTask instanceof ShiftChangeOverTask) { - // We need to fill the gap with a stay task - double shiftEndTime = ((ShiftChangeOverTask) operationalTask).getShift().getEndTime(); - if(shiftEndTime > currentTask.getEndTime()) { - if(currentTask instanceof DrtStayTask) { - currentTask.setEndTime(shiftEndTime); - } else { - currentTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), - shiftEndTime, operationalLink); - schedule.addTask(currentTask); - } - } - } - } - - double endTime = endTimeCalculator.calcNewEndTime(dvrpVehicle, (StayTask) operationalTask, - currentTask.getEndTime()); - operationalTask.setBeginTime(currentTask.getEndTime()); - operationalTask.setEndTime(endTime); - - currentTask = operationalTask; - schedule.addTask(currentTask); - } - } - - // Finally, add stay task until the end of the schedule - - if (currentTask instanceof DrtStayTask) { - currentTask.setEndTime(Math.max(currentTask.getEndTime(), vehicle.getVehicle().getServiceEndTime())); - }else if(currentTask instanceof WaitForShiftStayTask) { - if(currentTask.getEndTime() == now) { - //if the shift just started, re-create the stay task - StayTask stayTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), - Math.max(currentTask.getEndTime(), vehicle.getVehicle().getServiceEndTime()), currentLink); - schedule.addTask(stayTask); - } - } else { - StayTask stayTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), - Math.max(currentTask.getEndTime(), vehicle.getVehicle().getServiceEndTime()), currentLink); - schedule.addTask(stayTask); - } - } + private final DrtTaskFactory taskFactory; + private final LeastCostPathCalculator router; + private final TravelTime travelTime; + + private final PassengerStopDurationProvider stopDurationProvider; + private final double vehicleStopDuration; + private final boolean checkDeterminsticTravelTimes; + private final boolean reroutingDuringScheduling; + + private final org.matsim.alonso_mora.scheduling.DefaultAlonsoMoraScheduler.OperationalVoter operationalVoter; + + private final StayTaskEndTimeCalculator endTimeCalculator; + + public ShiftAlonsoMoraScheduler(DrtTaskFactory taskFactory, PassengerStopDurationProvider stopDurationProvider, + double vehicleStopDuration, boolean checkDeterminsticTravelTimes, boolean reroutingDuringScheduling, + TravelTime travelTime, Network network, StayTaskEndTimeCalculator endTimeCalculator, + LeastCostPathCalculator router, + org.matsim.alonso_mora.scheduling.DefaultAlonsoMoraScheduler.OperationalVoter operationalVoter) { + this.taskFactory = taskFactory; + this.vehicleStopDuration = vehicleStopDuration; + this.checkDeterminsticTravelTimes = checkDeterminsticTravelTimes; + this.reroutingDuringScheduling = reroutingDuringScheduling; + this.endTimeCalculator = endTimeCalculator; + this.travelTime = travelTime; + this.router = router; + this.operationalVoter = operationalVoter; + this.stopDurationProvider = stopDurationProvider; + } + + /** + * This is an additional check that makes sure that the result of the travel + * function does include stops for requests that are currently on board of the + * vehicle but have not been dropped off yet. + */ + private void verifyOnboardRequestsAreDroppedOff(AlonsoMoraVehicle vehicle, List stops) { + Set onboardRequests = new HashSet<>( + vehicle.getOnboardRequests().stream().filter(r -> !r.isDroppedOff()).collect(Collectors.toSet())); + + for (AlonsoMoraStop stop : stops) { + switch (stop.getType()) { + case Dropoff: + onboardRequests.remove(stop.getRequest()); + break; + case Pickup: + Verify.verify(!vehicle.getOnboardRequests().contains(stop.getRequest()), + "Cannot pick-up onboard request"); + break; + case Relocation: + break; + default: + throw new IllegalStateException(); + } + } + + Verify.verify(onboardRequests.size() == 0, "Some onboard requests are not dropped off"); + } + + /** + * This is an additional check that makes sure that pick-ups and drop-offs which + * are currently already in progress (task is started) are not added again as a + * stop. This can happen if the travel function is not implemented properly. + */ + private void verifyActivePickupAndDropoff(AlonsoMoraVehicle vehicle, List stops) { + Task currentTask = vehicle.getVehicle().getSchedule().getCurrentTask(); + + if (currentTask instanceof DrtStopTask) { + DrtStopTask stopTask = (DrtStopTask) currentTask; + + for (AlonsoMoraStop stop : stops) { + switch (stop.getType()) { + case Dropoff: { + // This means that the stop list contains a stop with a request that is + // currently being dropped off in the current task. As we don't want to add + // another task with this request to the vehicle's schedule, this should not be + // here. Most likely, this is an error in the TravelFunction. + + AcceptedDrtRequest drtRequest = stop.getRequest().getAcceptedDrtRequest(); + Verify.verify(!stopTask.getDropoffRequests().containsKey(drtRequest.getId())); + + break; + } + case Pickup: { + AcceptedDrtRequest drtRequest = stop.getRequest().getAcceptedDrtRequest(); + Verify.verify(!stopTask.getPickupRequests().containsKey(drtRequest.getId())); + + break; + } + case Relocation: + break; + default: + throw new IllegalStateException(); + } + } + } + } + + private void verifyRelocationIsLast(List stops) { + for (AlonsoMoraStop stop : stops) { + if (stop.getType().equals(StopType.Relocation)) { + Verify.verify(stops.get(stops.size() - 1) == stop, "Relocation must be the last!"); + } + } + } + + public void schedule(AlonsoMoraVehicle vehicle, double now) { + List stops = vehicle.getRoute(); + + verifyOnboardRequestsAreDroppedOff(vehicle, stops); + verifyActivePickupAndDropoff(vehicle, stops); + verifyRelocationIsLast(stops); + + DvrpVehicle dvrpVehicle = vehicle.getVehicle(); + Schedule schedule = dvrpVehicle.getSchedule(); + + Task currentTask = schedule.getCurrentTask(); + + // Verify that we understand what is in the schedule + for (int index = currentTask.getTaskIdx(); index < schedule.getTaskCount(); index++) { + Task task = schedule.getTasks().get(index); + + boolean isStayTask = task instanceof DrtStayTask; + boolean isStopTask = task instanceof DrtStopTask; + boolean isDriveTask = task instanceof DrtDriveTask; + boolean isOperationalTask = operationalVoter.isOperationalTask(task); + + Verify.verify(isStayTask || isStopTask || isDriveTask || isOperationalTask, + "Don't know what to do with this task"); + } + + // Collect operational tasks that need to be re-added at the end + List operationalTasks = new LinkedList<>(); + + for (int i = schedule.getCurrentTask().getTaskIdx() + 1; i < schedule.getTaskCount(); i++) { + Task task = schedule.getTasks().get(i); + + if (operationalVoter.isOperationalTask(task)) { + operationalTasks.add(task); + } + } + + // Clean up the task chain to reconstruct it + while (schedule.getTasks().get(schedule.getTaskCount() - 1).getStatus().equals(TaskStatus.PLANNED)) { + schedule.removeLastTask(); + } + + // Start rebuilding the schedule + + Link currentLink = null; + + if (operationalVoter.isOperationalTask(currentTask)) { + currentLink = ((StayTask) currentTask).getLink(); + } else if (currentTask instanceof StayTask) { + currentLink = ((StayTask) currentTask).getLink(); + + if (currentTask instanceof DrtStayTask) { + // If we are currently staying somewhere, end the stay task now + currentTask.setEndTime(now); + } + } else if (currentTask instanceof DriveTask) { + // Will be handled individually further below + } else { + throw new IllegalStateException(); + } + + for (int index = 0; index < stops.size(); index++) { + AlonsoMoraStop stop = stops.get(index); + + if (stop.getType().equals(StopType.Pickup) || stop.getType().equals(StopType.Dropoff)) { + // We want to add a pickup or dropoff + + if (index == 0 && currentTask instanceof DriveTask) { + // Vehicle is driving, so we may need to divert it + + DriveTask driveTask = (DriveTask) currentTask; + + if (!driveTask.getTaskType().equals(DrtDriveTask.TYPE)) { + // Not a standard drive task, so we have to abort it + + OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); + LinkTimePair diversionPoint = tracker.getDiversionPoint(); + VrpPathWithTravelData diversionPath = VrpPaths.createZeroLengthPathForDiversion(diversionPoint); + tracker.divertPath(diversionPath); + + currentLink = diversionPoint.link; + } else { + // We have a standard drive task, so we can simply divert it + + if (driveTask.getPath().getToLink() != stop.getLink() || reroutingDuringScheduling) { + OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); + LinkTimePair diversionPoint = tracker.getDiversionPoint(); + VrpPathWithTravelData diversionPath = VrpPaths.calcAndCreatePathForDiversion(diversionPoint, + stop.getLink(), router, travelTime); + tracker.divertPath(diversionPath); + } + + currentLink = stop.getLink(); + } + } + + if (currentLink != stop.getLink()) { + // Add a conventional drive (e.g. after a previous stop) + + VrpPathWithTravelData drivePath = VrpPaths.calcAndCreatePath(currentLink, stop.getLink(), + currentTask.getEndTime(), router, travelTime); + + currentTask = taskFactory.createDriveTask(dvrpVehicle, drivePath, DrtDriveTask.TYPE); + schedule.addTask(currentTask); + + currentLink = stop.getLink(); + } + + // For pre-booked requests, we may need to wait for the customer + if (stop.getType().equals(StopType.Pickup)) { + double earliestStartTime = stop.getRequest().getEarliestPickupTime(); + + if (earliestStartTime > currentTask.getEndTime()) { + if (currentTask instanceof DrtStayTask) { + currentTask.setEndTime(earliestStartTime); + } else { + currentTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), + earliestStartTime, currentLink); + schedule.addTask(currentTask); + } + } + } + + // Obtain the stop duration + final double passengerStopDuration; + + if (stop.getType().equals(StopType.Pickup)) { + passengerStopDuration = stopDurationProvider.calcPickupDuration(dvrpVehicle, + stop.getRequest().getDrtRequest()); + } else if (stop.getType().equals(StopType.Dropoff)) { + passengerStopDuration = stopDurationProvider.calcDropoffDuration(dvrpVehicle, + stop.getRequest().getDrtRequest()); + } else { + throw new IllegalStateException(); + } + + // Now, retrieve or create the stop task + + DrtStopTask stopTask = null; + + if (currentTask instanceof DrtStopTask && index > 0) { + // We're at a stop task and the stop task is not already started, so we can add + // the requests to this stop + + stopTask = (DrtStopTask) currentTask; + } else { + // Create a new stop task as we are not at a previously created stop + double stopDuration = Math.max(vehicleStopDuration, passengerStopDuration); + + stopTask = taskFactory.createStopTask(dvrpVehicle, currentTask.getEndTime(), + currentTask.getEndTime() + stopDuration, stop.getLink()); + + schedule.addTask(stopTask); + currentTask = stopTask; + } + + // Add requests to the stop task + + if (stop.getType().equals(StopType.Pickup)) { + stopTask.addPickupRequest(stop.getRequest().getAcceptedDrtRequest()); + stop.getRequest().setPickupTask(vehicle, stopTask); + + double passengerDepartureTime = Math.max(stopTask.getBeginTime(), + stop.getRequest().getEarliestPickupTime()); + double passengerPickupTime = passengerDepartureTime + passengerStopDuration; + stopTask.setEndTime(Math.max(stopTask.getEndTime(), passengerPickupTime)); + + if (checkDeterminsticTravelTimes) { + Verify.verify(stop.getTime() == stopTask.getEndTime(), + "Checking for determinstic travel times and found mismatch between expected stop time and scheduled stop time."); + Verify.verify(stop.getTime() <= stop.getRequest().getPlannedPickupTime(), + "Checking for determinstic travel times and found mismatch between expected stop time and planned stop time."); + } + } else if (stop.getType().equals(StopType.Dropoff)) { + stopTask.addDropoffRequest(stop.getRequest().getAcceptedDrtRequest()); + stop.getRequest().setDropoffTask(vehicle, stopTask); + stopTask.setEndTime( + Math.max(stopTask.getEndTime(), stopTask.getBeginTime() + passengerStopDuration)); + + if (checkDeterminsticTravelTimes) { + Verify.verify(stop.getTime() == stopTask.getBeginTime(), + "Checking for determinstic travel times and found mismatch between expected stop time and scheduled stop time."); + } + } else { + throw new IllegalStateException(); + } + } else if (stop.getType().equals(StopType.Relocation)) { + // We want to add a relocation to the schedule + + if (index == 0 && currentTask instanceof DriveTask) { + // Vehicle is driving, so we may need to divert it + + DriveTask driveTask = (DriveTask) currentTask; + + if (!driveTask.getTaskType().equals(EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE)) { + // Not a relocation drive task, so we have to abort it + + OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); + LinkTimePair diversionPoint = tracker.getDiversionPoint(); + VrpPathWithTravelData diversionPath = VrpPaths.createZeroLengthPathForDiversion(diversionPoint); + tracker.divertPath(diversionPath); + + currentLink = diversionPoint.link; + } else { + // We have a relocation drive task, so we can simply divert it + + if (driveTask.getPath().getToLink() != stop.getLink() || reroutingDuringScheduling) { + OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); + LinkTimePair diversionPoint = tracker.getDiversionPoint(); + VrpPathWithTravelData diversionPath = VrpPaths.calcAndCreatePathForDiversion(diversionPoint, + stop.getLink(), router, travelTime); + tracker.divertPath(diversionPath); + } + + currentLink = stop.getLink(); + } + } + + if (currentLink != stop.getLink()) { + // Add a relocation drive (e.g. after a stop or aborting another drive) + + VrpPathWithTravelData drivePath = VrpPaths.calcAndCreatePath(currentLink, stop.getLink(), + currentTask.getEndTime(), router, travelTime); + currentTask = taskFactory.createDriveTask(dvrpVehicle, drivePath, + EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE); + schedule.addTask(currentTask); + + currentLink = stop.getLink(); + } + } else { + throw new IllegalStateException(); + } + } + + if (stops.size() == 0 && operationalTasks.size() == 0) { + if (currentTask instanceof DriveTask) { + // We have neither stops nor relocation -> stop the drive + + DriveTask driveTask = (DriveTask) currentTask; + + OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); + LinkTimePair diversionPoint = tracker.getDiversionPoint(); + VrpPathWithTravelData diversionPath = VrpPaths.createZeroLengthPathForDiversion(diversionPoint); + tracker.divertPath(diversionPath); + + currentLink = diversionPoint.link; + } + } + + // Add operational tasks + + if (operationalTasks.size() > 0) { + for (int index = 0; index < operationalTasks.size(); index++) { + Task operationalTask = operationalTasks.get(index); + Link operationalLink = ((StayTask) operationalTask).getLink(); + + DrtTaskType driveTaskType = operationalVoter.getDriveTaskType(operationalTask); + + if (index == 0 && stops.size() == 0 && currentTask instanceof DriveTask) { + // Vehicle is driving, so we may need to divert it + + DriveTask driveTask = (DriveTask) currentTask; + + if (!driveTask.getTaskType().equals(driveTaskType)) { + // Not a standard drive task, so we have to abort it + + OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); + LinkTimePair diversionPoint = tracker.getDiversionPoint(); + VrpPathWithTravelData diversionPath = VrpPaths.createZeroLengthPathForDiversion(diversionPoint); + tracker.divertPath(diversionPath); + + currentLink = diversionPoint.link; + } else { + // We have a fitting drive task, so we can simply divert it + + if (driveTask.getPath().getToLink() != operationalLink || reroutingDuringScheduling) { + OnlineDriveTaskTracker tracker = (OnlineDriveTaskTracker) driveTask.getTaskTracker(); + LinkTimePair diversionPoint = tracker.getDiversionPoint(); + VrpPathWithTravelData diversionPath = VrpPaths.calcAndCreatePathForDiversion(diversionPoint, + operationalLink, router, travelTime); + tracker.divertPath(diversionPath); + } + + currentLink = operationalLink; + } + } + + if (currentLink != operationalLink) { + // Add a drive + + VrpPathWithTravelData drivePath = VrpPaths.calcAndCreatePath(currentLink, operationalLink, + currentTask.getEndTime(), router, travelTime); + + currentTask = taskFactory.createDriveTask(dvrpVehicle, drivePath, driveTaskType); + schedule.addTask(currentTask); + + currentLink = operationalLink; + } + + if (operationalTask.getBeginTime() > currentTask.getEndTime()) { + if (operationalTask instanceof ShiftBreakTask) { + // We need to fill the gap with a stay task if break is not planned to start yet + double earliestBreakStartTime = ((ShiftBreakTask) operationalTask).getShiftBreak() + .getEarliestBreakStartTime(); + if (earliestBreakStartTime > currentTask.getEndTime()) { + if (currentTask instanceof DrtStayTask) { + currentTask.setEndTime(earliestBreakStartTime); + } else { + currentTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), + earliestBreakStartTime, operationalLink); + schedule.addTask(currentTask); + } + } + } else if (operationalTask instanceof ShiftChangeOverTask) { + // We need to fill the gap with a stay task + double shiftEndTime = ((ShiftChangeOverTask) operationalTask).getShift().getEndTime(); + if (shiftEndTime > currentTask.getEndTime()) { + if (currentTask instanceof DrtStayTask) { + currentTask.setEndTime(shiftEndTime); + } else { + currentTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), + shiftEndTime, operationalLink); + schedule.addTask(currentTask); + } + } + } + } + + double endTime = endTimeCalculator.calcNewEndTime(dvrpVehicle, (StayTask) operationalTask, + currentTask.getEndTime()); + operationalTask.setBeginTime(currentTask.getEndTime()); + operationalTask.setEndTime(endTime); + + currentTask = operationalTask; + schedule.addTask(currentTask); + } + } + + // Finally, add stay task until the end of the schedule + + if (currentTask instanceof DrtStayTask) { + currentTask.setEndTime(Math.max(currentTask.getEndTime(), vehicle.getVehicle().getServiceEndTime())); + } else if (currentTask instanceof WaitForShiftStayTask) { + if (currentTask.getEndTime() == now) { + // if the shift just started, re-create the stay task + StayTask stayTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), + Math.max(currentTask.getEndTime(), vehicle.getVehicle().getServiceEndTime()), currentLink); + schedule.addTask(stayTask); + } + } else { + StayTask stayTask = taskFactory.createStayTask(dvrpVehicle, currentTask.getEndTime(), + Math.max(currentTask.getEndTime(), vehicle.getVehicle().getServiceEndTime()), currentLink); + schedule.addTask(stayTask); + } + } } - diff --git a/core/src/test/java/org/matsim/alonso_mora/DiversionTest.java b/core/src/test/java/org/matsim/alonso_mora/DiversionTest.java index 9d893ff..8bc2699 100644 --- a/core/src/test/java/org/matsim/alonso_mora/DiversionTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/DiversionTest.java @@ -1,12 +1,13 @@ package org.matsim.alonso_mora; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.LinkedList; import java.util.List; import java.util.Objects; import java.util.Set; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; @@ -128,8 +129,8 @@ public void testRepeatedSameDestinationDiversions() { { /* Create some necessary configuration for the test */ - config.controler().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); - config.controler().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setLastIteration(0); config.qsim().setStartTime(0.0); config.qsim().setSimStarttimeInterpretation(StarttimeInterpretation.onlyUseStarttime); @@ -223,16 +224,16 @@ protected void configureQSim() { // Took the fixed value from the simulation, to make sure this stays consistent // over refactorings - Assert.assertEquals(testTracker.eventBasedArrivalTime, 657.0, 1e-3); + assertEquals(testTracker.eventBasedArrivalTime, 657.0, 1e-3); // Initially calculated arrival time should predict correctly the final arrival // time - Assert.assertEquals(testTracker.initialArrivalTime, 657.0, 1e-3); + assertEquals(testTracker.initialArrivalTime, 657.0, 1e-3); // Along the route, when diverting to the same destination, arrival time should // stay constant testTracker.diversionArrivalTimes.forEach(t -> { - Assert.assertEquals(t, 657.0, 1e-3); + assertEquals(t, 657.0, 1e-3); }); } @@ -454,8 +455,8 @@ public void testRepeatedDiversionToDifferentDestinationRightBeforeLastLink() { { /* Create some necessary configuration for the test */ - config.controler().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); - config.controler().setLastIteration(0); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setLastIteration(0); config.qsim().setStartTime(0.0); config.qsim().setSimStarttimeInterpretation(StarttimeInterpretation.onlyUseStarttime); @@ -552,16 +553,16 @@ protected void configureQSim() { // Took the fixed value from the simulation, to make sure this stays consistent // over refactorings - same as previous unit test - Assert.assertEquals(testTracker.eventBasedArrivalTime, 657.0, 1e-3); + assertEquals(testTracker.eventBasedArrivalTime, 657.0, 1e-3); // Initially calculated arrival time should predict correctly the final arrival // time - as in the first unit test as we route to L8 - Assert.assertEquals(testTracker.initialArrivalTime, 657.0, 1e-3); + assertEquals(testTracker.initialArrivalTime, 657.0, 1e-3); // Along the route, when diverting to the same destination, arrival time should // stay constant testTracker.diversionArrivalTimes.forEach(t -> { - Assert.assertEquals(t, 739.0, 1e-3); + assertEquals(t, 739.0, 1e-3); }); // Without fix in OnlineDriveTaskTrackerImpl, the last test will lead to a diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/CbcMpsAssignmentSolverTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/CbcMpsAssignmentSolverTest.java index cbd0960..5634dbf 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/CbcMpsAssignmentSolverTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/CbcMpsAssignmentSolverTest.java @@ -1,16 +1,17 @@ package org.matsim.alonso_mora.algorithm.assignment; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.List; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraTrip; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; @@ -18,12 +19,9 @@ import org.mockito.Mockito; public class CbcMpsAssignmentSolverTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Before - public void checkSolver() { - Assume.assumeTrue("Checking for availability of Cbc solver", CbcMpsAssignmentSolver.checkAvailability()); + @BeforeAll + static public void checkSolver() { + assertTrue(CbcMpsAssignmentSolver.checkAvailability(), "Checking for availability of Cbc solver"); } private AlonsoMoraRequest mockRequest() { @@ -48,9 +46,11 @@ private AlonsoMoraTrip mockTrip(AlonsoMoraVehicle vehicle, double cost, AlonsoMo } @Test - public void testOneVehicleOneRequestExample() throws IOException { - AssignmentSolver solver = new CbcMpsAssignmentSolver(9000.0, 9000.0, 1000, 0.1, - temporaryFolder.newFile("problem"), temporaryFolder.newFile("solution"), 0); + public void testOneVehicleOneRequestExample(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "problem"); + + AssignmentSolver solver = new CbcMpsAssignmentSolver(9000.0, 9000.0, 1000, 0.1, problemFile, solutionFile, 0); AlonsoMoraVehicle vehicle = mockVehicle(); AlonsoMoraRequest request = mockRequest(); @@ -59,14 +59,16 @@ public void testOneVehicleOneRequestExample() throws IOException { List candidates = Arrays.asList(trip); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip)); } @Test - public void testTwoIndependentRequests() throws IOException { - AssignmentSolver solver = new CbcMpsAssignmentSolver(9000.0, 9000.0, 1000, 0.1, - temporaryFolder.newFile("problem"), temporaryFolder.newFile("solution"), 0); + public void testTwoIndependentRequests(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "problem"); + + AssignmentSolver solver = new CbcMpsAssignmentSolver(9000.0, 9000.0, 1000, 0.1, problemFile, solutionFile, 0); AlonsoMoraVehicle vehicle1 = mockVehicle(); AlonsoMoraRequest request1 = mockRequest(); @@ -79,15 +81,17 @@ public void testTwoIndependentRequests() throws IOException { List candidates = Arrays.asList(trip1, trip2); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(2, selection.size()); - Assert.assertTrue(selection.contains(trip1)); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(2, selection.size()); + assertTrue(selection.contains(trip1)); + assertTrue(selection.contains(trip2)); } @Test - public void testTwoRequestsWithOneVehicle() throws IOException { - AssignmentSolver solver = new CbcMpsAssignmentSolver(9000.0, 9000.0, 1000, 0.1, - temporaryFolder.newFile("problem"), temporaryFolder.newFile("solution"), 0); + public void testTwoRequestsWithOneVehicle(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "problem"); + + AssignmentSolver solver = new CbcMpsAssignmentSolver(9000.0, 9000.0, 1000, 0.1, problemFile, solutionFile, 0); AlonsoMoraVehicle vehicle = mockVehicle(); AlonsoMoraRequest request1 = mockRequest(); @@ -104,15 +108,17 @@ public void testTwoRequestsWithOneVehicle() throws IOException { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip3)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip3)); } } @Test - public void testTwoRequestsWithOneVehicleLowPenalty() throws IOException { - AssignmentSolver solver = new CbcMpsAssignmentSolver(250.0, 250.0, 1000, 0.1, - temporaryFolder.newFile("problem"), temporaryFolder.newFile("solution"), 0); + public void testTwoRequestsWithOneVehicleLowPenalty(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "problem"); + + AssignmentSolver solver = new CbcMpsAssignmentSolver(250.0, 250.0, 1000, 0.1, problemFile, solutionFile, 0); AlonsoMoraVehicle vehicle = mockVehicle(); AlonsoMoraRequest request1 = mockRequest(); @@ -128,8 +134,8 @@ public void testTwoRequestsWithOneVehicleLowPenalty() throws IOException { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip1)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip1)); } } } diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GlpkMpsAssignmentSolverTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GlpkMpsAssignmentSolverTest.java index 6eb3846..f0beff4 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GlpkMpsAssignmentSolverTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GlpkMpsAssignmentSolverTest.java @@ -1,16 +1,17 @@ package org.matsim.alonso_mora.algorithm.assignment; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.List; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraTrip; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; @@ -18,12 +19,9 @@ import org.mockito.Mockito; public class GlpkMpsAssignmentSolverTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Before - public void checkSolver() { - Assume.assumeTrue("Checking for availability of GLPK solver", GlpkMpsAssignmentSolver.checkAvailability()); + @BeforeAll + static public void checkSolver() { + assertTrue(GlpkMpsAssignmentSolver.checkAvailability(), "Checking for availability of GLPK solver"); } private AlonsoMoraRequest mockRequest() { @@ -48,9 +46,12 @@ private AlonsoMoraTrip mockTrip(AlonsoMoraVehicle vehicle, double cost, AlonsoMo } @Test - public void testOneVehicleOneRequestExample() throws IOException { + public void testOneVehicleOneRequestExample(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "solution"); + AssignmentSolver solver = new GlpkMpsAssignmentSolver(9000.0, 9000.0, 1000, 0.1, - temporaryFolder.newFile("problem"), temporaryFolder.newFile("solution")); + problemFile, solutionFile); AlonsoMoraVehicle vehicle = mockVehicle(); AlonsoMoraRequest request = mockRequest(); @@ -59,14 +60,17 @@ public void testOneVehicleOneRequestExample() throws IOException { List candidates = Arrays.asList(trip); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip)); } @Test - public void testTwoIndependentRequests() throws IOException { + public void testTwoIndependentRequests(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "solution"); + AssignmentSolver solver = new GlpkMpsAssignmentSolver(9000.0, 9000.0, 1000, 0.1, - temporaryFolder.newFile("problem"), temporaryFolder.newFile("solution")); + problemFile, solutionFile); AlonsoMoraVehicle vehicle1 = mockVehicle(); AlonsoMoraRequest request1 = mockRequest(); @@ -79,15 +83,18 @@ public void testTwoIndependentRequests() throws IOException { List candidates = Arrays.asList(trip1, trip2); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(2, selection.size()); - Assert.assertTrue(selection.contains(trip1)); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(2, selection.size()); + assertTrue(selection.contains(trip1)); + assertTrue(selection.contains(trip2)); } @Test - public void testTwoRequestsWithOneVehicle() throws IOException { + public void testTwoRequestsWithOneVehicle(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "solution"); + AssignmentSolver solver = new GlpkMpsAssignmentSolver(9000.0, 9000.0, 1000, 0.1, - temporaryFolder.newFile("problem"), temporaryFolder.newFile("solution")); + problemFile, solutionFile); AlonsoMoraVehicle vehicle = mockVehicle(); AlonsoMoraRequest request1 = mockRequest(); @@ -104,15 +111,18 @@ public void testTwoRequestsWithOneVehicle() throws IOException { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip3)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip3)); } } @Test - public void testTwoRequestsWithOneVehicleLowPenalty() throws IOException { + public void testTwoRequestsWithOneVehicleLowPenalty(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "solution"); + AssignmentSolver solver = new GlpkMpsAssignmentSolver(250.0, 250.0, 1000, 0.1, - temporaryFolder.newFile("problem"), temporaryFolder.newFile("solution")); + problemFile, solutionFile); AlonsoMoraVehicle vehicle = mockVehicle(); AlonsoMoraRequest request1 = mockRequest(); @@ -128,8 +138,8 @@ public void testTwoRequestsWithOneVehicleLowPenalty() throws IOException { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip1)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip1)); } } } diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GreedyTripFirstAssignmentSolverTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GreedyTripFirstAssignmentSolverTest.java index c60e8d9..51d8914 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GreedyTripFirstAssignmentSolverTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GreedyTripFirstAssignmentSolverTest.java @@ -1,11 +1,13 @@ package org.matsim.alonso_mora.algorithm.assignment; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.Arrays; import java.util.Collection; import java.util.List; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraTrip; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; @@ -45,8 +47,8 @@ public void testOneVehicleOneRequestExample() { List candidates = Arrays.asList(trip); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip)); } @Test @@ -64,9 +66,9 @@ public void testTwoIndependentRequests() { List candidates = Arrays.asList(trip1, trip2); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(2, selection.size()); - Assert.assertTrue(selection.contains(trip1)); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(2, selection.size()); + assertTrue(selection.contains(trip1)); + assertTrue(selection.contains(trip2)); } @Test @@ -85,8 +87,8 @@ public void testTwoRequestsWithOneVehicle() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip1)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip1)); } { @@ -97,8 +99,8 @@ public void testTwoRequestsWithOneVehicle() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip2)); } { @@ -109,8 +111,8 @@ public void testTwoRequestsWithOneVehicle() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip3)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip3)); } } @@ -133,8 +135,8 @@ public void testTwoRequestsWithTwoVehicles() { List candidates = Arrays.asList(trip1, trip2, trip3, trip4); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip3)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip3)); } { @@ -146,9 +148,9 @@ public void testTwoRequestsWithTwoVehicles() { List candidates = Arrays.asList(trip1, trip2, trip3, trip4); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(2, selection.size()); - Assert.assertTrue(selection.contains(trip1)); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(2, selection.size()); + assertTrue(selection.contains(trip1)); + assertTrue(selection.contains(trip2)); } } } diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GreedyVehicleFirstAssignmentSolverTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GreedyVehicleFirstAssignmentSolverTest.java index 96bbabd..50966df 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GreedyVehicleFirstAssignmentSolverTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/assignment/GreedyVehicleFirstAssignmentSolverTest.java @@ -1,11 +1,13 @@ package org.matsim.alonso_mora.algorithm.assignment; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.Arrays; import java.util.Collection; import java.util.List; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraTrip; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; @@ -52,8 +54,8 @@ public void testOneVehicleOneRequestExample() { List candidates = Arrays.asList(trip); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip)); } @Test @@ -71,9 +73,9 @@ public void testTwoIndependentRequests() { List candidates = Arrays.asList(trip1, trip2); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(2, selection.size()); - Assert.assertTrue(selection.contains(trip1)); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(2, selection.size()); + assertTrue(selection.contains(trip1)); + assertTrue(selection.contains(trip2)); } @Test @@ -92,8 +94,8 @@ public void testTwoRequestsWithOneVehicle() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip1)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip1)); } { @@ -104,8 +106,8 @@ public void testTwoRequestsWithOneVehicle() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip2)); } { @@ -116,8 +118,8 @@ public void testTwoRequestsWithOneVehicle() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip3)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip3)); } } @@ -140,8 +142,8 @@ public void testTwoRequestsWithTwoVehicles() { List candidates = Arrays.asList(trip1, trip2, trip3, trip4); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip3)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip3)); } { @@ -153,9 +155,9 @@ public void testTwoRequestsWithTwoVehicles() { List candidates = Arrays.asList(trip1, trip2, trip3, trip4); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(2, selection.size()); - Assert.assertTrue(selection.contains(trip1)); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(2, selection.size()); + assertTrue(selection.contains(trip1)); + assertTrue(selection.contains(trip2)); } } } diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/RouteTrackerTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/RouteTrackerTest.java index 29951dd..f749d49 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/RouteTrackerTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/RouteTrackerTest.java @@ -1,16 +1,18 @@ package org.matsim.alonso_mora.algorithm.function; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.LinkedList; import java.util.List; import java.util.Optional; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraStop; import org.matsim.alonso_mora.algorithm.AlonsoMoraStop.StopType; import org.matsim.alonso_mora.travel_time.TravelTimeEstimator; import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.drt.stops.StaticPassengerStopDurationProvider; import org.mockito.Mockito; public class RouteTrackerTest { @@ -29,7 +31,7 @@ public void testInitializationWithoutLink() { AlonsoMoraRequest request = Mockito.mock(AlonsoMoraRequest.class); Mockito.when(request.getSize()).thenReturn(1); - RouteTracker tracker = new RouteTracker(estimator, 5.0, 3, 7000.0, Optional.empty()); + RouteTracker tracker = new RouteTracker(null, estimator, StaticPassengerStopDurationProvider.of(5.0, 0.0), 5.0, 3, 7000.0, Optional.empty()); List initialStops = new LinkedList<>(); initialStops.add(new AlonsoMoraStop(StopType.Pickup, linkA, request)); @@ -37,13 +39,13 @@ public void testInitializationWithoutLink() { tracker.update(initialStops); - Assert.assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); - Assert.assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); - Assert.assertEquals(7105.0, tracker.getArrivalTime(1), 1e-3); - Assert.assertEquals(7110.0, tracker.getDepartureTime(1), 1e-3); + assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); + assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); + assertEquals(7105.0, tracker.getArrivalTime(1), 1e-3); + assertEquals(7110.0, tracker.getDepartureTime(1), 1e-3); - Assert.assertEquals(4, tracker.getOccupancyAfter(0)); - Assert.assertEquals(3, tracker.getOccupancyAfter(1)); + assertEquals(4, tracker.getOccupancyAfter(0)); + assertEquals(3, tracker.getOccupancyAfter(1)); } @Test @@ -64,7 +66,7 @@ public void testInitializationWithLink() { AlonsoMoraRequest request = Mockito.mock(AlonsoMoraRequest.class); Mockito.when(request.getSize()).thenReturn(1); - RouteTracker tracker = new RouteTracker(estimator, 5.0, 3, 7000.0, Optional.of(linkVehicle)); + RouteTracker tracker = new RouteTracker(null, estimator, StaticPassengerStopDurationProvider.of(5.0, 0.0), 5.0, 3, 7000.0, Optional.of(linkVehicle)); List initialStops = new LinkedList<>(); initialStops.add(new AlonsoMoraStop(StopType.Pickup, linkA, request)); @@ -72,13 +74,13 @@ public void testInitializationWithLink() { tracker.update(initialStops); - Assert.assertEquals(7000.0 + 100.0, tracker.getArrivalTime(0), 1e-3); - Assert.assertEquals(7005.0 + 100.0, tracker.getDepartureTime(0), 1e-3); - Assert.assertEquals(7105.0 + 100.0, tracker.getArrivalTime(1), 1e-3); - Assert.assertEquals(7110.0 + 100.0, tracker.getDepartureTime(1), 1e-3); + assertEquals(7000.0 + 100.0, tracker.getArrivalTime(0), 1e-3); + assertEquals(7005.0 + 100.0, tracker.getDepartureTime(0), 1e-3); + assertEquals(7105.0 + 100.0, tracker.getArrivalTime(1), 1e-3); + assertEquals(7110.0 + 100.0, tracker.getDepartureTime(1), 1e-3); - Assert.assertEquals(4, tracker.getOccupancyAfter(0)); - Assert.assertEquals(3, tracker.getOccupancyAfter(1)); + assertEquals(4, tracker.getOccupancyAfter(0)); + assertEquals(3, tracker.getOccupancyAfter(1)); } @Test @@ -94,7 +96,7 @@ public void testMultipleRequests() { AlonsoMoraRequest request = Mockito.mock(AlonsoMoraRequest.class); Mockito.when(request.getSize()).thenReturn(1); - RouteTracker tracker = new RouteTracker(estimator, 5.0, 0, 7000.0, Optional.empty()); + RouteTracker tracker = new RouteTracker(null, estimator, StaticPassengerStopDurationProvider.of(5.0, 0.0), 5.0, 0, 7000.0, Optional.empty()); List initialStops = new LinkedList<>(); initialStops.add(new AlonsoMoraStop(StopType.Pickup, linkA, request)); @@ -106,30 +108,30 @@ public void testMultipleRequests() { tracker.update(initialStops); - Assert.assertEquals(7100.0, tracker.getArrivalTime(0), 1e-3); - Assert.assertEquals(7105.0, tracker.getDepartureTime(0), 1e-3); + assertEquals(7100.0, tracker.getArrivalTime(0), 1e-3); + assertEquals(7105.0, tracker.getDepartureTime(0), 1e-3); - Assert.assertEquals(7205.0, tracker.getArrivalTime(1), 1e-3); - Assert.assertEquals(7210.0, tracker.getDepartureTime(1), 1e-3); + assertEquals(7205.0, tracker.getArrivalTime(1), 1e-3); + assertEquals(7210.0, tracker.getDepartureTime(1), 1e-3); - Assert.assertEquals(7310.0, tracker.getArrivalTime(2), 1e-3); - Assert.assertEquals(7315.0, tracker.getDepartureTime(2), 1e-3); + assertEquals(7310.0, tracker.getArrivalTime(2), 1e-3); + assertEquals(7315.0, tracker.getDepartureTime(2), 1e-3); - Assert.assertEquals(7415.0, tracker.getArrivalTime(3), 1e-3); - Assert.assertEquals(7420.0, tracker.getDepartureTime(3), 1e-3); + assertEquals(7415.0, tracker.getArrivalTime(3), 1e-3); + assertEquals(7420.0, tracker.getDepartureTime(3), 1e-3); - Assert.assertEquals(7520.0, tracker.getArrivalTime(4), 1e-3); - Assert.assertEquals(7525.0, tracker.getDepartureTime(4), 1e-3); + assertEquals(7520.0, tracker.getArrivalTime(4), 1e-3); + assertEquals(7525.0, tracker.getDepartureTime(4), 1e-3); - Assert.assertEquals(7625.0, tracker.getArrivalTime(5), 1e-3); - Assert.assertEquals(7630.0, tracker.getDepartureTime(5), 1e-3); + assertEquals(7625.0, tracker.getArrivalTime(5), 1e-3); + assertEquals(7630.0, tracker.getDepartureTime(5), 1e-3); - Assert.assertEquals(1, tracker.getOccupancyAfter(0)); - Assert.assertEquals(2, tracker.getOccupancyAfter(1)); - Assert.assertEquals(1, tracker.getOccupancyAfter(2)); - Assert.assertEquals(0, tracker.getOccupancyAfter(3)); - Assert.assertEquals(1, tracker.getOccupancyAfter(4)); - Assert.assertEquals(0, tracker.getOccupancyAfter(5)); + assertEquals(1, tracker.getOccupancyAfter(0)); + assertEquals(2, tracker.getOccupancyAfter(1)); + assertEquals(1, tracker.getOccupancyAfter(2)); + assertEquals(0, tracker.getOccupancyAfter(3)); + assertEquals(1, tracker.getOccupancyAfter(4)); + assertEquals(0, tracker.getOccupancyAfter(5)); } @Test @@ -151,7 +153,7 @@ public void testGroupRequests() { AlonsoMoraRequest request3 = Mockito.mock(AlonsoMoraRequest.class); Mockito.when(request3.getSize()).thenReturn(3); - RouteTracker tracker = new RouteTracker(estimator, 5.0, 0, 7000.0, Optional.empty()); + RouteTracker tracker = new RouteTracker(null, estimator, StaticPassengerStopDurationProvider.of(5.0, 0.0), 5.0, 0, 7000.0, Optional.empty()); List initialStops = new LinkedList<>(); initialStops.add(new AlonsoMoraStop(StopType.Pickup, linkA, request1)); @@ -163,12 +165,12 @@ public void testGroupRequests() { tracker.update(initialStops); - Assert.assertEquals(2, tracker.getOccupancyAfter(0)); - Assert.assertEquals(3, tracker.getOccupancyAfter(1)); - Assert.assertEquals(2, tracker.getOccupancyAfter(2)); - Assert.assertEquals(0, tracker.getOccupancyAfter(3)); - Assert.assertEquals(3, tracker.getOccupancyAfter(4)); - Assert.assertEquals(0, tracker.getOccupancyAfter(5)); + assertEquals(2, tracker.getOccupancyAfter(0)); + assertEquals(3, tracker.getOccupancyAfter(1)); + assertEquals(2, tracker.getOccupancyAfter(2)); + assertEquals(0, tracker.getOccupancyAfter(3)); + assertEquals(3, tracker.getOccupancyAfter(4)); + assertEquals(0, tracker.getOccupancyAfter(5)); } @Test @@ -181,7 +183,7 @@ public void testMultipleRequestsWithStopAggregation() { estimator.estimateTravelTime(Mockito.any(), Mockito.any(), Mockito.anyDouble(), Mockito.anyDouble())) .thenReturn(100.0); - RouteTracker tracker = new RouteTracker(estimator, 5.0, 0, 7000.0, Optional.empty()); + RouteTracker tracker = new RouteTracker(null, estimator, StaticPassengerStopDurationProvider.of(5.0, 0.0), 5.0, 0, 7000.0, Optional.empty()); AlonsoMoraRequest request = Mockito.mock(AlonsoMoraRequest.class); Mockito.when(request.getSize()).thenReturn(1); @@ -196,30 +198,30 @@ public void testMultipleRequestsWithStopAggregation() { tracker.update(initialStops); - Assert.assertEquals(7100.0, tracker.getArrivalTime(0), 1e-3); - Assert.assertEquals(7105.0, tracker.getDepartureTime(0), 1e-3); + assertEquals(7100.0, tracker.getArrivalTime(0), 1e-3); + assertEquals(7105.0, tracker.getDepartureTime(0), 1e-3); - Assert.assertEquals(7100.0, tracker.getArrivalTime(1), 1e-3); - Assert.assertEquals(7105.0, tracker.getDepartureTime(1), 1e-3); + assertEquals(7100.0, tracker.getArrivalTime(1), 1e-3); + assertEquals(7105.0, tracker.getDepartureTime(1), 1e-3); - Assert.assertEquals(7205.0, tracker.getArrivalTime(2), 1e-3); - Assert.assertEquals(7210.0, tracker.getDepartureTime(2), 1e-3); + assertEquals(7205.0, tracker.getArrivalTime(2), 1e-3); + assertEquals(7210.0, tracker.getDepartureTime(2), 1e-3); - Assert.assertEquals(7205.0, tracker.getArrivalTime(3), 1e-3); - Assert.assertEquals(7210.0, tracker.getDepartureTime(3), 1e-3); + assertEquals(7205.0, tracker.getArrivalTime(3), 1e-3); + assertEquals(7210.0, tracker.getDepartureTime(3), 1e-3); - Assert.assertEquals(7310.0, tracker.getArrivalTime(4), 1e-3); - Assert.assertEquals(7315.0, tracker.getDepartureTime(4), 1e-3); + assertEquals(7310.0, tracker.getArrivalTime(4), 1e-3); + assertEquals(7315.0, tracker.getDepartureTime(4), 1e-3); - Assert.assertEquals(7415.0, tracker.getArrivalTime(5), 1e-3); - Assert.assertEquals(7420.0, tracker.getDepartureTime(5), 1e-3); + assertEquals(7415.0, tracker.getArrivalTime(5), 1e-3); + assertEquals(7420.0, tracker.getDepartureTime(5), 1e-3); - Assert.assertEquals(1, tracker.getOccupancyAfter(0)); - Assert.assertEquals(2, tracker.getOccupancyAfter(1)); - Assert.assertEquals(1, tracker.getOccupancyAfter(2)); - Assert.assertEquals(0, tracker.getOccupancyAfter(3)); - Assert.assertEquals(1, tracker.getOccupancyAfter(4)); - Assert.assertEquals(0, tracker.getOccupancyAfter(5)); + assertEquals(1, tracker.getOccupancyAfter(0)); + assertEquals(2, tracker.getOccupancyAfter(1)); + assertEquals(1, tracker.getOccupancyAfter(2)); + assertEquals(0, tracker.getOccupancyAfter(3)); + assertEquals(1, tracker.getOccupancyAfter(4)); + assertEquals(0, tracker.getOccupancyAfter(5)); } @Test @@ -238,7 +240,7 @@ public void testUpdateIndex() { Mockito.when(estimator.estimateTravelTime(Mockito.eq(linkB), Mockito.eq(linkB), Mockito.anyDouble(), Mockito.anyDouble())).thenReturn(0.0); - RouteTracker tracker = new RouteTracker(estimator, 5.0, 0, 7000.0, Optional.empty()); + RouteTracker tracker = new RouteTracker(null, estimator, StaticPassengerStopDurationProvider.of(5.0, 0.0), 5.0, 0, 7000.0, Optional.empty()); AlonsoMoraRequest request = Mockito.mock(AlonsoMoraRequest.class); Mockito.when(request.getSize()).thenReturn(1); @@ -246,26 +248,26 @@ public void testUpdateIndex() { { List sequence = new LinkedList<>(); sequence.add(new AlonsoMoraStop(StopType.Pickup, linkA, request)); - Assert.assertEquals(0, tracker.update(sequence)); + assertEquals(0, tracker.update(sequence)); - Assert.assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); - Assert.assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); - Assert.assertEquals(1, tracker.getOccupancyAfter(0)); + assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); + assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); + assertEquals(1, tracker.getOccupancyAfter(0)); } { List sequence = new LinkedList<>(); sequence.add(new AlonsoMoraStop(StopType.Pickup, linkA, request)); sequence.add(new AlonsoMoraStop(StopType.Pickup, linkB, request)); - Assert.assertEquals(1, tracker.update(sequence)); + assertEquals(1, tracker.update(sequence)); - Assert.assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); - Assert.assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); - Assert.assertEquals(1, tracker.getOccupancyAfter(0)); + assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); + assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); + assertEquals(1, tracker.getOccupancyAfter(0)); - Assert.assertEquals(7105.0, tracker.getArrivalTime(1), 1e-3); - Assert.assertEquals(7110.0, tracker.getDepartureTime(1), 1e-3); - Assert.assertEquals(2, tracker.getOccupancyAfter(1)); + assertEquals(7105.0, tracker.getArrivalTime(1), 1e-3); + assertEquals(7110.0, tracker.getDepartureTime(1), 1e-3); + assertEquals(2, tracker.getOccupancyAfter(1)); } { @@ -274,48 +276,48 @@ public void testUpdateIndex() { sequence.add(new AlonsoMoraStop(StopType.Pickup, linkB, request)); sequence.add(new AlonsoMoraStop(StopType.Dropoff, linkA, request)); sequence.add(new AlonsoMoraStop(StopType.Dropoff, linkB, request)); - Assert.assertEquals(2, tracker.update(sequence)); + assertEquals(2, tracker.update(sequence)); - Assert.assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); - Assert.assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); - Assert.assertEquals(1, tracker.getOccupancyAfter(0)); + assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); + assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); + assertEquals(1, tracker.getOccupancyAfter(0)); - Assert.assertEquals(7105.0, tracker.getArrivalTime(1), 1e-3); - Assert.assertEquals(7110.0, tracker.getDepartureTime(1), 1e-3); - Assert.assertEquals(2, tracker.getOccupancyAfter(1)); + assertEquals(7105.0, tracker.getArrivalTime(1), 1e-3); + assertEquals(7110.0, tracker.getDepartureTime(1), 1e-3); + assertEquals(2, tracker.getOccupancyAfter(1)); - Assert.assertEquals(7120.0, tracker.getArrivalTime(2), 1e-3); - Assert.assertEquals(7125.0, tracker.getDepartureTime(2), 1e-3); - Assert.assertEquals(1, tracker.getOccupancyAfter(2)); + assertEquals(7120.0, tracker.getArrivalTime(2), 1e-3); + assertEquals(7125.0, tracker.getDepartureTime(2), 1e-3); + assertEquals(1, tracker.getOccupancyAfter(2)); - Assert.assertEquals(7225.0, tracker.getArrivalTime(3), 1e-3); - Assert.assertEquals(7230.0, tracker.getDepartureTime(3), 1e-3); - Assert.assertEquals(0, tracker.getOccupancyAfter(3)); + assertEquals(7225.0, tracker.getArrivalTime(3), 1e-3); + assertEquals(7230.0, tracker.getDepartureTime(3), 1e-3); + assertEquals(0, tracker.getOccupancyAfter(3)); } { List sequence = new LinkedList<>(); sequence.add(new AlonsoMoraStop(StopType.Pickup, linkA, request)); sequence.add(new AlonsoMoraStop(StopType.Dropoff, linkA, request)); - Assert.assertEquals(1, tracker.update(sequence)); + assertEquals(1, tracker.update(sequence)); - Assert.assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); - Assert.assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); - Assert.assertEquals(1, tracker.getOccupancyAfter(0)); + assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); + assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); + assertEquals(1, tracker.getOccupancyAfter(0)); - Assert.assertEquals(7000.0, tracker.getArrivalTime(1), 1e-3); - Assert.assertEquals(7005.0, tracker.getDepartureTime(1), 1e-3); - Assert.assertEquals(0, tracker.getOccupancyAfter(1)); + assertEquals(7000.0, tracker.getArrivalTime(1), 1e-3); + assertEquals(7005.0, tracker.getDepartureTime(1), 1e-3); + assertEquals(0, tracker.getOccupancyAfter(1)); } { List sequence = new LinkedList<>(); sequence.add(new AlonsoMoraStop(StopType.Pickup, linkB, request)); - Assert.assertEquals(0, tracker.update(sequence)); + assertEquals(0, tracker.update(sequence)); - Assert.assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); - Assert.assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); - Assert.assertEquals(1, tracker.getOccupancyAfter(0)); + assertEquals(7000.0, tracker.getArrivalTime(0), 1e-3); + assertEquals(7005.0, tracker.getDepartureTime(0), 1e-3); + assertEquals(1, tracker.getOccupancyAfter(0)); } } } diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultRequestGraphTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultRequestGraphTest.java index 387a702..001c894 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultRequestGraphTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultRequestGraphTest.java @@ -1,11 +1,14 @@ package org.matsim.alonso_mora.algorithm.function.graphs; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.Collection; import java.util.Optional; import java.util.concurrent.ForkJoinPool; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; import org.matsim.alonso_mora.algorithm.function.AlonsoMoraFunction; @@ -29,19 +32,19 @@ public void testBasicMatching() { graph.addRequest(request1, 0.0); - Assert.assertEquals(0, graph.getShareableRequests(request1).size()); - Assert.assertEquals(0, graph.getShareableRequests(request2).size()); + assertEquals(0, graph.getShareableRequests(request1).size()); + assertEquals(0, graph.getShareableRequests(request2).size()); graph.addRequest(request2, 0.0); - Assert.assertEquals(1, graph.getShareableRequests(request1).size()); - Assert.assertEquals(1, graph.getShareableRequests(request2).size()); + assertEquals(1, graph.getShareableRequests(request1).size()); + assertEquals(1, graph.getShareableRequests(request2).size()); - Assert.assertTrue(graph.getShareableRequests(request1).contains(request2)); - Assert.assertTrue(graph.getShareableRequests(request2).contains(request1)); + assertTrue(graph.getShareableRequests(request1).contains(request2)); + assertTrue(graph.getShareableRequests(request2).contains(request1)); } - @Test(expected = VerifyException.class) + @Test public void testAddTwice() { MockRequest request1 = new MockRequest(1); @@ -49,7 +52,10 @@ public void testAddTwice() { RequestGraph graph = new DefaultRequestGraph(function, new ForkJoinPool(1)); graph.addRequest(request1, 0.0); - graph.addRequest(request1, 0.0); + + Assertions.assertThrows(VerifyException.class, () -> { + graph.addRequest(request1, 0.0); + }); } @Test @@ -69,14 +75,14 @@ public void testSelectiveMatching() { graph.addRequest(request7, 0.0); graph.addRequest(request8, 0.0); - Assert.assertEquals(2, graph.getShareableRequests(request1).size()); - Assert.assertEquals(1, graph.getShareableRequests(request7).size()); - Assert.assertEquals(1, graph.getShareableRequests(request8).size()); + assertEquals(2, graph.getShareableRequests(request1).size()); + assertEquals(1, graph.getShareableRequests(request7).size()); + assertEquals(1, graph.getShareableRequests(request8).size()); - Assert.assertTrue(graph.getShareableRequests(request1).contains(request7)); - Assert.assertTrue(graph.getShareableRequests(request1).contains(request8)); - Assert.assertTrue(graph.getShareableRequests(request7).contains(request1)); - Assert.assertTrue(graph.getShareableRequests(request8).contains(request1)); + assertTrue(graph.getShareableRequests(request1).contains(request7)); + assertTrue(graph.getShareableRequests(request1).contains(request8)); + assertTrue(graph.getShareableRequests(request7).contains(request1)); + assertTrue(graph.getShareableRequests(request8).contains(request1)); } private static class MockRequest implements AlonsoMoraRequest { @@ -150,13 +156,13 @@ public boolean isAssigned() { } @Override - public Collection getDrtRequests() { + public DrtRequest getDrtRequest() { // TODO Auto-generated method stub return null; } - + @Override - public Collection getAcceptedDrtRequests() { + public AcceptedDrtRequest getAcceptedDrtRequest() { // TODO Auto-generated method stub return null; } @@ -220,6 +226,12 @@ public double getEarliestPickupTime() { // TODO Auto-generated method stub return 0; } + + @Override + public void accept(AcceptedDrtRequest acceptedRequest) { + // TODO Auto-generated method stub + + } } private static class MockFunction implements AlonsoMoraFunction { diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultVehicleGraphTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultVehicleGraphTest.java index c5178ff..2c3f1f1 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultVehicleGraphTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/graphs/DefaultVehicleGraphTest.java @@ -1,5 +1,7 @@ package org.matsim.alonso_mora.algorithm.function.graphs; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -9,8 +11,7 @@ import java.util.Set; import java.util.stream.Collectors; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraTrip; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; @@ -46,8 +47,8 @@ public void testSingleRequest() { List trips = graph.stream().collect(Collectors.toList()); // Only one request, so we only expect one trip - Assert.assertEquals(1, trips.size()); - Assert.assertEquals(1, trips.stream().filter(t -> t.getLength() == 1).count()); + assertEquals(1, trips.size()); + assertEquals(1, trips.stream().filter(t -> t.getLength() == 1).count()); } @Test @@ -72,9 +73,9 @@ public void testTwoConnectedRequests() { List trips = graph.stream().collect(Collectors.toList()); // Two connected requests, we have two single rides and one combined - Assert.assertEquals(3, trips.size()); - Assert.assertEquals(2, trips.stream().filter(t -> t.getLength() == 1).count()); - Assert.assertEquals(1, trips.stream().filter(t -> t.getLength() == 2).count()); + assertEquals(3, trips.size()); + assertEquals(2, trips.stream().filter(t -> t.getLength() == 1).count()); + assertEquals(1, trips.stream().filter(t -> t.getLength() == 2).count()); } @Test @@ -98,8 +99,8 @@ public void testTwoUNConnectedRequests() { List trips = graph.stream().collect(Collectors.toList()); // Two unconnected requests, we have two single rides - Assert.assertEquals(2, trips.size()); - Assert.assertEquals(2, trips.stream().filter(t -> t.getLength() == 1).count()); + assertEquals(2, trips.size()); + assertEquals(2, trips.stream().filter(t -> t.getLength() == 1).count()); } @Test @@ -142,9 +143,9 @@ public void testComplexMatching2() { // Only two passengers allowed currently (weight 25), // we expect 5 single passengers rides and 3 + 3 = 6 two-passengres rides - Assert.assertEquals(11, trips.size()); - Assert.assertEquals(5, trips.stream().filter(t -> t.getLength() == 1).count()); - Assert.assertEquals(6, trips.stream().filter(t -> t.getLength() == 2).count()); + assertEquals(11, trips.size()); + assertEquals(5, trips.stream().filter(t -> t.getLength() == 1).count()); + assertEquals(6, trips.stream().filter(t -> t.getLength() == 2).count()); } @Test @@ -188,10 +189,10 @@ public void testComplexMatching3() { // we expect 5 single passengers rides and 3 + 3 = 6 two-passengres rides, and 2 // three-passenger rides - Assert.assertEquals(13, trips.size()); - Assert.assertEquals(5, trips.stream().filter(t -> t.getLength() == 1).count()); - Assert.assertEquals(6, trips.stream().filter(t -> t.getLength() == 2).count()); - Assert.assertEquals(2, trips.stream().filter(t -> t.getLength() == 3).count()); + assertEquals(13, trips.size()); + assertEquals(5, trips.stream().filter(t -> t.getLength() == 1).count()); + assertEquals(6, trips.stream().filter(t -> t.getLength() == 2).count()); + assertEquals(2, trips.stream().filter(t -> t.getLength() == 3).count()); } @Test @@ -241,11 +242,11 @@ public void testComplexMatching4() { // we expect 6 single passengers rides and 3 + 3 + 3 = 9 two-passengres rides, // and 4 three-passenger ride, 1 four-passenger-ride - Assert.assertEquals(21, trips.size()); - Assert.assertEquals(6, trips.stream().filter(t -> t.getLength() == 1).count()); - Assert.assertEquals(9, trips.stream().filter(t -> t.getLength() == 2).count()); - Assert.assertEquals(5, trips.stream().filter(t -> t.getLength() == 3).count()); - Assert.assertEquals(1, trips.stream().filter(t -> t.getLength() == 4).count()); + assertEquals(21, trips.size()); + assertEquals(6, trips.stream().filter(t -> t.getLength() == 1).count()); + assertEquals(9, trips.stream().filter(t -> t.getLength() == 2).count()); + assertEquals(5, trips.stream().filter(t -> t.getLength() == 3).count()); + assertEquals(1, trips.stream().filter(t -> t.getLength() == 4).count()); } static private class MockFunction implements AlonsoMoraFunction { @@ -392,17 +393,17 @@ public boolean isAssigned() { } @Override - public Collection getDrtRequests() { + public DrtRequest getDrtRequest() { // TODO Auto-generated method stub return null; } @Override - public Collection getAcceptedDrtRequests() { + public AcceptedDrtRequest getAcceptedDrtRequest() { // TODO Auto-generated method stub return null; } - + @Override public int getSize() { // TODO Auto-generated method stub @@ -462,6 +463,12 @@ public double getEarliestPickupTime() { // TODO Auto-generated method stub return 0; } + + @Override + public void accept(AcceptedDrtRequest acceptedRequest) { + // TODO Auto-generated method stub + + } } private AlonsoMoraVehicle mockVehicle() { diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/EuclideanSequenceGeneratorTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/EuclideanSequenceGeneratorTest.java index 310bb6b..5a23eeb 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/EuclideanSequenceGeneratorTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/EuclideanSequenceGeneratorTest.java @@ -1,11 +1,12 @@ package org.matsim.alonso_mora.algorithm.function.sequence; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.Id; @@ -28,7 +29,7 @@ private AlonsoMoraRequest mockRequest(double fromLocation, double toLocation, St AlonsoMoraRequest request = Mockito.mock(AlonsoMoraRequest.class); Mockito.when(request.getPickupLink()).thenReturn(fromLink); Mockito.when(request.getDropoffLink()).thenReturn(toLink); - Mockito.when(request.getDrtRequests()).thenReturn(Collections.singleton(drtRequest)); + Mockito.when(request.getDrtRequest()).thenReturn(drtRequest); return request; } @@ -58,8 +59,8 @@ public void testOneRequests() { generator.advance(); } - Assert.assertEquals(2, partial); - Assert.assertEquals(1, complete); + assertEquals(2, partial); + assertEquals(1, complete); } @Test @@ -88,8 +89,8 @@ public void testTwoRequests() { generator.advance(); } - Assert.assertEquals(4, partial); - Assert.assertEquals(1, complete); + assertEquals(4, partial); + assertEquals(1, complete); } @Test @@ -128,8 +129,8 @@ public void testTwoRequestsWithAbort() { callIndex++; } - Assert.assertEquals(5, partial); - Assert.assertEquals(1, complete); + assertEquals(5, partial); + assertEquals(1, complete); } @Test diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/ExtensiveSequenceGeneratorTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/ExtensiveSequenceGeneratorTest.java index fcaf757..d3af78c 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/ExtensiveSequenceGeneratorTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/ExtensiveSequenceGeneratorTest.java @@ -1,11 +1,14 @@ package org.matsim.alonso_mora.algorithm.function.sequence; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.Collections; import java.util.LinkedList; import java.util.List; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.contrib.drt.passenger.DrtRequest; import org.mockito.Mockito; @@ -18,7 +21,7 @@ private DrtRequest createDrtRequestMock() { private AlonsoMoraRequest createAlonsoMoraRequestMock() { AlonsoMoraRequest request = Mockito.mock(AlonsoMoraRequest.class); - Mockito.when(request.getDrtRequests()).thenReturn(Collections.singleton(createDrtRequestMock())); + Mockito.when(request.getDrtRequest()).thenReturn(createDrtRequestMock()); return request; } @@ -42,8 +45,8 @@ public void testOneRequests() { generator.advance(); } - Assert.assertEquals(2, partial); - Assert.assertEquals(1, complete); + assertEquals(2, partial); + assertEquals(1, complete); } @Test @@ -67,8 +70,8 @@ public void testTwoRequests() { generator.advance(); } - Assert.assertEquals(18, partial); - Assert.assertEquals(6, complete); + assertEquals(18, partial); + assertEquals(6, complete); } @Test @@ -91,8 +94,8 @@ public void testOneOnboard() { generator.advance(); } - Assert.assertEquals(1, partial); - Assert.assertEquals(1, complete); + assertEquals(1, partial); + assertEquals(1, complete); } @Test @@ -116,8 +119,8 @@ public void testTwoOnboard() { generator.advance(); } - Assert.assertEquals(4, partial); - Assert.assertEquals(2, complete); + assertEquals(4, partial); + assertEquals(2, complete); } @Test @@ -146,8 +149,8 @@ public void testTwoRequestsWithOneOnboard() { generator.advance(); } - Assert.assertEquals(89, partial); - Assert.assertEquals(30, complete); + assertEquals(89, partial); + assertEquals(30, complete); } @Test @@ -174,8 +177,8 @@ public void testFourRequests() { generator.advance(); } - Assert.assertEquals(7364, partial); - Assert.assertEquals(2520, complete); + assertEquals(7364, partial); + assertEquals(2520, complete); } @Test @@ -186,21 +189,21 @@ public void testTwoRequestsFirstReject() { ExtensiveSequenceGenerator generator = new ExtensiveSequenceGenerator(requests, Collections.emptySet()); - Assert.assertTrue(generator.hasNext()); - Assert.assertEquals(1, generator.get().size()); + assertTrue(generator.hasNext()); + assertEquals(1, generator.get().size()); generator.abort(); - Assert.assertTrue(generator.hasNext()); - Assert.assertEquals(1, generator.get().size()); + assertTrue(generator.hasNext()); + assertEquals(1, generator.get().size()); generator.advance(); - Assert.assertTrue(generator.hasNext()); - Assert.assertEquals(2, generator.get().size()); + assertTrue(generator.hasNext()); + assertEquals(2, generator.get().size()); generator.advance(); - Assert.assertFalse(generator.hasNext()); + assertFalse(generator.hasNext()); } } diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/InsertiveSequenceGeneratorTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/InsertiveSequenceGeneratorTest.java index 38b3aea..7cf6a27 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/InsertiveSequenceGeneratorTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/function/sequence/InsertiveSequenceGeneratorTest.java @@ -1,11 +1,12 @@ package org.matsim.alonso_mora.algorithm.function.sequence; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.Collections; import java.util.LinkedList; import java.util.List; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.function.sequence.InsertiveSequenceGenerator.IndexCalculator; import org.matsim.contrib.drt.passenger.DrtRequest; @@ -17,16 +18,16 @@ public void testDefaultDelegation() { DrtRequest drtRequest = Mockito.mock(DrtRequest.class); AlonsoMoraRequest request1 = Mockito.mock(AlonsoMoraRequest.class); - Mockito.when(request1.getDrtRequests()).thenReturn(Collections.singleton(drtRequest)); + Mockito.when(request1.getDrtRequest()).thenReturn(drtRequest); AlonsoMoraRequest request2 = Mockito.mock(AlonsoMoraRequest.class); - Mockito.when(request2.getDrtRequests()).thenReturn(Collections.singleton(drtRequest)); + Mockito.when(request2.getDrtRequest()).thenReturn(drtRequest); AlonsoMoraRequest request3 = Mockito.mock(AlonsoMoraRequest.class); - Mockito.when(request3.getDrtRequests()).thenReturn(Collections.singleton(drtRequest)); + Mockito.when(request3.getDrtRequest()).thenReturn(drtRequest); AlonsoMoraRequest request4 = Mockito.mock(AlonsoMoraRequest.class); - Mockito.when(request4.getDrtRequests()).thenReturn(Collections.singleton(drtRequest)); + Mockito.when(request4.getDrtRequest()).thenReturn(drtRequest); List requests = new LinkedList<>(); @@ -55,8 +56,8 @@ public void testDefaultDelegation() { generator.advance(); } - Assert.assertEquals(7364, partial); - Assert.assertEquals(2520, complete); + assertEquals(7364, partial); + assertEquals(2520, complete); } @Test @@ -64,16 +65,16 @@ public void testKeepingOrder() { DrtRequest drtRequest = Mockito.mock(DrtRequest.class); AlonsoMoraRequest request1 = Mockito.mock(AlonsoMoraRequest.class); - Mockito.when(request1.getDrtRequests()).thenReturn(Collections.singleton(drtRequest)); + Mockito.when(request1.getDrtRequest()).thenReturn(drtRequest); AlonsoMoraRequest request2 = Mockito.mock(AlonsoMoraRequest.class); - Mockito.when(request2.getDrtRequests()).thenReturn(Collections.singleton(drtRequest)); + Mockito.when(request2.getDrtRequest()).thenReturn(drtRequest); AlonsoMoraRequest request3 = Mockito.mock(AlonsoMoraRequest.class); - Mockito.when(request3.getDrtRequests()).thenReturn(Collections.singleton(drtRequest)); + Mockito.when(request3.getDrtRequest()).thenReturn(drtRequest); AlonsoMoraRequest request4 = Mockito.mock(AlonsoMoraRequest.class); - Mockito.when(request4.getDrtRequests()).thenReturn(Collections.singleton(drtRequest)); + Mockito.when(request4.getDrtRequest()).thenReturn(drtRequest); List requests = new LinkedList<>(); @@ -108,7 +109,7 @@ public void testKeepingOrder() { generator.advance(); } - Assert.assertEquals(1440, partial); - Assert.assertEquals(420, complete); + assertEquals(1440, partial); + assertEquals(420, complete); } } diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/CbcMpsRelocationSolverTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/CbcMpsRelocationSolverTest.java index cbd9df4..7227218 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/CbcMpsRelocationSolverTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/CbcMpsRelocationSolverTest.java @@ -1,7 +1,9 @@ package org.matsim.alonso_mora.algorithm.relocation; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -10,11 +12,9 @@ import java.util.LinkedList; import java.util.List; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; import org.matsim.alonso_mora.algorithm.assignment.CbcMpsAssignmentSolver; import org.matsim.alonso_mora.algorithm.relocation.RelocationSolver.Relocation; @@ -22,19 +22,19 @@ import org.mockito.Mockito; public class CbcMpsRelocationSolverTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Before - public void checkSolver() { - Assume.assumeTrue("Checking for availability of Cbc solver", CbcMpsAssignmentSolver.checkAvailability()); + @BeforeAll + public static void checkSolver() { + assertTrue(CbcMpsAssignmentSolver.checkAvailability(), "Checking for availability of Cbc solver"); } @Test - public void testTwoVehicesOneDestination() throws IOException { + public void testTwoVehicesOneDestination(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "problem"); + CbcMpsRelocationSolver solver = new CbcMpsRelocationSolver(1000, // - temporaryFolder.newFile("problem"), // - temporaryFolder.newFile("solution"), 0); + problemFile, // + solutionFile, 0); AlonsoMoraVehicle vehicle = Mockito.mock(AlonsoMoraVehicle.class); @@ -49,10 +49,13 @@ public void testTwoVehicesOneDestination() throws IOException { } @Test - public void testOneVehicesTwoDestinations() throws IOException { + public void testOneVehicesTwoDestinations(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "problem"); + CbcMpsRelocationSolver solver = new CbcMpsRelocationSolver(1000, // - temporaryFolder.newFile("problem"), // - temporaryFolder.newFile("solution"), 0); + problemFile, // + solutionFile, 0); Link link = Mockito.mock(Link.class); @@ -67,10 +70,13 @@ public void testOneVehicesTwoDestinations() throws IOException { } @Test - public void testComplex() throws IOException { + public void testComplex(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "problem"); + CbcMpsRelocationSolver solver = new CbcMpsRelocationSolver(1000, // - temporaryFolder.newFile("problem"), // - temporaryFolder.newFile("solution"), 0); + problemFile, // + solutionFile, 0); Link linkA = Mockito.mock(Link.class); Link linkB = Mockito.mock(Link.class); @@ -96,10 +102,13 @@ public void testComplex() throws IOException { } @Test - public void testEmpty() throws IOException { + public void testEmpty(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "problem"); + CbcMpsRelocationSolver solver = new CbcMpsRelocationSolver(1000, // - temporaryFolder.newFile("problem"), // - temporaryFolder.newFile("solution"), 0); + problemFile, // + solutionFile, 0); Collection solution = solver.solve(Collections.emptyList()); diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/GlpkMpsRelocationSolverTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/GlpkMpsRelocationSolverTest.java index afb5af9..eade6ea 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/GlpkMpsRelocationSolverTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/GlpkMpsRelocationSolverTest.java @@ -1,7 +1,9 @@ package org.matsim.alonso_mora.algorithm.relocation; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -10,11 +12,9 @@ import java.util.LinkedList; import java.util.List; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; import org.matsim.alonso_mora.algorithm.assignment.GlpkMpsAssignmentSolver; import org.matsim.alonso_mora.algorithm.relocation.RelocationSolver.Relocation; @@ -22,19 +22,19 @@ import org.mockito.Mockito; public class GlpkMpsRelocationSolverTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Before - public void checkSolver() { - Assume.assumeTrue("Checking for availability of GLPK solver", GlpkMpsAssignmentSolver.checkAvailability()); + @BeforeAll + static public void checkSolver() { + assertTrue(GlpkMpsAssignmentSolver.checkAvailability(), "Checking for availability of GLPK solver"); } @Test - public void testTwoVehicesOneDestination() throws IOException { + public void testTwoVehicesOneDestination(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "solution"); + GlpkMpsRelocationSolver solver = new GlpkMpsRelocationSolver(1000, // - temporaryFolder.newFile("problem"), // - temporaryFolder.newFile("solution")); + problemFile, // + solutionFile); AlonsoMoraVehicle vehicle = Mockito.mock(AlonsoMoraVehicle.class); @@ -49,10 +49,13 @@ public void testTwoVehicesOneDestination() throws IOException { } @Test - public void testOneVehicesTwoDestinations() throws IOException { + public void testOneVehicesTwoDestinations(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "solution"); + GlpkMpsRelocationSolver solver = new GlpkMpsRelocationSolver(1000, // - temporaryFolder.newFile("problem"), // - temporaryFolder.newFile("solution")); + problemFile, // + solutionFile); Link link = Mockito.mock(Link.class); @@ -65,16 +68,19 @@ public void testOneVehicesTwoDestinations() throws IOException { assertEquals(1, solution.size()); assertEquals(relocations.get(0), solution.iterator().next()); } - + @Test - public void testComplex() throws IOException { + public void testComplex(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "solution"); + GlpkMpsRelocationSolver solver = new GlpkMpsRelocationSolver(1000, // - temporaryFolder.newFile("problem"), // - temporaryFolder.newFile("solution")); - + problemFile, // + solutionFile); + Link linkA = Mockito.mock(Link.class); Link linkB = Mockito.mock(Link.class); - + AlonsoMoraVehicle vehicle1 = Mockito.mock(AlonsoMoraVehicle.class); AlonsoMoraVehicle vehicle2 = Mockito.mock(AlonsoMoraVehicle.class); AlonsoMoraVehicle vehicle3 = Mockito.mock(AlonsoMoraVehicle.class); @@ -89,17 +95,20 @@ public void testComplex() throws IOException { Collection solution = solver.solve(relocations); assertEquals(2, solution.size()); - + List expected = new ArrayList<>(Arrays.asList(relocations.get(0), relocations.get(4))); expected.removeAll(relocations); assertEquals(0, expected.size()); } @Test - public void testEmpty() throws IOException { + public void testEmpty(@TempDir File temporaryFolder) throws IOException { + File problemFile = new File(temporaryFolder, "problem"); + File solutionFile = new File(temporaryFolder, "solution"); + GlpkMpsRelocationSolver solver = new GlpkMpsRelocationSolver(1000, // - temporaryFolder.newFile("problem"), // - temporaryFolder.newFile("solution")); + problemFile, // + solutionFile); Collection solution = solver.solve(Collections.emptyList()); diff --git a/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/MpsRelocationWriterTest.java b/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/MpsRelocationWriterTest.java index f11630f..a1a0118 100644 --- a/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/MpsRelocationWriterTest.java +++ b/core/src/test/java/org/matsim/alonso_mora/algorithm/relocation/MpsRelocationWriterTest.java @@ -1,23 +1,20 @@ package org.matsim.alonso_mora.algorithm.relocation; +import java.io.File; import java.io.IOException; import java.util.LinkedList; import java.util.List; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; import org.matsim.alonso_mora.algorithm.relocation.RelocationSolver.Relocation; import org.matsim.api.core.v01.network.Link; import org.mockito.Mockito; public class MpsRelocationWriterTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - @Test - public void testWriter() throws IOException { + public void testWriter(@TempDir File temporaryFolder) throws IOException { List relocations = new LinkedList<>(); AlonsoMoraVehicle vehicle = Mockito.mock(AlonsoMoraVehicle.class); @@ -26,6 +23,6 @@ public void testWriter() throws IOException { relocations.add(new Relocation(vehicle, Mockito.mock(Link.class), 50.0)); MpsRelocationWriter writer = new MpsRelocationWriter(relocations); - writer.write(temporaryFolder.newFile("problem")); + writer.write(new File(temporaryFolder, "problem")); } } diff --git a/core/src/test/java/org/matsim/alonso_mora/run/AlonsoMoraExamplesIT.java b/core/src/test/java/org/matsim/alonso_mora/run/AlonsoMoraExamplesIT.java index 427d603..38a2029 100644 --- a/core/src/test/java/org/matsim/alonso_mora/run/AlonsoMoraExamplesIT.java +++ b/core/src/test/java/org/matsim/alonso_mora/run/AlonsoMoraExamplesIT.java @@ -19,7 +19,7 @@ package org.matsim.alonso_mora.run; -import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.net.URL; @@ -32,17 +32,17 @@ import java.util.Random; import java.util.stream.Collectors; -import org.assertj.core.data.Percentage; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.matsim.alonso_mora.AlonsoMoraConfigGroup; +import org.matsim.alonso_mora.AlonsoMoraConfigGroup.GlpkMpsAssignmentParameters; +import org.matsim.alonso_mora.AlonsoMoraConfigGroup.RoutingEstimatorParameters; import org.matsim.alonso_mora.AlonsoMoraConfigurator; import org.matsim.alonso_mora.MultiModeAlonsoMoraConfigGroup; import org.matsim.alonso_mora.shifts.ShiftAlonsoMoraModule; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; import org.matsim.contrib.drt.extension.operations.DrtWithOperationsConfigGroup; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesParams; @@ -61,6 +61,8 @@ import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftSpecificationImpl; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecificationImpl; +import org.matsim.contrib.drt.prebooking.PrebookingParams; +import org.matsim.contrib.drt.prebooking.logic.ProbabilityBasedPrebookingLogic; import org.matsim.contrib.drt.routing.DrtRoute; import org.matsim.contrib.drt.routing.DrtRouteFactory; import org.matsim.contrib.drt.run.DrtConfigGroup; @@ -86,8 +88,8 @@ */ public class AlonsoMoraExamplesIT { - @Rule - public MatsimTestUtils utils = new MatsimTestUtils(); + @RegisterExtension + private MatsimTestUtils utils = new MatsimTestUtils(); @Test public void testRunAlonsoMora() { @@ -99,8 +101,8 @@ public void testRunAlonsoMora() { AlonsoMoraConfigGroup amConfig = new AlonsoMoraConfigGroup(); MultiModeAlonsoMoraConfigGroup.get(config).addParameterSet(amConfig); - config.controler().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); - config.controler().setOutputDirectory(utils.getOutputDirectory()); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); // Remove DRT rebalancer as we want to use AM rebalancer DrtConfigGroup drtConfig = MultiModeDrtConfigGroup.get(config).getModalElements().iterator().next(); @@ -119,15 +121,73 @@ public void testRunAlonsoMora() { controller.addOverridingModule(new MultiModeDrtModule()); controller.configureQSimComponents(DvrpQSimComponents.activateAllModes(MultiModeDrtConfigGroup.get(config))); - AlonsoMoraConfigurator.configure(controller, amConfig.getMode()); + AlonsoMoraConfigurator.configure(controller, amConfig.mode); controller.run(); var expectedStats = Stats.newBuilder() // .rejectionRate(0.2) // .rejections(78) // - .waitAverage(215.88) // - .inVehicleTravelTimeMean(347.02) // - .totalTravelTimeMean(562.9) // + .waitAverage(215.41) // + .inVehicleTravelTimeMean(346.55) // + .totalTravelTimeMean(561.97) // + .build(); + + verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); + } + + @Test + public void testRunAlonsoMoraWithDeterministicTravelTimesCheck() { + Id.resetCaches(); + URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_drt_config.xml"); + Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(), + new MultiModeAlonsoMoraConfigGroup(), new OTFVisConfigGroup()); + + AlonsoMoraConfigGroup amConfig = new AlonsoMoraConfigGroup(); + MultiModeAlonsoMoraConfigGroup.get(config).addParameterSet(amConfig); + + // Start: Configure deterministic travel times + config.qsim().setFlowCapFactor(1e9); + config.qsim().setStorageCapFactor(1e9); + + amConfig.checkDeterminsticTravelTimes = true; + + RoutingEstimatorParameters estimatorParameters = new RoutingEstimatorParameters(); + estimatorParameters.cacheLifetime = 0.0; + + amConfig.clearTravelTimeEstimator(); + amConfig.addParameterSet(estimatorParameters); + + // End + + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + + // Remove DRT rebalancer as we want to use AM rebalancer + DrtConfigGroup drtConfig = MultiModeDrtConfigGroup.get(config).getModalElements().iterator().next(); + drtConfig.removeParameterSet(drtConfig.getRebalancingParams().get()); + + // Load scenario + Scenario scenario = ScenarioUtils.createScenario(config); + scenario.getPopulation().getFactory().getRouteFactories().setRouteFactory(DrtRoute.class, + new DrtRouteFactory()); + ScenarioUtils.loadScenario(scenario); + + // Set up controller + Controler controller = new Controler(scenario); + + controller.addOverridingModule(new DvrpModule()); + controller.addOverridingModule(new MultiModeDrtModule()); + controller.configureQSimComponents(DvrpQSimComponents.activateAllModes(MultiModeDrtConfigGroup.get(config))); + + AlonsoMoraConfigurator.configure(controller, amConfig.mode); + controller.run(); + + var expectedStats = Stats.newBuilder() // + .rejectionRate(0.17) // + .rejections(66) // + .waitAverage(206.72) // + .inVehicleTravelTimeMean(332.17) // + .totalTravelTimeMean(538.89) // .build(); verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); @@ -137,26 +197,28 @@ public void testRunAlonsoMora() { public void testRunAlonsoMoraWithShifts() { Id.resetCaches(); URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_drt_config.xml"); - Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(DrtWithOperationsConfigGroup::new), new DvrpConfigGroup(), + Config config = ConfigUtils.loadConfig(configUrl, + new MultiModeDrtConfigGroup(DrtWithOperationsConfigGroup::new), new DvrpConfigGroup(), new MultiModeAlonsoMoraConfigGroup(), new OTFVisConfigGroup()); AlonsoMoraConfigGroup amConfig = new AlonsoMoraConfigGroup(); MultiModeAlonsoMoraConfigGroup.get(config).addParameterSet(amConfig); - config.controler().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); - config.controler().setOutputDirectory(utils.getOutputDirectory()); + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); // Remove DRT rebalancer as we want to use AM rebalancer - DrtWithOperationsConfigGroup drtConfig = (DrtWithOperationsConfigGroup) MultiModeDrtConfigGroup.get(config).getModalElements().iterator().next(); + DrtWithOperationsConfigGroup drtConfig = (DrtWithOperationsConfigGroup) MultiModeDrtConfigGroup.get(config) + .getModalElements().iterator().next(); drtConfig.removeParameterSet(drtConfig.getRebalancingParams().get()); - + // shift parameters DrtOperationsParams operationsParams = new DrtOperationsParams(); drtConfig.addParameterSet(operationsParams); - + OperationFacilitiesParams operationFacilitiesParams = new OperationFacilitiesParams(); operationsParams.addParameterSet(operationFacilitiesParams); - + ShiftsParams shiftParams = new ShiftsParams(); operationsParams.addParameterSet(shiftParams); @@ -235,7 +297,8 @@ public void testRunAlonsoMoraWithShifts() { for (DrtConfigGroup drtCfg : MultiModeDrtConfigGroup.get(config).getModalElements()) { controller.addOverridingModule(new ShiftDrtModeModule(drtCfg)); - controller.addOverridingQSimModule(new DrtModeQSimModule(drtCfg, new ShiftDrtModeOptimizerQSimModule(drtCfg))); + controller.addOverridingQSimModule( + new DrtModeQSimModule(drtCfg, new ShiftDrtModeOptimizerQSimModule(drtCfg))); controller.addOverridingQSimModule(new ShiftDvrpFleetQsimModule(drtCfg.getMode())); controller.addOverridingQSimModule(new OperationFacilitiesQSimModule(drtConfig)); } @@ -248,7 +311,7 @@ public void install() { } }); - AlonsoMoraConfigurator.configure(controller, amConfig.getMode()); + AlonsoMoraConfigurator.configure(controller, amConfig.mode); controller.addOverridingQSimModule(new ShiftAlonsoMoraModule(drtConfig, shiftParams, amConfig)); controller.run(); @@ -297,12 +360,11 @@ private void verifyDrtCustomerStatsCloseToExpectedStats(String outputDirectory, double rejectionRate = Double.parseDouble(params.get("rejectionRate")); double totalTravelTimeMean = Double.parseDouble(params.get("totalTravelTime_mean")); - var percentage = Percentage.withPercentage(0.00001); - assertThat(rejectionRate).isCloseTo(expectedStats.rejectionRate, percentage); - assertThat(rejections).isCloseTo(expectedStats.rejections, percentage); - assertThat(waitAverage).isCloseTo(expectedStats.waitAverage, percentage); - assertThat(inVehicleTravelTimeMean).isCloseTo(expectedStats.inVehicleTravelTimeMean, percentage); - assertThat(totalTravelTimeMean).isCloseTo(expectedStats.totalTravelTimeMean, percentage); + assertEquals(rejectionRate, expectedStats.rejectionRate); + assertEquals(rejections, expectedStats.rejections); + assertEquals(waitAverage, expectedStats.waitAverage); + assertEquals(inVehicleTravelTimeMean, expectedStats.inVehicleTravelTimeMean); + assertEquals(totalTravelTimeMean, expectedStats.totalTravelTimeMean); } private static class Stats { @@ -364,4 +426,74 @@ public Stats build() { } } } + + @Test + public void testRunAlonsoMoraWithPrebooking() { + Id.resetCaches(); + URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_drt_config.xml"); + Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(), + new MultiModeAlonsoMoraConfigGroup(), new OTFVisConfigGroup()); + + AlonsoMoraConfigGroup amConfig = new AlonsoMoraConfigGroup(); + MultiModeAlonsoMoraConfigGroup.get(config).addParameterSet(amConfig); + + // Start: Configure deterministic travel times + config.qsim().setFlowCapFactor(1e9); + config.qsim().setStorageCapFactor(1e9); + + amConfig.checkDeterminsticTravelTimes = true; + amConfig.preferNonViolation = true; + amConfig.congestionMitigation.allowPickupViolations = false; + amConfig.congestionMitigation.allowPickupsWithDropoffViolations = false; + + RoutingEstimatorParameters estimatorParameters = new RoutingEstimatorParameters(); + estimatorParameters.cacheLifetime = 0.0; + + amConfig.clearTravelTimeEstimator(); + amConfig.addParameterSet(estimatorParameters); + + amConfig.clearAssignmentSolver(); + amConfig.addParameterSet(new GlpkMpsAssignmentParameters()); + + // End + + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + + // Remove DRT rebalancer as we want to use AM rebalancer + DrtConfigGroup drtConfig = MultiModeDrtConfigGroup.get(config).getModalElements().iterator().next(); + drtConfig.removeParameterSet(drtConfig.getRebalancingParams().get()); + + // prebooking + PrebookingParams prebookingParams = new PrebookingParams(); + drtConfig.addParameterSet(prebookingParams); + + // Load scenario + Scenario scenario = ScenarioUtils.createScenario(config); + scenario.getPopulation().getFactory().getRouteFactories().setRouteFactory(DrtRoute.class, + new DrtRouteFactory()); + ScenarioUtils.loadScenario(scenario); + + // Set up controller + Controler controller = new Controler(scenario); + + controller.addOverridingModule(new DvrpModule()); + controller.addOverridingModule(new MultiModeDrtModule()); + controller.configureQSimComponents(DvrpQSimComponents.activateAllModes(MultiModeDrtConfigGroup.get(config))); + + ProbabilityBasedPrebookingLogic.install(controller, drtConfig, 0.25, 600.0); + + AlonsoMoraConfigurator.configure(controller, amConfig.mode); + controller.run(); + + var expectedStats = Stats.newBuilder() // + .rejectionRate(0.03) // + .rejections(11) // + .waitAverage(204.48) // + .inVehicleTravelTimeMean(345.55) // + .totalTravelTimeMean(550.03) // + .build(); + + verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); + } } diff --git a/cplex/src/main/java/org/matsim/alonso_mora/gurobi/CplexModule.java b/cplex/src/main/java/org/matsim/alonso_mora/gurobi/CplexModule.java index 8211471..0c75c06 100644 --- a/cplex/src/main/java/org/matsim/alonso_mora/gurobi/CplexModule.java +++ b/cplex/src/main/java/org/matsim/alonso_mora/gurobi/CplexModule.java @@ -35,15 +35,13 @@ protected void configureQSim() { bindModal(CplexAssignmentSolver.class).toProvider(modalProvider(getter -> { GlobalConfigGroup globalConfig = getter.get(GlobalConfigGroup.class); - CplexAssignmentParameters solverParameters = (CplexAssignmentParameters) amConfig - .getAssignmentSolverParameters(); + CplexAssignmentParameters solverParameters = (CplexAssignmentParameters) amConfig.assignmentSolver; - return new CplexAssignmentSolver(amConfig.getUnassignmentPenalty(), amConfig.getRejectionPenalty(), - globalConfig.getNumberOfThreads(), solverParameters.getTimeLimit(), - solverParameters.getOptimalityGap()); + return new CplexAssignmentSolver(amConfig.unassignmentPenalty, amConfig.rejectionPenalty, + globalConfig.getNumberOfThreads(), solverParameters.timeLimit, solverParameters.optimalityGap); })).in(Singleton.class); - if (amConfig.getAssignmentSolverParameters().getSolverType().equals(CplexAssignmentSolver.TYPE)) { + if (amConfig.assignmentSolver.getSolverType().equals(CplexAssignmentSolver.TYPE)) { bindModal(AssignmentSolver.class).to(modalKey(CplexAssignmentSolver.class)); } @@ -53,7 +51,7 @@ protected void configureQSim() { return new CplexRelocationSolver(globalConfig.getNumberOfThreads()); })).in(Singleton.class); - if (amConfig.getRelocationSolverParameters().getSolverType().equals(CplexRelocationSolver.TYPE)) { + if (amConfig.relocationSolver.getSolverType().equals(CplexRelocationSolver.TYPE)) { bindModal(RelocationSolver.class).to(modalKey(CplexRelocationSolver.class)); } } diff --git a/cplex/src/test/java/org/matsim/alonso_mora/gurobi/CplexAssignmentSolverTest.java b/cplex/src/test/java/org/matsim/alonso_mora/gurobi/CplexAssignmentSolverTest.java index a744f6e..d53970d 100644 --- a/cplex/src/test/java/org/matsim/alonso_mora/gurobi/CplexAssignmentSolverTest.java +++ b/cplex/src/test/java/org/matsim/alonso_mora/gurobi/CplexAssignmentSolverTest.java @@ -1,13 +1,14 @@ package org.matsim.alonso_mora.gurobi; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.Arrays; import java.util.Collection; import java.util.List; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraTrip; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; @@ -18,9 +19,9 @@ import org.mockito.Mockito; public class CplexAssignmentSolverTest { - @Before - public void checkSolver() { - Assume.assumeTrue("Checking for availability of CPLEX solver", CplexAssignmentSolver.checkAvailability()); + @BeforeAll + static public void checkSolver() { + assertTrue(CplexAssignmentSolver.checkAvailability(), "Checking for availability of CPLEX solver"); } private AlonsoMoraRequest mockRequest() { @@ -60,8 +61,8 @@ public void testOneVehicleOneRequestExample() { List candidates = Arrays.asList(trip); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip)); } @Test @@ -79,9 +80,9 @@ public void testTwoIndependentRequests() { List candidates = Arrays.asList(trip1, trip2); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(2, selection.size()); - Assert.assertTrue(selection.contains(trip1)); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(2, selection.size()); + assertTrue(selection.contains(trip1)); + assertTrue(selection.contains(trip2)); } @Test @@ -103,8 +104,8 @@ public void testTwoRequestsWithOneVehicle() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip3)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip3)); } } @@ -126,8 +127,8 @@ public void testTwoRequestsWithOneVehicleLowPenalty() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip1)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip1)); } } } diff --git a/cplex/src/test/java/org/matsim/alonso_mora/gurobi/CplexRelocationSolverTest.java b/cplex/src/test/java/org/matsim/alonso_mora/gurobi/CplexRelocationSolverTest.java index 25e7d37..934d8ee 100644 --- a/cplex/src/test/java/org/matsim/alonso_mora/gurobi/CplexRelocationSolverTest.java +++ b/cplex/src/test/java/org/matsim/alonso_mora/gurobi/CplexRelocationSolverTest.java @@ -1,6 +1,6 @@ package org.matsim.alonso_mora.gurobi; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.util.ArrayList; @@ -10,7 +10,7 @@ import java.util.LinkedList; import java.util.List; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; import org.matsim.alonso_mora.algorithm.relocation.RelocationSolver.Relocation; import org.matsim.api.core.v01.network.Link; diff --git a/glpk/.gitignore b/glpk/.gitignore index 8272e2b..2a27e84 100644 --- a/glpk/.gitignore +++ b/glpk/.gitignore @@ -5,3 +5,4 @@ /.settings /target /output +/test diff --git a/glpk/src/main/java/org/matsim/alonso_mora/glpk/GlpkModule.java b/glpk/src/main/java/org/matsim/alonso_mora/glpk/GlpkModule.java index d4dc676..5c84470 100644 --- a/glpk/src/main/java/org/matsim/alonso_mora/glpk/GlpkModule.java +++ b/glpk/src/main/java/org/matsim/alonso_mora/glpk/GlpkModule.java @@ -36,14 +36,13 @@ protected void configureQSim() { throw new IllegalStateException("GLPK JNI solver is not available on this system!"); } - GlpkJniAssignmentParameters solverParameters = (GlpkJniAssignmentParameters) amConfig - .getAssignmentSolverParameters(); + GlpkJniAssignmentParameters solverParameters = (GlpkJniAssignmentParameters) amConfig.assignmentSolver; - return new GlpkJniAssignmentSolver(amConfig.getUnassignmentPenalty(), amConfig.getRejectionPenalty(), - solverParameters.getTimeLimit(), solverParameters.getOptimalityGap()); + return new GlpkJniAssignmentSolver(amConfig.unassignmentPenalty, amConfig.rejectionPenalty, + solverParameters.timeLimit, solverParameters.optimalityGap); })).in(Singleton.class); - if (amConfig.getAssignmentSolverParameters().getSolverType().equals(GlpkJniAssignmentSolver.TYPE)) { + if (amConfig.assignmentSolver.getSolverType().equals(GlpkJniAssignmentSolver.TYPE)) { bindModal(AssignmentSolver.class).to(modalKey(GlpkJniAssignmentSolver.class)); } @@ -55,7 +54,7 @@ protected void configureQSim() { return new GlpkJniRelocationSolver(); })).in(Singleton.class); - if (amConfig.getRelocationSolverParameters().getSolverType().equals(GlpkJniRelocationSolver.TYPE)) { + if (amConfig.assignmentSolver.getSolverType().equals(GlpkJniRelocationSolver.TYPE)) { bindModal(RelocationSolver.class).to(modalKey(GlpkJniRelocationSolver.class)); } } diff --git a/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkExamplesIT.java b/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkExamplesIT.java new file mode 100644 index 0000000..3e89a9e --- /dev/null +++ b/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkExamplesIT.java @@ -0,0 +1,243 @@ +/* *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2017 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.alonso_mora.glpk; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.matsim.alonso_mora.AlonsoMoraConfigGroup; +import org.matsim.alonso_mora.AlonsoMoraConfigurator; +import org.matsim.alonso_mora.MultiModeAlonsoMoraConfigGroup; +import org.matsim.alonso_mora.shifts.ShiftAlonsoMoraModule; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; +import org.matsim.contrib.drt.extension.operations.DrtWithOperationsConfigGroup; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesParams; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesQSimModule; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesSpecification; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesSpecificationImpl; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitySpecificationImpl; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilityType; +import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; +import org.matsim.contrib.drt.extension.operations.shifts.run.ShiftDrtModeModule; +import org.matsim.contrib.drt.extension.operations.shifts.run.ShiftDrtModeOptimizerQSimModule; +import org.matsim.contrib.drt.extension.operations.shifts.run.ShiftDvrpFleetQsimModule; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftBreakSpecificationImpl; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftSpecificationImpl; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecificationImpl; +import org.matsim.contrib.drt.routing.DrtRoute; +import org.matsim.contrib.drt.routing.DrtRouteFactory; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.run.DrtModeQSimModule; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.drt.run.MultiModeDrtModule; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.run.DvrpConfigGroup; +import org.matsim.contrib.dvrp.run.DvrpModule; +import org.matsim.contrib.dvrp.run.DvrpQSimComponents; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy.OverwriteFileSetting; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.vis.otfvis.OTFVisConfigGroup; + +/** + * @author sebhoerl + */ +public class GlpkExamplesIT { + + @RegisterExtension + private MatsimTestUtils utils = new MatsimTestUtils(); + + @Test + public void testRunAlonsoMoraWithGlpk() { + Id.resetCaches(); + URL configUrl = IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("mielec"), "mielec_drt_config.xml"); + Config config = ConfigUtils.loadConfig(configUrl, new MultiModeDrtConfigGroup(), new DvrpConfigGroup(), + new MultiModeAlonsoMoraConfigGroup(), new OTFVisConfigGroup()); + + AlonsoMoraConfigGroup amConfig = new AlonsoMoraConfigGroup(); + MultiModeAlonsoMoraConfigGroup.get(config).addParameterSet(amConfig); + + GlpkModule.configure(amConfig); + + amConfig.clearAssignmentSolver(); + amConfig.addParameterSet(new GlpkJniAssignmentParameters()); + + amConfig.clearRelocationSolver(); + amConfig.addParameterSet(new GlpkJniRelocationParameters()); + + config.controller().setOverwriteFileSetting(OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory(utils.getOutputDirectory()); + + // Remove DRT rebalancer as we want to use AM rebalancer + DrtConfigGroup drtConfig = MultiModeDrtConfigGroup.get(config).getModalElements().iterator().next(); + drtConfig.removeParameterSet(drtConfig.getRebalancingParams().get()); + + // Load scenario + Scenario scenario = ScenarioUtils.createScenario(config); + scenario.getPopulation().getFactory().getRouteFactories().setRouteFactory(DrtRoute.class, + new DrtRouteFactory()); + ScenarioUtils.loadScenario(scenario); + + // Set up controller + Controler controller = new Controler(scenario); + + controller.addOverridingModule(new DvrpModule()); + controller.addOverridingModule(new MultiModeDrtModule()); + controller.addOverridingQSimModule(new GlpkModule(drtConfig, amConfig)); + controller.configureQSimComponents(DvrpQSimComponents.activateAllModes(MultiModeDrtConfigGroup.get(config))); + + AlonsoMoraConfigurator.configure(controller, amConfig.mode); + controller.run(); + + var expectedStats = Stats.newBuilder() // + .rejectionRate(0.04) // + .rejections(14) // + .waitAverage(268.97) // + .inVehicleTravelTimeMean(370.26) // + .totalTravelTimeMean(639.24) // + .build(); + + verifyDrtCustomerStatsCloseToExpectedStats(utils.getOutputDirectory(), expectedStats); + } + + /** + * Early warning system: if customer stats vary more than the defined percentage + * above or below the expected values then the following unit tests will fail. + * This is meant to serve as a red flag. The following customer parameter + * checked are: rejectionRate, rejections, waitAverage, inVehicleTravelTimeMean, + * & totalTravelTimeMean + */ + + private void verifyDrtCustomerStatsCloseToExpectedStats(String outputDirectory, Stats expectedStats) { + + String filename = outputDirectory + "/drt_customer_stats_drt.csv"; + + final List collect; + try { + collect = Files.lines(Paths.get(filename)).collect(Collectors.toList()); + } catch (IOException e) { + throw new RuntimeException(e); + } + + int size = collect.size(); + List keys = List.of(collect.get(0).split(";")); + List lastIterationValues = List.of(collect.get(size - 1).split(";")); + + Map params = new HashMap<>(); + for (int i = 0; i < keys.size(); i++) { + params.put(keys.get(i), lastIterationValues.get(i)); + } + + double inVehicleTravelTimeMean = Double.parseDouble(params.get("inVehicleTravelTime_mean")); + double waitAverage = Double.parseDouble(params.get("wait_average")); + double rejections = Double.parseDouble(params.get("rejections")); + double rejectionRate = Double.parseDouble(params.get("rejectionRate")); + double totalTravelTimeMean = Double.parseDouble(params.get("totalTravelTime_mean")); + + assertEquals(rejectionRate, expectedStats.rejectionRate); + assertEquals(rejections, expectedStats.rejections); + assertEquals(waitAverage, expectedStats.waitAverage); + assertEquals(inVehicleTravelTimeMean, expectedStats.inVehicleTravelTimeMean); + assertEquals(totalTravelTimeMean, expectedStats.totalTravelTimeMean); + } + + private static class Stats { + private final double rejectionRate; + private final double rejections; + private final double waitAverage; + private final double inVehicleTravelTimeMean; + private final double totalTravelTimeMean; + + private Stats(Builder builder) { + rejectionRate = builder.rejectionRate; + rejections = builder.rejections; + waitAverage = builder.waitAverage; + inVehicleTravelTimeMean = builder.inVehicleTravelTimeMean; + totalTravelTimeMean = builder.totalTravelTimeMean; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static final class Builder { + private double rejectionRate; + private double rejections; + private double waitAverage; + private double inVehicleTravelTimeMean; + private double totalTravelTimeMean; + + private Builder() { + } + + public Builder rejectionRate(double val) { + rejectionRate = val; + return this; + } + + public Builder rejections(double val) { + rejections = val; + return this; + } + + public Builder waitAverage(double val) { + waitAverage = val; + return this; + } + + public Builder inVehicleTravelTimeMean(double val) { + inVehicleTravelTimeMean = val; + return this; + } + + public Builder totalTravelTimeMean(double val) { + totalTravelTimeMean = val; + return this; + } + + public Stats build() { + return new Stats(this); + } + } + } +} diff --git a/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkJniAssignmentSolverTest.java b/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkJniAssignmentSolverTest.java index d5ffcf7..138ac0f 100644 --- a/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkJniAssignmentSolverTest.java +++ b/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkJniAssignmentSolverTest.java @@ -1,13 +1,14 @@ package org.matsim.alonso_mora.glpk; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.Arrays; import java.util.Collection; import java.util.List; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraTrip; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; @@ -16,9 +17,9 @@ import org.mockito.Mockito; public class GlpkJniAssignmentSolverTest { - @Before - public void checkSolver() { - Assume.assumeTrue("Checking for availability of GLPK solver", GlpkJniAssignmentSolver.checkAvailability()); + @BeforeAll + static public void checkSolver() { + assertTrue(GlpkJniAssignmentSolver.checkAvailability(), "Checking for availability of GLPK solver"); } private AlonsoMoraRequest mockRequest() { @@ -53,8 +54,8 @@ public void testOneVehicleOneRequestExample() { List candidates = Arrays.asList(trip); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip)); } @Test @@ -72,9 +73,9 @@ public void testTwoIndependentRequests() { List candidates = Arrays.asList(trip1, trip2); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(2, selection.size()); - Assert.assertTrue(selection.contains(trip1)); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(2, selection.size()); + assertTrue(selection.contains(trip1)); + assertTrue(selection.contains(trip2)); } @Test @@ -96,8 +97,8 @@ public void testTwoRequestsWithOneVehicle() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip3)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip3)); } } @@ -119,8 +120,8 @@ public void testTwoRequestsWithOneVehicleLowPenalty() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip1)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip1)); } } } diff --git a/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkJniRelocationSolverTest.java b/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkJniRelocationSolverTest.java index 086aacd..a23af72 100644 --- a/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkJniRelocationSolverTest.java +++ b/glpk/src/test/java/org/matsim/alonso_mora/glpk/GlpkJniRelocationSolverTest.java @@ -1,6 +1,6 @@ package org.matsim.alonso_mora.glpk; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.util.ArrayList; @@ -10,7 +10,7 @@ import java.util.LinkedList; import java.util.List; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; import org.matsim.alonso_mora.algorithm.relocation.RelocationSolver.Relocation; import org.matsim.api.core.v01.network.Link; diff --git a/gurobi/src/main/java/org/matsim/alonso_mora/gurobi/GurobiModule.java b/gurobi/src/main/java/org/matsim/alonso_mora/gurobi/GurobiModule.java index 7c440a5..fef72ae 100644 --- a/gurobi/src/main/java/org/matsim/alonso_mora/gurobi/GurobiModule.java +++ b/gurobi/src/main/java/org/matsim/alonso_mora/gurobi/GurobiModule.java @@ -35,15 +35,13 @@ protected void configureQSim() { bindModal(GurobiAssignmentSolver.class).toProvider(modalProvider(getter -> { GlobalConfigGroup globalConfig = getter.get(GlobalConfigGroup.class); - GurobiAssignmentParameters solverParameters = (GurobiAssignmentParameters) amConfig - .getAssignmentSolverParameters(); + GurobiAssignmentParameters solverParameters = (GurobiAssignmentParameters) amConfig.assignmentSolver; - return new GurobiAssignmentSolver(amConfig.getUnassignmentPenalty(), amConfig.getRejectionPenalty(), - globalConfig.getNumberOfThreads(), solverParameters.getTimeLimit(), - solverParameters.getOptimalityGap()); + return new GurobiAssignmentSolver(amConfig.unassignmentPenalty, amConfig.rejectionPenalty, + globalConfig.getNumberOfThreads(), solverParameters.timeLimit, solverParameters.optimalityGap); })).in(Singleton.class); - if (amConfig.getAssignmentSolverParameters().getSolverType().equals(GurobiAssignmentSolver.TYPE)) { + if (amConfig.assignmentSolver.getSolverType().equals(GurobiAssignmentSolver.TYPE)) { bindModal(AssignmentSolver.class).to(modalKey(GurobiAssignmentSolver.class)); } @@ -53,7 +51,7 @@ protected void configureQSim() { return new GurobiRelocationSolver(globalConfig.getNumberOfThreads()); })).in(Singleton.class); - if (amConfig.getRelocationSolverParameters().getSolverType().equals(GurobiRelocationSolver.TYPE)) { + if (amConfig.relocationSolver.getSolverType().equals(GurobiRelocationSolver.TYPE)) { bindModal(RelocationSolver.class).to(modalKey(GurobiRelocationSolver.class)); } } diff --git a/gurobi/src/test/java/org/matsim/alonso_mora/gurobi/GurobiAssignmentSolverTest.java b/gurobi/src/test/java/org/matsim/alonso_mora/gurobi/GurobiAssignmentSolverTest.java index 6b47ff0..b9c4179 100644 --- a/gurobi/src/test/java/org/matsim/alonso_mora/gurobi/GurobiAssignmentSolverTest.java +++ b/gurobi/src/test/java/org/matsim/alonso_mora/gurobi/GurobiAssignmentSolverTest.java @@ -1,13 +1,14 @@ package org.matsim.alonso_mora.gurobi; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.Arrays; import java.util.Collection; import java.util.List; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraRequest; import org.matsim.alonso_mora.algorithm.AlonsoMoraTrip; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; @@ -18,9 +19,9 @@ import org.mockito.Mockito; public class GurobiAssignmentSolverTest { - @Before - public void checkSolver() { - Assume.assumeTrue("Checking for availability of GLPK solver", GurobiAssignmentSolver.checkAvailability()); + @BeforeAll + static public void checkSolver() { + assertTrue(GurobiAssignmentSolver.checkAvailability(), "Checking for availability of GLPK solver"); } private AlonsoMoraRequest mockRequest() { @@ -60,8 +61,8 @@ public void testOneVehicleOneRequestExample() { List candidates = Arrays.asList(trip); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip)); } @Test @@ -79,9 +80,9 @@ public void testTwoIndependentRequests() { List candidates = Arrays.asList(trip1, trip2); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(2, selection.size()); - Assert.assertTrue(selection.contains(trip1)); - Assert.assertTrue(selection.contains(trip2)); + assertEquals(2, selection.size()); + assertTrue(selection.contains(trip1)); + assertTrue(selection.contains(trip2)); } @Test @@ -103,8 +104,8 @@ public void testTwoRequestsWithOneVehicle() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip3)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip3)); } } @@ -126,8 +127,8 @@ public void testTwoRequestsWithOneVehicleLowPenalty() { List candidates = Arrays.asList(trip1, trip2, trip3); Collection selection = solver.solve(candidates.stream()).trips; - Assert.assertEquals(1, selection.size()); - Assert.assertTrue(selection.contains(trip1)); + assertEquals(1, selection.size()); + assertTrue(selection.contains(trip1)); } } } diff --git a/gurobi/src/test/java/org/matsim/alonso_mora/gurobi/GurobiRelocationSolverTest.java b/gurobi/src/test/java/org/matsim/alonso_mora/gurobi/GurobiRelocationSolverTest.java index b7bdd3f..37bbe92 100644 --- a/gurobi/src/test/java/org/matsim/alonso_mora/gurobi/GurobiRelocationSolverTest.java +++ b/gurobi/src/test/java/org/matsim/alonso_mora/gurobi/GurobiRelocationSolverTest.java @@ -1,6 +1,6 @@ package org.matsim.alonso_mora.gurobi; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.util.ArrayList; @@ -10,7 +10,7 @@ import java.util.LinkedList; import java.util.List; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.matsim.alonso_mora.algorithm.AlonsoMoraVehicle; import org.matsim.alonso_mora.algorithm.relocation.RelocationSolver.Relocation; import org.matsim.api.core.v01.network.Link; diff --git a/pom.xml b/pom.xml index 8dfe1a1..e868e1c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,17 +6,22 @@ alonso-mora 1.0.0 pom - Implementation of the fleet dispatcher by Alonso-Mora et al. for MATSim - This package implements the pooled fleet dispatching algorithm introduced by + Implementation of the fleet dispatcher by Alonso-Mora et al. for + MATSim + This package implements the pooled fleet dispatching algorithm + introduced by -Alonso-Mora, J., Samaranayake, S., Wallar, A., Frazzoli, E., Rus, D., 2017. On-demand high-capacity ride-sharing via dynamic trip-vehicle assignment. Proc Natl Acad Sci USA 114, 462–467. + Alonso-Mora, J., Samaranayake, S., Wallar, A., Frazzoli, E., Rus, D., + 2017. On-demand high-capacity ride-sharing via dynamic trip-vehicle + assignment. Proc Natl Acad Sci USA 114, 462–467. -to the MATSim framework. + to the MATSim framework. 11 11 - 15.0 + 16.0-PR3034 + 5.10.1 @@ -40,21 +45,21 @@ to the MATSim framework. - org.assertj - assertj-core - 3.15.0 + org.junit.jupiter + junit-jupiter-engine + ${junit.version} test - junit - junit - 4.13.1 + org.junit.jupiter + junit-jupiter + ${junit.version} test org.mockito - mockito-core - 3.3.3 + mockito-junit-jupiter + 5.8.0 test