1
0
Fork 0
mirror of https://github.com/graphhopper/jsprit.git synced 2020-01-24 07:45:05 +01:00

Merge branch 'multiple-capacities'

This commit is contained in:
Stefan Schroeder 2014-03-06 19:55:43 +01:00
commit 56067dc590
135 changed files with 5020 additions and 1095 deletions

View file

@ -22,7 +22,7 @@ public class VariablePlusFixedSolutionCostCalculatorFactory {
public double getCosts(VehicleRoutingProblemSolution solution) {
double c = 0.0;
for(VehicleRoute r : solution.getRoutes()){
c += stateManager.getRouteState(r, StateFactory.COSTS).toDouble();
c += stateManager.getRouteState(r, StateFactory.COSTS,Double.class);
c += r.getVehicle().getType().getVehicleCostParams().fix;
}
return c;

View file

@ -537,7 +537,7 @@ public class VehicleRoutingAlgorithms {
stateManager = stateMan;
}
else{
stateManager = new StateManager(vrp);
stateManager = new StateManager(vrp.getTransportCosts());
}
stateManager.updateLoadStates();
stateManager.updateTimeWindowStates();
@ -617,7 +617,7 @@ public class VehicleRoutingAlgorithms {
public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.0;
for(VehicleRoute route : solution.getRoutes()){
costs += stateManager.getRouteState(route, StateFactory.COSTS).toDouble() + getFixedCosts(route.getVehicle());
costs += stateManager.getRouteState(route, StateFactory.COSTS, Double.class) + getFixedCosts(route.getVehicle());
}
return costs;
}

View file

@ -17,6 +17,7 @@
package jsprit.core.algorithm.recreate;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
@ -83,37 +84,40 @@ final class JobInsertionConsideringFixCostsCalculator implements JobInsertionCos
}
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
double load = getCurrentMaxLoadInRoute(route) + job.getCapacityDemand();
Capacity load = Capacity.addup(getCurrentMaxLoadInRoute(route), job.getSize());
// double load = getCurrentMaxLoadInRoute(route) + job.getCapacityDemand();
double currentFix = 0.0;
if(route.getVehicle() != null){
if(!(route.getVehicle() instanceof NoVehicle)){
currentFix += route.getVehicle().getType().getVehicleCostParams().fix;
}
}
if(newVehicle.getCapacity() < load){
if(!newVehicle.getType().getCapacityDimensions().isGreaterOrEqual(load)){
return Double.MAX_VALUE;
}
return newVehicle.getType().getVehicleCostParams().fix - currentFix;
}
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
int currentLoad = getCurrentMaxLoadInRoute(route);
double load = currentLoad + job.getCapacityDemand();
Capacity currentLoad = getCurrentMaxLoadInRoute(route);
// int currentLoad = getCurrentMaxLoadInRoute(route);
Capacity load = Capacity.addup(currentLoad, job.getSize());
// double load = currentLoad + job.getCapacityDemand();
double currentRelFix = 0.0;
if(route.getVehicle() != null){
if(!(route.getVehicle() instanceof NoVehicle)){
currentRelFix += route.getVehicle().getType().getVehicleCostParams().fix*currentLoad/route.getVehicle().getCapacity();
currentRelFix += route.getVehicle().getType().getVehicleCostParams().fix * Capacity.divide(currentLoad, route.getVehicle().getType().getCapacityDimensions());
}
}
if(newVehicle.getCapacity() < load){
if(!newVehicle.getType().getCapacityDimensions().isGreaterOrEqual(load)){
return Double.MAX_VALUE;
}
double relativeFixCost = newVehicle.getType().getVehicleCostParams().fix*(load/newVehicle.getCapacity()) - currentRelFix;
double relativeFixCost = newVehicle.getType().getVehicleCostParams().fix* (Capacity.divide(load, newVehicle.getType().getCapacityDimensions())) - currentRelFix;
return relativeFixCost;
}
private int getCurrentMaxLoadInRoute(VehicleRoute route) {
return (int) stateGetter.getRouteState(route, StateFactory.MAXLOAD).toDouble();
private Capacity getCurrentMaxLoadInRoute(VehicleRoute route) {
return stateGetter.getRouteState(route, StateFactory.MAXLOAD, Capacity.class);
}
}

View file

@ -73,9 +73,9 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) {
if(act instanceof End){
return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble();
return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS,Double.class);
}
return stateManager.getActivityState(act,StateFactory.COSTS).toDouble();
return stateManager.getActivityState(act,StateFactory.COSTS,Double.class);
}
private List<TourActivity> getForwardLookingPath(VehicleRoute route, int actIndex) {

View file

@ -291,7 +291,7 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
/**
* compute cost-diff of tour with and without new activity --> insertion_costs
*/
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateFactory.COSTS).toDouble();
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateFactory.COSTS,Double.class);
/**
* if better than best known, make it the best known
@ -336,9 +336,9 @@ final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsC
private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) {
if(act instanceof End){
return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble();
return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS,Double.class);
}
return stateManager.getActivityState(act,StateFactory.COSTS).toDouble();
return stateManager.getActivityState(act,StateFactory.COSTS,Double.class);
}
/**

View file

@ -30,6 +30,7 @@ import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
import jsprit.core.algorithm.recreate.listener.JobInsertedListener;
import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.algorithm.ruin.listener.RuinListeners;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.job.Job;
@ -45,14 +46,39 @@ import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.solution.route.state.StateFactory;
import jsprit.core.problem.solution.route.state.StateFactory.State;
import jsprit.core.problem.solution.route.state.StateFactory.StateId;
import jsprit.core.problem.solution.route.state.StateFactory.States;
/**
* Manages states.
*
* <p>Some condition, rules or constraints are stateful. This StateManager manages these states, i.e. it offers
* methods to add, store and retrieve states based on vehicle-routes and tour-activities.
*
* @author schroeder
*
*/
public class StateManager implements RouteAndActivityStateGetter, IterationStartsListener, RuinListener, InsertionStartsListener, JobInsertedListener, InsertionEndsListener {
private Map<VehicleRoute,States> vehicleRouteStates = new HashMap<VehicleRoute, States>();
static class States_ {
private Map<StateId,Object> states = new HashMap<StateId,Object>();
public <T> void putState(StateId id, Class<T> type, T state){
states.put(id, type.cast(state));
}
public <T> T getState(StateId id, Class<T> type){
if(states.containsKey(id)){
T s = type.cast(states.get(id));
return s;
}
return null;
}
}
private Map<VehicleRoute,States_> vehicleRouteStates_ = new HashMap<VehicleRoute, States_>();
private Map<TourActivity,States> activityStates = new HashMap<TourActivity, States>();
private Map<TourActivity,States_> activityStates_ = new HashMap<TourActivity, States_>();
private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor();
@ -66,9 +92,9 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart
private Collection<StateUpdater> updaters = new ArrayList<StateUpdater>();
private Map<StateId,State> defaultRouteStates = new HashMap<StateId, State>();
private Map<StateId,Object> defaultRouteStates_ = new HashMap<StateId,Object>();
private Map<StateId,State> defaultActivityStates = new HashMap<StateId, State>();
private Map<StateId,Object> defaultActivityStates_ = new HashMap<StateId,Object>();
private VehicleRoutingTransportCosts routingCosts;
@ -76,79 +102,269 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart
private boolean updateTWs = false;
/**
* @deprecated use <code>StateManager(VehicleRoutingTransportCosts tpcosts)</code> instead.
* @param vrp
*/
@Deprecated
public StateManager(VehicleRoutingProblem vrp) {
super();
this.routingCosts = vrp.getTransportCosts();
addDefaultStates();
}
private void addDefaultStates() {
defaultActivityStates_.put(StateFactory.LOAD, Capacity.Builder.newInstance().build());
defaultActivityStates_.put(StateFactory.COSTS, 0.);
defaultActivityStates_.put(StateFactory.DURATION, 0.);
defaultActivityStates_.put(StateFactory.FUTURE_MAXLOAD, Capacity.Builder.newInstance().build());
defaultActivityStates_.put(StateFactory.PAST_MAXLOAD, Capacity.Builder.newInstance().build());
defaultRouteStates_.put(StateFactory.LOAD, Capacity.Builder.newInstance().build());
defaultRouteStates_.put(StateFactory.COSTS, 0.);
defaultRouteStates_.put(StateFactory.DURATION, 0.);
defaultRouteStates_.put(StateFactory.FUTURE_MAXLOAD, Capacity.Builder.newInstance().build());
defaultRouteStates_.put(StateFactory.PAST_MAXLOAD, Capacity.Builder.newInstance().build());
defaultRouteStates_.put(StateFactory.MAXLOAD, Capacity.Builder.newInstance().build());
defaultRouteStates_.put(StateFactory.LOAD_AT_END, Capacity.Builder.newInstance().build());
defaultRouteStates_.put(StateFactory.LOAD_AT_BEGINNING, Capacity.Builder.newInstance().build());
}
public StateManager(VehicleRoutingTransportCosts routingCosts){
this.routingCosts = routingCosts;
addDefaultStates();
}
/**
* @deprecated use the generic methode <code>addDefaultRouteState(StateId stateId, Class<T> type, T defaultState)</code> instead.
* @param stateId
* @param defaultState
*/
@Deprecated
public void addDefaultRouteState(StateId stateId, State defaultState){
if(StateFactory.isReservedId(stateId)) StateFactory.throwReservedIdException(stateId.toString());
defaultRouteStates.put(stateId, defaultState);
addDefaultRouteState(stateId, State.class, defaultState);
}
/**
* Generic method to add a default route state.
*
* <p>for example if you want to store 'maximum weight' at route-level, the default might be zero and you
* can add the default simply by coding <br>
* <code>addDefaultRouteState(StateFactory.createStateId("max_weight"), Integer.class, 0)</code>
*
* @param stateId
* @param type
* @param defaultState
*/
public <T> void addDefaultRouteState(StateId stateId, Class<T> type, T defaultState){
if(StateFactory.isReservedId(stateId)) StateFactory.throwReservedIdException(stateId.toString());
defaultRouteStates_.put(stateId, type.cast(defaultState));
}
/**
* @deprecated use generic method <code>addDefaultActivityState(StateId stateId, Class<T> type, T defaultState)</code>
* @param stateId
* @param defaultState
*/
@Deprecated
public void addDefaultActivityState(StateId stateId, State defaultState){
if(StateFactory.isReservedId(stateId)) StateFactory.throwReservedIdException(stateId.toString());
defaultActivityStates.put(stateId, defaultState);
addDefaultActivityState(stateId, State.class, defaultState);
}
/**
* Generic method to add default activity state.
*
* @param stateId
* @param type
* @param defaultState
*/
public <T> void addDefaultActivityState(StateId stateId, Class<T> type, T defaultState){
if(StateFactory.isReservedId(stateId)) StateFactory.throwReservedIdException(stateId.toString());
defaultActivityStates_.put(stateId, type.cast(defaultState));
}
/**
* Clears all states.
*
*/
public void clear(){
vehicleRouteStates.clear();
activityStates.clear();
vehicleRouteStates_.clear();
activityStates_.clear();
}
/**
* @Deprecated use generic method instead <code>getActivityState(TourActivity act, StateId stateId, Class<T> type)</code>
*/
@Deprecated
@Override
public State getActivityState(TourActivity act, StateId stateId) {
if(!activityStates.containsKey(act)){
return getDefaultActState(stateId,act);
if(!activityStates_.containsKey(act)){
return getDefaultTypedActivityState(act,stateId,State.class);
}
States actStates = activityStates.get(act);
State state = actStates.getState(stateId);
States_ actStates = activityStates_.get(act);
State state = actStates.getState(stateId, State.class);
if(state == null){
return getDefaultActState(stateId,act);
return getDefaultTypedActivityState(act,stateId,State.class);
}
return state;
}
void putInternalActivityState(TourActivity act, StateId stateId, State state){
if(!activityStates.containsKey(act)){
activityStates.put(act, StateFactory.createStates());
/**
* Returns activity state of type 'type'.
*
*/
@Override
public <T> T getActivityState(TourActivity act, StateId stateId, Class<T> type) {
if(!activityStates_.containsKey(act)){
return getDefaultTypedActivityState(act, stateId, type);
}
States actStates = activityStates.get(act);
actStates.putState(stateId, state);
States_ states = activityStates_.get(act);
T state = states.getState(stateId, type);
if(state == null) return getDefaultTypedActivityState(act, stateId, type);
return state;
}
/**
*
* @param act
* @param stateId
* @param type
* @return
*/
private <T> T getDefaultTypedActivityState(TourActivity act, StateId stateId,Class<T> type) {
if(defaultActivityStates_.containsKey(stateId)){
return type.cast(defaultActivityStates_.get(stateId));
}
if(stateId.equals(StateFactory.EARLIEST_OPERATION_START_TIME)){
return type.cast(act.getTheoreticalEarliestOperationStartTime());
}
if(stateId.equals(StateFactory.LATEST_OPERATION_START_TIME)){
return type.cast(act.getTheoreticalLatestOperationStartTime());
}
return null;
}
/**
* Return route state of type 'type'.
*
* @return route-state
* @throws ClassCastException if state of route and stateId is of another type
*/
@Override
public <T> T getRouteState(VehicleRoute route, StateId stateId, Class<T> type) {
if(!vehicleRouteStates_.containsKey(route)){
return getDefaultTypedRouteState(stateId, type);
}
States_ states = vehicleRouteStates_.get(route);
T state = states.getState(stateId, type);
if(state == null) return getDefaultTypedRouteState(stateId, type);
return state;
}
private <T> T getDefaultTypedRouteState(StateId stateId, Class<T> type) {
if(defaultRouteStates_.containsKey(stateId)){
return type.cast(defaultRouteStates_.get(stateId));
}
return null;
}
/**
*
* @param act
* @param stateId
* @param state
* @deprecated use generic method <code>putTypedActivityState(TourActivity act, StateId stateId, Class<T> type, T state)</code> instead
*/
@Deprecated
public void putActivityState(TourActivity act, StateId stateId, State state){
putTypedActivityState(act, stateId, State.class, state);
}
/**
* Generic method to memorize state 'state' of type 'type' of act and stateId.
*
* <p><b>For example: </b><br>
* <code>Capacity loadAtMyActivity = Capacity.Builder.newInstance().addCapacityDimension(0,10).build();<br>
* stateManager.putTypedActivityState(myActivity, StateFactory.createStateId("act-load"), Capacity.class, loadAtMyActivity);</code>
* <p>you can retrieve the load at myActivity by <br>
* <code>Capacity load = stateManager.getActivityState(myActivity, StateFactory.createStateId("act-load"), Capacity.class);</code>
*
* @param act
* @param stateId
* @param type
* @param state
*/
public <T> void putTypedActivityState(TourActivity act, StateId stateId, Class<T> type, T state){
if(StateFactory.isReservedId(stateId)) StateFactory.throwReservedIdException(stateId.toString());
putInternalActivityState(act, stateId, state);
putInternalTypedActivityState(act, stateId, type, state);
}
void putInternalRouteState(VehicleRoute route, StateId stateId, State state){
if(!vehicleRouteStates.containsKey(route)){
vehicleRouteStates.put(route, StateFactory.createStates());
@Deprecated
void putInternalActivityState(TourActivity act, StateId stateId, State state){
putInternalTypedActivityState(act, stateId, State.class, state);
}
<T> void putInternalTypedActivityState(TourActivity act, StateId stateId, Class<T> type, T state){
if(!activityStates_.containsKey(act)){
activityStates_.put(act, new States_());
}
States routeStates = (States) vehicleRouteStates.get(route);
routeStates.putState(stateId, state);
States_ actStates = activityStates_.get(act);
actStates.putState(stateId, type, state);
}
@Deprecated
void putInternalRouteState(VehicleRoute route, StateId stateId, State state){
putTypedInternalRouteState(route, stateId, State.class, state);
}
<T> void putTypedInternalRouteState(VehicleRoute route, StateId stateId, Class<T> type, T state){
if(!vehicleRouteStates_.containsKey(route)){
vehicleRouteStates_.put(route, new States_());
}
States_ routeStates = vehicleRouteStates_.get(route);
routeStates.putState(stateId, type, state);
}
@Deprecated
public void putRouteState(VehicleRoute route, StateId stateId, State state){
if(StateFactory.isReservedId(stateId)) StateFactory.throwReservedIdException(stateId.toString());
putInternalRouteState(route, stateId, state);
putTypedRouteState(route, stateId, State.class, state);
}
/**
* Generic method to memorize state 'state' of type 'type' of route and stateId.
*
* <p><b>For example:</b> <br>
* <code>double totalRouteDuration = 100.0;<br>
* stateManager.putTypedActivityState(myRoute, StateFactory.createStateId("route-duration"), Double.class, totalRouteDuration);</code>
* <p>you can retrieve the duration of myRoute then by <br>
* <code>double totalRouteDuration = stateManager.getRouteState(myRoute, StateFactory.createStateId("route-duration"), Double.class);</code>
*
* @param act
* @param stateId
* @param type
* @param state
*/
public <T> void putTypedRouteState(VehicleRoute route, StateId stateId, Class<T> type, T state){
if(StateFactory.isReservedId(stateId)) StateFactory.throwReservedIdException(stateId.toString());
putTypedInternalRouteState(route, stateId, type, state);
}
@Deprecated
@Override
public State getRouteState(VehicleRoute route, StateId stateId) {
if(!vehicleRouteStates.containsKey(route)){
return getDefaultRouteState(stateId,route);
if(!vehicleRouteStates_.containsKey(route)){
return getDefaultTypedRouteState(stateId,State.class);
}
States routeStates = vehicleRouteStates.get(route);
State state = routeStates.getState(stateId);
States_ routeStates = vehicleRouteStates_.get(route);
State state = routeStates.getState(stateId,State.class);
if(state == null){
return getDefaultRouteState(stateId, route);
return getDefaultTypedRouteState(stateId, State.class);
}
return state;
}
@ -220,29 +436,7 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart
insertionListeners.removeListener(insertionListener);
}
private State getDefaultActState(StateId stateId, TourActivity act){
if(stateId.equals(StateFactory.LOAD)) return StateFactory.createState(0);
if(stateId.equals(StateFactory.COSTS)) return StateFactory.createState(0);
if(stateId.equals(StateFactory.DURATION)) return StateFactory.createState(0);
if(stateId.equals(StateFactory.EARLIEST_OPERATION_START_TIME)) return StateFactory.createState(act.getTheoreticalEarliestOperationStartTime());
if(stateId.equals(StateFactory.LATEST_OPERATION_START_TIME)) return StateFactory.createState(act.getTheoreticalLatestOperationStartTime());
if(stateId.equals(StateFactory.FUTURE_MAXLOAD)) return StateFactory.createState(0);
if(stateId.equals(StateFactory.PAST_MAXLOAD)) return StateFactory.createState(0);
if(defaultActivityStates.containsKey(stateId)) return defaultActivityStates.get(stateId);
return null;
}
private State getDefaultRouteState(StateId stateId, VehicleRoute route){
if(stateId.equals(StateFactory.MAXLOAD)) return StateFactory.createState(0);
if(stateId.equals(StateFactory.LOAD)) return StateFactory.createState(0);
if(stateId.equals(StateFactory.LOAD_AT_END)) return StateFactory.createState(0);
if(stateId.equals(StateFactory.LOAD_AT_BEGINNING)) return StateFactory.createState(0);
if(stateId.equals(StateFactory.COSTS)) return StateFactory.createState(0);
if(stateId.equals(StateFactory.DURATION)) return StateFactory.createState(0);
if(defaultRouteStates.containsKey(stateId)) return defaultRouteStates.get(stateId);
return null;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
// log.debug("insert " + job2insert + " in " + inRoute);
@ -294,16 +488,18 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart
UpdateLoads updateLoads = new UpdateLoads(this);
addActivityVisitor(updateLoads);
addListener(updateLoads);
addActivityVisitor(new UpdatePrevMaxLoad(this));
addActivityVisitor(new UpdateMaxLoad(this));
addActivityVisitor(new UpdateMaxLoad_(this));
addActivityVisitor(new UpdateMaxCapacityUtilisationAtActivitiesByLookingBackwardInRoute(this));
addActivityVisitor(new UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute(this));
addActivityVisitor(new UpdateMaxCapacityUtilisationAtRoute(this));
}
}
public void updateTimeWindowStates() {
if(!updateTWs){
updateTWs=true;
addActivityVisitor(new UpdateTimeWindow(this, routingCosts));
addActivityVisitor(new UpdatePracticalTimeWindows(this, routingCosts));
}
}
}

View file

@ -1,37 +0,0 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.StateFactory;
import jsprit.core.util.ActivityTimeTracker;
class UpdateEarliestStartTime implements ActivityVisitor,StateUpdater{
private StateManager states;
private ActivityTimeTracker timeTracker;
public UpdateEarliestStartTime(StateManager states, VehicleRoutingTransportCosts transportCosts) {
super();
this.states = states;
timeTracker = new ActivityTimeTracker(transportCosts);
}
@Override
public void begin(VehicleRoute route) {
timeTracker.begin(route);
}
@Override
public void visit(TourActivity activity) {
timeTracker.visit(activity);
states.putInternalActivityState(activity, StateFactory.EARLIEST_OPERATION_START_TIME, StateFactory.createState(Math.max(timeTracker.getActArrTime(), activity.getTheoreticalEarliestOperationStartTime())));
}
@Override
public void finish() {}
}

View file

@ -4,6 +4,7 @@ import java.util.Collection;
import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
import jsprit.core.algorithm.recreate.listener.JobInsertedListener;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.job.Delivery;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Pickup;
@ -15,34 +16,27 @@ import jsprit.core.problem.solution.route.state.StateFactory;
/**
* Updates load at activity level.
* Updates load at start and end of route as well as at each activity. And update is triggered when either
* activityVisitor has been started, the insertion process has been started or a job has been inserted.
*
* <p>Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT.
* If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot.
*
* <p>Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT
* <p>Note that this only works properly if you register this class as ActivityVisitor AND InsertionStartsListener AND JobInsertedListener.
* The reason behind is that activity states are dependent on route-level states and vice versa. If this is properly registered,
* this dependency is solved automatically.
*
* @author stefan
*
*/
class UpdateLoads implements ActivityVisitor, StateUpdater, InsertionStartsListener, JobInsertedListener {
private StateManager stateManager;
private int currentLoad = 0;
private VehicleRoute route;
/**
* Updates load at activity level.
*
* <p>Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT.
* If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot.
*
* <p>Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT
*
* <p>The loads can be retrieved by <br>
* <code>stateManager.getActivityState(activity,StateTypes.LOAD);</code>
*
* @author stefan
*
/*
* default has one dimension with a value of zero
*/
private Capacity currentLoad = Capacity.Builder.newInstance().build();
private VehicleRoute route;
public UpdateLoads(StateManager stateManager) {
super();
this.stateManager = stateManager;
@ -50,37 +44,36 @@ class UpdateLoads implements ActivityVisitor, StateUpdater, InsertionStartsListe
@Override
public void begin(VehicleRoute route) {
currentLoad = (int) stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble();
currentLoad = stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class);
this.route = route;
}
@Override
public void visit(TourActivity act) {
currentLoad += act.getCapacityDemand();
stateManager.putInternalActivityState(act, StateFactory.LOAD, StateFactory.createState(currentLoad));
assert currentLoad <= route.getVehicle().getCapacity() : "currentLoad at activity must not be > vehicleCapacity";
assert currentLoad >= 0 : "currentLoad at act must not be < 0";
currentLoad = Capacity.addup(currentLoad, act.getSize());
stateManager.putInternalTypedActivityState(act, StateFactory.LOAD, Capacity.class, currentLoad);
assert currentLoad.isLessOrEqual(route.getVehicle().getType().getCapacityDimensions()) : "currentLoad at activity must not be > vehicleCapacity";
assert currentLoad.isGreaterOrEqual(Capacity.Builder.newInstance().build()) : "currentLoad at act must not be < 0 in one of the applied dimensions";
}
@Override
public void finish() {
// stateManager.putRouteState(route, StateFactory., state)
currentLoad = 0;
currentLoad = Capacity.Builder.newInstance().build();
}
void insertionStarts(VehicleRoute route) {
int loadAtDepot = 0;
int loadAtEnd = 0;
Capacity loadAtDepot = Capacity.Builder.newInstance().build();
Capacity loadAtEnd = Capacity.Builder.newInstance().build();
for(Job j : route.getTourActivities().getJobs()){
if(j instanceof Delivery){
loadAtDepot += j.getCapacityDemand();
loadAtDepot = Capacity.addup(loadAtDepot, j.getSize());
}
else if(j instanceof Pickup || j instanceof Service){
loadAtEnd += j.getCapacityDemand();
loadAtEnd = Capacity.addup(loadAtEnd, j.getSize());
}
}
stateManager.putInternalRouteState(route, StateFactory.LOAD_AT_BEGINNING, StateFactory.createState(loadAtDepot));
stateManager.putInternalRouteState(route, StateFactory.LOAD_AT_END, StateFactory.createState(loadAtEnd));
stateManager.putTypedInternalRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class, loadAtDepot);
stateManager.putTypedInternalRouteState(route, StateFactory.LOAD_AT_END, Capacity.class, loadAtEnd);
}
@Override
@ -90,17 +83,13 @@ class UpdateLoads implements ActivityVisitor, StateUpdater, InsertionStartsListe
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
// log.debug("insert("+job2insert+").into("+inRoute+")");
// log(inRoute);
if(job2insert instanceof Delivery){
int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING).toDouble();
// log.info("loadAtDepot="+loadAtDepot);
stateManager.putInternalRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING, StateFactory.createState(loadAtDepot + job2insert.getCapacityDemand()));
Capacity loadAtDepot = stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING, Capacity.class);
stateManager.putTypedInternalRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING, Capacity.class, Capacity.addup(loadAtDepot, job2insert.getSize()));
}
else if(job2insert instanceof Pickup || job2insert instanceof Service){
int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_END).toDouble();
// log.info("loadAtEnd="+loadAtEnd);
stateManager.putInternalRouteState(inRoute, StateFactory.LOAD_AT_END, StateFactory.createState(loadAtEnd + job2insert.getCapacityDemand()));
Capacity loadAtEnd = stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_END, Capacity.class);
stateManager.putTypedInternalRouteState(inRoute, StateFactory.LOAD_AT_END, Capacity.class, Capacity.addup(loadAtEnd, job2insert.getSize()));
}
}

View file

@ -0,0 +1,44 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.StateFactory;
/**
* Determines and memorizes the maximum capacity utilization at each activity by looking backward in route,
* i.e. the maximum capacity utilization at previous activities.
*
* @author schroeder
*
*/
class UpdateMaxCapacityUtilisationAtActivitiesByLookingBackwardInRoute implements ActivityVisitor, StateUpdater {
private StateManager stateManager;
private VehicleRoute route;
private Capacity maxLoad;
public UpdateMaxCapacityUtilisationAtActivitiesByLookingBackwardInRoute(StateManager stateManager) {
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
maxLoad = stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class);
}
@Override
public void visit(TourActivity act) {
maxLoad = Capacity.max(maxLoad, stateManager.getActivityState(act, StateFactory.LOAD, Capacity.class));
stateManager.putInternalTypedActivityState(act, StateFactory.PAST_MAXLOAD, Capacity.class, maxLoad);
assert maxLoad.isGreaterOrEqual(Capacity.Builder.newInstance().build()) : "maxLoad can never be smaller than 0";
assert maxLoad.isLessOrEqual(route.getVehicle().getType().getCapacityDimensions()) : "maxLoad can never be bigger than vehicleCap";
}
@Override
public void finish() {}
}

View file

@ -0,0 +1,63 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ReverseActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.StateFactory;
/**
* A {@link ReverseActivityVisitor} that looks forward in the vehicle route and determines
* the maximum capacity utilization (in terms of loads) at subsequent activities.
*
* <p>Assume a vehicle route with the following activity sequence {start,pickup(1,4),delivery(2,3),pickup(3,2),end} where
* pickup(1,2) = pickup(id,cap-demand).<br>
* Future maxLoad for each activity are calculated as follows:<br>
* loadAt(end)=6 (since two pickups need to be delivered to depot)<br>
* pickup(3)=max(loadAt(pickup(3)), futureMaxLoad(end))=max(6,6)=6
* delivery(2)=max(loadAt(delivery(2),futureMaxLoad(pickup(3))=max(4,6)=6
* pickup(1)=max(7,6)=7
* start=max(7,7)=7
* activity (apart from start and end), the maximum capacity is determined when forward looking into the route.
* That is at each activity we know how much capacity is available whithout breaking future capacity constraints.
*
*
* @author schroeder
*
*/
class UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute implements ReverseActivityVisitor, StateUpdater {
private StateManager stateManager;
private VehicleRoute route;
private Capacity maxLoad = Capacity.Builder.newInstance().build();
// private double maxLoad;
public UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
maxLoad = stateManager.getRouteState(route, StateFactory.LOAD_AT_END, Capacity.class);
// maxLoad = stateManager.getRouteState(route, StateFactory.LOAD_AT_END).toDouble();
}
@Override
public void visit(TourActivity act) {
maxLoad = Capacity.max(maxLoad, stateManager.getActivityState(act, StateFactory.LOAD, Capacity.class));
// maxLoad = Math.max(maxLoad, stateManager.getActivityState(act, StateFactory.LOAD).toDouble());
stateManager.putInternalTypedActivityState(act, StateFactory.FUTURE_MAXLOAD, Capacity.class, maxLoad);
// stateManager.putInternalActivityState(act, StateFactory.FUTURE_MAXLOAD, StateFactory.createState(maxLoad));
assert maxLoad.isLessOrEqual(route.getVehicle().getType().getCapacityDimensions()) : "maxLoad can in every capacity dimension never be bigger than vehicleCap";
// assert maxLoad <= route.getVehicle().getCapacity() : "maxLoad can never be bigger than vehicleCap";
assert maxLoad.isGreaterOrEqual(Capacity.Builder.newInstance().build()) : "maxLoad can never be smaller than 0";
// assert maxLoad >= 0 : "maxLoad can never be smaller than 0";
}
@Override
public void finish() {}
}

View file

@ -0,0 +1,52 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.StateFactory;
/**
* Updates load at activity level.
*
* <p>Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT.
* If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot.
*
* <p>Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT
*
* @author stefan
*
*/
class UpdateMaxCapacityUtilisationAtRoute implements ActivityVisitor, StateUpdater {
private StateManager stateManager;
private Capacity currentLoad = Capacity.Builder.newInstance().build();
private VehicleRoute route;
private Capacity maxLoad = Capacity.Builder.newInstance().build();
public UpdateMaxCapacityUtilisationAtRoute(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
currentLoad = stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING, Capacity.class);
maxLoad = currentLoad;
this.route = route;
}
@Override
public void visit(TourActivity act) {
currentLoad = Capacity.addup(currentLoad, act.getSize());
maxLoad = Capacity.max(maxLoad, currentLoad);
}
@Override
public void finish() {
stateManager.putTypedInternalRouteState(route, StateFactory.MAXLOAD, Capacity.class, maxLoad);
}
}

View file

@ -1,34 +0,0 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ReverseActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.StateFactory;
class UpdateMaxLoad implements ReverseActivityVisitor, StateUpdater {
private StateManager stateManager;
private VehicleRoute route;
private double maxLoad;
public UpdateMaxLoad(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
maxLoad = stateManager.getRouteState(route, StateFactory.LOAD_AT_END).toDouble();
}
@Override
public void visit(TourActivity act) {
maxLoad = Math.max(maxLoad, stateManager.getActivityState(act, StateFactory.LOAD).toDouble());
stateManager.putInternalActivityState(act, StateFactory.FUTURE_MAXLOAD, StateFactory.createState(maxLoad));
assert maxLoad <= route.getVehicle().getCapacity() : "maxLoad can never be bigger than vehicleCap";
assert maxLoad >= 0 : "maxLoad can never be smaller than 0";
}
@Override
public void finish() {}
}

View file

@ -1,68 +0,0 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.StateFactory;
/**
* Updates load at activity level.
*
* <p>Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT.
* If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot.
*
* <p>Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT
*
* @author stefan
*
*/
class UpdateMaxLoad_ implements ActivityVisitor, StateUpdater {
private StateManager stateManager;
private int currentLoad = 0;
private VehicleRoute route;
private int maxLoad = 0;
/**
* Updates load at activity level.
*
* <p>Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT.
* If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot.
*
* <p>Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT
*
*
*
* <p>The loads can be retrieved by <br>
* <code>stateManager.getActivityState(activity,StateTypes.LOAD);</code>
*
*
* @author stefan
*
*/
public UpdateMaxLoad_(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
currentLoad = (int) stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble();
maxLoad = currentLoad;
this.route = route;
}
@Override
public void visit(TourActivity act) {
currentLoad += act.getCapacityDemand();
maxLoad = Math.max(maxLoad, currentLoad);
assert currentLoad <= route.getVehicle().getCapacity() : "currentLoad at activity must not be > vehicleCapacity";
assert currentLoad >= 0 : "currentLoad at act must not be < 0";
}
@Override
public void finish() {
stateManager.putInternalRouteState(route, StateFactory.MAXLOAD, StateFactory.createState(maxLoad));
currentLoad = 0;
maxLoad = 0;
}
}

View file

@ -6,8 +6,13 @@ import jsprit.core.problem.solution.route.activity.ReverseActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.StateFactory;
class UpdateTimeWindow implements ReverseActivityVisitor, StateUpdater{
/**
* Updates and memorizes latest operation start times at activities.
*
* @author schroeder
*
*/
class UpdatePracticalTimeWindows implements ReverseActivityVisitor, StateUpdater{
private StateManager states;
@ -19,7 +24,7 @@ class UpdateTimeWindow implements ReverseActivityVisitor, StateUpdater{
private TourActivity prevAct;
public UpdateTimeWindow(StateManager states, VehicleRoutingTransportCosts tpCosts) {
public UpdatePracticalTimeWindows(StateManager states, VehicleRoutingTransportCosts tpCosts) {
super();
this.states = states;
this.transportCosts = tpCosts;
@ -37,7 +42,7 @@ class UpdateTimeWindow implements ReverseActivityVisitor, StateUpdater{
double potentialLatestArrivalTimeAtCurrAct = latestArrTimeAtPrevAct - transportCosts.getBackwardTransportTime(activity.getLocationId(), prevAct.getLocationId(), latestArrTimeAtPrevAct, route.getDriver(),route.getVehicle()) - activity.getOperationTime();
double latestArrivalTime = Math.min(activity.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct);
states.putInternalActivityState(activity, StateFactory.LATEST_OPERATION_START_TIME, StateFactory.createState(latestArrivalTime));
states.putInternalTypedActivityState(activity, StateFactory.LATEST_OPERATION_START_TIME, Double.class, latestArrivalTime);
latestArrTimeAtPrevAct = latestArrivalTime;
prevAct = activity;

View file

@ -1,37 +0,0 @@
package jsprit.core.algorithm.state;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.StateFactory;
class UpdatePrevMaxLoad implements ActivityVisitor, StateUpdater {
private StateManager stateManager;
private VehicleRoute route;
private double currLoad;
private double prevMaxLoad;
public UpdatePrevMaxLoad(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
currLoad = stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble();
prevMaxLoad = currLoad;
}
@Override
public void visit(TourActivity act) {
prevMaxLoad = Math.max(prevMaxLoad, stateManager.getActivityState(act, StateFactory.LOAD).toDouble());
stateManager.putInternalActivityState(act, StateFactory.PAST_MAXLOAD, StateFactory.createState(prevMaxLoad));
assert prevMaxLoad >= 0 : "maxLoad can never be smaller than 0";
assert prevMaxLoad <= route.getVehicle().getCapacity() : "maxLoad can never be bigger than vehicleCap";
}
@Override
public void finish() {}
}

View file

@ -61,7 +61,6 @@ public class UpdateVariableCosts implements ActivityVisitor,StateUpdater{
@Override
public void begin(VehicleRoute route) {
vehicleRoute = route;
// vehicleRoute.getVehicleRouteCostCalculator().reset();
timeTracker.begin(route);
prevAct = route.getStart();
startTimeAtPrevAct = timeTracker.getActEndTime();
@ -74,13 +73,10 @@ public class UpdateVariableCosts implements ActivityVisitor,StateUpdater{
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(act, timeTracker.getActArrTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle());
// vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
// vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
//
totalOperationCost += transportCost;
totalOperationCost += actCost;
states.putInternalActivityState(act, StateFactory.COSTS, StateFactory.createState(totalOperationCost));
states.putInternalTypedActivityState(act, StateFactory.COSTS, Double.class, totalOperationCost);
prevAct = act;
startTimeAtPrevAct = timeTracker.getActEndTime();
@ -91,20 +87,11 @@ public class UpdateVariableCosts implements ActivityVisitor,StateUpdater{
timeTracker.finish();
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), vehicleRoute.getEnd().getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(vehicleRoute.getEnd(), timeTracker.getActEndTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle());
// vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
// vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
//
totalOperationCost += transportCost;
totalOperationCost += actCost;
// totalOperationCost += getFixCosts(vehicleRoute.getVehicle());
states.putInternalRouteState(vehicleRoute, StateFactory.COSTS, StateFactory.createState(totalOperationCost));
// //this is rather strange and likely to change
// vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
// vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
// vehicleRoute.getVehicleRouteCostCalculator().finish();
states.putTypedInternalRouteState(vehicleRoute, StateFactory.COSTS, Double.class, totalOperationCost);
startTimeAtPrevAct = 0.0;
prevAct = null;

View file

@ -0,0 +1,276 @@
package jsprit.core.problem;
/**
* Capacity with an arbitrary number of capacity-dimension.
*
* <p>Note that this assumes the the values of each capacity dimension can be added up and subtracted
*
* @author schroeder
*
*/
public class Capacity {
/**
* Adds up two capacities, i.e. sums up each and every capacity dimension, and returns the resulting Capacity.
*
* <p>Note that this assumes that capacity dimension can be added up.
*
* @param cap1
* @param cap2
* @return new capacity
* @throws NullPointerException if one of the args is null
*/
public static Capacity addup(Capacity cap1, Capacity cap2){
if(cap1==null || cap2==null) throw new NullPointerException("arguments must not be null");
Capacity.Builder capacityBuilder= Capacity.Builder.newInstance();
for(int i=0;i<Math.max(cap1.getNuOfDimensions(),cap2.getNuOfDimensions());i++){
capacityBuilder.addDimension(i, cap1.get(i)+cap2.get(i));
}
return capacityBuilder.build();
}
/**
* Subtracts cap2substract from cap and returns the resulting Capacity.
*
* @param cap
* @param cap2substract
* @return new capacity
* @throws NullPointerException if one of the args is null
* @throws IllegalStateException if number of capacityDimensions of cap1 and cap2 are different (i.e. <code>cap1.getNuOfDimension() != cap2.getNuOfDimension()</code>).
*
*/
public static Capacity subtract(Capacity cap, Capacity cap2substract){
if(cap==null || cap2substract==null) throw new NullPointerException("arguments must not be null");
Capacity.Builder capacityBuilder= Capacity.Builder.newInstance();
for(int i=0;i<Math.max(cap.getNuOfDimensions(),cap2substract.getNuOfDimensions());i++){
int dimValue = cap.get(i)-cap2substract.get(i);
capacityBuilder.addDimension(i, dimValue);
}
return capacityBuilder.build();
}
/**
* Returns the inverted capacity, i.e. it multiplies all capacity dimensions with -1.
*
* @param cap
* @return inverted capacity
* @throws NullPointerException if one of the args is null
*/
public static Capacity invert(Capacity cap2invert){
if(cap2invert==null) throw new NullPointerException("arguments must not be null");
Capacity.Builder capacityBuilder= Capacity.Builder.newInstance();
for(int i=0;i<cap2invert.getNuOfDimensions();i++){
int dimValue = cap2invert.get(i)*-1;
capacityBuilder.addDimension(i, dimValue);
}
return capacityBuilder.build();
}
/**
* Divides every dimension of numerator capacity by the corresponding dimension of denominator capacity,
* , and averages each quotient.
*
* <p>If both nominator.get(i) and denominator.get(i) equal to 0, dimension i is ignored.
* <p>If both capacities are have only dimensions with dimensionVal=0, it returns 0.0
* @param numerator
* @param denominator
* @return
* @throws IllegalStateException if numerator.get(i) != 0 and denominator.get(i) == 0
*/
public static double divide(Capacity numerator, Capacity denominator){
int nuOfDimensions = 0;
double sumQuotients = 0.0;
for(int index=0;index<Math.max(numerator.getNuOfDimensions(), denominator.getNuOfDimensions());index++){
if(numerator.get(index) != 0 && denominator.get(index) == 0){
throw new IllegalStateException("numerator > 0 and denominator = 0. cannot divide by 0");
}
else if(numerator.get(index) == 0 && denominator.get(index) == 0){
continue;
}
else{
nuOfDimensions++;
sumQuotients += (double)numerator.get(index)/(double)denominator.get(index);
}
}
if(nuOfDimensions > 0) return sumQuotients/(double)nuOfDimensions;
return 0.0;
}
/**
* Makes a deep copy of Capacity.
*
* @param capacity
* @return
*/
public static Capacity copyOf(Capacity capacity){
if(capacity == null) return null;
return new Capacity(capacity);
}
/**
* Builder that builds Capacity
*
* @author schroeder
*
*/
public static class Builder {
/**
* default is 1 dimension with size of zero
*/
private int[] dimensions = new int[1];
/**
* Returns a new instance of Capacity with one dimension and a value/size of 0
*
* @return this builder
*/
public static Builder newInstance(){
return new Builder();
}
Builder(){}
/**
* add capacity dimension
*
* <p>Note that it automatically resizes dimensions according to index, i.e. if index=7 there are 8 dimensions.
* New dimensions then are initialized with 0
*
* @param index
* @param dimValue
* @return
*/
public Builder addDimension(int index, int dimValue){
if(index < dimensions.length){
dimensions[index] = dimValue;
}
else{
int requiredSize = index + 1;
int[] newDimensions = new int[requiredSize];
copy(dimensions,newDimensions);
newDimensions[index]=dimValue;
this.dimensions=newDimensions;
}
return this;
}
private void copy(int[] from, int[] to) {
for(int i=0;i<dimensions.length;i++){
to[i]=from[i];
}
}
/**
* Builds an immutable Capacity and returns it.
*
* @return Capacity
*/
public Capacity build() {
return new Capacity(this);
}
}
private int[] dimensions;
/**
* copy constructor
*
* @param capacity
*/
Capacity(Capacity capacity){
this.dimensions = new int[capacity.getNuOfDimensions()];
for(int i=0;i<capacity.getNuOfDimensions();i++){
this.dimensions[i]=capacity.get(i);
}
}
Capacity(Builder builder) {
dimensions = builder.dimensions;
}
/**
* Returns the number of specified capacity dimensions.
*
* @return
*/
public int getNuOfDimensions(){
return dimensions.length;
}
/**
* Returns value of capacity-dimension with specified index.
*
* <p>If capacity dimension does not exist, it returns 0 (rather than IndexOutOfBoundsException).
*
* @param index
* @return
*/
public int get(int index){
if(index<dimensions.length) return dimensions[index];
return 0;
}
/**
* Returns true if this capacity is less or equal than the capacity toCompare, i.e. if none of the capacity dimensions > than the corresponding dimension in toCompare.
*
* @param toCompare
* @return
* @throws NullPointerException if one of the args is null
*/
public boolean isLessOrEqual(Capacity toCompare){
if(toCompare == null) throw new NullPointerException();
for(int i=0;i<this.getNuOfDimensions();i++){
if(this.get(i) > toCompare.get(i)) return false;
}
return true;
}
/**
* Returns true if this capacity is greater or equal than the capacity toCompare
*
* @param toCompare
* @return
* @throws NullPointerException if one of the args is null
*/
public boolean isGreaterOrEqual(Capacity toCompare) {
if(toCompare == null) throw new NullPointerException();
for(int i=0;i<Math.max(this.getNuOfDimensions(), toCompare.getNuOfDimensions());i++){
if(this.get(i) < toCompare.get(i)) return false;
}
return true;
}
@Override
public String toString() {
StringBuilder sBuilder = new StringBuilder();
sBuilder.append("[nuOfDimensions="+getNuOfDimensions()+"]");
for(int i=0;i<getNuOfDimensions();i++){
sBuilder.append("[[dimIndex="+i+"][dimValue="+dimensions[i]+"]]");
}
return sBuilder.toString();
}
/**
* Return the maximum, i.e. the maximum of each capacity dimension.
*
* @param cap1
* @param cap2
* @return
*/
public static Capacity max(Capacity cap1, Capacity cap2) {
if(cap1 == null || cap2 == null) throw new IllegalArgumentException("arg must not be null");
Capacity.Builder toReturnBuilder = Capacity.Builder.newInstance();
for(int i=0;i<Math.max(cap1.getNuOfDimensions(), cap2.getNuOfDimensions());i++){
toReturnBuilder.addDimension(i, Math.max(cap1.get(i), cap2.get(i)));
}
return toReturnBuilder.build();
}
}

View file

@ -388,10 +388,11 @@ public class VehicleRoutingProblem {
if(penaltyFixedCosts!=null){
fixed = penaltyFixedCosts;
}
VehicleTypeImpl t = VehicleTypeImpl.Builder.newInstance(v.getType().getTypeId(), v.getCapacity())
VehicleTypeImpl t = VehicleTypeImpl.Builder.newInstance(v.getType().getTypeId())
.setCostPerDistance(penaltyFactor*v.getType().getVehicleCostParams().perDistanceUnit)
.setCostPerTime(penaltyFactor*v.getType().getVehicleCostParams().perTimeUnit)
.setFixedCost(fixed)
.setCapacityDimensions(v.getType().getCapacityDimensions())
.build();
PenaltyVehicleType penType = new PenaltyVehicleType(t,penaltyFactor);
String vehicleId = "penaltyVehicle_" + v.getStartLocationId() + "_" + t.getTypeId();

View file

@ -1,5 +1,6 @@
package jsprit.core.problem.constraint;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.activity.DeliverShipment;
import jsprit.core.problem.solution.route.activity.PickupShipment;
@ -36,27 +37,38 @@ public class PickupAndDeliverShipmentLoadActivityLevelConstraint implements Hard
this.stateManager = stateManager;
}
/**
* Checks whether there is enough capacity to insert newAct between prevAct and nextAct.
*
*/
@Override
public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(!(newAct instanceof PickupShipment) && !(newAct instanceof DeliverShipment)){
return ConstraintsStatus.FULFILLED;
}
int loadAtPrevAct;
Capacity loadAtPrevAct;
// int loadAtPrevAct;
if(prevAct instanceof Start){
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_BEGINNING).toDouble();
loadAtPrevAct = stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_BEGINNING, Capacity.class);
}
else{
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateFactory.LOAD).toDouble();
loadAtPrevAct = stateManager.getActivityState(prevAct, StateFactory.LOAD, Capacity.class);
}
if(newAct instanceof PickupShipment){
if(loadAtPrevAct + newAct.getCapacityDemand() > iFacts.getNewVehicle().getCapacity()){
if(!Capacity.addup(loadAtPrevAct, newAct.getSize()).isLessOrEqual(iFacts.getNewVehicle().getType().getCapacityDimensions())){
return ConstraintsStatus.NOT_FULFILLED;
}
// if(loadAtPrevAct + newAct.getCapacityDemand() > iFacts.getNewVehicle().getCapacity()){
// return ConstraintsStatus.NOT_FULFILLED;
// }
}
if(newAct instanceof DeliverShipment){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) > iFacts.getNewVehicle().getCapacity()){
if(!Capacity.addup(loadAtPrevAct, Capacity.invert(newAct.getSize())).isLessOrEqual(iFacts.getNewVehicle().getType().getCapacityDimensions())){
return ConstraintsStatus.NOT_FULFILLED_BREAK;
}
// if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) > iFacts.getNewVehicle().getCapacity()){
// return ConstraintsStatus.NOT_FULFILLED_BREAK;
// }
}
return ConstraintsStatus.FULFILLED;
}

View file

@ -1,5 +1,6 @@
package jsprit.core.problem.constraint;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.activity.DeliverService;
import jsprit.core.problem.solution.route.activity.PickupService;
@ -30,28 +31,38 @@ class ServiceLoadActivityLevelConstraint implements HardActivityStateLevelConstr
@Override
public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
int futureMaxLoad;
int prevMaxLoad;
Capacity futureMaxLoad;
Capacity prevMaxLoad;
if(prevAct instanceof Start){
futureMaxLoad = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.MAXLOAD).toDouble();
prevMaxLoad = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_BEGINNING).toDouble();
futureMaxLoad = stateManager.getRouteState(iFacts.getRoute(), StateFactory.MAXLOAD, Capacity.class);
// futureMaxLoad = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.MAXLOAD).toDouble();
prevMaxLoad = stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_BEGINNING, Capacity.class);
// prevMaxLoad = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_BEGINNING).toDouble();
}
else{
futureMaxLoad = (int) stateManager.getActivityState(prevAct, StateFactory.FUTURE_MAXLOAD).toDouble();
prevMaxLoad = (int) stateManager.getActivityState(prevAct, StateFactory.PAST_MAXLOAD).toDouble();
futureMaxLoad = stateManager.getActivityState(prevAct, StateFactory.FUTURE_MAXLOAD, Capacity.class);
// futureMaxLoad = (int) stateManager.getActivityState(prevAct, StateFactory.FUTURE_MAXLOAD).toDouble();
prevMaxLoad = stateManager.getActivityState(prevAct, StateFactory.PAST_MAXLOAD, Capacity.class);
// prevMaxLoad = (int) stateManager.getActivityState(prevAct, StateFactory.PAST_MAXLOAD).toDouble();
}
if(newAct instanceof PickupService || newAct instanceof ServiceActivity){
if(newAct.getCapacityDemand() + futureMaxLoad > iFacts.getNewVehicle().getCapacity()){
// log.debug("insertionOf("+newAct+").BETWEEN("+prevAct+").AND("+nextAct+")=NOT_POSSIBLE");
if(!Capacity.addup(newAct.getSize(), futureMaxLoad).isLessOrEqual(iFacts.getNewVehicle().getType().getCapacityDimensions())){
return ConstraintsStatus.NOT_FULFILLED;
}
// if(newAct.getCapacityDemand() + futureMaxLoad > iFacts.getNewVehicle().getCapacity()){
//// log.debug("insertionOf("+newAct+").BETWEEN("+prevAct+").AND("+nextAct+")=NOT_POSSIBLE");
// return ConstraintsStatus.NOT_FULFILLED;
// }
}
if(newAct instanceof DeliverService){
if(Math.abs(newAct.getCapacityDemand()) + prevMaxLoad > iFacts.getNewVehicle().getCapacity()){
// log.debug("insertionOf("+newAct+").BETWEEN("+prevAct+").AND("+nextAct+")=NOT_POSSIBLE[break=neverBePossibleAnymore]");
if(!Capacity.addup(Capacity.invert(newAct.getSize()), prevMaxLoad).isLessOrEqual(iFacts.getNewVehicle().getType().getCapacityDimensions())){
return ConstraintsStatus.NOT_FULFILLED_BREAK;
}
// if(Math.abs(newAct.getCapacityDemand()) + prevMaxLoad > iFacts.getNewVehicle().getCapacity()){
//// log.debug("insertionOf("+newAct+").BETWEEN("+prevAct+").AND("+nextAct+")=NOT_POSSIBLE[break=neverBePossibleAnymore]");
// return ConstraintsStatus.NOT_FULFILLED_BREAK;
// }
}
// log.debug("insertionOf("+newAct+").BETWEEN("+prevAct+").AND("+nextAct+")=POSSIBLE");

View file

@ -1,5 +1,6 @@
package jsprit.core.problem.constraint;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.job.Delivery;
import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service;
@ -25,16 +26,25 @@ class ServiceLoadRouteLevelConstraint implements HardRouteStateLevelConstraint {
@Override
public boolean fulfilled(JobInsertionContext insertionContext) {
if(insertionContext.getJob() instanceof Delivery){
int loadAtDepot = (int) stateManager.getRouteState(insertionContext.getRoute(), StateFactory.LOAD_AT_BEGINNING).toDouble();
if(loadAtDepot + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
Capacity loadAtDepot = stateManager.getRouteState(insertionContext.getRoute(), StateFactory.LOAD_AT_BEGINNING, Capacity.class);
// int loadAtDepot = (int) stateManager.getRouteState(insertionContext.getRoute(), StateFactory.LOAD_AT_BEGINNING).toDouble();
if(!Capacity.addup(loadAtDepot, insertionContext.getJob().getSize()).isLessOrEqual(insertionContext.getNewVehicle().getType().getCapacityDimensions())){
return false;
}
// if(loadAtDepot + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
// return false;
// }
}
else if(insertionContext.getJob() instanceof Pickup || insertionContext.getJob() instanceof Service){
int loadAtEnd = (int) stateManager.getRouteState(insertionContext.getRoute(), StateFactory.LOAD_AT_END).toDouble();
if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
Capacity loadAtEnd = stateManager.getRouteState(insertionContext.getRoute(), StateFactory.LOAD_AT_END, Capacity.class);
// int loadAtEnd = (int) stateManager.getRouteState(insertionContext.getRoute(), StateFactory.LOAD_AT_END).toDouble();
if(!Capacity.addup(loadAtEnd, insertionContext.getJob().getSize()).isLessOrEqual(insertionContext.getNewVehicle().getType().getCapacityDimensions())){
return false;
}
//
// if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
// return false;
// }
}
return true;
}

View file

@ -35,7 +35,7 @@ import jsprit.core.util.CalculationUtils;
}
// log.info("check insertion of " + newAct + " between " + prevAct + " and " + nextAct + ". prevActDepTime=" + prevActDepTime);
double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double latestArrTimeAtNewAct = states.getActivityState(newAct, StateFactory.LATEST_OPERATION_START_TIME).toDouble();
double latestArrTimeAtNewAct = states.getActivityState(newAct, StateFactory.LATEST_OPERATION_START_TIME, Double.class);
if(arrTimeAtNewAct > latestArrTimeAtNewAct){
return ConstraintsStatus.NOT_FULFILLED;
@ -43,7 +43,7 @@ import jsprit.core.util.CalculationUtils;
// log.info(newAct + " arrTime=" + arrTimeAtNewAct);
double endTimeAtNewAct = CalculationUtils.getActivityEndTime(arrTimeAtNewAct, newAct);
double arrTimeAtNextAct = endTimeAtNewAct + routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), endTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double latestArrTimeAtNextAct = states.getActivityState(nextAct, StateFactory.LATEST_OPERATION_START_TIME).toDouble();
double latestArrTimeAtNextAct = states.getActivityState(nextAct, StateFactory.LATEST_OPERATION_START_TIME, Double.class);
if(arrTimeAtNextAct > latestArrTimeAtNextAct){
return ConstraintsStatus.NOT_FULFILLED;
}

View file

@ -35,7 +35,6 @@ import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.problem.solution.route.activity.TourActivityFactory;
import jsprit.core.problem.vehicle.PenaltyVehicleType;
@ -60,21 +59,25 @@ import org.xml.sax.SAXException;
public class VrpXMLReader{
public interface ServiceBuilderFactory {
Service.Builder createBuilder(String serviceType, String id, int size);
Service.Builder createBuilder(String serviceType, String id, Integer size);
}
static class DefaultServiceBuilderFactory implements ServiceBuilderFactory{
@Override
public jsprit.core.problem.job.Service.Builder createBuilder(String serviceType, String id, int size) {
public jsprit.core.problem.job.Service.Builder createBuilder(String serviceType, String id, Integer size) {
if(serviceType.equals("pickup")){
return Pickup.Builder.newInstance(id, size);
if(size != null) return Pickup.Builder.newInstance(id, size);
else return Pickup.Builder.newInstance(id);
}
else if(serviceType.equals("delivery")){
return Delivery.Builder.newInstance(id, size);
if(size != null) return Delivery.Builder.newInstance(id, size);
else return Delivery.Builder.newInstance(id);
}
else{
return Service.Builder.newInstance(id, size);
if(size != null) return Service.Builder.newInstance(id, size);
else return Service.Builder.newInstance(id);
}
}
}
@ -236,11 +239,6 @@ public class VrpXMLReader{
String end = routeConfig.getString("end");
if(end == null) throw new IllegalStateException("route end-time is missing.");
// Start startAct = Start.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
// startAct.setEndTime(Double.parseDouble(start));
End endAct = End.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
endAct.setArrTime(Double.parseDouble(end));
VehicleRoute.Builder routeBuilder = VehicleRoute.Builder.newInstance(vehicle, driver);
routeBuilder.setDepartureTime(departureTime);
routeBuilder.setRouteEndArrivalTime(Double.parseDouble(end));
@ -313,8 +311,29 @@ public class VrpXMLReader{
for(HierarchicalConfiguration shipmentConfig : shipmentConfigs){
String id = shipmentConfig.getString("[@id]");
if(id == null) throw new IllegalStateException("shipment[@id] is missing.");
int cap = getCap(shipmentConfig);
Shipment.Builder builder = Shipment.Builder.newInstance(id, cap);
String capacityString = shipmentConfig.getString("capacity-demand");
boolean capacityDimensionsExist = shipmentConfig.containsKey("capacity-dimensions.dimension(0)");
if(capacityString == null && !capacityDimensionsExist){
throw new IllegalStateException("capacity of shipment is not set. use 'capacity-dimensions'");
}
if(capacityString != null && capacityDimensionsExist){
throw new IllegalStateException("either use capacity or capacity-dimension, not both. prefer the use of 'capacity-dimensions' over 'capacity'.");
}
Shipment.Builder builder;
if(capacityString != null){
builder = Shipment.Builder.newInstance(id, Integer.parseInt(capacityString));
}
else {
builder = Shipment.Builder.newInstance(id);
List<HierarchicalConfiguration> dimensionConfigs = shipmentConfig.configurationsAt("capacity-dimensions.dimension");
for(HierarchicalConfiguration dimension : dimensionConfigs){
Integer index = dimension.getInt("[@index]");
Integer value = dimension.getInt("");
builder.addSizeDimension(index, value);
}
}
//pickup-locationId
String pickupLocationId = shipmentConfig.getString("pickup.locationId");
@ -394,13 +413,6 @@ public class VrpXMLReader{
return pickupCoord;
}
private static int getCap(HierarchicalConfiguration serviceConfig) {
String capacityDemand = serviceConfig.getString("capacity-demand");
int cap = 0;
if(capacityDemand != null) cap = Integer.parseInt(capacityDemand);
return cap;
}
private void readServices(XMLConfiguration vrpProblem) {
List<HierarchicalConfiguration> serviceConfigs = vrpProblem.configurationsAt("services.service");
for(HierarchicalConfiguration serviceConfig : serviceConfigs){
@ -408,8 +420,29 @@ public class VrpXMLReader{
if(id == null) throw new IllegalStateException("service[@id] is missing.");
String type = serviceConfig.getString("[@type]");
if(type == null) type = "service";
int cap = getCap(serviceConfig);
Service.Builder builder = serviceBuilderFactory.createBuilder(type, id, cap);
String capacityString = serviceConfig.getString("capacity-demand");
boolean capacityDimensionsExist = serviceConfig.containsKey("capacity-dimensions.dimension(0)");
if(capacityString == null && !capacityDimensionsExist){
throw new IllegalStateException("capacity of service is not set. use 'capacity-dimensions'");
}
if(capacityString != null && capacityDimensionsExist){
throw new IllegalStateException("either use capacity or capacity-dimension, not both. prefer the use of 'capacity-dimensions' over 'capacity'.");
}
Service.Builder builder;
if(capacityString != null){
builder = serviceBuilderFactory.createBuilder(type, id, Integer.parseInt(capacityString));
}
else {
builder = serviceBuilderFactory.createBuilder(type, id, null);
List<HierarchicalConfiguration> dimensionConfigs = serviceConfig.configurationsAt("capacity-dimensions.dimension");
for(HierarchicalConfiguration dimension : dimensionConfigs){
Integer index = dimension.getInt("[@index]");
Integer value = dimension.getInt("");
builder.addSizeDimension(index, value);
}
}
String serviceLocationId = serviceConfig.getString("locationId");
if(serviceLocationId != null) builder.setLocationId(serviceLocationId);
Coordinate serviceCoord = getCoord(serviceConfig,"");
@ -446,13 +479,34 @@ public class VrpXMLReader{
List<HierarchicalConfiguration> typeConfigs = vrpProblem.configurationsAt("vehicleTypes.type");
for(HierarchicalConfiguration typeConfig : typeConfigs){
String typeId = typeConfig.getString("id");
Integer capacity = typeConfig.getInt("capacity");
if(typeId == null) throw new IllegalStateException("typeId is missing.");
String capacityString = typeConfig.getString("capacity");
boolean capacityDimensionsExist = typeConfig.containsKey("capacity-dimensions.dimension(0)");
if(capacityString == null && !capacityDimensionsExist){
throw new IllegalStateException("capacity of type is not set. use 'capacity-dimensions'");
}
if(capacityString != null && capacityDimensionsExist){
throw new IllegalStateException("either use capacity or capacity-dimension, not both. prefer the use of 'capacity-dimensions' over 'capacity'.");
}
VehicleTypeImpl.Builder typeBuilder;
if(capacityString != null){
typeBuilder = VehicleTypeImpl.Builder.newInstance(typeId, Integer.parseInt(capacityString));
}
else {
typeBuilder = VehicleTypeImpl.Builder.newInstance(typeId);
List<HierarchicalConfiguration> dimensionConfigs = typeConfig.configurationsAt("capacity-dimensions.dimension");
for(HierarchicalConfiguration dimension : dimensionConfigs){
Integer index = dimension.getInt("[@index]");
Integer value = dimension.getInt("");
typeBuilder.addCapacityDimension(index, value);
}
}
Double fix = typeConfig.getDouble("costs.fixed");
Double timeC = typeConfig.getDouble("costs.time");
Double distC = typeConfig.getDouble("costs.distance");
if(typeId == null) throw new IllegalStateException("typeId is missing.");
if(capacity == null) throw new IllegalStateException("capacity is missing.");
VehicleTypeImpl.Builder typeBuilder = VehicleTypeImpl.Builder.newInstance(typeId, capacity);
if(fix != null) typeBuilder.setFixedCost(fix);
if(timeC != null) typeBuilder.setCostPerTime(timeC);
if(distC != null) typeBuilder.setCostPerDistance(distC);

View file

@ -174,7 +174,10 @@ public class VrpXMLWriter {
xmlConfig.setProperty(shipmentPathString + "("+counter+").coord[@x]", service.getCoord().getX());
xmlConfig.setProperty(shipmentPathString + "("+counter+").coord[@y]", service.getCoord().getY());
}
xmlConfig.setProperty(shipmentPathString + "("+counter+").capacity-demand", service.getCapacityDemand());
for(int i=0;i<service.getSize().getNuOfDimensions();i++){
xmlConfig.setProperty(shipmentPathString + "("+counter+").capacity-dimensions.dimension("+i+")[@index]", i);
xmlConfig.setProperty(shipmentPathString + "("+counter+").capacity-dimensions.dimension("+i+")", service.getSize().get(i));
}
xmlConfig.setProperty(shipmentPathString + "("+counter+").duration", service.getServiceDuration());
xmlConfig.setProperty(shipmentPathString + "("+counter+").timeWindows.timeWindow(0).start", service.getTimeWindow().getStart());
xmlConfig.setProperty(shipmentPathString + "("+counter+").timeWindows.timeWindow(0).end", service.getTimeWindow().getEnd());
@ -212,8 +215,10 @@ public class VrpXMLWriter {
xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.timeWindows.timeWindow(0).start", shipment.getDeliveryTimeWindow().getStart());
xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.timeWindows.timeWindow(0).end", shipment.getDeliveryTimeWindow().getEnd());
xmlConfig.setProperty(shipmentPathString + "("+counter+").capacity-demand", shipment.getCapacityDemand());
for(int i=0;i<shipment.getSize().getNuOfDimensions();i++){
xmlConfig.setProperty(shipmentPathString + "("+counter+").capacity-dimensions.dimension("+i+")[@index]", i);
xmlConfig.setProperty(shipmentPathString + "("+counter+").capacity-dimensions.dimension("+i+")", shipment.getSize().get(i));
}
counter++;
}
}
@ -262,7 +267,12 @@ public class VrpXMLWriter {
xmlConfig.setProperty(typePathString + "("+typeCounter+")[@penaltyFactor]", ((PenaltyVehicleType)type).getPenaltyFactor());
}
xmlConfig.setProperty(typePathString + "("+typeCounter+").id", type.getTypeId());
xmlConfig.setProperty(typePathString + "("+typeCounter+").capacity", type.getCapacity());
for(int i=0;i<type.getCapacityDimensions().getNuOfDimensions();i++){
xmlConfig.setProperty(typePathString + "("+typeCounter+").capacity-dimensions.dimension("+i+")[@index]", i);
xmlConfig.setProperty(typePathString + "("+typeCounter+").capacity-dimensions.dimension("+i+")", type.getCapacityDimensions().get(i));
}
xmlConfig.setProperty(typePathString + "("+typeCounter+").costs.fixed", type.getVehicleCostParams().fix);
xmlConfig.setProperty(typePathString + "("+typeCounter+").costs.distance", type.getVehicleCostParams().perDistanceUnit);
xmlConfig.setProperty(typePathString + "("+typeCounter+").costs.time", type.getVehicleCostParams().perTimeUnit);

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.job;
/**
* Delivery extends Service and is intended to model a Service where smth is UNLOADED (i.e. delivered) from a transport unit.
*
@ -33,9 +34,24 @@ public class Delivery extends Service{
* @param size
* @return builder
* @throws IllegalArgumentException if size < 0 or id is null
* @deprecated use <code>.newInstance(String id)</code> instead, and add a capacity dimension
* with dimensionIndex='your index' and and dimsionValue=size to the returned builder
*/
@Deprecated
public static Builder newInstance(String id, int size){
return new Builder(id,size);
Builder builder = new Builder(id,size);
builder.addSizeDimension(0, size);
return builder;
}
/**
* Returns a new instance of builder that builds a delivery.
*
* @param id
* @return the builder
*/
public static Builder newInstance(String id){
return new Builder(id);
}
/**
@ -48,6 +64,11 @@ public class Delivery extends Service{
Builder(String id, int size) {
super(id, size);
}
Builder(String id) {
super(id);
}
/**
* Builds Delivery.
*
@ -60,6 +81,7 @@ public class Delivery extends Service{
locationId = coord.toString();
}
this.setType("delivery");
super.capacity = super.capacityBuilder.build();
return new Delivery(this);
}

View file

@ -16,6 +16,9 @@
******************************************************************************/
package jsprit.core.problem.job;
import jsprit.core.problem.Capacity;
/**
* Basic interface for all jobs.
*
@ -36,9 +39,17 @@ public interface Job {
*
* <p>It determines how much capacity this job consumes of vehicle/transport unit.
*
* @deprecated use <code>.getCapacity()</code> instead
* @return
*/
@Deprecated
public int getCapacityDemand();
/**
* Returns size, i.e. capacity-demand, of this job which can consist of an arbitrary number of capacity dimensions.
*
* @return Capacity
*/
public Capacity getSize();
}

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.job;
/**
* Pickup extends Service and is intended to model a Service where smth is LOADED (i.e. picked up) to a transport unit.
*
@ -33,9 +34,24 @@ public class Pickup extends Service {
* @param size
* @return builder
* @throws IllegalArgumentException if size < 0 or id is null
* @deprecated use <code>.newInstance(String id)</code> instead, and add a capacity dimension
* with dimensionIndex='your index' and and dimsionValue=size to the returned builder
*/
@Deprecated
public static Builder newInstance(String id, int size){
return new Builder(id,size);
Builder builder = new Builder(id,size);
builder.addSizeDimension(0, size);
return builder;
}
/**
* Returns a new instance of builder that builds a pickup.
*
* @param id
* @return the builder
*/
public static Builder newInstance(String id){
return new Builder(id);
}
/**
@ -49,6 +65,10 @@ public class Pickup extends Service {
super(id, size);
}
Builder(String id) {
super(id);
}
/**
* Builds Pickup.
*
@ -63,6 +83,7 @@ public class Pickup extends Service {
locationId = coord.toString();
}
this.setType("pickup");
super.capacity = super.capacityBuilder.build();
return new Pickup(this);
}

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.job;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.util.Coordinate;
@ -43,13 +44,30 @@ public class Service implements Job {
/**
* Returns a new instance of service-builder.
*
* <p>Note that if you use this builder, size is assigned to capacity-dimension with index=0.
*
* @param id of service
* @param size of capacity-demand
* @return builder
* @throws IllegalArgumentException if size < 0 or id is null
* @deprecated use <code>.newInstance(String id)</code> instead, and add a capacity dimension
* with dimensionIndex='your index' and and dimsionValue=size to the returned builder
*/
@Deprecated
public static Builder newInstance(String id, int size){
return new Builder(id,size);
Builder builder = new Builder(id,size);
builder.addSizeDimension(0, size);
return builder;
}
/**
* Returns a new instance of builder that builds a service.
*
* @param id
* @return the builder
*/
public static Builder newInstance(String id){
return new Builder(id);
}
private String id;
@ -64,7 +82,9 @@ public class Service implements Job {
protected TimeWindow timeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);
protected int demand;
protected Capacity.Builder capacityBuilder = Capacity.Builder.newInstance();
protected Capacity capacity;
/**
* Constructs the builder.
@ -77,7 +97,10 @@ public class Service implements Job {
if(size < 0) throw new IllegalArgumentException("size must be greater than or equal to zero");
if(id == null) throw new IllegalArgumentException("id must not be null");
this.id = id;
this.demand = size;
}
Builder(String id){
this.id = id;
}
/**
@ -131,6 +154,20 @@ public class Service implements Job {
return this;
}
/**
* Adds capacity dimension.
*
* @param dimensionIndex
* @param dimensionValue
* @return the builder
* @throws IllegalArgumentException if dimensionValue < 0
*/
public Builder addSizeDimension(int dimensionIndex, int dimensionValue){
if(dimensionValue<0) throw new IllegalArgumentException("capacity value cannot be negative");
capacityBuilder.addDimension(dimensionIndex, dimensionValue);
return this;
}
/**
* Sets the time-window of this service.
*
@ -158,6 +195,7 @@ public class Service implements Job {
locationId = coord.toString();
}
this.setType("service");
capacity = capacityBuilder.build();
return new Service(this);
}
@ -175,8 +213,8 @@ public class Service implements Job {
private final double serviceTime;
private final TimeWindow timeWindow;
private final int demand;
private final Capacity size;
Service(Builder builder){
id = builder.id;
@ -184,8 +222,8 @@ public class Service implements Job {
coord = builder.coord;
serviceTime = builder.serviceTime;
timeWindow = builder.timeWindow;
demand = builder.demand;
type = builder.type;
size = builder.capacity;
}
@Override
@ -229,9 +267,15 @@ public class Service implements Job {
return timeWindow;
}
/**
* @Deprecated use <code>.getCapacity()</code> instead. if you still use this method, it returns the
* capacity dimension with index=0.
*
*/
@Override
@Deprecated
public int getCapacityDemand() {
return demand;
return size.get(0);
}
/**
@ -248,7 +292,7 @@ public class Service implements Job {
*/
@Override
public String toString() {
return "[id=" + id + "][type="+type+"][locationId=" + locationId + "][coord="+coord+"][size=" + demand + "][serviceTime=" + serviceTime + "][timeWindow=" + timeWindow + "]";
return "[id=" + id + "][type="+type+"][locationId=" + locationId + "][coord="+coord+"][capacity=" + size + "][serviceTime=" + serviceTime + "][timeWindow=" + timeWindow + "]";
}
@ -281,6 +325,9 @@ public class Service implements Job {
return true;
}
@Override
public Capacity getSize() {
return size;
}
}

View file

@ -1,5 +1,6 @@
package jsprit.core.problem.job;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.util.Coordinate;
@ -30,8 +31,6 @@ public class Shipment implements Job{
*/
public static class Builder {
private int demand;
private String id;
private String pickupLocation;
@ -48,18 +47,33 @@ public class Shipment implements Job{
private TimeWindow deliveryTimeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);
private TimeWindow pickupTimeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);;
private TimeWindow pickupTimeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);
private Capacity.Builder capacityBuilder = Capacity.Builder.newInstance();
private Capacity capacity;
/**
* Returns a new instance of this builder.
*
* <p>Note that if you use this builder, size is assigned to capacity-dimension with index=0.
*
* @param id
* @param size
* @return builder
* @throws IllegalArgumentException if size < 0 or id is null
* @deprecated use <code>.newInstance(String id)</code> instead, and add a capacity dimension
* with dimensionIndex='your index' and and dimsionValue=size to the returned builder
*/
@Deprecated
public static Builder newInstance(String id, int size){
return new Builder(id,size);
Builder builder = new Builder(id,size);
builder.addSizeDimension(0, size);
return builder;
}
public static Builder newInstance(String id){
return new Builder(id);
}
/**
@ -73,7 +87,10 @@ public class Shipment implements Job{
if(size < 0) throw new IllegalArgumentException("size must be greater than or equal to zero");
if(id == null) throw new IllegalArgumentException("id must not be null");
this.id = id;
this.demand = size;
}
Builder(String id){
this.id = id;
}
/**
@ -190,6 +207,21 @@ public class Shipment implements Job{
return this;
}
/**
* Adds capacity dimension.
*
* @param dimensionIndex
* @param dimensionValue
* @return builder
* @throws IllegalArgumentException if dimVal < 0
*/
public Builder addSizeDimension(int dimensionIndex, int dimensionValue) {
if(dimensionValue<0) throw new IllegalArgumentException("capacity value cannot be negative");
capacityBuilder.addDimension(dimensionIndex, dimensionValue);
return this;
}
/**
* Builds the shipment.
*
@ -206,12 +238,13 @@ public class Shipment implements Job{
if(deliveryCoord == null) throw new IllegalStateException("either locationId or a coordinate must be given. But is not.");
deliveryLocation = deliveryCoord.toString();
}
capacity = capacityBuilder.build();
return new Shipment(this);
}
}
private final int demand;
private final String id;
private final String pickupLocation;
@ -230,6 +263,9 @@ public class Shipment implements Job{
private final TimeWindow pickupTimeWindow;
private final Capacity capacity;
/**
* Constructs the shipment.
*
@ -237,7 +273,6 @@ public class Shipment implements Job{
*/
Shipment(Builder builder){
this.id = builder.id;
this.demand = builder.demand;
this.pickupLocation = builder.pickupLocation;
this.pickupCoord = builder.pickupCoord;
this.pickupServiceTime = builder.pickupServiceTime;
@ -246,6 +281,7 @@ public class Shipment implements Job{
this.deliveryCoord = builder.deliveryCoord;
this.deliveryServiceTime = builder.deliveryServiceTime;
this.deliveryTimeWindow = builder.deliveryTimeWindow;
this.capacity = builder.capacity;
}
@Override
@ -253,9 +289,14 @@ public class Shipment implements Job{
return id;
}
/**
* @Deprecated use <code>.getCapacity()</code> instead. if you still use this method, it returns the
* capacity dimension with index=0.
*/
@Deprecated
@Override
public int getCapacityDemand() {
return demand;
return capacity.get(0);
}
/**
@ -362,5 +403,10 @@ public class Shipment implements Job{
return true;
}
@Override
public Capacity getSize() {
return capacity;
}
}

View file

@ -1,11 +1,14 @@
package jsprit.core.problem.solution.route.activity;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.job.Delivery;
public final class DeliverService implements DeliveryActivity{
private Delivery delivery;
private Capacity capacity;
private double arrTime;
private double endTime;
@ -13,14 +16,20 @@ public final class DeliverService implements DeliveryActivity{
public DeliverService(Delivery delivery) {
super();
this.delivery = delivery;
capacity = Capacity.invert(delivery.getSize());
}
private DeliverService(DeliverService deliveryActivity){
this.delivery=deliveryActivity.getJob();
this.arrTime=deliveryActivity.getArrTime();
this.endTime=deliveryActivity.getEndTime();
capacity = deliveryActivity.getSize();
}
/**
* @deprecated use <code>getCapacity()</code> instead
*/
@Deprecated
@Override
public int getCapacityDemand() {
return delivery.getCapacityDemand()*-1;
@ -85,4 +94,9 @@ public final class DeliverService implements DeliveryActivity{
public String toString() {
return "[act="+getName()+"][capDemand="+getCapacityDemand()+"][loc="+getLocationId()+"]";
}
@Override
public Capacity getSize() {
return capacity;
}
}

View file

@ -1,23 +1,30 @@
package jsprit.core.problem.solution.route.activity;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Shipment;
public final class DeliverShipment implements DeliveryActivity{
private Shipment shipment;
private double endTime;
private double arrTime;
private Capacity capacity;
public DeliverShipment(Shipment shipment) {
super();
this.shipment = shipment;
this.capacity = Capacity.invert(shipment.getSize());
}
public DeliverShipment(DeliverShipment deliveryShipmentActivity) {
this.shipment = (Shipment) deliveryShipmentActivity.getJob();
this.arrTime = deliveryShipmentActivity.getArrTime();
this.endTime = deliveryShipmentActivity.getEndTime();
this.capacity = deliveryShipmentActivity.getSize();
}
@Override
@ -25,6 +32,10 @@ public final class DeliverShipment implements DeliveryActivity{
return shipment;
}
/**
* @deprecated use <code>getCapacity()</code> instead
*/
@Deprecated
@Override
public int getCapacityDemand() {
return shipment.getCapacityDemand()*-1;
@ -84,4 +95,9 @@ public final class DeliverShipment implements DeliveryActivity{
public String toString() {
return "[act="+getName()+"][loc="+getLocationId()+"]";
}
@Override
public Capacity getSize() {
return capacity;
}
}

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.solution.route.activity;
import jsprit.core.problem.Capacity;
import jsprit.core.util.Coordinate;
public final class End implements TourActivity {
@ -31,6 +32,8 @@ public final class End implements TourActivity {
return new End(end);
}
private final static Capacity capacity = Capacity.Builder.newInstance().build();
private String locationId;
private Coordinate coordinate;
@ -147,4 +150,9 @@ public final class End implements TourActivity {
return new End(this);
}
@Override
public Capacity getSize() {
return capacity;
}
}

View file

@ -1,5 +1,6 @@
package jsprit.core.problem.solution.route.activity;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service;
@ -81,7 +82,12 @@ public final class PickupService implements PickupActivity{
return pickup;
}
/**
* @deprecated use <code>getCapacity()</code> instead
*
*/
@Override
@Deprecated
public int getCapacityDemand() {
return pickup.getCapacityDemand();
}
@ -91,4 +97,9 @@ public final class PickupService implements PickupActivity{
return "[act="+getName()+"][capDemand="+getCapacityDemand()+"][loc="+getLocationId()+"]";
}
@Override
public Capacity getSize() {
return pickup.getSize();
}
}

View file

@ -1,12 +1,15 @@
package jsprit.core.problem.solution.route.activity;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Shipment;
public final class PickupShipment implements PickupActivity{
private Shipment shipment;
private double endTime;
private double arrTime;
public PickupShipment(Shipment shipment) {
@ -25,6 +28,10 @@ public final class PickupShipment implements PickupActivity{
return shipment;
}
/**
* @deprecated use <code>getCapacity()</code> instead
*/
@Deprecated
@Override
public int getCapacityDemand() {
return shipment.getCapacityDemand();
@ -85,4 +92,11 @@ public final class PickupShipment implements PickupActivity{
return "[act="+getName()+"][loc="+getLocationId()+"]";
}
@Override
public Capacity getSize() {
return shipment.getSize();
}
}

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.solution.route.activity;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.solution.route.activity.TourActivity.JobActivity;
@ -27,8 +28,6 @@ public class ServiceActivity implements JobActivity{
public double endTime;
public int capacityDemand;
/**
* @return the arrTime
*/
@ -64,24 +63,13 @@ public class ServiceActivity implements JobActivity{
public static ServiceActivity newInstance(Service service){
return new ServiceActivity(service);
}
/**
* creates a new instance of {@link ServiceActivity} with a flag that indicates whether smthing is unloaded or loaded.
*
* @param service
* @param capacityDemand
* @return
*/
// public static ServiceActivity newInstance(Service service, boolean isPickup){
// return new ServiceActivity(service, capacityDemand);
// }
private final Service service;
protected ServiceActivity(Service service) {
counter++;
this.service = service;
this.capacityDemand = service.getCapacityDemand();
}
protected ServiceActivity(ServiceActivity serviceActivity) {
@ -89,7 +77,6 @@ public class ServiceActivity implements JobActivity{
this.service = serviceActivity.getJob();
this.arrTime = serviceActivity.getArrTime();
this.endTime = serviceActivity.getEndTime();
this.capacityDemand = serviceActivity.getCapacityDemand();
}
@ -132,9 +119,13 @@ public class ServiceActivity implements JobActivity{
return service.getTimeWindow().getEnd();
}
/**
* @deprecated use <code>getCapacity()</code> instead
*/
@Override
@Deprecated
public int getCapacityDemand() {
return this.capacityDemand;
return service.getCapacityDemand();
}
@Override
@ -166,6 +157,11 @@ public class ServiceActivity implements JobActivity{
public TourActivity duplicate() {
return new ServiceActivity(this);
}
@Override
public Capacity getSize() {
return service.getSize();
}

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.solution.route.activity;
import jsprit.core.problem.Capacity;
import jsprit.core.util.Coordinate;
public final class Start implements TourActivity {
@ -24,6 +25,8 @@ public final class Start implements TourActivity {
public static int creation;
private final static Capacity capacity = Capacity.Builder.newInstance().build();
public static Start newInstance(String locationId, double theoreticalStart, double theoreticalEnd){
creation++;
return new Start(locationId,theoreticalStart,theoreticalEnd);
@ -35,8 +38,6 @@ public final class Start implements TourActivity {
private String locationId;
private Coordinate coordinate;
private double theoretical_earliestOperationStartTime;
@ -45,7 +46,7 @@ public final class Start implements TourActivity {
private double endTime;
private double arrTime;
private double arrTime;
public Start(String locationId, double theoreticalStart, double theoreticalEnd) {
super();
@ -62,13 +63,13 @@ public final class Start implements TourActivity {
theoretical_latestOperationStartTime = start.getTheoreticalLatestOperationStartTime();
endTime = start.getEndTime();
}
@Deprecated
Coordinate getCoordinate() {
return coordinate;
}
@Deprecated
void setCoordinate(Coordinate coordinate) {
this.coordinate = coordinate;
}
@ -153,6 +154,9 @@ public final class Start implements TourActivity {
return new Start(this);
}
@Override
public Capacity getSize() {
return capacity;
}
}

View file

@ -16,37 +16,130 @@
******************************************************************************/
package jsprit.core.problem.solution.route.activity;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.job.Job;
/**
* Basic interface for tour-activities.
*
* <p>A tour activity is the basic element of a tour, which is consequently a sequence of tour-activities.
*
* @author schroeder
*
*/
public interface TourActivity {
/**
* Basic interface of job-activies.
*
* <p>A job activity is related to a {@link Job}.
*
* @author schroeder
*
*/
public interface JobActivity extends TourActivity {
/**
* Returns the job that is involved with this activity.
*
* @return job
*/
public Job getJob();
}
/**
* Returns the capacity-demand of that activity, in terms of what needs to be loaded or unloaded at
* this activity.
*
* @return int
* @deprecated use <code>getCapacity()</code> instead
*/
@Deprecated
public int getCapacityDemand();
/**
* Returns the name of this activity.
*
* @return name
*/
public abstract String getName();
/**
* Returns the activity's locationId.
*
* @return locationId
*/
public abstract String getLocationId();
/**
* Returns the theoretical earliest operation start time, which is the time that is just allowed
* (not earlier) to start this activity, that is for example <code>service.getTimeWindow().getStart()</code>.
*
* @return earliest start time
*/
public abstract double getTheoreticalEarliestOperationStartTime();
/**
* Returns the theoretical latest operation start time, which is the time that is just allowed
* (not later) to start this activity, that is for example <code>service.getTimeWindow().getEnd()</code>.
*
*
* @return latest start time
*/
public abstract double getTheoreticalLatestOperationStartTime();
/**
* Returns the operation-time this activity takes.
*
* <p>Note that this is not necessarily the duration of this activity, but the
* service time a pickup/delivery actually takes, that is for example <code>service.getServiceTime()</code>.
*
* @return operation time
*/
public abstract double getOperationTime();
/**
* Returns the arrival-time of this activity.
*
* @return arrival time
*/
public abstract double getArrTime();
/**
* Returns end-time of this activity.
*
* @return end time
*/
public abstract double getEndTime();
/**
* Sets the arrival time of that activity.
*
* @param arrTime
*/
public abstract void setArrTime(double arrTime);
/**
* Sets the end-time of this activity.
*
* @param endTime
*/
public abstract void setEndTime(double endTime);
public TourActivity duplicate();
/**
* Returns the capacity-demand of that activity, in terms of what needs to be loaded or unloaded at
* this activity.
*
* @return capacity
*/
public abstract Capacity getSize();
/**
* Makes a deep copy of this activity.
*
* @return copied activity
*/
public abstract TourActivity duplicate();
}

View file

@ -23,9 +23,14 @@ import jsprit.core.problem.solution.route.state.StateFactory.StateId;
public interface RouteAndActivityStateGetter {
@Deprecated
public State getActivityState(TourActivity act, StateId stateId);
@Deprecated
public State getRouteState(VehicleRoute route, StateId stateId);
public <T> T getActivityState(TourActivity act, StateId stateId, Class<T> type);
public <T> T getRouteState(VehicleRoute route, StateId stateId, Class<T> type);
}

View file

@ -47,6 +47,7 @@ public class StateFactory {
}
static class StateImpl implements State{
double state;

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.vehicle;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.vehicle.VehicleTypeImpl.VehicleCostParams;
public class PenaltyVehicleType implements VehicleType{
@ -44,6 +45,10 @@ public class PenaltyVehicleType implements VehicleType{
return type.getTypeId();
}
/**
* @deprecated use <code>getCapacityDimensions()</code> instead
*/
@Deprecated
@Override
public int getCapacity() {
return type.getCapacity();
@ -59,6 +64,11 @@ public class PenaltyVehicleType implements VehicleType{
return type.getMaxVelocity();
}
@Override
public Capacity getCapacityDimensions() {
return type.getCapacityDimensions();
}
}

View file

@ -81,7 +81,11 @@ public interface Vehicle {
* Returns the capacity of this vehicle.
*
* @return capacity
* @deprecated use .getType().getCapacityDimensions() - if you still use this method,
* but set capacity-dimensions via <code>VehicleTypeImpl.Builder.newInstance(...).addCapacityDimension(...)</code> then this method returns the
* dimension with index=0.
*/
@Deprecated
public abstract int getCapacity();
/**

View file

@ -87,7 +87,7 @@ public class VehicleImpl implements Vehicle {
private boolean returnToDepot = true;
private VehicleType type = VehicleTypeImpl.Builder.newInstance("default", 0).build();
private VehicleType type = VehicleTypeImpl.Builder.newInstance("default").build();
/**
* Constructs the builder with the vehicleId.
@ -372,6 +372,7 @@ public class VehicleImpl implements Vehicle {
}
@Override
@Deprecated
public int getCapacity() {
return type.getCapacity();
}

View file

@ -16,6 +16,7 @@
******************************************************************************/
package jsprit.core.problem.vehicle;
import jsprit.core.problem.Capacity;
import jsprit.core.problem.vehicle.VehicleTypeImpl.VehicleCostParams;
/**
@ -38,10 +39,21 @@ public interface VehicleType {
*
* <p>In future versions there will be a capacity-object with an arbitrary number of capacity dimensions. (stefan,11.01.14)
*
*
* @deprecated use <code>.getCapacityDimensions()</code> - if you still use it, but set CapacityDimensions rather
* than setCapacity(...) it will return the capacity.dimension with index=0
* @return cap
*/
@Deprecated
public int getCapacity();
/**
* Returns capacity dimensions.
*
* @return {@link Capacity}
*/
public Capacity getCapacityDimensions();
/**
* Returns maximum velocity of this vehicle-type.
*

View file

@ -16,6 +16,9 @@
******************************************************************************/
package jsprit.core.problem.vehicle;
import jsprit.core.problem.Capacity;
/**
* Implementation of {@link VehicleType}.
*
@ -73,15 +76,24 @@ public class VehicleTypeImpl implements VehicleType {
* @param capacity
* @return the vehicleType builder
* @throws IllegalStateException if capacity is smaller than zero or id is null
* @deprecated use <code>newInstance(String id)</code> instead
*/
@Deprecated
public static VehicleTypeImpl.Builder newInstance(String id, int capacity){
if(capacity < 0) throw new IllegalStateException("capacity cannot be smaller than zero");
if(id == null) throw new IllegalStateException("typeId must be null");
return new Builder(id,capacity);
Builder builder = new Builder(id,capacity);
builder.addCapacityDimension(0, capacity);
return builder;
}
public static VehicleTypeImpl.Builder newInstance(String id) {
return new Builder(id);
}
private String id;
private int capacity;
private int capacity = 0;
private double maxVelo = Double.MAX_VALUE;
/**
* default cost values for default vehicle type
@ -89,6 +101,12 @@ public class VehicleTypeImpl implements VehicleType {
private double fixedCost = 0.0;
private double perDistance = 1.0;
private double perTime = 0.0;
private Capacity.Builder capacityBuilder = Capacity.Builder.newInstance();
private Capacity capacityDimensions = null;
private boolean dimensionAdded = false;
/**
* Constructs the builder.
@ -96,12 +114,17 @@ public class VehicleTypeImpl implements VehicleType {
* @param id
* @param capacity
*/
@Deprecated
private Builder(String id, int capacity) {
super();
this.id = id;
this.capacity = capacity;
}
public Builder(String id) {
this.id = id;
}
/**
* Sets the maximum velocity this vehicle-type can go [in meter per seconds].
*
@ -165,9 +188,49 @@ public class VehicleTypeImpl implements VehicleType {
* @return VehicleTypeImpl
*/
public VehicleTypeImpl build(){
if(capacityDimensions == null){
capacityDimensions = capacityBuilder.build();
}
return new VehicleTypeImpl(this);
}
/**
* Adds a capacity dimension.
*
* @param dimIndex
* @param dimVal
* @return the builder
* @throws IllegalArgumentException if dimVal < 0
* @throws IllegalStateException if capacity dimension is already set
*/
public Builder addCapacityDimension(int dimIndex, int dimVal) {
if(dimVal<0) throw new IllegalArgumentException("capacity value cannot be negative");
if(capacityDimensions != null) throw new IllegalStateException("either build your dimension with build your dimensions with " +
"addCapacityDimension(int dimIndex, int dimVal) or set the already built dimensions with .setCapacityDimensions(Capacity capacity)." +
"You used both methods.");
dimensionAdded = true;
capacityBuilder.addDimension(dimIndex,dimVal);
return this;
}
/**
* Sets capacity dimensions.
*
* <p>Note if you use this you cannot use <code>addCapacityDimension(int dimIndex, int dimVal)</code> anymore. Thus either build
* your dimensions with <code>addCapacityDimension(int dimIndex, int dimVal)</code> or set the already built dimensions with
* this method.
*
* @param capacity
* @return this builder
* @throws IllegalStateException if capacityDimension has already been added
*/
public Builder setCapacityDimensions(Capacity capacity){
if(dimensionAdded) throw new IllegalStateException("either build your dimension with build your dimensions with " +
"addCapacityDimension(int dimIndex, int dimVal) or set the already built dimensions with .setCapacityDimensions(Capacity capacity)." +
"You used both methods.");
this.capacityDimensions = capacity;
return this;
}
}
@Override
@ -205,8 +268,11 @@ public class VehicleTypeImpl implements VehicleType {
private final VehicleTypeImpl.VehicleCostParams vehicleCostParams;
private final Capacity capacityDimensions;
private final double maxVelocity;
/**
* @deprecated use builder instead
*/
@ -225,6 +291,7 @@ public class VehicleTypeImpl implements VehicleType {
capacity = builder.capacity;
maxVelocity = builder.maxVelo;
vehicleCostParams = new VehicleCostParams(builder.fixedCost, builder.perTime, builder.perDistance);
capacityDimensions = builder.capacityDimensions;
}
/**
@ -240,6 +307,7 @@ public class VehicleTypeImpl implements VehicleType {
this.typeId = typeId;
this.capacity = capacity;
this.vehicleCostParams = vehicleCostParams;
this.capacityDimensions = Capacity.Builder.newInstance().addDimension(0, capacity).build();
this.maxVelocity = Double.MAX_VALUE;
}
@ -255,8 +323,9 @@ public class VehicleTypeImpl implements VehicleType {
* @see basics.route.VehicleType#getCapacity()
*/
@Override
@Deprecated
public int getCapacity() {
return capacity;
return capacityDimensions.get(0);
}
/* (non-Javadoc)
@ -276,4 +345,9 @@ public class VehicleTypeImpl implements VehicleType {
public double getMaxVelocity() {
return maxVelocity;
}
@Override
public Capacity getCapacityDimensions() {
return capacityDimensions;
}
}

View file

@ -1,97 +0,0 @@
/*******************************************************************************
* 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 <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.util;
import java.util.Collection;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.vehicle.Vehicle;
import org.apache.log4j.Logger;
/**
* Verifies whether vrp can be solved.
*
* <p>Checks<br>
* - capacities, i.e. whether all job at least fit into the biggest vehicle
*
* @author stefan
*
*/
public class VrpVerifier implements AlgorithmStartsListener{
private static Logger log = Logger.getLogger(VrpVerifier.class);
@Override
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
//check capacity
log.info("verifying vehicle-routing-problem ...");
log.info("check vehicle capacities ...");
Vehicle vehicleWithMaxCapacity = getMaxVehicle(problem);
if(vehicleWithMaxCapacity == null) throw new IllegalStateException("vehicles are missing.");
for(Job j : problem.getJobs().values()){
if(vehicleWithMaxCapacity.getCapacity() < Math.abs(j.getCapacityDemand())){
throw new IllegalStateException("maximal vehicle-capacity is "+vehicleWithMaxCapacity.getCapacity() + ", but there is a job bigger than this. [job=" + j + "]");
}
}
log.info("ok");
// log.info("check vehicles can manage shuttle tours ...");
// for(Job j : problem.getJobs().values()){
// Service s = (Service)j;
// boolean jobCanBeRoutedWithinTimeWindow = false;
// for(Vehicle v : problem.getVehicles()){
// double transportTime = problem.getTransportCosts().getTransportTime(v.getStartLocationId(), s.getLocationId(), v.getEarliestDeparture(), DriverImpl.noDriver(), v);
// if(transportTime+v.getEarliestDeparture() < s.getTimeWindow().getEnd()){
// jobCanBeRoutedWithinTimeWindow = true;
// break;
// }
// else{
// log.warn("vehicle " + v + " needs " + transportTime + " time-units to get to " + s.getLocationId() + ". latestOperationStartTime however is " + s.getTimeWindow().getEnd());
// }
//
// }
// if(!jobCanBeRoutedWithinTimeWindow){
// throw new IllegalStateException("no vehicle is able to cover the distance from depot to " + s.getLocationId() + " to meet the time-window " + s.getTimeWindow() + ".");
// }
// }
// log.info("ok");
log.info("verifying done");
}
public void verify(VehicleRoutingProblem pblm, VehicleRoutingAlgorithm vra){
informAlgorithmStarts(pblm, vra, null);
}
private Vehicle getMaxVehicle(VehicleRoutingProblem problem) {
Vehicle maxVehicle = null;
for(Vehicle v : problem.getVehicles()){
if(maxVehicle == null) {
maxVehicle = v;
continue;
}
else if(v.getCapacity() > maxVehicle.getCapacity()){
maxVehicle = v;
}
}
return maxVehicle;
}
}

View file

@ -82,6 +82,21 @@
<xs:all>
<xs:element name="id" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="capacity" type="xs:integer" minOccurs="0" maxOccurs="1" default="0"/>
<xs:element name="capacity-dimensions" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="dimension" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:integer">
<xs:attribute name="index" type="xs:integer" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="costs">
<xs:complexType>
<xs:all>
@ -109,6 +124,21 @@
<xs:element name="locationId" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="coord" type="coordType" minOccurs="0" maxOccurs="1"/>
<xs:element name="capacity-demand" type="xs:integer" minOccurs="0" maxOccurs="1" default="0"/>
<xs:element name="capacity-dimensions" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="dimension" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:integer">
<xs:attribute name="index" type="xs:integer" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="duration" type="xs:decimal" minOccurs="0" maxOccurs="1" default="0.0"/>
<xs:element name="timeWindows" minOccurs="0" maxOccurs="1">
<xs:complexType>
@ -165,7 +195,22 @@
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="capacity-demand" type="xs:integer" minOccurs="1" maxOccurs="1"/>
<xs:element name="capacity-demand" type="xs:integer" minOccurs="0" maxOccurs="1"/>
<xs:element name="capacity-dimensions" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="dimension" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:integer">
<xs:attribute name="index" type="xs:integer" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required" />
</xs:complexType>