mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
add a way to use fast regret with custom contraints
This commit is contained in:
parent
ea1889b15a
commit
82565b4416
7 changed files with 359 additions and 49 deletions
|
|
@ -436,6 +436,7 @@ public class Jsprit {
|
|||
.build();
|
||||
scorer = getRegretScorer(vrp);
|
||||
regretInsertion.setScoringFunction(scorer);
|
||||
regretInsertion.setDependencyTypes(constraintManager.getDependencyTypes());
|
||||
regret = regretInsertion;
|
||||
}
|
||||
else {
|
||||
|
|
@ -461,6 +462,7 @@ public class Jsprit {
|
|||
.build();
|
||||
scorer = getRegretScorer(vrp);
|
||||
regretInsertion.setScoringFunction(scorer);
|
||||
regretInsertion.setDependencyTypes(constraintManager.getDependencyTypes());
|
||||
regret = regretInsertion;
|
||||
}
|
||||
else{
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.DependencyType;
|
||||
import com.graphhopper.jsprit.core.problem.job.Break;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
|
|
@ -57,6 +58,8 @@ public class RegretInsertionConcurrentFast extends AbstractInsertionStrategy {
|
|||
|
||||
private boolean switchAllowed = true;
|
||||
|
||||
private DependencyType[] dependencyTypes = null;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the scoring function.
|
||||
|
|
@ -97,6 +100,10 @@ public class RegretInsertionConcurrentFast extends AbstractInsertionStrategy {
|
|||
return ids;
|
||||
}
|
||||
|
||||
public void setDependencyTypes(DependencyType[] dependencyTypes){
|
||||
this.dependencyTypes = dependencyTypes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs insertion.
|
||||
|
|
@ -139,15 +146,8 @@ public class RegretInsertionConcurrentFast extends AbstractInsertionStrategy {
|
|||
List<Job> unassignedJobList = new ArrayList<Job>(jobs);
|
||||
List<Job> badJobList = new ArrayList<Job>();
|
||||
if(!firstRun && lastModified == null) throw new IllegalStateException("ho. this must not be.");
|
||||
if(firstRun){
|
||||
firstRun = false;
|
||||
updateInsertionData(priorityQueues, routes, unassignedJobList, updateRound);
|
||||
for(VehicleRoute r : routes) updates.put(r,updateRound);
|
||||
}
|
||||
else{
|
||||
updateInsertionData(priorityQueues, Arrays.asList(lastModified), unassignedJobList, updateRound);
|
||||
updates.put(lastModified,updateRound);
|
||||
}
|
||||
updateInsertionData(priorityQueues, routes, unassignedJobList, updateRound,firstRun,lastModified,updates);
|
||||
if(firstRun) firstRun = false;
|
||||
updateRound++;
|
||||
ScoredJob bestScoredJob = InsertionDataUpdater.getBest(switchAllowed,initialVehicleIds,fleetManager, insertionCostsCalculator, scoringFunction, priorityQueues, updates, unassignedJobList, badJobList);
|
||||
if (bestScoredJob != null) {
|
||||
|
|
@ -167,19 +167,38 @@ public class RegretInsertionConcurrentFast extends AbstractInsertionStrategy {
|
|||
return badJobs;
|
||||
}
|
||||
|
||||
private void updateInsertionData(final TreeSet<VersionedInsertionData>[] priorityQueues, final Collection<VehicleRoute> routes, List<Job> unassignedJobList, final int updateRound) {
|
||||
private void updateInsertionData(final TreeSet<VersionedInsertionData>[] priorityQueues, final Collection<VehicleRoute> routes, List<Job> unassignedJobList, final int updateRound, final boolean firstRun, final VehicleRoute lastModified, Map<VehicleRoute, Integer> updates) {
|
||||
List<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>();
|
||||
boolean updatedAllRoutes = false;
|
||||
for (final Job unassignedJob : unassignedJobList) {
|
||||
if(priorityQueues[unassignedJob.getIndex()] == null){
|
||||
priorityQueues[unassignedJob.getIndex()] = new TreeSet<VersionedInsertionData>(InsertionDataUpdater.getComparator());
|
||||
}
|
||||
final TreeSet<VersionedInsertionData> priorityQueue = priorityQueues[unassignedJob.getIndex()];
|
||||
tasks.add(new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
return InsertionDataUpdater.update(switchAllowed,initialVehicleIds,fleetManager, insertionCostsCalculator, priorityQueue, updateRound, unassignedJob, routes);
|
||||
if(firstRun) {
|
||||
makeCallables(tasks, true, priorityQueues[unassignedJob.getIndex()], updateRound, unassignedJob, routes, lastModified);
|
||||
updatedAllRoutes = true;
|
||||
}
|
||||
});
|
||||
else{
|
||||
if(dependencyTypes == null || dependencyTypes[unassignedJob.getIndex()] == null){
|
||||
makeCallables(tasks, false, priorityQueues[unassignedJob.getIndex()], updateRound, unassignedJob, routes, lastModified);
|
||||
}
|
||||
else {
|
||||
DependencyType dependencyType = dependencyTypes[unassignedJob.getIndex()];
|
||||
if (dependencyType.equals(DependencyType.INTER_ROUTE) || dependencyType.equals(DependencyType.INTRA_ROUTE)) {
|
||||
makeCallables(tasks, false, priorityQueues[unassignedJob.getIndex()], updateRound, unassignedJob, routes, lastModified);
|
||||
updatedAllRoutes = true;
|
||||
} else {
|
||||
makeCallables(tasks, true, priorityQueues[unassignedJob.getIndex()], updateRound, unassignedJob, routes, lastModified);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(updatedAllRoutes){
|
||||
for(VehicleRoute r : routes) updates.put(r,updateRound);
|
||||
}
|
||||
else{
|
||||
updates.put(lastModified,updateRound);
|
||||
}
|
||||
try {
|
||||
List<Future<Boolean>> futures = executor.invokeAll(tasks);
|
||||
|
|
@ -189,8 +208,24 @@ public class RegretInsertionConcurrentFast extends AbstractInsertionStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void makeCallables(List<Callable<Boolean>> tasks, boolean updateAll, final TreeSet<VersionedInsertionData> priorityQueue, final int updateRound, final Job unassignedJob, final Collection<VehicleRoute> routes, final VehicleRoute lastModified) {
|
||||
if(updateAll) {
|
||||
tasks.add(new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
return InsertionDataUpdater.update(switchAllowed, initialVehicleIds, fleetManager, insertionCostsCalculator, priorityQueue, updateRound, unassignedJob, routes);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
tasks.add(new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
return InsertionDataUpdater.update(switchAllowed, initialVehicleIds, fleetManager, insertionCostsCalculator, priorityQueue, updateRound, unassignedJob, Arrays.asList(lastModified));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.Break;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.DependencyType;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleFleetManager;
|
||||
|
|
@ -51,7 +51,7 @@ public class RegretInsertionFast extends AbstractInsertionStrategy {
|
|||
|
||||
private boolean switchAllowed = true;
|
||||
|
||||
|
||||
private DependencyType[] dependencyTypes = null;
|
||||
|
||||
public RegretInsertionFast(JobInsertionCostsCalculator jobInsertionCalculator, VehicleRoutingProblem vehicleRoutingProblem, VehicleFleetManager fleetManager) {
|
||||
super(vehicleRoutingProblem);
|
||||
|
|
@ -78,6 +78,10 @@ public class RegretInsertionFast extends AbstractInsertionStrategy {
|
|||
this.switchAllowed = switchAllowed;
|
||||
}
|
||||
|
||||
public void setDependencyTypes(DependencyType[] dependencyTypes){
|
||||
this.dependencyTypes = dependencyTypes;
|
||||
}
|
||||
|
||||
private Set<String> getInitialVehicleIds(VehicleRoutingProblem vehicleRoutingProblem) {
|
||||
Set<String> ids = new HashSet<String>();
|
||||
for(VehicleRoute r : vehicleRoutingProblem.getInitialVehicleRoutes()){
|
||||
|
|
@ -101,25 +105,25 @@ public class RegretInsertionFast extends AbstractInsertionStrategy {
|
|||
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||
|
||||
Iterator<Job> jobIterator = unassignedJobs.iterator();
|
||||
while (jobIterator.hasNext()){
|
||||
Job job = jobIterator.next();
|
||||
if(job instanceof Break){
|
||||
VehicleRoute route = InsertionDataUpdater.findRoute(routes, job);
|
||||
if(route == null){
|
||||
badJobs.add(job);
|
||||
}
|
||||
else {
|
||||
InsertionData iData = insertionCostsCalculator.getInsertionData(route, job, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
|
||||
if (iData instanceof InsertionData.NoInsertionFound) {
|
||||
badJobs.add(job);
|
||||
} else {
|
||||
insertJob(job, iData, route);
|
||||
}
|
||||
}
|
||||
jobIterator.remove();
|
||||
}
|
||||
}
|
||||
// Iterator<Job> jobIterator = unassignedJobs.iterator();
|
||||
// while (jobIterator.hasNext()){
|
||||
// Job job = jobIterator.next();
|
||||
// if(job instanceof Break){
|
||||
// VehicleRoute route = InsertionDataUpdater.findRoute(routes, job);
|
||||
// if(route == null){
|
||||
// badJobs.add(job);
|
||||
// }
|
||||
// else {
|
||||
// InsertionData iData = insertionCostsCalculator.getInsertionData(route, job, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
|
||||
// if (iData instanceof InsertionData.NoInsertionFound) {
|
||||
// badJobs.add(job);
|
||||
// } else {
|
||||
// insertJob(job, iData, route);
|
||||
// }
|
||||
// }
|
||||
// jobIterator.remove();
|
||||
// }
|
||||
// }
|
||||
|
||||
List<Job> jobs = new ArrayList<Job>(unassignedJobs);
|
||||
TreeSet<VersionedInsertionData>[] priorityQueues = new TreeSet[vrp.getJobs().values().size() + 2];
|
||||
|
|
@ -130,15 +134,15 @@ public class RegretInsertionFast extends AbstractInsertionStrategy {
|
|||
while (!jobs.isEmpty()) {
|
||||
List<Job> unassignedJobList = new ArrayList<Job>(jobs);
|
||||
List<Job> badJobList = new ArrayList<Job>();
|
||||
if(!firstRun && lastModified == null) throw new IllegalStateException("fooo");
|
||||
if(!firstRun && lastModified == null) throw new IllegalStateException("last modified route is null. this should not be.");
|
||||
if(firstRun){
|
||||
updateInsertionData(priorityQueues, routes, unassignedJobList, updateRound, firstRun, lastModified, updates);
|
||||
firstRun = false;
|
||||
updateInsertionData(priorityQueues, routes, unassignedJobList, updateRound);
|
||||
for(VehicleRoute r : routes) updates.put(r,updateRound);
|
||||
}
|
||||
else{
|
||||
updateInsertionData(priorityQueues, Arrays.asList(lastModified), unassignedJobList, updateRound);
|
||||
updates.put(lastModified,updateRound);
|
||||
//update for all routes || remove history and only update modified route
|
||||
updateInsertionData(priorityQueues, routes, unassignedJobList, updateRound, firstRun, lastModified, updates);
|
||||
// updates.put(lastModified,updateRound);
|
||||
}
|
||||
updateRound++;
|
||||
ScoredJob bestScoredJob = InsertionDataUpdater.getBest(switchAllowed,initialVehicleIds,fleetManager,insertionCostsCalculator,scoringFunction,priorityQueues,updates,unassignedJobList,badJobList);
|
||||
|
|
@ -159,12 +163,31 @@ public class RegretInsertionFast extends AbstractInsertionStrategy {
|
|||
return badJobs;
|
||||
}
|
||||
|
||||
private void updateInsertionData(TreeSet<VersionedInsertionData>[] priorityQueues, Collection<VehicleRoute> routes, List<Job> unassignedJobList, int updateRound) {
|
||||
private void updateInsertionData(TreeSet<VersionedInsertionData>[] priorityQueues, Collection<VehicleRoute> routes, List<Job> unassignedJobList, int updateRound, boolean firstRun, VehicleRoute lastModified, Map<VehicleRoute, Integer> updates) {
|
||||
for (Job unassignedJob : unassignedJobList) {
|
||||
if(priorityQueues[unassignedJob.getIndex()] == null){
|
||||
priorityQueues[unassignedJob.getIndex()] = new TreeSet<VersionedInsertionData>(InsertionDataUpdater.getComparator());
|
||||
}
|
||||
InsertionDataUpdater.update(switchAllowed, initialVehicleIds,fleetManager,insertionCostsCalculator, priorityQueues[unassignedJob.getIndex()], updateRound, unassignedJob, routes);
|
||||
if(firstRun) {
|
||||
InsertionDataUpdater.update(switchAllowed, initialVehicleIds, fleetManager, insertionCostsCalculator, priorityQueues[unassignedJob.getIndex()], updateRound, unassignedJob, routes);
|
||||
for(VehicleRoute r : routes) updates.put(r,updateRound);
|
||||
}
|
||||
else{
|
||||
if(dependencyTypes == null || dependencyTypes[unassignedJob.getIndex()] == null){
|
||||
InsertionDataUpdater.update(switchAllowed, initialVehicleIds, fleetManager, insertionCostsCalculator, priorityQueues[unassignedJob.getIndex()], updateRound, unassignedJob, Arrays.asList(lastModified));
|
||||
for(VehicleRoute r : routes) updates.put(r,updateRound);
|
||||
}
|
||||
else {
|
||||
DependencyType dependencyType = dependencyTypes[unassignedJob.getIndex()];
|
||||
if (dependencyType.equals(DependencyType.INTER_ROUTE) || dependencyType.equals(DependencyType.INTRA_ROUTE)) {
|
||||
InsertionDataUpdater.update(switchAllowed, initialVehicleIds, fleetManager, insertionCostsCalculator, priorityQueues[unassignedJob.getIndex()], updateRound, unassignedJob, routes);
|
||||
for(VehicleRoute r : routes) updates.put(r,updateRound);
|
||||
} else {
|
||||
InsertionDataUpdater.update(switchAllowed, initialVehicleIds, fleetManager, insertionCostsCalculator, priorityQueues[unassignedJob.getIndex()], updateRound, unassignedJob, Arrays.asList(lastModified));
|
||||
updates.put(lastModified,updateRound);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package com.graphhopper.jsprit.core.problem.constraint;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
|
||||
|
|
@ -59,17 +60,40 @@ public class ConstraintManager implements HardActivityConstraint, HardRouteConst
|
|||
|
||||
private boolean skillconstraintSet = false;
|
||||
|
||||
private final DependencyType[] dependencyTypes;
|
||||
|
||||
public ConstraintManager(VehicleRoutingProblem vrp, RouteAndActivityStateGetter stateManager) {
|
||||
this.vrp = vrp;
|
||||
this.stateManager = stateManager;
|
||||
dependencyTypes = new DependencyType[vrp.getJobs().size() + 1];
|
||||
}
|
||||
|
||||
public ConstraintManager(VehicleRoutingProblem vrp, RouteAndActivityStateGetter stateManager, Collection<Constraint> constraints) {
|
||||
this.vrp = vrp;
|
||||
this.stateManager = stateManager;
|
||||
dependencyTypes = new DependencyType[vrp.getJobs().size() + 1];
|
||||
resolveConstraints(constraints);
|
||||
}
|
||||
|
||||
public DependencyType[] getDependencyTypes() {
|
||||
return dependencyTypes;
|
||||
}
|
||||
|
||||
public void setDependencyType(String jobId, DependencyType dependencyType){
|
||||
Job job = vrp.getJobs().get(jobId);
|
||||
if(job != null) {
|
||||
dependencyTypes[job.getIndex()] = dependencyType;
|
||||
}
|
||||
}
|
||||
|
||||
public DependencyType getDependencyType(String jobId){
|
||||
Job job = vrp.getJobs().get(jobId);
|
||||
if(job != null){
|
||||
return dependencyTypes[job.getIndex()];
|
||||
}
|
||||
return DependencyType.NO_TYPE;
|
||||
}
|
||||
|
||||
private void resolveConstraints(Collection<Constraint> constraints) {
|
||||
for (Constraint c : constraints) {
|
||||
boolean constraintTypeKnown = false;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package com.graphhopper.jsprit.core.problem.constraint;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 12/07/16.
|
||||
*/
|
||||
public enum DependencyType {
|
||||
|
||||
INTER_ROUTE, INTRA_ROUTE, NO_TYPE
|
||||
|
||||
}
|
||||
|
|
@ -17,20 +17,30 @@
|
|||
|
||||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||
import com.graphhopper.jsprit.core.algorithm.box.Jsprit;
|
||||
import com.graphhopper.jsprit.core.algorithm.recreate.listener.BeforeJobInsertionListener;
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateId;
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
|
||||
import com.graphhopper.jsprit.core.algorithm.state.StateUpdater;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.DependencyType;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.HardRouteConstraint;
|
||||
import com.graphhopper.jsprit.core.problem.driver.Driver;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
import com.graphhopper.jsprit.core.problem.job.Shipment;
|
||||
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
|
||||
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.ActivityVisitor;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.FiniteFleetManagerFactory;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleFleetManager;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.*;
|
||||
import com.graphhopper.jsprit.core.reporting.SolutionPrinter;
|
||||
import com.graphhopper.jsprit.core.util.Coordinate;
|
||||
import com.graphhopper.jsprit.core.util.Solutions;
|
||||
import junit.framework.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
|
@ -92,6 +102,197 @@ public class RegretInsertionTest {
|
|||
Assert.assertTrue(position.isCorrect());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void solutionWithFastRegretMustBeCorrect() {
|
||||
Service s1 = Service.Builder.newInstance("s1").setLocation(Location.newInstance(0, 10)).build();
|
||||
Service s2 = Service.Builder.newInstance("s2").setLocation(Location.newInstance(0, -10)).build();
|
||||
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(Location.newInstance(0, 5)).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance(0, -5)).build();
|
||||
final VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addJob(s1).addJob(s2)
|
||||
.addVehicle(v1).addVehicle(v2).setFleetSize(VehicleRoutingProblem.FleetSize.FINITE).build();
|
||||
|
||||
StateManager stateManager = new StateManager(vrp);
|
||||
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
|
||||
|
||||
VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp)
|
||||
.addCoreStateAndConstraintStuff(true)
|
||||
.setProperty(Jsprit.Parameter.FAST_REGRET,"true")
|
||||
.setStateAndConstraintManager(stateManager, constraintManager).buildAlgorithm();
|
||||
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
|
||||
|
||||
Assert.assertEquals(2, solution.getRoutes().size());
|
||||
}
|
||||
|
||||
static class JobInRouteUpdater implements StateUpdater, ActivityVisitor {
|
||||
|
||||
private StateManager stateManager;
|
||||
|
||||
private StateId job1AssignedId;
|
||||
|
||||
private StateId job2AssignedId;
|
||||
|
||||
private VehicleRoute route;
|
||||
|
||||
public JobInRouteUpdater(StateManager stateManager, StateId job1AssignedId, StateId job2AssignedId) {
|
||||
this.stateManager = stateManager;
|
||||
this.job1AssignedId = job1AssignedId;
|
||||
this.job2AssignedId = job2AssignedId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void begin(VehicleRoute route) {
|
||||
this.route = route;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(TourActivity activity) {
|
||||
if(((TourActivity.JobActivity)activity).getJob().getId().equals("s1")){
|
||||
stateManager.putProblemState(job1AssignedId,Boolean.class,true);
|
||||
}
|
||||
if(((TourActivity.JobActivity)activity).getJob().getId().equals("s2")){
|
||||
stateManager.putProblemState(job2AssignedId,Boolean.class,true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static class RouteConstraint implements HardRouteConstraint{
|
||||
|
||||
private final StateId job1AssignedId;
|
||||
|
||||
private final StateId job2AssignedId;
|
||||
|
||||
private StateManager stateManager;
|
||||
|
||||
public RouteConstraint(StateId job1Assigned, StateId job2Assigned, StateManager stateManager) {
|
||||
this.job1AssignedId = job1Assigned;
|
||||
this.job2AssignedId = job2Assigned;
|
||||
this.stateManager = stateManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fulfilled(JobInsertionContext insertionContext) {
|
||||
if(insertionContext.getJob().getId().equals("s1")){
|
||||
Boolean job2Assigned = stateManager.getProblemState(job2AssignedId,Boolean.class);
|
||||
if(job2Assigned == null || job2Assigned == false) return true;
|
||||
else {
|
||||
for(Job j : insertionContext.getRoute().getTourActivities().getJobs()){
|
||||
if(j.getId().equals("s2")) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(insertionContext.getJob().getId().equals("s2")){
|
||||
Boolean job1Assigned = stateManager.getProblemState(job1AssignedId,Boolean.class);
|
||||
if(job1Assigned == null || job1Assigned == false) return true;
|
||||
else {
|
||||
for(Job j : insertionContext.getRoute().getTourActivities().getJobs()){
|
||||
if(j.getId().equals("s1")) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void solutionWithConstraintAndWithFastRegretMustBeCorrect() {
|
||||
Service s1 = Service.Builder.newInstance("s1").addSizeDimension(0,1).setLocation(Location.newInstance(0, 10)).build();
|
||||
Service s2 = Service.Builder.newInstance("s2").addSizeDimension(0,1).setLocation(Location.newInstance(0, -10)).build();
|
||||
Service s3 = Service.Builder.newInstance("s3").addSizeDimension(0,1).setLocation(Location.newInstance(0, -11)).build();
|
||||
Service s4 = Service.Builder.newInstance("s4").addSizeDimension(0,1).setLocation(Location.newInstance(0, 11)).build();
|
||||
|
||||
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0,2).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setType(type).setStartLocation(Location.newInstance(0, 10)).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setType(type).setStartLocation(Location.newInstance(0, -10)).build();
|
||||
final VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addJob(s1).addJob(s2).addJob(s3).addJob(s4)
|
||||
.addVehicle(v1).addVehicle(v2).setFleetSize(VehicleRoutingProblem.FleetSize.FINITE).build();
|
||||
|
||||
final StateManager stateManager = new StateManager(vrp);
|
||||
StateId job1Assigned = stateManager.createStateId("job1-assigned");
|
||||
StateId job2Assigned = stateManager.createStateId("job2-assigned");
|
||||
stateManager.addStateUpdater(new JobInRouteUpdater(stateManager,job1Assigned,job2Assigned));
|
||||
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
|
||||
constraintManager.addConstraint(new RouteConstraint(job1Assigned,job2Assigned,stateManager));
|
||||
constraintManager.setDependencyType("s1", DependencyType.INTRA_ROUTE);
|
||||
constraintManager.setDependencyType("s2", DependencyType.INTRA_ROUTE);
|
||||
|
||||
VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp)
|
||||
.addCoreStateAndConstraintStuff(true)
|
||||
.setProperty(Jsprit.Parameter.FAST_REGRET, "true")
|
||||
.setStateAndConstraintManager(stateManager, constraintManager)
|
||||
// .setProperty(Jsprit.Strategy.CLUSTER_REGRET, "0.")
|
||||
// .setProperty(Jsprit.Strategy.CLUSTER_BEST, "0.")
|
||||
// .setProperty(Jsprit.Strategy.RADIAL_REGRET, "0.")
|
||||
// .setProperty(Jsprit.Strategy.RADIAL_BEST, "0.")
|
||||
// .setProperty(Jsprit.Strategy.RANDOM_REGRET, "1.")
|
||||
// .setProperty(Jsprit.Strategy.RANDOM_BEST, "0.")
|
||||
// .setProperty(Jsprit.Strategy.WORST_REGRET, "0.")
|
||||
// .setProperty(Jsprit.Strategy.WORST_BEST, "0.")
|
||||
.buildAlgorithm();
|
||||
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
|
||||
SolutionPrinter.print(vrp,solution, SolutionPrinter.Print.VERBOSE);
|
||||
for(VehicleRoute route : solution.getRoutes()){
|
||||
if(route.getTourActivities().servesJob(s1)){
|
||||
if(!route.getTourActivities().servesJob(s2)){
|
||||
Assert.assertFalse(true);
|
||||
}
|
||||
else Assert.assertTrue(true);
|
||||
}
|
||||
}
|
||||
// Assert.assertEquals(1, solution.getRoutes().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void solutionWithConstraintAndWithFastRegretConcurrentMustBeCorrect() {
|
||||
Service s1 = Service.Builder.newInstance("s1").addSizeDimension(0,1).setLocation(Location.newInstance(0, 10)).build();
|
||||
Service s2 = Service.Builder.newInstance("s2").addSizeDimension(0,1).setLocation(Location.newInstance(0, -10)).build();
|
||||
Service s3 = Service.Builder.newInstance("s3").addSizeDimension(0,1).setLocation(Location.newInstance(0, -11)).build();
|
||||
Service s4 = Service.Builder.newInstance("s4").addSizeDimension(0,1).setLocation(Location.newInstance(0, 11)).build();
|
||||
|
||||
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0,2).build();
|
||||
VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setType(type).setStartLocation(Location.newInstance(0, 10)).build();
|
||||
VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setType(type).setStartLocation(Location.newInstance(0, -10)).build();
|
||||
final VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addJob(s1).addJob(s2).addJob(s3).addJob(s4)
|
||||
.addVehicle(v1).addVehicle(v2).setFleetSize(VehicleRoutingProblem.FleetSize.FINITE).build();
|
||||
|
||||
final StateManager stateManager = new StateManager(vrp);
|
||||
StateId job1Assigned = stateManager.createStateId("job1-assigned");
|
||||
StateId job2Assigned = stateManager.createStateId("job2-assigned");
|
||||
stateManager.addStateUpdater(new JobInRouteUpdater(stateManager,job1Assigned,job2Assigned));
|
||||
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
|
||||
constraintManager.addConstraint(new RouteConstraint(job1Assigned,job2Assigned,stateManager));
|
||||
constraintManager.setDependencyType("s1", DependencyType.INTRA_ROUTE);
|
||||
constraintManager.setDependencyType("s2", DependencyType.INTRA_ROUTE);
|
||||
|
||||
VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp)
|
||||
.addCoreStateAndConstraintStuff(true)
|
||||
.setProperty(Jsprit.Parameter.FAST_REGRET, "true")
|
||||
.setProperty(Jsprit.Parameter.THREADS,"4")
|
||||
.setStateAndConstraintManager(stateManager, constraintManager)
|
||||
.buildAlgorithm();
|
||||
|
||||
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
|
||||
SolutionPrinter.print(vrp,solution, SolutionPrinter.Print.VERBOSE);
|
||||
for(VehicleRoute route : solution.getRoutes()){
|
||||
if(route.getTourActivities().servesJob(s1)){
|
||||
if(!route.getTourActivities().servesJob(s2)){
|
||||
Assert.assertFalse(true);
|
||||
}
|
||||
else Assert.assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shipment1ShouldBeAddedFirst() {
|
||||
Shipment s1 = Shipment.Builder.newInstance("s1")
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
******************************************************************************/
|
||||
package com.graphhopper.jsprit.core.problem;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Random;
|
||||
|
|
@ -369,4 +370,18 @@ public class CapacityTest {
|
|||
Capacity cap2 = Capacity.Builder.newInstance().build();
|
||||
assertEquals(0.0, Capacity.divide(cap1, cap2), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeEqual(){
|
||||
Capacity cap1 = Capacity.Builder.newInstance().build();
|
||||
Capacity cap2 = Capacity.Builder.newInstance().build();
|
||||
Assert.assertTrue(cap1.equals(cap2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeEqual2(){
|
||||
Capacity cap1 = Capacity.Builder.newInstance().addDimension(0,10).addDimension(1,100).addDimension(2,1000).build();
|
||||
Capacity cap2 = Capacity.Builder.newInstance().addDimension(0,10).addDimension(2, 1000).addDimension(1,100).build();
|
||||
Assert.assertTrue(cap1.equals(cap2));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue