diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/VehicleRoutingAlgorithm.java b/jsprit-core/src/main/java/jsprit/core/algorithm/VehicleRoutingAlgorithm.java
index 97475eb6..41fcdeac 100644
--- a/jsprit-core/src/main/java/jsprit/core/algorithm/VehicleRoutingAlgorithm.java
+++ b/jsprit-core/src/main/java/jsprit/core/algorithm/VehicleRoutingAlgorithm.java
@@ -97,15 +97,6 @@ public class VehicleRoutingAlgorithm {
private int maxIterations = 100;
- private PrematureAlgorithmTermination prematureAlgorithmTermination = new PrematureAlgorithmTermination() {
-
- @Override
- public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
- return false;
- }
-
- };
-
private TerminationManager terminationManager = new TerminationManager();
private VehicleRoutingProblemSolution bestEver = null;
@@ -158,7 +149,8 @@ public class VehicleRoutingAlgorithm {
}
/**
- * Sets premature termination.
+ * Sets premature termination and overrides existing termination criteria. If existing ones should not be
+ * overridden use .addTerminationCriterion(...).
*
* @param prematureAlgorithmTermination the termination criterion
*/
@@ -168,6 +160,12 @@ public class VehicleRoutingAlgorithm {
// this.prematureAlgorithmTermination = prematureAlgorithmTermination;
}
+ /**
+ * Adds a termination criterion to the collection of already specified termination criteria. If one
+ * of the termination criteria is fulfilled, the algorithm terminates prematurely.
+ *
+ * @param terminationCriterion the termination criterion
+ */
public void addTerminationCriterion(PrematureAlgorithmTermination terminationCriterion){
terminationManager.addTermination(terminationCriterion);
}
diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java b/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java
index 42705a3b..8827a82b 100644
--- a/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java
+++ b/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java
@@ -18,7 +18,6 @@ package jsprit.core.algorithm.io;
import jsprit.core.algorithm.*;
-import jsprit.core.algorithm.SearchStrategy.DiscoveredSolution;
import jsprit.core.algorithm.acceptor.*;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.*;
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
@@ -606,8 +605,16 @@ public class VehicleRoutingAlgorithms {
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager));
//define prematureBreak
- PrematureAlgorithmTermination prematureAlgoBreaker = getPrematureBreaker(config,algorithmListeners);
- metaAlgorithm.setPrematureAlgorithmTermination(prematureAlgoBreaker);
+ PrematureAlgorithmTermination prematureAlgorithmTermination = getPrematureTermination(config, algorithmListeners);
+ if(prematureAlgorithmTermination != null) metaAlgorithm.setPrematureAlgorithmTermination(prematureAlgorithmTermination);
+ else{
+ List terminationCriteria = config.configurationsAt("terminationCriteria.termination");
+ for(HierarchicalConfiguration terminationConfig : terminationCriteria){
+ PrematureAlgorithmTermination termination = getTerminationCriterion(terminationConfig, algorithmListeners);
+ if(termination != null) metaAlgorithm.addTerminationCriterion(termination);
+ }
+ }
+
//misc
// algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
@@ -634,17 +641,48 @@ public class VehicleRoutingAlgorithms {
"makes sure your config file contains one of these options");
}
- private static PrematureAlgorithmTermination getPrematureBreaker(XMLConfiguration config, Set algorithmListeners) {
+ private static PrematureAlgorithmTermination getTerminationCriterion(HierarchicalConfiguration config, Set algorithmListeners) {
+ String basedOn = config.getString("[@basedOn]");
+ if(basedOn == null){
+ log.info("set default prematureBreak, i.e. no premature break at all.");
+ return null;
+ }
+ if(basedOn.equals("iterations")){
+ log.info("set prematureBreak based on iterations");
+ String iter = config.getString("iterations");
+ if(iter == null) throw new IllegalStateException("iterations is missing");
+ int iterations = Integer.valueOf(iter);
+ return new IterationWithoutImprovementTermination(iterations);
+ }
+ if(basedOn.equals("time")){
+ log.info("set prematureBreak based on time");
+ String timeString = config.getString("time");
+ if(timeString == null) throw new IllegalStateException("time is missing");
+ double time = Double.valueOf(timeString);
+ TimeTermination timeBreaker = new TimeTermination(time);
+ algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, timeBreaker));
+ return timeBreaker;
+ }
+ if(basedOn.equals("variationCoefficient")){
+ log.info("set prematureBreak based on variation coefficient");
+ String thresholdString = config.getString("threshold");
+ String iterationsString = config.getString("iterations");
+ if(thresholdString == null) throw new IllegalStateException("threshold is missing");
+ if(iterationsString == null) throw new IllegalStateException("iterations is missing");
+ double threshold = Double.valueOf(thresholdString);
+ int iterations = Integer.valueOf(iterationsString);
+ VariationCoefficientTermination variationCoefficientBreaker = new VariationCoefficientTermination(iterations, threshold);
+ algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, variationCoefficientBreaker));
+ return variationCoefficientBreaker;
+ }
+ throw new IllegalStateException("prematureBreak basedOn " + basedOn + " is not defined");
+ }
+
+ private static PrematureAlgorithmTermination getPrematureTermination(XMLConfiguration config, Set algorithmListeners) {
String basedOn = config.getString("prematureBreak[@basedOn]");
if(basedOn == null){
log.info("set default prematureBreak, i.e. no premature break at all.");
- return new PrematureAlgorithmTermination() {
-
- @Override
- public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
- return false;
- }
- };
+ return null;
}
if(basedOn.equals("iterations")){
log.info("set prematureBreak based on iterations");
diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/VehicleRoutingAlgorithmTest.java b/jsprit-core/src/test/java/jsprit/core/algorithm/VehicleRoutingAlgorithmTest.java
index d7c3c2f6..b8462332 100644
--- a/jsprit-core/src/test/java/jsprit/core/algorithm/VehicleRoutingAlgorithmTest.java
+++ b/jsprit-core/src/test/java/jsprit/core/algorithm/VehicleRoutingAlgorithmTest.java
@@ -143,4 +143,43 @@ public class VehicleRoutingAlgorithmTest {
assertEquals(50,counter.getCountIterations());
}
+ @Test
+ public void whenAddingPrematureTwoTerminationCriteria_itIsExecutedCorrectly(){
+ SearchStrategyManager stratManager = mock(SearchStrategyManager.class);
+ VehicleRoutingAlgorithm algorithm = new VehicleRoutingAlgorithm(mock(VehicleRoutingProblem.class),stratManager);
+ when(stratManager.getRandomStrategy()).thenReturn(mock(SearchStrategy.class));
+ when(stratManager.getProbabilities()).thenReturn(Arrays.asList(1.0));
+ algorithm.setMaxIterations(1000);
+ PrematureAlgorithmTermination termination = new PrematureAlgorithmTermination() {
+
+ private int nuOfIterations = 1;
+
+ @Override
+ public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
+ if(nuOfIterations == 50) return true;
+ nuOfIterations++;
+ return false;
+ }
+
+ };
+ PrematureAlgorithmTermination termination2 = new PrematureAlgorithmTermination() {
+
+ private int nuOfIterations = 1;
+
+ @Override
+ public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
+ if(nuOfIterations == 25) return true;
+ nuOfIterations++;
+ return false;
+ }
+
+ };
+ CountIterations counter = new CountIterations();
+ algorithm.addListener(counter);
+ algorithm.addTerminationCriterion(termination);
+ algorithm.addTerminationCriterion(termination2);
+ algorithm.searchSolutions();
+ assertEquals(25,counter.getCountIterations());
+ }
+
}
diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/io/TestAlgorithmReader.java b/jsprit-core/src/test/java/jsprit/core/algorithm/io/TestAlgorithmReader.java
index bcd4d4d2..4a839675 100644
--- a/jsprit-core/src/test/java/jsprit/core/algorithm/io/TestAlgorithmReader.java
+++ b/jsprit-core/src/test/java/jsprit/core/algorithm/io/TestAlgorithmReader.java
@@ -99,7 +99,7 @@ public class TestAlgorithmReader {
IterationCounter iCounter = new IterationCounter();
vra.addListener(iCounter);
vra.searchSolutions();
- Assert.assertEquals(100,iCounter.iterations);
+ Assert.assertEquals(25,iCounter.iterations);
}
diff --git a/jsprit-core/src/test/resources/algorithmConfigForReaderTest.xml b/jsprit-core/src/test/resources/algorithmConfigForReaderTest.xml
index 7129aa61..e30dc37c 100755
--- a/jsprit-core/src/test/resources/algorithmConfigForReaderTest.xml
+++ b/jsprit-core/src/test/resources/algorithmConfigForReaderTest.xml
@@ -25,6 +25,9 @@
100
+
+ 25
+