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

Merge branch 'restructureAPIinPreparationForV0.1.1'

Conflicts:
	CHANGELOG.md
This commit is contained in:
Stefan Schroeder 2013-11-26 10:42:47 +01:00
commit a0ad012768
369 changed files with 75965 additions and 6728 deletions

View file

@ -1,72 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.ArrayList;
import java.util.Collection;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class BackwardInTimeListeners {
interface BackwardInTimeListener{
public void start(VehicleRoute route, End end, double latestArrivalTime);
public void prevActivity(TourActivity act, double latestDepartureTime, double latestOperationStartTime);
public void end(Start start, double latestDepartureTime);
}
private Collection<BackwardInTimeListener> listeners = new ArrayList<BackwardInTimeListener>();
public void addListener(BackwardInTimeListener l){
listeners.add(l);
}
public void start(VehicleRoute route, End end, double latestArrivalTime){
for(BackwardInTimeListener l : listeners){ l.start(route, end, latestArrivalTime); }
}
/**
* Informs listener about nextActivity.
*
* <p>LatestDepartureTime is the theoretical latest departureTime to meet the latestOperationStartTimeWindow at the nextActivity (forward in time), i.e.
* assume act_i and act_j are two successive activities and the latestDepTime of act_j is 10pm. With a travelTime from act_i to act_j of 1h the latestDepartureTime at act_i is 9pm.
* However, the latestOperationStartTime of act_i is 8pm, then (with a serviceTime of 0) the latestOperationStartTime at act_i amounts to 8pm.
*
* @param act
* @param latestDepartureTime
* @param latestArrivalTime
*/
public void prevActivity(TourActivity act, double latestDepartureTime, double latestArrivalTime){
for(BackwardInTimeListener l : listeners){ l.prevActivity(act,latestDepartureTime,latestArrivalTime); }
}
public void end(Start start, double latestDepartureTime){
for(BackwardInTimeListener l : listeners){ l.end(start, latestDepartureTime); }
}
public boolean isEmpty() {
return listeners.isEmpty();
}
}

View file

@ -1,198 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
//
//
///**
// *
// * @author stefan schroeder
// *
// */
//
//final class BestInsertionConcurrent implements InsertionStrategy{
//
// public static BestInsertionConcurrent newInstance(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads){
// return new BestInsertionConcurrent(routeAlgorithm, executor, nuOfThreads);
// }
//
// static class Batch {
// List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
//
// }
//
// private static Logger logger = Logger.getLogger(BestInsertionConcurrent.class);
//
// private Random random = RandomNumberGeneration.getRandom();
//
// private RouteAlgorithm routeAlgorithm;
//
//// private ExecutorService executor;
//
// private int nuOfBatches;
//
// private ExecutorCompletionService<Insertion> completionService;
//
// public void setRandom(Random random) {
// this.random = random;
// }
//
// private BestInsertionConcurrent(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads) {
// super();
// this.routeAlgorithm = routeAlgorithm;
//// this.executor = executor;
// logger.info("initialise " + this);
// this.nuOfBatches = nuOfThreads;
// completionService = new ExecutorCompletionService<Insertion>(executor);
// }
//
// @Override
// public String toString() {
// return "[name=concurrentBestInsertion]";
// }
//
// @Override
// public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
// List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
// Collections.shuffle(unassignedJobList, random);
//// informInsertionStarts(vehicleRoutes,unassignedJobs.size());
// int inserted = 0;
// for(final Job unassignedJob : unassignedJobList){
// VehicleRoute insertIn = null;
// Insertion bestInsertion = null;
// double bestInsertionCost = Double.MAX_VALUE;
//
// List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
//
// for(final Batch batch : batches){
// completionService.submit(new Callable<Insertion>() {
//
// @Override
// public Insertion call() throws Exception {
// return getBestInsertion(batch,unassignedJob);
// }
//
// });
//
// }
//
// try{
// for(int i=0;i<batches.size();i++){
// Future<Insertion> futureIData = completionService.take();
// Insertion insertion = futureIData.get();
// if(insertion == null) continue;
// if(insertion.getInsertionData().getInsertionCost() < bestInsertionCost){
// bestInsertion = insertion;
// bestInsertionCost = insertion.getInsertionData().getInsertionCost();
// }
// }
// }
// catch(InterruptedException e){
// Thread.currentThread().interrupt();
// }
// catch (ExecutionException e) {
// e.printStackTrace();
// logger.error(e.getCause().toString());
// System.exit(1);
// }
//
// if(bestInsertion != null){
//// informBeforeJobInsertion(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
// insertIn = bestInsertion.getRoute();
//// logger.debug("insert job="+unassignedJob+" at index=" + bestInsertion.getInsertionData().getInsertionIndex() + " delta cost=" + bestInsertion.getInsertionData().getInsertionCost());
// routeAlgorithm.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
// }
// else {
//// VehicleRoute newRoute = VehicleRoute.emptyRoute();
//// InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE);
//// if(bestI instanceof InsertionData.NoInsertionFound)
// throw new IllegalStateException("given the vehicles, could not create a valid solution.\n\tthe reason might be" +
// " inappropriate vehicle capacity.\n\tthe job that does not fit in any vehicle anymore is \n\t" + unassignedJob);
//// insertIn = newRoute;
//// informBeforeJobInsertion(unassignedJob,bestI,newRoute);
//// routeAlgorithm.insertJob(unassignedJob,bestI,newRoute);
//// vehicleRoutes.add(newRoute);
// }
// inserted++;
//// informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn);
// }
//// informInsertionEndsListeners(vehicleRoutes);
// }
//
// private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
// Insertion bestInsertion = null;
// double bestInsertionCost = Double.MAX_VALUE;
// for(VehicleRoute vehicleRoute : batch.routes){
// InsertionData iData = routeAlgorithm.calculateBestInsertion(vehicleRoute, unassignedJob, bestInsertionCost);
// if(iData instanceof NoInsertionFound) continue;
// if(iData.getInsertionCost() < bestInsertionCost){
// bestInsertion = new Insertion(vehicleRoute,iData);
// bestInsertionCost = iData.getInsertionCost();
// }
// }
// return bestInsertion;
// }
//
// private List<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
// List<Batch> batches = new ArrayList<Batch>();
// for(int i=0;i<nuOfBatches;i++) batches.add(new Batch());
// /*
// * if route.size < nuOfBatches add as much routes as empty batches are available
// * else add one empty route anyway
// */
//// if(vehicleRoutes.size()<nuOfBatches){
//// int nOfNewRoutes = nuOfBatches-vehicleRoutes.size();
//// for(int i=0;i<nOfNewRoutes;i++){
//// vehicleRoutes.add(VehicleRoute.emptyRoute());
//// }
//// }
//// else{
// vehicleRoutes.add(VehicleRoute.emptyRoute());
//// }
// /*
// * distribute routes to batches equally
// */
// int count = 0;
// for(VehicleRoute route : vehicleRoutes){
// if(count == nuOfBatches) count=0;
// batches.get(count).routes.add(route);
// count++;
// }
// return batches;
// }
//
//
// @Override
// public void removeListener(InsertionListener insertionListener) {
// // TODO Auto-generated method stub
//
// }
//
// @Override
// public Collection<InsertionListener> getListeners() {
// // TODO Auto-generated method stub
// return null;
// }
//
// @Override
// public void addListener(InsertionListener insertionListener) {
// // TODO Auto-generated method stub
//
// }
//
//}

View file

@ -1,97 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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/>.
******************************************************************************/
/* *********************************************************************** *
* project: org.matsim.*
* IniSolution.java
* *
* *********************************************************************** *
* *
* copyright : (C) 2011 by the members listed in the COPYING, *
* LICENSE and WARRANTY file. *
* email : info at matsim dot org *
* *
* *********************************************************************** *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* See also COPYING, LICENSE and WARRANTY file *
* *
* *********************************************************************** */
package algorithms;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.SolutionCostCalculator;
import basics.route.DriverImpl;
import basics.route.TourActivities;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
final class CreateInitialSolution implements InitialSolutionFactory {
private static final Logger logger = Logger.getLogger(CreateInitialSolution.class);
private final InsertionStrategy insertion;
private SolutionCostCalculator solutionCostCalculator;
private boolean generateAsMuchAsRoutesAsVehiclesExist = false;
public void setGenerateAsMuchAsRoutesAsVehiclesExist(boolean generateAsMuchAsRoutesAsVehiclesExist) {
this.generateAsMuchAsRoutesAsVehiclesExist = generateAsMuchAsRoutesAsVehiclesExist;
}
public CreateInitialSolution(InsertionStrategy insertionStrategy, SolutionCostCalculator solutionCostCalculator) {
super();
this.insertion = insertionStrategy;
this.solutionCostCalculator = solutionCostCalculator;
}
@Override
public VehicleRoutingProblemSolution createInitialSolution(final VehicleRoutingProblem vrp) {
logger.info("create initial solution.");
List<VehicleRoute> vehicleRoutes = new ArrayList<VehicleRoute>();
if(generateAsMuchAsRoutesAsVehiclesExist){
for(Vehicle vehicle : vrp.getVehicles()){
vehicleRoutes.add(VehicleRoute.newInstance(TourActivities.emptyTour(), DriverImpl.noDriver(), vehicle));
}
}
insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
// double totalCost = getTotalCost(vehicleRoutes);
logger.info("creation done");
VehicleRoutingProblemSolution vehicleRoutingProblemSolution = new VehicleRoutingProblemSolution(vehicleRoutes, 0.0);
solutionCostCalculator.calculateCosts(vehicleRoutingProblemSolution);
return vehicleRoutingProblemSolution;
}
private List<Job> getUnassignedJobs(VehicleRoutingProblem vrp) {
List<Job> jobs = new ArrayList<Job>(vrp.getJobs().values());
return jobs;
}
}

View file

@ -1,53 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import basics.Job;
import basics.algo.InsertionStartsListener;
import basics.route.VehicleRoute;
class FindCheaperVehicle implements InsertionStartsListener{
FindCheaperVehicleAlgo findCheaperVehicle;
public FindCheaperVehicle(FindCheaperVehicleAlgo findCheaperVehicle) {
super();
this.findCheaperVehicle = findCheaperVehicle;
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
List<VehicleRoute> newRoutes = new ArrayList<VehicleRoute>();
for(VehicleRoute route : vehicleRoutes){
if(route.isEmpty()) continue;
VehicleRoute cheaperRoute = findCheaperVehicle.runAndGetVehicleRoute(route);
newRoutes.add(cheaperRoute);
}
vehicleRoutes.clear();
vehicleRoutes.addAll(newRoutes);
}
@Override
public String toString() {
return "[name=findCheaperVehicle]";
}
}

View file

@ -1,109 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class FindCheaperVehicleAlgo {
private static Logger log = Logger.getLogger(FindCheaperVehicleAlgo.class);
private VehicleFleetManager fleetManager;
private VehicleRouteUpdater tourStateCalculator;
private AuxilliaryCostCalculator auxilliaryCostCalculator;
private double weightFixCosts = 1.0;
private StateManager states;
public void setWeightFixCosts(double weightFixCosts) {
this.weightFixCosts = weightFixCosts;
}
public void setStates(StateManager states) {
this.states = states;
}
public FindCheaperVehicleAlgo(VehicleFleetManager fleetManager, VehicleRouteUpdater tourStateCalculator, AuxilliaryCostCalculator auxilliaryCostCalculator) {
super();
this.fleetManager = fleetManager;
this.tourStateCalculator = tourStateCalculator;
this.auxilliaryCostCalculator = auxilliaryCostCalculator;
}
public VehicleRoute runAndGetVehicleRoute(VehicleRoute vehicleRoute) {
if(vehicleRoute.getVehicle() instanceof NoVehicle){
return vehicleRoute;
}
if(vehicleRoute.getTourActivities() == null || vehicleRoute.getVehicle() == null){
return vehicleRoute;
}
// Collection<TypeKey> availableVehicleTypes = fleetManager.getAvailableVehicleTypes(new TypeKey(vehicleRoute.getVehicle().getType(),vehicleRoute.getVehicle().getLocationId()));
double bestSaving = 0.0;
Vehicle bestVehicle = null;
List<TourActivity> path = new ArrayList<TourActivity>();
path.add(vehicleRoute.getStart());
path.addAll(vehicleRoute.getTourActivities().getActivities());
path.add(vehicleRoute.getEnd());
for(Vehicle vehicle : fleetManager.getAvailableVehicles(vehicleRoute.getVehicle().getType().getTypeId(), vehicleRoute.getVehicle().getLocationId())){
// Vehicle vehicle = fleetManager.getEmptyVehicle(vehicleType);
if(vehicle.getType().getTypeId().equals(vehicleRoute.getVehicle().getType().getTypeId())){
continue;
}
if(states.getRouteState(vehicleRoute,StateTypes.LOAD).toDouble() <= vehicle.getCapacity()){
double fixCostSaving = vehicleRoute.getVehicle().getType().getVehicleCostParams().fix - vehicle.getType().getVehicleCostParams().fix;
double departureTime = vehicleRoute.getStart().getEndTime();
double newCost = auxilliaryCostCalculator.costOfPath(path, departureTime, vehicleRoute.getDriver(), vehicle);
double varCostSaving = states.getRouteState(vehicleRoute, StateTypes.COSTS).toDouble() - newCost;
double totalCostSaving = varCostSaving + weightFixCosts*fixCostSaving;
if(totalCostSaving > bestSaving){
bestSaving = totalCostSaving;
bestVehicle = vehicle;
}
}
}
if(bestVehicle != null){
try{
fleetManager.unlock(vehicleRoute.getVehicle());
fleetManager.lock(bestVehicle);
}
catch(IllegalStateException e){
throw new IllegalStateException(e);
}
TourActivities newTour = TourActivities.copyOf(vehicleRoute.getTourActivities());
tourStateCalculator.iterate(vehicleRoute);
return VehicleRoute.newInstance(newTour,vehicleRoute.getDriver(),bestVehicle);
}
return vehicleRoute;
}
}

View file

@ -1,61 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.ArrayList;
import java.util.Collection;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class ForwardInTimeListeners {
interface ForwardInTimeListener{
public void start(VehicleRoute route, Start start, double departureTime);
public void nextActivity(TourActivity act, double arrTime,double endTime);
public void end(End end, double arrivalTime);
}
private Collection<ForwardInTimeListener> listeners = new ArrayList<ForwardInTimeListeners.ForwardInTimeListener>();
public void addListener(ForwardInTimeListener l){
listeners.add(l);
}
public void start(VehicleRoute route, Start start, double departureTime){
for(ForwardInTimeListener l : listeners){ l.start(route, start, departureTime); }
}
public void nextActivity(TourActivity act, double arrTime, double endTime){
for(ForwardInTimeListener l : listeners){ l.nextActivity(act,arrTime,endTime); }
}
public void end(End end, double arrivalTime){
for(ForwardInTimeListener l : listeners){ l.end(end, arrivalTime); }
}
public boolean isEmpty() {
return listeners.isEmpty();
}
}

View file

@ -1,218 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import org.apache.log4j.Logger;
import util.RandomNumberGeneration;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionListener;
import basics.algo.SearchStrategyModule;
import basics.algo.SearchStrategyModuleListener;
import basics.route.TourActivity;
import basics.route.TourActivity.JobActivity;
import basics.route.VehicleRoute;
final class Gendreau implements SearchStrategyModule{
private final static Logger log = Logger.getLogger(Gendreau.class);
private final static String NAME = "gendreauPostOpt";
private final RuinStrategy ruin;
private final VehicleRoutingProblem vrp;
private final InsertionStrategy insertionStrategy;
private VehicleFleetManager fleetManager;
private Random random = RandomNumberGeneration.getRandom();
private int nOfIterations = 10;
private double shareOfJobsToRuin = 0.15;
public void setShareOfJobsToRuin(double shareOfJobsToRuin) {
this.shareOfJobsToRuin = shareOfJobsToRuin;
}
public Gendreau(VehicleRoutingProblem vrp, RuinStrategy ruin, InsertionStrategy insertionStrategy) {
super();
InsertionListeners insertionListeners = new InsertionListeners();
insertionListeners.addAllListeners(insertionStrategy.getListeners());
new Inserter(insertionListeners);
this.ruin = ruin;
this.vrp = vrp;
this.insertionStrategy = insertionStrategy;
}
@Override
public String toString() {
return "[name=gendreau][iterations="+nOfIterations+"][share2ruin="+shareOfJobsToRuin+"]";
}
public void setRandom(Random random) {
this.random = random;
}
public void setNuOfIterations(int nOfIterations) {
this.nOfIterations = nOfIterations;
}
public void setFleetManager(VehicleFleetManager vehicleFleetManager) {
this.fleetManager = vehicleFleetManager;
}
@Override
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
// log.info("run gendreau postopt");
VehicleRoutingProblemSolution bestSolution = vrpSolution;
int itersWithoutImprovement = 0;
for(int i=0;i<nOfIterations;i++){
List<VehicleRoute> copiedRoutes = copyRoutes(bestSolution.getRoutes());
iniFleet(copiedRoutes);
VehicleRoute route2split = pickRouteThatHasAtLeastTwoJobs(copiedRoutes);
if(route2split == null) continue;
List<Job> jobsInRoute = getJobs(route2split);
Set<Job> unassignedJobs = new HashSet<Job>();
unassignedJobs.addAll(jobsInRoute);
copiedRoutes.remove(route2split);
Collections.shuffle(jobsInRoute,random);
Job targetJob = jobsInRoute.get(0);
int nOfJobs2BeRemovedAdditionally = (int) (shareOfJobsToRuin*(double)vrp.getJobs().size());
Collection<Job> unassignedJobsList = ruin.ruin(copiedRoutes, targetJob, nOfJobs2BeRemovedAdditionally);
unassignedJobs.addAll(unassignedJobsList);
VehicleRoute emptyRoute1 = VehicleRoute.emptyRoute();
copiedRoutes.add(emptyRoute1);
insertionStrategy.insertJobs(Arrays.asList(emptyRoute1), Arrays.asList(targetJob));
// routeAlgorithm.insertJob(targetJob, routeAlgorithm.calculateBestInsertion(emptyRoute1, targetJob, Double.MAX_VALUE), emptyRoute1);
unassignedJobs.remove(targetJob);
VehicleRoute emptyRoute2 = VehicleRoute.emptyRoute();
copiedRoutes.add(emptyRoute2);
Job job2 = jobsInRoute.get(1);
insertionStrategy.insertJobs(Arrays.asList(emptyRoute2), Arrays.asList(job2));
// routeAlgorithm.insertJob(job2, routeAlgorithm.calculateBestInsertion(emptyRoute2, job2, Double.MAX_VALUE), emptyRoute2);
unassignedJobs.remove(job2);
insertionStrategy.insertJobs(copiedRoutes, unassignedJobs);
double cost = getCost(copiedRoutes);
if(cost < bestSolution.getCost()){
// log.info("BING - new: " + cost + " old: " + bestSolution.getCost());
bestSolution = new VehicleRoutingProblemSolution(copiedRoutes, cost);
itersWithoutImprovement=0;
}
else{
itersWithoutImprovement++;
if(itersWithoutImprovement > 200){
// log.info("BREAK i="+i);
break;
}
}
}
return bestSolution;
}
private List<VehicleRoute> copyRoutes(Collection<VehicleRoute> routes) {
List<VehicleRoute> routeList = new ArrayList<VehicleRoute>();
for(VehicleRoute r : routes){
routeList.add(VehicleRoute.copyOf(r));
}
return routeList;
}
private void iniFleet(Collection<VehicleRoute> routes) {
fleetManager.unlockAll();
for(VehicleRoute route : routes){
if(!route.isEmpty()){
fleetManager.lock(route.getVehicle());
}
}
}
private double getCost(Collection<VehicleRoute> routes) {
double c = 0.0;
for(VehicleRoute r : routes){
c+=r.getCost();
}
return c;
}
private List<Job> getJobs(VehicleRoute route2split) {
Set<Job> jobs = new HashSet<Job>();
for(TourActivity act : route2split.getTourActivities().getActivities()){
if(act instanceof JobActivity){
jobs.add(((JobActivity) act).getJob());
}
}
return new ArrayList<Job>(jobs);
}
private VehicleRoute pickRouteThatHasAtLeastTwoJobs(Collection<VehicleRoute> routeList) {
List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
for(VehicleRoute r : routeList){
if(getJobs(r).size() > 1){
routes.add(r);
}
}
if(routes.isEmpty()) return null;
Collections.shuffle(routes,random);
return routes.get(0);
}
@Override
public String getName() {
return NAME;
}
@Override
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
if(moduleListener instanceof InsertionListener){
InsertionListener iListener = (InsertionListener) moduleListener;
if(!insertionStrategy.getListeners().contains(iListener)){
insertionStrategy.addListener(iListener);
}
}
if(moduleListener instanceof RuinListener){
RuinListener rListener = (RuinListener) moduleListener;
if(!ruin.getListeners().contains(rListener)){
ruin.addListener(rListener);
}
}
}
}

View file

@ -1,307 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import basics.Delivery;
import basics.Pickup;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DeliveryActivity;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TourActivity;
/**
* collection of hard constrainters bot at activity and at route level.
*
* <p>HardPickupAndDeliveryLoadConstraint requires LOAD_AT_DEPOT and LOAD (i.e. load at end) at route-level
*
* <p>HardTimeWindowConstraint requires LATEST_OPERATION_START_TIME
*
* <p>HardPickupAndDeliveryConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level
*
* <p>HardPickupAndDeliveryBackhaulConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level
*
* @author stefan
*
*/
class HardConstraints {
interface HardRouteLevelConstraint {
public boolean fulfilled(InsertionContext insertionContext);
}
interface HardActivityLevelConstraint {
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime);
}
static class HardRouteLevelConstraintManager implements HardRouteLevelConstraint {
private Collection<HardRouteLevelConstraint> hardConstraints = new ArrayList<HardRouteLevelConstraint>();
public void addConstraint(HardRouteLevelConstraint constraint){
hardConstraints.add(constraint);
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
for(HardRouteLevelConstraint constraint : hardConstraints){
if(!constraint.fulfilled(insertionContext)){
return false;
}
}
return true;
}
}
static class ConstraintManager implements HardActivityLevelConstraint, HardRouteLevelConstraint{
private HardActivityLevelConstraintManager actLevelConstraintManager = new HardActivityLevelConstraintManager();
private HardRouteLevelConstraintManager routeLevelConstraintManager = new HardRouteLevelConstraintManager();
public void addConstraint(HardActivityLevelConstraint actLevelConstraint){
actLevelConstraintManager.addConstraint(actLevelConstraint);
}
public void addConstraint(HardRouteLevelConstraint routeLevelConstraint){
routeLevelConstraintManager.addConstraint(routeLevelConstraint);
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
return routeLevelConstraintManager.fulfilled(insertionContext);
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
return actLevelConstraintManager.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
}
}
static class HardActivityLevelConstraintManager implements HardActivityLevelConstraint {
private Collection<HardActivityLevelConstraint> hardConstraints = new ArrayList<HardActivityLevelConstraint>();
public void addConstraint(HardActivityLevelConstraint constraint){
hardConstraints.add(constraint);
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
for(HardActivityLevelConstraint constraint : hardConstraints){
if(!constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime)){
return false;
}
}
return true;
}
}
static class HardLoadConstraint implements HardRouteLevelConstraint{
private StateManager states;
public HardLoadConstraint(StateManager states) {
super();
this.states = states;
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
int currentLoad = (int) states.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble();
Service service = (Service) insertionContext.getJob();
if(currentLoad + service.getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
return false;
}
return true;
}
}
/**
* lsjdfjsdlfjsa
*
* @author stefan
*
*/
static class HardPickupAndDeliveryLoadConstraint implements HardRouteLevelConstraint {
private StateManager stateManager;
public HardPickupAndDeliveryLoadConstraint(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
if(insertionContext.getJob() instanceof Delivery){
int loadAtDepot = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
if(loadAtDepot + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
return false;
}
}
else if(insertionContext.getJob() instanceof Pickup || insertionContext.getJob() instanceof Service){
int loadAtEnd = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble();
if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}
/**
* ljsljslfjs
* @author stefan
*
*/
public static class HardTimeWindowActivityLevelConstraint implements HardActivityLevelConstraint {
private static Logger log = Logger.getLogger(HardTimeWindowActivityLevelConstraint.class);
private StateManager states;
private VehicleRoutingTransportCosts routingCosts;
public HardTimeWindowActivityLevelConstraint(StateManager states, VehicleRoutingTransportCosts routingCosts) {
super();
this.states = states;
this.routingCosts = routingCosts;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
// log.info("check insertion of " + newAct + " between " + prevAct + " and " + nextAct + ". prevActDepTime=" + prevActDepTime);
double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double latestArrTimeAtNewAct = states.getActivityState(newAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
if(arrTimeAtNewAct > latestArrTimeAtNewAct){
return false;
}
// log.info(newAct + " arrTime=" + arrTimeAtNewAct);
double endTimeAtNewAct = CalcUtils.getActivityEndTime(arrTimeAtNewAct, newAct);
double arrTimeAtNextAct = endTimeAtNewAct + routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), endTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double latestArrTimeAtNextAct = states.getActivityState(nextAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
if(arrTimeAtNextAct > latestArrTimeAtNextAct){
return false;
}
// log.info(nextAct + " arrTime=" + arrTimeAtNextAct);
return true;
}
}
static class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelConstraint {
private StateManager stateManager;
public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
int loadAtPrevAct;
int futurePicks;
int pastDeliveries;
if(prevAct instanceof Start){
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
pastDeliveries = 0;
}
else{
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble();
futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble();
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble();
}
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
if(newAct instanceof DeliveryActivity){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}
static class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivityLevelConstraint {
private StateManager stateManager;
public HardPickupAndDeliveryBackhaulActivityLevelConstraint(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(newAct instanceof PickupActivity && nextAct instanceof DeliveryActivity){ return false; }
if(newAct instanceof ServiceActivity && nextAct instanceof DeliveryActivity){ return false; }
if(newAct instanceof DeliveryActivity && prevAct instanceof PickupActivity){ return false; }
if(newAct instanceof DeliveryActivity && prevAct instanceof ServiceActivity){ return false; }
int loadAtPrevAct;
int futurePicks;
int pastDeliveries;
if(prevAct instanceof Start){
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
pastDeliveries = 0;
}
else{
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble();
futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble();
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble();
}
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
if(newAct instanceof DeliveryActivity){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}
}

View file

@ -1,56 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.Service;
import basics.route.DefaultTourActivityFactory;
import basics.route.TourActivityFactory;
import basics.route.VehicleRoute;
class Inserter {
private InsertionListeners insertionListeners;
private TourActivityFactory activityFactory;
public Inserter(InsertionListeners insertionListeners) {
this.insertionListeners = insertionListeners;
activityFactory = new DefaultTourActivityFactory();
}
public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute){
insertionListeners.informBeforeJobInsertion(job, insertionData, vehicleRoute);
if(insertionData == null || (insertionData instanceof NoInsertionFound)) throw new IllegalStateException("insertionData null. cannot insert job.");
if(job == null) throw new IllegalStateException("cannot insert null-job");
if(!(vehicleRoute.getVehicle().getId().toString().equals(insertionData.getSelectedVehicle().getId().toString()))){
insertionListeners.informVehicleSwitched(vehicleRoute, vehicleRoute.getVehicle(), insertionData.getSelectedVehicle());
vehicleRoute.setVehicle(insertionData.getSelectedVehicle(), insertionData.getVehicleDepartureTime());
}
// if(vehicleRoute.getDepartureTime() != vehicleRoute.g)
if(job instanceof Service) {
vehicleRoute.getTourActivities().addActivity(insertionData.getDeliveryInsertionIndex(), activityFactory.createActivity((Service)job));
vehicleRoute.setDepartureTime(insertionData.getVehicleDepartureTime());
}
else throw new IllegalStateException("neither service nor shipment. this is not supported.");
insertionListeners.informJobInserted(job, vehicleRoute, insertionData.getInsertionCost(), insertionData.getAdditionalTime());
// updateTour(vehicleRoute);
}
}

View file

@ -1,82 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.Iterator;
import org.apache.log4j.Logger;
import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
import basics.costs.BackwardTransportTime;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
/**
*
* @author stefan schroeder
*
*/
class IterateRouteBackwardInTime implements VehicleRouteUpdater{
private static Logger log = Logger.getLogger(IterateRouteBackwardInTime.class);
private BackwardTransportTime transportTime;
private BackwardInTimeListeners listeners;
public IterateRouteBackwardInTime(BackwardTransportTime transportTime) {
super();
this.transportTime = transportTime;
listeners = new BackwardInTimeListeners();
}
/*
*
*/
public void iterate(VehicleRoute vehicleRoute) {
if(listeners.isEmpty()) return;
if(vehicleRoute.isEmpty()) return;
listeners.start(vehicleRoute, vehicleRoute.getEnd(), vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime());
Iterator<TourActivity> reverseActIter = vehicleRoute.getTourActivities().reverseActivityIterator();
TourActivity prevAct;
prevAct = vehicleRoute.getEnd();
double latestArrivalTimeAtPrevAct = prevAct.getTheoreticalLatestOperationStartTime();
while(reverseActIter.hasNext()){
TourActivity currAct = reverseActIter.next();
double latestDepTimeAtCurrAct = latestArrivalTimeAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), latestArrivalTimeAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
double potentialLatestArrivalTimeAtCurrAct = latestDepTimeAtCurrAct - currAct.getOperationTime();
double latestArrivalTime = Math.min(currAct.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct);
listeners.prevActivity(currAct, latestDepTimeAtCurrAct, latestArrivalTime);
prevAct = currAct;
latestArrivalTimeAtPrevAct = latestArrivalTime;
}
TourActivity currAct = vehicleRoute.getStart();
double latestDepTimeAtCurrAct = latestArrivalTimeAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), latestArrivalTimeAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
listeners.end(vehicleRoute.getStart(), latestDepTimeAtCurrAct);
}
public void addListener(BackwardInTimeListener l){ listeners.addListener(l); }
}

View file

@ -1,87 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import org.apache.log4j.Logger;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import basics.costs.ForwardTransportTime;
import basics.route.Driver;
import basics.route.End;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
/**
*
* @author sschroeder
*
*/
class IterateRouteForwardInTime implements VehicleRouteUpdater{
private static Logger log = Logger.getLogger(IterateRouteForwardInTime.class);
private ForwardTransportTime transportTime;
private ForwardInTimeListeners listeners;
public IterateRouteForwardInTime(ForwardTransportTime transportTime) {
super();
this.transportTime = transportTime;
listeners = new ForwardInTimeListeners();
}
/**
*
*
*/
public void iterate(VehicleRoute vehicleRoute) {
if(listeners.isEmpty()) return;
if(vehicleRoute.isEmpty()) return;
listeners.start(vehicleRoute, vehicleRoute.getStart(), vehicleRoute.getStart().getEndTime());
Vehicle vehicle = vehicleRoute.getVehicle();
Driver driver = vehicleRoute.getDriver();
TourActivity prevAct = vehicleRoute.getStart();
double startAtPrevAct = prevAct.getEndTime();
for(TourActivity currentAct : vehicleRoute.getTourActivities().getActivities()){
double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
double operationStartTime = Math.max(currentAct.getTheoreticalEarliestOperationStartTime(), arrivalTimeAtCurrAct);
double operationEndTime = operationStartTime + currentAct.getOperationTime();
listeners.nextActivity(currentAct,arrivalTimeAtCurrAct,operationEndTime);
prevAct = currentAct;
startAtPrevAct = operationEndTime;
}
End currentAct = vehicleRoute.getEnd();
double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
listeners.end(vehicleRoute.getEnd(), arrivalTimeAtCurrAct);
}
public void addListener(ForwardInTimeListener l){
listeners.addListener(l);
}
}

View file

@ -1,57 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import util.CrowFlyCosts;
import util.Locations;
import basics.Job;
import basics.Service;
class JobDistanceBeeline implements JobDistance {
private Locations locations;
public JobDistanceBeeline(Locations locations) {
super();
this.locations = locations;
}
@Override
public double calculateDistance(Job i, Job j) {
double avgCost = 0.0;
if (i instanceof Service && j instanceof Service) {
if (i.equals(j)) {
avgCost = 0.0;
} else {
Service s_i = (Service) i;
Service s_j = (Service) j;
avgCost = calcDist(s_i.getLocationId(), s_j.getLocationId());
}
} else {
throw new UnsupportedOperationException(
"currently, this class just works with shipments and services.");
}
return avgCost;
}
private double calcDist(String from, String to) {
return new CrowFlyCosts(locations).getTransportCost(from, to, 0.0,null, null);
}
}

View file

@ -1,54 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.route.VehicleRoute;
class RuinListeners {
private Collection<RuinListener> ruinListeners = new ArrayList<RuinListener>();
void ruinStarts(Collection<VehicleRoute> routes){
for(RuinListener l : ruinListeners) l.ruinStarts(routes);
}
void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs){
for(RuinListener l : ruinListeners) l.ruinEnds(routes, unassignedJobs);
}
void removed(Job job, VehicleRoute fromRoute){
for(RuinListener l : ruinListeners) l.removed(job, fromRoute);
}
void addListener(RuinListener ruinListener){
ruinListeners.add(ruinListener);
}
void removeListener(RuinListener ruinListener){
ruinListeners.remove(ruinListener);
}
Collection<RuinListener> getListeners(){
return Collections.unmodifiableCollection(ruinListeners);
}
}

View file

@ -1,59 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import basics.Job;
import basics.route.VehicleRoute;
class ScoredJob {
private final Job job;
private final double score;
private final InsertionData insertionData;
private final VehicleRoute route;
public ScoredJob(final Job job, final double score, final InsertionData insertionData, final VehicleRoute route) {
super();
this.job = job;
this.score = score;
this.insertionData = insertionData;
this.route = route;
}
public InsertionData getInsertionData() {
return insertionData;
}
public VehicleRoute getRoute() {
return route;
}
public Job getJob() {
return job;
}
public double getScore() {
return score;
}
}

View file

@ -1,53 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
interface StateManager {
interface State {
double toDouble();
}
class StateImpl implements State{
double state;
public StateImpl(double state) {
super();
this.state = state;
}
@Override
public double toDouble() {
return state;
}
}
interface States {
State getState(String key);
}
State getActivityState(TourActivity act, String stateType);
State getRouteState(VehicleRoute route, String stateType);
}

View file

@ -1,151 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import basics.Job;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class StateManagerImpl implements StateManager, InsertionStartsListener, JobInsertedListener {
static class StatesImpl implements States{
private Map<String,State> states = new HashMap<String, State>();
public void putState(String key, State state) {
states.put(key, state);
}
@Override
public State getState(String key) {
return states.get(key);
}
}
private Map<VehicleRoute,States> vehicleRouteStates = new HashMap<VehicleRoute, StateManager.States>();
private Map<TourActivity,States> activityStates = new HashMap<TourActivity, StateManager.States>();
private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor();
private ReverseRouteActivityVisitor revRouteActivityVisitor = new ReverseRouteActivityVisitor();
private Collection<RouteVisitor> routeVisitors = new ArrayList<RouteVisitor>();
public void clear(){
vehicleRouteStates.clear();
activityStates.clear();
}
@Override
public State getActivityState(TourActivity act, String stateType) {
if(!activityStates.containsKey(act)){
return getDefaultActState(stateType,act);
}
StatesImpl actStates = (StatesImpl) activityStates.get(act);
State state = actStates.getState(stateType);
if(state == null){
return getDefaultActState(stateType,act);
}
return state;
}
public void putActivityState(TourActivity act, String stateType, State state){
if(!activityStates.containsKey(act)){
activityStates.put(act, new StatesImpl());
}
StatesImpl actStates = (StatesImpl) activityStates.get(act);
actStates.putState(stateType, state);
}
private State getDefaultActState(String stateType, TourActivity act){
if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0);
if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0);
if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0);
if(stateType.equals(StateTypes.EARLIEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalEarliestOperationStartTime());
if(stateType.equals(StateTypes.LATEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalLatestOperationStartTime());
if(stateType.equals(StateTypes.FUTURE_PICKS)) return new StateImpl(0);
if(stateType.equals(StateTypes.PAST_DELIVERIES)) return new StateImpl(0);
return null;
}
private State getDefaultRouteState(String stateType, VehicleRoute route){
if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0);
if(stateType.equals(StateTypes.LOAD_AT_DEPOT)) return new StateImpl(0);
if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0);
if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0);
return null;
}
@Override
public State getRouteState(VehicleRoute route, String stateType) {
if(!vehicleRouteStates.containsKey(route)){
return getDefaultRouteState(stateType,route);
}
StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route);
State state = routeStates.getState(stateType);
if(state == null){
return getDefaultRouteState(stateType, route);
}
return state;
}
public void putRouteState(VehicleRoute route, String stateType, State state){
if(!vehicleRouteStates.containsKey(route)){
vehicleRouteStates.put(route, new StatesImpl());
}
StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route);
routeStates.putState(stateType, state);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
for(RouteVisitor v : routeVisitors){ v.visit(inRoute); }
routeActivityVisitor.visit(inRoute);
revRouteActivityVisitor.visit(inRoute);
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes,Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
for(RouteVisitor v : routeVisitors){ v.visit(route); }
routeActivityVisitor.visit(route);
revRouteActivityVisitor.visit(route);
}
}
public void addActivityVisitor(ActivityVisitor activityVistor){
routeActivityVisitor.addActivityVisitor(activityVistor);
}
public void addActivityVisitor(ReverseActivityVisitor activityVistor){
revRouteActivityVisitor.addActivityVisitor(activityVistor);
}
public void addRouteVisitor(RouteVisitor routeVisitor){
routeVisitors.add(routeVisitor);
}
}

View file

@ -1,40 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
class StateTypes {
// final static StateId LOAD = new StateIdImpl("load");
final static String LOAD = "load";
final static String LOAD_AT_DEPOT = "loadAtDepot";
final static String DURATION = "duration";
final static String LATEST_OPERATION_START_TIME = "latestOST";
final static String EARLIEST_OPERATION_START_TIME = "earliestOST";
static final String COSTS = "costs";
final static String FUTURE_PICKS = "futurePicks";
final static String PAST_DELIVERIES = "pastDeliveries";
}

View file

@ -1,633 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import algorithms.RuinStrategy.RuinListener;
import algorithms.StateManager.StateImpl;
import basics.Delivery;
import basics.Job;
import basics.Pickup;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionEndsListener;
import basics.algo.InsertionStartsListener;
import basics.algo.IterationStartsListener;
import basics.algo.JobInsertedListener;
import basics.costs.ForwardTransportCost;
import basics.costs.ForwardTransportTime;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DeliveryActivity;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.VehicleType;
class StateUpdates {
static class UpdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{
private StateManagerImpl states;
private VehicleRoutingTransportCosts tpCosts;
private VehicleRoutingActivityCosts actCosts;
public UpdateCostsAtRouteLevel(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts, VehicleRoutingActivityCosts actCosts) {
super();
this.states = states;
this.tpCosts = tpCosts;
this.actCosts = actCosts;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
// inRoute.getVehicleRouteCostCalculator().addTransportCost(additionalCosts);
double oldCosts = states.getRouteState(inRoute, StateTypes.COSTS).toDouble();
oldCosts += additionalCosts;
states.putRouteState(inRoute, StateTypes.COSTS, new StateImpl(oldCosts));
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
RouteActivityVisitor forwardInTime = new RouteActivityVisitor();
forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
for(VehicleRoute route : vehicleRoutes){
forwardInTime.visit(route);
}
}
@Override
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
// IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
// forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
// for(VehicleRoute route : vehicleRoutes){
// if(route.isEmpty()) continue;
// route.getVehicleRouteCostCalculator().reset();
// route.getVehicleRouteCostCalculator().addOtherCost(states.getRouteState(route, StateTypes.COSTS).toDouble());
// route.getVehicleRouteCostCalculator().price(route.getVehicle());
// forwardInTime.iterate(route);
// }
}
}
static class UpdateActivityTimes implements ActivityVisitor{
private Logger log = Logger.getLogger(UpdateActivityTimes.class);
private ActivityTimeTracker timeTracker;
private VehicleRoute route;
public UpdateActivityTimes(ForwardTransportTime transportTime) {
super();
timeTracker = new ActivityTimeTracker(transportTime);
}
@Override
public void begin(VehicleRoute route) {
timeTracker.begin(route);
this.route = route;
route.getStart().setEndTime(timeTracker.getActEndTime());
}
@Override
public void visit(TourActivity activity) {
timeTracker.visit(activity);
activity.setArrTime(timeTracker.getActArrTime());
activity.setEndTime(timeTracker.getActEndTime());
}
@Override
public void finish() {
timeTracker.finish();
route.getEnd().setArrTime(timeTracker.getActArrTime());
}
}
static class UpdateCostsAtAllLevels implements ActivityVisitor{
private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class);
private VehicleRoutingActivityCosts activityCost;
private ForwardTransportCost transportCost;
private StateManagerImpl states;
private double totalOperationCost = 0.0;
private VehicleRoute vehicleRoute = null;
private TourActivity prevAct = null;
private double startTimeAtPrevAct = 0.0;
private ActivityTimeTracker timeTracker;
public UpdateCostsAtAllLevels(VehicleRoutingActivityCosts activityCost, VehicleRoutingTransportCosts transportCost, StateManagerImpl states) {
super();
this.activityCost = activityCost;
this.transportCost = transportCost;
this.states = states;
timeTracker = new ActivityTimeTracker(transportCost);
}
@Override
public void begin(VehicleRoute route) {
vehicleRoute = route;
vehicleRoute.getVehicleRouteCostCalculator().reset();
timeTracker.begin(route);
prevAct = route.getStart();
startTimeAtPrevAct = timeTracker.getActEndTime();
}
@Override
public void visit(TourActivity act) {
timeTracker.visit(act);
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(act, timeTracker.getActArrTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
totalOperationCost += transportCost;
totalOperationCost += actCost;
states.putActivityState(act, StateTypes.COSTS, new StateImpl(totalOperationCost));
prevAct = act;
startTimeAtPrevAct = timeTracker.getActEndTime();
}
@Override
public void finish() {
timeTracker.finish();
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), vehicleRoute.getEnd().getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(vehicleRoute.getEnd(), timeTracker.getActEndTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
totalOperationCost += transportCost;
totalOperationCost += actCost;
// totalOperationCost += getFixCosts();
states.putRouteState(vehicleRoute, StateTypes.COSTS, new StateImpl(totalOperationCost));
// this is rather strange and likely to change
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().finish();
startTimeAtPrevAct = 0.0;
prevAct = null;
vehicleRoute = null;
totalOperationCost = 0.0;
}
private double getFixCosts() {
Vehicle vehicle = vehicleRoute.getVehicle();
if(vehicle == null) return 0.0;
VehicleType type = vehicle.getType();
if(type == null) return 0.0;
return type.getVehicleCostParams().fix;
}
}
static class UpdateEarliestStartTimeWindowAtActLocations implements ActivityVisitor{
private StateManagerImpl states;
private ActivityTimeTracker timeTracker;
public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts transportCosts) {
super();
this.states = states;
timeTracker = new ActivityTimeTracker(transportCosts);
}
@Override
public void begin(VehicleRoute route) {
timeTracker.begin(route);
}
@Override
public void visit(TourActivity activity) {
timeTracker.visit(activity);
states.putActivityState(activity, StateTypes.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(timeTracker.getActArrTime(), activity.getTheoreticalEarliestOperationStartTime())));
}
@Override
public void finish() {}
}
static class UpdateLatestOperationStartTimeAtActLocations implements ReverseActivityVisitor{
private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class);
private StateManagerImpl states;
private VehicleRoute route;
private VehicleRoutingTransportCosts transportCosts;
private double latestArrTimeAtPrevAct;
private TourActivity prevAct;
public UpdateLatestOperationStartTimeAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts) {
super();
this.states = states;
this.transportCosts = tpCosts;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
latestArrTimeAtPrevAct = route.getEnd().getTheoreticalLatestOperationStartTime();
prevAct = route.getEnd();
}
@Override
public void visit(TourActivity activity) {
double potentialLatestArrivalTimeAtCurrAct = latestArrTimeAtPrevAct - transportCosts.getBackwardTransportTime(activity.getLocationId(), prevAct.getLocationId(), latestArrTimeAtPrevAct, route.getDriver(),route.getVehicle()) - activity.getOperationTime();
double latestArrivalTime = Math.min(activity.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct);
states.putActivityState(activity, StateTypes.LATEST_OPERATION_START_TIME, new StateImpl(latestArrivalTime));
latestArrTimeAtPrevAct = latestArrivalTime;
prevAct = activity;
}
@Override
public void finish() {}
}
static class UpdateLoadAtAllLevels implements ActivityVisitor{
private double load = 0.0;
private StateManagerImpl states;
private VehicleRoute vehicleRoute;
public UpdateLoadAtAllLevels(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void begin(VehicleRoute route) {
vehicleRoute = route;
}
@Override
public void visit(TourActivity activity) {
load += (double)activity.getCapacityDemand();
states.putActivityState(activity, StateTypes.LOAD, new StateImpl(load));
}
@Override
public void finish() {
states.putRouteState(vehicleRoute, StateTypes.LOAD, new StateImpl(load));
load=0;
vehicleRoute = null;
}
}
static class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener{
private StateManagerImpl states;
public UpdateLoadAtRouteLevel(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(!(job2insert instanceof Service)){
return;
}
double oldLoad = states.getRouteState(inRoute, StateTypes.LOAD).toDouble();
states.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(oldLoad + job2insert.getCapacityDemand()));
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
int load = 0;
for(Job j : route.getTourActivities().getJobs()){
load += j.getCapacityDemand();
}
states.putRouteState(route, StateTypes.LOAD, new StateImpl(load));
}
}
}
static class UpdateStates implements JobInsertedListener, RuinListener{
private RouteActivityVisitor routeActivityVisitor;
private ReverseRouteActivityVisitor revRouteActivityVisitor;
public UpdateStates(StateManagerImpl states, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) {
routeActivityVisitor = new RouteActivityVisitor();
routeActivityVisitor.addActivityVisitor(new UpdateActivityTimes(routingCosts));
routeActivityVisitor.addActivityVisitor(new UpdateCostsAtAllLevels(activityCosts, routingCosts, states));
routeActivityVisitor.addActivityVisitor(new UpdateLoadAtAllLevels(states));
revRouteActivityVisitor = new ReverseRouteActivityVisitor();
revRouteActivityVisitor.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(states, routingCosts));
}
public void update(VehicleRoute route){
routeActivityVisitor.visit(route);
revRouteActivityVisitor.visit(route);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
routeActivityVisitor.visit(inRoute);
revRouteActivityVisitor.visit(inRoute);
}
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
for(VehicleRoute route : routes) {
routeActivityVisitor.visit(route);
revRouteActivityVisitor.visit(route);
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
}
static class UpdateFuturePickupsAtActivityLevel implements ReverseActivityVisitor {
private StateManagerImpl stateManager;
private int futurePicks = 0;
private VehicleRoute route;
public UpdateFuturePickupsAtActivityLevel(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
}
@Override
public void visit(TourActivity act) {
stateManager.putActivityState(act, StateTypes.FUTURE_PICKS, new StateImpl(futurePicks));
if(act instanceof PickupActivity || act instanceof ServiceActivity){
futurePicks += act.getCapacityDemand();
}
assert futurePicks <= route.getVehicle().getCapacity() : "sum of pickups must not be > vehicleCap";
assert futurePicks >= 0 : "sum of pickups must not < 0";
}
@Override
public void finish() {
futurePicks = 0;
route = null;
}
}
static class UpdateOccuredDeliveriesAtActivityLevel implements ActivityVisitor {
private StateManagerImpl stateManager;
private int deliveries = 0;
private VehicleRoute route;
public UpdateOccuredDeliveriesAtActivityLevel(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
}
@Override
public void visit(TourActivity act) {
if(act instanceof DeliveryActivity){
deliveries += Math.abs(act.getCapacityDemand());
}
stateManager.putActivityState(act, StateTypes.PAST_DELIVERIES, new StateImpl(deliveries));
assert deliveries >= 0 : "deliveries < 0";
assert deliveries <= route.getVehicle().getCapacity() : "deliveries > vehicleCap";
}
@Override
public void finish() {
deliveries = 0;
route = null;
}
}
/**
* Updates load at activity level. Note that this assumed that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT.
* If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot.
*
* @author stefan
*
*/
static class UpdateLoadAtActivityLevel implements ActivityVisitor {
private StateManagerImpl stateManager;
private int currentLoad = 0;
private VehicleRoute route;
public UpdateLoadAtActivityLevel(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
currentLoad = (int) stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT).toDouble();
this.route = route;
}
@Override
public void visit(TourActivity act) {
currentLoad += act.getCapacityDemand();
stateManager.putActivityState(act, StateTypes.LOAD, new StateImpl(currentLoad));
assert currentLoad <= route.getVehicle().getCapacity() : "currentLoad at activity must not be > vehicleCapacity";
assert currentLoad >= 0 : "currentLoad at act must not be < 0";
}
@Override
public void finish() {
currentLoad = 0;
}
}
static class ResetStateManager implements IterationStartsListener {
private StateManagerImpl stateManager;
public ResetStateManager(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
stateManager.clear();
}
}
static interface InsertionStarts {
void insertionStarts(VehicleRoute route);
}
static class UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts implements InsertionStarts {
private StateManagerImpl stateManager;
public UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void insertionStarts(VehicleRoute route) {
int loadAtDepot = 0;
int loadAtEnd = 0;
for(Job j : route.getTourActivities().getJobs()){
if(j instanceof Delivery){
loadAtDepot += j.getCapacityDemand();
}
else if(j instanceof Pickup || j instanceof Service){
loadAtEnd += j.getCapacityDemand();
}
}
stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot));
stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd));
}
}
static class UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted implements JobInsertedListener {
private StateManagerImpl stateManager;
public UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(job2insert instanceof Delivery){
int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble();
// log.info("loadAtDepot="+loadAtDepot);
stateManager.putRouteState(inRoute, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot + job2insert.getCapacityDemand()));
}
else if(job2insert instanceof Pickup || job2insert instanceof Service){
int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD).toDouble();
// log.info("loadAtEnd="+loadAtEnd);
stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand()));
}
}
}
static class UpdateRouteStatesOnceTheRouteHasBeenChanged implements InsertionStartsListener, JobInsertedListener {
private RouteActivityVisitor forwardInTimeIterator;
private ReverseRouteActivityVisitor backwardInTimeIterator;
private Collection<InsertionStarts> insertionStartsListeners;
private Collection<JobInsertedListener> jobInsertionListeners;
public UpdateRouteStatesOnceTheRouteHasBeenChanged(VehicleRoutingTransportCosts routingCosts) {
forwardInTimeIterator = new RouteActivityVisitor();
backwardInTimeIterator = new ReverseRouteActivityVisitor();
insertionStartsListeners = new ArrayList<InsertionStarts>();
jobInsertionListeners = new ArrayList<JobInsertedListener>();
}
void addVisitor(ActivityVisitor vis){
forwardInTimeIterator.addActivityVisitor(vis);
}
void addVisitor(ReverseActivityVisitor revVis){
backwardInTimeIterator.addActivityVisitor(revVis);
}
void addInsertionStartsListener(InsertionStarts insertionStartListener){
insertionStartsListeners.add(insertionStartListener);
}
void addJobInsertedListener(JobInsertedListener jobInsertedListener){
jobInsertionListeners.add(jobInsertedListener);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
for(JobInsertedListener l : jobInsertionListeners){ l.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); }
forwardInTimeIterator.visit(inRoute);
backwardInTimeIterator.visit(inRoute);
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
for(InsertionStarts insertionsStartsHandler : insertionStartsListeners){
insertionsStartsHandler.insertionStarts(route);
}
forwardInTimeIterator.visit(route);
backwardInTimeIterator.visit(route);
}
}
}
}

View file

@ -1,84 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 algorithms;
import java.util.Collection;
import basics.route.Vehicle;
interface VehicleFleetManager {
static class TypeKey {
public final String type;
public final String locationId;
public TypeKey(String typeId, String locationId) {
super();
this.type = typeId;
this.locationId = locationId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((locationId == null) ? 0 : locationId.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TypeKey other = (TypeKey) obj;
if (locationId == null) {
if (other.locationId != null)
return false;
} else if (!locationId.equals(other.locationId))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
}
abstract void lock(Vehicle vehicle);
abstract void unlock(Vehicle vehicle);
abstract boolean isLocked(Vehicle vehicle);
abstract void unlockAll();
abstract Collection<Vehicle> getAvailableVehicles();
Collection<Vehicle> getAvailableVehicles(String withoutThisType, String locationId);
}

View file

@ -1,45 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 basics.costs;
import basics.route.Driver;
import basics.route.TourActivity;
import basics.route.Vehicle;
/**
* Function that basically does not allow soft time-windows. Actually, it is allowed but it is penalized with Double.MaxValue().
*
* @author schroeder
*
*/
public class DefaultVehicleRoutingActivityCosts implements VehicleRoutingActivityCosts{
@Override
public double getActivityCost(TourActivity tourAct, double arrivalTime, Driver driver, Vehicle vehicle) {
if(arrivalTime > tourAct.getTheoreticalLatestOperationStartTime()){
return Double.MAX_VALUE;
}
return 0;
}
@Override
public String toString() {
return "[name=hardTimeWindowActCosts]";
}
}

View file

@ -1,128 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 basics.route;
public class DefaultVehicleRouteCostCalculator implements VehicleRouteCostCalculator {
private double tpCosts = 0.0;
private double actCosts = 0.0;
private double vehicleCosts = 0.0;
private double driverCosts = 0.0;
private double other = 0.0;
public DefaultVehicleRouteCostCalculator(){}
private DefaultVehicleRouteCostCalculator(DefaultVehicleRouteCostCalculator costCalc){
this.tpCosts=costCalc.getTpCosts();
this.actCosts = costCalc.getActCosts();
this.driverCosts = costCalc.getDriverCosts();
this.other = costCalc.getOther();
this.vehicleCosts = costCalc.getVehicleCosts();
}
public void addTransportCost(double tpCost) {
this.tpCosts+=tpCost;
}
public void addActivityCost(double actCost){
this.actCosts+=actCost;
}
public void price(Vehicle vehicle){
if(vehicle != null){
VehicleType type = vehicle.getType();
if(type != null){
this.vehicleCosts = type.getVehicleCostParams().fix;
}
}
}
public void price(Driver driver){
}
@Override
public void finish() {
// TODO Auto-generated method stub
}
@Override
public void reset() {
tpCosts = 0.0;
actCosts = 0.0;
vehicleCosts = 0.0;
driverCosts = 0.0;
other = 0.0;
}
@Override
public void addOtherCost(double cost) {
this.other = cost;
}
@Override
public double getCosts() {
return tpCosts + actCosts + vehicleCosts + driverCosts + other;
}
/**
* @return the tpCosts
*/
public double getTpCosts() {
return tpCosts;
}
/**
* @return the actCosts
*/
public double getActCosts() {
return actCosts;
}
/**
* @return the vehicleCosts
*/
public double getVehicleCosts() {
return vehicleCosts;
}
/**
* @return the driverCosts
*/
public double getDriverCosts() {
return driverCosts;
}
/**
* @return the other
*/
public double getOther() {
return other;
}
@Override
public VehicleRouteCostCalculator duplicate() {
return new DefaultVehicleRouteCostCalculator(this);
}
}

View file

@ -1,102 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 basics.route;
import basics.Pickup;
import basics.route.TourActivity.JobActivity;
public class PickupActivity implements JobActivity<Pickup>{
private Pickup pickup;
private double arrTime;
private double depTime;
public PickupActivity(Pickup pickup) {
super();
this.pickup = pickup;
}
private PickupActivity(PickupActivity pickupActivity){
this.pickup=pickupActivity.getJob();
this.arrTime=pickupActivity.getArrTime();
this.depTime=pickupActivity.getEndTime();
}
@Override
public String getName() {
return pickup.getType();
}
@Override
public String getLocationId() {
return pickup.getLocationId();
}
@Override
public double getTheoreticalEarliestOperationStartTime() {
return pickup.getTimeWindow().getStart();
}
@Override
public double getTheoreticalLatestOperationStartTime() {
return pickup.getTimeWindow().getEnd();
}
@Override
public double getOperationTime() {
return pickup.getServiceDuration();
}
@Override
public double getArrTime() {
return arrTime;
}
@Override
public double getEndTime() {
return depTime;
}
@Override
public void setArrTime(double arrTime) {
this.arrTime=arrTime;
}
@Override
public void setEndTime(double endTime) {
this.depTime=endTime;
}
@Override
public TourActivity duplicate() {
return new PickupActivity(this);
}
@Override
public Pickup getJob() {
return pickup;
}
@Override
public int getCapacityDemand() {
return pickup.getCapacityDemand();
}
}

View file

@ -1,204 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 basics.route;
import basics.route.VehicleImpl.NoVehicle;
public class VehicleRoute {
public static VehicleRoute copyOf(VehicleRoute route) {
return new VehicleRoute(route);
}
public static VehicleRoute newInstance(TourActivities tour, Driver driver, Vehicle vehicle) {
return new VehicleRoute(tour,driver,vehicle);
}
public static VehicleRoute emptyRoute() {
return new VehicleRoute(TourActivities.emptyTour(), DriverImpl.noDriver(), VehicleImpl.noVehicle());
}
public static class Builder {
public static Builder newInstance(Start start, End end){
return new Builder(start,end);
}
private Start start;
private End end;
private Vehicle vehicle = VehicleImpl.noVehicle();
private Driver driver = DriverImpl.noDriver();
private TourActivities tour;
private Builder(Start start, End end) {
super();
this.start = start;
this.end = end;
this.tour = TourActivities.emptyTour();
}
public Builder setVehicle(Vehicle vehicle){
this.vehicle = vehicle;
return this;
}
public Builder setDriver(Driver driver){
this.driver = driver;
return this;
}
public Builder addActivity(TourActivity act){
if(act instanceof Start || act instanceof End){
throw new IllegalStateException("tourActivity should be of type Delivery or Pickup, but is of type " + act.getName());
}
tour.addActivity(act);
return this;
}
public VehicleRoute build(){
return new VehicleRoute(this);
}
}
private TourActivities tourActivities;
private Vehicle vehicle;
private Driver driver;
private Start start;
private End end;
@Deprecated
private VehicleRouteCostCalculator costCalculator = new DefaultVehicleRouteCostCalculator();
@Deprecated
public VehicleRouteCostCalculator getVehicleRouteCostCalculator(){
return costCalculator;
}
private VehicleRoute(VehicleRoute route){
this.start = Start.copyOf(route.getStart());
this.end = End.copyOf(route.getEnd());
this.tourActivities = TourActivities.copyOf(route.getTourActivities());
this.vehicle = route.getVehicle();
this.driver = route.getDriver();
this.costCalculator = route.getVehicleRouteCostCalculator().duplicate();
}
private VehicleRoute(TourActivities tour, Driver driver, Vehicle vehicle) {
super();
verify(tour, driver, vehicle);
this.tourActivities = tour;
this.vehicle = vehicle;
this.driver = driver;
setStartAndEnd(vehicle, vehicle.getEarliestDeparture());
}
private VehicleRoute(Builder builder){
this.tourActivities = builder.tour;
this.vehicle = builder.vehicle;
this.driver = builder.driver;
this.start = builder.start;
this.end = builder.end;
}
private void verify(TourActivities tour, Driver driver, Vehicle vehicle) {
if(tour == null || driver == null || vehicle == null) throw new IllegalStateException("null is not allowed for tour, driver or vehicle. use emptyRoute. use Tour.emptyTour, DriverImpl.noDriver() and VehicleImpl.noVehicle() instead." +
"\n\tor make it easier and use VehicleRoute.emptyRoute()");
if(!tour.isEmpty() && vehicle instanceof NoVehicle){
throw new IllegalStateException("if tour is not empty. there must be a vehicle for this tour, but there is no vehicle.");
}
}
public TourActivities getTourActivities() {
return tourActivities;
}
public Vehicle getVehicle() {
return vehicle;
}
public Driver getDriver() {
return driver;
}
public void setVehicle(Vehicle vehicle, double vehicleDepTime){
this.vehicle = vehicle;
setStartAndEnd(vehicle, vehicleDepTime);
}
public void setDepartureTime(double vehicleDepTime){
if(start == null) throw new IllegalStateException("cannot set departureTime without having a vehicle on this route. use setVehicle(vehicle,departureTime) instead.");
start.setEndTime(vehicleDepTime);
}
public double getDepartureTime(){
if(start == null) throw new IllegalStateException("cannot get departureTime without having a vehicle on this route. use setVehicle(vehicle,departureTime) instead.");
return start.getEndTime();
}
private void setStartAndEnd(Vehicle vehicle, double vehicleDepTime) {
if(!(vehicle instanceof NoVehicle)){
if(start == null && end == null){
start = Start.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
end = End.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
}
start.setEndTime(vehicleDepTime);
start.setTheoreticalEarliestOperationStartTime(vehicle.getEarliestDeparture());
start.setTheoreticalLatestOperationStartTime(vehicle.getLatestArrival());
start.setLocationId(vehicle.getLocationId());
end.setLocationId(vehicle.getLocationId());
end.setTheoreticalEarliestOperationStartTime(vehicle.getEarliestDeparture());
end.setTheoreticalLatestOperationStartTime(vehicle.getLatestArrival());
}
}
public boolean isEmpty() {
return tourActivities.isEmpty();
}
public Start getStart() {
return start;
}
public End getEnd() {
return end;
}
@Deprecated
public void setVehicleRouteCostCalculator(VehicleRouteCostCalculator costAccumulator){
this.costCalculator = costAccumulator;
}
@Deprecated
public double getCost() {
if(tourActivities.isEmpty()){
return 0.0;
}
return costCalculator.getCosts();
}
}

View file

@ -1,40 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 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 basics.route;
@Deprecated
public interface VehicleRouteCostCalculator {
public void addTransportCost(double cost);
public void addActivityCost(double cost);
public void addOtherCost(double cost);
public void price(Vehicle vehicle);
public void price(Driver driver);
public double getCosts();
public void finish();
public void reset();
public VehicleRouteCostCalculator duplicate();
}

View file

@ -0,0 +1,54 @@
///*******************************************************************************
// * Copyright (C) 2013 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;
//
//import java.util.ArrayList;
//import java.util.Collection;
//import java.util.List;
//
//import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
//import jsprit.core.problem.job.Job;
//import jsprit.core.problem.solution.route.VehicleRoute;
//
//
//class FindCheaperVehicle implements InsertionStartsListener{
//
// FindCheaperVehicleAlgo findCheaperVehicle;
//
// public FindCheaperVehicle(FindCheaperVehicleAlgo findCheaperVehicle) {
// super();
// this.findCheaperVehicle = findCheaperVehicle;
// }
//
// @Override
// public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
// List<VehicleRoute> newRoutes = new ArrayList<VehicleRoute>();
// for(VehicleRoute route : vehicleRoutes){
// if(route.isEmpty()) continue;
// VehicleRoute cheaperRoute = findCheaperVehicle.runAndGetVehicleRoute(route);
// newRoutes.add(cheaperRoute);
// }
// vehicleRoutes.clear();
// vehicleRoutes.addAll(newRoutes);
// }
//
// @Override
// public String toString() {
// return "[name=findCheaperVehicle]";
// }
//
//}

View file

@ -0,0 +1,114 @@
///*******************************************************************************
// * Copyright (C) 2013 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;
//
//import java.util.ArrayList;
//import java.util.List;
//
//import jsprit.core.algorithm.recreate.AuxilliaryCostCalculator;
//import jsprit.core.algorithm.state.StateFactory;
//import jsprit.core.algorithm.state.StateGetter;
//import jsprit.core.problem.solution.route.VehicleRoute;
//import jsprit.core.problem.solution.route.activity.TourActivities;
//import jsprit.core.problem.solution.route.activity.TourActivity;
//import jsprit.core.problem.vehicle.Vehicle;
//import jsprit.core.problem.vehicle.VehicleFleetManager;
//import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
//
//import org.apache.log4j.Logger;
//
//
//
//
//final class FindCheaperVehicleAlgo {
//
// private static Logger log = Logger.getLogger(FindCheaperVehicleAlgo.class);
//
// private VehicleFleetManager fleetManager;
//
// private VehicleRouteUpdater tourStateCalculator;
//
// private AuxilliaryCostCalculator auxilliaryCostCalculator;
//
// private double weightFixCosts = 1.0;
//
// private StateGetter states;
//
// public void setWeightFixCosts(double weightFixCosts) {
// this.weightFixCosts = weightFixCosts;
// }
//
// public void setStates(StateGetter states) {
// this.states = states;
// }
//
// public FindCheaperVehicleAlgo(VehicleFleetManager fleetManager, VehicleRouteUpdater tourStateCalculator, AuxilliaryCostCalculator auxilliaryCostCalculator) {
// super();
// this.fleetManager = fleetManager;
// this.tourStateCalculator = tourStateCalculator;
// this.auxilliaryCostCalculator = auxilliaryCostCalculator;
// }
//
//
// public VehicleRoute runAndGetVehicleRoute(VehicleRoute vehicleRoute) {
// if(vehicleRoute.getVehicle() instanceof NoVehicle){
// return vehicleRoute;
// }
// if(vehicleRoute.getTourActivities() == null || vehicleRoute.getVehicle() == null){
// return vehicleRoute;
// }
//// Collection<TypeKey> availableVehicleTypes = fleetManager.getAvailableVehicleTypes(new TypeKey(vehicleRoute.getVehicle().getType(),vehicleRoute.getVehicle().getLocationId()));
// double bestSaving = 0.0;
// Vehicle bestVehicle = null;
// List<TourActivity> path = new ArrayList<TourActivity>();
// path.add(vehicleRoute.getStart());
// path.addAll(vehicleRoute.getTourActivities().getActivities());
// path.add(vehicleRoute.getEnd());
//
// for(Vehicle vehicle : fleetManager.getAvailableVehicles(vehicleRoute.getVehicle().getType().getTypeId(), vehicleRoute.getVehicle().getLocationId())){
//// Vehicle vehicle = fleetManager.getEmptyVehicle(vehicleType);
// if(vehicle.getType().getTypeId().equals(vehicleRoute.getVehicle().getType().getTypeId())){
// continue;
// }
// if(states.getRouteState(vehicleRoute,StateFactory.LOAD).toDouble() <= vehicle.getCapacity()){
// double fixCostSaving = vehicleRoute.getVehicle().getType().getVehicleCostParams().fix - vehicle.getType().getVehicleCostParams().fix;
// double departureTime = vehicleRoute.getStart().getEndTime();
// double newCost = auxilliaryCostCalculator.costOfPath(path, departureTime, vehicleRoute.getDriver(), vehicle);
// double varCostSaving = states.getRouteState(vehicleRoute, StateFactory.COSTS).toDouble() - newCost;
// double totalCostSaving = varCostSaving + weightFixCosts*fixCostSaving;
// if(totalCostSaving > bestSaving){
// bestSaving = totalCostSaving;
// bestVehicle = vehicle;
// }
// }
// }
// if(bestVehicle != null){
// try{
// fleetManager.unlock(vehicleRoute.getVehicle());
// fleetManager.lock(bestVehicle);
// }
// catch(IllegalStateException e){
// throw new IllegalStateException(e);
// }
// TourActivities newTour = TourActivities.copyOf(vehicleRoute.getTourActivities());
// tourStateCalculator.iterate(vehicleRoute);
// return VehicleRoute.newInstance(newTour,vehicleRoute.getDriver(),bestVehicle);
// }
// return vehicleRoute;
// }
//
//}

View file

@ -0,0 +1,82 @@
/*******************************************************************************
* Copyright (c) 2011 Stefan Schroeder.
* eMail: stefan.schroeder@kit.edu
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
/* *********************************************************************** *
* project: org.matsim.*
* IniSolution.java
* *
* *********************************************************************** *
* *
* copyright : (C) 2011 by the members listed in the COPYING, *
* LICENSE and WARRANTY file. *
* email : info at matsim dot org *
* *
* *********************************************************************** *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* See also COPYING, LICENSE and WARRANTY file *
* *
* *********************************************************************** */
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.List;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.InitialSolutionFactory;
import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import org.apache.log4j.Logger;
public final class InsertionInitialSolutionFactory implements InitialSolutionFactory {
private static final Logger logger = Logger.getLogger(InsertionInitialSolutionFactory.class);
private final InsertionStrategy insertion;
private SolutionCostCalculator solutionCostsCalculator;
public InsertionInitialSolutionFactory(InsertionStrategy insertionStrategy, SolutionCostCalculator solutionCostCalculator) {
super();
this.insertion = insertionStrategy;
this.solutionCostsCalculator = solutionCostCalculator;
}
@Override
public VehicleRoutingProblemSolution createSolution(final VehicleRoutingProblem vrp) {
logger.info("create initial solution.");
List<VehicleRoute> vehicleRoutes = new ArrayList<VehicleRoute>();
insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(vehicleRoutes, Double.MAX_VALUE);
double costs = solutionCostsCalculator.getCosts(solution);
solution.setCost(costs);
logger.info("creation done");
return solution;
}
private List<Job> getUnassignedJobs(VehicleRoutingProblem vrp) {
List<Job> jobs = new ArrayList<Job>(vrp.getJobs().values());
return jobs;
}
}

View file

@ -14,28 +14,28 @@
* 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 algorithms;
package jsprit.core.algorithm;
import java.util.Collection;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.util.CrowFlyCosts;
import jsprit.core.util.EuclideanDistanceCalculator;
import jsprit.core.util.Locations;
import jsprit.core.util.NeighborhoodImpl;
import jsprit.core.util.Solutions;
import org.apache.commons.math.stat.descriptive.moment.Mean;
import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
import org.apache.log4j.Logger;
import util.CrowFlyCosts;
import util.EuclideanDistanceCalculator;
import util.Locations;
import util.NeighborhoodImpl;
import util.Solutions;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmStartsListener;
import basics.algo.VehicleRoutingAlgorithmFactory;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
public class NeighborhoodThresholdInitialiser implements AlgorithmStartsListener{
class NeighborhoodThresholdInitialiser implements AlgorithmStartsListener{
private static Logger log = Logger.getLogger(NeighborhoodThresholdInitialiser.class);

View file

@ -14,24 +14,22 @@
* 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 algorithms;
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.log4j.Logger;
import jsprit.core.algorithm.recreate.listener.InsertionEndsListener;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import basics.algo.InsertionEndsListener;
import basics.route.VehicleRoute;
class RemoveEmptyVehicles implements InsertionEndsListener{
public class RemoveEmptyVehicles implements InsertionEndsListener{
private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class);
private VehicleFleetManager fleetManager;
RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
public RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
super();
this.fleetManager = fleetManager;
}

View file

@ -14,24 +14,22 @@
* 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 algorithms;
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import basics.Job;
import basics.algo.InsertionStartsListener;
import basics.route.VehicleRoute;
class ResetAndIniFleetManager implements InsertionStartsListener{
public class ResetAndIniFleetManager implements InsertionStartsListener{
private static Logger log = Logger.getLogger(ResetAndIniFleetManager.class);
private VehicleFleetManager vehicleFleetManager;
ResetAndIniFleetManager(VehicleFleetManager vehicleFleetManager) {
public ResetAndIniFleetManager(VehicleFleetManager vehicleFleetManager) {
super();
this.vehicleFleetManager = vehicleFleetManager;
}
@ -41,12 +39,7 @@ class ResetAndIniFleetManager implements InsertionStartsListener{
vehicleFleetManager.unlockAll();
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
for(VehicleRoute route : routes){
// if(route.isEmpty()){
// vehicleRoutes.remove(route);
// }
// else{
vehicleFleetManager.lock(route.getVehicle());
// }
vehicleFleetManager.lock(route.getVehicle());
}
}

View file

@ -14,18 +14,21 @@
* 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 basics.algo;
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import jsprit.core.algorithm.acceptor.SolutionAcceptor;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.algorithm.selector.SolutionSelector;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import org.apache.log4j.Logger;
import algorithms.acceptors.SolutionAcceptor;
import algorithms.selectors.SolutionSelector;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
@ -125,7 +128,8 @@ public class SearchStrategy {
VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(lastSolution);
lastSolution = newSolution;
}
solutionCostCalculator.calculateCosts(lastSolution);
double costs = solutionCostCalculator.getCosts(lastSolution);
lastSolution.setCost(costs);
boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution);
DiscoveredSolution discoveredSolution = new DiscoveredSolution(lastSolution, solutionAccepted, getName());
return discoveredSolution;

View file

@ -14,14 +14,17 @@
* 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 basics.algo;
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import util.RandomNumberGeneration;
import jsprit.core.algorithm.listener.SearchStrategyListener;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.util.RandomNumberGeneration;
public class SearchStrategyManager {

View file

@ -14,9 +14,10 @@
* 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 basics.algo;
package jsprit.core.algorithm;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
public interface SearchStrategyModule {

View file

@ -0,0 +1,33 @@
package jsprit.core.algorithm;
import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.solution.route.state.StateFactory;
public class VariablePlusFixedSolutionCostCalculatorFactory {
private RouteAndActivityStateGetter stateManager;
public VariablePlusFixedSolutionCostCalculatorFactory(RouteAndActivityStateGetter stateManager) {
super();
this.stateManager = stateManager;
}
public SolutionCostCalculator createCalculator(){
return new SolutionCostCalculator() {
@Override
public double getCosts(VehicleRoutingProblemSolution solution) {
double c = 0.0;
for(VehicleRoute r : solution.getRoutes()){
c += stateManager.getRouteState(r, StateFactory.COSTS).toDouble();
c += r.getVehicle().getType().getVehicleCostParams().fix;
}
return c;
}
};
}
}

View file

@ -14,26 +14,29 @@
* 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 basics;
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.Collection;
import jsprit.core.algorithm.SearchStrategy.DiscoveredSolution;
import jsprit.core.algorithm.acceptor.SolutionAcceptor;
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.algorithm.listener.IterationEndsListener;
import jsprit.core.algorithm.listener.IterationStartsListener;
import jsprit.core.algorithm.listener.SearchStrategyListener;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.algorithm.listener.StrategySelectedListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners;
import jsprit.core.algorithm.termination.IterationWithoutImprovementTermination;
import jsprit.core.algorithm.termination.PrematureAlgorithmTermination;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import org.apache.log4j.Logger;
import util.Counter;
import algorithms.acceptors.SolutionAcceptor;
import basics.algo.AlgorithmEndsListener;
import basics.algo.AlgorithmStartsListener;
import basics.algo.IterationEndsListener;
import basics.algo.IterationStartsListener;
import basics.algo.IterationWithoutImprovementBreaker;
import basics.algo.PrematureAlgorithmBreaker;
import basics.algo.SearchStrategy;
import basics.algo.SearchStrategy.DiscoveredSolution;
import basics.algo.SearchStrategyManager;
import basics.algo.VehicleRoutingAlgorithmListener;
import basics.algo.VehicleRoutingAlgorithmListeners;
/**
* Algorithm that solves a {@link VehicleRoutingProblem}.
@ -43,7 +46,36 @@ import basics.algo.VehicleRoutingAlgorithmListeners;
*/
public class VehicleRoutingAlgorithm {
private static class Counter {
private final String name;
private long counter = 0;
private long nextCounter = 1;
private static final Logger log = Logger.getLogger(Counter.class);
public Counter(final String name) {
this.name = name;
}
public void incCounter() {
long i = counter++;
long n = nextCounter;
if (i >= n) {
if (nextCounter==n) {
nextCounter=n*2;
log.info(this.name + n);
}
}
}
public void print() {
log.info(this.name + counter);
}
public void reset() {
counter=0;
nextCounter=1;
}
}
public static final int NOBREAK = Integer.MAX_VALUE;
@ -61,7 +93,7 @@ public class VehicleRoutingAlgorithm {
private Collection<VehicleRoutingProblemSolution> initialSolutions;
private PrematureAlgorithmBreaker prematureAlgorithmBreaker = new PrematureAlgorithmBreaker() {
private PrematureAlgorithmTermination prematureAlgorithmTermination = new PrematureAlgorithmTermination() {
@Override
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
@ -100,15 +132,16 @@ public class VehicleRoutingAlgorithm {
* Improvement is what {@link SolutionAcceptor} understands about improvement. Or to put it in other words, the algo breaks prematurely after
* the assigned number of iterations without solution-acceptance.
*
*
* @deprecated use setPrematureAlgorithmTermination(new IterationWithoutImprovementTermination(int nuIterationsWithoutImprovement));
* @param nuIterationsWithoutImprovement
*/
@Deprecated
public void setPrematureBreak(int nuIterationsWithoutImprovement){
prematureAlgorithmBreaker = new IterationWithoutImprovementBreaker(nuIterationsWithoutImprovement);
prematureAlgorithmTermination = new IterationWithoutImprovementTermination(nuIterationsWithoutImprovement);
}
public void setPrematureAlgorithmBreaker(PrematureAlgorithmBreaker prematureAlgorithmBreaker){
this.prematureAlgorithmBreaker = prematureAlgorithmBreaker;
public void setPrematureAlgorithmTermination(PrematureAlgorithmTermination prematureAlgorithmTermination){
this.prematureAlgorithmTermination = prematureAlgorithmTermination;
}
/**
@ -146,7 +179,7 @@ public class VehicleRoutingAlgorithm {
SearchStrategy strategy = searchStrategyManager.getRandomStrategy();
DiscoveredSolution discoveredSolution = strategy.run(problem, solutions);
selectedStrategy(strategy.getName(),problem, solutions);
if(prematureAlgorithmBreaker.isPrematureBreak(discoveredSolution)){
if(prematureAlgorithmTermination.isPrematureBreak(discoveredSolution)){
logger.info("premature break at iteration "+ (i+1));
nuOfIterationsThisAlgoIsRunning = (i+1);
break;
@ -193,6 +226,12 @@ public class VehicleRoutingAlgorithm {
public VehicleRoutingAlgorithmListeners getAlgorithmListeners() {
return algoListeners;
}
public void addListener(VehicleRoutingAlgorithmListener l){
algoListeners.addListener(l);
if(l instanceof SearchStrategyListener) searchStrategyManager.addSearchStrategyListener((SearchStrategyListener) l);
if(l instanceof SearchStrategyModuleListener) searchStrategyManager.addSearchStrategyModuleListener((SearchStrategyModuleListener) l);
}
private void iterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
algoListeners.iterationEnds(i,problem, solutions);

View file

@ -14,10 +14,9 @@
* 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 basics.algo;
package jsprit.core.algorithm;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem;
public interface VehicleRoutingAlgorithmFactory {

View file

@ -14,11 +14,12 @@
* 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 algorithms.acceptors;
package jsprit.core.algorithm.acceptor;
import java.util.Collection;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
public class AcceptNewRemoveFirst implements SolutionAcceptor{

View file

@ -0,0 +1,158 @@
/*******************************************************************************
* Copyright (C) 2013 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.acceptor;
import java.net.URL;
import java.util.Collection;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.io.AlgorithmConfig;
import jsprit.core.algorithm.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.algorithm.listener.IterationEndsListener;
import jsprit.core.algorithm.listener.IterationStartsListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.util.Resource;
import jsprit.core.util.Solutions;
import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
import org.apache.log4j.Logger;
public class ExperimentalSchrimpfAcceptance implements SolutionAcceptor, IterationStartsListener, AlgorithmStartsListener{
private static Logger logger = Logger.getLogger(ExperimentalSchrimpfAcceptance.class);
private final double alpha;
private int nOfTotalIterations = 1000;
private int currentIteration = 0;
private double initialThreshold = 0.0;
private final int nOfRandomWalks;
private final int solutionMemory;
public ExperimentalSchrimpfAcceptance(int solutionMemory, double alpha, int nOfWarmupIterations) {
super();
this.alpha = alpha;
this.nOfRandomWalks = nOfWarmupIterations;
this.solutionMemory = solutionMemory;
logger.info("initialise " + this);
}
@Override
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
boolean solutionAccepted = false;
if (solutions.size() < solutionMemory) {
solutions.add(newSolution);
solutionAccepted = true;
} else {
VehicleRoutingProblemSolution worst = null;
double threshold = getThreshold(currentIteration);
for(VehicleRoutingProblemSolution solutionInMemory : solutions){
if(worst == null) worst = solutionInMemory;
else if(solutionInMemory.getCost() > worst.getCost()) worst = solutionInMemory;
}
if(newSolution.getRoutes().size() < worst.getRoutes().size()){
solutions.remove(worst);
solutions.add(newSolution);
solutionAccepted = true;
}
else if(newSolution.getRoutes().size() == worst.getRoutes().size() && newSolution.getCost() < worst.getCost() + threshold){
solutions.remove(worst);
solutions.add(newSolution);
solutionAccepted = true;
}
}
return solutionAccepted;
}
@Override
public String toString() {
return "[name=schrimpfAcceptanceFunction][alpha="+alpha+"][warmup=" + nOfRandomWalks + "]";
}
private double getThreshold(int iteration) {
double scheduleVariable = (double) iteration / (double) nOfTotalIterations;
// logger.debug("iter="+iteration+" totalIter="+nOfTotalIterations+" scheduling="+scheduleVariable);
double currentThreshold = initialThreshold * Math.exp(-Math.log(2) * scheduleVariable / alpha);
return currentThreshold;
}
@Override
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
reset();
logger.info("---------------------------------------------------------------------");
logger.info("prepare schrimpfAcceptanceFunction, i.e. determine initial threshold");
logger.info("start random-walk (see randomWalk.xml)");
double now = System.currentTimeMillis();
this.nOfTotalIterations = algorithm.getNuOfIterations();
/*
* randomWalk to determine standardDev
*/
final double[] results = new double[nOfRandomWalks];
URL resource = Resource.getAsURL("randomWalk.xml");
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
new AlgorithmConfigXmlReader(algorithmConfig).read(resource);
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.createAlgorithm(problem, algorithmConfig);
vra.setNuOfIterations(nOfRandomWalks);
vra.getAlgorithmListeners().addListener(new IterationEndsListener() {
@Override
public void informIterationEnds(int iteration, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
double result = Solutions.getBest(solutions).getCost();
// logger.info("result="+result);
results[iteration-1] = result;
}
});
vra.searchSolutions();
StandardDeviation dev = new StandardDeviation();
double standardDeviation = dev.evaluate(results);
initialThreshold = standardDeviation / 2;
logger.info("warmup done");
logger.info("total time: " + ((System.currentTimeMillis()-now)/1000.0) + "s");
logger.info("initial threshold: " + initialThreshold);
logger.info("---------------------------------------------------------------------");
}
private void reset() {
currentIteration = 0;
}
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
currentIteration = i;
}
}

View file

@ -14,18 +14,19 @@
* 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 algorithms.acceptors;
package jsprit.core.algorithm.acceptor;
import java.util.Collection;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
public class AcceptNewIfBetterThanWorst implements SolutionAcceptor{
public class GreedyAcceptance implements SolutionAcceptor{
private final int solutionMemory;
public AcceptNewIfBetterThanWorst(int solutionMemory){
public GreedyAcceptance(int solutionMemory){
this.solutionMemory = solutionMemory;
}
@ -47,6 +48,12 @@ public class AcceptNewIfBetterThanWorst implements SolutionAcceptor{
if (worstSolution == null) worstSolution = s;
else if (s.getCost() > worstSolution.getCost()) worstSolution = s;
}
// if(newSolution.getRoutes().size() < worstSolution.getRoutes().size()){
// solutions.remove(worstSolution);
// solutions.add(newSolution);
// solutionAccepted = true;
// }
// else
if(newSolution.getCost() < worstSolution.getCost()){
solutions.remove(worstSolution);
solutions.add(newSolution);

View file

@ -0,0 +1,73 @@
/*******************************************************************************
* Copyright (C) 2013 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.acceptor;
import java.util.Collection;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
public class GreedyAcceptance_minVehFirst implements SolutionAcceptor{
private final int solutionMemory;
public GreedyAcceptance_minVehFirst(int solutionMemory){
this.solutionMemory = solutionMemory;
}
/**
* Accepts every solution if solution memory allows. If memory occupied, than accepts new solution only if better than the worst in memory.
* Consequently, the worst solution is removed from solutions, and the new solution added.
*
* <p>Note that this modifies Collection<VehicleRoutingProblemSolution> solutions.
*/
@Override
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
boolean solutionAccepted = false;
if (solutions.size() < solutionMemory) {
solutions.add(newSolution);
solutionAccepted = true;
} else {
VehicleRoutingProblemSolution worstSolution = null;
for (VehicleRoutingProblemSolution s : solutions) {
if (worstSolution == null) worstSolution = s;
else if (s.getRoutes().size() > worstSolution.getRoutes().size()) worstSolution = s;
}
if(newSolution.getRoutes().size() < worstSolution.getRoutes().size()){
solutions.remove(worstSolution);
solutions.add(newSolution);
solutionAccepted = true;
}
else if(newSolution.getRoutes().size() == worstSolution.getRoutes().size() && newSolution.getCost() < worstSolution.getCost()){
solutions.remove(worstSolution);
solutions.add(newSolution);
solutionAccepted = true;
}
}
return solutionAccepted;
}
@Override
public String toString() {
return "[name=greedyAcceptance_minVehFirst]";
}
}

View file

@ -14,25 +14,26 @@
* 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 algorithms.acceptors;
package jsprit.core.algorithm.acceptor;
import java.net.URL;
import java.util.Collection;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.io.AlgorithmConfig;
import jsprit.core.algorithm.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.algorithm.listener.IterationEndsListener;
import jsprit.core.algorithm.listener.IterationStartsListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.util.Resource;
import jsprit.core.util.Solutions;
import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
import org.apache.log4j.Logger;
import util.Resource;
import util.Solutions;
import algorithms.VehicleRoutingAlgorithms;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmStartsListener;
import basics.algo.IterationEndsListener;
import basics.algo.IterationStartsListener;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;

View file

@ -14,11 +14,12 @@
* 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 algorithms.acceptors;
package jsprit.core.algorithm.acceptor;
import java.util.Collection;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
/**
* Acceptor that decides whether the newSolution is accepted or not.

View file

@ -14,15 +14,17 @@
* 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 algorithms;
package jsprit.core.algorithm.box;
import java.net.URL;
import util.Resource;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.io.AlgorithmConfig;
import jsprit.core.algorithm.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.util.Resource;
/**

View file

@ -14,15 +14,17 @@
* 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 algorithms;
package jsprit.core.algorithm.box;
import java.net.URL;
import util.Resource;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.io.AlgorithmConfig;
import jsprit.core.algorithm.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.util.Resource;
/**

View file

@ -14,7 +14,7 @@
* 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 basics.io;
package jsprit.core.algorithm.io;
import org.apache.commons.configuration.XMLConfiguration;

View file

@ -14,19 +14,20 @@
* 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 basics.io;
package jsprit.core.algorithm.io;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import jsprit.core.util.Resource;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import util.Resource;
public class AlgorithmConfigXmlReader {

View file

@ -14,28 +14,32 @@
* 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 algorithms;
package jsprit.core.algorithm.io;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.recreate.BestInsertionBuilder;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.state.StateManager;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.log4j.Logger;
import algorithms.HardConstraints.ConstraintManager;
import basics.VehicleRoutingProblem;
import basics.algo.InsertionListener;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
class InsertionFactory {
private static Logger log = Logger.getLogger(InsertionFactory.class);
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
boolean concurrentInsertion = false;
if(executorService != null) concurrentInsertion = true;
VehicleFleetManager vehicleFleetManager, StateManager routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
if(config.containsKey("[@name]")){
String insertionName = config.getString("[@name]");
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
@ -45,16 +49,17 @@ class InsertionFactory {
List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>();
CalculatorBuilder calcBuilder = new CalculatorBuilder(insertionListeners, algorithmListeners);
calcBuilder.setStates(routeStates);
calcBuilder.setVehicleRoutingProblem(vrp);
calcBuilder.setVehicleFleetManager(vehicleFleetManager);
calcBuilder.setConstraintManager(constraintManager);
BestInsertionBuilder iBuilder = new BestInsertionBuilder(vrp, vehicleFleetManager, routeStates, constraintManager);
if(executorService != null){
iBuilder.setConcurrentMode(executorService, nuOfThreads);
}
if(config.containsKey("level")){
String level = config.getString("level");
if(level.equals("local")){
calcBuilder.setLocalLevel();
iBuilder.setLocalLevel();
// calcBuilder.setLocalLevel();
}
else if(level.equals("route")){
int forwardLooking = 0;
@ -65,11 +70,12 @@ class InsertionFactory {
else log.warn("parameter route[@forwardLooking] is missing. by default it is 0 which equals to local level");
if(mem != null) memory = Integer.parseInt(mem);
else log.warn("parameter route[@memory] is missing. by default it is 1");
calcBuilder.setRouteLevel(forwardLooking, memory);
iBuilder.setRouteLevel(forwardLooking, memory);
// calcBuilder.setRouteLevel(forwardLooking, memory);
}
else throw new IllegalStateException("level " + level + " is not known. currently it only knows \"local\" or \"route\"");
}
else calcBuilder.setLocalLevel();
else iBuilder.setLocalLevel();
if(config.containsKey("considerFixedCosts") || config.containsKey("considerFixedCost")){
String val = config.getString("considerFixedCosts");
@ -80,36 +86,21 @@ class InsertionFactory {
if(weight == null) weight = config.getString("considerFixedCost[@weight]");
if(weight != null) fixedCostWeight = Double.parseDouble(weight);
else log.warn("parameter considerFixedCosts[@weight] is missing. by default, it is 0.5.");
calcBuilder.considerFixedCosts(fixedCostWeight);
iBuilder.considerFixedCosts(fixedCostWeight);
}
}
String timeSliceString = config.getString("experimental[@timeSlice]");
String neighbors = config.getString("experimental[@neighboringSlices]");
if(timeSliceString != null && neighbors != null){
calcBuilder.experimentalTimeScheduler(Double.parseDouble(timeSliceString),Integer.parseInt(neighbors));
iBuilder.experimentalTimeScheduler(Double.parseDouble(timeSliceString),Integer.parseInt(neighbors));
}
JobInsertionCalculator jic = calcBuilder.build();
if(insertionName.equals("bestInsertion")){
insertionStrategy = new BestInsertion(jic);
insertionStrategy = iBuilder.build();
}
// else if(insertionName.equals("regretInsertion")){
// insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
// }
// insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
// insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager));
// insertionStrategy.addListener(new VehicleSwitched(vehicleFleetManager));
// insertionStrategy.addListener(new UpdateLoadAtRouteLevel(routeStates));
// insertionStrategy.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
else throw new IllegalStateException("currently only 'bestInsertion' is supported");
for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l);
// insertionStrategy.addListener(new FindCheaperVehicle(
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));
algorithmListeners.addAll(algoListeners);
return insertionStrategy;

View file

@ -14,9 +14,10 @@
* 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 algorithms;
package jsprit.core.algorithm.io;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
@ -26,47 +27,68 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import jsprit.core.algorithm.InsertionInitialSolutionFactory;
import jsprit.core.algorithm.RemoveEmptyVehicles;
import jsprit.core.algorithm.ResetAndIniFleetManager;
import jsprit.core.algorithm.SearchStrategy;
import jsprit.core.algorithm.SearchStrategy.DiscoveredSolution;
import jsprit.core.algorithm.SearchStrategyManager;
import jsprit.core.algorithm.SearchStrategyModule;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.acceptor.AcceptNewRemoveFirst;
import jsprit.core.algorithm.acceptor.ExperimentalSchrimpfAcceptance;
import jsprit.core.algorithm.acceptor.GreedyAcceptance;
import jsprit.core.algorithm.acceptor.GreedyAcceptance_minVehFirst;
import jsprit.core.algorithm.acceptor.SchrimpfAcceptance;
import jsprit.core.algorithm.acceptor.SolutionAcceptor;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.RuinStrategyKey;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.SelectorKey;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.StrategyModuleKey;
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.Priority;
import jsprit.core.algorithm.module.RuinAndRecreateModule;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.algorithm.recreate.VehicleSwitched;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.ruin.RadialRuinStrategyFactory;
import jsprit.core.algorithm.ruin.RandomRuinStrategyFactory;
import jsprit.core.algorithm.ruin.RuinStrategy;
import jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance;
import jsprit.core.algorithm.ruin.distance.JobDistance;
import jsprit.core.algorithm.selector.SelectBest;
import jsprit.core.algorithm.selector.SelectRandomly;
import jsprit.core.algorithm.selector.SolutionSelector;
import jsprit.core.algorithm.state.StateManager;
import jsprit.core.algorithm.state.UpdateActivityTimes;
import jsprit.core.algorithm.state.UpdateVariableCosts;
import jsprit.core.algorithm.termination.IterationWithoutImprovementTermination;
import jsprit.core.algorithm.termination.PrematureAlgorithmTermination;
import jsprit.core.algorithm.termination.TimeTermination;
import jsprit.core.algorithm.termination.VariationCoefficientTermination;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem.FleetSize;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.state.StateFactory;
import jsprit.core.problem.vehicle.FiniteFleetManagerFactory;
import jsprit.core.problem.vehicle.InfiniteFleetManagerFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import jsprit.core.util.SolutionVerifier;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;
import algorithms.HardConstraints.ConstraintManager;
import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.RuinStrategyKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.SelectorKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.StrategyModuleKey;
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
import algorithms.acceptors.AcceptNewRemoveFirst;
import algorithms.acceptors.SchrimpfAcceptance;
import algorithms.acceptors.SolutionAcceptor;
import algorithms.selectors.SelectBest;
import algorithms.selectors.SelectRandomly;
import algorithms.selectors.SolutionSelector;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblem.Constraint;
import basics.VehicleRoutingProblem.FleetSize;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmStartsListener;
import basics.algo.InsertionListener;
import basics.algo.IterationWithoutImprovementBreaker;
import basics.algo.PrematureAlgorithmBreaker;
import basics.algo.SearchStrategy;
import basics.algo.SearchStrategy.DiscoveredSolution;
import basics.algo.SearchStrategyManager;
import basics.algo.SearchStrategyModule;
import basics.algo.SolutionCostCalculator;
import basics.algo.TimeBreaker;
import basics.algo.VariationCoefficientBreaker;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
@ -370,12 +392,12 @@ public class VehicleRoutingAlgorithms {
* @return {@link VehicleRoutingAlgorithm}
*/
public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp, final AlgorithmConfig algorithmConfig){
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),null,0);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0);
}
@Deprecated
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final XMLConfiguration config){
return createAlgo(vrp,config,null,0);
return createAlgo(vrp,config,0);
}
/**
@ -389,7 +411,7 @@ public class VehicleRoutingAlgorithms {
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
xmlReader.read(configURL);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),null,0);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0);
}
/**
@ -403,26 +425,18 @@ public class VehicleRoutingAlgorithms {
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
xmlReader.read(configFileName);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),null, 0);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0);
}
/**
* Read and creates {@link VehicleRoutingAlgorithm} from config-file.
*
* @param vrp
* @param configFileName
* @param nuOfThreads TODO
* @param {@link ExecutorService}
* @return {@link VehicleRoutingAlgorithm}
*/
private static VehicleRoutingAlgorithm readAndCreateConcurrentAlgorithm(final VehicleRoutingProblem vrp, final String configFileName, final ExecutorService executorService, int nuOfThreads){
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(VehicleRoutingProblem vrp, int nThreads, String configFileName) {
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
xmlReader.read(configFileName);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(), executorService, nuOfThreads);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),nThreads);
}
private static VehicleRoutingAlgorithm createAlgo(final VehicleRoutingProblem vrp, XMLConfiguration config, ExecutorService executorService, int nuOfThreads){
private static VehicleRoutingAlgorithm createAlgo(final VehicleRoutingProblem vrp, XMLConfiguration config, int nuOfThreads){
// map to store constructed modules
TypedMap definedClasses = new TypedMap();
@ -433,27 +447,54 @@ public class VehicleRoutingAlgorithms {
// insertion listeners
List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
//threading
final ExecutorService executorService;
if(nuOfThreads > 0){
log.info("setup executor-service with " + nuOfThreads + " threads");
executorService = Executors.newFixedThreadPool(nuOfThreads);
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new AlgorithmEndsListener() {
@Override
public void informAlgorithmEnds(VehicleRoutingProblem problem,Collection<VehicleRoutingProblemSolution> solutions) {
log.info("shutdown executor-service");
executorService.shutdown();
}
}));
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread arg0, Throwable arg1) {
System.err.println(arg1.toString());
System.exit(0);
}
});
Runtime.getRuntime().addShutdownHook(new Thread(){
public void run(){
if(!executorService.isShutdown()){
System.err.println("shutdowHook shuts down executorService");
executorService.shutdown();
}
}
});
}
else executorService = null;
//create fleetmanager
final VehicleFleetManager vehicleFleetManager = createFleetManager(vrp);
//create state-manager
final StateManagerImpl stateManager = new StateManagerImpl();
final StateManager stateManager = new StateManager(vrp);
stateManager.updateLoadStates();
stateManager.updateTimeWindowStates();
/*
* define constraints
*/
//constraint manager
ConstraintManager constraintManager = new ConstraintManager();
constraintManager.addConstraint(new HardConstraints.HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
if(vrp.getProblemConstraints().contains(Constraint.DELIVERIES_FIRST)){
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager));
}
else{
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryActivityLevelConstraint(stateManager));
}
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager));
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
constraintManager.addTimeWindowConstraint();
constraintManager.addLoadConstraint();
//construct initial solution creator
AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,constraintManager);
@ -490,32 +531,26 @@ public class VehicleRoutingAlgorithms {
/*
* define stateUpdates
*/
// UpdateLoads loadUpdater = new UpdateLoads(stateManager);
// stateManager.addListener(loadUpdater);
// stateManager.addActivityVisitor(loadUpdater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts()));
stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
//reset stateManager
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new StateUpdates.ResetStateManager(stateManager)));
//update states
// metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateStates(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged routeChangedListener = new StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged(vrp.getTransportCosts());
// stateManager.addActivityVisitor(new UpdateOccuredDeliveries(stateManager));
// stateManager.addActivityVisitor(new TimeWindowUpdater(stateManager, vrp.getTransportCosts()));
// stateManager.addActivityVisitor(new UpdateFuturePickups(stateManager));
routeChangedListener.addInsertionStartsListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
routeChangedListener.addJobInsertedListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(stateManager);
metaAlgorithm.getAlgorithmListeners().addListener(stateManager);
routeChangedListener.addVisitor(new StateUpdates.UpdateActivityTimes(vrp.getTransportCosts()));
routeChangedListener.addVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager));
routeChangedListener.addVisitor(new StateUpdates.UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
routeChangedListener.addVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager));
routeChangedListener.addVisitor(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
routeChangedListener.addVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(routeChangedListener);
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(vehicleFleetManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new ResetAndIniFleetManager(vehicleFleetManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager));
//define prematureBreak
PrematureAlgorithmBreaker prematureAlgoBreaker = getPrematureBreaker(config,algorithmListeners);
metaAlgorithm.setPrematureAlgorithmBreaker(prematureAlgoBreaker);
PrematureAlgorithmTermination prematureAlgoBreaker = getPrematureBreaker(config,algorithmListeners);
metaAlgorithm.setPrematureAlgorithmTermination(prematureAlgoBreaker);
//misc
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
@ -526,16 +561,16 @@ public class VehicleRoutingAlgorithms {
return metaAlgorithm;
}
private static SolutionCostCalculator getCostCalculator(final StateManagerImpl stateManager) {
private static SolutionCostCalculator getCostCalculator(final StateManager stateManager) {
SolutionCostCalculator calc = new SolutionCostCalculator() {
@Override
public void calculateCosts(VehicleRoutingProblemSolution solution) {
public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.0;
for(VehicleRoute route : solution.getRoutes()){
costs += stateManager.getRouteState(route, StateTypes.COSTS).toDouble() + getFixedCosts(route.getVehicle());
costs += stateManager.getRouteState(route, StateFactory.COSTS).toDouble() + getFixedCosts(route.getVehicle());
}
solution.setCost(costs);
return costs;
}
private double getFixedCosts(Vehicle vehicle) {
@ -549,21 +584,21 @@ public class VehicleRoutingAlgorithms {
private static VehicleFleetManager createFleetManager(final VehicleRoutingProblem vrp) {
if(vrp.getFleetSize().equals(FleetSize.INFINITE)){
return new InfiniteVehicles(vrp.getVehicles());
return new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
}
else if(vrp.getFleetSize().equals(FleetSize.FINITE)){
return new VehicleFleetManagerImpl(vrp.getVehicles());
return new FiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
}
throw new IllegalStateException("fleet size can only be infinite or finite. " +
"makes sure your config file contains one of these options");
}
private static PrematureAlgorithmBreaker getPrematureBreaker(XMLConfiguration config, Set<PrioritizedVRAListener> algorithmListeners) {
private static PrematureAlgorithmTermination getPrematureBreaker(XMLConfiguration config, Set<PrioritizedVRAListener> algorithmListeners) {
String basedOn = config.getString("prematureBreak[@basedOn]");
if(basedOn == null){
log.info("set default prematureBreak, i.e. no premature break at all.");
return new PrematureAlgorithmBreaker() {
return new PrematureAlgorithmTermination() {
@Override
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
@ -576,14 +611,14 @@ public class VehicleRoutingAlgorithms {
String iter = config.getString("prematureBreak.iterations");
if(iter == null) throw new IllegalStateException("prematureBreak.iterations is missing");
int iterations = Integer.valueOf(iter);
return new IterationWithoutImprovementBreaker(iterations);
return new IterationWithoutImprovementTermination(iterations);
}
if(basedOn.equals("time")){
log.info("set prematureBreak based on time");
String timeString = config.getString("prematureBreak.time");
if(timeString == null) throw new IllegalStateException("prematureBreak.time is missing");
double time = Double.valueOf(timeString);
TimeBreaker timeBreaker = new TimeBreaker(time);
TimeTermination timeBreaker = new TimeTermination(time);
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, timeBreaker));
return timeBreaker;
}
@ -595,7 +630,7 @@ public class VehicleRoutingAlgorithms {
if(iterationsString == null) throw new IllegalStateException("prematureBreak.iterations is missing");
double threshold = Double.valueOf(thresholdString);
int iterations = Integer.valueOf(iterationsString);
VariationCoefficientBreaker variationCoefficientBreaker = new VariationCoefficientBreaker(iterations, threshold);
VariationCoefficientTermination variationCoefficientBreaker = new VariationCoefficientTermination(iterations, threshold);
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, variationCoefficientBreaker));
return variationCoefficientBreaker;
}
@ -626,7 +661,7 @@ public class VehicleRoutingAlgorithms {
metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners);
}
private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManager routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
if(modConfigs == null) return null;
if(modConfigs.isEmpty()) return null;
@ -651,9 +686,11 @@ public class VehicleRoutingAlgorithms {
@Override
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy, getCostCalculator(routeStates));
createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false);
VehicleRoutingProblemSolution vrpSol = createInitialSolution.createInitialSolution(vrp);
InsertionInitialSolutionFactory insertionInitialSolutionFactory = new InsertionInitialSolutionFactory(finalInsertionStrategy, getCostCalculator(routeStates));
// CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy, getCostCalculator(routeStates));
//
// createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false);
VehicleRoutingProblemSolution vrpSol = insertionInitialSolutionFactory.createSolution(vrp);
solutions.add(vrpSol);
}
};
@ -698,7 +735,7 @@ public class VehicleRoutingAlgorithms {
SolutionAcceptor definedAcceptor = typedMap.get(acceptorKey);
if(definedAcceptor != null) return definedAcceptor;
if(acceptorName.equals("acceptNewRemoveWorst")){
AcceptNewIfBetterThanWorst acceptor = new AcceptNewIfBetterThanWorst(solutionMemory);
GreedyAcceptance acceptor = new GreedyAcceptance(solutionMemory);
typedMap.put(acceptorKey, acceptor);
return acceptor;
}
@ -707,6 +744,16 @@ public class VehicleRoutingAlgorithms {
typedMap.put(acceptorKey, acceptor);
return acceptor;
}
if(acceptorName.equals("greedyAcceptance")){
GreedyAcceptance acceptor = new GreedyAcceptance(solutionMemory);
typedMap.put(acceptorKey, acceptor);
return acceptor;
}
if(acceptorName.equals("greedyAcceptance_minVehFirst")){
GreedyAcceptance_minVehFirst acceptor = new GreedyAcceptance_minVehFirst(solutionMemory);
typedMap.put(acceptorKey, acceptor);
return acceptor;
}
if(acceptorName.equals("schrimpfAcceptance")){
int iterOfSchrimpf = strategyConfig.getInt("acceptor.warmup");
double alpha = strategyConfig.getDouble("acceptor.alpha");
@ -715,13 +762,21 @@ public class VehicleRoutingAlgorithms {
typedMap.put(acceptorKey, schrimpf);
return schrimpf;
}
if(acceptorName.equals("experimentalSchrimpfAcceptance")){
int iterOfSchrimpf = strategyConfig.getInt("acceptor.warmup");
double alpha = strategyConfig.getDouble("acceptor.alpha");
ExperimentalSchrimpfAcceptance schrimpf = new ExperimentalSchrimpfAcceptance(solutionMemory, alpha, iterOfSchrimpf);
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, schrimpf));
typedMap.put(acceptorKey, schrimpf);
return schrimpf;
}
else{
throw new IllegalStateException("solution acceptor " + acceptorName + " is not known");
}
}
private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
final StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
final StateManager routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
String moduleName = moduleConfig.getString("[@name]");
if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
String moduleId = moduleConfig.getString("[@id]");
@ -746,15 +801,15 @@ public class VehicleRoutingAlgorithms {
}
else if(ruin_name.equals("radialRuin")){
String ruin_distance = moduleConfig.getString("ruin.distance");
JobDistance jobDistance;
if(ruin_distance == null) jobDistance = new JobDistanceAvgCosts(vrp.getTransportCosts());
else {
if(ruin_distance.equals("euclidean")){
jobDistance = new EuclideanServiceDistance();
}
else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
+ "default is used or use 'euclidean'");
}
JobDistance jobDistance = new AvgServiceAndShipmentDistance(vrp.getTransportCosts());
// if(ruin_distance == null) jobDistance
// else {
// if(ruin_distance.equals("euclidean")){
// jobDistance = new EuclideanServiceDistance();
// }
// else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
// + "default is used or use 'euclidean'");
// }
ruin = getRadialRuin(vrp, routeStates, definedClasses, ruinKey, shareToRuin, jobDistance);
}
else throw new IllegalStateException("ruin[@name] " + ruin_name + " is not known. Use either randomRuin or radialRuin.");
@ -779,40 +834,40 @@ public class VehicleRoutingAlgorithms {
return rrModule;
}
if(moduleName.equals("gendreau")){
int iterations = moduleConfig.getInt("iterations");
double share = moduleConfig.getDouble("share");
String ruinName = moduleConfig.getString("ruin[@name]");
if(ruinName == null) throw new IllegalStateException("gendreau.ruin[@name] is missing. set it to \"radialRuin\" or \"randomRuin\"");
String ruinId = moduleConfig.getString("ruin[@id]");
if(ruinId == null) ruinId = "noId";
ModKey ruinKey = makeKey(ruinName,ruinId);
RuinStrategyKey stratKey = new RuinStrategyKey(ruinKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
ruin = new RuinRadial(vrp, 0.3, new JobDistanceAvgCosts(vrp.getTransportCosts()));
definedClasses.put(stratKey, ruin);
}
String insertionName = moduleConfig.getString("insertion[@name]");
if(insertionName == null) throw new IllegalStateException("gendreau.insertion[@name] is missing. set it to \"regretInsertion\" or \"bestInsertion\"");
String insertionId = moduleConfig.getString("insertion[@id]");
if(insertionId == null) insertionId = "noId";
ModKey insertionKey = makeKey(insertionName,insertionId);
InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
if(insertion == null){
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads, constraintManager);
algorithmListeners.addAll(prioListeners);
}
Gendreau gendreau = new Gendreau(vrp, ruin, insertion);
gendreau.setShareOfJobsToRuin(share);
gendreau.setNuOfIterations(iterations);
gendreau.setFleetManager(vehicleFleetManager);
definedClasses.put(strategyModuleKey, gendreau);
return gendreau;
throw new UnsupportedOperationException("gendreau is not supported yet");
// int iterations = moduleConfig.getInt("iterations");
// double share = moduleConfig.getDouble("share");
// String ruinName = moduleConfig.getString("ruin[@name]");
// if(ruinName == null) throw new IllegalStateException("gendreau.ruin[@name] is missing. set it to \"radialRuin\" or \"randomRuin\"");
// String ruinId = moduleConfig.getString("ruin[@id]");
// if(ruinId == null) ruinId = "noId";
// ModKey ruinKey = makeKey(ruinName,ruinId);
// RuinStrategyKey stratKey = new RuinStrategyKey(ruinKey);
// RuinStrategy ruin = definedClasses.get(stratKey);
// if(ruin == null){
// ruin = new RadialRuinStrategyFactory(0.3, new AvgJobDistance(vrp.getTransportCosts())).createStrategy(vrp);
// definedClasses.put(stratKey, ruin);
// }
//
// String insertionName = moduleConfig.getString("insertion[@name]");
// if(insertionName == null) throw new IllegalStateException("gendreau.insertion[@name] is missing. set it to \"regretInsertion\" or \"bestInsertion\"");
// String insertionId = moduleConfig.getString("insertion[@id]");
// if(insertionId == null) insertionId = "noId";
// ModKey insertionKey = makeKey(insertionName,insertionId);
// InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
// InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
// if(insertion == null){
// List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
// if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
// List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
// insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads, constraintManager);
// algorithmListeners.addAll(prioListeners);
// }
// Gendreau gendreau = new Gendreau(vrp, ruin, insertion, vehicleFleetManager);
// gendreau.setShareOfJobsToRuin(share);
// gendreau.setNuOfIterations(iterations);
// definedClasses.put(strategyModuleKey, gendreau);
// return gendreau;
}
throw new NullPointerException("no module found with moduleName=" + moduleName +
"\n\tcheck config whether the correct names are used" +
@ -823,30 +878,32 @@ public class VehicleRoutingAlgorithms {
"\n\tgendreauPostOpt");
}
private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManagerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) {
private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
ruin = new RuinRadial(vrp, shareToRuin, jobDistance);
ruin = new RadialRuinStrategyFactory(shareToRuin, jobDistance).createStrategy(vrp);
definedClasses.put(stratKey, ruin);
}
return ruin;
}
private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManagerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) {
private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
ruin = new RuinRandom(vrp, shareToRuin);
ruin = new RandomRuinStrategyFactory(shareToRuin).createStrategy(vrp);
definedClasses.put(stratKey, ruin);
}
return ruin;
}
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManager routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads, constraintManager);
return insertion;
}
}

View file

@ -14,12 +14,13 @@
* 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 basics.algo;
package jsprit.core.algorithm.listener;
import java.util.Collection;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -14,13 +14,14 @@
* 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 basics.algo;
package jsprit.core.algorithm.listener;
import java.util.Collection;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -14,12 +14,13 @@
* 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 basics.algo;
package jsprit.core.algorithm.listener;
import java.util.Collection;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -14,12 +14,13 @@
* 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 basics.algo;
package jsprit.core.algorithm.listener;
import java.util.Collection;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -14,7 +14,7 @@
* 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 basics.algo;
package jsprit.core.algorithm.listener;
public interface SearchStrategyListener extends VehicleRoutingAlgorithmListener{

View file

@ -14,7 +14,7 @@
* 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 basics.algo;
package jsprit.core.algorithm.listener;
public interface SearchStrategyModuleListener extends VehicleRoutingAlgorithmListener{

View file

@ -14,12 +14,13 @@
* 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 basics.algo;
package jsprit.core.algorithm.listener;
import java.util.Collection;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -14,7 +14,7 @@
* 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 basics.algo;
package jsprit.core.algorithm.listener;
public interface VehicleRoutingAlgorithmListener {

View file

@ -14,7 +14,7 @@
* 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 basics.algo;
package jsprit.core.algorithm.listener;
import java.util.ArrayList;
import java.util.Collection;
@ -23,9 +23,10 @@ import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -0,0 +1,224 @@
///*******************************************************************************
// * Copyright (C) 2013 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.module;
//
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.Collection;
//import java.util.Collections;
//import java.util.HashSet;
//import java.util.List;
//import java.util.Random;
//import java.util.Set;
//
//import jsprit.core.algorithm.SearchStrategyModule;
//import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
//import jsprit.core.algorithm.recreate.InsertionStrategy;
//import jsprit.core.algorithm.recreate.listener.InsertionListener;
//import jsprit.core.algorithm.recreate.listener.InsertionListeners;
//import jsprit.core.algorithm.ruin.RuinStrategy;
//import jsprit.core.algorithm.ruin.listener.RuinListener;
//import jsprit.core.problem.Job;
//import jsprit.core.problem.VehicleRoutingProblem;
//import jsprit.core.problem.VehicleRoutingProblemSolution;
//import jsprit.core.problem.route.TourActivity;
//import jsprit.core.problem.route.TourActivity.JobActivity;
//import jsprit.core.problem.route.VehicleFleetManager;
//import jsprit.core.problem.route.VehicleRoute;
//import jsprit.core.util.RandomNumberGeneration;
//
//import org.apache.log4j.Logger;
//
//
//final class Gendreau implements SearchStrategyModule{
//
// private final static Logger log = Logger.getLogger(Gendreau.class);
//
// private final static String NAME = "gendreauPostOpt";
//
// private final RuinStrategy ruin;
//
// private final VehicleRoutingProblem vrp;
//
// private final InsertionStrategy insertionStrategy;
//
// private VehicleFleetManager fleetManager;
//
// private Random random = RandomNumberGeneration.getRandom();
//
// private int nOfIterations = 10;
//
// private double shareOfJobsToRuin = 0.15;
//
// public void setShareOfJobsToRuin(double shareOfJobsToRuin) {
// this.shareOfJobsToRuin = shareOfJobsToRuin;
// }
//
// public Gendreau(VehicleRoutingProblem vrp, RuinStrategy ruin, InsertionStrategy insertionStrategy, VehicleFleetManager vehicleFleetManager) {
// super();
// InsertionListeners insertionListeners = new InsertionListeners();
// insertionListeners.addAllListeners(insertionStrategy.getListeners());
// new Inserter(insertionListeners);
// this.ruin = ruin;
// this.vrp = vrp;
// this.insertionStrategy = insertionStrategy;
// this.fleetManager = vehicleFleetManager;
// }
//
// @Override
// public String toString() {
// return "[name=gendreau][iterations="+nOfIterations+"][share2ruin="+shareOfJobsToRuin+"]";
// }
//
// public void setRandom(Random random) {
// this.random = random;
// }
//
//
// public void setNuOfIterations(int nOfIterations) {
// this.nOfIterations = nOfIterations;
// }
//
//// public void setFleetManager(VehicleFleetManager vehicleFleetManager) {
//// this.fleetManager = vehicleFleetManager;
////
//// }
//
// @Override
// public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
//// log.info("run gendreau postopt");
// VehicleRoutingProblemSolution bestSolution = vrpSolution;
// int itersWithoutImprovement = 0;
//
// for(int i=0;i<nOfIterations;i++){
// List<VehicleRoute> copiedRoutes = copyRoutes(bestSolution.getRoutes());
// iniFleet(copiedRoutes);
//
// VehicleRoute route2split = pickRouteThatHasAtLeastTwoJobs(copiedRoutes);
// if(route2split == null) continue;
// List<Job> jobsInRoute = getJobs(route2split);
// Set<Job> unassignedJobs = new HashSet<Job>();
// unassignedJobs.addAll(jobsInRoute);
// copiedRoutes.remove(route2split);
//
// Collections.shuffle(jobsInRoute,random);
// Job targetJob = jobsInRoute.get(0);
// int nOfJobs2BeRemovedAdditionally = (int) (shareOfJobsToRuin*(double)vrp.getJobs().size());
// Collection<Job> unassignedJobsList = ruin.ruin(copiedRoutes, targetJob, nOfJobs2BeRemovedAdditionally);
// unassignedJobs.addAll(unassignedJobsList);
//
// VehicleRoute emptyRoute1 = VehicleRoute.emptyRoute();
// copiedRoutes.add(emptyRoute1);
// insertionStrategy.insertJobs(Arrays.asList(emptyRoute1), Arrays.asList(targetJob));
//
// unassignedJobs.remove(targetJob);
//
// VehicleRoute emptyRoute2 = VehicleRoute.emptyRoute();
// copiedRoutes.add(emptyRoute2);
// Job job2 = jobsInRoute.get(1);
// insertionStrategy.insertJobs(Arrays.asList(emptyRoute2), Arrays.asList(job2));
//
// unassignedJobs.remove(job2);
//
// insertionStrategy.insertJobs(copiedRoutes, unassignedJobs);
// double cost = getCost(copiedRoutes);
//
// if(cost < bestSolution.getCost()){
//// log.info("BING - new: " + cost + " old: " + bestSolution.getCost());
// bestSolution = new VehicleRoutingProblemSolution(copiedRoutes, cost);
// itersWithoutImprovement=0;
// }
// else{
// itersWithoutImprovement++;
// if(itersWithoutImprovement > 200){
//// log.info("BREAK i="+i);
// break;
// }
// }
// }
// return bestSolution;
// }
//
// private List<VehicleRoute> copyRoutes(Collection<VehicleRoute> routes) {
// List<VehicleRoute> routeList = new ArrayList<VehicleRoute>();
// for(VehicleRoute r : routes){
// routeList.add(VehicleRoute.copyOf(r));
// }
// return routeList;
// }
//
// private void iniFleet(Collection<VehicleRoute> routes) {
// fleetManager.unlockAll();
// for(VehicleRoute route : routes){
// if(!route.isEmpty()){
// fleetManager.lock(route.getVehicle());
// }
// }
// }
//
// private double getCost(Collection<VehicleRoute> routes) {
// double c = 0.0;
// for(VehicleRoute r : routes){
// c+=r.getCost();
// }
// return c;
// }
//
// private List<Job> getJobs(VehicleRoute route2split) {
// Set<Job> jobs = new HashSet<Job>();
// for(TourActivity act : route2split.getTourActivities().getActivities()){
// if(act instanceof JobActivity){
// jobs.add(((JobActivity) act).getJob());
// }
// }
// return new ArrayList<Job>(jobs);
// }
//
// private VehicleRoute pickRouteThatHasAtLeastTwoJobs(Collection<VehicleRoute> routeList) {
// List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
// for(VehicleRoute r : routeList){
// if(getJobs(r).size() > 1){
// routes.add(r);
// }
// }
// if(routes.isEmpty()) return null;
// Collections.shuffle(routes,random);
// return routes.get(0);
// }
//
// @Override
// public String getName() {
// return NAME;
// }
//
// @Override
// public void addModuleListener(SearchStrategyModuleListener moduleListener) {
// if(moduleListener instanceof InsertionListener){
// InsertionListener iListener = (InsertionListener) moduleListener;
// if(!insertionStrategy.getListeners().contains(iListener)){
// insertionStrategy.addListener(iListener);
// }
// }
// if(moduleListener instanceof RuinListener){
// RuinListener rListener = (RuinListener) moduleListener;
// if(!ruin.getListeners().contains(rListener)){
// ruin.addListener(rListener);
// }
// }
//
// }
//}

View file

@ -14,18 +14,21 @@
* 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 algorithms;
package jsprit.core.algorithm.module;
import java.util.Collection;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionListener;
import basics.algo.SearchStrategyModule;
import basics.algo.SearchStrategyModuleListener;
import jsprit.core.algorithm.SearchStrategyModule;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.ruin.RuinStrategy;
import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
class RuinAndRecreateModule implements SearchStrategyModule{
public class RuinAndRecreateModule implements SearchStrategyModule{
private InsertionStrategy insertion;
@ -44,9 +47,8 @@ class RuinAndRecreateModule implements SearchStrategyModule{
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs);
// double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
// vrpSolution.setCost(totalCost);
return vrpSolution;
}
@Override

View file

@ -18,13 +18,14 @@
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import basics.route.TourActivity;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.activity.TourActivity;
interface ActivityInsertionCostsCalculator {
public interface ActivityInsertionCostsCalculator {
class ActivityInsertionCosts {
public class ActivityInsertionCosts {
private double additionalCosts;
private double additionalTime;
@ -50,6 +51,6 @@ interface ActivityInsertionCostsCalculator {
}
ActivityInsertionCosts calculate(InsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct);
public ActivityInsertionCosts getCosts(JobInsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct);
}

View file

@ -14,16 +14,17 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import java.util.Iterator;
import java.util.List;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.TourActivity;
import basics.route.Vehicle;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
final class AuxilliaryCostCalculator {

View file

@ -14,7 +14,7 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.Collection;
@ -22,15 +22,17 @@ import java.util.Collections;
import java.util.List;
import java.util.Random;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.recreate.listener.InsertionListeners;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.util.RandomNumberGeneration;
import org.apache.log4j.Logger;
import util.RandomNumberGeneration;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.algo.InsertionListener;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
@ -42,6 +44,28 @@ import basics.route.VehicleRoute;
final class BestInsertion implements InsertionStrategy{
class Insertion {
private final VehicleRoute route;
private final InsertionData insertionData;
public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) {
super();
this.route = vehicleRoute;
this.insertionData = insertionData;
}
public VehicleRoute getRoute() {
return route;
}
public InsertionData getInsertionData() {
return insertionData;
}
}
private static Logger logger = Logger.getLogger(BestInsertion.class);
private Random random = RandomNumberGeneration.getRandom();
@ -56,7 +80,7 @@ final class BestInsertion implements InsertionStrategy{
private Inserter inserter;
private JobInsertionCalculator bestInsertionCostCalculator;
private JobInsertionCostsCalculator bestInsertionCostCalculator;
private boolean minVehiclesFirst = false;
@ -64,7 +88,7 @@ final class BestInsertion implements InsertionStrategy{
this.random = random;
}
public BestInsertion(JobInsertionCalculator jobInsertionCalculator) {
public BestInsertion(JobInsertionCostsCalculator jobInsertionCalculator) {
super();
this.insertionsListeners = new InsertionListeners();
inserter = new Inserter(insertionsListeners);
@ -86,7 +110,7 @@ final class BestInsertion implements InsertionStrategy{
Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE;
for(VehicleRoute vehicleRoute : vehicleRoutes){
InsertionData iData = bestInsertionCostCalculator.calculate(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(iData instanceof NoInsertionFound) {
continue;
}
@ -97,7 +121,7 @@ final class BestInsertion implements InsertionStrategy{
}
if(!minVehiclesFirst){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
InsertionData newIData = bestInsertionCostCalculator.calculate(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(newIData.getInsertionCost() < bestInsertionCost){
bestInsertion = new Insertion(newRoute,newIData);
bestInsertionCost = newIData.getInsertionCost();
@ -106,7 +130,7 @@ final class BestInsertion implements InsertionStrategy{
}
if(bestInsertion == null){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
InsertionData bestI = bestInsertionCostCalculator.calculate(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
InsertionData bestI = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
if(bestI instanceof InsertionData.NoInsertionFound){
throw new IllegalStateException(getErrorMsg(unassignedJob));
}
@ -115,9 +139,8 @@ final class BestInsertion implements InsertionStrategy{
vehicleRoutes.add(newRoute);
}
}
// logger.info("insert " + unassignedJob + " pickup@" + bestInsertion.getInsertionData().getPickupInsertionIndex() + " delivery@" + bestInsertion.getInsertionData().getDeliveryInsertionIndex());
inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
}
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
}

View file

@ -0,0 +1,137 @@
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.state.StateManager;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.vehicle.VehicleFleetManager;
public class BestInsertionBuilder {
private VehicleRoutingProblem vrp;
private StateManager stateManager;
private boolean local = true;
private ConstraintManager constraintManager;
private VehicleFleetManager fleetManager;
private double weightOfFixedCosts;
private boolean considerFixedCosts = false;
private ActivityInsertionCostsCalculator actInsertionCostsCalculator = null;
private int forwaredLooking;
private int memory;
private ExecutorService executor;
private int nuOfThreads;
private double timeSlice;
private int nNeighbors;
private boolean timeScheduling=false;
public BestInsertionBuilder(VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManager stateManager, ConstraintManager constraintManager) {
super();
this.vrp = vrp;
this.stateManager = stateManager;
this.constraintManager = constraintManager;
this.fleetManager = vehicleFleetManager;
}
public BestInsertionBuilder setRouteLevel(int forwardLooking, int memory){
local = false;
this.forwaredLooking = forwardLooking;
this.memory = memory;
return this;
};
public BestInsertionBuilder setLocalLevel(){
local = true;
return this;
};
public BestInsertionBuilder considerFixedCosts(double weightOfFixedCosts){
this.weightOfFixedCosts = weightOfFixedCosts;
this.considerFixedCosts = true;
return this;
}
public BestInsertionBuilder setActivityInsertionCostCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){
this.actInsertionCostsCalculator = activityInsertionCostsCalculator;
return this;
};
public BestInsertionBuilder setConcurrentMode(ExecutorService executor, int nuOfThreads){
this.executor = executor;
this.nuOfThreads = nuOfThreads;
return this;
}
public InsertionStrategy build() {
List<InsertionListener> iListeners = new ArrayList<InsertionListener>();
List<PrioritizedVRAListener> algorithmListeners = new ArrayList<PrioritizedVRAListener>();
CalculatorBuilder calcBuilder = new CalculatorBuilder(iListeners, algorithmListeners);
if(local){
calcBuilder.setLocalLevel();
}
else {
calcBuilder.setRouteLevel(forwaredLooking, memory);
}
calcBuilder.setConstraintManager(constraintManager);
calcBuilder.setStates(stateManager);
calcBuilder.setVehicleRoutingProblem(vrp);
calcBuilder.setVehicleFleetManager(fleetManager);
calcBuilder.setActivityInsertionCostsCalculator(actInsertionCostsCalculator);
if(considerFixedCosts) {
calcBuilder.considerFixedCosts(weightOfFixedCosts);
}
if(timeScheduling){
calcBuilder.experimentalTimeScheduler(timeSlice, nNeighbors);
}
JobInsertionCostsCalculator jobInsertions = calcBuilder.build();
InsertionStrategy bestInsertion;
if(executor == null){
bestInsertion = new BestInsertion(jobInsertions);
}
else{
bestInsertion = new BestInsertionConcurrent(jobInsertions,executor,nuOfThreads);
}
for(InsertionListener l : iListeners) bestInsertion.addListener(l);
return bestInsertion;
}
/**
* @deprecated this is experimental and can disappear.
* @param parseDouble
* @param parseInt
*/
@Deprecated
public void experimentalTimeScheduler(double timeSlice, int nNeighbors) {
this.timeSlice=timeSlice;
this.nNeighbors=nNeighbors;
timeScheduling=true;
}
}

View file

@ -0,0 +1,266 @@
/*******************************************************************************
* Copyright (C) 2013 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.recreate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.recreate.listener.InsertionListeners;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.util.RandomNumberGeneration;
import org.apache.log4j.Logger;
/**
*
* @author stefan schroeder
*
*/
final class BestInsertionConcurrent implements InsertionStrategy{
static class Batch {
List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
}
class Insertion {
private final VehicleRoute route;
private final InsertionData insertionData;
public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) {
super();
this.route = vehicleRoute;
this.insertionData = insertionData;
}
public VehicleRoute getRoute() {
return route;
}
public InsertionData getInsertionData() {
return insertionData;
}
}
private static Logger logger = Logger.getLogger(BestInsertionConcurrent.class);
private Random random = RandomNumberGeneration.getRandom();
private final static double NO_NEW_DEPARTURE_TIME_YET = -12345.12345;
private final static Vehicle NO_NEW_VEHICLE_YET = null;
private final static Driver NO_NEW_DRIVER_YET = null;
private InsertionListeners insertionsListeners;
private Inserter inserter;
private JobInsertionCostsCalculator bestInsertionCostCalculator;
private boolean minVehiclesFirst = false;
private int nuOfBatches;
private ExecutorService executor;
private ExecutorCompletionService<Insertion> completionService;
public void setRandom(Random random) {
this.random = random;
}
public BestInsertionConcurrent(JobInsertionCostsCalculator jobInsertionCalculator, ExecutorService executorService, int nuOfBatches) {
super();
this.insertionsListeners = new InsertionListeners();
this.executor = executorService;
this.nuOfBatches = nuOfBatches;
inserter = new Inserter(insertionsListeners);
bestInsertionCostCalculator = jobInsertionCalculator;
completionService = new ExecutorCompletionService<Insertion>(executor);
logger.info("initialise " + this);
}
@Override
public String toString() {
return "[name=bestInsertion]";
}
@Override
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs);
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
Collections.shuffle(unassignedJobList, random);
List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
for(final Job unassignedJob : unassignedJobList){
Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE;
for(final Batch batch : batches){
completionService.submit(new Callable<Insertion>() {
@Override
public Insertion call() throws Exception {
return getBestInsertion(batch,unassignedJob);
}
});
}
try{
for(int i=0;i<batches.size();i++){
Future<Insertion> futureIData = completionService.take();
Insertion insertion = futureIData.get();
if(insertion == null) continue;
if(insertion.getInsertionData().getInsertionCost() < bestInsertionCost){
bestInsertion = insertion;
bestInsertionCost = insertion.getInsertionData().getInsertionCost();
}
}
}
catch(InterruptedException e){
Thread.currentThread().interrupt();
}
catch (ExecutionException e) {
e.printStackTrace();
logger.error(e.getCause().toString());
System.exit(1);
}
if(!minVehiclesFirst){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(newIData.getInsertionCost() < bestInsertionCost){
bestInsertion = new Insertion(newRoute,newIData);
bestInsertionCost = newIData.getInsertionCost();
vehicleRoutes.add(newRoute);
batches.get(random.nextInt(batches.size())).routes.add(newRoute);
}
}
if(bestInsertion == null){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
InsertionData bestI = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
if(bestI instanceof InsertionData.NoInsertionFound){
throw new IllegalStateException(getErrorMsg(unassignedJob));
}
else{
bestInsertion = new Insertion(newRoute,bestI);
vehicleRoutes.add(newRoute);
}
}
// logger.info("insert " + unassignedJob + " pickup@" + bestInsertion.getInsertionData().getPickupInsertionIndex() + " delivery@" + bestInsertion.getInsertionData().getDeliveryInsertionIndex());
inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
}
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
}
private String getErrorMsg(Job unassignedJob) {
return "given the vehicles, could not insert job\n" +
"\t" + unassignedJob +
"\n\tthis might have the following reasons:\n" +
"\t- no vehicle has the capacity to transport the job [check whether there is at least one vehicle that is capable to transport the job]\n" +
"\t- the time-window cannot be met, even in a commuter tour the time-window is missed [check whether it is possible to reach the time-window on the shortest path or make hard time-windows soft]\n" +
"\t- if you deal with finite vehicles, and the available vehicles are already fully employed, no vehicle can be found anymore to transport the job [add penalty-vehicles]";
}
@Override
public void removeListener(InsertionListener insertionListener) {
insertionsListeners.removeListener(insertionListener);
}
@Override
public Collection<InsertionListener> getListeners() {
return Collections.unmodifiableCollection(insertionsListeners.getListeners());
}
@Override
public void addListener(InsertionListener insertionListener) {
insertionsListeners.addListener(insertionListener);
}
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE;
for(VehicleRoute vehicleRoute : batch.routes){
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(iData instanceof NoInsertionFound) {
continue;
}
if(iData.getInsertionCost() < bestInsertionCost){
bestInsertion = new Insertion(vehicleRoute,iData);
bestInsertionCost = iData.getInsertionCost();
}
}
return bestInsertion;
}
private List<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
List<Batch> batches = new ArrayList<Batch>();
for(int i=0;i<nuOfBatches;i++) batches.add(new Batch());
/*
* if route.size < nuOfBatches add as much routes as empty batches are available
* else add one empty route anyway
*/
if(vehicleRoutes.size()<nuOfBatches){
int nOfNewRoutes = nuOfBatches-vehicleRoutes.size();
for(int i=0;i<nOfNewRoutes;i++){
vehicleRoutes.add(VehicleRoute.emptyRoute());
}
}
else{
vehicleRoutes.add(VehicleRoute.emptyRoute());
}
/*
* distribute routes to batches equally
*/
int count = 0;
for(VehicleRoute route : vehicleRoutes){
if(count == nuOfBatches) count=0;
batches.get(count).routes.add(route);
count++;
}
return batches;
}
}

View file

@ -14,30 +14,27 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import org.apache.log4j.Logger;
import basics.Job;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
/**
* This is experimental. It ignores vehicles' earliestStartTime.
*
* @author schroeder
*
*/
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalculator{
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator{
private static Logger log = Logger.getLogger(CalculatesServiceInsertionWithTimeScheduling.class);
private JobInsertionCalculator jic;
private JobInsertionCostsCalculator jic;
private Random random = new Random();
@ -45,7 +42,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
private double timeSlice = 900.0;
public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCalculator jic, double timeSlice, int neighbors) {
public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCostsCalculator jic, double timeSlice, int neighbors) {
super();
this.jic = jic;
this.timeSlice = timeSlice;
@ -59,7 +56,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
}
@Override
public InsertionData calculate(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
List<Double> vehicleDepartureTimes = new ArrayList<Double>();
double currentStart;
if(currentRoute.getStart() == null){
@ -84,7 +81,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
InsertionData bestIData = null;
for(Double departureTime : vehicleDepartureTimes){
InsertionData iData = jic.calculate(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
InsertionData iData = jic.getInsertionData(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
if(bestIData == null) bestIData = iData;
else if(iData.getInsertionCost() < bestIData.getInsertionCost()){
iData.setVehicleDepartureTime(departureTime);

View file

@ -14,15 +14,23 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.List;
import algorithms.HardConstraints.ConstraintManager;
import basics.VehicleRoutingProblem;
import basics.algo.InsertionListener;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.job.Delivery;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.vehicle.VehicleFleetManager;
@ -30,16 +38,16 @@ class CalculatorBuilder {
private static class CalculatorPlusListeners {
private JobInsertionCalculator calculator;
private JobInsertionCostsCalculator calculator;
public JobInsertionCalculator getCalculator() {
public JobInsertionCostsCalculator getCalculator() {
return calculator;
}
private List<PrioritizedVRAListener> algorithmListener = new ArrayList<PrioritizedVRAListener>();
private List<InsertionListener> insertionListener = new ArrayList<InsertionListener>();
public CalculatorPlusListeners(JobInsertionCalculator calculator) {
public CalculatorPlusListeners(JobInsertionCostsCalculator calculator) {
super();
this.calculator = calculator;
}
@ -59,7 +67,7 @@ class CalculatorBuilder {
private VehicleRoutingProblem vrp;
private StateManager states;
private RouteAndActivityStateGetter states;
private boolean local = true;
@ -80,6 +88,8 @@ class CalculatorBuilder {
private int neighbors;
private ConstraintManager constraintManager;
private ActivityInsertionCostsCalculator activityInsertionCostCalculator = null;
/**
* Constructs the builder.
@ -102,7 +112,7 @@ class CalculatorBuilder {
*
* @return
*/
public CalculatorBuilder setStates(StateManager states){
public CalculatorBuilder setStates(RouteAndActivityStateGetter states){
this.states = states;
return this;
}
@ -137,6 +147,10 @@ class CalculatorBuilder {
public void setLocalLevel(){
local = true;
}
public void setActivityInsertionCostsCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){
this.activityInsertionCostCalculator = activityInsertionCostsCalculator;
}
/**
* Sets a flag to build a calculator that evaluates job insertion on route-level.
@ -173,16 +187,17 @@ class CalculatorBuilder {
* @return jobInsertionCalculator.
* @throws IllegalStateException if vrp == null or activityStates == null or fleetManager == null.
*/
public JobInsertionCalculator build(){
public JobInsertionCostsCalculator build(){
if(vrp == null) throw new IllegalStateException("vehicle-routing-problem is null, but it must be set (this.setVehicleRoutingProblem(vrp))");
if(states == null) throw new IllegalStateException("states is null, but is must be set (this.setStates(states))");
if(fleetManager == null) throw new IllegalStateException("fleetManager is null, but it must be set (this.setVehicleFleetManager(fleetManager))");
JobInsertionCalculator baseCalculator = null;
JobInsertionCostsCalculator baseCalculator = null;
CalculatorPlusListeners standardLocal = null;
if(local){
standardLocal = createStandardLocal(vrp, states);
}
else{
checkServicesOnly();
standardLocal = createStandardRoute(vrp, states,forwardLooking,memory);
}
baseCalculator = standardLocal.getCalculator();
@ -200,6 +215,17 @@ class CalculatorBuilder {
return createFinalInsertion(fleetManager, baseCalculator, states);
}
private void checkServicesOnly() {
for(Job j : vrp.getJobs().values()){
if(j instanceof Shipment){
throw new UnsupportedOperationException("currently the 'insert-on-route-level' option is only available for services (i.e. service, pickup, delivery), \n" +
"if you want to deal with shipments switch to option 'local-level' by either setting bestInsertionBuilder.setLocalLevel() or \n"
+ "by omitting the xml-tag '<level forwardLooking=2 memory=1>route</level>' when defining your insertionStrategy in algo-config.xml file");
}
}
}
private void addInsertionListeners(List<InsertionListener> list) {
for(InsertionListener iL : list){
insertionListeners.add(iL);
@ -212,40 +238,62 @@ class CalculatorBuilder {
}
}
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager statesManager){
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, RouteAndActivityStateGetter statesManager){
if(constraintManager == null) throw new IllegalStateException("constraint-manager is null");
ActivityInsertionCostsCalculator defaultCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager);
JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), defaultCalc, constraintManager);
ActivityInsertionCostsCalculator actInsertionCalc;
if(activityInsertionCostCalculator == null){
actInsertionCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts());
}
else{
actInsertionCalc = activityInsertionCostCalculator;
}
ShipmentInsertionCalculator shipmentInsertion = new ShipmentInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
switcher.put(Shipment.class, shipmentInsertion);
switcher.put(Service.class, serviceInsertion);
switcher.put(Pickup.class, serviceInsertion);
switcher.put(Delivery.class, serviceInsertion);
// JobInsertionCostsCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
// ((ServiceInsertionCalculator) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(switcher);
return calcPlusListeners;
}
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, StateManager activityStates2, double weightOfFixedCosts){
final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates2);
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCostsCalculator baseCalculator, RouteAndActivityStateGetter activityStates2, double weightOfFixedCosts){
final JobInsertionConsideringFixCostsCalculator withFixCost = new JobInsertionConsideringFixCostsCalculator(baseCalculator, activityStates2);
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
return calcPlusListeners;
}
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StateManager activityStates2, int forwardLooking, int solutionMemory){
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, RouteAndActivityStateGetter activityStates2, int forwardLooking, int solutionMemory){
int after = forwardLooking;
ActivityInsertionCostsCalculator routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, activityStates2);
JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, routeLevelCostEstimator);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNuOfActsForwardLooking(after);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setMemorySize(solutionMemory);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setStates(activityStates2);
ActivityInsertionCostsCalculator routeLevelCostEstimator;
if(activityInsertionCostCalculator == null){
routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityStates2);
}
else{
routeLevelCostEstimator = activityInsertionCostCalculator;
}
JobInsertionCostsCalculator jobInsertionCalculator = new ServiceInsertionOnRouteLevelCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), routeLevelCostEstimator, constraintManager, constraintManager);
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setNuOfActsForwardLooking(after);
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setMemorySize(solutionMemory);
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
((ServiceInsertionOnRouteLevelCalculator) jobInsertionCalculator).setStates(activityStates2);
CalculatorPlusListeners calcPlusListener = new CalculatorPlusListeners(jobInsertionCalculator);
return calcPlusListener;
}
private JobInsertionCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCalculator baseCalc, StateManager activityStates2){
return new CalculatesVehTypeDepServiceInsertion(fleetManager, baseCalc);
private JobInsertionCostsCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCostsCalculator baseCalc, RouteAndActivityStateGetter activityStates2){
return new VehicleTypeDependentJobInsertionCalculator(fleetManager, baseCalc);
}
public void setConstraintManager(ConstraintManager constraintManager) {

View file

@ -14,18 +14,19 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import java.util.Collection;
import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
import jsprit.core.algorithm.recreate.listener.JobInsertedListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import org.apache.log4j.Logger;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.route.VehicleRoute;
@ -37,11 +38,11 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn
VehicleRoutingProblem vrp;
CalculatesServiceInsertionConsideringFixCost calcConsideringFix;
JobInsertionConsideringFixCostsCalculator calcConsideringFix;
private int nuOfJobsToRecreate;
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, CalculatesServiceInsertionConsideringFixCost calcConsideringFix) {
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, JobInsertionConsideringFixCostsCalculator calcConsideringFix) {
super();
this.vrp = vrp;
this.calcConsideringFix = calcConsideringFix;

View file

@ -0,0 +1,122 @@
/*******************************************************************************
* Copyright (C) 2013 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.recreate;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.algorithm.recreate.listener.InsertionListeners;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.DefaultShipmentActivityFactory;
import jsprit.core.problem.solution.route.activity.DefaultTourActivityFactory;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.activity.TourActivityFactory;
import jsprit.core.problem.solution.route.activity.TourShipmentActivityFactory;
class Inserter {
interface JobInsertionHandler {
void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route);
void setNextHandler(JobInsertionHandler handler);
}
class JobExceptionHandler implements JobInsertionHandler{
@Override
public void handleJobInsertion(Job job, InsertionData iData,VehicleRoute route) {
throw new IllegalStateException("job insertion is not supported. Do not know job type.");
}
@Override
public void setNextHandler(JobInsertionHandler handler) {
// TODO Auto-generated method stub
}
}
class ServiceInsertionHandler implements JobInsertionHandler{
private TourActivityFactory activityFactory = new DefaultTourActivityFactory();
private JobInsertionHandler delegator = new JobExceptionHandler();
@Override
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
if(job instanceof Service){
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), this.activityFactory.createActivity((Service)job));
route.setDepartureTime(iData.getVehicleDepartureTime());
}
else delegator.handleJobInsertion(job, iData, route);
}
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
this.delegator = jobInsertionHandler;
}
}
class ShipmentInsertionHandler implements JobInsertionHandler {
private TourShipmentActivityFactory activityFactory = new DefaultShipmentActivityFactory();
private JobInsertionHandler delegator = new JobExceptionHandler();
@Override
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
if(job instanceof Shipment){
TourActivity pickupShipment = this.activityFactory.createPickup((Shipment)job);
TourActivity deliverShipment = this.activityFactory.createDelivery((Shipment)job);
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), deliverShipment);
route.getTourActivities().addActivity(iData.getPickupInsertionIndex(), pickupShipment);
route.setDepartureTime(iData.getVehicleDepartureTime());
}
else delegator.handleJobInsertion(job, iData, route);
}
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
this.delegator = jobInsertionHandler;
}
}
private InsertionListeners insertionListeners;
private JobInsertionHandler jobInsertionHandler;
public Inserter(InsertionListeners insertionListeners) {
this.insertionListeners = insertionListeners;
new DefaultTourActivityFactory();
jobInsertionHandler = new ServiceInsertionHandler();
jobInsertionHandler.setNextHandler(new ShipmentInsertionHandler());
}
public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute){
insertionListeners.informBeforeJobInsertion(job, insertionData, vehicleRoute);
if(insertionData == null || (insertionData instanceof NoInsertionFound)) throw new IllegalStateException("insertionData null. cannot insert job.");
if(job == null) throw new IllegalStateException("cannot insert null-job");
if(!(vehicleRoute.getVehicle().getId().toString().equals(insertionData.getSelectedVehicle().getId().toString()))){
insertionListeners.informVehicleSwitched(vehicleRoute, vehicleRoute.getVehicle(), insertionData.getSelectedVehicle());
vehicleRoute.setVehicle(insertionData.getSelectedVehicle(), insertionData.getVehicleDepartureTime());
}
jobInsertionHandler.handleJobInsertion(job, insertionData, vehicleRoute);
insertionListeners.informJobInserted(job, vehicleRoute, insertionData.getInsertionCost(), insertionData.getAdditionalTime());
}
}

View file

@ -14,14 +14,19 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import basics.route.Driver;
import basics.route.Vehicle;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.vehicle.Vehicle;
class InsertionData {
/**
* Data object that collects insertion information. It collects insertionCosts, insertionIndeces, vehicle and driver to be employed
* and departureTime of vehicle at vehicle's start location (e.g. depot).
*
* @author stefan
*
*/
public class InsertionData {
static class NoInsertionFound extends InsertionData{
@ -33,7 +38,15 @@ class InsertionData {
private static InsertionData noInsertion = new NoInsertionFound();
public static InsertionData noInsertionFound(){
/**
* Returns an instance of InsertionData that represents an EmptyInsertionData (which might indicate
* that no insertion has been found). It is internally instantiated as follows:<br>
* <code>new InsertionData(Double.MAX_VALUE, NO_INDEX, NO_INDEX, null, null);</code><br>
* where NO_INDEX=-1.
*
* @return
*/
public static InsertionData createEmptyInsertionData(){
return noInsertion;
}
@ -80,22 +93,47 @@ class InsertionData {
return "[iCost="+insertionCost+"][iIndex="+deliveryInsertionIndex+"][depTime="+departureTime+"][vehicle="+selectedVehicle+"][driver="+selectedDriver+"]";
}
/**
* Returns insertionIndex of deliveryActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
*
* @return
*/
public int getDeliveryInsertionIndex(){
return deliveryInsertionIndex;
}
/**
* Returns insertionIndex of pickkupActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
*
* @return
*/
public int getPickupInsertionIndex(){
return pickupInsertionIndex;
}
/**
* Returns insertion costs (which might be the additional costs of inserting the corresponding job).
*
* @return
*/
public double getInsertionCost() {
return insertionCost;
}
/**
* Returns the vehicle to be employed.
*
* @return
*/
public Vehicle getSelectedVehicle() {
return selectedVehicle;
}
/**
* Returns the vehicle to be employed.
*
* @return
*/
public Driver getSelectedDriver(){
return selectedDriver;
}

View file

@ -14,13 +14,14 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import java.util.Collection;
import basics.Job;
import basics.algo.InsertionListener;
import basics.route.VehicleRoute;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
@ -31,33 +32,7 @@ import basics.route.VehicleRoute;
*
*/
interface InsertionStrategy {
class Insertion {
private final VehicleRoute route;
private final InsertionData insertionData;
public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) {
super();
this.route = vehicleRoute;
this.insertionData = insertionData;
}
public VehicleRoute getRoute() {
return route;
}
public InsertionData getInsertionData() {
return insertionData;
}
}
public interface InsertionStrategy {
/**
* Assigns the unassigned jobs to service-providers

View file

@ -14,11 +14,11 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import basics.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem;
interface InsertionStrategyFactory {
public interface InsertionStrategyFactory {
public InsertionStrategy createStrategy(VehicleRoutingProblem vrp);

View file

@ -0,0 +1,26 @@
package jsprit.core.algorithm.recreate;
import java.util.HashMap;
import java.util.Map;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
class JobCalculatorSwitcher implements JobInsertionCostsCalculator{
private Map<Class<? extends Job>,JobInsertionCostsCalculator> calcMap = new HashMap<Class<? extends Job>, JobInsertionCostsCalculator>();
void put(Class<? extends Job> jobClass, JobInsertionCostsCalculator jic){
calcMap.put(jobClass, jic);
}
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore){
JobInsertionCostsCalculator jic = calcMap.get(jobToInsert.getClass());
if(jic==null) throw new IllegalStateException("cannot find calculator for " + jobToInsert.getClass());
return jic.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownScore);
}
}

View file

@ -14,48 +14,51 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.solution.route.state.StateFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import org.apache.log4j.Logger;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class CalculatesServiceInsertionConsideringFixCost implements JobInsertionCalculator{
final class JobInsertionConsideringFixCostsCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionConsideringFixCost.class);
private static final Logger logger = Logger.getLogger(JobInsertionConsideringFixCostsCalculator.class);
private final JobInsertionCalculator standardServiceInsertion;
private final JobInsertionCostsCalculator standardServiceInsertion;
private double weight_deltaFixCost = 0.5;
private double solution_completeness_ratio = 0.5;
private StateManager states;
private RouteAndActivityStateGetter stateGetter;
public CalculatesServiceInsertionConsideringFixCost(final JobInsertionCalculator standardInsertionCalculator, StateManager activityStates2) {
public JobInsertionConsideringFixCostsCalculator(final JobInsertionCostsCalculator standardInsertionCalculator, RouteAndActivityStateGetter stateGetter) {
super();
this.standardServiceInsertion = standardInsertionCalculator;
this.states = activityStates2;
this.stateGetter = stateGetter;
logger.info("inialise " + this);
}
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) {
double relFixCost = getDeltaRelativeFixCost(currentRoute, newVehicle, jobToInsert);
double absFixCost = getDeltaAbsoluteFixCost(currentRoute, newVehicle, jobToInsert);
double deltaFixCost = (1-solution_completeness_ratio)*relFixCost + solution_completeness_ratio*absFixCost;
double fixcost_contribution = weight_deltaFixCost*solution_completeness_ratio*deltaFixCost;
if(fixcost_contribution > bestKnownPrice){
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
InsertionData iData = standardServiceInsertion.calculate(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice);
InsertionData iData = standardServiceInsertion.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice);
if(iData instanceof NoInsertionFound){
return iData;
}
@ -80,7 +83,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
}
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
double load = getCurrentLoad(route) + job.getCapacityDemand();
double load = getCurrentMaxLoadInRoute(route) + job.getCapacityDemand();
double currentFix = 0.0;
if(route.getVehicle() != null){
if(!(route.getVehicle() instanceof NoVehicle)){
@ -94,7 +97,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
}
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
int currentLoad = getCurrentLoad(route);
int currentLoad = getCurrentMaxLoadInRoute(route);
double load = currentLoad + job.getCapacityDemand();
double currentRelFix = 0.0;
if(route.getVehicle() != null){
@ -109,8 +112,8 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
return relativeFixCost;
}
private int getCurrentLoad(VehicleRoute route) {
return (int) states.getRouteState(route, StateTypes.LOAD).toDouble();
private int getCurrentMaxLoadInRoute(VehicleRoute route) {
return (int) stateGetter.getRouteState(route, StateFactory.MAXLOAD).toDouble();
}
}

View file

@ -14,16 +14,16 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import basics.Job;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
interface JobInsertionCalculator {
public interface JobInsertionCostsCalculator {
public InsertionData calculate(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore);
public InsertionData getInsertionData(VehicleRoute currentRoute, Job newJob, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownCosts);
}

View file

@ -18,39 +18,46 @@
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import algorithms.HardConstraints.HardActivityLevelConstraint;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.TourActivity;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.util.CalculationUtils;
/**
* Calculates activity insertion costs locally, i.e. by comparing the additional costs of insertion the new activity k between
* activity i (prevAct) and j (nextAct).
* Additional costs are then basically calculated as delta c = c_ik + c_kj - c_ij.
*
* <p>Note once time has an effect on costs this class requires activity endTimes.
*
* @author stefan
*
*/
class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator{
private HardActivityLevelConstraint hardConstraint;
private VehicleRoutingTransportCosts routingCosts;
private VehicleRoutingActivityCosts activityCosts;
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint) {
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts) {
super();
this.routingCosts = routingCosts;
this.activityCosts = actCosts;
this.hardConstraint = hardActivityLevelConstraint;
}
@Override
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){
return null;
}
public ActivityInsertionCosts getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
double newAct_endTime = CalcUtils.getActivityEndTime(newAct_arrTime, newAct);
double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct);
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
@ -66,8 +73,12 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
double oldCosts;
double oldTime;
if(iFacts.getRoute().isEmpty()){
oldCosts = 0.0;
oldTime = 0.0;
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
oldTime = (nextAct.getArrTime() - depTimeAtPrevAct);
}
else{
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());

View file

@ -1,3 +1,4 @@
package jsprit.core.algorithm.recreate;
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*

View file

@ -1,3 +1,4 @@
package jsprit.core.algorithm.recreate;
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*

View file

@ -18,45 +18,41 @@
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.List;
import algorithms.HardConstraints.HardActivityLevelConstraint;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.Start;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.solution.route.state.StateFactory;
class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCostsCalculator{
private HardActivityLevelConstraint hardConstraint;
private VehicleRoutingActivityCosts activityCosts;
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
private StateManager stateManager;
private RouteAndActivityStateGetter stateManager;
private int nuOfActivities2LookForward = 0;
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint, StateManager stateManager) {
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, RouteAndActivityStateGetter stateManager) {
super();
this.activityCosts = actCosts;
this.hardConstraint = hardActivityLevelConstraint;
this.stateManager = stateManager;
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts);
}
@Override
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){
return null;
}
public ActivityInsertionCosts getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
List<TourActivity> path = new ArrayList<TourActivity>();
path.add(prevAct); path.add(newAct); path.add(nextAct);
int actIndex;
@ -77,9 +73,9 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) {
if(act instanceof End){
return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble();
return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble();
}
return stateManager.getActivityState(act,StateTypes.COSTS).toDouble();
return stateManager.getActivityState(act,StateFactory.COSTS).toDouble();
}
private List<TourActivity> getForwardLookingPath(VehicleRoute route, int actIndex) {

View file

@ -14,33 +14,40 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import jsprit.core.algorithm.recreate.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint.ConstraintsStatus;
import jsprit.core.problem.constraint.HardRouteStateLevelConstraint;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.DefaultTourActivityFactory;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.Start;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.activity.TourActivityFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import jsprit.core.util.CalculationUtils;
import jsprit.core.util.Neighborhood;
import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import algorithms.HardConstraints.HardRouteLevelConstraint;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DefaultTourActivityFactory;
import basics.route.Driver;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.TourActivityFactory;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class CalculatesServiceInsertion implements JobInsertionCalculator{
final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertion.class);
private static final Logger logger = Logger.getLogger(ServiceInsertionCalculator.class);
private HardRouteLevelConstraint hardRouteLevelConstraint;
private HardRouteStateLevelConstraint hardRouteLevelConstraint;
private HardActivityStateLevelConstraint hardActivityLevelConstraint;
private Neighborhood neighborhood = new Neighborhood() {
@ -61,10 +68,12 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
logger.info("initialise neighborhood " + neighborhood);
}
public CalculatesServiceInsertion(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint) {
public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteStateLevelConstraint hardRouteLevelConstraint, HardActivityStateLevelConstraint hardActivityLevelConstraint) {
super();
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
this.transportCosts = routingCosts;
activityFactory = new DefaultTourActivityFactory();
logger.info("initialise " + this);
@ -81,13 +90,13 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
*
*/
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
double bestCost = bestKnownCosts;
@ -99,17 +108,40 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
End end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
TourActivity prevAct = start;
double prevActStartTime = newVehicleDepartureTime;
int actIndex = 0;
boolean loopBroken = false;
for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc != null){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
bestMarginals = mc;
insertionIndex = actIndex;
}
}
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
loopBroken = true;
break;
}
}
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle);
double nextActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
prevActStartTime = nextActEndTime;
prevAct = nextAct;
actIndex++;
}
End nextAct = end;
if(!loopBroken){
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
bestMarginals = mc;
@ -117,28 +149,10 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
}
}
}
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle);
double nextActEndTime = CalcUtils.getActivityEndTime(nextActArrTime, nextAct);
prevActStartTime = nextActEndTime;
prevAct = nextAct;
actIndex++;
}
End nextAct = end;
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc != null) {
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
bestMarginals = mc;
insertionIndex = actIndex;
}
}
}
if(insertionIndex == InsertionData.NO_INDEX) {
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
@ -146,8 +160,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
return insertionData;
}
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) {
return activityInsertionCostsCalculator.calculate(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
public ActivityInsertionCosts calculate(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) {
return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
}
}

View file

@ -14,7 +14,7 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.Comparator;
@ -23,31 +23,37 @@ import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import jsprit.core.algorithm.recreate.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint.ConstraintsStatus;
import jsprit.core.problem.constraint.HardRouteStateLevelConstraint;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.DefaultTourActivityFactory;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.Start;
import jsprit.core.problem.solution.route.activity.TourActivities;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.activity.TourActivityFactory;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.solution.route.state.StateFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import jsprit.core.util.Neighborhood;
import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import algorithms.HardConstraints.HardRouteLevelConstraint;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DefaultTourActivityFactory;
import basics.route.Driver;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.TourActivityFactory;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalculator{
final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionOnRouteLevel.class);
private static final Logger logger = Logger.getLogger(ServiceInsertionOnRouteLevelCalculator.class);
private final VehicleRoutingTransportCosts transportCosts;
@ -57,9 +63,11 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private TourActivityFactory tourActivityFactory = new DefaultTourActivityFactory();
private StateManager stateManager;
private RouteAndActivityStateGetter stateManager;
private HardRouteLevelConstraint hardRouteLevelConstraint;
private HardRouteStateLevelConstraint hardRouteLevelConstraint;
private HardActivityStateLevelConstraint hardActivityLevelConstraint;
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
@ -94,18 +102,19 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
logger.info("set [solutionMemory="+memorySize+"]");
}
public CalculatesServiceInsertionOnRouteLevel(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, HardRouteLevelConstraint hardRouteLevelConstraint, ActivityInsertionCostsCalculator activityInsertionCostsCalculator) {
public ServiceInsertionOnRouteLevelCalculator(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteStateLevelConstraint hardRouteLevelConstraint, HardActivityStateLevelConstraint hardActivityLevelConstraint) {
super();
this.transportCosts = vehicleRoutingCosts;
this.activityCosts = costFunc;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts);
logger.info("initialise " + this);
}
public void setStates(StateManager stateManager){
public void setStates(RouteAndActivityStateGetter stateManager){
this.stateManager = stateManager;
}
@ -128,13 +137,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
*
*/
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double best_known_insertion_costs) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double best_known_insertion_costs) {
if(jobToInsert == null) throw new IllegalStateException("job is null. cannot calculate the insertion of a null-job.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("no vehicle given. set para vehicle!");
InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
/**
@ -150,6 +159,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
TourActivities tour = currentRoute.getTourActivities();
double best_insertion_costs = best_known_insertion_costs;
Service service = (Service)jobToInsert;
/**
* some inis
@ -164,6 +174,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
double sumOf_prevCosts_newVehicle = 0.0;
double prevActDepTime_newVehicle = start.getEndTime();
boolean loopBroken = false;
/**
* inserting serviceAct2Insert in route r={0,1,...,i-1,i,j,j+1,...,n(r),n(r)+1}
* i=prevAct
@ -172,12 +183,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
*/
for(TourActivity nextAct : tour.getActivities()){
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
/**
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
*/
InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle);
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
if(actInsertionCosts != null){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
if(status.equals(ConstraintsStatus.FULFILLED)){
/**
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
*/
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
/**
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
*/
@ -190,6 +202,10 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
}
}
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
loopBroken = true;
break;
}
}
/**
@ -219,22 +235,25 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
actIndex++;
}
End nextAct = end;
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
if(!loopBroken){
End nextAct = end;
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
if(actInsertionCosts != null){
/**
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
*/
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle);
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
if(actInsertionCosts != null){
/**
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
*/
double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts();
/**
* memorize it in insertion-queue
*/
if(insertion_cost_approximation < best_known_insertion_costs){
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
/**
* memorize it in insertion-queue
*/
if(insertion_cost_approximation < best_known_insertion_costs){
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
}
}
}
}
}
@ -254,6 +273,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
}
}
else{
for(int i=0;i<memorySize;i++){
InsertionData data = bestInsertionsQueue.poll();
if(data == null){
@ -271,7 +291,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
/**
* compute cost-diff of tour with and without new activity --> insertion_costs
*/
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateTypes.COSTS).toDouble();
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateFactory.COSTS).toDouble();
/**
* if better than best known, make it the best known
@ -282,10 +302,8 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
}
}
}
if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.noInsertionFound();
InsertionData insertionData = new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
return insertionData;
if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.createEmptyInsertionData();
return new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
}
/**
@ -318,9 +336,9 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) {
if(act instanceof End){
return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble();
return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble();
}
return stateManager.getActivityState(act,StateTypes.COSTS).toDouble();
return stateManager.getActivityState(act,StateFactory.COSTS).toDouble();
}
/**

View file

@ -0,0 +1,213 @@
/*******************************************************************************
* Copyright (C) 2013 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.recreate;
import java.util.List;
import jsprit.core.algorithm.recreate.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint.ConstraintsStatus;
import jsprit.core.problem.constraint.HardRouteStateLevelConstraint;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.DefaultShipmentActivityFactory;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.Start;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.activity.TourShipmentActivityFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import jsprit.core.util.CalculationUtils;
import jsprit.core.util.Neighborhood;
import org.apache.log4j.Logger;
final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(ShipmentInsertionCalculator.class);
private HardRouteStateLevelConstraint hardRouteLevelConstraint;
private HardActivityStateLevelConstraint hardActivityLevelConstraint;
private Neighborhood neighborhood = new Neighborhood() {
@Override
public boolean areNeighbors(String location1, String location2) {
return true;
}
};
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
private VehicleRoutingTransportCosts transportCosts;
private TourShipmentActivityFactory activityFactory;
public void setNeighborhood(Neighborhood neighborhood) {
this.neighborhood = neighborhood;
logger.info("initialise neighborhood " + neighborhood);
}
public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteStateLevelConstraint hardRouteLevelConstraint, HardActivityStateLevelConstraint hardActivityLevelConstraint) {
super();
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
this.transportCosts = routingCosts;
activityFactory = new DefaultShipmentActivityFactory();
logger.info("initialise " + this);
}
@Override
public String toString() {
return "[name=calculatesServiceInsertion]";
}
/**
* Calculates the marginal cost of inserting job i locally. This is based on the
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
*
*/
@Override
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
if(!(jobToInsert instanceof Shipment)) throw new IllegalStateException("jobToInsert should be of type Shipment!");
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.createEmptyInsertionData();
}
double bestCost = bestKnownCosts;
Shipment shipment = (Shipment)jobToInsert;
TourActivity pickupShipment = activityFactory.createPickup(shipment);
TourActivity deliverShipment = activityFactory.createDelivery(shipment);
int pickupInsertionIndex = InsertionData.NO_INDEX;
int deliveryInsertionIndex = InsertionData.NO_INDEX;
Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
End end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
TourActivity prevAct = start;
double prevActEndTime = newVehicleDepartureTime;
boolean pickupShipmentLoopBroken = false;
//pickupShipmentLoop
List<TourActivity> activities = currentRoute.getTourActivities().getActivities();
for(int i=0;i<activities.size();i++){
ConstraintsStatus pickupShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, pickupShipment, activities.get(i), prevActEndTime);
if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED)){
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), activities.get(i).getLocationId(), prevActEndTime, newDriver, newVehicle);
prevActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, activities.get(i));
prevAct = activities.get(i);
continue;
}
else if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
pickupShipmentLoopBroken = true;
break;
}
ActivityInsertionCosts pickupAIC = calculate(insertionContext,prevAct,pickupShipment,activities.get(i),prevActEndTime);
TourActivity prevAct_deliveryLoop = pickupShipment;
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), pickupShipment.getLocationId(), prevActEndTime, newDriver, newVehicle);
double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
boolean deliverShipmentLoopBroken = false;
//deliverShipmentLoop
for(int j=i;j<activities.size();j++){
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, activities.get(j), prevActEndTime_deliveryLoop);
if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,activities.get(j),prevActEndTime_deliveryLoop);
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = i;
deliveryInsertionIndex = j;
}
}
else if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
deliverShipmentLoopBroken = true;
break;
}
//update prevAct and endTime
double nextActArrTime = prevActEndTime_deliveryLoop + transportCosts.getTransportTime(prevAct_deliveryLoop.getLocationId(), activities.get(j).getLocationId(), prevActEndTime_deliveryLoop, newDriver, newVehicle);
prevActEndTime_deliveryLoop = CalculationUtils.getActivityEndTime(nextActArrTime, activities.get(j));
prevAct_deliveryLoop = activities.get(j);
}
if(!deliverShipmentLoopBroken){ //check insertion between lastAct and endOfTour
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, end, prevActEndTime_deliveryLoop);
if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,end,prevActEndTime_deliveryLoop);
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = i;
deliveryInsertionIndex = activities.size();
}
}
}
//update prevAct and endTime
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), activities.get(i).getLocationId(), prevActEndTime, newDriver, newVehicle);
prevActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, activities.get(i));
prevAct = activities.get(i);
}
if(!pickupShipmentLoopBroken){ //check insertion of pickupShipment and deliverShipment at just before tour ended
ConstraintsStatus pickupShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, pickupShipment, end, prevActEndTime);
if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts pickupAIC = calculate(insertionContext,prevAct,pickupShipment,end,prevActEndTime);
TourActivity prevAct_deliveryLoop = pickupShipment;
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), pickupShipment.getLocationId(), prevActEndTime, newDriver, newVehicle);
double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, end, prevActEndTime_deliveryLoop);
if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,end,prevActEndTime_deliveryLoop);
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = activities.size();
deliveryInsertionIndex = activities.size();
}
}
}
}
if(pickupInsertionIndex == InsertionData.NO_INDEX) {
return InsertionData.createEmptyInsertionData();
}
InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver);
// logger.info("pickupIndex="+pickupInsertionIndex + ";deliveryIndex=" + deliveryInsertionIndex);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
return insertionData;
}
private ActivityInsertionCosts calculate(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double departureTimeAtPrevAct) {
return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
}
}

View file

@ -14,17 +14,19 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import jsprit.core.algorithm.recreate.listener.VehicleSwitchedListener;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleFleetManager;
class VehicleSwitched implements VehicleSwitchedListener{
public class VehicleSwitched implements VehicleSwitchedListener{
private VehicleFleetManager fleetManager;
VehicleSwitched(VehicleFleetManager fleetManager){
public VehicleSwitched(VehicleFleetManager fleetManager){
this.fleetManager = fleetManager;
}

View file

@ -14,31 +14,33 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.Collection;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import org.apache.log4j.Logger;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculator{
final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCostsCalculator{
private Logger logger = Logger.getLogger(CalculatesVehTypeDepServiceInsertion.class);
private Logger logger = Logger.getLogger(VehicleTypeDependentJobInsertionCalculator.class);
private final VehicleFleetManager fleetManager;
private final JobInsertionCalculator insertionCalculator;
private final JobInsertionCostsCalculator insertionCalculator;
public CalculatesVehTypeDepServiceInsertion(final VehicleFleetManager fleetManager, final JobInsertionCalculator jobInsertionCalc) {
public VehicleTypeDependentJobInsertionCalculator(final VehicleFleetManager fleetManager, final JobInsertionCostsCalculator jobInsertionCalc) {
this.fleetManager = fleetManager;
this.insertionCalculator = jobInsertionCalc;
logger.info("inialise " + this);
@ -49,10 +51,10 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
return "[name=vehicleTypeDependentServiceInsertion]";
}
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) {
Vehicle selectedVehicle = currentRoute.getVehicle();
Driver selectedDriver = currentRoute.getDriver();
InsertionData bestIData = InsertionData.noInsertionFound();
InsertionData bestIData = InsertionData.createEmptyInsertionData();
double bestKnownCost_ = bestKnownCost;
Collection<Vehicle> relevantVehicles = new ArrayList<Vehicle>();
if(!(selectedVehicle instanceof NoVehicle)) {
@ -65,7 +67,7 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
for(Vehicle v : relevantVehicles){
double depTime = v.getEarliestDeparture();
InsertionData iData = insertionCalculator.calculate(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
InsertionData iData = insertionCalculator.getInsertionData(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
if(iData instanceof NoInsertionFound) {
if(bestIData instanceof NoInsertionFound) bestIData = iData;
continue;

View file

@ -14,11 +14,11 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate.listener;
import basics.Job;
import basics.algo.InsertionListener;
import basics.route.VehicleRoute;
import jsprit.core.algorithm.recreate.InsertionData;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
interface BeforeJobInsertionListener extends InsertionListener{

View file

@ -14,11 +14,12 @@
* 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 basics.algo;
package jsprit.core.algorithm.recreate.listener;
import java.util.Collection;
import basics.route.VehicleRoute;
import jsprit.core.problem.solution.route.VehicleRoute;
public interface InsertionEndsListener extends InsertionListener {

View file

@ -14,7 +14,9 @@
* 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 basics.algo;
package jsprit.core.algorithm.recreate.listener;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;

View file

@ -14,20 +14,18 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate.listener;
import java.util.ArrayList;
import java.util.Collection;
import basics.Job;
import basics.algo.InsertionEndsListener;
import basics.algo.InsertionListener;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import jsprit.core.algorithm.recreate.InsertionData;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
class InsertionListeners {
public class InsertionListeners {
private Collection<InsertionListener> listeners = new ArrayList<InsertionListener>();

View file

@ -14,15 +14,17 @@
* 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 basics.algo;
package jsprit.core.algorithm.recreate.listener;
import java.util.Collection;
import basics.Job;
import basics.route.VehicleRoute;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
public interface InsertionStartsListener extends InsertionListener {
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
}

View file

@ -14,10 +14,10 @@
* 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 basics.algo;
package jsprit.core.algorithm.recreate.listener;
import basics.Job;
import basics.route.VehicleRoute;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;

View file

@ -14,13 +14,12 @@
* 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 algorithms;
package jsprit.core.algorithm.recreate.listener;
import basics.algo.InsertionListener;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
interface VehicleSwitchedListener extends InsertionListener{
public interface VehicleSwitchedListener extends InsertionListener{
public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle);

View file

@ -0,0 +1,23 @@
package jsprit.core.algorithm.ruin;
import jsprit.core.algorithm.ruin.distance.JobDistance;
import jsprit.core.problem.VehicleRoutingProblem;
public class RadialRuinStrategyFactory implements RuinStrategyFactory{
private double fraction;
private JobDistance jobDistance;
public RadialRuinStrategyFactory(double fraction, JobDistance jobDistance) {
super();
this.fraction = fraction;
this.jobDistance = jobDistance;
}
@Override
public RuinStrategy createStrategy(VehicleRoutingProblem vrp) {
return new RuinRadial(vrp,fraction,jobDistance);
}
}

View file

@ -0,0 +1,19 @@
package jsprit.core.algorithm.ruin;
import jsprit.core.problem.VehicleRoutingProblem;
public class RandomRuinStrategyFactory implements RuinStrategyFactory{
private double fraction;
public RandomRuinStrategyFactory(double fraction) {
super();
this.fraction = fraction;
}
@Override
public RuinStrategy createStrategy(VehicleRoutingProblem vrp) {
return new RuinRandom(vrp, fraction);
}
}

View file

@ -14,7 +14,7 @@
* 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 algorithms;
package jsprit.core.algorithm.ruin;
import java.util.ArrayList;
import java.util.Collection;
@ -27,18 +27,22 @@ import java.util.Map;
import java.util.Random;
import java.util.TreeSet;
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.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.util.RandomNumberGeneration;
import jsprit.core.util.StopWatch;
import org.apache.log4j.Logger;
import util.RandomNumberGeneration;
import util.StopWatch;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.route.VehicleRoute;
/**
*
* RuinStrategy that ruins the neighborhood of a randomly selected service. The size and the structure of the neighborhood is defined by
* 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).
*
@ -141,7 +145,7 @@ final class RuinRadial implements RuinStrategy {
distanceNodeTree.put(i.getId(), treeSet);
for (Job j : vrp.getJobs().values()) {
if(i==j) continue;
double distance = jobDistance.calculateDistance(i, j);
double distance = jobDistance.getDistance(i, j);
ReferencedJob refNode = new ReferencedJob(j, distance);
treeSet.add(refNode);
nuOfDistancesStored++;
@ -206,7 +210,7 @@ final class RuinRadial implements RuinStrategy {
distanceNodeTree.put(i.getId(), treeSet);
for (Job j : vrp.getJobs().values()) {
if(i==j) continue;
double distance = jobDistance.calculateDistance(i, j);
double distance = jobDistance.getDistance(i, j);
ReferencedJob refNode = new ReferencedJob(j, distance);
if(treeSet.size() < capacity){
treeSet.add(refNode);
@ -287,6 +291,39 @@ final class RuinRadial implements RuinStrategy {
jobNeighborhoodsImpl.initialise();
jobNeighborhoods = jobNeighborhoodsImpl;
logger.info("intialise " + this);
//<<<<<<< HEAD
// }
//
// private void calculateDistancesFromJob2Job() {
// logger.info("preprocess distances between locations ...");
// StopWatch stopWatch = new StopWatch();
// stopWatch.start();
// int nuOfDistancesStored = 0;
// for (Job i : vrp.getJobs().values()) {
// TreeSet<ReferencedJob> treeSet = new TreeSet<ReferencedJob>(
// new Comparator<ReferencedJob>() {
// @Override
// public int compare(ReferencedJob o1, ReferencedJob o2) {
// if (o1.getDistance() <= o2.getDistance()) {
// return 1;
// } else {
// return -1;
// }
// }
// });
// distanceNodeTree.put(i.getId(), treeSet);
// for (Job j : vrp.getJobs().values()) {
// double distance = jobDistance.getDistance(i, j);
// ReferencedJob refNode = new ReferencedJob(j, distance);
// treeSet.add(refNode);
// nuOfDistancesStored++;
// }
// }
// stopWatch.stop();
// logger.info("preprocessing comp-time: " + stopWatch + "; nuOfDistances stored: " + nuOfDistancesStored + "; estimated memory: " +
// (distanceNodeTree.keySet().size()*64+nuOfDistancesStored*92) + " bytes");
//=======
//>>>>>>> refs/heads/master
}
@Override

View file

@ -14,7 +14,7 @@
* 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 algorithms;
package jsprit.core.algorithm.ruin;
import java.util.ArrayList;
import java.util.Collection;
@ -22,12 +22,15 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.algorithm.ruin.listener.RuinListeners;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.util.RandomNumberGeneration;
import org.apache.log4j.Logger;
import util.RandomNumberGeneration;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.route.VehicleRoute;
/**

View file

@ -14,12 +14,14 @@
* 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 algorithms;
package jsprit.core.algorithm.ruin;
import java.util.Collection;
import basics.Job;
import basics.route.VehicleRoute;
import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
@ -30,41 +32,8 @@ import basics.route.VehicleRoute;
*
*/
interface RuinStrategy {
public interface RuinStrategy {
/**
* Listener that listens to the ruin-process. It informs whoever is interested about start, end and about a removal of a job.
*
* @author schroeder
*
*/
public static interface RuinListener {
/**
* informs about ruin-start.
*
* @param routes
*/
public void ruinStarts(Collection<VehicleRoute> routes);
/**
* informs about ruin-end.
*
* @param routes
* @param unassignedJobs
*/
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs);
/**
* informs if a {@link Job} has been removed from a {@link VehicleRoute}.
*
* @param job
* @param fromRoute
*/
public void removed(Job job, VehicleRoute fromRoute);
}
/**
* Ruins a current solution, i.e. a collection of vehicle-routes and
* returns a collection of removed and thus unassigned jobs.

View file

@ -14,11 +14,11 @@
* 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 algorithms;
package jsprit.core.algorithm.ruin;
import basics.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem;
interface RuinStrategyFactory {
public interface RuinStrategyFactory {
public RuinStrategy createStrategy(VehicleRoutingProblem vrp);

View file

@ -0,0 +1,105 @@
/*******************************************************************************
* Copyright (C) 2013 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.distance;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.util.Coordinate;
import jsprit.core.util.EuclideanDistanceCalculator;
import org.apache.log4j.Logger;
/**
* Calculator that calculates average distance between two jobs based on the input-transport costs.
*
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
*
* @author stefan schroeder
*
*/
public class AvgServiceAndShipmentDistance implements JobDistance {
private static Logger log = Logger.getLogger(AvgServiceAndShipmentDistance.class);
private VehicleRoutingTransportCosts costs;
public AvgServiceAndShipmentDistance(VehicleRoutingTransportCosts costs) {
super();
this.costs = costs;
}
/**
* Calculates and returns the average distance between two jobs based on the input-transport costs.
*
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
*/
@Override
public double getDistance(Job i, Job j) {
if (i.equals(j)) return 0.0;
if (i instanceof Service && j instanceof Service) {
return calcDist((Service)i, (Service)j);
}
else if(i instanceof Service && j instanceof Shipment){
return calcDist((Service)i,(Shipment)j);
}
else if(i instanceof Shipment && j instanceof Service){
return calcDist((Service)j,(Shipment)i);
}
else if(i instanceof Shipment && j instanceof Shipment){
return calcDist((Shipment)i,(Shipment)j);
}
else{
throw new IllegalStateException("this supports only shipments or services");
}
}
private double calcDist(Service i, Service j) {
return calcDist(i.getLocationId(),i.getCoord(),j.getLocationId(),j.getCoord());
}
private double calcDist(Service i, Shipment j) {
double c_ij1 = calcDist(i.getLocationId(),i.getCoord(),j.getPickupLocation(),j.getPickupCoord());
double c_ij2 = calcDist(i.getLocationId(),i.getCoord(),j.getDeliveryLocation(),j.getDeliveryCoord());
return (c_ij1 + c_ij2)/2.0;
}
private double calcDist(Shipment i, Shipment j) {
double c_i1j1 = calcDist(i.getPickupLocation(),i.getPickupCoord(),j.getPickupLocation(),j.getPickupCoord());
double c_i1j2 = calcDist(i.getPickupLocation(),i.getPickupCoord(),j.getDeliveryLocation(),j.getDeliveryCoord());
double c_i2j1 = calcDist(i.getDeliveryLocation(),i.getDeliveryCoord(),j.getPickupLocation(),j.getPickupCoord());
double c_i2j2 = calcDist(i.getDeliveryLocation(),i.getDeliveryCoord(),j.getDeliveryLocation(),j.getDeliveryCoord());
return (c_i1j1 + c_i1j2 + c_i2j1 + c_i2j2)/4.0;
}
private double calcDist(String location_i, Coordinate coord_i, String location_j, Coordinate coord_j){
try{
double c_ij = costs.getTransportCost(location_i, location_j, 0.0, null, null);
return c_ij;
}
catch(IllegalStateException e){
// now try the euclidean distance between these two services
}
double c_ij = EuclideanDistanceCalculator.calculateDistance(coord_i, coord_j);
return c_ij;
}
}

View file

@ -14,13 +14,14 @@
* 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 algorithms;
package jsprit.core.algorithm.ruin.distance;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import org.apache.log4j.Logger;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
/**
@ -31,13 +32,13 @@ import basics.costs.VehicleRoutingTransportCosts;
* @author stefan schroeder
*
*/
class JobDistanceAvgCosts implements JobDistance {
public class AvgServiceDistance implements JobDistance {
private static Logger log = Logger.getLogger(JobDistanceAvgCosts.class);
private static Logger log = Logger.getLogger(AvgServiceDistance.class);
private VehicleRoutingTransportCosts costs;
public JobDistanceAvgCosts(VehicleRoutingTransportCosts costs) {
public AvgServiceDistance(VehicleRoutingTransportCosts costs) {
super();
this.costs = costs;
@ -49,7 +50,7 @@ class JobDistanceAvgCosts implements JobDistance {
* <p>If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs.
*/
@Override
public double calculateDistance(Job i, Job j) {
public double getDistance(Job i, Job j) {
double avgCost = 0.0;
if (i instanceof Service && j instanceof Service) {
if (i.equals(j)) {
@ -61,7 +62,7 @@ class JobDistanceAvgCosts implements JobDistance {
}
} else {
throw new UnsupportedOperationException(
"currently, this class just works with shipments and services.");
"currently, this class just works services.");
}
return avgCost;
}
@ -76,7 +77,7 @@ class JobDistanceAvgCosts implements JobDistance {
// now try the euclidean distance between these two services
}
EuclideanServiceDistance euclidean = new EuclideanServiceDistance();
distance = euclidean.calculateDistance(s_i, s_j);
distance = euclidean.getDistance(s_i, s_j);
return distance;
}

View file

@ -14,20 +14,20 @@
* 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 algorithms;
package jsprit.core.algorithm.ruin.distance;
import util.EuclideanDistanceCalculator;
import basics.Job;
import basics.Service;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import jsprit.core.util.EuclideanDistanceCalculator;
class EuclideanServiceDistance implements JobDistance {
public class EuclideanServiceDistance implements JobDistance {
public EuclideanServiceDistance() {
super();
}
@Override
public double calculateDistance(Job i, Job j) {
public double getDistance(Job i, Job j) {
double avgCost = 0.0;
if (i instanceof Service && j instanceof Service) {
if (i.equals(j)) {

View file

@ -14,14 +14,14 @@
* 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 algorithms;
package jsprit.core.algorithm.ruin.distance;
import basics.Job;
import jsprit.core.problem.job.Job;
interface JobDistance {
public interface JobDistance {
public double calculateDistance(Job i, Job j);
public double getDistance(Job i, Job j);
}

Some files were not shown because too many files have changed in this diff Show more