1
0
Fork 0
mirror of https://github.com/graphhopper/jsprit.git synced 2020-01-24 07:45:05 +01:00

test and modify ruin strategies to deal with initial routes

This commit is contained in:
oblonski 2015-03-10 10:45:59 +01:00
parent 62e12d5153
commit 2b87155879
10 changed files with 192 additions and 29 deletions

View file

@ -20,6 +20,7 @@ package jsprit.core.algorithm.ruin;
import jsprit.core.algorithm.ruin.listener.RuinListener; import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.algorithm.ruin.listener.RuinListeners; import jsprit.core.algorithm.ruin.listener.RuinListeners;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Job; import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.util.RandomNumberGeneration; import jsprit.core.util.RandomNumberGeneration;
@ -33,14 +34,12 @@ public abstract class AbstractRuinStrategy implements RuinStrategy{
protected Random random = RandomNumberGeneration.getRandom(); protected Random random = RandomNumberGeneration.getRandom();
protected VehicleRoutingProblem vrp;
public void setRandom(Random random) { public void setRandom(Random random) {
this.random = random; this.random = random;
} }
protected AbstractRuinStrategy() {
ruinListeners = new RuinListeners();
}
protected RuinShareFactory ruinShareFactory; protected RuinShareFactory ruinShareFactory;
public void setRuinShareFactory(RuinShareFactory ruinShareFactory){ public void setRuinShareFactory(RuinShareFactory ruinShareFactory){
@ -51,6 +50,11 @@ public abstract class AbstractRuinStrategy implements RuinStrategy{
return ruinShareFactory; return ruinShareFactory;
} }
protected AbstractRuinStrategy(VehicleRoutingProblem vrp) {
this.vrp = vrp;
ruinListeners = new RuinListeners();
}
@Override @Override
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes){ public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes){
ruinListeners.ruinStarts(vehicleRoutes); ruinListeners.ruinStarts(vehicleRoutes);
@ -90,6 +94,7 @@ public abstract class AbstractRuinStrategy implements RuinStrategy{
} }
protected boolean removeJob(Job job, Collection<VehicleRoute> vehicleRoutes) { protected boolean removeJob(Job job, Collection<VehicleRoute> vehicleRoutes) {
if(jobIsInitial(job)) return false;
for (VehicleRoute route : vehicleRoutes) { for (VehicleRoute route : vehicleRoutes) {
if (removeJob(job, route)) { if (removeJob(job, route)) {
return true; return true;
@ -98,7 +103,12 @@ public abstract class AbstractRuinStrategy implements RuinStrategy{
return false; return false;
} }
private boolean jobIsInitial(Job job){
return !vrp.getJobs().containsKey(job.getId()); //for initial jobs (being not contained in problem
}
protected boolean removeJob(Job job, VehicleRoute route) { protected boolean removeJob(Job job, VehicleRoute route) {
if(jobIsInitial(job)) return false;
boolean removed = route.getTourActivities().removeJob(job); boolean removed = route.getTourActivities().removeJob(job);
if (removed) { if (removed) {
ruinListeners.removed(job,route); ruinListeners.removed(job,route);

View file

@ -79,7 +79,7 @@ public final class RuinClusters extends AbstractRuinStrategy implements Iteratio
private double epsFactor = 0.8; private double epsFactor = 0.8;
public RuinClusters(VehicleRoutingProblem vrp, final int initialNumberJobsToRemove, JobNeighborhoods jobNeighborhoods) { public RuinClusters(VehicleRoutingProblem vrp, final int initialNumberJobsToRemove, JobNeighborhoods jobNeighborhoods) {
super(); super(vrp);
this.vrp = vrp; this.vrp = vrp;
setRuinShareFactory(new RuinShareFactory() { setRuinShareFactory(new RuinShareFactory() {
@Override @Override
@ -156,9 +156,10 @@ public final class RuinClusters extends AbstractRuinStrategy implements Iteratio
List<Job> cluster = dbscan.getRandomCluster(targetRoute); List<Job> cluster = dbscan.getRandomCluster(targetRoute);
for(Job j : cluster){ for(Job j : cluster){
if(toRemove == 0) break; if(toRemove == 0) break;
removeJob(j, vehicleRoutes); if(removeJob(j, vehicleRoutes)) {
lastRemoved.add(j); lastRemoved.add(j);
unassignedJobs.add(j); unassignedJobs.add(j);
}
toRemove--; toRemove--;
} }
ruined.add(targetRoute); ruined.add(targetRoute);

View file

@ -54,7 +54,7 @@ public final class RuinRadial extends AbstractRuinStrategy {
* @param jobDistance i.e. a measure to define the distance between two jobs and whether they are located close or distant to eachother * @param jobDistance i.e. a measure to define the distance between two jobs and whether they are located close or distant to eachother
*/ */
public RuinRadial(VehicleRoutingProblem vrp, double fraction2beRemoved, JobDistance jobDistance) { public RuinRadial(VehicleRoutingProblem vrp, double fraction2beRemoved, JobDistance jobDistance) {
super(); super(vrp);
this.vrp = vrp; this.vrp = vrp;
noJobsToMemorize = (int) Math.ceil(vrp.getJobs().values().size()*fraction2beRemoved); noJobsToMemorize = (int) Math.ceil(vrp.getJobs().values().size()*fraction2beRemoved);
ruinShareFactory = new RuinShareFactory() { ruinShareFactory = new RuinShareFactory() {
@ -72,7 +72,7 @@ public final class RuinRadial extends AbstractRuinStrategy {
} }
public RuinRadial(VehicleRoutingProblem vrp, int noJobs2beRemoved, JobDistance jobDistance) { public RuinRadial(VehicleRoutingProblem vrp, int noJobs2beRemoved, JobDistance jobDistance) {
super(); super(vrp);
this.vrp = vrp; this.vrp = vrp;
// this.fractionOfAllNodes2beRuined = fraction2beRemoved; // this.fractionOfAllNodes2beRuined = fraction2beRemoved;
noJobsToMemorize = noJobs2beRemoved; noJobsToMemorize = noJobs2beRemoved;
@ -91,7 +91,7 @@ public final class RuinRadial extends AbstractRuinStrategy {
} }
public RuinRadial(VehicleRoutingProblem vrp, int noJobs2beRemoved, JobNeighborhoods neighborhoods) { public RuinRadial(VehicleRoutingProblem vrp, int noJobs2beRemoved, JobNeighborhoods neighborhoods) {
super(); super(vrp);
this.vrp = vrp; this.vrp = vrp;
noJobsToMemorize = noJobs2beRemoved; noJobsToMemorize = noJobs2beRemoved;
ruinShareFactory = new RuinShareFactory() { ruinShareFactory = new RuinShareFactory() {
@ -141,8 +141,9 @@ public final class RuinRadial extends AbstractRuinStrategy {
Iterator<Job> neighborhoodIterator = jobNeighborhoods.getNearestNeighborsIterator(nNeighbors, targetJob); Iterator<Job> neighborhoodIterator = jobNeighborhoods.getNearestNeighborsIterator(nNeighbors, targetJob);
while(neighborhoodIterator.hasNext()){ while(neighborhoodIterator.hasNext()){
Job job = neighborhoodIterator.next(); Job job = neighborhoodIterator.next();
removeJob(job,vehicleRoutes); if(removeJob(job,vehicleRoutes)){
unassignedJobs.add(job); unassignedJobs.add(job);
}
} }
return unassignedJobs; return unassignedJobs;
} }

View file

@ -48,7 +48,7 @@ public final class RuinRadialMultipleCenters extends AbstractRuinStrategy {
private int noCenters = 1; private int noCenters = 1;
public RuinRadialMultipleCenters(VehicleRoutingProblem vrp, int neighborhoodSize, JobDistance jobDistance) { public RuinRadialMultipleCenters(VehicleRoutingProblem vrp, int neighborhoodSize, JobDistance jobDistance) {
super(); super(vrp);
this.vrp = vrp; this.vrp = vrp;
noJobsToMemorize = neighborhoodSize; noJobsToMemorize = neighborhoodSize;
ruinShareFactory = new RuinShareFactory() { ruinShareFactory = new RuinShareFactory() {
@ -116,8 +116,9 @@ public final class RuinRadialMultipleCenters extends AbstractRuinStrategy {
while(neighborhoodIterator.hasNext()){ while(neighborhoodIterator.hasNext()){
Job job = neighborhoodIterator.next(); Job job = neighborhoodIterator.next();
if(available!=null) available.remove(job); if(available!=null) available.remove(job);
removeJob(job,vehicleRoutes); if(removeJob(job,vehicleRoutes)) {
unassignedJobs.add(job); unassignedJobs.add(job);
}
} }
return unassignedJobs; return unassignedJobs;
} }

View file

@ -51,7 +51,7 @@ public final class RuinRandom extends AbstractRuinStrategy {
* @param fraction which is the fraction of total c * @param fraction which is the fraction of total c
*/ */
public RuinRandom(VehicleRoutingProblem vrp, double fraction) { public RuinRandom(VehicleRoutingProblem vrp, double fraction) {
super(); super(vrp);
this.vrp = vrp; this.vrp = vrp;
this.fractionOfAllNodes2beRuined = fraction; this.fractionOfAllNodes2beRuined = fraction;
setRuinShareFactory(new RuinShareFactory() { setRuinShareFactory(new RuinShareFactory() {
@ -96,9 +96,10 @@ public final class RuinRandom extends AbstractRuinStrategy {
for (int i = 0; i < nOfJobs2BeRemoved; i++) { for (int i = 0; i < nOfJobs2BeRemoved; i++) {
if(availableJobs.isEmpty()) break; if(availableJobs.isEmpty()) break;
Job job = pickRandomJob(availableJobs); Job job = pickRandomJob(availableJobs);
unassignedJobs.add(job); if(removeJob(job,vehicleRoutes)) {
availableJobs.remove(job); unassignedJobs.add(job);
removeJob(job,vehicleRoutes); availableJobs.remove(job);
}
} }
} }

View file

@ -56,7 +56,7 @@ public final class RuinWorst extends AbstractRuinStrategy {
} }
public RuinWorst(VehicleRoutingProblem vrp, final int initialNumberJobsToRemove) { public RuinWorst(VehicleRoutingProblem vrp, final int initialNumberJobsToRemove) {
super(); super(vrp);
this.vrp = vrp; this.vrp = vrp;
setRuinShareFactory(new RuinShareFactory() { setRuinShareFactory(new RuinShareFactory() {
@Override @Override
@ -95,9 +95,10 @@ public final class RuinWorst extends AbstractRuinStrategy {
while(toRemove > 0){ while(toRemove > 0){
Job worst = getWorst(vehicleRoutes); Job worst = getWorst(vehicleRoutes);
if(worst == null) break; if(worst == null) break;
removeJob(worst,vehicleRoutes); if(removeJob(worst,vehicleRoutes)) {
availableJobs.remove(worst); availableJobs.remove(worst);
unassignedJobs.add(worst); unassignedJobs.add(worst);
}
toRemove--; toRemove--;
} }
} }

View file

@ -19,6 +19,7 @@ package jsprit.core.algorithm;
import jsprit.core.algorithm.box.GreedySchrimpfFactory; import jsprit.core.algorithm.box.GreedySchrimpfFactory;
import jsprit.core.algorithm.box.Jsprit;
import jsprit.core.algorithm.box.SchrimpfFactory; import jsprit.core.algorithm.box.SchrimpfFactory;
import jsprit.core.problem.AbstractActivity; import jsprit.core.problem.AbstractActivity;
import jsprit.core.problem.Location; import jsprit.core.problem.Location;
@ -209,11 +210,40 @@ public class InitialRoutesTest {
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions(); Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions); VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions);
assertTrue(hasActivityIn(solution.getRoutes().iterator().next(),"1")); SolutionPrinter.print(vrp,solution, SolutionPrinter.Print.VERBOSE);
Job job = getInitialJob("1",vrp);
assertTrue(hasActivityIn(solution,"veh1", job));
}
private Job getInitialJob(String jobId, VehicleRoutingProblem vrp) {
for(VehicleRoute r : vrp.getInitialVehicleRoutes()){
for(Job j : r.getTourActivities().getJobs()){
if(j.getId().equals(jobId)) return j;
}
}
return null;
} }
@Test @Test
public void whenSolvingProblem2_deliverServices_and_allShipmentActs_shouldBeInRoute(){ public void whenSolvingWithJsprit_deliverService1_shouldBeInRoute(){
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(vrpBuilder).read("src/test/resources/simpleProblem_iniRoutes_3.xml");
VehicleRoutingProblem vrp = vrpBuilder.build();
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions);
SolutionPrinter.print(vrp,solution, SolutionPrinter.Print.VERBOSE);
Job job = getInitialJob("1",vrp);
assertTrue(hasActivityIn(solution,"veh1", job));
}
@Test
public void whenSolvingProblem2With_deliverServices_and_allShipmentActs_shouldBeInRoute(){
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(vrpBuilder).read("src/test/resources/simpleProblem_inclShipments_iniRoutes.xml"); new VrpXMLReader(vrpBuilder).read("src/test/resources/simpleProblem_inclShipments_iniRoutes.xml");
@ -227,6 +257,29 @@ public class InitialRoutesTest {
assertTrue(hasActivityIn(solution.getRoutes(),"2")); assertTrue(hasActivityIn(solution.getRoutes(),"2"));
assertTrue(hasActivityIn(solution.getRoutes(),"3")); assertTrue(hasActivityIn(solution.getRoutes(),"3"));
assertTrue(hasActivityIn(solution.getRoutes(),"4")); assertTrue(hasActivityIn(solution.getRoutes(),"4"));
assertTrue(hasActivityIn(solution,"veh1", getInitialJob("1",vrp)));
assertTrue(hasActivityIn(solution,"veh2", getInitialJob("3",vrp)));
}
@Test
public void whenSolvingProblem2WithJsprit_deliverServices_and_allShipmentActs_shouldBeInRoute(){
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(vrpBuilder).read("src/test/resources/simpleProblem_inclShipments_iniRoutes.xml");
VehicleRoutingProblem vrp = vrpBuilder.build();
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions);
assertTrue(hasActivityIn(solution.getRoutes(),"1"));
assertTrue(hasActivityIn(solution.getRoutes(),"2"));
assertTrue(hasActivityIn(solution.getRoutes(),"3"));
assertTrue(hasActivityIn(solution.getRoutes(),"4"));
assertTrue(hasActivityIn(solution,"veh1", getInitialJob("1",vrp)));
assertTrue(hasActivityIn(solution,"veh2", getInitialJob("3",vrp)));
} }
private boolean hasActivityIn(Collection<VehicleRoute> routes, String jobId) { private boolean hasActivityIn(Collection<VehicleRoute> routes, String jobId) {
@ -241,6 +294,19 @@ public class InitialRoutesTest {
return isInRoute; return isInRoute;
} }
private boolean hasActivityIn(VehicleRoutingProblemSolution solution, String vehicleId, Job job) {
for(VehicleRoute route : solution.getRoutes()){
String vehicleId_ = route.getVehicle().getId();
if(vehicleId_.equals(vehicleId)){
if(route.getTourActivities().servesJob(job)){
return true;
}
}
}
return false;
}
private boolean hasActivityIn(VehicleRoute route, String jobId){ private boolean hasActivityIn(VehicleRoute route, String jobId){
boolean isInRoute = false; boolean isInRoute = false;
for(TourActivity act : route.getActivities()){ for(TourActivity act : route.getActivities()){

View file

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<problem xmlns="http://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com vrp_xml_schema.xsd">
<problemType>
<fleetSize>FINITE</fleetSize>
<fleetComposition>HOMOGENEOUS</fleetComposition>
</problemType>
<vehicles>
<vehicle>
<id>veh1</id>
<typeId>type1</typeId>
<startLocation>
<id>[x=5000.0][y=5000.0]</id>
<coord x="5000.0" y="5000.0"/>
</startLocation>
<timeSchedule>
<start>0.0</start>
<end>46800.0</end>
</timeSchedule>
<returnToDepot>true</returnToDepot>
</vehicle>
<vehicle>
<id>veh2</id>
<typeId>type1</typeId>
<startLocation>
<id>[x=0.0][y=0.0]</id>
<coord x="0.0" y="0.0"/>
</startLocation>
<timeSchedule>
<start>0.0</start>
<end>64800.0</end>
</timeSchedule>
<returnToDepot>true</returnToDepot>
</vehicle>
</vehicles>
<vehicleTypes>
<type>
<id>type1</id>
<capacity-dimensions>
<dimension index="0">0</dimension>
</capacity-dimensions>
<costs>
<fixed>0.0</fixed>
<distance>1.0</distance>
<time>0.0</time>
</costs>
</type>
</vehicleTypes>
<services>
<service id="2" type="service">
<locationId>loc_s2</locationId>
<coord x="1000.0" y="0.0"/>
<capacity-dimensions>
<dimension index="0">0</dimension>
</capacity-dimensions>
<duration>0.0</duration>
</service>
<service id="1" type="service">
<locationId>loc_s3</locationId>
<coord x="1000.0" y="1000.0"/>
<capacity-dimensions>
<dimension index="0">0</dimension>
</capacity-dimensions>
<duration>0.0</duration>
</service>
</services>
<initialRoutes>
<route>
<driverId>noDriver</driverId>
<vehicleId>veh1</vehicleId>
<start>0.</start>
<act type="deliverService">
<serviceId>1</serviceId>
</act>
<end/>
</route>
</initialRoutes>
</problem>

View file

@ -14,7 +14,7 @@
<strategy> <strategy>
<memory>1</memory> <memory>1</memory>
<searchStrategies> <searchStrategies>
<searchStrategy name="radialRuinAndRecreate"> <searchStrategy name="random_best">
<selector name="selectBest"/> <selector name="selectBest"/>
<acceptor name="acceptNewRemoveWorst"/> <acceptor name="acceptNewRemoveWorst"/>
@ -30,7 +30,7 @@
<probability>0.2</probability> <probability>0.2</probability>
</searchStrategy> </searchStrategy>
<searchStrategy name="radialRuinAndRecreate"> <searchStrategy name="radial_best">
<selector name="selectBest"/> <selector name="selectBest"/>
<acceptor name="acceptNewRemoveWorst"/> <acceptor name="acceptNewRemoveWorst"/>
@ -46,7 +46,7 @@
<probability>0.2</probability> <probability>0.2</probability>
</searchStrategy> </searchStrategy>
<searchStrategy name="radialRuinAndRecreate"> <searchStrategy name="small_radial_best">
<selector name="selectBest"/> <selector name="selectBest"/>
<acceptor name="acceptNewRemoveWorst"/> <acceptor name="acceptNewRemoveWorst"/>
<modules> <modules>

View file

@ -76,6 +76,9 @@ public class MultipleDepotWithInitialRoutesExample {
/* /*
* solve the problem * solve the problem
*/ */
// VehicleRoutingAlgorithm vra = Jsprit.Builder.newInstance(vrp)
// .setProperty(Jsprit.Parameter.ITERATIONS,"10000").buildAlgorithm();
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_noVehicleSwitch.xml"); VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_noVehicleSwitch.xml");
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions(); Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();