Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added: TimeWindows is now an extension point, notably allowing TimeWindow exclusions #1

Merged
merged 10 commits into from
Sep 21, 2023
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