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 9b04d438..baced979 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 @@ -27,12 +27,15 @@ import jsprit.core.problem.misc.JobInsertionContext; import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.activity.End; import jsprit.core.problem.solution.route.activity.Start; +import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.problem.solution.route.activity.TourActivity; import jsprit.core.problem.vehicle.Vehicle; import jsprit.core.util.CalculationUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.Collection; + /** * Calculator that calculates the best insertion position for a {@link Service}. * @@ -108,6 +111,7 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{ double bestCost = bestKnownCosts; additionalICostsAtRouteLevel += additionalAccessEgressCalculator.getCosts(insertionContext); + TimeWindow bestTimeWindow = null; /* generate new start and end for new vehicle @@ -121,17 +125,28 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{ int actIndex = 0; boolean loopBroken = false; for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){ - ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime); - if(status.equals(ConstraintsStatus.FULFILLED)){ - //from job2insert induced costs at activity level - double additionalICostsAtActLevel = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime); - double additionalTransportationCosts = additionalTransportCostsCalculator.getCosts(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime); - if(additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts < bestCost){ - bestCost = additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts; - insertionIndex = actIndex; + double actArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocation(),deliveryAct2Insert.getLocation(),prevActStartTime,newDriver,newVehicle); + Collection timeWindows = service.getTimeWindows(actArrTime); + boolean not_fulfilled_break = true; + for(TimeWindow timeWindow : timeWindows) { + deliveryAct2Insert.setTheoreticalEarliestStart(timeWindow.getStart()); + deliveryAct2Insert.setTheoreticalLatestStart(timeWindow.getEnd()); + ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime); + if (status.equals(ConstraintsStatus.FULFILLED)) { + //from job2insert induced costs at activity level + double additionalICostsAtActLevel = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime); + double additionalTransportationCosts = additionalTransportCostsCalculator.getCosts(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime); + if (additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts < bestCost) { + bestCost = additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts; + insertionIndex = actIndex; + bestTimeWindow = timeWindow; + } + not_fulfilled_break = false; + } else if (status.equals(ConstraintsStatus.NOT_FULFILLED)) { + not_fulfilled_break = false; } } - else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){ + if(not_fulfilled_break){ loopBroken = true; break; } @@ -141,6 +156,10 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{ actIndex++; } if(!loopBroken){ + Collection timeWindows = service.getTimeWindows(actArrTime); + for(TimeWindow timeWindow : timeWindows) { + + } ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, end, prevActStartTime); if(status.equals(ConstraintsStatus.FULFILLED)){ double additionalICostsAtActLevel = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, end, prevActStartTime); diff --git a/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java b/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java index 30b1ba7b..723972e3 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java @@ -21,8 +21,11 @@ import jsprit.core.problem.Capacity; import jsprit.core.problem.Location; import jsprit.core.problem.Skills; import jsprit.core.problem.solution.route.activity.TimeWindow; +import jsprit.core.problem.solution.route.activity.TimeWindows; import jsprit.core.util.Coordinate; +import java.util.Collection; + /** * Service implementation of a job. * @@ -83,6 +86,8 @@ public class Service extends AbstractJob { protected Location location; + protected TimeWindows timeWindows; + Builder(String id){ this.id = id; } @@ -111,6 +116,11 @@ public class Service extends AbstractJob { return this; } + public Builder setTimeWindows(TimeWindows timeWindows){ + this.timeWindows = timeWindows; + return this; + } + /** * Sets the serviceTime of this service. * @@ -198,6 +208,8 @@ public class Service extends AbstractJob { private final Location location; + private final TimeWindows timeWindowManager; + Service(Builder builder){ id = builder.id; serviceTime = builder.serviceTime; @@ -207,6 +219,11 @@ public class Service extends AbstractJob { skills = builder.skills; name = builder.name; location = builder.location; + timeWindowManager = builder.timeWindows; + } + + public Collection getTimeWindows(double time){ + return timeWindowManager.getTimeWindows(time); } @Override