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

add infrastructure to simplify the creation of new ruin strategies

This commit is contained in:
oblonski 2014-11-22 12:36:09 +01:00
parent 369877e9fc
commit a32a750bed
2 changed files with 33 additions and 108 deletions

View file

@ -1,28 +1,25 @@
/******************************************************************************* /*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder * Copyright (C) 2014 Stefan Schroeder
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version. * version 3.0 of the License, or (at your option) any later version.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/ ******************************************************************************/
package jsprit.core.algorithm.ruin; package jsprit.core.algorithm.ruin;
import jsprit.core.algorithm.ruin.distance.JobDistance; import jsprit.core.algorithm.ruin.distance.JobDistance;
import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.algorithm.ruin.listener.RuinListeners;
import jsprit.core.problem.VehicleRoutingProblem; 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.StopWatch; import jsprit.core.util.StopWatch;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -39,7 +36,7 @@ import java.util.*;
* @author stefan * @author stefan
* *
*/ */
final class RuinRadial implements RuinStrategy { final class RuinRadial extends AbstractRuinStrategy {
static interface JobNeighborhoods { static interface JobNeighborhoods {
@ -255,15 +252,8 @@ final class RuinRadial implements RuinStrategy {
private double fractionOfAllNodes2beRuined; private double fractionOfAllNodes2beRuined;
private Random random = RandomNumberGeneration.getRandom();
private RuinListeners ruinListeners;
private JobNeighborhoods jobNeighborhoods; private JobNeighborhoods jobNeighborhoods;
public void setRandom(Random random) {
this.random = random;
}
/** /**
* Constructs RuinRadial. * Constructs RuinRadial.
@ -276,7 +266,6 @@ final class RuinRadial implements RuinStrategy {
super(); super();
this.vrp = vrp; this.vrp = vrp;
this.fractionOfAllNodes2beRuined = fraction2beRemoved; this.fractionOfAllNodes2beRuined = fraction2beRemoved;
ruinListeners = new RuinListeners();
int nJobsToMemorize = (int) Math.ceil(vrp.getJobs().values().size()*fraction2beRemoved); int nJobsToMemorize = (int) Math.ceil(vrp.getJobs().values().size()*fraction2beRemoved);
JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, nJobsToMemorize); JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, nJobsToMemorize);
jobNeighborhoodsImpl.initialise(); jobNeighborhoodsImpl.initialise();
@ -294,7 +283,7 @@ final class RuinRadial implements RuinStrategy {
* the neighborhood plus the randomly selected job from the number of vehicleRoutes. All removed jobs are then returned as a collection. * the neighborhood plus the randomly selected job from the number of vehicleRoutes. All removed jobs are then returned as a collection.
*/ */
@Override @Override
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes) { public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
if(vehicleRoutes.isEmpty()){ if(vehicleRoutes.isEmpty()){
return Collections.emptyList(); return Collections.emptyList();
} }
@ -303,16 +292,14 @@ final class RuinRadial implements RuinStrategy {
return Collections.emptyList(); return Collections.emptyList();
} }
Job randomJob = pickRandomJob(); Job randomJob = pickRandomJob();
Collection<Job> unassignedJobs = ruin(vehicleRoutes,randomJob,nOfJobs2BeRemoved); return ruin(vehicleRoutes,randomJob,nOfJobs2BeRemoved);
return unassignedJobs;
} }
/** /**
* Removes targetJob and its neighborhood and returns the removed jobs. * Removes targetJob and its neighborhood and returns the removed jobs.
*/ */
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){ public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){
ruinListeners.ruinStarts(vehicleRoutes); List<Job> unassignedJobs = new ArrayList<Job>();
List<Job> unassignedJobs = new ArrayList<Job>();
int nNeighbors = nOfJobs2BeRemoved - 1; int nNeighbors = nOfJobs2BeRemoved - 1;
removeJob(targetJob,vehicleRoutes); removeJob(targetJob,vehicleRoutes);
unassignedJobs.add(targetJob); unassignedJobs.add(targetJob);
@ -322,47 +309,19 @@ final class RuinRadial implements RuinStrategy {
removeJob(job,vehicleRoutes); removeJob(job,vehicleRoutes);
unassignedJobs.add(job); unassignedJobs.add(job);
} }
ruinListeners.ruinEnds(vehicleRoutes, unassignedJobs); return unassignedJobs;
return unassignedJobs;
}
private void removeJob(Job job, Collection<VehicleRoute> vehicleRoutes) {
boolean removed = false;
for (VehicleRoute route : vehicleRoutes) {
removed = route.getTourActivities().removeJob(job);;
if (removed) {
ruinListeners.removed(job,route);
break;
}
}
} }
private Job pickRandomJob() { private Job pickRandomJob() {
int totNuOfJobs = vrp.getJobs().values().size(); int totNuOfJobs = vrp.getJobs().values().size();
int randomIndex = random.nextInt(totNuOfJobs); int randomIndex = random.nextInt(totNuOfJobs);
Job job = new ArrayList<Job>(vrp.getJobs().values()).get(randomIndex); return new ArrayList<Job>(vrp.getJobs().values()).get(randomIndex);
return job; }
}
private int getNuOfJobs2BeRemoved() { private int getNuOfJobs2BeRemoved() {
return (int) Math.ceil(vrp.getJobs().values().size() return (int) Math.ceil(vrp.getJobs().values().size()
* fractionOfAllNodes2beRuined); * fractionOfAllNodes2beRuined);
} }
@Override
public void addListener(RuinListener ruinListener) {
ruinListeners.addListener(ruinListener);
}
@Override
public void removeListener(RuinListener ruinListener) {
ruinListeners.removeListener(ruinListener);
}
@Override
public Collection<RuinListener> getListeners() {
return ruinListeners.getListeners();
}
} }

View file

@ -1,31 +1,31 @@
/******************************************************************************* /*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder * Copyright (C) 2014 Stefan Schroeder
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version. * version 3.0 of the License, or (at your option) any later version.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>. * License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/ ******************************************************************************/
package jsprit.core.algorithm.ruin; package jsprit.core.algorithm.ruin;
import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.algorithm.ruin.listener.RuinListeners;
import jsprit.core.problem.VehicleRoutingProblem; 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 org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
/** /**
@ -36,7 +36,7 @@ import java.util.*;
* *
*/ */
final class RuinRandom implements RuinStrategy { final class RuinRandom extends AbstractRuinStrategy {
private Logger logger = LogManager.getLogger(RuinRandom.class); private Logger logger = LogManager.getLogger(RuinRandom.class);
@ -44,14 +44,6 @@ final class RuinRandom implements RuinStrategy {
private double fractionOfAllNodes2beRuined; private double fractionOfAllNodes2beRuined;
private Random random = RandomNumberGeneration.getRandom();
private RuinListeners ruinListeners;
public void setRandom(Random random) {
this.random = random;
}
/** /**
* Constructs ruinRandom. * Constructs ruinRandom.
* *
@ -62,8 +54,7 @@ final class RuinRandom implements RuinStrategy {
super(); super();
this.vrp = vrp; this.vrp = vrp;
this.fractionOfAllNodes2beRuined = fraction; this.fractionOfAllNodes2beRuined = fraction;
ruinListeners = new RuinListeners(); logger.info("initialise " + this);
logger.info("initialise " + this);
logger.info("done"); logger.info("done");
} }
@ -73,37 +64,32 @@ final class RuinRandom implements RuinStrategy {
* <p>The number of jobs is calculated as follows: Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined). * <p>The number of jobs is calculated as follows: Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined).
*/ */
@Override @Override
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes) { public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
ruinListeners.ruinStarts(vehicleRoutes); List<Job> unassignedJobs = new ArrayList<Job>();
List<Job> unassignedJobs = new ArrayList<Job>();
int nOfJobs2BeRemoved = selectNuOfJobs2BeRemoved(); int nOfJobs2BeRemoved = selectNuOfJobs2BeRemoved();
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs); ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
ruinListeners.ruinEnds(vehicleRoutes, unassignedJobs); return unassignedJobs;
return unassignedJobs;
} }
/** /**
* Removes nOfJobs2BeRemoved from vehicleRoutes, including targetJob. * Removes nOfJobs2BeRemoved from vehicleRoutes, including targetJob.
*/ */
@Override @Override
public Collection<Job> ruin(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) { public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved) {
ruinListeners.ruinStarts(vehicleRoutes); List<Job> unassignedJobs = new ArrayList<Job>();
List<Job> unassignedJobs = new ArrayList<Job>();
if(targetJob != null){ if(targetJob != null){
boolean removed = false; boolean removed = false;
for (VehicleRoute route : vehicleRoutes) { for (VehicleRoute route : vehicleRoutes) {
removed = route.getTourActivities().removeJob(targetJob); removed = removeJob(targetJob,route);
if (removed) { if (removed) {
nOfJobs2BeRemoved--; nOfJobs2BeRemoved--;
unassignedJobs.add(targetJob); unassignedJobs.add(targetJob);
ruinListeners.removed(targetJob,route);
break; break;
} }
} }
} }
ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs); ruin(vehicleRoutes, nOfJobs2BeRemoved, unassignedJobs);
ruinListeners.ruinEnds(vehicleRoutes, unassignedJobs); return unassignedJobs;
return unassignedJobs;
} }
public void setRuinFraction(double fractionOfAllNodes2beRuined) { public void setRuinFraction(double fractionOfAllNodes2beRuined) {
@ -117,13 +103,7 @@ final class RuinRandom implements RuinStrategy {
Job job = pickRandomJob(availableJobs); Job job = pickRandomJob(availableJobs);
unassignedJobs.add(job); unassignedJobs.add(job);
availableJobs.remove(job); availableJobs.remove(job);
for (VehicleRoute route : vehicleRoutes) { removeJob(job,vehicleRoutes);
boolean removed = route.getTourActivities().removeJob(job);
if (removed) {
ruinListeners.removed(job,route);
break;
}
}
} }
} }
@ -142,19 +122,5 @@ final class RuinRandom implements RuinStrategy {
return (int) Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined); return (int) Math.ceil(vrp.getJobs().values().size() * fractionOfAllNodes2beRuined);
} }
@Override
public void addListener(RuinListener ruinListener) {
ruinListeners.addListener(ruinListener);
}
@Override
public void removeListener(RuinListener ruinListener) {
ruinListeners.removeListener(ruinListener);
}
@Override
public Collection<RuinListener> getListeners() {
return ruinListeners.getListeners();
}
} }