mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
Merge branch 'master' of https://github.com/graphhopper/jsprit
This commit is contained in:
commit
0a2840428a
18 changed files with 471 additions and 91 deletions
|
|
@ -14,6 +14,7 @@ import com.graphhopper.jsprit.core.algorithm.selector.SelectBest;
|
|||
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.solution.SolutionCostCalculator;
|
||||
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
|
|
@ -568,8 +569,7 @@ public class Jsprit {
|
|||
}
|
||||
|
||||
private DefaultScorer getRegretScorer(VehicleRoutingProblem vrp) {
|
||||
DefaultScorer scorer;
|
||||
scorer = new DefaultScorer(vrp);
|
||||
DefaultScorer scorer = new DefaultScorer(vrp);
|
||||
scorer.setTimeWindowParam(Double.valueOf(properties.getProperty(Parameter.REGRET_TIME_WINDOW_SCORER.toString())));
|
||||
scorer.setDepotDistanceParam(Double.valueOf(properties.getProperty(Parameter.REGRET_DISTANCE_SCORER.toString())));
|
||||
return scorer;
|
||||
|
|
@ -638,14 +638,14 @@ public class Jsprit {
|
|||
if (!hasBreak) {
|
||||
//break defined and required but not assigned penalty
|
||||
if (route.getEnd().getArrTime() > route.getVehicle().getBreak().getTimeWindow().getEnd()) {
|
||||
costs += maxCosts * 2 + route.getVehicle().getBreak().getServiceDuration() * route.getVehicle().getType().getVehicleCostParams().perServiceTimeUnit;
|
||||
} else {
|
||||
costs -= maxCosts * 2;
|
||||
costs += 4 * (maxCosts * 2 + route.getVehicle().getBreak().getServiceDuration() * route.getVehicle().getType().getVehicleCostParams().perServiceTimeUnit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
costs += solution.getUnassignedJobs().size() * maxCosts * 2;
|
||||
for(Job j : solution.getUnassignedJobs()){
|
||||
costs += maxCosts * 2 * (4 - j.getPriority());
|
||||
}
|
||||
return costs;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,10 +23,7 @@ import com.graphhopper.jsprit.core.util.NoiseMaker;
|
|||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -65,6 +62,7 @@ public final class BestInsertion extends AbstractInsertionStrategy {
|
|||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||
Collections.shuffle(unassignedJobList, random);
|
||||
sometimesSortPriorities(unassignedJobList);
|
||||
for (Job unassignedJob : unassignedJobList) {
|
||||
Insertion bestInsertion = null;
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
|
|
@ -93,4 +91,15 @@ public final class BestInsertion extends AbstractInsertionStrategy {
|
|||
return badJobs;
|
||||
}
|
||||
|
||||
private void sometimesSortPriorities(List<Job> unassignedJobList) {
|
||||
if(random.nextDouble() < 0.5){
|
||||
Collections.sort(unassignedJobList, new Comparator<Job>() {
|
||||
@Override
|
||||
public int compare(Job o1, Job o2) {
|
||||
return o1.getPriority() - o2.getPriority();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
|||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
|
||||
|
|
@ -101,6 +98,7 @@ public final class BestInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||
Collections.shuffle(unassignedJobList, random);
|
||||
sometimesSortPriorities(unassignedJobList);
|
||||
List<Batch> batches = distributeRoutes(vehicleRoutes, nuOfBatches);
|
||||
for (final Job unassignedJob : unassignedJobList) {
|
||||
Insertion bestInsertion = null;
|
||||
|
|
@ -143,6 +141,17 @@ public final class BestInsertionConcurrent extends AbstractInsertionStrategy {
|
|||
return badJobs;
|
||||
}
|
||||
|
||||
private void sometimesSortPriorities(List<Job> unassignedJobList) {
|
||||
if(random.nextDouble() < 0.5){
|
||||
Collections.sort(unassignedJobList, new Comparator<Job>() {
|
||||
@Override
|
||||
public int compare(Job o1, Job o2) {
|
||||
return o1.getPriority() - o2.getPriority();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
|
||||
Insertion bestInsertion = null;
|
||||
double bestInsertionCost = Double.MAX_VALUE;
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ public class DefaultScorer implements ScoringFunction {
|
|||
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private double tw_param = -0.5;
|
||||
private double timeWindowParam = -0.5;
|
||||
|
||||
private double depotDistance_param = +0.1;
|
||||
private double depotDistanceParam = +0.1;
|
||||
|
||||
private double minTimeWindowScore = -100000;
|
||||
|
||||
|
|
@ -24,11 +24,11 @@ public class DefaultScorer implements ScoringFunction {
|
|||
}
|
||||
|
||||
public void setTimeWindowParam(double tw_param) {
|
||||
this.tw_param = tw_param;
|
||||
this.timeWindowParam = tw_param;
|
||||
}
|
||||
|
||||
public void setDepotDistanceParam(double depotDistance_param) {
|
||||
this.depotDistance_param = depotDistance_param;
|
||||
this.depotDistanceParam = depotDistance_param;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -55,7 +55,7 @@ public class DefaultScorer implements ScoringFunction {
|
|||
double maxDepotDistance = Math.max(maxDepotDistance_1, maxDepotDistance_2);
|
||||
double minTimeToOperate = Math.min(shipment.getPickupTimeWindow().getEnd() - shipment.getPickupTimeWindow().getStart(),
|
||||
shipment.getDeliveryTimeWindow().getEnd() - shipment.getDeliveryTimeWindow().getStart());
|
||||
return Math.max(tw_param * minTimeToOperate, minTimeWindowScore) + depotDistance_param * maxDepotDistance;
|
||||
return Math.max(timeWindowParam * minTimeToOperate, minTimeWindowScore) + depotDistanceParam * maxDepotDistance;
|
||||
}
|
||||
|
||||
private double scoreService(InsertionData best, Job job) {
|
||||
|
|
@ -67,8 +67,8 @@ public class DefaultScorer implements ScoringFunction {
|
|||
getDistance(best.getSelectedVehicle().getEndLocation(), location)
|
||||
);
|
||||
}
|
||||
return Math.max(tw_param * (((Service) job).getTimeWindow().getEnd() - ((Service) job).getTimeWindow().getStart()), minTimeWindowScore) +
|
||||
depotDistance_param * maxDepotDistance;
|
||||
return Math.max(timeWindowParam * (((Service) job).getTimeWindow().getEnd() - ((Service) job).getTimeWindow().getStart()), minTimeWindowScore) +
|
||||
depotDistanceParam * maxDepotDistance;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -78,6 +78,6 @@ public class DefaultScorer implements ScoringFunction {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=defaultScorer][twParam=" + tw_param + "][depotDistanceParam=" + depotDistance_param + "]";
|
||||
return "[name=defaultScorer][twParam=" + timeWindowParam + "][depotDistanceParam=" + depotDistanceParam + "]";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,18 +140,7 @@ class InsertionDataUpdater {
|
|||
}
|
||||
|
||||
static double score(Job unassignedJob, InsertionData best, InsertionData secondBest, ScoringFunction scoringFunction) {
|
||||
if (best == null) {
|
||||
throw new IllegalStateException("cannot insert job " + unassignedJob.getId());
|
||||
}
|
||||
double score;
|
||||
if (secondBest == null) { //either there is only one vehicle or there are more vehicles, but they cannot load unassignedJob
|
||||
//if only one vehicle, I want the job to be inserted with min iCosts
|
||||
//if there are more vehicles, I want this job to be prioritized since there are no alternatives
|
||||
score = Integer.MAX_VALUE - best.getInsertionCost() + scoringFunction.score(best, unassignedJob);
|
||||
} else {
|
||||
score = (secondBest.getInsertionCost() - best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||
}
|
||||
return score;
|
||||
return Scorer.score(unassignedJob,best,secondBest,scoringFunction);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,18 +204,7 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
|||
|
||||
|
||||
static double score(Job unassignedJob, InsertionData best, InsertionData secondBest, ScoringFunction scoringFunction) {
|
||||
if (best == null) {
|
||||
throw new IllegalStateException("cannot insert job " + unassignedJob.getId());
|
||||
}
|
||||
double score;
|
||||
if (secondBest == null) { //either there is only one vehicle or there are more vehicles, but they cannot load unassignedJob
|
||||
//if only one vehicle, I want the job to be inserted with min iCosts
|
||||
//if there are more vehicles, I want this job to be prioritized since there are no alternatives
|
||||
score = Integer.MAX_VALUE - best.getInsertionCost() + scoringFunction.score(best, unassignedJob);
|
||||
} else {
|
||||
score = (secondBest.getInsertionCost() - best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||
}
|
||||
return score;
|
||||
return Scorer.score(unassignedJob,best,secondBest,scoringFunction);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 24/05/16.
|
||||
*/
|
||||
class Scorer {
|
||||
|
||||
static double score(Job unassignedJob, InsertionData best, InsertionData secondBest, ScoringFunction scoringFunction){
|
||||
if (best == null) {
|
||||
throw new IllegalStateException("cannot insert job " + unassignedJob.getId());
|
||||
}
|
||||
double score;
|
||||
if (secondBest == null) { //either there is only one vehicle or there are more vehicles, but they cannot load unassignedJob
|
||||
//if only one vehicle, I want the job to be inserted with min iCosts
|
||||
//if there are more vehicles, I want this job to be prioritized since there are no alternatives
|
||||
score = (4 - unassignedJob.getPriority()) * (Integer.MAX_VALUE - best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||
} else {
|
||||
score = (4 - unassignedJob.getPriority()) * (secondBest.getInsertionCost() - best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||
}
|
||||
return score;
|
||||
}
|
||||
}
|
||||
|
|
@ -51,4 +51,14 @@ public interface Job extends HasId, HasIndex {
|
|||
* @return name
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Get priority of job. Only 1 = high priority, 2 = medium and 3 = low are allowed.
|
||||
* <p>
|
||||
* Default is 2 = medium.
|
||||
*
|
||||
* @return priority
|
||||
*/
|
||||
public int getPriority();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ import java.util.Collection;
|
|||
*/
|
||||
public class Service extends AbstractJob {
|
||||
|
||||
|
||||
/**
|
||||
* Builder that builds a service.
|
||||
*
|
||||
|
|
@ -48,6 +47,8 @@ public class Service extends AbstractJob {
|
|||
public static class Builder<T extends Service> {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new instance of builder that builds a service.
|
||||
*
|
||||
|
|
@ -86,6 +87,8 @@ public class Service extends AbstractJob {
|
|||
|
||||
private boolean twAdded = false;
|
||||
|
||||
private int priority = 2;
|
||||
|
||||
Builder(String id){
|
||||
this.id = id;
|
||||
timeWindows = new TimeWindowsImpl();
|
||||
|
|
@ -206,6 +209,20 @@ public class Service extends AbstractJob {
|
|||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set priority to service. Only 1 = high priority, 2 = medium and 3 = low are allowed.
|
||||
* <p>
|
||||
* Default is 2 = medium.
|
||||
*
|
||||
* @param priority
|
||||
* @return builder
|
||||
*/
|
||||
public Builder<T> setPriority(int priority) {
|
||||
if(priority < 1 || priority > 3) throw new IllegalStateException("incorrect priority. only 1 = high, 2 = medium and 3 = low is allowed");
|
||||
this.priority = priority;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private final String id;
|
||||
|
|
@ -226,6 +243,8 @@ public class Service extends AbstractJob {
|
|||
|
||||
private final TimeWindows timeWindowManager;
|
||||
|
||||
private final int priority;
|
||||
|
||||
Service(Builder builder) {
|
||||
id = builder.id;
|
||||
serviceTime = builder.serviceTime;
|
||||
|
|
@ -236,6 +255,7 @@ public class Service extends AbstractJob {
|
|||
name = builder.name;
|
||||
location = builder.location;
|
||||
timeWindowManager = builder.timeWindows;
|
||||
priority = builder.priority;
|
||||
}
|
||||
|
||||
public Collection<TimeWindow> getTimeWindows(){
|
||||
|
|
@ -338,4 +358,15 @@ public class Service extends AbstractJob {
|
|||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get priority of service. Only 1 = high priority, 2 = medium and 3 = low are allowed.
|
||||
* <p>
|
||||
* Default is 2 = medium.
|
||||
*
|
||||
* @return priority
|
||||
*/
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public class Shipment extends AbstractJob {
|
|||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Builder that builds the shipment.
|
||||
*
|
||||
|
|
@ -85,6 +86,8 @@ public class Shipment extends AbstractJob {
|
|||
|
||||
private TimeWindowsImpl pickupTimeWindows;
|
||||
|
||||
private int priority = 2;
|
||||
|
||||
/**
|
||||
* Returns new instance of this builder.
|
||||
*
|
||||
|
|
@ -263,6 +266,20 @@ public class Shipment extends AbstractJob {
|
|||
public Builder addPickupTimeWindow(double earliest, double latest) {
|
||||
return addPickupTimeWindow(TimeWindow.newInstance(earliest, latest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set priority to shipment. Only 1 = high priority, 2 = medium and 3 = low are allowed.
|
||||
* <p>
|
||||
* Default is 2 = medium.
|
||||
*
|
||||
* @param priority
|
||||
* @return builder
|
||||
*/
|
||||
public Builder setPriority(int priority) {
|
||||
if(priority < 1 || priority > 3) throw new IllegalStateException("incorrect priority. only 1 = high, 2 = medium and 3 = low is allowed");
|
||||
this.priority = priority;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private final String id;
|
||||
|
|
@ -289,6 +306,8 @@ public class Shipment extends AbstractJob {
|
|||
|
||||
private final TimeWindowsImpl pickupTimeWindows;
|
||||
|
||||
private final int priority;
|
||||
|
||||
Shipment(Builder builder) {
|
||||
this.id = builder.id;
|
||||
this.pickupServiceTime = builder.pickupServiceTime;
|
||||
|
|
@ -302,6 +321,7 @@ public class Shipment extends AbstractJob {
|
|||
this.deliveryLocation_ = builder.deliveryLocation_;
|
||||
this.deliveryTimeWindows = builder.deliveryTimeWindows;
|
||||
this.pickupTimeWindows = builder.pickupTimeWindows;
|
||||
this.priority = builder.priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -409,5 +429,14 @@ public class Shipment extends AbstractJob {
|
|||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get priority of shipment. Only 1 = high priority, 2 = medium and 3 = low are allowed.
|
||||
* <p>
|
||||
* Default is 2 = medium.
|
||||
*
|
||||
* @return priority
|
||||
*/
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue