mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
make no. unassigned jobs configurable - related to #431
This commit is contained in:
parent
13156f7acc
commit
48611e1085
2 changed files with 142 additions and 11 deletions
|
|
@ -26,9 +26,7 @@ import com.graphhopper.jsprit.core.algorithm.ruin.listener.RuinListener;
|
||||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||||
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
|
|
||||||
public class RuinAndRecreateModule implements SearchStrategyModule {
|
public class RuinAndRecreateModule implements SearchStrategyModule {
|
||||||
|
|
@ -39,6 +37,12 @@ public class RuinAndRecreateModule implements SearchStrategyModule {
|
||||||
|
|
||||||
private String moduleName;
|
private String moduleName;
|
||||||
|
|
||||||
|
private Random random = new Random(4711);
|
||||||
|
|
||||||
|
private int minUnassignedJobsToBeReinserted = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
private double proportionOfUnassignedJobsToBeReinserted = 1d;
|
||||||
|
|
||||||
public RuinAndRecreateModule(String moduleName, InsertionStrategy insertion, RuinStrategy ruin) {
|
public RuinAndRecreateModule(String moduleName, InsertionStrategy insertion, RuinStrategy ruin) {
|
||||||
super();
|
super();
|
||||||
this.insertion = insertion;
|
this.insertion = insertion;
|
||||||
|
|
@ -46,16 +50,58 @@ public class RuinAndRecreateModule implements SearchStrategyModule {
|
||||||
this.moduleName = moduleName;
|
this.moduleName = moduleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To make overall results reproducible, make sure this class is provided with the "global" random number generator.
|
||||||
|
*
|
||||||
|
* @param random
|
||||||
|
*/
|
||||||
|
public void setRandom(Random random) {
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum number of unassigned jobs that is reinserted in each iteration.
|
||||||
|
*
|
||||||
|
* @param minUnassignedJobsToBeReinserted
|
||||||
|
*/
|
||||||
|
public void setMinUnassignedJobsToBeReinserted(int minUnassignedJobsToBeReinserted) {
|
||||||
|
this.minUnassignedJobsToBeReinserted = minUnassignedJobsToBeReinserted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proportion of unassigned jobs that is reinserted in each iteration.
|
||||||
|
*
|
||||||
|
* @param proportionOfUnassignedJobsToBeReinserted
|
||||||
|
*/
|
||||||
|
public void setProportionOfUnassignedJobsToBeReinserted(double proportionOfUnassignedJobsToBeReinserted) {
|
||||||
|
this.proportionOfUnassignedJobsToBeReinserted = proportionOfUnassignedJobsToBeReinserted;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
|
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution previousVrpSolution) {
|
||||||
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
|
Collection<Job> ruinedJobs = ruin.ruin(previousVrpSolution.getRoutes());
|
||||||
Set<Job> ruinedJobSet = new HashSet<Job>();
|
Set<Job> ruinedJobSet = new HashSet<>();
|
||||||
ruinedJobSet.addAll(ruinedJobs);
|
ruinedJobSet.addAll(ruinedJobs);
|
||||||
ruinedJobSet.addAll(vrpSolution.getUnassignedJobs());
|
List<Job> stillUnassignedInThisIteration = new ArrayList<>();
|
||||||
Collection<Job> unassignedJobs = insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobSet);
|
if (previousVrpSolution.getUnassignedJobs().size() < minUnassignedJobsToBeReinserted) {
|
||||||
vrpSolution.getUnassignedJobs().clear();
|
ruinedJobSet.addAll(previousVrpSolution.getUnassignedJobs());
|
||||||
vrpSolution.getUnassignedJobs().addAll(unassignedJobs);
|
} else {
|
||||||
return vrpSolution;
|
int noUnassignedToBeInserted = Math.max(minUnassignedJobsToBeReinserted, (int) (previousVrpSolution.getUnassignedJobs().size() * proportionOfUnassignedJobsToBeReinserted));
|
||||||
|
List<Job> jobList = new ArrayList<>(previousVrpSolution.getUnassignedJobs());
|
||||||
|
Collections.shuffle(jobList, random);
|
||||||
|
for (int i = 0; i < noUnassignedToBeInserted; i++) {
|
||||||
|
ruinedJobSet.add(jobList.get(i));
|
||||||
|
}
|
||||||
|
for (int i = noUnassignedToBeInserted; i < jobList.size(); i++) {
|
||||||
|
stillUnassignedInThisIteration.add(jobList.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collection<Job> unassignedJobs = insertion.insertJobs(previousVrpSolution.getRoutes(), ruinedJobSet);
|
||||||
|
previousVrpSolution.getUnassignedJobs().clear();
|
||||||
|
previousVrpSolution.getUnassignedJobs().addAll(unassignedJobs);
|
||||||
|
previousVrpSolution.getUnassignedJobs().addAll(stillUnassignedInThisIteration);
|
||||||
|
VehicleRoutingProblemSolution newSolution = previousVrpSolution;
|
||||||
|
return newSolution;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Licensed to GraphHopper GmbH under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with this work for
|
||||||
|
* additional information regarding copyright ownership.
|
||||||
|
*
|
||||||
|
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except in
|
||||||
|
* compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.graphhopper.jsprit.core.algorithm.module;
|
||||||
|
|
||||||
|
import com.graphhopper.jsprit.core.algorithm.recreate.InsertionStrategy;
|
||||||
|
import com.graphhopper.jsprit.core.algorithm.ruin.RuinStrategy;
|
||||||
|
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||||
|
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
public class RuinAndRecreateModuleTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void initialNumOfUnassignedShouldWorkCorrectly() {
|
||||||
|
InsertionStrategy insertionStrategy = mock(InsertionStrategy.class);
|
||||||
|
RuinStrategy ruinStrategy = mock(RuinStrategy.class);
|
||||||
|
RuinAndRecreateModule module = new RuinAndRecreateModule("name", insertionStrategy, ruinStrategy);
|
||||||
|
Collection<VehicleRoute> routes = new ArrayList<>();
|
||||||
|
List<Job> unassigned = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
unassigned.add(mock(Job.class));
|
||||||
|
}
|
||||||
|
VehicleRoutingProblemSolution previousSolution = new VehicleRoutingProblemSolution(routes, unassigned, 0);
|
||||||
|
VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(previousSolution);
|
||||||
|
Assert.assertEquals(0, newSolution.getUnassignedJobs().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void proportionOfUnassignedShouldWorkCorrectly() {
|
||||||
|
InsertionStrategy insertionStrategy = mock(InsertionStrategy.class);
|
||||||
|
RuinStrategy ruinStrategy = mock(RuinStrategy.class);
|
||||||
|
RuinAndRecreateModule module = new RuinAndRecreateModule("name", insertionStrategy, ruinStrategy);
|
||||||
|
module.setMinUnassignedJobsToBeReinserted(5);
|
||||||
|
module.setProportionOfUnassignedJobsToBeReinserted(0.01);
|
||||||
|
Collection<VehicleRoute> routes = new ArrayList<>();
|
||||||
|
List<Job> unassigned = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
unassigned.add(mock(Job.class));
|
||||||
|
}
|
||||||
|
VehicleRoutingProblemSolution previousSolution = new VehicleRoutingProblemSolution(routes, unassigned, 0);
|
||||||
|
VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(previousSolution);
|
||||||
|
Assert.assertEquals(15, newSolution.getUnassignedJobs().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void proportionOfUnassignedShouldWorkCorrectly2() {
|
||||||
|
InsertionStrategy insertionStrategy = mock(InsertionStrategy.class);
|
||||||
|
RuinStrategy ruinStrategy = mock(RuinStrategy.class);
|
||||||
|
RuinAndRecreateModule module = new RuinAndRecreateModule("name", insertionStrategy, ruinStrategy);
|
||||||
|
module.setMinUnassignedJobsToBeReinserted(5);
|
||||||
|
module.setProportionOfUnassignedJobsToBeReinserted(0.5);
|
||||||
|
Collection<VehicleRoute> routes = new ArrayList<>();
|
||||||
|
List<Job> unassigned = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
unassigned.add(mock(Job.class));
|
||||||
|
}
|
||||||
|
VehicleRoutingProblemSolution previousSolution = new VehicleRoutingProblemSolution(routes, unassigned, 0);
|
||||||
|
VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(previousSolution);
|
||||||
|
Assert.assertEquals(10, newSolution.getUnassignedJobs().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue