diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/CalculatorBuilder.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/CalculatorBuilder.java
index 32ec036a..aedae439 100644
--- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/CalculatorBuilder.java
+++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/CalculatorBuilder.java
@@ -253,7 +253,7 @@ class CalculatorBuilder {
}
ShipmentInsertionCalculator shipmentInsertion = new ShipmentInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
- ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
+ ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), constraintManager);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
switcher.put(Shipment.class, shipmentInsertion);
@@ -263,8 +263,6 @@ class CalculatorBuilder {
PenalyzeInsertionCostsWithPenaltyVehicle penalyzeInsertionCosts = new PenalyzeInsertionCostsWithPenaltyVehicle(switcher);
-// JobInsertionCostsCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
-// ((ServiceInsertionCalculator) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(penalyzeInsertionCosts);
return calcPlusListeners;
diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/ServiceInsertionCalculator.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/ServiceInsertionCalculator.java
index 1a1ead9c..c8000ac3 100644
--- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/ServiceInsertionCalculator.java
+++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/ServiceInsertionCalculator.java
@@ -16,10 +16,12 @@
******************************************************************************/
package jsprit.core.algorithm.recreate;
-import jsprit.core.algorithm.recreate.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
+import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint.ConstraintsStatus;
import jsprit.core.problem.constraint.HardRouteStateLevelConstraint;
+import jsprit.core.problem.constraint.SoftActivityConstraint;
+import jsprit.core.problem.constraint.SoftRouteConstraint;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
@@ -34,13 +36,15 @@ import jsprit.core.problem.solution.route.activity.TourActivityFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import jsprit.core.util.CalculationUtils;
-import jsprit.core.util.Neighborhood;
import org.apache.log4j.Logger;
-
-
-
+/**
+ * Calculator that calculates the best insertion position for a {@link Service}.
+ *
+ * @author schroeder
+ *
+ */
final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(ServiceInsertionCalculator.class);
@@ -49,32 +53,21 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{
private HardActivityStateLevelConstraint hardActivityLevelConstraint;
- private Neighborhood neighborhood = new Neighborhood() {
-
- @Override
- public boolean areNeighbors(String location1, String location2) {
- return true;
- }
- };
+ private SoftRouteConstraint softRouteConstraint;
- private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
+ private SoftActivityConstraint softActivityConstraint;
private VehicleRoutingTransportCosts transportCosts;
private TourActivityFactory activityFactory;
-
- public void setNeighborhood(Neighborhood neighborhood) {
- this.neighborhood = neighborhood;
- logger.info("initialise neighborhood " + neighborhood);
- }
-
- public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteStateLevelConstraint hardRouteLevelConstraint, HardActivityStateLevelConstraint hardActivityLevelConstraint) {
+ public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ConstraintManager constraintManager) {
super();
- this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
- this.hardRouteLevelConstraint = hardRouteLevelConstraint;
- this.hardActivityLevelConstraint = hardActivityLevelConstraint;
this.transportCosts = routingCosts;
+ hardRouteLevelConstraint = constraintManager;
+ hardActivityLevelConstraint = constraintManager;
+ softActivityConstraint = constraintManager;
+ softRouteConstraint = constraintManager;
activityFactory = new DefaultTourActivityFactory();
logger.info("initialise " + this);
}
@@ -100,7 +93,10 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{
}
double bestCost = bestKnownCosts;
- ActivityInsertionCosts bestMarginals = null;
+
+ //from job2insert induced costs at route level
+ double routeICosts = softRouteConstraint.getCosts(insertionContext);
+
Service service = (Service)jobToInsert;
int insertionIndex = InsertionData.NO_INDEX;
@@ -115,21 +111,19 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{
int actIndex = 0;
boolean loopBroken = false;
for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){
- if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
- ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
- if(status.equals(ConstraintsStatus.FULFILLED)){
- ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
- if(mc.getAdditionalCosts() < bestCost){
- bestCost = mc.getAdditionalCosts();
- bestMarginals = mc;
- insertionIndex = actIndex;
- }
- }
- else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
- loopBroken = true;
- break;
+ ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
+ if(status.equals(ConstraintsStatus.FULFILLED)){
+ //from job2insert induced costs at activity level
+ double activityICosts = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
+ if(routeICosts + activityICosts < bestCost){
+ bestCost = routeICosts + activityICosts;
+ insertionIndex = actIndex;
}
}
+ else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
+ loopBroken = true;
+ break;
+ }
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle);
double nextActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
prevActStartTime = nextActEndTime;
@@ -138,29 +132,21 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{
}
End nextAct = end;
if(!loopBroken){
- if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
- ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
- if(status.equals(ConstraintsStatus.FULFILLED)){
- ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
- if(mc.getAdditionalCosts() < bestCost){
- bestCost = mc.getAdditionalCosts();
- bestMarginals = mc;
- insertionIndex = actIndex;
- }
+ ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
+ if(status.equals(ConstraintsStatus.FULFILLED)){
+ double activityICosts = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
+ if(routeICosts + activityICosts < bestCost){
+ bestCost = routeICosts + activityICosts;
+ insertionIndex = actIndex;
}
}
}
-
if(insertionIndex == InsertionData.NO_INDEX) {
return InsertionData.createEmptyInsertionData();
}
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
- insertionData.setAdditionalTime(bestMarginals.getAdditionalTime());
return insertionData;
}
- public ActivityInsertionCosts calculate(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) {
- return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
- }
}
diff --git a/jsprit-core/src/main/java/jsprit/core/problem/constraint/AdditionalTransportationCosts.java b/jsprit-core/src/main/java/jsprit/core/problem/constraint/AdditionalTransportationCosts.java
new file mode 100644
index 00000000..f2a4451a
--- /dev/null
+++ b/jsprit-core/src/main/java/jsprit/core/problem/constraint/AdditionalTransportationCosts.java
@@ -0,0 +1,70 @@
+package jsprit.core.problem.constraint;
+
+import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
+import jsprit.core.problem.misc.JobInsertionContext;
+import jsprit.core.problem.solution.route.activity.End;
+import jsprit.core.problem.solution.route.activity.TourActivity;
+import jsprit.core.util.CalculationUtils;
+
+/**
+ * Calculates additional transportation costs induced by inserting newAct.
+ *
+ * @author schroeder
+ *
+ */
+public class AdditionalTransportationCosts implements SoftActivityConstraint{
+
+ private VehicleRoutingTransportCosts routingCosts;
+
+ /**
+ * Constructs the calculator that calculates additional transportation costs induced by inserting new activity.
+ *
+ *
It is calculated at local level, i.e. the additional costs of inserting act_new between act_i and act_j is c(act_i,act_new,newVehicle)+c(act_new,act_j,newVehicle)-c(act_i,act_j,oldVehicle)
+ *
If newVehicle.isReturnToDepot == false then the additional costs of inserting act_new between act_i and end is c(act_i,act_new) [since act_new is then the new end-of-route]
+ *
+ * @param routingCosts
+ */
+ public AdditionalTransportationCosts(VehicleRoutingTransportCosts routingCosts) {
+ super();
+ this.routingCosts = routingCosts;
+ }
+
+ /**
+ * Returns additional transportation costs induced by inserting newAct.
+ *
+ *
It is calculated at local level, i.e. the additional costs of inserting act_new between act_i and act_j is c(act_i,act_new,newVehicle)+c(act_new,act_j,newVehicle)-c(act_i,act_j,oldVehicle)
+ *
If newVehicle.isReturnToDepot == false then the additional costs of inserting act_new between act_i and end is c(act_i,act_new) [since act_new is then the new end-of-route]
+ */
+ @Override
+ public double getCosts(JobInsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double depTimeAtPrevAct) {
+ double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
+ double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
+
+ double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
+ double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct);
+
+ //open routes
+ if(nextAct instanceof End){
+ if(!iFacts.getNewVehicle().isReturnToDepot()){
+ return tp_costs_prevAct_newAct;
+ }
+ }
+
+ double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
+ double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct;
+
+ double oldCosts;
+ if(iFacts.getRoute().isEmpty()){
+ double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
+ oldCosts = tp_costs_prevAct_nextAct;
+ }
+ else{
+ double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
+ oldCosts = tp_costs_prevAct_nextAct;
+ }
+
+ double additionalCosts = totalCosts - oldCosts;
+ return additionalCosts;
+ }
+
+}
diff --git a/jsprit-core/src/main/java/jsprit/core/problem/constraint/ConstraintManager.java b/jsprit-core/src/main/java/jsprit/core/problem/constraint/ConstraintManager.java
index 6c2dc332..fd6545c4 100644
--- a/jsprit-core/src/main/java/jsprit/core/problem/constraint/ConstraintManager.java
+++ b/jsprit-core/src/main/java/jsprit/core/problem/constraint/ConstraintManager.java
@@ -14,7 +14,7 @@ import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import org.apache.log4j.Logger;
@SuppressWarnings("deprecation")
-public class ConstraintManager implements HardActivityStateLevelConstraint, HardRouteStateLevelConstraint{
+public class ConstraintManager implements HardActivityStateLevelConstraint, HardRouteStateLevelConstraint, SoftActivityConstraint, SoftRouteConstraint{
public static enum Priority {
CRITICAL, HIGH, LOW
@@ -26,6 +26,10 @@ public class ConstraintManager implements HardActivityStateLevelConstraint, Hard
private HardRouteLevelConstraintManager routeLevelConstraintManager = new HardRouteLevelConstraintManager();
+ private SoftActivityConstraintManager softActivityConstraintManager = new SoftActivityConstraintManager();
+
+ private SoftRouteConstraintManager softRouteConstraintManager = new SoftRouteConstraintManager();
+
private VehicleRoutingProblem vrp;
private RouteAndActivityStateGetter stateManager;
@@ -56,6 +60,14 @@ public class ConstraintManager implements HardActivityStateLevelConstraint, Hard
routeLevelConstraintManager.addConstraint((HardRouteStateLevelConstraint) c);
constraintTypeKnown = true;
}
+ if(c instanceof SoftRouteConstraint){
+ softRouteConstraintManager.addConstraint((SoftRouteConstraint)c);
+ constraintTypeKnown = true;
+ }
+ if(c instanceof SoftActivityConstraint){
+ softActivityConstraintManager.addConstraint((SoftActivityConstraint)c);
+ constraintTypeKnown = true;
+ }
if(!constraintTypeKnown){
log.warn("constraint " + c + " unknown thus ignores the constraint. currently, a constraint must implement either HardActivityStateLevelConstraint or HardRouteStateLevelConstraint");
}
@@ -82,6 +94,8 @@ public class ConstraintManager implements HardActivityStateLevelConstraint, Hard
}
}
+// public void add
+
public void addConstraint(HardActivityStateLevelConstraint actLevelConstraint, Priority priority){
actLevelConstraintManager.addConstraint(actLevelConstraint,priority);
}
@@ -90,6 +104,14 @@ public class ConstraintManager implements HardActivityStateLevelConstraint, Hard
routeLevelConstraintManager.addConstraint(routeLevelConstraint);
}
+ public void addConstraint(SoftActivityConstraint softActivityConstraint){
+ softActivityConstraintManager.addConstraint(softActivityConstraint);
+ }
+
+ public void addConstraint(SoftRouteConstraint softRouteConstraint){
+ softRouteConstraintManager.addConstraint(softRouteConstraint);
+ }
+
@Override
public boolean fulfilled(JobInsertionContext insertionContext) {
return routeLevelConstraintManager.fulfilled(insertionContext);
@@ -104,7 +126,19 @@ public class ConstraintManager implements HardActivityStateLevelConstraint, Hard
List constraints = new ArrayList();
constraints.addAll(actLevelConstraintManager.getAllConstraints());
constraints.addAll(routeLevelConstraintManager.getConstraints());
+ constraints.addAll(softActivityConstraintManager.getConstraints());
+ constraints.addAll(softRouteConstraintManager.getConstraints());
return Collections.unmodifiableCollection(constraints);
}
+
+ @Override
+ public double getCosts(JobInsertionContext insertionContext) {
+ return softRouteConstraintManager.getCosts(insertionContext);
+ }
+
+ @Override
+ public double getCosts(JobInsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
+ return softActivityConstraintManager.getCosts(iFacts, prevAct, newAct, nextAct, prevActDepTime);
+ }
}
\ No newline at end of file
diff --git a/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftActivityConstraint.java b/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftActivityConstraint.java
new file mode 100644
index 00000000..8817b2ad
--- /dev/null
+++ b/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftActivityConstraint.java
@@ -0,0 +1,10 @@
+package jsprit.core.problem.constraint;
+
+import jsprit.core.problem.misc.JobInsertionContext;
+import jsprit.core.problem.solution.route.activity.TourActivity;
+
+public interface SoftActivityConstraint extends SoftConstraint{
+
+ public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime);
+
+}
diff --git a/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftActivityConstraintManager.java b/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftActivityConstraintManager.java
new file mode 100644
index 00000000..bb8a1106
--- /dev/null
+++ b/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftActivityConstraintManager.java
@@ -0,0 +1,29 @@
+package jsprit.core.problem.constraint;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import jsprit.core.problem.misc.JobInsertionContext;
+import jsprit.core.problem.solution.route.activity.TourActivity;
+
+class SoftActivityConstraintManager implements SoftActivityConstraint{
+
+ private Collection softConstraints = new ArrayList();
+
+ public void addConstraint(SoftActivityConstraint constraint){
+ softConstraints.add(constraint);
+ }
+
+ Collection getConstraints(){ return Collections.unmodifiableCollection(softConstraints); }
+
+ @Override
+ public double getCosts(JobInsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
+ double sumCosts = 0.0;
+ for(SoftActivityConstraint c : softConstraints){
+ sumCosts += c.getCosts(iFacts, prevAct, newAct, nextAct, prevActDepTime);
+ }
+ return sumCosts;
+ }
+
+}
diff --git a/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftRouteConstraint.java b/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftRouteConstraint.java
new file mode 100644
index 00000000..1cc1d6e5
--- /dev/null
+++ b/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftRouteConstraint.java
@@ -0,0 +1,9 @@
+package jsprit.core.problem.constraint;
+
+import jsprit.core.problem.misc.JobInsertionContext;
+
+public interface SoftRouteConstraint extends SoftConstraint{
+
+ public double getCosts(JobInsertionContext insertionContext);
+
+}
diff --git a/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftRouteConstraintManager.java b/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftRouteConstraintManager.java
new file mode 100644
index 00000000..311ac857
--- /dev/null
+++ b/jsprit-core/src/main/java/jsprit/core/problem/constraint/SoftRouteConstraintManager.java
@@ -0,0 +1,28 @@
+package jsprit.core.problem.constraint;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import jsprit.core.problem.misc.JobInsertionContext;
+
+class SoftRouteConstraintManager implements SoftRouteConstraint{
+
+ private Collection softConstraints = new ArrayList();
+
+ public void addConstraint(SoftRouteConstraint constraint){
+ softConstraints.add(constraint);
+ }
+
+ Collection getConstraints(){ return Collections.unmodifiableCollection(softConstraints); }
+
+ @Override
+ public double getCosts(JobInsertionContext insertionContext) {
+ double sumCosts = 0.0;
+ for(SoftRouteConstraint c : softConstraints){
+ sumCosts += c.getCosts(insertionContext);
+ }
+ return sumCosts;
+ }
+
+}
diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/BuildCVRPAlgoFromScratch_IT.java b/jsprit-core/src/test/java/jsprit/core/algorithm/BuildCVRPAlgoFromScratch_IT.java
index 9c3a63da..944999c0 100644
--- a/jsprit-core/src/test/java/jsprit/core/algorithm/BuildCVRPAlgoFromScratch_IT.java
+++ b/jsprit-core/src/test/java/jsprit/core/algorithm/BuildCVRPAlgoFromScratch_IT.java
@@ -32,6 +32,7 @@ import jsprit.core.algorithm.selector.SelectBest;
import jsprit.core.algorithm.state.StateManager;
import jsprit.core.algorithm.state.UpdateVariableCosts;
import jsprit.core.problem.VehicleRoutingProblem;
+import jsprit.core.problem.constraint.AdditionalTransportationCosts;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.io.VrpXMLReader;
import jsprit.core.problem.solution.SolutionCostCalculator;
@@ -67,6 +68,7 @@ public class BuildCVRPAlgoFromScratch_IT {
ConstraintManager cManager = new ConstraintManager(vrp, stateManager);
cManager.addLoadConstraint();
cManager.addTimeWindowConstraint();
+ cManager.addConstraint(new AdditionalTransportationCosts(vrp.getTransportCosts()));
VehicleFleetManager fleetManager = new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
@@ -102,11 +104,7 @@ public class BuildCVRPAlgoFromScratch_IT {
vra = new VehicleRoutingAlgorithm(vrp, strategyManager);
vra.addListener(stateManager);
vra.addListener(new RemoveEmptyVehicles(fleetManager));
-
-// vra.getAlgorithmListeners().addListener(stateManager);
-// vra.getSearchStrategyManager().addSearchStrategyModuleListener(stateManager);
-// vra.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(fleetManager));
-
+
VehicleRoutingProblemSolution iniSolution = new InsertionInitialSolutionFactory(bestInsertion, solutionCostCalculator).createSolution(vrp);
vra.addInitialSolution(iniSolution);
diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/ServiceInsertionAndLoadConstraintsTest.java b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/ServiceInsertionAndLoadConstraintsTest.java
index 20093453..ce3dae97 100644
--- a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/ServiceInsertionAndLoadConstraintsTest.java
+++ b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/ServiceInsertionAndLoadConstraintsTest.java
@@ -136,7 +136,7 @@ public class ServiceInsertionAndLoadConstraintsTest {
stateManager.informInsertionStarts(Arrays.asList(route), null);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
- ServiceInsertionCalculator serviceInsertionCalc = new ServiceInsertionCalculator(routingCosts, activityInsertionCostsCalculator, hardRouteLevelConstraint, constraintManager);
+ ServiceInsertionCalculator serviceInsertionCalc = new ServiceInsertionCalculator(routingCosts, constraintManager);
ShipmentInsertionCalculator insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityInsertionCostsCalculator, hardRouteLevelConstraint, constraintManager);
switcher.put(Pickup.class, serviceInsertionCalc);
switcher.put(Delivery.class, serviceInsertionCalc);
diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/ShipmentInsertionCalculatorTest.java b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/ShipmentInsertionCalculatorTest.java
index 0937f9ee..0401f981 100644
--- a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/ShipmentInsertionCalculatorTest.java
+++ b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/ShipmentInsertionCalculatorTest.java
@@ -240,7 +240,7 @@ public class ShipmentInsertionCalculatorTest {
stateManager.informInsertionStarts(Arrays.asList(route), null);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
- ServiceInsertionCalculator serviceInsertionCalc = new ServiceInsertionCalculator(routingCosts, activityInsertionCostsCalculator, hardRouteLevelConstraint, constraintManager);
+ ServiceInsertionCalculator serviceInsertionCalc = new ServiceInsertionCalculator(routingCosts, constraintManager);
ShipmentInsertionCalculator insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityInsertionCostsCalculator, hardRouteLevelConstraint, constraintManager);
switcher.put(Pickup.class, serviceInsertionCalc);
switcher.put(Shipment.class, insertionCalculator);
diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestCalculatesServiceInsertion.java b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestCalculatesServiceInsertion.java
index 675bcb98..82bd6c2c 100644
--- a/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestCalculatesServiceInsertion.java
+++ b/jsprit-core/src/test/java/jsprit/core/algorithm/recreate/TestCalculatesServiceInsertion.java
@@ -27,6 +27,7 @@ import java.util.Collection;
import jsprit.core.algorithm.ExampleActivityCostFunction;
import jsprit.core.algorithm.state.StateManager;
import jsprit.core.problem.VehicleRoutingProblem;
+import jsprit.core.problem.constraint.AdditionalTransportationCosts;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.DriverImpl;
@@ -165,11 +166,9 @@ public class TestCalculatesServiceInsertion {
ConstraintManager cManager = new ConstraintManager(vrp,states);
cManager.addLoadConstraint();
cManager.addTimeWindowConstraint();
+ cManager.addConstraint(new AdditionalTransportationCosts(costs));
- ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
-
-
- serviceInsertion = new ServiceInsertionCalculator(costs, new LocalActivityInsertionCostsCalculator(costs, activityCosts), cManager, cManager);
+ serviceInsertion = new ServiceInsertionCalculator(costs, cManager);
// stateUpdater = new UpdateStates(states, costs, activityCosts);
diff --git a/jsprit-examples/src/main/java/jsprit/examples/BuildAlgorithmFromScratchWithHardAndSoftConstraints.java b/jsprit-examples/src/main/java/jsprit/examples/BuildAlgorithmFromScratchWithHardAndSoftConstraints.java
new file mode 100644
index 00000000..64f5aa9d
--- /dev/null
+++ b/jsprit-examples/src/main/java/jsprit/examples/BuildAlgorithmFromScratchWithHardAndSoftConstraints.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Stefan Schroeder.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3.0 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see .
+ *
+ * Contributors:
+ * Stefan Schroeder - initial API and implementation
+ ******************************************************************************/
+package jsprit.examples;
+
+import java.util.Collection;
+
+import jsprit.analysis.toolbox.SolutionPrinter;
+import jsprit.core.algorithm.InsertionInitialSolutionFactory;
+import jsprit.core.algorithm.RemoveEmptyVehicles;
+import jsprit.core.algorithm.SearchStrategy;
+import jsprit.core.algorithm.SearchStrategyManager;
+import jsprit.core.algorithm.VariablePlusFixedSolutionCostCalculatorFactory;
+import jsprit.core.algorithm.VehicleRoutingAlgorithm;
+import jsprit.core.algorithm.acceptor.GreedyAcceptance;
+import jsprit.core.algorithm.module.RuinAndRecreateModule;
+import jsprit.core.algorithm.recreate.BestInsertionBuilder;
+import jsprit.core.algorithm.recreate.InsertionStrategy;
+import jsprit.core.algorithm.ruin.RadialRuinStrategyFactory;
+import jsprit.core.algorithm.ruin.RandomRuinStrategyFactory;
+import jsprit.core.algorithm.ruin.RuinStrategy;
+import jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance;
+import jsprit.core.algorithm.selector.SelectBest;
+import jsprit.core.algorithm.state.StateManager;
+import jsprit.core.algorithm.state.UpdateVariableCosts;
+import jsprit.core.algorithm.termination.IterationWithoutImprovementTermination;
+import jsprit.core.problem.VehicleRoutingProblem;
+import jsprit.core.problem.constraint.AdditionalTransportationCosts;
+import jsprit.core.problem.constraint.ConstraintManager;
+import jsprit.core.problem.solution.SolutionCostCalculator;
+import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
+import jsprit.core.problem.vehicle.InfiniteFleetManagerFactory;
+import jsprit.core.problem.vehicle.VehicleFleetManager;
+import jsprit.core.util.Solutions;
+import jsprit.instance.reader.SolomonReader;
+import jsprit.util.Examples;
+
+public class BuildAlgorithmFromScratchWithHardAndSoftConstraints {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ /*
+ * some preparation - create output folder
+ */
+ Examples.createOutputFolder();
+
+ /*
+ * Build the problem.
+ *
+ * But define a problem-builder first.
+ */
+ VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
+
+ /*
+ * A solomonReader reads solomon-instance files, and stores the required information in the builder.
+ */
+ new SolomonReader(vrpBuilder).read("input/C101_solomon.txt");
+
+ /*
+ * Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances).
+ */
+ VehicleRoutingProblem vrp = vrpBuilder.build();
+
+ /*
+ * Build algorithm
+ */
+ VehicleRoutingAlgorithm vra = buildAlgorithmFromScratch(vrp);
+
+ /*
+ * search solution
+ */
+ Collection solutions = vra.searchSolutions();
+
+ /*
+ * print result
+ */
+ SolutionPrinter.print(Solutions.bestOf(solutions));
+
+ }
+
+ private static VehicleRoutingAlgorithm buildAlgorithmFromScratch(VehicleRoutingProblem vrp) {
+
+ /*
+ * manages route and activity states.
+ */
+ StateManager stateManager = new StateManager(vrp);
+ /*
+ * tells stateManager to update load states
+ */
+ stateManager.updateLoadStates();
+ /*
+ * tells stateManager to update time-window states
+ */
+ stateManager.updateTimeWindowStates();
+ /*
+ * stateManager.addStateUpdater(updater);
+ * lets you register your own stateUpdater
+ */
+
+ /*
+ * updates variable costs once a vehicleRoute has changed (by removing or adding a customer)
+ */
+ stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
+
+ /*
+ * constructs a constraintManager that manages the various hardConstraints (and soon also softConstraints)
+ */
+ ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
+ /*
+ * tells constraintManager to add timeWindowConstraints
+ */
+ constraintManager.addTimeWindowConstraint();
+ /*
+ * tells constraintManager to add loadConstraints
+ */
+ constraintManager.addLoadConstraint();
+ /*
+ * add an arbitrary number of hardConstraints by
+ * constraintManager.addConstraint(...)
+ */
+ constraintManager.addConstraint(new AdditionalTransportationCosts(vrp.getTransportCosts()));
+
+ /*
+ * define a fleetManager, here infinite vehicles can be used
+ */
+ VehicleFleetManager fleetManager = new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
+
+ /*
+ * define ruin-and-recreate strategies
+ *
+ */
+ /*
+ * first, define an insertion-strategy, i.e. bestInsertion
+ */
+ BestInsertionBuilder iBuilder = new BestInsertionBuilder(vrp, fleetManager, stateManager, constraintManager);
+ /*
+ * no need to set further options
+ */
+ InsertionStrategy iStrategy = iBuilder.build();
+
+ /*
+ * second, define random-ruin that ruins 50-percent of the selected solution
+ */
+ RuinStrategy randomRuin = new RandomRuinStrategyFactory(0.5).createStrategy(vrp);
+
+ /*
+ * third, define radial-ruin that ruins 30-percent of the selected solution
+ * the second para defines the distance between two jobs.
+ */
+ RuinStrategy radialRuin = new RadialRuinStrategyFactory(0.3, new AvgServiceAndShipmentDistance(vrp.getTransportCosts())).createStrategy(vrp);
+
+ /*
+ * now define a strategy
+ */
+ /*
+ * but before define how a generated solution is evaluated
+ * here: the VariablePlusFixed.... comes out of the box and it does what its name suggests
+ */
+ SolutionCostCalculator solutionCostCalculator = new VariablePlusFixedSolutionCostCalculatorFactory(stateManager).createCalculator();
+
+ SearchStrategy firstStrategy = new SearchStrategy(new SelectBest(), new GreedyAcceptance(1), solutionCostCalculator);
+ firstStrategy.addModule(new RuinAndRecreateModule("randomRuinAndBestInsertion", iStrategy, randomRuin));
+
+ SearchStrategy secondStrategy = new SearchStrategy(new SelectBest(), new GreedyAcceptance(1), solutionCostCalculator);
+ secondStrategy.addModule(new RuinAndRecreateModule("radialRuinAndBestInsertion", iStrategy, radialRuin));
+
+ /*
+ * put both strategies together, each with the prob of 0.5 to be selected
+ */
+ SearchStrategyManager searchStrategyManager = new SearchStrategyManager();
+ searchStrategyManager.addStrategy(firstStrategy, 0.5);
+ searchStrategyManager.addStrategy(secondStrategy, 0.5);
+
+ /*
+ * construct the algorithm
+ */
+ VehicleRoutingAlgorithm vra = new VehicleRoutingAlgorithm(vrp, searchStrategyManager);
+ //do not forgett to add the stateManager listening to the algorithm-stages
+ vra.addListener(stateManager);
+ //remove empty vehicles after insertion has finished
+ vra.addListener(new RemoveEmptyVehicles(fleetManager));
+
+ /*
+ * Do not forget to add an initial solution by vra.addInitialSolution(solution);
+ * or
+ */
+ vra.addInitialSolution(new InsertionInitialSolutionFactory(iStrategy, solutionCostCalculator).createSolution(vrp));
+
+ /*
+ * define the nIterations (by default nIteration=100)
+ */
+ vra.setNuOfIterations(1000);
+
+ /*
+ * optionally define a premature termination criterion (by default: not criterion is set)
+ */
+ vra.setPrematureAlgorithmTermination(new IterationWithoutImprovementTermination(100));
+
+ return vra;
+ }
+
+}