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:
parent
cc47719eac
commit
b6bc3e0d93
5 changed files with 177 additions and 18 deletions
|
|
@ -31,7 +31,10 @@ import basics.algo.AlgorithmEndsListener;
|
||||||
import basics.algo.AlgorithmStartsListener;
|
import basics.algo.AlgorithmStartsListener;
|
||||||
import basics.algo.IterationEndsListener;
|
import basics.algo.IterationEndsListener;
|
||||||
import basics.algo.IterationStartsListener;
|
import basics.algo.IterationStartsListener;
|
||||||
|
import basics.algo.IterationWithoutImprovementBreaker;
|
||||||
|
import basics.algo.PrematureAlgorithmBreaker;
|
||||||
import basics.algo.SearchStrategy;
|
import basics.algo.SearchStrategy;
|
||||||
|
import basics.algo.SearchStrategy.DiscoveredSolution;
|
||||||
import basics.algo.SearchStrategyManager;
|
import basics.algo.SearchStrategyManager;
|
||||||
import basics.algo.VehicleRoutingAlgorithmListener;
|
import basics.algo.VehicleRoutingAlgorithmListener;
|
||||||
import basics.algo.VehicleRoutingAlgorithmListeners;
|
import basics.algo.VehicleRoutingAlgorithmListeners;
|
||||||
|
|
@ -44,6 +47,8 @@ import basics.algo.VehicleRoutingAlgorithmListeners;
|
||||||
*/
|
*/
|
||||||
public class VehicleRoutingAlgorithm {
|
public class VehicleRoutingAlgorithm {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static final int NOBREAK = Integer.MAX_VALUE;
|
public static final int NOBREAK = Integer.MAX_VALUE;
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(VehicleRoutingAlgorithm.class);
|
private static Logger logger = Logger.getLogger(VehicleRoutingAlgorithm.class);
|
||||||
|
|
@ -52,8 +57,6 @@ public class VehicleRoutingAlgorithm {
|
||||||
|
|
||||||
private int nOfIterations = 100;
|
private int nOfIterations = 100;
|
||||||
|
|
||||||
private int prematureBreak = NOBREAK;
|
|
||||||
|
|
||||||
private Counter counter = new Counter("iterations ");
|
private Counter counter = new Counter("iterations ");
|
||||||
|
|
||||||
private SearchStrategyManager searchStrategyManager;
|
private SearchStrategyManager searchStrategyManager;
|
||||||
|
|
@ -62,6 +65,15 @@ public class VehicleRoutingAlgorithm {
|
||||||
|
|
||||||
private Collection<VehicleRoutingProblemSolution> initialSolutions;
|
private Collection<VehicleRoutingProblemSolution> initialSolutions;
|
||||||
|
|
||||||
|
private PrematureAlgorithmBreaker prematureAlgorithmBreaker = new PrematureAlgorithmBreaker() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
public VehicleRoutingAlgorithm(VehicleRoutingProblem problem, SearchStrategyManager searchStrategyManager) {
|
public VehicleRoutingAlgorithm(VehicleRoutingProblem problem, SearchStrategyManager searchStrategyManager) {
|
||||||
super();
|
super();
|
||||||
this.problem = problem;
|
this.problem = problem;
|
||||||
|
|
@ -93,10 +105,14 @@ public class VehicleRoutingAlgorithm {
|
||||||
* the assigned number of iterations without solution-acceptance.
|
* the assigned number of iterations without solution-acceptance.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param iterationsWithoutImprovement
|
* @param nuIterationsWithoutImprovement
|
||||||
*/
|
*/
|
||||||
public void setPrematureBreak(int iterationsWithoutImprovement){
|
public void setPrematureBreak(int nuIterationsWithoutImprovement){
|
||||||
prematureBreak = iterationsWithoutImprovement;
|
prematureAlgorithmBreaker = new IterationWithoutImprovementBreaker(nuIterationsWithoutImprovement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrematureAlgorithmBreaker(PrematureAlgorithmBreaker prematureAlgorithmBreaker){
|
||||||
|
this.prematureAlgorithmBreaker = prematureAlgorithmBreaker;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -127,17 +143,14 @@ public class VehicleRoutingAlgorithm {
|
||||||
counter.reset();
|
counter.reset();
|
||||||
Collection<VehicleRoutingProblemSolution> solutions = new ArrayList<VehicleRoutingProblemSolution>(initialSolutions);
|
Collection<VehicleRoutingProblemSolution> solutions = new ArrayList<VehicleRoutingProblemSolution>(initialSolutions);
|
||||||
algorithmStarts(problem,solutions);
|
algorithmStarts(problem,solutions);
|
||||||
int iterWithoutImprovement = 0;
|
|
||||||
logger.info("iterations start");
|
logger.info("iterations start");
|
||||||
for(int i=0;i<nOfIterations;i++){
|
for(int i=0;i<nOfIterations;i++){
|
||||||
iterationStarts(i+1,problem,solutions);
|
iterationStarts(i+1,problem,solutions);
|
||||||
counter.incCounter();
|
counter.incCounter();
|
||||||
SearchStrategy strat = searchStrategyManager.getRandomStrategy();
|
SearchStrategy strategy = searchStrategyManager.getRandomStrategy();
|
||||||
boolean newSolutionFoundAndAccepted = strat.run(problem, solutions);
|
DiscoveredSolution discoveredSolution = strategy.run(problem, solutions);
|
||||||
selectedStrategy(strat.getName(),problem, solutions);
|
selectedStrategy(strategy.getName(),problem, solutions);
|
||||||
if(newSolutionFoundAndAccepted) iterWithoutImprovement = 0;
|
if(prematureAlgorithmBreaker.isPrematureBreak(discoveredSolution)){
|
||||||
else iterWithoutImprovement++;
|
|
||||||
if(iterWithoutImprovement > prematureBreak){
|
|
||||||
logger.info("premature break at iteration "+ (i+1));
|
logger.info("premature break at iteration "+ (i+1));
|
||||||
nuOfIterationsThisAlgoIsRunning = (i+1);
|
nuOfIterationsThisAlgoIsRunning = (i+1);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package basics.algo;
|
||||||
|
|
||||||
|
import basics.algo.SearchStrategy.DiscoveredSolution;
|
||||||
|
|
||||||
|
public interface PrematureAlgorithmBreaker {
|
||||||
|
|
||||||
|
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -26,11 +26,10 @@ import java.util.Collections;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import basics.VehicleRoutingProblem;
|
|
||||||
import basics.VehicleRoutingProblemSolution;
|
|
||||||
|
|
||||||
import algorithms.acceptors.SolutionAcceptor;
|
import algorithms.acceptors.SolutionAcceptor;
|
||||||
import algorithms.selectors.SolutionSelector;
|
import algorithms.selectors.SolutionSelector;
|
||||||
|
import basics.VehicleRoutingProblem;
|
||||||
|
import basics.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -38,6 +37,32 @@ import algorithms.selectors.SolutionSelector;
|
||||||
|
|
||||||
public class SearchStrategy {
|
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 static Logger logger = Logger.getLogger(SearchStrategy.class);
|
||||||
|
|
||||||
private Collection<SearchStrategyModule> searchStrategyModules = new ArrayList<SearchStrategyModule>();
|
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
|
* <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}.
|
* ({@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 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 vrp
|
||||||
* @param solutions which will be modified
|
* @param solutions which will be modified
|
||||||
* @return boolean true if solution has been accepted, false otherwise
|
* @return boolean true if solution has been accepted, false otherwise
|
||||||
* @see SolutionSelector, SearchStrategyModule, SolutionAcceptor
|
* @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);
|
VehicleRoutingProblemSolution solution = solutionSelector.selectSolution(solutions);
|
||||||
if(solution == null) throw new IllegalStateException("solution is null. check solutionSelector to return an appropiate solution.");
|
if(solution == null) throw new IllegalStateException("solution is null. check solutionSelector to return an appropiate solution.");
|
||||||
VehicleRoutingProblemSolution lastSolution = VehicleRoutingProblemSolution.copyOf(solution);
|
VehicleRoutingProblemSolution lastSolution = VehicleRoutingProblemSolution.copyOf(solution);
|
||||||
|
|
@ -102,7 +127,8 @@ public class SearchStrategy {
|
||||||
lastSolution = newSolution;
|
lastSolution = newSolution;
|
||||||
}
|
}
|
||||||
boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution);
|
boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution);
|
||||||
return solutionAccepted;
|
DiscoveredSolution discoveredSolution = new DiscoveredSolution(lastSolution, solutionAccepted, getName());
|
||||||
|
return discoveredSolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue