mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
add new ruin strategy
This commit is contained in:
parent
a04aa2061a
commit
7450f476b6
1 changed files with 137 additions and 0 deletions
|
|
@ -0,0 +1,137 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (C) 2014 Stefan Schroeder
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* 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,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* 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/>.
|
||||
******************************************************************************/
|
||||
package jsprit.core.algorithm.ruin;
|
||||
|
||||
import jsprit.core.algorithm.ruin.distance.JobDistance;
|
||||
import jsprit.core.problem.VehicleRoutingProblem;
|
||||
import jsprit.core.problem.job.Job;
|
||||
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* RuinStrategy that ruins the neighborhood of a randomly selected job. The size and the structure of the neighborhood is defined by
|
||||
* the share of jobs to be removed and the distance between jobs (where distance not necessarily mean Euclidean distance but an arbitrary
|
||||
* measure).
|
||||
*
|
||||
* @author stefan
|
||||
*
|
||||
*/
|
||||
public final class RuinRadialMultipleCenters extends AbstractRuinStrategy {
|
||||
|
||||
private Logger logger = LogManager.getLogger(RuinRadialMultipleCenters.class);
|
||||
|
||||
private VehicleRoutingProblem vrp;
|
||||
|
||||
private JobNeighborhoods jobNeighborhoods;
|
||||
|
||||
private final int noJobsToMemorize;
|
||||
|
||||
private int noCenters = 1;
|
||||
|
||||
public RuinRadialMultipleCenters(VehicleRoutingProblem vrp, int neighborhoodSize, JobDistance jobDistance) {
|
||||
super();
|
||||
this.vrp = vrp;
|
||||
noJobsToMemorize = neighborhoodSize;
|
||||
ruinShareFactory = new RuinShareFactory() {
|
||||
|
||||
@Override
|
||||
public int createNumberToBeRemoved() {
|
||||
return noJobsToMemorize;
|
||||
}
|
||||
|
||||
};
|
||||
JobNeighborhoodsImplWithCapRestriction jobNeighborhoodsImpl = new JobNeighborhoodsImplWithCapRestriction(vrp, jobDistance, noJobsToMemorize);
|
||||
jobNeighborhoodsImpl.initialise();
|
||||
jobNeighborhoods = jobNeighborhoodsImpl;
|
||||
logger.info("initialise " + this);
|
||||
}
|
||||
|
||||
public void setNumberOfRuinCenters(int noCenters){
|
||||
this.noCenters = noCenters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=radialRuin][noJobsToBeRemoved="+noJobsToMemorize+"]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Ruins the collection of vehicleRoutes, i.e. removes a share of jobs. First, it selects a job randomly. Second, it identifies its neighborhood. And finally, it removes
|
||||
* the neighborhood plus the randomly selected job from the number of vehicleRoutes. All removed jobs are then returned as a collection.
|
||||
*/
|
||||
@Override
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes) {
|
||||
if(vehicleRoutes.isEmpty()){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Set<Job> available = new HashSet<Job>(vrp.getJobs().values());
|
||||
Collection<Job> ruined = new ArrayList<Job>();
|
||||
for(int center=0;center<noCenters;center++) {
|
||||
int nOfJobs2BeRemoved = ruinShareFactory.createNumberToBeRemoved();
|
||||
if (nOfJobs2BeRemoved == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Job randomJob = pickRandomJob(available);
|
||||
if(randomJob != null) {
|
||||
ruined.addAll(ruinRoutes_(vehicleRoutes, randomJob, nOfJobs2BeRemoved, available));
|
||||
}
|
||||
}
|
||||
return ruined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes targetJob and its neighborhood and returns the removed jobs.
|
||||
* @deprecated will be private
|
||||
*/
|
||||
@Deprecated
|
||||
public Collection<Job> ruinRoutes(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved){
|
||||
return ruinRoutes_(vehicleRoutes,targetJob,nOfJobs2BeRemoved,null);
|
||||
}
|
||||
|
||||
private Collection<Job> ruinRoutes_(Collection<VehicleRoute> vehicleRoutes, Job targetJob, int nOfJobs2BeRemoved, Set<Job> available){
|
||||
List<Job> unassignedJobs = new ArrayList<Job>();
|
||||
int nNeighbors = nOfJobs2BeRemoved - 1;
|
||||
removeJob(targetJob,vehicleRoutes);
|
||||
unassignedJobs.add(targetJob);
|
||||
Iterator<Job> neighborhoodIterator = jobNeighborhoods.getNearestNeighborsIterator(nNeighbors, targetJob);
|
||||
while(neighborhoodIterator.hasNext()){
|
||||
Job job = neighborhoodIterator.next();
|
||||
if(available!=null) available.remove(job);
|
||||
removeJob(job,vehicleRoutes);
|
||||
unassignedJobs.add(job);
|
||||
}
|
||||
return unassignedJobs;
|
||||
}
|
||||
|
||||
private Job pickRandomJob(Set<Job> available) {
|
||||
int randomIndex = random.nextInt(available.size());
|
||||
int i=0;
|
||||
for(Job j : available){
|
||||
if(i>=randomIndex) {
|
||||
return j;
|
||||
}
|
||||
else i++;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue