From b6bc3e0d9355a2c2c150f438d59603d1a4b59a89 Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Fri, 28 Jun 2013 07:55:32 +0200 Subject: [PATCH] Improve premature algorithm break --- .../java/basics/VehicleRoutingAlgorithm.java | 37 +++++--- .../IterationWithoutImprovementBreaker.java | 26 ++++++ .../algo/PrematureAlgorithmBreaker.java | 9 ++ .../main/java/basics/algo/SearchStrategy.java | 38 +++++++-- .../algo/VariationCoefficientBreaker.java | 85 +++++++++++++++++++ 5 files changed, 177 insertions(+), 18 deletions(-) create mode 100644 jsprit-core/src/main/java/basics/algo/IterationWithoutImprovementBreaker.java create mode 100644 jsprit-core/src/main/java/basics/algo/PrematureAlgorithmBreaker.java create mode 100644 jsprit-core/src/main/java/basics/algo/VariationCoefficientBreaker.java diff --git a/jsprit-core/src/main/java/basics/VehicleRoutingAlgorithm.java b/jsprit-core/src/main/java/basics/VehicleRoutingAlgorithm.java index 05ad9ec6..436c597e 100644 --- a/jsprit-core/src/main/java/basics/VehicleRoutingAlgorithm.java +++ b/jsprit-core/src/main/java/basics/VehicleRoutingAlgorithm.java @@ -31,7 +31,10 @@ 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; @@ -44,6 +47,8 @@ import basics.algo.VehicleRoutingAlgorithmListeners; */ public class VehicleRoutingAlgorithm { + + public static final int NOBREAK = Integer.MAX_VALUE; private static Logger logger = Logger.getLogger(VehicleRoutingAlgorithm.class); @@ -52,8 +57,6 @@ public class VehicleRoutingAlgorithm { private int nOfIterations = 100; - private int prematureBreak = NOBREAK; - private Counter counter = new Counter("iterations "); private SearchStrategyManager searchStrategyManager; @@ -62,6 +65,15 @@ public class VehicleRoutingAlgorithm { private Collection initialSolutions; + private PrematureAlgorithmBreaker prematureAlgorithmBreaker = new PrematureAlgorithmBreaker() { + + @Override + public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) { + return false; + } + + }; + public VehicleRoutingAlgorithm(VehicleRoutingProblem problem, SearchStrategyManager searchStrategyManager) { super(); this.problem = problem; @@ -93,10 +105,14 @@ public class VehicleRoutingAlgorithm { * the assigned number of iterations without solution-acceptance. * * - * @param iterationsWithoutImprovement + * @param nuIterationsWithoutImprovement */ - public void setPrematureBreak(int iterationsWithoutImprovement){ - prematureBreak = iterationsWithoutImprovement; + public void setPrematureBreak(int nuIterationsWithoutImprovement){ + prematureAlgorithmBreaker = new IterationWithoutImprovementBreaker(nuIterationsWithoutImprovement); + } + + public void setPrematureAlgorithmBreaker(PrematureAlgorithmBreaker prematureAlgorithmBreaker){ + this.prematureAlgorithmBreaker = prematureAlgorithmBreaker; } /** @@ -127,17 +143,14 @@ public class VehicleRoutingAlgorithm { counter.reset(); Collection solutions = new ArrayList(initialSolutions); algorithmStarts(problem,solutions); - int iterWithoutImprovement = 0; logger.info("iterations start"); for(int i=0;i prematureBreak){ + SearchStrategy strategy = searchStrategyManager.getRandomStrategy(); + DiscoveredSolution discoveredSolution = strategy.run(problem, solutions); + selectedStrategy(strategy.getName(),problem, solutions); + if(prematureAlgorithmBreaker.isPrematureBreak(discoveredSolution)){ logger.info("premature break at iteration "+ (i+1)); nuOfIterationsThisAlgoIsRunning = (i+1); break; diff --git a/jsprit-core/src/main/java/basics/algo/IterationWithoutImprovementBreaker.java b/jsprit-core/src/main/java/basics/algo/IterationWithoutImprovementBreaker.java new file mode 100644 index 00000000..0e8dc725 --- /dev/null +++ b/jsprit-core/src/main/java/basics/algo/IterationWithoutImprovementBreaker.java @@ -0,0 +1,26 @@ +package basics.algo; + +import basics.algo.SearchStrategy.DiscoveredSolution; + +public class IterationWithoutImprovementBreaker implements PrematureAlgorithmBreaker{ + + private int nuOfIterationWithoutImprovement; + + private int iterationsWithoutImprovement = 0; + + public IterationWithoutImprovementBreaker(int nuOfIterationsWithoutImprovement){ + this.nuOfIterationWithoutImprovement=nuOfIterationsWithoutImprovement; + } + + @Override + public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) { + if(discoveredSolution.isAccepted()) iterationsWithoutImprovement = 0; + else iterationsWithoutImprovement++; + if(iterationsWithoutImprovement > nuOfIterationWithoutImprovement){ + return true; + } + return false; + } + + +} diff --git a/jsprit-core/src/main/java/basics/algo/PrematureAlgorithmBreaker.java b/jsprit-core/src/main/java/basics/algo/PrematureAlgorithmBreaker.java new file mode 100644 index 00000000..2b437872 --- /dev/null +++ b/jsprit-core/src/main/java/basics/algo/PrematureAlgorithmBreaker.java @@ -0,0 +1,9 @@ +package basics.algo; + +import basics.algo.SearchStrategy.DiscoveredSolution; + +public interface PrematureAlgorithmBreaker { + + public boolean isPrematureBreak(DiscoveredSolution discoveredSolution); + +} diff --git a/jsprit-core/src/main/java/basics/algo/SearchStrategy.java b/jsprit-core/src/main/java/basics/algo/SearchStrategy.java index f0594dd5..8be14414 100644 --- a/jsprit-core/src/main/java/basics/algo/SearchStrategy.java +++ b/jsprit-core/src/main/java/basics/algo/SearchStrategy.java @@ -26,11 +26,10 @@ import java.util.Collections; import org.apache.log4j.Logger; -import basics.VehicleRoutingProblem; -import basics.VehicleRoutingProblemSolution; - import algorithms.acceptors.SolutionAcceptor; import algorithms.selectors.SolutionSelector; +import basics.VehicleRoutingProblem; +import basics.VehicleRoutingProblemSolution; @@ -38,6 +37,32 @@ import algorithms.selectors.SolutionSelector; public class SearchStrategy { + public static class DiscoveredSolution { + private VehicleRoutingProblemSolution solution; + private boolean accepted; + private String strategyName; + + public DiscoveredSolution(VehicleRoutingProblemSolution solution,boolean accepted, String strategyName) { + super(); + this.solution = solution; + this.accepted = accepted; + this.strategyName = strategyName; + } + + public VehicleRoutingProblemSolution getSolution() { + return solution; + } + + public boolean isAccepted() { + return accepted; + } + + public String getStrategyName() { + return strategyName; + } + + } + private static Logger logger = Logger.getLogger(SearchStrategy.class); private Collection searchStrategyModules = new ArrayList(); @@ -86,14 +111,14 @@ public class SearchStrategy { *

This involves three basic steps: 1) Selecting a solution from solutions (input parameter) according to {@link SolutionSelector}, 2) running the modules * ({@link SearchStrategyModule}) on the selectedSolution and 3) accepting the new solution according to {@link SolutionAcceptor}. *

Note that after 1) the selected solution is copied, thus the original solution is not modified. - *

Note also that 3) modifies the input parameter solutions by adding, removing, replacing existing solutions. + *

Note also that 3) modifies the input parameter solutions by adding, removing, replacing the existing solutions or whatever is defined in the solutionAcceptor. * * @param vrp * @param solutions which will be modified * @return boolean true if solution has been accepted, false otherwise * @see SolutionSelector, SearchStrategyModule, SolutionAcceptor */ - public boolean run(VehicleRoutingProblem vrp, Collection solutions){ + public DiscoveredSolution run(VehicleRoutingProblem vrp, Collection solutions){ VehicleRoutingProblemSolution solution = solutionSelector.selectSolution(solutions); if(solution == null) throw new IllegalStateException("solution is null. check solutionSelector to return an appropiate solution."); VehicleRoutingProblemSolution lastSolution = VehicleRoutingProblemSolution.copyOf(solution); @@ -102,7 +127,8 @@ public class SearchStrategy { lastSolution = newSolution; } boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution); - return solutionAccepted; + DiscoveredSolution discoveredSolution = new DiscoveredSolution(lastSolution, solutionAccepted, getName()); + return discoveredSolution; } diff --git a/jsprit-core/src/main/java/basics/algo/VariationCoefficientBreaker.java b/jsprit-core/src/main/java/basics/algo/VariationCoefficientBreaker.java new file mode 100644 index 00000000..1538dd76 --- /dev/null +++ b/jsprit-core/src/main/java/basics/algo/VariationCoefficientBreaker.java @@ -0,0 +1,85 @@ +package basics.algo; + +import java.util.Collection; + +import org.apache.commons.math.stat.StatUtils; +import org.apache.commons.math.stat.descriptive.moment.Mean; +import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; +import org.apache.log4j.Logger; + +import basics.VehicleRoutingAlgorithm; +import basics.VehicleRoutingProblem; +import basics.VehicleRoutingProblemSolution; +import basics.algo.SearchStrategy.DiscoveredSolution; + +public class VariationCoefficientBreaker implements PrematureAlgorithmBreaker, AlgorithmStartsListener, IterationEndsListener{ + + private static Logger logger = Logger.getLogger(VariationCoefficientBreaker.class); + + private int nuOfIterations; + + private double variationCoefficientThreshold; + + private int currentIteration; + + private double[] solutionValues; + + private VehicleRoutingProblemSolution lastAccepted = null; + + public VariationCoefficientBreaker(int nuOfIterations, double variationCoefficientThreshold) { + super(); + this.nuOfIterations = nuOfIterations; + this.variationCoefficientThreshold = variationCoefficientThreshold; + solutionValues = new double[nuOfIterations]; + } + + @Override + public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) { + if(discoveredSolution.isAccepted()){ + lastAccepted = discoveredSolution.getSolution(); + solutionValues[currentIteration]=discoveredSolution.getSolution().getCost(); + } + else{ + if(lastAccepted != null){ + solutionValues[currentIteration]=lastAccepted.getCost(); + } + else solutionValues[currentIteration]=Double.MAX_VALUE; + } + if(lastAccepted !=null) { +// logger.info(lastAccepted.getCost()); +// logger.info("inArr,"+(currentIteration)+","+solutionValues[currentIteration]); + } + if(currentIteration == (nuOfIterations-1)){ + double mean = StatUtils.mean(solutionValues); + double stdDev = new StandardDeviation(true).evaluate(solutionValues, mean); + double variationCoefficient = stdDev/mean; +// logger.info("[mean="+mean+"][stdDev="+stdDev+"][variationCoefficient="+variationCoefficient+"]"); + if(variationCoefficient < variationCoefficientThreshold){ + return true; + } + } + return false; + } + + private void reset(){ + currentIteration=0; + } + + @Override + public void informAlgorithmStarts(VehicleRoutingProblem problem,VehicleRoutingAlgorithm algorithm,Collection solutions) { + reset(); + } + + @Override + public void informIterationEnds(int i, VehicleRoutingProblem problem, Collection solutions) { + if(currentIteration == (nuOfIterations-1)){ + reset(); + } + else{ + currentIteration++; + } + } + + + +}