From eb78625e1fec64d3cb19685f93fc9b82b5b8656d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Vissy?= Date: Mon, 12 Jun 2017 22:26:28 +0200 Subject: [PATCH 1/2] #354 - partial solution: adding new jobs as unassigned --- .../algorithm/VehicleRoutingAlgorithm.java | 84 +++++++++++++------ 1 file changed, 57 insertions(+), 27 deletions(-) diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/VehicleRoutingAlgorithm.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/VehicleRoutingAlgorithm.java index 7bdeae78..cea9975b 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/VehicleRoutingAlgorithm.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/VehicleRoutingAlgorithm.java @@ -17,6 +17,14 @@ */ package com.graphhopper.jsprit.core.algorithm; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.graphhopper.jsprit.core.algorithm.SearchStrategy.DiscoveredSolution; import com.graphhopper.jsprit.core.algorithm.listener.SearchStrategyListener; import com.graphhopper.jsprit.core.algorithm.listener.SearchStrategyModuleListener; @@ -30,11 +38,6 @@ import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolutio import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity; import com.graphhopper.jsprit.core.util.Solutions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collection; /** @@ -57,9 +60,8 @@ public class VehicleRoutingAlgorithm { @Override public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) { for (PrematureAlgorithmTermination termination : terminationCriteria) { - if (termination.isPrematureBreak(discoveredSolution)) { + if (termination.isPrematureBreak(discoveredSolution)) return true; - } } return false; } @@ -145,25 +147,41 @@ public class VehicleRoutingAlgorithm { } private void verify(VehicleRoutingProblemSolution solution) { - int nuJobs = 0; + Set allJobs = new HashSet(problem.getJobs().values()); + allJobs.removeAll(solution.getUnassignedJobs()); for (VehicleRoute route : solution.getRoutes()) { - nuJobs += route.getTourActivities().getJobs().size(); + allJobs.removeAll(route.getTourActivities().getJobs()); if (route.getVehicle().getIndex() == 0) throw new IllegalStateException("vehicle used in initial solution has no index. probably a vehicle is used that has not been added to the " + - " the VehicleRoutingProblem. only use vehicles that have already been added to the problem."); + " the VehicleRoutingProblem. only use vehicles that have already been added to the problem."); for (TourActivity act : route.getActivities()) { - if (act.getIndex() == 0) { + if (act.getIndex() == 0) throw new IllegalStateException("act in initial solution has no index. activities are created and associated to their job in VehicleRoutingProblem\n." + - " thus if you build vehicle-routes use the jobActivityFactory from vehicle routing problem like that \n" + - " VehicleRoute.Builder.newInstance(knownVehicle).setJobActivityFactory(vrp.getJobActivityFactory).addService(..)....build() \n" + - " then the activities that are created to build the route are identical to the ones used in VehicleRoutingProblem"); - } + " thus if you build vehicle-routes use the jobActivityFactory from vehicle routing problem like that \n" + + " VehicleRoute.Builder.newInstance(knownVehicle).setJobActivityFactory(vrp.getJobActivityFactory).addService(..)....build() \n" + + " then the activities that are created to build the route are identical to the ones used in VehicleRoutingProblem"); } } -// if (nuJobs != problem.getJobs().values().size()) { -// logger.warn("number of jobs in initial solution ({}) is not equal nuJobs in vehicle routing problem ({})" + -// "\n this might yield unintended effects, e.g. initial solution cannot be improved anymore.", nuJobs, problem.getJobs().values().size()); -// } + + solution.getUnassignedJobs().addAll(allJobs); + + // Doesn't work + // for (Vehicle v : problem.getVehicles()) { + // boolean found = false; + // for (VehicleRoute vr : solution.getRoutes()) + // if (vr.getVehicle().getId().equals(v.getId())) { + // found = true; + // break; + // } + // if (!found) { + // solution.getRoutes().add(VehicleRoute.Builder.newInstance(v).build()); + // } + // } + + // if (nuJobs != problem.getJobs().values().size()) { + // logger.warn("number of jobs in initial solution ({}) is not equal nuJobs in vehicle routing problem ({})" + + // "\n this might yield unintended effects, e.g. initial solution cannot be improved anymore.", nuJobs, problem.getJobs().values().size()); + // } } /** @@ -214,7 +232,9 @@ public class VehicleRoutingAlgorithm { Collection solutions = new ArrayList(initialSolutions); algorithmStarts(problem, solutions); bestEver = Solutions.bestOf(solutions); - if (logger.isTraceEnabled()) log(solutions); + if (logger.isTraceEnabled()) { + log(solutions); + } logger.info("iterations start"); for (int i = 0; i < maxIterations; i++) { iterationStarts(i + 1, problem, solutions); @@ -222,7 +242,9 @@ public class VehicleRoutingAlgorithm { counter.incCounter(); SearchStrategy strategy = searchStrategyManager.getRandomStrategy(); DiscoveredSolution discoveredSolution = strategy.run(problem, solutions); - if (logger.isTraceEnabled()) log(discoveredSolution); + if (logger.isTraceEnabled()) { + log(discoveredSolution); + } memorizeIfBestEver(discoveredSolution); selectedStrategy(discoveredSolution, problem, solutions); if (terminationManager.isPrematureBreak(discoveredSolution)) { @@ -240,11 +262,15 @@ public class VehicleRoutingAlgorithm { } private void addBestEver(Collection solutions) { - if (bestEver != null) solutions.add(bestEver); + if (bestEver != null) { + solutions.add(bestEver); + } } private void log(Collection solutions) { - for (VehicleRoutingProblemSolution sol : solutions) log(sol); + for (VehicleRoutingProblemSolution sol : solutions) { + log(sol); + } } private void log(VehicleRoutingProblemSolution solution) { @@ -277,9 +303,11 @@ public class VehicleRoutingAlgorithm { private void memorizeIfBestEver(DiscoveredSolution discoveredSolution) { if (discoveredSolution == null) return; - if (bestEver == null) bestEver = discoveredSolution.getSolution(); - else if (discoveredSolution.getSolution().getCost() < bestEver.getCost()) + if (bestEver == null) { bestEver = discoveredSolution.getSolution(); + } else if (discoveredSolution.getSolution().getCost() < bestEver.getCost()) { + bestEver = discoveredSolution.getSolution(); + } } @@ -297,10 +325,12 @@ public class VehicleRoutingAlgorithm { public void addListener(VehicleRoutingAlgorithmListener l) { algoListeners.addListener(l); - if (l instanceof SearchStrategyListener) + if (l instanceof SearchStrategyListener) { searchStrategyManager.addSearchStrategyListener((SearchStrategyListener) l); - if (l instanceof SearchStrategyModuleListener) + } + if (l instanceof SearchStrategyModuleListener) { searchStrategyManager.addSearchStrategyModuleListener((SearchStrategyModuleListener) l); + } } private void iterationEnds(int i, VehicleRoutingProblem problem, Collection solutions) { From 1af75329396cfb66b12fa6d57386e05b8d918442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Vissy?= Date: Mon, 12 Jun 2017 22:38:35 +0200 Subject: [PATCH 2/2] #354 - fixed - Cost recalculated for solution after jobs added (also a copy is made from the solution) --- .../core/algorithm/VehicleRoutingAlgorithm.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/VehicleRoutingAlgorithm.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/VehicleRoutingAlgorithm.java index cea9975b..b60fae9f 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/VehicleRoutingAlgorithm.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/VehicleRoutingAlgorithm.java @@ -142,6 +142,8 @@ public class VehicleRoutingAlgorithm { * @param solution the solution to be added */ public void addInitialSolution(VehicleRoutingProblemSolution solution) { + // We will make changes so let's make a copy + solution = VehicleRoutingProblemSolution.copyOf(solution); verify(solution); initialSolutions.add(solution); } @@ -164,19 +166,7 @@ public class VehicleRoutingAlgorithm { } solution.getUnassignedJobs().addAll(allJobs); - - // Doesn't work - // for (Vehicle v : problem.getVehicles()) { - // boolean found = false; - // for (VehicleRoute vr : solution.getRoutes()) - // if (vr.getVehicle().getId().equals(v.getId())) { - // found = true; - // break; - // } - // if (!found) { - // solution.getRoutes().add(VehicleRoute.Builder.newInstance(v).build()); - // } - // } + solution.setCost(getObjectiveFunction().getCosts(solution)); // if (nuJobs != problem.getJobs().values().size()) { // logger.warn("number of jobs in initial solution ({}) is not equal nuJobs in vehicle routing problem ({})" +