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

break feature

This commit is contained in:
oblonski 2015-09-23 18:19:32 +02:00
parent a55ea8f3cf
commit 1919c05ceb
6 changed files with 34 additions and 247 deletions

View file

@ -17,6 +17,7 @@ import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.solution.SolutionCostCalculator; import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.BreakActivity;
import jsprit.core.problem.solution.route.activity.TourActivity; import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.FiniteFleetManagerFactory; import jsprit.core.problem.vehicle.FiniteFleetManagerFactory;
import jsprit.core.problem.vehicle.InfiniteFleetManagerFactory; import jsprit.core.problem.vehicle.InfiniteFleetManagerFactory;
@ -485,8 +486,10 @@ public class Jsprit {
vra.addListener(noiseMaker); vra.addListener(noiseMaker);
vra.addListener(noise); vra.addListener(noise);
vra.addListener(clusters); vra.addListener(clusters);
vra.addListener(new RuinBreaks());
handleExecutorShutdown(vra); handleExecutorShutdown(vra);
vra.setMaxIterations(Integer.valueOf(properties.getProperty(Parameter.ITERATIONS.toString()))); vra.setMaxIterations(Integer.valueOf(properties.getProperty(Parameter.ITERATIONS.toString())));
return vra; return vra;
} }
@ -546,15 +549,24 @@ public class Jsprit {
@Override @Override
public double getCosts(VehicleRoutingProblemSolution solution) { public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.; double costs = 0.;
for (VehicleRoute route : solution.getRoutes()) { for (VehicleRoute route : solution.getRoutes()) {
costs += route.getVehicle().getType().getVehicleCostParams().fix; costs += route.getVehicle().getType().getVehicleCostParams().fix;
boolean hasBreak = false;
TourActivity prevAct = route.getStart(); TourActivity prevAct = route.getStart();
for (TourActivity act : route.getActivities()) { for (TourActivity act : route.getActivities()) {
if(act instanceof BreakActivity) hasBreak = true;
costs += vrp.getTransportCosts().getTransportCost(prevAct.getLocation(), act.getLocation(), prevAct.getEndTime(), route.getDriver(), route.getVehicle()); costs += vrp.getTransportCosts().getTransportCost(prevAct.getLocation(), act.getLocation(), prevAct.getEndTime(), route.getDriver(), route.getVehicle());
costs += vrp.getActivityCosts().getActivityCost(act, act.getArrTime(), route.getDriver(), route.getVehicle()); costs += vrp.getActivityCosts().getActivityCost(act, act.getArrTime(), route.getDriver(), route.getVehicle());
prevAct = act; prevAct = act;
} }
costs += vrp.getTransportCosts().getTransportCost(prevAct.getLocation(), route.getEnd().getLocation(), prevAct.getEndTime(), route.getDriver(), route.getVehicle()); costs += vrp.getTransportCosts().getTransportCost(prevAct.getLocation(), route.getEnd().getLocation(), prevAct.getEndTime(), route.getDriver(), route.getVehicle());
if(route.getVehicle().getBreak() != null){
if(!hasBreak){
//break defined but not assigned penalty
costs += maxCosts * 2;
}
}
} }
costs += solution.getUnassignedJobs().size() * maxCosts * 2; costs += solution.getUnassignedJobs().size() * maxCosts * 2;
return costs; return costs;

View file

@ -25,7 +25,7 @@ public class RuinBreaks implements RuinListener {
Break aBreak = r.getVehicle().getBreak(); Break aBreak = r.getVehicle().getBreak();
if(aBreak != null){ if(aBreak != null){
r.getTourActivities().removeJob(aBreak); r.getTourActivities().removeJob(aBreak);
logger.trace("ruin: " + aBreak.getId()); logger.trace("ruin: {}",aBreak.getId());
unassignedJobs.add(aBreak); unassignedJobs.add(aBreak);
} }
} }

View file

@ -28,7 +28,7 @@ import jsprit.core.problem.Skills;
*/ */
public class Break extends Service { public class Break extends Service {
public static class Builder extends Service.Builder { public static class Builder extends Service.Builder<Break> {
/** /**
* Returns a new instance of builder that builds a pickup. * Returns a new instance of builder that builds a pickup.

View file

@ -88,10 +88,11 @@ public class VehicleImpl extends AbstractVehicle {
public Skills getSkills() { public Skills getSkills() {
return null; return null;
} }
}
@Override @Override
public Break getBreak() { return null; } public Break getBreak() { return null; }
} }
/** /**
@ -201,28 +202,6 @@ public class VehicleImpl extends AbstractVehicle {
return this; return this;
} }
/**
* Sets earliest-start of vehicle which should be the lower bound of the vehicle's departure times.
*
* @param earliest_startTime the earliest start time / departure time of the vehicle at its start location
* @return this builder
*/
public Builder setEarliestStart(double earliest_startTime) {
this.earliestStart = earliest_startTime;
return this;
}
/**
* Sets the latest arrival at vehicle's end-location which is the upper bound of the vehicle's arrival times.
*
* @param latest_arrTime the latest arrival time of the vehicle at its end location
* @return this builder
*/
public Builder setLatestArrival(double latest_arrTime) {
this.latestArrival = latest_arrTime;
return this;
}
public Builder addSkill(String skill) { public Builder addSkill(String skill) {
skillBuilder.addSkill(skill); skillBuilder.addSkill(skill);
return this; return this;
@ -294,8 +273,6 @@ public class VehicleImpl extends AbstractVehicle {
private final String id; private final String id;
private final String id;
private final VehicleType type; private final VehicleType type;
private final double earliestDeparture; private final double earliestDeparture;
@ -339,23 +316,9 @@ public class VehicleImpl extends AbstractVehicle {
"[endLocation=" + endLocation + "]" + "[endLocation=" + endLocation + "]" +
"[isReturnToDepot=" + isReturnToDepot() + "]" + "[isReturnToDepot=" + isReturnToDepot() + "]" +
"[skills=" + skills + "]"; "[skills=" + skills + "]";
/**
* Returns String with attributes of this vehicle
* <p/>
* <p>String has the following format [attr1=val1][attr2=val2]...[attrn=valn]
*/
@Override
public String toString() {
return "[id=" + id + "]" +
"[type=" + type + "]" +
"[startLocation=" + startLocation + "]" +
"[endLocation=" + endLocation + "]" +
"[isReturnToDepot=" + isReturnToDepot() + "]" +
"[skills=" + skills + "]";
} }
@Override @Override
public double getEarliestDeparture() { public double getEarliestDeparture() {
return earliestDeparture; return earliestDeparture;
@ -437,7 +400,5 @@ public class VehicleImpl extends AbstractVehicle {
return true; return true;
} }
} }

View file

@ -37,191 +37,6 @@ public class VehicleImplTest {
Vehicle v = VehicleImpl.Builder.newInstance("v").build(); Vehicle v = VehicleImpl.Builder.newInstance("v").build();
} }
@Test
public void whenVehicleIsBuiltToReturnToDepot_itShouldReturnToDepot(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setReturnToDepot(true).setStartLocation(Location.newInstance("loc")).build();
assertTrue(v.isReturnToDepot());
}
@Test
public void whenVehicleIsBuiltToNotReturnToDepot_itShouldNotReturnToDepot(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setReturnToDepot(false).setStartLocation(Location.newInstance("loc")).build();
assertFalse(v.isReturnToDepot());
}
@Test
public void whenVehicleIsBuiltWithLocation_itShouldHvTheCorrectLocation(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("loc")).build();
assertEquals("loc",v.getStartLocation().getId());
}
@Test
public void whenVehicleIsBuiltWithCoord_itShouldHvTheCorrectCoord(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(1, 2)).build();
assertEquals(1.0,v.getStartLocation().getCoordinate().getX(),0.01);
assertEquals(2.0,v.getStartLocation().getCoordinate().getY(),0.01);
}
@Test
public void whenVehicleIsBuiltAndEarliestStartIsNotSet_itShouldSetTheDefaultOfZero(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(1, 2)).build();
assertEquals(0.0,v.getEarliestDeparture(),0.01);
}
@Test
public void whenVehicleIsBuiltAndEarliestStartSet_itShouldBeSetCorrectly(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setEarliestStart(10.0).setStartLocation(Location.newInstance(1, 2)).build();
assertEquals(10.0,v.getEarliestDeparture(),0.01);
}
@Test
public void whenVehicleIsBuiltAndLatestArrivalIsNotSet_itShouldSetDefaultOfDoubleMaxValue(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(1, 2)).build();
assertEquals(Double.MAX_VALUE,v.getLatestArrival(),0.01);
}
@Test
public void whenVehicleIsBuiltAndLatestArrivalIsSet_itShouldBeSetCorrectly(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setLatestArrival(30.0).setStartLocation(Location.newInstance(1, 2)).build();
assertEquals(30.0,v.getLatestArrival(),0.01);
}
@Test
public void whenNoVehicleIsCreate_itShouldHvTheCorrectId(){
Vehicle v = VehicleImpl.createNoVehicle();
assertEquals("noVehicle",v.getId());
}
@Test
public void whenStartLocationIsSet_itIsDoneCorrectly(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("startLoc")).build();
assertEquals("startLoc", v.getStartLocation().getId());
}
@Test(expected=IllegalStateException.class)
public void whenStartLocationIsNull_itThrowsException(){
@SuppressWarnings("unused")
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(null)).build();
}
@Test
public void whenStartLocationCoordIsSet_itIsDoneCorrectly(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(1, 2)).build();
assertEquals(1.0, v.getStartLocation().getCoordinate().getX(),0.01);
assertEquals(2.0, v.getStartLocation().getCoordinate().getY(),0.01);
}
@Test
public void whenEndLocationIsSet_itIsDoneCorrectly(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("startLoc")).setEndLocation(Location.newInstance("endLoc")).build();
assertEquals("startLoc", v.getStartLocation().getId());
assertEquals("endLoc", v.getEndLocation().getId());
}
@Test
public void whenEndLocationCoordIsSet_itIsDoneCorrectly(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("startLoc")).setEndLocation(Location.newInstance(1, 2)).build();
assertEquals(1.0, v.getEndLocation().getCoordinate().getX(),0.01);
assertEquals(2.0, v.getEndLocation().getCoordinate().getY(),0.01);
}
@Test
public void whenNeitherEndLocationIdNorEndLocationCoordAreSet_endLocationIdMustBeEqualToStartLocationId(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("startLoc")).build();
assertEquals("startLoc", v.getEndLocation().getId());
}
@Test
public void whenNeitherEndLocationIdNorEndLocationCoordAreSet_endLocationCoordMustBeEqualToStartLocationCoord(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("startLoc")).build();
assertEquals(v.getEndLocation().getCoordinate(), v.getStartLocation().getCoordinate());
}
@Test
public void whenNeitherEndLocationIdNorEndLocationCoordAreSet_endLocationCoordMustBeEqualToStartLocationCoordV2(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(1.0, 2.0)).build();
assertEquals(v.getEndLocation().getCoordinate(), v.getStartLocation().getCoordinate());
}
@Test
public void whenEndLocationCoordinateIsSetButNoId_idMustBeCoordToString(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(1.0, 2.0)).setEndLocation(Location.newInstance(3.0, 4.0)).build();
assertEquals(v.getEndLocation().getCoordinate().toString(), v.getEndLocation().getId());
}
@Test(expected=IllegalStateException.class)
public void whenEndLocationIdIsSpecifiedANDReturnToDepotIsFalse_itShouldThrowException(){
@SuppressWarnings("unused")
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(1.0, 2.0)).setEndLocation(Location.newInstance("endLoc")).setReturnToDepot(false).build();
}
@Test(expected=IllegalStateException.class)
public void whenEndLocationCoordIsSpecifiedANDReturnToDepotIsFalse_itShouldThrowException(){
@SuppressWarnings("unused")
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(1.0, 2.0)).setEndLocation(Location.newInstance(3, 4)).setReturnToDepot(false).build();
}
@Test
public void whenEndLocationCoordIsNotSpecifiedANDReturnToDepotIsFalse_endLocationCoordMustBeStartLocationCoord(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(1.0, 2.0)).setReturnToDepot(false).build();
assertEquals(v.getStartLocation().getCoordinate(),v.getEndLocation().getCoordinate());
}
@Test
public void whenEndLocationIdIsNotSpecifiedANDReturnToDepotIsFalse_endLocationIdMustBeStartLocationId(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(1.0, 2.0)).setReturnToDepot(false).build();
assertEquals(v.getStartLocation().getCoordinate().toString(),v.getEndLocation().getId());
}
@Test(expected=IllegalStateException.class)
public void whenStartAndEndAreUnequalANDReturnToDepotIsFalse_itShouldThrowException(){
@SuppressWarnings("unused")
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("start")).setEndLocation(Location.newInstance("end")).setReturnToDepot(false).build();
}
@Test
public void whenStartAndEndAreEqualANDReturnToDepotIsFalse_itShouldThrowException(){
@SuppressWarnings("unused")
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("start")).setEndLocation(Location.newInstance("start")).setReturnToDepot(false).build();
assertTrue(true);
}
@Test
public void whenTwoVehiclesHaveTheSameId_theyShouldBeEqual(){
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("start")).setEndLocation(Location.newInstance("start")).setReturnToDepot(false).build();
Vehicle v2 = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("start")).setEndLocation(Location.newInstance("start")).setReturnToDepot(false).build();
assertTrue(v.equals(v2));
}
@Test
public void whenAddingSkills_theyShouldBeAddedCorrectly(){
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("type").build();
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("start")).setType(type1).setEndLocation(Location.newInstance("start"))
.addSkill("drill").addSkill("screwdriver").build();
assertTrue(v.getSkills().containsSkill("drill"));
assertTrue(v.getSkills().containsSkill("drill"));
assertTrue(v.getSkills().containsSkill("screwdriver"));
}
@Test
public void whenAddingSkillsCaseSens_theyShouldBeAddedCorrectly(){
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("type").build();
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("start")).setType(type1).setEndLocation(Location.newInstance("start"))
.addSkill("drill").addSkill("screwdriver").build();
assertTrue(v.getSkills().containsSkill("drill"));
assertTrue(v.getSkills().containsSkill("dRill"));
assertTrue(v.getSkills().containsSkill("ScrewDriver"));
}
@Test
public void whenAddingSkillsCaseSensV2_theyShouldBeAddedCorrectly(){
VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("type").build();
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("start")).setType(type1).setEndLocation(Location.newInstance("start"))
.addSkill("drill").build();
assertFalse(v.getSkills().containsSkill("ScrewDriver"));
}
@Test @Test
public void whenAddingDriverBreak_itShouldBeAddedCorrectly(){ public void whenAddingDriverBreak_itShouldBeAddedCorrectly(){

View file

@ -19,7 +19,6 @@ package jsprit.examples;
import jsprit.analysis.toolbox.Plotter; import jsprit.analysis.toolbox.Plotter;
import jsprit.core.algorithm.VehicleRoutingAlgorithm; import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.box.Jsprit; import jsprit.core.algorithm.box.Jsprit;
import jsprit.core.algorithm.ruin.RuinBreaks;
import jsprit.core.problem.Location; import jsprit.core.problem.Location;
import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Break; import jsprit.core.problem.job.Break;
@ -56,7 +55,8 @@ public class BreakExample {
*/ */
Builder vehicleBuilder = Builder.newInstance("v1"); Builder vehicleBuilder = Builder.newInstance("v1");
vehicleBuilder.setStartLocation(Location.newInstance(10, 10)); vehicleBuilder.setStartLocation(Location.newInstance(10, 10));
Break myFirstBreak = (Break) Break.Builder.newInstance("myFirstBreak").setTimeWindow(TimeWindow.newInstance(10, 15)).setServiceTime(100).build(); Break myFirstBreak = Break.Builder.newInstance("myFirstBreak")
.setTimeWindow(TimeWindow.newInstance(10, 15)).setServiceTime(100).build();
vehicleBuilder.setBreak(myFirstBreak); vehicleBuilder.setBreak(myFirstBreak);
vehicleBuilder.setType(vehicleType); vehicleBuilder.setType(vehicleType);
VehicleImpl vehicle = vehicleBuilder.build(); VehicleImpl vehicle = vehicleBuilder.build();
@ -85,7 +85,6 @@ public class BreakExample {
VehicleRoutingAlgorithm algorithm = Jsprit.Builder.newInstance(problem) VehicleRoutingAlgorithm algorithm = Jsprit.Builder.newInstance(problem)
.setProperty(Jsprit.Strategy.CLUSTER_REGRET,"0.") .setProperty(Jsprit.Strategy.CLUSTER_REGRET,"0.")
.setProperty(Jsprit.Strategy.CLUSTER_BEST,"0.").buildAlgorithm(); .setProperty(Jsprit.Strategy.CLUSTER_BEST,"0.").buildAlgorithm();
algorithm.addListener(new RuinBreaks());
/* /*
* and search a solution * and search a solution
*/ */