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..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 @@ -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; } @@ -140,30 +142,36 @@ 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); } 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); + 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 ({})" + + // "\n this might yield unintended effects, e.g. initial solution cannot be improved anymore.", nuJobs, problem.getJobs().values().size()); + // } } /** @@ -214,7 +222,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 +232,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 +252,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 +293,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 +315,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) {