diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateLoads.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateLoads.java index b6efcfa7..7ad3afe7 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateLoads.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateLoads.java @@ -1,20 +1,18 @@ /******************************************************************************* - * Copyright (c) 2014 Stefan Schroeder. - * + * Copyright (C) 2014 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 + * 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 + * 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 . - * - * Contributors: - * Stefan Schroeder - initial API and implementation ******************************************************************************/ package jsprit.core.algorithm.state; @@ -73,8 +71,8 @@ class UpdateLoads implements ActivityVisitor, StateUpdater, InsertionStartsListe public void visit(TourActivity act) { currentLoad = Capacity.addup(currentLoad, act.getSize()); stateManager.putInternalTypedActivityState(act, InternalStates.LOAD, 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"; +// 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 diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxCapacityUtilisationAtActivitiesByLookingBackwardInRoute.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxCapacityUtilisationAtActivitiesByLookingBackwardInRoute.java index 7a76d160..4355d6cd 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxCapacityUtilisationAtActivitiesByLookingBackwardInRoute.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxCapacityUtilisationAtActivitiesByLookingBackwardInRoute.java @@ -1,20 +1,18 @@ /******************************************************************************* - * Copyright (c) 2014 Stefan Schroeder. - * + * Copyright (C) 2014 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 + * 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 + * 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 . - * - * Contributors: - * Stefan Schroeder - initial API and implementation ******************************************************************************/ package jsprit.core.algorithm.state; @@ -56,8 +54,8 @@ class UpdateMaxCapacityUtilisationAtActivitiesByLookingBackwardInRoute implement public void visit(TourActivity act) { maxLoad = Capacity.max(maxLoad, stateManager.getActivityState(act, InternalStates.LOAD, Capacity.class)); stateManager.putInternalTypedActivityState(act, InternalStates.PAST_MAXLOAD, 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"; +// 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 diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute.java index fa2075b8..d66e7267 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute.java @@ -1,20 +1,18 @@ /******************************************************************************* - * Copyright (c) 2014 Stefan Schroeder. - * + * Copyright (C) 2014 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 + * 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 + * 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 . - * - * Contributors: - * Stefan Schroeder - initial API and implementation ******************************************************************************/ package jsprit.core.algorithm.state; @@ -69,8 +67,8 @@ class UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute implements public void visit(TourActivity act) { maxLoad = Capacity.max(maxLoad, stateManager.getActivityState(act, InternalStates.LOAD, Capacity.class)); stateManager.putInternalTypedActivityState(act, InternalStates.FUTURE_MAXLOAD, maxLoad); - assert maxLoad.isLessOrEqual(route.getVehicle().getType().getCapacityDimensions()) : "maxLoad can in every capacity dimension never be bigger than vehicleCap"; - assert maxLoad.isGreaterOrEqual(Capacity.Builder.newInstance().build()) : "maxLoad can never be smaller than 0"; +// assert maxLoad.isLessOrEqual(route.getVehicle().getType().getCapacityDimensions()) : "maxLoad can in every capacity dimension never be bigger than vehicleCap"; +// assert maxLoad.isGreaterOrEqual(Capacity.Builder.newInstance().build()) : "maxLoad can never be smaller than 0"; } @Override diff --git a/jsprit-core/src/main/java/jsprit/core/analysis/SolutionAnalyser.java b/jsprit-core/src/main/java/jsprit/core/analysis/SolutionAnalyser.java index 7eb9449c..92a249fd 100644 --- a/jsprit-core/src/main/java/jsprit/core/analysis/SolutionAnalyser.java +++ b/jsprit-core/src/main/java/jsprit/core/analysis/SolutionAnalyser.java @@ -23,6 +23,10 @@ import jsprit.core.algorithm.state.StateManager; import jsprit.core.algorithm.state.StateUpdater; import jsprit.core.problem.Capacity; import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.constraint.ConstraintManager; +import jsprit.core.problem.constraint.HardActivityConstraint; +import jsprit.core.problem.constraint.HardRouteConstraint; +import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.activity.ActivityVisitor; import jsprit.core.problem.solution.route.activity.End; @@ -31,7 +35,6 @@ import jsprit.core.problem.solution.route.activity.TourActivity; import jsprit.core.util.ActivityTimeTracker; import java.util.ArrayList; -import java.util.Collection; import java.util.List; /** @@ -39,12 +42,35 @@ import java.util.List; */ public class SolutionAnalyser { + + + public static interface DistanceCalculator { public double getDistance(String fromLocationId, String toLocationId); } +// public static class ViolatedRouteConstraints { +// +// private List hardRouteConstraints = new ArrayList(); +// +// public List getHardRouteConstraints() { +// return hardRouteConstraints; +// } +// +// } +// +// public static class ViolatedActivityConstraints { +// +// private List hardConstraints = new ArrayList(); +// +// public List getHardActivityConstraints() { +// return hardConstraints; +// } +// +// } + private static class SumUpWaitingTimes implements StateUpdater, ActivityVisitor { private StateId waiting_time_id; @@ -53,6 +79,8 @@ public class SolutionAnalyser { private StateId service_time_id; + private StateId too_late_id; + private StateManager stateManager; private ActivityTimeTracker.ActivityPolicy activityPolicy; @@ -65,12 +93,15 @@ public class SolutionAnalyser { double sum_service_time = 0.; + double sum_too_late = 0.; + double prevActDeparture; - private SumUpWaitingTimes(StateId waiting_time_id, StateId transport_time_id, StateId service_time_id, StateManager stateManager, ActivityTimeTracker.ActivityPolicy activityPolicy) { + private SumUpWaitingTimes(StateId waiting_time_id, StateId transport_time_id, StateId service_time_id, StateId too_late_id, StateManager stateManager, ActivityTimeTracker.ActivityPolicy activityPolicy) { this.waiting_time_id = waiting_time_id; this.transport_time_id = transport_time_id; this.service_time_id = service_time_id; + this.too_late_id = too_late_id; this.stateManager = stateManager; this.activityPolicy = activityPolicy; } @@ -81,23 +112,28 @@ public class SolutionAnalyser { sum_waiting_time = 0.; sum_transport_time = 0.; sum_service_time = 0.; + sum_too_late = 0.; prevActDeparture = route.getDepartureTime(); } @Override public void visit(TourActivity activity) { - //waiting time + //waiting time & toolate double waitAtAct = 0.; + double tooLate = 0.; if(activityPolicy.equals(ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS)){ waitAtAct = Math.max(0,activity.getTheoreticalEarliestOperationStartTime() - activity.getArrTime()); + tooLate = Math.max(0,activity.getArrTime() - activity.getTheoreticalLatestOperationStartTime()); } sum_waiting_time += waitAtAct; + sum_too_late += tooLate; //transport time double transportTime = activity.getArrTime() - prevActDeparture; sum_transport_time += transportTime; prevActDeparture = activity.getEndTime(); //service time sum_service_time += activity.getOperationTime(); + } @Override @@ -106,6 +142,7 @@ public class SolutionAnalyser { stateManager.putRouteState(route,transport_time_id,sum_transport_time); stateManager.putRouteState(route,waiting_time_id,sum_waiting_time); stateManager.putRouteState(route,service_time_id,sum_service_time); + stateManager.putRouteState(route,too_late_id,sum_too_late); } } @@ -152,12 +189,77 @@ public class SolutionAnalyser { } } +// private static class ConstraintViolationUpdater implements StateUpdater, ActivityVisitor { +// +// private ConstraintManager constraintManager; +// +// private StateManager stateManager; +// +// private StateId violated_route_constraints_id; +// +// private VehicleRoute route; +// +// private List hardRouteConstraints; +// +// private Set examinedJobs = new HashSet(); +// +//// ViolatedRouteConstraints violatedRouteConstraints = new ViolatedRouteConstraints(); +// +// private ConstraintViolationUpdater(ConstraintManager constraintManager, StateManager stateManager, StateId violated_route_constraints_id) { +// this.constraintManager = constraintManager; +// this.stateManager = stateManager; +// this.violated_route_constraints_id = violated_route_constraints_id; +// hardRouteConstraints = getHardRouteConstraints(constraintManager); +// } +// +// private List getHardRouteConstraints(ConstraintManager constraintManager) { +// List constraints = new ArrayList(); +// for(Constraint c : constraintManager.getConstraints()){ +// if(c instanceof HardRouteConstraint){ +// constraints.add((HardRouteConstraint) c); +// } +// } +// return constraints; +// } +// +// @Override +// public void begin(VehicleRoute route) { +// this.route = route; +// examinedJobs.clear(); +//// violatedRouteConstraints.getHardRouteConstraints().clear(); +// } +// +// @Override +// public void visit(TourActivity activity) { +// //hard route constraints +// if(activity instanceof TourActivity.JobActivity){ +// Job job = ((TourActivity.JobActivity) activity).getJob(); +// if(!examinedJobs.contains(job.getId())){ +// examinedJobs.add(job.getId()); +// JobInsertionContext iContext = new JobInsertionContext(route,job,route.getVehicle(),route.getDriver(),route.getDepartureTime()); +// for(HardRouteConstraint hardRouteConstraint : hardRouteConstraints){ +// boolean fulfilled = hardRouteConstraint.fulfilled(iContext); +// if(!fulfilled) violatedRouteConstraints.getHardRouteConstraints().add(hardRouteConstraint); +// } +// } +// } +// +// } +// +// @Override +// public void finish() { +// stateManager.putRouteState(route,violated_route_constraints_id,violatedRouteConstraints); +// } +// } + private VehicleRoutingProblem vrp; private List routes; private StateManager stateManager; + private ConstraintManager constraintManager; + private DistanceCalculator distanceCalculator; private final StateId waiting_time_id; @@ -168,34 +270,134 @@ public class SolutionAnalyser { private final StateId distance_id; + private final StateId too_late_id; + +// private final StateId violated_constraint_id; + private ActivityTimeTracker.ActivityPolicy activityPolicy; - public SolutionAnalyser(VehicleRoutingProblem vrp, Collection routes, StateManager stateManager, DistanceCalculator distanceCalculator) { + private List hardRouteConstraints; + + private List hardActivityConstraints; + + private final VehicleRoutingProblemSolution working_solution; + +// private final VehicleRoutingProblemSolution original_solution; + + public SolutionAnalyser(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution, DistanceCalculator distanceCalculator) { this.vrp = vrp; - this.routes = new ArrayList(routes); - this.stateManager = stateManager; +// this.original_solution = VehicleRoutingProblemSolution.copyOf(solution); + this.working_solution = solution; + this.routes = new ArrayList(working_solution.getRoutes()); + this.stateManager = new StateManager(vrp); + this.stateManager.updateTimeWindowStates(); + this.stateManager.updateLoadStates(); + this.stateManager.updateSkillStates(); + this.constraintManager = new ConstraintManager(vrp,stateManager); this.distanceCalculator = distanceCalculator; waiting_time_id = stateManager.createStateId("waiting-time"); transport_time_id = stateManager.createStateId("transport-time"); service_time_id = stateManager.createStateId("service-time"); distance_id = stateManager.createStateId("distance"); - activityPolicy = ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_ARRIVED; - if(stateManager.timeWindowUpdateIsActivated()){ - activityPolicy = ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS; - } - stateManager.addStateUpdater(new SumUpWaitingTimes(waiting_time_id, transport_time_id, service_time_id, stateManager, activityPolicy)); + too_late_id = stateManager.createStateId("too-late"); +// violated_constraint_id = stateManager.createStateId("violated-constraints"); + activityPolicy = ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS; +// if(stateManager.timeWindowUpdateIsActivated()){ +// activityPolicy = ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS; +// } + stateManager.addStateUpdater(new SumUpWaitingTimes(waiting_time_id, transport_time_id, service_time_id,too_late_id , stateManager, activityPolicy)); stateManager.addStateUpdater(new DistanceUpdater(distance_id,stateManager,distanceCalculator)); +// hardRouteConstraints = getHardRouteConstraints(constraintManager); +// hardActivityConstraints = getHardActivityConstrains(constraintManager); refreshStates(); } +// private List getHardActivityConstrains(ConstraintManager constraintManager) { +// List constraints = new ArrayList(); +// for(Constraint c : constraintManager.getConstraints()){ +// if(c instanceof HardActivityConstraint){ +// constraints.add((HardActivityConstraint) c); +// } +// } +// return constraints; +// } + private void refreshStates(){ stateManager.clear(); stateManager.informInsertionStarts(routes,null); +// checkConstraintViolation(); } + +// private void checkConstraintViolation() { +// for(VehicleRoute route : routes){ +// Set unique = new HashSet(); +// Set examinedJobIds = new HashSet(); +// TourActivity actBeforePrevAct = route.getStart(); +// TourActivity prevAct = null; +// JobInsertionContext prevJobInsertionContext = null; +// for(TourActivity act : route.getActivities()){ +// if(prevAct == null){ +// prevAct = act; +// prevJobInsertionContext = createContext(route,act); +// continue; +// } +// //examine hard route constraints +// if(!examinedJobIds.contains(prevJobInsertionContext.getJob().getId())){ +// examinedJobIds.add(prevJobInsertionContext.getJob().getId()); +// for(HardRouteConstraint hardRouteConstraint : hardRouteConstraints){ +// boolean fulfilled = hardRouteConstraint.fulfilled(prevJobInsertionContext); +// if(!fulfilled) unique.add(hardRouteConstraint); +// } +// } +// +// //exmaine hard activity constraints +// examineActivityConstraints(prevJobInsertionContext, actBeforePrevAct, prevAct, act); +// +// actBeforePrevAct = prevAct; +// prevAct = act; +// prevJobInsertionContext = createContext(route,act); +// } +// examineActivityConstraints(prevJobInsertionContext,actBeforePrevAct,prevAct,route.getEnd()); +// +//// ViolatedRouteConstraints violatedRouteConstraints = new ViolatedRouteConstraints(); +//// violatedRouteConstraints.getHardRouteConstraints().addAll(unique); +//// stateManager.putRouteState(route, violated_constraint_id,violatedRouteConstraints); +// } +// } + +// private void examineActivityConstraints(JobInsertionContext prevJobInsertionContext, TourActivity actBeforePrevAct, TourActivity prevAct, TourActivity act) { +// ViolatedActivityConstraints violatedActivityConstraints = new ViolatedActivityConstraints(); +// for(HardActivityConstraint activityConstraint : hardActivityConstraints){ +// HardActivityConstraint.ConstraintsStatus status = +// activityConstraint.fulfilled(prevJobInsertionContext,actBeforePrevAct,prevAct,act,actBeforePrevAct.getEndTime()); +// if(!status.equals(HardActivityConstraint.ConstraintsStatus.FULFILLED)){ +// violatedActivityConstraints.getHardActivityConstraints().add(activityConstraint); +// } +// } +// stateManager.putActivityState(prevAct, violated_constraint_id,violatedActivityConstraints); +// } + +// private JobInsertionContext createContext(VehicleRoute route, TourActivity act) { +// if(act instanceof TourActivity.JobActivity){ +// return new JobInsertionContext(route,((TourActivity.JobActivity) act).getJob(),route.getVehicle(),route.getDriver(),route.getDepartureTime()); +// } +// throw new IllegalStateException("act not a job activity. this should not be currently"); +// } +// +// private List getHardRouteConstraints(ConstraintManager constraintManager) { +// List constraints = new ArrayList(); +// for(Constraint c : constraintManager.getConstraints()){ +// if(c instanceof HardRouteConstraint){ +// constraints.add((HardRouteConstraint) c); +// } +// } +// return constraints; +// } + // // // public void informRouteChanged(VehicleRoute route){ -//// update(route); +// update(route); // } // // @@ -234,7 +436,7 @@ public class SolutionAnalyser { public Capacity getLoadRightAfterActivity(TourActivity activity, VehicleRoute route){ if(activity instanceof Start) return getLoadAtBeginning(route); if(activity instanceof End) return getLoadAtEnd(route); - return stateManager.getActivityState(activity, InternalStates.LOAD,Capacity.class); + return stateManager.getActivityState(activity, InternalStates.LOAD, Capacity.class); } /** @@ -252,21 +454,88 @@ public class SolutionAnalyser { else if(afterAct != null) return afterAct; else return null; } -// -//// public Capacity getViolationAtBeginning(VehicleRoute route){ -//// Capacity atBeginning = getLoadAtBeginning(route); -//// return Capacity.max(Capacity.Builder.newInstance().build(),Capacity.subtract(atBeginning,route.getVehicle().getType().getCapacityDimensions())); -//// } -//// -//// public Capacity getViolationAtEnd(VehicleRoute route){ -//// Capacity atEnd = getLoadAtEnd(route); -//// return Capacity.max(Capacity.Builder.newInstance().build(),Capacity.subtract(atEnd,route.getVehicle().getType().getCapacityDimensions())); -//// } -//// -//// public Capacity getViolationRightAfterActivity(TourActivity activity, VehicleRoute route){ -//// Capacity afterAct = getLoadRightAfterActivity(activity); -//// return Capacity.max(Capacity.Builder.newInstance().build(),Capacity.subtract(afterAct,route.getVehicle().getType().getCapacityDimensions())); -//// } + + /** + * @param route to get the capacity violation from + * @return the capacity violation on this route, i.e. maxLoad - vehicleCapacity + */ + public Capacity getCapacityViolation(VehicleRoute route){ + Capacity maxLoad = getMaxLoad(route); + return Capacity.max(Capacity.Builder.newInstance().build(),Capacity.subtract(maxLoad,route.getVehicle().getType().getCapacityDimensions())); + } + + /** + * @param route to get the capacity violation from (at beginning of the route) + * @return violation, i.e. all dimensions and their corresponding violation. For example, if vehicle has two capacity + * dimension with dimIndex=0 and dimIndex=1 and dimIndex=1 is violated by 4 units then this method returns + * [[dimIndex=0][dimValue=0][dimIndex=1][dimValue=4]] + */ + public Capacity getCapacityViolationAtBeginning(VehicleRoute route){ + Capacity atBeginning = getLoadAtBeginning(route); + return Capacity.max(Capacity.Builder.newInstance().build(),Capacity.subtract(atBeginning,route.getVehicle().getType().getCapacityDimensions())); + } + + /** + * @param route to get the capacity violation from (at end of the route) + * @return violation, i.e. all dimensions and their corresponding violation. For example, if vehicle has two capacity + * dimension with dimIndex=0 and dimIndex=1 and dimIndex=1 is violated by 4 units then this method returns + * [[dimIndex=0][dimValue=0][dimIndex=1][dimValue=4]] + */ + public Capacity getCapacityViolationAtEnd(VehicleRoute route){ + Capacity atEnd = getLoadAtEnd(route); + return Capacity.max(Capacity.Builder.newInstance().build(),Capacity.subtract(atEnd,route.getVehicle().getType().getCapacityDimensions())); + } + + + /** + * @param route to get the capacity violation from (at activity of the route) + * @return violation, i.e. all dimensions and their corresponding violation. For example, if vehicle has two capacity + * dimension with dimIndex=0 and dimIndex=1 and dimIndex=1 is violated by 4 units then this method returns + * [[dimIndex=0][dimValue=0][dimIndex=1][dimValue=4]] + */ + public Capacity getCapacityViolationAfterActivity(TourActivity activity, VehicleRoute route){ + Capacity afterAct = getLoadRightAfterActivity(activity,route); + return Capacity.max(Capacity.Builder.newInstance().build(),Capacity.subtract(afterAct,route.getVehicle().getType().getCapacityDimensions())); + } + + /** + * @param route to get the time window violation from + * @return time violation of route, i.e. sum of individual activity time window violations. + */ + public Double getTimeWindowViolation(VehicleRoute route){ + return stateManager.getRouteState(route,too_late_id,Double.class); + } + + /** + * @param activity to get the time window violation from + * @param route where activity needs to be part of + * @return time violation of activity + */ + public Double getTimeWindowViolationAtActivity(TourActivity activity, VehicleRoute route){ + return Math.max(0,activity.getArrTime()-activity.getTheoreticalLatestOperationStartTime()); + } + + public Boolean skillConstraintIsViolated(VehicleRoute route){ + return null; + } + + public Boolean skillConstraintIsViolatedAtActivity(TourActivity activity, VehicleRoute route){ + return null; + } + + public Boolean backhaulConstraintIsViolated(VehicleRoute route){ + return null; + } + + public Boolean shipmentConstraintIsViolated(VehicleRoute route){ + return null; + } + + public Boolean shipmentConstraintIsViolatedAtActivity(TourActivity activity, VehicleRoute route){ + return null; + } + + /** * @param route to get the total operation time from @@ -301,8 +570,56 @@ public class SolutionAnalyser { return stateManager.getRouteState(route, service_time_id, Double.class); } + /** + * @param route to get the transport costs from + * @return total variable transport costs of route, i.e. sum of transport costs specified by + * vrp.getTransportCosts().getTransportCost(fromId,toId,...) + */ + public Double getVariableTransportCosts(VehicleRoute route){ + return stateManager.getRouteState(route,InternalStates.COSTS,Double.class); + } + + /** + * @param route to get the fixed costs from + * @return fixed costs of route, i.e. fixed costs of employed vehicle on this route. + */ + public Double getFixedCosts(VehicleRoute route){ + return route.getVehicle().getType().getVehicleCostParams().fix; + } + +// public ViolatedRouteConstraints getViolatedHardConstraints(VehicleRoute route){ +// return stateManager.getRouteState(route, violated_constraint_id,ViolatedRouteConstraints.class); +// } + +// public Map getViolatedSoftConstraints(VehicleRoute route){ +// return null; +// } + +// public ViolatedActivityConstraints getViolatedHardConstraintsAtActivity(TourActivity activity, VehicleRoute route){ +// if(activity instanceof Start) return new ViolatedActivityConstraints(); +// if(activity instanceof End) return new ViolatedActivityConstraints(); +// return stateManager.getActivityState(activity,violated_constraint_id,ViolatedActivityConstraints.class); +// } + +// public Map getViolatedSoftConstraint(VehicleRoute route){ +// return null; +// } + + /** + * @param activity to get the variable transport costs from + * @param route where the activity should be part of + * @return variable transport costs at activity, i.e. sum of transport costs from start of route to the specified activity + * If activity is start, it returns 0.. If it is end, it returns .getVariableTransportCosts(route). + */ + public Double getVariableTransportCostsAtActivity(TourActivity activity, VehicleRoute route){ + if(activity instanceof Start) return 0.; + if(activity instanceof End) return getVariableTransportCosts(route); + return stateManager.getActivityState(activity,InternalStates.COSTS,Double.class); + } + /** * @param activity to get the waiting from + * @param route where activity should be part of * @return waiting time at activity */ public Double getWaitingTimeAtActivity(TourActivity activity, VehicleRoute route){ @@ -312,11 +629,27 @@ public class SolutionAnalyser { } return waitingTime; } -// -// public double getTimeTooLateAtActivity(TourActivity activity){ -// -// } -// + + /** + * @param activity to get the late arrival times from + * @return time too late + */ + public Double getLateArrivalTimesAtActivity(TourActivity activity, VehicleRoute route){ + double tooLate = 0.; + if(activityPolicy.equals(ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS)){ + tooLate = Math.max(0,activity.getArrTime()-activity.getTheoreticalLatestOperationStartTime()); + } + return tooLate; + } + + /** + * @param route to get the late arrival times from + * @return time too late, i.e. sum of late time of activities + */ + public Double getLateArrivalTimes(VehicleRoute route){ + return stateManager.getRouteState(route,too_late_id,Double.class); + } + /** * @param route to get the distance from * @return total distance of route @@ -329,13 +662,15 @@ public class SolutionAnalyser { * @param activity at which is distance of the current route is measured * @return distance at activity */ - public double getDistanceAtActivity(TourActivity activity, VehicleRoute route){ + public Double getDistanceAtActivity(TourActivity activity, VehicleRoute route){ if(activity instanceof Start) return 0.; if(activity instanceof End) return getDistance(route); return stateManager.getActivityState(activity, distance_id, Double.class); } -// + + + // /** // * @return total distance // */ diff --git a/jsprit-core/src/main/java/jsprit/core/util/CrowFlyCosts.java b/jsprit-core/src/main/java/jsprit/core/util/CrowFlyCosts.java index f3ba857c..074a4095 100644 --- a/jsprit-core/src/main/java/jsprit/core/util/CrowFlyCosts.java +++ b/jsprit-core/src/main/java/jsprit/core/util/CrowFlyCosts.java @@ -1,16 +1,16 @@ /******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * + * Copyright (C) 2014 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 + * 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 . ******************************************************************************/ @@ -72,8 +72,7 @@ public class CrowFlyCosts extends AbstractForwardVehicleRoutingTransportCosts { } catch (NullPointerException e) { throw new NullPointerException("cannot calculate euclidean distance. coordinates are missing. either add coordinates or use another transport-cost-calculator."); } - double transportTime = distance / speed; - return transportTime; + return distance / speed; } } diff --git a/jsprit-core/src/main/java/jsprit/core/util/ManhattanCosts.java b/jsprit-core/src/main/java/jsprit/core/util/ManhattanCosts.java index 2229b61a..4af99018 100644 --- a/jsprit-core/src/main/java/jsprit/core/util/ManhattanCosts.java +++ b/jsprit-core/src/main/java/jsprit/core/util/ManhattanCosts.java @@ -1,16 +1,16 @@ /******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * + * Copyright (C) 2014 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 + * 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 . ******************************************************************************/ @@ -41,21 +41,29 @@ public class ManhattanCosts extends AbstractForwardVehicleRoutingTransportCosts @Override public double getTransportCost(String fromId, String toId, double time,Driver driver, Vehicle vehicle) { - return calculateDistance(fromId, toId); + double distance; + try { + distance = calculateDistance(fromId, toId); + } catch (NullPointerException e) { + throw new NullPointerException("cannot calculate euclidean distance. coordinates are missing. either add coordinates or use another transport-cost-calculator."); + } + double costs = distance; + if(vehicle != null){ + if(vehicle.getType() != null){ + costs = distance * vehicle.getType().getVehicleCostParams().perDistanceUnit; + } + } + return costs; } @Override public double getTransportTime(String fromId, String toId, double time,Driver driver, Vehicle vehicle) { - double transportTime = calculateDistance(fromId, toId) / speed; - return transportTime; + return calculateDistance(fromId, toId) / speed; } private double calculateDistance(String fromId, String toId) { - double distance = Math.abs(locations.getCoord(fromId).getX() - - locations.getCoord(toId).getX()) - + Math.abs(locations.getCoord(fromId).getY() - - locations.getCoord(toId).getY()); - return distance; + return Math.abs(locations.getCoord(fromId).getX() - locations.getCoord(toId).getX()) + + Math.abs(locations.getCoord(fromId).getY() - locations.getCoord(toId).getY()); } } diff --git a/jsprit-core/src/test/java/jsprit/core/analysis/SolutionAnalyserTest.java b/jsprit-core/src/test/java/jsprit/core/analysis/SolutionAnalyserTest.java index 89a806e2..c0832588 100644 --- a/jsprit-core/src/test/java/jsprit/core/analysis/SolutionAnalyserTest.java +++ b/jsprit-core/src/test/java/jsprit/core/analysis/SolutionAnalyserTest.java @@ -21,16 +21,21 @@ package jsprit.core.analysis; import jsprit.core.algorithm.VehicleRoutingAlgorithm; import jsprit.core.algorithm.VehicleRoutingAlgorithmBuilder; import jsprit.core.algorithm.state.StateManager; +import jsprit.core.problem.Capacity; import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.constraint.ConstraintManager; +import jsprit.core.problem.job.Delivery; +import jsprit.core.problem.job.Pickup; 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.TimeWindow; +import jsprit.core.problem.solution.route.activity.TourActivity; import jsprit.core.problem.vehicle.VehicleImpl; import jsprit.core.problem.vehicle.VehicleType; import jsprit.core.problem.vehicle.VehicleTypeImpl; +import jsprit.core.reporting.SolutionPrinter; import jsprit.core.util.Coordinate; import jsprit.core.util.ManhattanCosts; import jsprit.core.util.Solutions; @@ -40,7 +45,7 @@ import org.junit.Test; import java.util.Iterator; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.*; public class SolutionAnalyserTest { @@ -50,12 +55,14 @@ public class SolutionAnalyserTest { private StateManager stateManager; + private ConstraintManager constraintManager; + private SolutionAnalyser.DistanceCalculator distanceCalculator; @Before public void doBefore(){ - VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0,15).build(); + VehicleType type = VehicleTypeImpl.Builder.newInstance("type").setFixedCost(100.).setCostPerDistance(2.).addCapacityDimension(0, 15).build(); VehicleImpl vehicle = VehicleImpl.Builder.newInstance("v1").setType(type) .setStartLocationCoordinate(Coordinate.newInstance(-5, 0)).build(); @@ -79,7 +86,9 @@ public class SolutionAnalyserTest { .setPickupServiceTime(20.).setDeliveryServiceTime(20.) .setDeliveryCoord(Coordinate.newInstance(16, 5)).addSizeDimension(0,10).build(); - VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance().addVehicle(vehicle).addVehicle(vehicle2).addJob(s1) + VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance().addVehicle(vehicle) + .addVehicle(vehicle2) + .addJob(s1) .addJob(s2).addJob(shipment1).addJob(s3).addJob(s4).addJob(shipment2).setFleetSize(VehicleRoutingProblem.FleetSize.FINITE); vrpBuilder.setRoutingCost(new ManhattanCosts(vrpBuilder.getLocations())); vrp = vrpBuilder.build(); @@ -88,7 +97,8 @@ public class SolutionAnalyserTest { vraBuilder.addDefaultCostCalculators(); vraBuilder.addCoreConstraints(); stateManager = new StateManager(vrp); - ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager); + stateManager.updateLoadStates(); + constraintManager = new ConstraintManager(vrp,stateManager); vraBuilder.setStateAndConstraintManager(stateManager,constraintManager); VehicleRoutingAlgorithm vra = vraBuilder.build(); @@ -99,7 +109,7 @@ public class SolutionAnalyserTest { @Test public void constructionShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -110,7 +120,7 @@ public class SolutionAnalyserTest { @Test public void loadAtBeginningOfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -122,7 +132,7 @@ public class SolutionAnalyserTest { @Test public void loadAtBeginningOfRoute2ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -137,7 +147,7 @@ public class SolutionAnalyserTest { @Test public void loadAtEnd_OfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -149,7 +159,7 @@ public class SolutionAnalyserTest { @Test public void loadAtEnd_OfRoute2ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -164,7 +174,7 @@ public class SolutionAnalyserTest { @Test public void loadAfterActivity_ofStartActOfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -176,7 +186,7 @@ public class SolutionAnalyserTest { @Test public void loadAfterActivity_ofAct1ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -188,7 +198,7 @@ public class SolutionAnalyserTest { @Test public void loadAfterActivity_ofAct2ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -200,7 +210,7 @@ public class SolutionAnalyserTest { @Test public void loadAfterActivity_ofAct3ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -212,7 +222,7 @@ public class SolutionAnalyserTest { @Test public void loadAfterActivity_ofAct4ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -224,7 +234,7 @@ public class SolutionAnalyserTest { @Test public void loadAfterActivity_ofEndActOfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -251,7 +261,7 @@ public class SolutionAnalyserTest { @Test public void loadBeforeActivity_ofStartActOfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -263,7 +273,7 @@ public class SolutionAnalyserTest { @Test public void loadBeforeActivity_ofAct1ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -275,7 +285,7 @@ public class SolutionAnalyserTest { @Test public void loadBeforeActivity_ofAct2ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -287,7 +297,7 @@ public class SolutionAnalyserTest { @Test public void loadBeforeActivity_ofAct3ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -299,7 +309,7 @@ public class SolutionAnalyserTest { @Test public void loadBeforeActivity_ofAct4ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -311,7 +321,7 @@ public class SolutionAnalyserTest { @Test public void loadBeforeActivity_ofEndActOfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -323,7 +333,7 @@ public class SolutionAnalyserTest { @Test public void maxLoad_OfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -335,7 +345,7 @@ public class SolutionAnalyserTest { @Test public void operationTime_OfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -347,7 +357,7 @@ public class SolutionAnalyserTest { @Test public void waitingTime_OfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -359,7 +369,7 @@ public class SolutionAnalyserTest { @Test public void transportTime_OfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -371,7 +381,7 @@ public class SolutionAnalyserTest { @Test public void serviceTime_OfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -383,7 +393,7 @@ public class SolutionAnalyserTest { @Test public void distance_OfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -395,7 +405,7 @@ public class SolutionAnalyserTest { @Test public void waitingTime_atStartActOfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -407,7 +417,7 @@ public class SolutionAnalyserTest { @Test public void waitingTime_ofAct1ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -419,7 +429,7 @@ public class SolutionAnalyserTest { @Test public void waitingTime_ofAct2ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -431,7 +441,7 @@ public class SolutionAnalyserTest { @Test public void waitingTime_ofAct3ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -443,7 +453,7 @@ public class SolutionAnalyserTest { @Test public void waitingTime_ofAct4ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -455,7 +465,7 @@ public class SolutionAnalyserTest { @Test public void waitingTime_ofEndActOfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -467,7 +477,7 @@ public class SolutionAnalyserTest { @Test public void distance_atStartActOfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -479,7 +489,7 @@ public class SolutionAnalyserTest { @Test public void distance_ofAct1ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -491,7 +501,7 @@ public class SolutionAnalyserTest { @Test public void distance_ofAct2ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -503,7 +513,7 @@ public class SolutionAnalyserTest { @Test public void distance_ofAct3ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -515,7 +525,7 @@ public class SolutionAnalyserTest { @Test public void distance_ofAct4ofRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -527,7 +537,7 @@ public class SolutionAnalyserTest { @Test public void distance_ofEndActOfRoute1ShouldWork(){ - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager,new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); @@ -537,11 +547,642 @@ public class SolutionAnalyserTest { Assert.assertEquals(42., analyser.getDistanceAtActivity(route.getEnd(), route), 0.01); } + + @Test public void whatHappensWhenUserSpecifiedOwnEndTime_stateManagerShouldNotOverwriteThis(){ assertFalse(true); } + @Test + public void lateArrivalTimes_atStartActOfRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(0, analyser.getLateArrivalTimesAtActivity(route.getStart(), route), 0.01); + } + @Test + public void lateArrivalTimes_ofAct1ofRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(0., analyser.getLateArrivalTimesAtActivity(route.getActivities().get(0), route), 0.01); + } + + @Test + public void lateArrivalTimes_ofAct2ofRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(0., analyser.getLateArrivalTimesAtActivity(route.getActivities().get(1), route), 0.01); + } + + @Test + public void lateArrivalTimes_ofAct3ofRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(0., analyser.getLateArrivalTimesAtActivity(route.getActivities().get(2), route), 0.01); + } + + @Test + public void lateArrivalTimes_ofAct4ofRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(0., analyser.getLateArrivalTimesAtActivity(route.getActivities().get(3), route), 0.01); + } + + @Test + public void lateArrivalTimes_ofEndActOfRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(0., analyser.getLateArrivalTimesAtActivity(route.getEnd(), route), 0.01); + } + + @Test + public void lateArrTimes_OfRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(0., analyser.getLateArrivalTimes(route), 0.01); + } + + @Test + public void variableTransportCosts_OfRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(84., analyser.getVariableTransportCosts(route), 0.01); + } + + @Test + public void fixedCosts_OfRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(100., analyser.getFixedCosts(route), 0.01); + } + + @Test + public void transportCosts_atStartActOfRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(0, analyser.getVariableTransportCostsAtActivity(route.getStart(), route), 0.01); + } + + @Test + public void transportCosts_ofAct1ofRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(6.*2., analyser.getVariableTransportCostsAtActivity(route.getActivities().get(0), route), 0.01); + } + + @Test + public void transportCosts_ofAct2ofRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(12.*2., analyser.getVariableTransportCostsAtActivity(route.getActivities().get(1), route), 0.01); + } + + @Test + public void transportCosts_ofAct3ofRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(16.*2., analyser.getVariableTransportCostsAtActivity(route.getActivities().get(2), route), 0.01); + } + + @Test + public void transportCosts_ofAct4ofRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(27.*2., analyser.getVariableTransportCostsAtActivity(route.getActivities().get(3), route), 0.01); + } + + @Test + public void transportCosts_ofEndActOfRoute1ShouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Assert.assertEquals(42.*2., analyser.getVariableTransportCostsAtActivity(route.getEnd(), route), 0.01); + } + + @Test + public void whatShouldHappenIf_Route_or_Activity_isEmpty_or_notPartOfRoute(){ + assertFalse(true); + } + + @Test + public void capacityViolationAtBeginning_shouldWork(){ + SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { + @Override + public double getDistance(String fromLocationId, String toLocationId) { + return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); + } + }); + VehicleRoute route = solution.getRoutes().iterator().next(); + Capacity atBeginning = analyser.getCapacityViolationAtBeginning(route); + for(int i=0;i violatedConstraints = analyser.getViolatedHardConstraints(route).getHardRouteConstraints(); +//// Assert.assertEquals(2,violatedConstraints.size()); +// for(HardRouteConstraint c : violatedConstraints) System.out.println("violated: " + c.getClass().toString()); +// } +// +// @Test +// public void violatedActivityConstraint_shouldWorkForAct1(){ +// buildAnotherScenarioWithOnlyOneVehicleAndWithoutAnyConstraintsBefore(); +// +// SolutionPrinter.print(vrp,solution, SolutionPrinter.Print.VERBOSE); +// +// simulateTW_and_LoadConstraint(); +// +// SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution, new SolutionAnalyser.DistanceCalculator() { +// @Override +// public double getDistance(String fromLocationId, String toLocationId) { +// return vrp.getTransportCosts().getTransportCost(fromLocationId,toLocationId,0.,null,null); +// } +// }); +// +// VehicleRoute route = solution.getRoutes().iterator().next(); +// List violatedConstraints = analyser.getViolatedHardConstraintsAtActivity(route.getActivities().get(0),route).getHardActivityConstraints(); +//// Assert.assertEquals(2,violatedConstraints.size()); +// for(HardActivityConstraint c : violatedConstraints) System.out.println("violated: " + c.getClass().toString()); +// } } diff --git a/jsprit-examples/src/main/java/jsprit/examples/SimpleExample.java b/jsprit-examples/src/main/java/jsprit/examples/SimpleExample.java index fbb99d67..650f5145 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/SimpleExample.java +++ b/jsprit-examples/src/main/java/jsprit/examples/SimpleExample.java @@ -80,7 +80,7 @@ public class SimpleExample { VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); vrpBuilder.addVehicle(vehicle); vrpBuilder.addJob(service1).addJob(service2).addJob(service3).addJob(service4); - + VehicleRoutingProblem problem = vrpBuilder.build(); /* diff --git a/jsprit-examples/src/main/java/jsprit/examples/VRPWithBackhaulsExample2.java b/jsprit-examples/src/main/java/jsprit/examples/VRPWithBackhaulsExample2.java index caf1f3b4..0d86ec06 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/VRPWithBackhaulsExample2.java +++ b/jsprit-examples/src/main/java/jsprit/examples/VRPWithBackhaulsExample2.java @@ -16,8 +16,6 @@ ******************************************************************************/ package jsprit.examples; -import jsprit.analysis.toolbox.Plotter; -import jsprit.analysis.toolbox.Plotter.Label; import jsprit.core.algorithm.VehicleRoutingAlgorithm; import jsprit.core.algorithm.VehicleRoutingAlgorithmBuilder; import jsprit.core.algorithm.selector.SelectBest; @@ -63,7 +61,7 @@ public class VRPWithBackhaulsExample2 { */ final VehicleRoutingProblem vrp = vrpBuilder.build(); - new Plotter(vrp).plot("output/vrpwbh_christophides_vrpnc1.png", "pd_vrpnc1"); +// new Plotter(vrp).plot("output/vrpwbh_christophides_vrpnc1.png", "pd_vrpnc1"); /* @@ -84,6 +82,8 @@ public class VRPWithBackhaulsExample2 { vraBuilder.setStateAndConstraintManager(stateManager,constraintManager); VehicleRoutingAlgorithm vra = vraBuilder.build(); + + /* * Solve the problem. * @@ -105,11 +105,11 @@ public class VRPWithBackhaulsExample2 { * Plot solution. */ // SolutionPlotter.plotSolutionAsPNG(vrp, solution, "output/pd_solomon_r101_solution.png","pd_r101"); - Plotter plotter = new Plotter(vrp, solution); - plotter.setLabel(Label.SIZE); - plotter.plot("output/vrpwbh_christophides_vrpnc1_solution.png","vrpwbh_vrpnc1"); +// Plotter plotter = new Plotter(vrp, solution); +// plotter.setLabel(Label.SIZE); +// plotter.plot("output/vrpwbh_christophides_vrpnc1_solution.png","vrpwbh_vrpnc1"); - SolutionAnalyser analyser = new SolutionAnalyser(vrp,solution.getRoutes(),stateManager, new SolutionAnalyser.DistanceCalculator() { + SolutionAnalyser analyser = new SolutionAnalyser(vrp, solution, new SolutionAnalyser.DistanceCalculator() { @Override public double getDistance(String fromLocationId, String toLocationId) { @@ -129,6 +129,12 @@ public class VRPWithBackhaulsExample2 { System.out.println("operationTime: " + analyser.getOperationTime(route)); System.out.println("serviceTime: " + analyser.getServiceTime(route)); System.out.println("transportTime: " + analyser.getTransportTime(route)); + System.out.println("lateArrival: " + analyser.getLateArrivalTimes(route)); + System.out.println("transportCosts: " + analyser.getVariableTransportCosts(route)); + System.out.println("fixedCosts: " + analyser.getFixedCosts(route)); + System.out.println("capViolationOnRoute: " + analyser.getCapacityViolation(route)); + System.out.println("capViolation@beginning: " + analyser.getCapacityViolationAtBeginning(route)); + System.out.println("capViolation@end: " + analyser.getCapacityViolationAtEnd(route)); System.out.println("dist@" + route.getStart().getLocationId() + ": " + analyser.getDistanceAtActivity(route.getStart(),route)); for(TourActivity act : route.getActivities()){ @@ -137,6 +143,9 @@ public class VRPWithBackhaulsExample2 { System.out.println("dist@" + act.getLocationId() + ": " + analyser.getDistanceAtActivity(act,route)); System.out.println("load(before)@" + act.getLocationId() + ": " + analyser.getLoadJustBeforeActivity(act,route)); System.out.println("load(after)@" + act.getLocationId() + ": " + analyser.getLoadRightAfterActivity(act, route)); + System.out.println("tooLate@" + act.getLocationId() + ": " + analyser.getLateArrivalTimesAtActivity(act, route)); + System.out.println("transportCosts@" + act.getLocationId() + ": " + analyser.getVariableTransportCostsAtActivity(act,route)); + System.out.println("capViolation(after)@" + act.getLocationId() + ": " + analyser.getCapacityViolationAfterActivity(act,route)); } System.out.println("--"); System.out.println("dist@" + route.getEnd().getLocationId() + ": " + analyser.getDistanceAtActivity(route.getEnd(),route));