mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
Merge branch 'improvePrematureBreak' into benchmarking
This commit is contained in:
commit
6b7c1f035b
5 changed files with 177 additions and 18 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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