diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/SearchStrategy.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/SearchStrategy.java index a68808e4..c95959ef 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/SearchStrategy.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/SearchStrategy.java @@ -164,7 +164,5 @@ public class SearchStrategy { for (SearchStrategyModule module : searchStrategyModules) { module.addModuleListener(moduleListener); } - } - } diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/termination/IterationWithoutImprovementTermination.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/termination/IterationWithoutImprovementTermination.java index c2ee487d..f45046c7 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/termination/IterationWithoutImprovementTermination.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/algorithm/termination/IterationWithoutImprovementTermination.java @@ -18,9 +18,13 @@ package com.graphhopper.jsprit.core.algorithm.termination; import com.graphhopper.jsprit.core.algorithm.SearchStrategy; +import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.List; + /** * Terminates algorithm prematurely based on iterations without any improvement (i.e. new solution acceptance). @@ -39,6 +43,11 @@ public class IterationWithoutImprovementTermination implements PrematureAlgorith private int iterationsWithoutImprovement = 0; + private List costs; + + private List unassignedCount; + + private int bestCost = Integer.MAX_VALUE; /** * Constructs termination. * @@ -46,6 +55,8 @@ public class IterationWithoutImprovementTermination implements PrematureAlgorith */ public IterationWithoutImprovementTermination(int noIterationsWithoutImprovement) { this.noIterationWithoutImprovement = noIterationsWithoutImprovement; + costs = new ArrayList<>(); + unassignedCount = new ArrayList<>(); log.debug("initialise " + this); } @@ -56,10 +67,21 @@ public class IterationWithoutImprovementTermination implements PrematureAlgorith @Override public boolean isPrematureBreak(SearchStrategy.DiscoveredSolution discoveredSolution) { - if (discoveredSolution.isAccepted()) iterationsWithoutImprovement = 0; - else iterationsWithoutImprovement++; - return (iterationsWithoutImprovement > noIterationWithoutImprovement); + VehicleRoutingProblemSolution sol = discoveredSolution.getSolution(); + double currentCost = sol.getCost(); + costs.add(Math.min(currentCost, bestCost)); + int currentUnassigned = sol.getUnassignedJobs().size(); + unassignedCount.add(currentUnassigned); + + int i = costs.size() - 1; + if (i < noIterationWithoutImprovement) + return false; + + int progressPercentTerminationCondition = 1; // TODO: Move to configuration + boolean unassignedEqual = (currentUnassigned == unassignedCount.get(i-noIterationWithoutImprovement)); + boolean progressTooSlow = (100 * Math.abs(currentCost - costs.get(i - noIterationWithoutImprovement))) / currentCost < progressPercentTerminationCondition; + + return (unassignedEqual && progressTooSlow); } - } diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/reporting/SolutionPrinter.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/reporting/SolutionPrinter.java index 53690df2..7633eabd 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/reporting/SolutionPrinter.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/reporting/SolutionPrinter.java @@ -131,7 +131,7 @@ public class SolutionPrinter { out.format("+---------------+------------------------------------------+%n"); out.printf("| indicator | value |%n"); out.format("+---------------+------------------------------------------+%n"); - out.format(leftAlignSolution, "costs", solution.getCost()); + out.format(leftAlignSolution, "costs", Math.round(solution.getCost())); out.format(leftAlignSolution, "noVehicles", solution.getRoutes().size()); out.format(leftAlignSolution, "unassgndJobs", solution.getUnassignedJobs().size()); out.format("+----------------------------------------------------------+%n");