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 conditional time windows #555

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
* Created by schroeder on 06/02/17.
*/
abstract class AbstractInsertionCalculator implements JobInsertionCostsCalculator {

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,13 +135,15 @@ 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()) {
for(TimeWindow timeWindow : service.getTimeWindows(insertionContext)) {
deliveryAct2Insert.setTheoreticalEarliestOperationStartTime(timeWindow.getStart());
deliveryAct2Insert.setTheoreticalLatestOperationStartTime(timeWindow.getEnd());
ActivityContext activityContext = new ActivityContext();
activityContext.setInsertionIndex(actIndex);
insertionContext.setActivityContext(activityContext);

ConstraintsStatus status = fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime, failedActivityConstraints, constraintManager);
if (status.equals(ConstraintsStatus.FULFILLED)) {
double additionalICostsAtActLevel = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,13 @@ public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job
}

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

ConstraintsStatus pickupShipmentConstraintStatus = fulfilled(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime, failedActivityConstraints, constraintManager);
if (pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED)) {
pickupInsertionNotFulfilledBreak = false;
Expand Down Expand Up @@ -190,12 +191,13 @@ else if (pickupShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)) {
}

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

ConstraintsStatus deliverShipmentConstraintStatus = fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop, failedActivityConstraints, constraintManager);
if (deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)) {
double additionalDeliveryICosts = softActivityConstraint.getCosts(insertionContext, prevAct_deliveryLoop, deliverShipment, nextAct_deliveryLoop, prevActEndTime_deliveryLoop);
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 All @@ -101,7 +103,7 @@ public static Builder newInstance(String id) {
Builder(String id){
this.id = id;
timeWindows = new TimeWindowsImpl();
timeWindows.add(TimeWindow.newInstance(0.0, Double.MAX_VALUE));
timeWindows.add(TimeWindowsImpl.defaultTimeWindow);
}

/**
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 All @@ -108,9 +110,9 @@ public static Builder newInstance(String id) {
if (id == null) throw new IllegalArgumentException("id must not be null");
this.id = id;
pickupTimeWindows = new TimeWindowsImpl();
pickupTimeWindows.add(TimeWindow.newInstance(0.0, Double.MAX_VALUE));
pickupTimeWindows.add(TimeWindowsImpl.defaultTimeWindow);
deliveryTimeWindows = new TimeWindowsImpl();
deliveryTimeWindows.add(TimeWindow.newInstance(0.0, Double.MAX_VALUE));
deliveryTimeWindows.add(TimeWindowsImpl.defaultTimeWindow);
}

/**
Expand Down Expand Up @@ -176,7 +178,19 @@ 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 (pickupTimeWindowAdded) {
// 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;
pickupTimeWindowAdded = true;
return this;
}

/**
* Sets delivery location.
Expand Down Expand Up @@ -222,6 +236,20 @@ 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 (deliveryTimeWindowAdded) {
// 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;
deliveryTimeWindowAdded = true;
return this;
}

/**
* Adds capacity dimension.
*
Expand Down Expand Up @@ -367,9 +395,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 +470,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 +487,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 @@ -17,6 +17,8 @@
*/
package com.graphhopper.jsprit.core.problem.solution.route.activity;

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

/**
* TimeWindow consists of a startTime and endTime.
*
Expand Down Expand Up @@ -116,5 +118,12 @@ public boolean equals(Object obj) {
return true;
}


/**
* Returns true if this time window is applicable in the current context. By default always true, only sub classes of TimeWindow may return false.
* @param time
* @return
*/
public boolean isApplicable(JobInsertionContext insertionContext) {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.graphhopper.jsprit.core.problem.solution.route.activity;

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

/**
* A time window that is only applicable for a specific type of vehicle.
* When using this, beware of vehicle switching.
*/
public class TimeWindowConditionalOnVehicleType extends TimeWindow {
private final String vehicleTypeId;

/**
* Returns new instance of TimeWindowConditionalOnVehicleType.
*
* @param start
* @param end
* @param vehicleTypeId
* @return TimeWindow
* @throw IllegalArgumentException either if start or end < 0.0 or end < start
*/
public static TimeWindow newInstance(double start, double end, String vehicleTypeId) {
return new TimeWindowConditionalOnVehicleType(start, end, vehicleTypeId);
}

public TimeWindowConditionalOnVehicleType(double start, double end, String vehicleTypeId) {
super(start, end);
this.vehicleTypeId = vehicleTypeId;
}

@Override
public boolean isApplicable(JobInsertionContext insertionContext) {
return insertionContext.getNewVehicle().getType().getTypeId().equals(vehicleTypeId);
}
}
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