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

Improve premature algorithm break

This commit is contained in:
oblonski 2013-06-28 07:55:32 +02:00
parent cc47719eac
commit b6bc3e0d93
5 changed files with 177 additions and 18 deletions

View file

@ -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<VehicleRoutingProblemSolution> 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<VehicleRoutingProblemSolution> solutions = new ArrayList<VehicleRoutingProblemSolution>(initialSolutions);
algorithmStarts(problem,solutions);
int iterWithoutImprovement = 0;
logger.info("iterations start");
for(int i=0;i<nOfIterations;i++){
iterationStarts(i+1,problem,solutions);
counter.incCounter();
SearchStrategy strat = searchStrategyManager.getRandomStrategy();
boolean newSolutionFoundAndAccepted = strat.run(problem, solutions);
selectedStrategy(strat.getName(),problem, solutions);
if(newSolutionFoundAndAccepted) iterWithoutImprovement = 0;
else iterWithoutImprovement++;
if(iterWithoutImprovement > 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;

View file

@ -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;
}
}

View file

@ -0,0 +1,9 @@
package basics.algo;
import basics.algo.SearchStrategy.DiscoveredSolution;
public interface PrematureAlgorithmBreaker {
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution);
}

View file

@ -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<SearchStrategyModule> searchStrategyModules = new ArrayList<SearchStrategyModule>();
@ -86,14 +111,14 @@ public class SearchStrategy {
* <p>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}.
* <p> Note that after 1) the selected solution is copied, thus the original solution is not modified.
* <p> Note also that 3) modifies the input parameter solutions by adding, removing, replacing existing solutions.
* <p> 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<VehicleRoutingProblemSolution> solutions){
public DiscoveredSolution run(VehicleRoutingProblem vrp, Collection<VehicleRoutingProblemSolution> 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;
}

View file

@ -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<VehicleRoutingProblemSolution> solutions) {
reset();
}
@Override
public void informIterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
if(currentIteration == (nuOfIterations-1)){
reset();
}
else{
currentIteration++;
}
}
}