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

Merge branch 'master' into OPTI-871-serialize-vrp-object

This commit is contained in:
hilaminster 2019-10-31 09:52:48 +02:00
commit 5a96c58aca
3 changed files with 3 additions and 150 deletions

View file

@ -18,13 +18,9 @@
package com.graphhopper.jsprit.core.algorithm.termination;
import com.graphhopper.jsprit.core.algorithm.SearchStrategy;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
/**
* Terminates algorithm prematurely based on iterations without any improvement (i.e. new solution acceptance).
@ -43,28 +39,13 @@ public class IterationWithoutImprovementTermination implements PrematureAlgorith
private int iterationsWithoutImprovement = 0;
private List<Double> costs;
private List<Integer> unassignedJobsCount;
private double bestCost = Double.MAX_VALUE;
private double terminationByCostPercentage = 0.0;
/**
* Constructs termination.
*
* @param noIterationsWithoutImprovement previous iterations without any improvement
*/
public IterationWithoutImprovementTermination(int noIterationsWithoutImprovement) {
this(noIterationsWithoutImprovement, 0.0);
}
public IterationWithoutImprovementTermination(int noIterationsWithoutImprovement, double terminationByCostPercentage) {
this.noIterationWithoutImprovement = noIterationsWithoutImprovement;
this.terminationByCostPercentage = terminationByCostPercentage;
costs = new ArrayList<>();
unassignedJobsCount = new ArrayList<>();
log.debug("initialise " + this);
}
@ -75,43 +56,10 @@ public class IterationWithoutImprovementTermination implements PrematureAlgorith
@Override
public boolean isPrematureBreak(SearchStrategy.DiscoveredSolution discoveredSolution) {
if(this.terminationByCostPercentage == 0.0)
return checkStrictTerminationCondition(discoveredSolution);
else
return checkPercentageTerminationCondition(discoveredSolution);
}
private boolean checkStrictTerminationCondition(SearchStrategy.DiscoveredSolution discoveredSolution){
// The original logic that is counting the number of iterations without any change
if (discoveredSolution.isAccepted())
iterationsWithoutImprovement = 0;
else
iterationsWithoutImprovement++;
if (discoveredSolution.isAccepted()) iterationsWithoutImprovement = 0;
else iterationsWithoutImprovement++;
return (iterationsWithoutImprovement > noIterationWithoutImprovement);
}
private boolean checkPercentageTerminationCondition(SearchStrategy.DiscoveredSolution discoveredSolution){
// The alternative logic that detects also very slow improvment
// On large tasks small improvments to the route may significantly increase the runtime
VehicleRoutingProblemSolution sol = discoveredSolution.getSolution();
double currentCost = sol.getCost();
bestCost = Math.min(currentCost, bestCost);
costs.add(bestCost);
int currentJobsUnassigned = sol.getUnassignedJobs().size();
unassignedJobsCount.add(currentJobsUnassigned);
int i = costs.size() - 1;
if (i < noIterationWithoutImprovement)
return false;
boolean unassignedJobsEqual = (currentJobsUnassigned == unassignedJobsCount.get(i - noIterationWithoutImprovement));
boolean progressTooSlow = 100 * ((costs.get(i - noIterationWithoutImprovement) - bestCost) / bestCost) <= terminationByCostPercentage;
if (unassignedJobsEqual && progressTooSlow){
log.debug("Termination condition by percentage reached after " + Integer.toString(i) + " iterations.");
return true;
}
return false;
}
}

View file

@ -496,7 +496,7 @@ public class Shipment extends AbstractJob {
+ "][deliveryLocation=" + deliveryLocation_ + "][capacity=" + capacity
+ "][pickupServiceTime=" + pickupServiceTime + "][deliveryServiceTime="
+ deliveryServiceTime + "][pickupTimeWindows=" + pickupTimeWindows
+ "][deliveryTimeWindows=" + deliveryTimeWindows + "]";
+ "][deliveryTimeWindows=" + deliveryTimeWindows + "][userData=" + getUserData() + "]";
}

View file

@ -20,13 +20,8 @@ package com.graphhopper.jsprit.core.algorithm.termination;
import com.graphhopper.jsprit.core.algorithm.SearchStrategy;
import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -81,94 +76,4 @@ public class IterationsWithoutImprovementTest {
}
Assert.assertEquals(150, terminatedAfter);
}
@Test
public void isPrematureBreakZeroPercentage() {
int maxIterations = 200;
IterationWithoutImprovementTermination termination = new IterationWithoutImprovementTermination(100, 0);
SearchStrategy.DiscoveredSolution discoveredSolution = mock(SearchStrategy.DiscoveredSolution.class);
int terminatedAfter = maxIterations;
for (int i = 0; i < maxIterations; i++) {
when(discoveredSolution.isAccepted()).thenReturn(i< 50 ? true : false);
if (termination.isPrematureBreak(discoveredSolution)) {
terminatedAfter = i;
break;
}
}
Assert.assertEquals(150, terminatedAfter);
}
@Test
public void isPrematureBreakWithPercentageShouldBreak() {
int maxIterations = 200;
IterationWithoutImprovementTermination termination = new IterationWithoutImprovementTermination(10, 1.0);
SearchStrategy.DiscoveredSolution discoveredSolution = mock(SearchStrategy.DiscoveredSolution.class);
VehicleRoutingProblemSolution solution = mock(VehicleRoutingProblemSolution.class);
when(discoveredSolution.getSolution()).thenReturn(solution);
when(solution.getUnassignedJobs()).thenReturn(new ArrayList<Job>());
int terminatedAfter = maxIterations;
for (int i = 0; i < maxIterations; i++) {
when(solution.getCost()).thenReturn(i < 100 ? 100.0 - (0.1*i) : 40-((i-100)*0.01));
boolean terminate = termination.isPrematureBreak(discoveredSolution);
if (terminate) {
terminatedAfter = i;
break;
}
}
Assert.assertEquals(110, terminatedAfter);
}
@Test
public void isPrematureBreakWithPercentageCostNotImprovedButUnassignedImproved() {
int maxIterations = 200;
IterationWithoutImprovementTermination termination = new IterationWithoutImprovementTermination(10, 1.0);
SearchStrategy.DiscoveredSolution discoveredSolution = mock(SearchStrategy.DiscoveredSolution.class);
VehicleRoutingProblemSolution solution = mock(VehicleRoutingProblemSolution.class);
Job job = mock(Job.class);
when(discoveredSolution.getSolution()).thenReturn(solution);
List<Job> unassignedJobs = new ArrayList<>();
for (int i = 0; i < 100; i++) {
unassignedJobs.add(job);
}
int terminatedAfter = maxIterations;
for (int i = 0; i < maxIterations; i++) {
when(solution.getCost()).thenReturn(100.0);
if (i <= 50){
unassignedJobs.remove(0);
}
when(solution.getUnassignedJobs()).thenReturn(unassignedJobs);
boolean terminate = termination.isPrematureBreak(discoveredSolution);
if (terminate) {
terminatedAfter = i;
break;
}
}
Assert.assertEquals(60, terminatedAfter);
}
@Test
public void isPrematureBreakLastCostIsWorstShouldNotBreak() {
int maxIterations = 7;
IterationWithoutImprovementTermination termination = new IterationWithoutImprovementTermination(5, 1.0);
SearchStrategy.DiscoveredSolution discoveredSolution = mock(SearchStrategy.DiscoveredSolution.class);
VehicleRoutingProblemSolution solution = mock(VehicleRoutingProblemSolution.class);
when(discoveredSolution.getSolution()).thenReturn(solution);
when(solution.getUnassignedJobs()).thenReturn(new ArrayList<Job>());
boolean isTerminate = false;
for (int i = 0; i < maxIterations; i++) {
when(solution.getCost()).thenReturn(i < 6.0 ? 10.0-i : 12);
boolean terminate = termination.isPrematureBreak(discoveredSolution);
if (terminate) {
isTerminate= true;
break;
}
}
Assert.assertFalse(isTerminate);
}
}