Skip to content

Commit

Permalink
Added: TimeWindows is now an extension point, notably allowing TimeWi…
Browse files Browse the repository at this point in the history
…ndow exclusions (#1)
  • Loading branch information
croooo authored and marcanpilami committed Sep 21, 2023
1 parent b2b34a2 commit 76f43ea
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import com.graphhopper.jsprit.core.problem.constraint.HardConstraint;
import com.graphhopper.jsprit.core.problem.constraint.HardRouteConstraint;
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;

import java.util.ArrayList;
Expand All @@ -35,8 +34,6 @@
* Created by schroeder on 06/02/17.
*/
abstract class AbstractInsertionCalculator implements JobInsertionCostsCalculator {
protected TimeWindow defaultTimeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);

InsertionData checkRouteConstraints(JobInsertionContext insertionContext, ConstraintManager constraintManager) {
for (HardRouteConstraint hardRouteConstraint : constraintManager.getHardRouteConstraints()) {
if (!hardRouteConstraint.fulfilled(insertionContext)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,12 @@ public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job
nextAct = end;
tourEnd = true;
}

ActivityContext activityContext = new ActivityContext();
activityContext.setInsertionIndex(actIndex);
insertionContext.setActivityContext(activityContext);
boolean not_fulfilled_break = true;
for(TimeWindow timeWindow : service.getTimeWindows()) {
ActivityContext activityContext = new ActivityContext();
activityContext.setInsertionIndex(actIndex);
insertionContext.setActivityContext(activityContext);
if (!timeWindow.isApplicable(insertionContext)) {
timeWindow = defaultTimeWindow;
}
for(TimeWindow timeWindow : service.getTimeWindows(insertionContext)) {
deliveryAct2Insert.setTheoreticalEarliestOperationStartTime(timeWindow.getStart());
deliveryAct2Insert.setTheoreticalLatestOperationStartTime(timeWindow.getEnd());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,10 @@ public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job
}

boolean pickupInsertionNotFulfilledBreak = true;
for(TimeWindow pickupTimeWindow : shipment.getPickupTimeWindows()) {
ActivityContext activityContext = new ActivityContext();
activityContext.setInsertionIndex(i);
insertionContext.setActivityContext(activityContext);
if (!pickupTimeWindow.isApplicable(insertionContext)) {
pickupTimeWindow = defaultTimeWindow;
}
ActivityContext activityContext = new ActivityContext();
activityContext.setInsertionIndex(i);
insertionContext.setActivityContext(activityContext);
for(TimeWindow pickupTimeWindow : shipment.getPickupTimeWindows(insertionContext)) {
pickupShipment.setTheoreticalLatestOperationStartTime(pickupTimeWindow.getEnd());
pickupShipment.setTheoreticalEarliestOperationStartTime(pickupTimeWindow.getStart());

Expand Down Expand Up @@ -194,13 +191,10 @@ else if (pickupShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)) {
}

boolean deliveryInsertionNotFulfilledBreak = true;
for (TimeWindow deliveryTimeWindow : shipment.getDeliveryTimeWindows()) {
ActivityContext activityContext_ = new ActivityContext();
activityContext_.setInsertionIndex(j);
insertionContext.setActivityContext(activityContext_);
if (!deliveryTimeWindow.isApplicable(insertionContext)) {
deliveryTimeWindow = defaultTimeWindow;
}
ActivityContext activityContext_ = new ActivityContext();
activityContext_.setInsertionIndex(j);
insertionContext.setActivityContext(activityContext_);
for (TimeWindow deliveryTimeWindow : shipment.getDeliveryTimeWindows(insertionContext)) {
deliverShipment.setTheoreticalEarliestOperationStartTime(deliveryTimeWindow.getStart());
deliverShipment.setTheoreticalLatestOperationStartTime(deliveryTimeWindow.getEnd());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
import com.graphhopper.jsprit.core.problem.Capacity;
import com.graphhopper.jsprit.core.problem.Location;
import com.graphhopper.jsprit.core.problem.Skills;
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindows;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindowsImpl;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindowsOverlapImpl;
import com.graphhopper.jsprit.core.util.Coordinate;

import java.util.ArrayList;
Expand Down Expand Up @@ -87,7 +89,7 @@ public static Builder newInstance(String id) {

protected Location location;

protected TimeWindowsImpl timeWindows;
protected TimeWindows timeWindows;

private boolean twAdded = false;

Expand Down Expand Up @@ -184,6 +186,20 @@ public Builder<T> setTimeWindow(TimeWindow tw){
return this;
}

public Builder<T> setTimeWindows(TimeWindows timeWindows){
if (timeWindows == null) throw new IllegalArgumentException("The time windows must not be null.");
if (twAdded) {
// Report already added TW for ascending compatibility and API clarity
// (otherwise previous calls to addTimeWindow would be silently ignored)
for (TimeWindow tw : this.timeWindows.getTimeWindows()) {
timeWindows.add(tw);
}
}
this.timeWindows = timeWindows;
twAdded = true;
return this;
}

public Builder<T> addTimeWindow(TimeWindow timeWindow) {
if (timeWindow == null) throw new IllegalArgumentException("The time window must not be null.");
if(!twAdded){
Expand Down Expand Up @@ -310,6 +326,10 @@ public Collection<TimeWindow> getTimeWindows(){
return timeWindows.getTimeWindows();
}

public Collection<TimeWindow> getTimeWindows(JobInsertionContext insertionContext){
return timeWindows.getTimeWindows(insertionContext);
}

@Override
public String getId() {
return id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
import com.graphhopper.jsprit.core.problem.Capacity;
import com.graphhopper.jsprit.core.problem.Location;
import com.graphhopper.jsprit.core.problem.Skills;
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindows;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindowsImpl;

import java.util.ArrayList;
Expand Down Expand Up @@ -76,13 +78,13 @@ public static class Builder {

private Location deliveryLocation_;

protected TimeWindowsImpl deliveryTimeWindows;
protected TimeWindows deliveryTimeWindows;

private boolean deliveryTimeWindowAdded = false;

private boolean pickupTimeWindowAdded = false;

private TimeWindowsImpl pickupTimeWindows;
private TimeWindows pickupTimeWindows;

private int priority = 2;

Expand Down Expand Up @@ -176,7 +178,18 @@ public Builder setPickupTimeWindow(TimeWindow timeWindow) {
return this;
}


public Builder setPickupTimeWindows(TimeWindows timeWindows){
if (timeWindows == null) throw new IllegalArgumentException("The time windows must not be null.");
if (pickupTimeWindows != null) {
// Report already added TW for ascending compatibility and API clarity
// (otherwise previous calls to addXXXTimeWindow would be silently ignored)
for (TimeWindow tw : this.pickupTimeWindows.getTimeWindows()) {
timeWindows.add(tw);
}
}
this.pickupTimeWindows = timeWindows;
return this;
}

/**
* Sets delivery location.
Expand Down Expand Up @@ -222,6 +235,19 @@ public Builder setDeliveryTimeWindow(TimeWindow timeWindow) {
return this;
}

public Builder setDeliveryTimeWindows(TimeWindows timeWindows){
if (timeWindows == null) throw new IllegalArgumentException("The time windows must not be null.");
if (deliveryTimeWindows != null) {
// Report already added TW for ascending compatibility and API clarity
// (otherwise previous calls to addXXXTimeWindow would be silently ignored)
for (TimeWindow tw : this.deliveryTimeWindows.getTimeWindows()) {
timeWindows.add(tw);
}
}
this.deliveryTimeWindows = timeWindows;
return this;
}

/**
* Adds capacity dimension.
*
Expand Down Expand Up @@ -367,9 +393,9 @@ public Builder setMaxTimeInVehicle(double maxTimeInVehicle){

private final Location deliveryLocation_;

private final TimeWindowsImpl deliveryTimeWindows;
private final TimeWindows deliveryTimeWindows;

private final TimeWindowsImpl pickupTimeWindows;
private final TimeWindows pickupTimeWindows;

private final int priority;

Expand Down Expand Up @@ -442,6 +468,10 @@ public Collection<TimeWindow> getDeliveryTimeWindows() {
return deliveryTimeWindows.getTimeWindows();
}

public Collection<TimeWindow> getDeliveryTimeWindows(JobInsertionContext insertionContext) {
return deliveryTimeWindows.getTimeWindows(insertionContext);
}

/**
* Returns the time-window of pickup.
*
Expand All @@ -455,6 +485,10 @@ public Collection<TimeWindow> getPickupTimeWindows() {
return pickupTimeWindows.getTimeWindows();
}

public Collection<TimeWindow> getPickupTimeWindows(JobInsertionContext insertionContext) {
return pickupTimeWindows.getTimeWindows(insertionContext);
}


/**
* Returns a string with the shipment's attributes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,18 @@

import java.util.Collection;

import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;

/**
* Created by schroeder on 20/05/15.
*/
public interface TimeWindows {
static TimeWindow defaultTimeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);

public void add(TimeWindow timeWindow);

public Collection<TimeWindow> getTimeWindows();

public Collection<TimeWindow> getTimeWindows(JobInsertionContext insertionContext);

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;

/**
* Created by schroeder on 26/05/15.
Expand All @@ -29,6 +32,7 @@ public class TimeWindowsImpl implements TimeWindows {

private Collection<TimeWindow> timeWindows = new ArrayList<TimeWindow>();

@Override
public void add(TimeWindow timeWindow){
for(TimeWindow tw : timeWindows){
if(timeWindow.getStart() > tw.getStart() && timeWindow.getStart() < tw.getEnd()){
Expand All @@ -44,10 +48,25 @@ public void add(TimeWindow timeWindow){
timeWindows.add(timeWindow);
}

@Override
public Collection<TimeWindow> getTimeWindows() {
return Collections.unmodifiableCollection(timeWindows);
}

@Override
public Collection<TimeWindow> getTimeWindows(JobInsertionContext insertionContext) {
List<TimeWindow> timeWindows = new ArrayList<TimeWindow>(this.timeWindows.size());
for(TimeWindow tw : this.timeWindows){
if (tw.isApplicable(insertionContext)) {
timeWindows.add(tw);
}
}
if (timeWindows.isEmpty()) {
timeWindows.add(TimeWindows.defaultTimeWindow);
}
return Collections.unmodifiableCollection(timeWindows);
}

@Override
public String toString() {
StringBuffer sb = new StringBuffer(timeWindows.size() * 60);
Expand Down
Loading

0 comments on commit 76f43ea

Please sign in to comment.