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

Merge branch 'bad-job-list'

This commit is contained in:
oblonski 2014-08-26 20:35:14 +02:00
commit 264dafd06a
31 changed files with 528 additions and 460 deletions

View file

@ -29,6 +29,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@ -51,8 +52,8 @@ public final class InsertionInitialSolutionFactory implements InitialSolutionFac
logger.info("create initial solution.");
List<VehicleRoute> vehicleRoutes = new ArrayList<VehicleRoute>();
vehicleRoutes.addAll(vrp.getInitialVehicleRoutes());
insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(vehicleRoutes, Double.MAX_VALUE);
Collection<Job> badJobs = insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(vehicleRoutes, badJobs, Double.MAX_VALUE);
double costs = solutionCostsCalculator.getCosts(solution);
solution.setCost(costs);
logger.info("creation done");

View file

@ -1,125 +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 jsprit.core.algorithm;
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.*;
import org.apache.commons.math.stat.descriptive.moment.Mean;
import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Collection;
class NeighborhoodThresholdInitialiser implements AlgorithmStartsListener{
private static Logger log = LogManager.getLogger(NeighborhoodThresholdInitialiser.class);
private NeighborhoodImpl neighborhood;
private VehicleRoutingAlgorithmFactory routingAlgorithmFactory = new VehicleRoutingAlgorithmFactory() {
@Override
public VehicleRoutingAlgorithm createAlgorithm(VehicleRoutingProblem vrp) {
VehicleRoutingAlgorithm algorithm = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "resources/config.xml");
return algorithm;
}
};
private int crowFlySpeed = 20;
public NeighborhoodThresholdInitialiser(NeighborhoodImpl neighborhood) {
this.neighborhood = neighborhood;
}
/**
* @param crowFlySpeed the crowFlySpeed to set
*/
public void setCrowFlySpeed(int crowFlySpeed) {
this.crowFlySpeed = crowFlySpeed;
}
/**
* @param routingAlgorithmFactory the routingAlgorithm to set
*/
public void setRoutingAlgorithmFactory(VehicleRoutingAlgorithmFactory routingAlgorithmFactory) {
this.routingAlgorithmFactory = routingAlgorithmFactory;
}
public void initialise(VehicleRoutingProblem problem){
informAlgorithmStarts(problem, null, null);
}
@Override
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
builder.addAllJobs(problem.getJobs().values());
builder.addAllVehicles(problem.getVehicles());
CrowFlyCosts crowFly = new CrowFlyCosts(builder.getLocations());
crowFly.speed = crowFlySpeed;
builder.setRoutingCost(crowFly);
VehicleRoutingProblem pblm = builder.build();
VehicleRoutingAlgorithm algo = routingAlgorithmFactory.createAlgorithm(pblm);
Collection<VehicleRoutingProblemSolution> mySolutions = algo.searchSolutions();
double threshold = determineThreshold(pblm,builder.getLocations(), mySolutions);
neighborhood.setThreshold(threshold);
neighborhood.initialise();
}
private double determineThreshold(VehicleRoutingProblem pblm, Locations locations, Collection<VehicleRoutingProblemSolution> mySolutions) {
VehicleRoutingProblemSolution bestSolution = Solutions.bestOf(mySolutions);
double[] distances = new double[bestSolution.getRoutes().size()+pblm.getJobs().size()];
getDistances(distances,bestSolution,locations);
Mean mean = new Mean();
double meanValue = mean.evaluate(distances);
StandardDeviation dev = new StandardDeviation();
double devValue = dev.evaluate(distances, meanValue);
log.info("mean="+meanValue+", dev="+devValue);
return meanValue + devValue;
// + 2*devValue;
// return Double.MAX_VALUE;
}
private void getDistances(double[] distances, VehicleRoutingProblemSolution bestSolution, Locations locations) {
int index = 0;
for(VehicleRoute route : bestSolution.getRoutes()){
TourActivity prev = null;
for(TourActivity act : route.getTourActivities().getActivities()){
if(prev == null){ prev = act; continue; }
double dist = EuclideanDistanceCalculator.calculateDistance(locations.getCoord(prev.getLocationId()), locations.getCoord(act.getLocationId()));
// log.info("dist="+dist);
distances[index] = dist;
index++;
prev = act;
}
// double dist = EuclideanDistanceCalculator.calculateDistance(locations.getCoord(prev.getLocationId()), locations.getCoord(route.getEnd().getLocationId()));
// distances[index] = dist;
// index++;
}
}
}

View file

@ -117,7 +117,8 @@ public class SearchStrategy {
* @param vrp the underlying vehicle routing problem
* @param solutions which will be modified
* @return discoveredSolution
*/
* @throws java.lang.IllegalStateException if selector cannot select any solution
*/
@SuppressWarnings("UnusedParameters")
public DiscoveredSolution run(VehicleRoutingProblem vrp, Collection<VehicleRoutingProblemSolution> solutions){
VehicleRoutingProblemSolution solution = solutionSelector.selectSolution(solutions);

View file

@ -16,15 +16,15 @@
******************************************************************************/
package jsprit.core.algorithm;
import jsprit.core.algorithm.listener.SearchStrategyListener;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.util.RandomNumberGeneration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import jsprit.core.algorithm.listener.SearchStrategyListener;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.util.RandomNumberGeneration;
public class SearchStrategyManager {
@ -55,8 +55,9 @@ public class SearchStrategyManager {
/**
* adds a new search strategy. the probability must be within [0,1].
* @param strategy
* @param probability
* @param strategy strategy to be added
* @param probability probability of corresponding strategy to be added
* @throws java.lang.IllegalStateException if strategy is null OR prob > 1. OR prob < 0.
*/
public void addStrategy(SearchStrategy strategy, double probability){
if(strategy == null){
@ -76,6 +77,12 @@ public class SearchStrategyManager {
}
}
/**
* Returns search strategy that has been randomly selected.
*
* @return selected search strategy
* @throws java.lang.IllegalStateException if randomNumberGenerator is null OR no search strategy can be found
*/
public SearchStrategy getRandomStrategy() {
if(random == null) throw new IllegalStateException("randomizer is null. make sure you set random object correctly");
double randomFig = random.nextDouble();

View file

@ -23,6 +23,7 @@ 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.vehicle.Vehicle;
/**
* Default objective function which is the sum of all fixed vehicle and variable
@ -43,16 +44,23 @@ public class VariablePlusFixedSolutionCostCalculatorFactory {
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, InternalStates.COSTS,Double.class);
c += r.getVehicle().getType().getVehicleCostParams().fix;
for(VehicleRoute r : solution.getRoutes()){
c += stateManager.getRouteState(r, InternalStates.COSTS, Double.class);
c += getFixedCosts(r.getVehicle());
}
c += solution.getUnassignedJobs().size() * c * .1;
return c;
}
private double getFixedCosts(Vehicle vehicle) {
if(vehicle == null) return 0.0;
if(vehicle.getType() == null) return 0.0;
return vehicle.getType().getVehicleCostParams().fix;
}
};
}

View file

@ -16,10 +16,10 @@
******************************************************************************/
package jsprit.core.algorithm.acceptor;
import java.util.Collection;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import java.util.Collection;
public class GreedyAcceptance implements SolutionAcceptor{
@ -48,12 +48,6 @@ public class GreedyAcceptance 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

@ -620,25 +620,8 @@ public class VehicleRoutingAlgorithms {
}
private static SolutionCostCalculator getDefaultCostCalculator(final StateManager stateManager) {
SolutionCostCalculator calc = new SolutionCostCalculator() {
@Override
public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.0;
for(VehicleRoute route : solution.getRoutes()){
costs += stateManager.getRouteState(route, InternalStates.COSTS, Double.class) + getFixedCosts(route.getVehicle());
}
return costs;
}
private double getFixedCosts(Vehicle vehicle) {
if(vehicle == null) return 0.0;
if(vehicle.getType() == null) return 0.0;
return vehicle.getType().getVehicleCostParams().fix;
}
};
return calc;
}
return new VariablePlusFixedSolutionCostCalculatorFactory(stateManager).createCalculator();
}
private static VehicleFleetManager createFleetManager(final VehicleRoutingProblem vrp) {
if(vrp.getFleetSize().equals(FleetSize.INFINITE)){

View file

@ -16,8 +16,6 @@
******************************************************************************/
package jsprit.core.algorithm.module;
import java.util.Collection;
import jsprit.core.algorithm.SearchStrategyModule;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.algorithm.recreate.InsertionStrategy;
@ -27,6 +25,10 @@ import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class RuinAndRecreateModule implements SearchStrategyModule{
@ -46,7 +48,12 @@ public class RuinAndRecreateModule implements SearchStrategyModule{
@Override
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs);
Set<Job> ruinedJobSet = new HashSet<Job>();
ruinedJobSet.addAll(ruinedJobs);
ruinedJobSet.addAll(vrpSolution.getUnassignedJobs());
Collection<Job> unassignedJobs = insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobSet);
vrpSolution.getUnassignedJobs().clear();
vrpSolution.getUnassignedJobs().addAll(unassignedJobs);
return vrpSolution;
}

View file

@ -34,11 +34,11 @@ import java.util.*;
/**
*
* Best insertion that insert the job where additional costs are minimal.
*
* @author stefan schroeder
*
*/
final class BestInsertion implements InsertionStrategy{
class Insertion {
@ -79,8 +79,6 @@ final class BestInsertion implements InsertionStrategy{
private JobInsertionCostsCalculator bestInsertionCostCalculator;
private boolean minVehiclesFirst = false;
public void setRandom(Random random) {
this.random = random;
}
@ -99,9 +97,10 @@ final class BestInsertion implements InsertionStrategy{
}
@Override
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
public Collection<Job> insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs);
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
Collections.shuffle(unassignedJobList, random);
for(Job unassignedJob : unassignedJobList){
Insertion bestInsertion = null;
@ -116,41 +115,20 @@ final class BestInsertion implements InsertionStrategy{
bestInsertionCost = iData.getInsertionCost();
}
}
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);
vehicleRoutes.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 NoSolutionFoundException(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());
}
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);
vehicleRoutes.add(newRoute);
}
if(bestInsertion == null) badJobs.add(unassignedJob);
else inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
}
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
return badJobs;
}
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
@Override
public void removeListener(InsertionListener insertionListener) {
insertionsListeners.removeListener(insertionListener);
}

View file

@ -85,12 +85,8 @@ final class BestInsertionConcurrent implements InsertionStrategy{
private JobInsertionCostsCalculator bestInsertionCostCalculator;
private boolean minVehiclesFirst = false;
private int nuOfBatches;
private ExecutorService executor;
private ExecutorCompletionService<Insertion> completionService;
public void setRandom(Random random) {
@ -100,11 +96,10 @@ final class BestInsertionConcurrent implements InsertionStrategy{
public BestInsertionConcurrent(JobInsertionCostsCalculator jobInsertionCalculator, ExecutorService executorService, int nuOfBatches, VehicleRoutingProblem vehicleRoutingProblem) {
super();
this.insertionsListeners = new InsertionListeners();
this.executor = executorService;
this.nuOfBatches = nuOfBatches;
inserter = new Inserter(insertionsListeners, vehicleRoutingProblem);
bestInsertionCostCalculator = jobInsertionCalculator;
completionService = new ExecutorCompletionService<Insertion>(executor);
completionService = new ExecutorCompletionService<Insertion>(executorService);
logger.info("initialise " + this);
}
@ -114,19 +109,16 @@ final class BestInsertionConcurrent implements InsertionStrategy{
}
@Override
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
public Collection<Job> insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs);
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
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;
List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
for(final Job unassignedJob : unassignedJobList){
Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE;
for(final Batch batch : batches){
for(final Batch batch : batches){
completionService.submit(new Callable<Insertion>() {
@Override
@ -135,21 +127,18 @@ final class BestInsertionConcurrent implements InsertionStrategy{
}
});
}
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){
}
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) {
@ -157,42 +146,18 @@ final class BestInsertionConcurrent implements InsertionStrategy{
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());
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);
vehicleRoutes.add(newRoute);
batches.get(random.nextInt(batches.size())).routes.add(newRoute);
}
if(bestInsertion == null) badJobs.add(unassignedJob);
else 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]";
return badJobs;
}
@Override

View file

@ -16,18 +16,17 @@
******************************************************************************/
package jsprit.core.algorithm.recreate;
import java.util.Collection;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import java.util.Collection;
/**
*
* Basic interface for insertion strategies
*
* @author stefan schroeder
*
*/
@ -35,14 +34,13 @@ import jsprit.core.problem.solution.route.VehicleRoute;
public interface InsertionStrategy {
/**
* Assigns the unassigned jobs to service-providers
*
* @param vehicleRoutes
* @param unassignedJobs
*/
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
public void addListener(InsertionListener insertionListener);
* Inserts unassigned jobs into vehicle routes.
* @param vehicleRoutes existing vehicle routes
* @param unassignedJobs jobs to be inserted
*/
public Collection<Job> insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
public void addListener(InsertionListener insertionListener);
public void removeListener(InsertionListener insertionListener);

View file

@ -526,7 +526,9 @@ public class VehicleRoutingProblem {
*
* @param penaltyFactor penaltyFactor of penaltyVehicle
* @return this builder
* @deprecated since 1.3.2-SNAPSHOT bad job list replaces penalty vehicles
*/
@Deprecated
public Builder addPenaltyVehicles(double penaltyFactor){
this.addPenaltyVehicles = true;
this.penaltyFactor = penaltyFactor;
@ -543,7 +545,9 @@ public class VehicleRoutingProblem {
* @param penaltyFactor the penaltyFactor of penaltyVehicle
* @param penaltyFixedCosts which is an absolute penaltyValue (in contrary to penaltyFactor)
* @return this builder
* @deprecated since 1.3.2-SNAPSHOT bad job list replaces penalty vehicles
*/
@Deprecated
public Builder addPenaltyVehicles(double penaltyFactor, double penaltyFixedCosts){
this.addPenaltyVehicles = true;
this.penaltyFactor = penaltyFactor;

View file

@ -20,10 +20,7 @@ import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem.FleetSize;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.driver.DriverImpl;
import jsprit.core.problem.job.Delivery;
import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.job.*;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.TimeWindow;
@ -304,7 +301,16 @@ public class VrpXMLReader{
}
routes.add(routeBuilder.build());
}
VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(routes, cost);
VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(routes, cost);
List<HierarchicalConfiguration> unassignedJobConfigs = solutionConfig.configurationsAt("unassignedJobs.job");
for(HierarchicalConfiguration unassignedJobConfig : unassignedJobConfigs){
String jobId = unassignedJobConfig.getString("[@id]");
Job job = getShipment(jobId);
if(job == null) job = getService(jobId);
if(job == null) throw new IllegalStateException("cannot find unassignedJob with id " + jobId);
solution.getUnassignedJobs().add(job);
}
solutions.add(solution);
}
}

View file

@ -203,6 +203,11 @@ public class VrpXMLWriter {
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").end", route.getEnd().getArrTime());
routeCounter++;
}
int unassignedJobCounter = 0;
for(Job unassignedJob : solution.getUnassignedJobs()){
xmlConfig.setProperty(solutionPath + "(" + counter + ").unassignedJobs.job(" + unassignedJobCounter + ")[@id]", unassignedJob.getId());
unassignedJobCounter++;
}
counter++;
}
}

View file

@ -16,11 +16,12 @@
******************************************************************************/
package jsprit.core.problem.solution;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import java.util.ArrayList;
import java.util.Collection;
import jsprit.core.problem.solution.route.VehicleRoute;
/**
* Contains the solution of a vehicle routing problem and its corresponding costs.
@ -29,14 +30,12 @@ import jsprit.core.problem.solution.route.VehicleRoute;
*
*/
public class VehicleRoutingProblemSolution {
public static double NO_COST_YET = -9999.0;
/**
* Makes a deep copy of the solution to be copied.
*
* @param solution2copy
* @return
* @param solution2copy solution to be copied
* @return solution
*/
public static VehicleRoutingProblemSolution copyOf(VehicleRoutingProblemSolution solution2copy){
return new VehicleRoutingProblemSolution(solution2copy);
@ -44,6 +43,8 @@ public class VehicleRoutingProblemSolution {
private final Collection<VehicleRoute> routes;
private Collection<Job> unassignedJobs = new ArrayList<Job>();
private double cost;
private VehicleRoutingProblemSolution(VehicleRoutingProblemSolution solution){
@ -53,13 +54,14 @@ public class VehicleRoutingProblemSolution {
routes.add(route);
}
this.cost = solution.getCost();
unassignedJobs.addAll(solution.getUnassignedJobs());
}
/**
* Constructs a solution with a number of {@link VehicleRoute}s and their corresponding aggregate cost value.
*
* @param routes
* @param cost
* @param routes routes being part of the solution
* @param cost total costs of solution
*/
public VehicleRoutingProblemSolution(Collection<VehicleRoute> routes, double cost) {
super();
@ -67,6 +69,21 @@ public class VehicleRoutingProblemSolution {
this.cost = cost;
}
/**
* Constructs a solution with a number of {@link VehicleRoute}s, bad jobs and their corresponding aggregate cost value.
*
* @param routes routes being part of the solution
* @param unassignedJobs jobs that could not be assigned to any vehicle
* @param cost total costs of solution
*
*/
public VehicleRoutingProblemSolution(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs, double cost) {
super();
this.routes = routes;
this.unassignedJobs = unassignedJobs;
this.cost = cost;
}
/**
* Returns a collection of vehicle-routes.
*
@ -88,10 +105,19 @@ public class VehicleRoutingProblemSolution {
/**
* Sets the costs of this solution.
*
* @param cost
* @param cost the cost to assigned to this solution
*/
public void setCost(double cost){
this.cost = cost;
}
/**
* Returns bad jobs, i.e. jobs that are not assigned to any vehicle route.
*
* @return bad jobs
*/
public Collection<Job> getUnassignedJobs(){
return unassignedJobs;
}
}

View file

@ -77,10 +77,10 @@ public class SolutionPrinter {
System.out.printf("| indicator | value |%n");
System.out.format("+---------------+----------+%n");
System.out.format(leftAlign, "nJobs", problem.getJobs().values().size());
System.out.format(leftAlign, "noJobs", problem.getJobs().values().size());
Jobs jobs = getNuOfJobs(problem);
System.out.format(leftAlign, "nServices",jobs.nServices);
System.out.format(leftAlign, "nShipments",jobs.nShipments);
System.out.format(leftAlign, "noServices",jobs.nServices);
System.out.format(leftAlign, "noShipments",jobs.nShipments);
System.out.format(leftAlign, "fleetsize",problem.getFleetSize().toString());
System.out.format("+--------------------------+%n");
@ -92,7 +92,8 @@ public class SolutionPrinter {
System.out.printf("| indicator | value |%n");
System.out.format("+---------------+------------------------------------------+%n");
System.out.format(leftAlignSolution, "costs",solution.getCost());
System.out.format(leftAlignSolution, "nVehicles",solution.getRoutes().size());
System.out.format(leftAlignSolution, "noVehicles",solution.getRoutes().size());
System.out.format(leftAlignSolution, "unassgndJobs", solution.getUnassignedJobs().size());
System.out.format("+----------------------------------------------------------+%n");
if(print.equals(Print.VERBOSE)){
@ -130,6 +131,14 @@ public class SolutionPrinter {
}
System.out.format("+*:=PenaltyVehicle+%n");
System.out.format("+--------------------------------------------------------------------------------------------------------------------------------+%n");
System.out.format("+----------------+%n");
System.out.format("| unassignedJobs |%n");
System.out.format("+----------------+%n");
String unassignedJobAlgin = "| %-14s |%n";
for(Job j : solution.getUnassignedJobs()){
System.out.format(unassignedJobAlgin,j.getId());
}
System.out.format("+----------------+%n");
}
private static String getVehicleString(VehicleRoute route) {

View file

@ -281,7 +281,18 @@
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:element name="unassignedJobs" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="job" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="id" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>