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

Merge remote-tracking branch 'choose_remote_name/vrpWithBackhauls'

Conflicts:
	jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java
This commit is contained in:
Stefan Schroeder 2013-09-02 19:01:32 +02:00
commit f1bb6c7bd0
96 changed files with 17748 additions and 1121 deletions

View file

@ -52,6 +52,8 @@
<version>2.4.0</version>
</dependency>
</dependencies>

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.ArrayList;
@ -49,4 +69,8 @@ class BackwardInTimeListeners {
for(BackwardInTimeListener l : listeners){ l.end(start, latestDepartureTime); }
}
public boolean isEmpty() {
return listeners.isEmpty();
}
}

View file

@ -1,14 +1,38 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import basics.route.TourActivity;
class CalcUtils {
static double getStartTimeAtAct(double startTimeAtPrevAct, double tpTime_prevAct_nextAct, TourActivity nextAct){
return Math.max(startTimeAtPrevAct + tpTime_prevAct_nextAct, nextAct.getTheoreticalEarliestOperationStartTime()) + nextAct.getOperationTime();
}
static double getStartTimeAtAct(double nextActArrTime, TourActivity nextAct){
return Math.max(nextActArrTime, nextAct.getTheoreticalEarliestOperationStartTime()) + nextAct.getOperationTime();
/**
* Calculates actEndTime assuming that activity can at earliest start at act.getTheoreticalEarliestOperationStartTime().
*
* @param actArrTime
* @param act
* @return
*/
static double getActivityEndTime(double actArrTime, TourActivity act){
return Math.max(actArrTime, act.getTheoreticalEarliestOperationStartTime()) + act.getOperationTime();
}
}

View file

@ -25,6 +25,8 @@ import basics.route.End;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.TourActivityFactory;
import basics.route.DefaultTourActivityFactory;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
@ -49,6 +51,8 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
private VehicleRoutingTransportCosts transportCosts;
private TourActivityFactory activityFactory;
public void setNeighborhood(Neighborhood neighborhood) {
this.neighborhood = neighborhood;
logger.info("initialise neighborhood " + neighborhood);
@ -59,6 +63,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
this.marginalCalculus = marginalsCalculus;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.transportCosts = routingCosts;
activityFactory = new DefaultTourActivityFactory();
logger.info("initialise " + this);
}
@ -86,7 +91,8 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
Marginals bestMarginals = null;
Service service = (Service)jobToInsert;
int insertionIndex = InsertionData.NO_INDEX;
TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service);
TourActivity deliveryAct2Insert = activityFactory.createActivity(service);
Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
@ -96,11 +102,9 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
TourActivity prevAct = start;
double prevActStartTime = newVehicleDepartureTime;
int actIndex = 0;
// logger.info("start");
for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){
if(deliveryAct2Insert.getTheoreticalLatestOperationStartTime() < prevAct.getTheoreticalEarliestOperationStartTime()){
break;
}
// logger.info("prevActStartTime="+prevActStartTime);
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
Marginals mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc != null){
@ -111,10 +115,16 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
}
}
}
prevActStartTime = CalcUtils.getStartTimeAtAct(prevActStartTime, transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle), nextAct);
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle);
double nextActEndTime = CalcUtils.getActivityEndTime(nextActArrTime, nextAct);
prevActStartTime = nextActEndTime;
prevAct = nextAct;
actIndex++;
}
// logger.info("prevActStartTime="+prevActStartTime);
End nextAct = end;
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
Marginals mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);

View file

@ -23,21 +23,21 @@ import java.util.PriorityQueue;
import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.RouteStates.ActivityState;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DefaultTourActivityFactory;
import basics.route.Driver;
import basics.route.End;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.TourActivityFactory;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
@ -51,6 +51,8 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
private TourActivityFactory tourActivityFactory = new DefaultTourActivityFactory();
private StateManager states;
private int nuOfActsForwardLooking = 0;
@ -70,7 +72,9 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
};
public void setTourActivityFactory(TourActivityFactory tourActivityFactory){
this.tourActivityFactory=tourActivityFactory;
}
public void setNeighborhood(Neighborhood neighborhood) {
this.neighborhood = neighborhood;
@ -142,7 +146,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
/**
* some inis
*/
TourActivity serviceAct2Insert = ServiceActivity.newInstance(service);
TourActivity serviceAct2Insert = tourActivityFactory.createActivity(service);
int best_insertion_index = InsertionData.NO_INDEX;
initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);

View file

@ -23,6 +23,7 @@ package algorithms;
import java.util.ArrayList;
import java.util.List;
import algorithms.HardConstraints.ConstraintManager;
import basics.VehicleRoutingProblem;
import basics.algo.InsertionListener;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
@ -81,6 +82,8 @@ class CalculatorBuilder {
private double timeSlice;
private int neighbors;
private ConstraintManager constraintManager;
/**
* Constructs the builder.
@ -213,9 +216,11 @@ class CalculatorBuilder {
}
}
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager activityStates2){
MarginalsCalculus defaultCalc = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), new HardConstraints.HardTimeWindowConstraint(activityStates2) );
JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), defaultCalc, new HardConstraints.HardLoadConstraint(activityStates2));
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager statesManager){
if(constraintManager == null) throw new IllegalStateException("constraint-manager is null");
MarginalsCalculus defaultCalc = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager);
JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), defaultCalc, constraintManager);
((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
@ -246,6 +251,10 @@ class CalculatorBuilder {
return new CalculatesVehTypeDepServiceInsertion(fleetManager, baseCalc);
}
public void setConstraintManager(ConstraintManager constraintManager) {
this.constraintManager = constraintManager;
}
}

View file

@ -21,17 +21,15 @@
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.log4j.Logger;
import algorithms.VehicleFleetManager.TypeKey;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
@ -47,13 +45,13 @@ final class FindCheaperVehicleAlgo {
private double weightFixCosts = 1.0;
private RouteStates states;
private StateManager states;
public void setWeightFixCosts(double weightFixCosts) {
this.weightFixCosts = weightFixCosts;
}
public void setStates(RouteStates states) {
public void setStates(StateManager states) {
this.states = states;
}
@ -85,11 +83,11 @@ final class FindCheaperVehicleAlgo {
if(vehicle.getType().getTypeId().equals(vehicleRoute.getVehicle().getType().getTypeId())){
continue;
}
if(states.getRouteState(vehicleRoute).getLoad() <= vehicle.getCapacity()){
if(states.getRouteState(vehicleRoute,StateTypes.LOAD).toDouble() <= vehicle.getCapacity()){
double fixCostSaving = vehicleRoute.getVehicle().getType().getVehicleCostParams().fix - vehicle.getType().getVehicleCostParams().fix;
double departureTime = vehicleRoute.getStart().getEndTime();
double newCost = auxilliaryCostCalculator.costOfPath(path, departureTime, vehicleRoute.getDriver(), vehicle);
double varCostSaving = states.getRouteState(vehicleRoute).getCosts() - newCost;
double varCostSaving = states.getRouteState(vehicleRoute, StateTypes.COSTS).toDouble() - newCost;
double totalCostSaving = varCostSaving + weightFixCosts*fixCostSaving;
if(totalCostSaving > bestSaving){
bestSaving = totalCostSaving;

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.ArrayList;
@ -38,4 +58,8 @@ class ForwardInTimeListeners {
for(ForwardInTimeListener l : listeners){ l.end(end, arrivalTime); }
}
public boolean isEmpty() {
return listeners.isEmpty();
}
}

View file

@ -32,9 +32,11 @@ import java.util.Set;
import org.apache.log4j.Logger;
import util.RandomNumberGeneration;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionListener;
import basics.algo.SearchStrategyModule;
import basics.algo.SearchStrategyModuleListener;
import basics.route.TourActivity;
@ -53,8 +55,6 @@ final class Gendreau implements SearchStrategyModule{
private final InsertionStrategy insertionStrategy;
private final Inserter inserter;
private VehicleFleetManager fleetManager;
private Random random = RandomNumberGeneration.getRandom();
@ -71,7 +71,7 @@ final class Gendreau implements SearchStrategyModule{
super();
InsertionListeners insertionListeners = new InsertionListeners();
insertionListeners.addAllListeners(insertionStrategy.getListeners());
inserter = new Inserter(insertionListeners);
new Inserter(insertionListeners);
this.ruin = ruin;
this.vrp = vrp;
this.insertionStrategy = insertionStrategy;
@ -205,7 +205,18 @@ final class Gendreau implements SearchStrategyModule{
@Override
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
// TODO Auto-generated method stub
if(moduleListener instanceof InsertionListener){
InsertionListener iListener = (InsertionListener) moduleListener;
if(!insertionStrategy.getListeners().contains(iListener)){
insertionStrategy.addListener(iListener);
}
}
if(moduleListener instanceof RuinListener){
RuinListener rListener = (RuinListener) moduleListener;
if(!ruin.getListeners().contains(rListener)){
ruin.addListener(rListener);
}
}
}
}

View file

@ -1,8 +1,54 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import basics.Delivery;
import basics.Pickup;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DeliveryActivity;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TourActivity;
/**
* collection of hard constrainters bot at activity and at route level.
*
* <p>HardPickupAndDeliveryLoadConstraint requires LOAD_AT_DEPOT and LOAD (i.e. load at end) at route-level
*
* <p>HardTimeWindowConstraint requires LATEST_OPERATION_START_TIME
*
* <p>HardPickupAndDeliveryConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level
*
* <p>HardPickupAndDeliveryBackhaulConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level
*
* @author stefan
*
*/
class HardConstraints {
interface HardRouteLevelConstraint {
@ -13,10 +59,76 @@ class HardConstraints {
interface HardActivityLevelConstraint {
public boolean fulfilled(InsertionContext iFacts, TourActivity act, double arrTime);
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime);
}
static class HardRouteLevelConstraintManager implements HardRouteLevelConstraint {
private Collection<HardRouteLevelConstraint> hardConstraints = new ArrayList<HardRouteLevelConstraint>();
public void addConstraint(HardRouteLevelConstraint constraint){
hardConstraints.add(constraint);
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
for(HardRouteLevelConstraint constraint : hardConstraints){
if(!constraint.fulfilled(insertionContext)){
return false;
}
}
return true;
}
}
static class ConstraintManager implements HardActivityLevelConstraint, HardRouteLevelConstraint{
private HardActivityLevelConstraintManager actLevelConstraintManager = new HardActivityLevelConstraintManager();
private HardRouteLevelConstraintManager routeLevelConstraintManager = new HardRouteLevelConstraintManager();
public void addConstraint(HardActivityLevelConstraint actLevelConstraint){
actLevelConstraintManager.addConstraint(actLevelConstraint);
}
public void addConstraint(HardRouteLevelConstraint routeLevelConstraint){
routeLevelConstraintManager.addConstraint(routeLevelConstraint);
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
return routeLevelConstraintManager.fulfilled(insertionContext);
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
return actLevelConstraintManager.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
}
}
static class HardActivityLevelConstraintManager implements HardActivityLevelConstraint {
private Collection<HardActivityLevelConstraint> hardConstraints = new ArrayList<HardActivityLevelConstraint>();
public void addConstraint(HardActivityLevelConstraint constraint){
hardConstraints.add(constraint);
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
for(HardActivityLevelConstraint constraint : hardConstraints){
if(!constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime)){
return false;
}
}
return true;
}
}
static class HardLoadConstraint implements HardRouteLevelConstraint{
private StateManager states;
@ -37,23 +149,163 @@ class HardConstraints {
}
}
static class HardTimeWindowConstraint implements HardActivityLevelConstraint {
/**
* lsjdfjsdlfjsa
*
* @author stefan
*
*/
static class HardPickupAndDeliveryLoadConstraint implements HardRouteLevelConstraint {
private StateManager states;
private StateManager stateManager;
public HardTimeWindowConstraint(StateManager states) {
public HardPickupAndDeliveryLoadConstraint(StateManager stateManager) {
super();
this.states = states;
this.stateManager = stateManager;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity act, double arrTime) {
if(arrTime > states.getActivityState(act, StateTypes.LATEST_OPERATION_START_TIME).toDouble()){
return false;
public boolean fulfilled(InsertionContext insertionContext) {
if(insertionContext.getJob() instanceof Delivery){
int loadAtDepot = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
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(), StateTypes.LOAD).toDouble();
if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}
/**
* ljsljslfjs
* @author stefan
*
*/
public static class HardTimeWindowActivityLevelConstraint implements HardActivityLevelConstraint {
private static Logger log = Logger.getLogger(HardTimeWindowActivityLevelConstraint.class);
private StateManager states;
private VehicleRoutingTransportCosts routingCosts;
public HardTimeWindowActivityLevelConstraint(StateManager states, VehicleRoutingTransportCosts routingCosts) {
super();
this.states = states;
this.routingCosts = routingCosts;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
// 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, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
if(arrTimeAtNewAct > latestArrTimeAtNewAct){
return false;
}
// log.info(newAct + " arrTime=" + arrTimeAtNewAct);
double endTimeAtNewAct = CalcUtils.getActivityEndTime(arrTimeAtNewAct, newAct);
double arrTimeAtNextAct = endTimeAtNewAct + routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), endTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double latestArrTimeAtNextAct = states.getActivityState(nextAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
if(arrTimeAtNextAct > latestArrTimeAtNextAct){
return false;
}
// log.info(nextAct + " arrTime=" + arrTimeAtNextAct);
return true;
}
}
static class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelConstraint {
private StateManager stateManager;
public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
int loadAtPrevAct;
int futurePicks;
int pastDeliveries;
if(prevAct instanceof Start){
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
pastDeliveries = 0;
}
else{
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble();
futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble();
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble();
}
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
if(newAct instanceof DeliveryActivity){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}
static class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivityLevelConstraint {
private StateManager stateManager;
public HardPickupAndDeliveryBackhaulActivityLevelConstraint(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(newAct instanceof PickupActivity && nextAct instanceof DeliveryActivity){ return false; }
if(newAct instanceof ServiceActivity && nextAct instanceof DeliveryActivity){ return false; }
if(newAct instanceof DeliveryActivity && prevAct instanceof PickupActivity){ return false; }
if(newAct instanceof DeliveryActivity && prevAct instanceof ServiceActivity){ return false; }
int loadAtPrevAct;
int futurePicks;
int pastDeliveries;
if(prevAct instanceof Start){
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
pastDeliveries = 0;
}
else{
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble();
futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble();
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble();
}
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
if(newAct instanceof DeliveryActivity){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}
}

View file

@ -1,17 +1,42 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.Service;
import basics.route.ServiceActivity;
import basics.route.TourActivityFactory;
import basics.route.DefaultTourActivityFactory;
import basics.route.VehicleRoute;
class Inserter {
private InsertionListeners insertionListeners;
private TourActivityFactory activityFactory;
public Inserter(InsertionListeners insertionListeners) {
this.insertionListeners = insertionListeners;
activityFactory = new DefaultTourActivityFactory();
}
public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute){
@ -25,7 +50,7 @@ class Inserter {
}
// if(vehicleRoute.getDepartureTime() != vehicleRoute.g)
if(job instanceof Service) {
vehicleRoute.getTourActivities().addActivity(insertionData.getDeliveryInsertionIndex(), ServiceActivity.newInstance((Service)job));
vehicleRoute.getTourActivities().addActivity(insertionData.getDeliveryInsertionIndex(), activityFactory.createActivity((Service)job));
vehicleRoute.setDepartureTime(insertionData.getVehicleDepartureTime());
}
else throw new IllegalStateException("neither service nor shipment. this is not supported.");

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import basics.Job;

View file

@ -25,11 +25,11 @@ import java.util.List;
import java.util.concurrent.ExecutorService;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;
import algorithms.HardConstraints.ConstraintManager;
import algorithms.StateUpdates.UpdateStates;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblem.FleetComposition;
import basics.algo.InsertionListener;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
@ -38,7 +38,7 @@ class InsertionFactory {
private static Logger log = Logger.getLogger(InsertionFactory.class);
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads){
VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
boolean concurrentInsertion = false;
if(executorService != null) concurrentInsertion = true;
if(config.containsKey("[@name]")){
@ -54,6 +54,7 @@ class InsertionFactory {
calcBuilder.setStates(routeStates);
calcBuilder.setVehicleRoutingProblem(vrp);
calcBuilder.setVehicleFleetManager(vehicleFleetManager);
calcBuilder.setConstraintManager(constraintManager);
if(config.containsKey("level")){
String level = config.getString("level");
@ -103,13 +104,13 @@ class InsertionFactory {
// insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
// }
insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager));
insertionStrategy.addListener(new VehicleSwitched(vehicleFleetManager));
// insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
// insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager));
// insertionStrategy.addListener(new VehicleSwitched(vehicleFleetManager));
// insertionStrategy.addListener(new UpdateLoadAtRouteLevel(routeStates));
insertionStrategy.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
// insertionStrategy.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l);
// insertionStrategy.addListener(new FindCheaperVehicle(
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.ArrayList;

View file

@ -46,6 +46,7 @@ class IterateRouteBackwardInTime implements VehicleRouteUpdater{
*
*/
public void iterate(VehicleRoute vehicleRoute) {
if(listeners.isEmpty()) return;
listeners.start(vehicleRoute, vehicleRoute.getEnd(), vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime());
Iterator<TourActivity> reverseActIter = vehicleRoute.getTourActivities().reverseActivityIterator();

View file

@ -48,6 +48,7 @@ class IterateRouteForwardInTime implements VehicleRouteUpdater{
*
*/
public void iterate(VehicleRoute vehicleRoute) {
if(listeners.isEmpty()) return;
listeners.start(vehicleRoute, vehicleRoute.getStart(), vehicleRoute.getStart().getEndTime());
Vehicle vehicle = vehicleRoute.getVehicle();

View file

@ -1,156 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import algorithms.RouteStates.ActivityState;
import basics.algo.AlgorithmEndsListener;
import basics.algo.JobInsertedListener;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
import basics.route.TourActivity.JobActivity;
import basics.Job;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
class JobObserver implements JobInsertedListener, BeforeJobInsertionListener, AlgorithmEndsListener{
private static class Info {
double depTime;
double tourSize;
double insertionIndex;
double error;
public Info(double depTime, double tourSize, double insertionIndex,
double error) {
super();
this.depTime = depTime;
this.tourSize = tourSize;
this.insertionIndex = insertionIndex;
this.error = error;
}
}
private String locationId = "70";
private double routeCostBefore;
private double estimatedMC;
private boolean beforeFirst = false;
private RouteStates actStates;
public void setActivityStates(RouteStates actStates){
this.actStates = actStates;
}
public ActivityState state(TourActivity act){
return actStates.getState(act);
}
Collection<Info> infos = new ArrayList<Info>();
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(job2insert instanceof Service){
if(((Service) job2insert).getLocationId().equals(locationId)){
double actualMC = inRoute.getCost()-routeCostBefore;
TourActivity act = getAct(job2insert,inRoute);
double error = (estimatedMC-actualMC);
int tourSize = inRoute.getTourActivities().getActivities().size();
int insertionIndex = getIndexOf(job2insert, inRoute);
// infos.add(new Info())
double depTime = state(act).getEarliestOperationStart()+act.getOperationTime();
infos.add(new Info(depTime,tourSize,insertionIndex,error));
// System.out.println("[id=1][tourSize="+tourSize+"][index="+insertionIndex+
// "][earliestDeparture="+depTime+
// "][tourCostBefore="+routeCostBefore+"][routeCostAfter="+insertedIn.getCost()+"]" +
// "[estimated="+Math.round(estimatedMC)+"][actual="+Math.round(actualMC)+"][error(abs)="+error +
// "][errorPerNextCustomer="+ (error/(double)(tourSize-insertionIndex)) + "]");
routeCostBefore = 0.0;
estimatedMC = 0.0;
if(!beforeFirst) throw new IllegalStateException("ähhh");
beforeFirst = false;
}
}
}
private TourActivity getAct(Job job2insert, VehicleRoute insertedIn) {
for(TourActivity act : insertedIn.getTourActivities().getActivities()){
if(act instanceof JobActivity){
if(((JobActivity) act).getJob().getId().equals(job2insert.getId())){
return act;
}
}
}
return null;
}
private int getIndexOf(Job job2insert, VehicleRoute insertedIn) {
int index=0;
for(TourActivity act : insertedIn.getTourActivities().getActivities()){
if(act instanceof JobActivity){
if(((JobActivity) act).getJob().getId().equals(job2insert.getId())){
return index;
}
}
index++;
}
return -1;
}
@Override
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route) {
if(job instanceof Service){
if(((Service) job).getLocationId().equals(locationId)){
// System.out.println("[id=1][tourSize="+route.getTour().getActivities().size()+"][tourCost="+route.getCost()+"]" +
// "[estimatedMarginalInsertionCost="+data.getInsertionCost()+"]");
routeCostBefore = route.getCost();
estimatedMC = data.getInsertionCost();
beforeFirst = true;
}
}
}
@Override
public void informAlgorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter("output/errorAna.txt"));
for(Info info : infos){
writer.write(new StringBuilder().append(info.depTime).append(";").append(info.tourSize).append(";").append(info.insertionIndex).append(";")
.append(info.error).append("\n").toString());
}
writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import basics.route.TourActivity;

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import algorithms.HardConstraints.HardActivityLevelConstraint;
@ -21,16 +41,16 @@ class MarginalsCalculusTriangleInequality implements MarginalsCalculus{
@Override
public Marginals calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){
return null;
}
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
if(!hardConstraint.fulfilled(iFacts, newAct, newAct_arrTime)){
return null;
}
double newAct_endTime = CalcUtils.getStartTimeAtAct(newAct_arrTime, newAct);
double newAct_endTime = CalcUtils.getActivityEndTime(newAct_arrTime, newAct);
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
@ -38,11 +58,7 @@ class MarginalsCalculusTriangleInequality implements MarginalsCalculus{
double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct;
if(!hardConstraint.fulfilled(iFacts, nextAct, nextAct_arrTime)){
return null;
}
double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct;

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
///*******************************************************************************
// * Copyright (c) 2011 Stefan Schroeder.
// * eMail: stefan.schroeder@kit.edu

View file

@ -1,208 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import basics.Job;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmEndsListener;
import basics.algo.IterationEndsListener;
import basics.algo.IterationStartsListener;
import basics.route.ServiceActivity;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class RouteStates implements IterationStartsListener{
Logger log = Logger.getLogger(RouteStates.class);
static class RouteState {
private double costs;
private int load;
private VehicleRoute route;
public RouteState(VehicleRoute route) {
super();
this.route = route;
}
/**
* @return the costs
*/
public double getCosts() {
return costs;
}
/**
* @param costs the costs to set
*/
public void setCosts(double costs) {
this.costs = costs;
}
/**
* @return the load
*/
public int getLoad() {
return load;
}
/**
* @param load the load to set
*/
public void setLoad(int load) {
this.load = load;
}
}
static class ActivityState {
private double earliestOperationStart;
private double latestOperationStart;
private double currentLoad;
private double currentCost;
private TourActivity act;
public ActivityState(TourActivity activity){
this.earliestOperationStart=activity.getTheoreticalEarliestOperationStartTime();
this.latestOperationStart=activity.getTheoreticalLatestOperationStartTime();
this.act = activity;
}
@Override
public String toString() {
return "[earliestStart="+earliestOperationStart+"][latestStart="+
latestOperationStart+"][currLoad="+currentLoad+"][currCost="+currentCost+"]";
}
public double getEarliestOperationStart() {
return earliestOperationStart;
}
void setEarliestOperationStart(double earliestOperationStart) {
this.earliestOperationStart = earliestOperationStart;
}
public double getLatestOperationStart() {
return latestOperationStart;
}
void setLatestOperationStart(double latestOperationStart) {
this.latestOperationStart = latestOperationStart;
}
public double getCurrentLoad() {
return currentLoad;
}
void setCurrentLoad(double currentLoad) {
this.currentLoad = currentLoad;
}
public double getCurrentCost() {
return currentCost;
}
void setCurrentCost(double currentCost) {
this.currentCost = currentCost;
}
public void reset() {
earliestOperationStart = act.getTheoreticalEarliestOperationStartTime();
latestOperationStart = act.getTheoreticalLatestOperationStartTime() ;
currentLoad = 0.0;
currentCost = 0.0;
}
}
private Map<TourActivity, ActivityState> activityStates;
private Map<Service, TourActivity> tourActivities;
private Map<VehicleRoute, RouteState> routeStates;
public RouteStates() {
activityStates = new HashMap<TourActivity, RouteStates.ActivityState>();
tourActivities = new HashMap<Service,TourActivity>();
routeStates = new HashMap<VehicleRoute, RouteStates.RouteState>();
}
ActivityState getState(TourActivity act){
if(!activityStates.containsKey(act)) return null;
return activityStates.get(act);
}
public void clearStates(){
activityStates.clear();
}
public Map<TourActivity, ActivityState> getActivityStates() {
return activityStates;
}
TourActivity getActivity(Service service, boolean resetState){
TourActivity tourActivity = tourActivities.get(service);
getState(tourActivity).reset();
return tourActivity;
}
public void resetRouteStates(){
routeStates.clear();
}
public RouteState getRouteState(VehicleRoute route){
RouteState routeState = routeStates.get(route);
if(routeState == null){
routeState = new RouteState(route);
putRouteState(route, routeState);
}
return routeState;
}
private void putRouteState(VehicleRoute route, RouteState routeState){
routeStates.put(route, routeState);
}
void initialiseStateOfJobs(Collection<Job> jobs){
for(Job job : jobs){
if(job instanceof Service){
ServiceActivity service = ServiceActivity.newInstance((Service)job);
ActivityState state = new ActivityState(service);
tourActivities.put((Service) job, service);
activityStates.put(service, state);
}
else{
throw new IllegalStateException();
}
}
}
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
resetRouteStates();
}
}

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.Collection;

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.ArrayList;

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import basics.route.TourActivity;

View file

@ -1,6 +1,25 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -28,30 +47,6 @@ class StateManagerImpl implements StateManager{
private Map<TourActivity,States> activityStates = new HashMap<TourActivity, StateManager.States>();
public Map<VehicleRoute, States> getRouteStates() {
return Collections.unmodifiableMap(vehicleRouteStates);
}
public States getRouteStates(VehicleRoute route){
return vehicleRouteStates.get(route);
}
public void put(VehicleRoute route, States states) {
vehicleRouteStates.put(route, states);
}
public Map<TourActivity, States> getActivityStates() {
return Collections.unmodifiableMap(activityStates);
}
public States getActivityStates(TourActivity act){
return activityStates.get(act);
}
public void put(TourActivity act, States states) {
activityStates.put(act, states);
}
public void clear(){
vehicleRouteStates.clear();
activityStates.clear();
@ -85,11 +80,14 @@ class StateManagerImpl implements StateManager{
if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0);
if(stateType.equals(StateTypes.EARLIEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalEarliestOperationStartTime());
if(stateType.equals(StateTypes.LATEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalLatestOperationStartTime());
if(stateType.equals(StateTypes.FUTURE_PICKS)) return new StateImpl(0);
if(stateType.equals(StateTypes.PAST_DELIVERIES)) return new StateImpl(0);
return null;
}
private State getDefaultRouteState(String stateType, VehicleRoute route){
if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0);
if(stateType.equals(StateTypes.LOAD_AT_DEPOT)) return new StateImpl(0);
if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0);
if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0);
return null;

View file

@ -1,13 +1,39 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
class StateTypes {
final static String LOAD = "load";
final static String LOAD_AT_DEPOT = "loadAtDepot";
final static String DURATION = "duration";
final static String LATEST_OPERATION_START_TIME = "latestOST";
final static String EARLIEST_OPERATION_START_TIME = "earliestOST";
public static final String COSTS = "costs";
static final String COSTS = "costs";
final static String FUTURE_PICKS = "futurePicks";
final static String PAST_DELIVERIES = "pastDeliveries";
}

View file

@ -0,0 +1,678 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import algorithms.RuinStrategy.RuinListener;
import algorithms.StateManager.StateImpl;
import basics.Delivery;
import basics.Job;
import basics.Pickup;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionEndsListener;
import basics.algo.InsertionStartsListener;
import basics.algo.IterationEndsListener;
import basics.algo.IterationStartsListener;
import basics.algo.JobInsertedListener;
import basics.algo.VehicleRoutingAlgorithmListener;
import basics.costs.ForwardTransportCost;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DeliveryActivity;
import basics.route.End;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class StateUpdates {
static class VRAListenersManager implements IterationStartsListener, IterationEndsListener, InsertionStartsListener, InsertionEndsListener, JobInsertedListener, RuinListener{
private Map<Class<? extends VehicleRoutingAlgorithmListener>,Collection<VehicleRoutingAlgorithmListener>> listeners = new HashMap<Class<? extends VehicleRoutingAlgorithmListener>,Collection<VehicleRoutingAlgorithmListener>>();
public void addListener(VehicleRoutingAlgorithmListener vraListener){
if(!listeners.containsKey(vraListener.getClass())){
listeners.put(vraListener.getClass(), new ArrayList<VehicleRoutingAlgorithmListener>());
}
listeners.get(vraListener.getClass()).add(vraListener);
}
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {
if(listeners.containsKey(RuinListener.class)){
for(VehicleRoutingAlgorithmListener l : listeners.get(RuinListener.class)){
((RuinListener)l).ruinStarts(routes);
}
}
}
@Override
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
if(listeners.containsKey(RuinListener.class)){
for(VehicleRoutingAlgorithmListener l : listeners.get(RuinListener.class)){
((RuinListener)l).ruinEnds(routes,unassignedJobs);
}
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {
if(listeners.containsKey(RuinListener.class)){
for(VehicleRoutingAlgorithmListener l : listeners.get(RuinListener.class)){
((RuinListener)l).removed(job, fromRoute);
}
}
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(listeners.containsKey(JobInsertedListener.class)){
for(VehicleRoutingAlgorithmListener l : listeners.get(RuinListener.class)){
((JobInsertedListener)l).informJobInserted(job2insert, inRoute, additionalCosts, additionalTime);
}
}
}
@Override
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
// if(listeners.containsKey(JobInsertedListener.class)){
// for(VehicleRoutingAlgorithmListener l : listeners.get(RuinListener.class)){
// ((JobInsertedListener)l).informJobInserted(job2insert, inRoute, additionalCosts, additionalTime);
// }
// }
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes,Collection<Job> unassignedJobs) {
// TODO Auto-generated method stub
}
@Override
public void informIterationEnds(int i, VehicleRoutingProblem problem,Collection<VehicleRoutingProblemSolution> solutions) {
// TODO Auto-generated method stub
}
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem,Collection<VehicleRoutingProblemSolution> solutions) {
// TODO Auto-generated method stub
}
}
static class UpdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{
private StateManagerImpl states;
private VehicleRoutingTransportCosts tpCosts;
private VehicleRoutingActivityCosts actCosts;
public UpdateCostsAtRouteLevel(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts, VehicleRoutingActivityCosts actCosts) {
super();
this.states = states;
this.tpCosts = tpCosts;
this.actCosts = actCosts;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
// inRoute.getVehicleRouteCostCalculator().addTransportCost(additionalCosts);
double oldCosts = states.getRouteState(inRoute, StateTypes.COSTS).toDouble();
oldCosts += additionalCosts;
states.putRouteState(inRoute, StateTypes.COSTS, new StateImpl(oldCosts));
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
for(VehicleRoute route : vehicleRoutes){
forwardInTime.iterate(route);
}
}
@Override
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
// IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
// forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
for(VehicleRoute route : vehicleRoutes){
if(route.isEmpty()) continue;
route.getVehicleRouteCostCalculator().reset();
route.getVehicleRouteCostCalculator().addOtherCost(states.getRouteState(route, StateTypes.COSTS).toDouble());
route.getVehicleRouteCostCalculator().price(route.getVehicle());
// forwardInTime.iterate(route);
}
}
}
static class UpdateActivityTimes implements ForwardInTimeListener{
private Logger log = Logger.getLogger(UpdateActivityTimes.class);
@Override
public void start(VehicleRoute route, Start start, double departureTime) {
start.setEndTime(departureTime);
}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
act.setArrTime(arrTime);
act.setEndTime(endTime);
}
@Override
public void end(End end, double arrivalTime) {
end.setArrTime(arrivalTime);
}
}
static class UpdateCostsAtAllLevels implements ForwardInTimeListener{
private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class);
private VehicleRoutingActivityCosts activityCost;
private ForwardTransportCost transportCost;
private StateManagerImpl states;
private double totalOperationCost = 0.0;
private VehicleRoute vehicleRoute = null;
private TourActivity prevAct = null;
private double startTimeAtPrevAct = 0.0;
public UpdateCostsAtAllLevels(VehicleRoutingActivityCosts activityCost, ForwardTransportCost transportCost, StateManagerImpl states) {
super();
this.activityCost = activityCost;
this.transportCost = transportCost;
this.states = states;
}
@Override
public void start(VehicleRoute route, Start start, double departureTime) {
vehicleRoute = route;
vehicleRoute.getVehicleRouteCostCalculator().reset();
prevAct = start;
startTimeAtPrevAct = departureTime;
// log.info(start + " depTime=" + departureTime);
}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
// log.info(act + " job " + ((JobActivity)act).getJob().getId() + " arrTime=" + arrTime + " endTime=" + endTime);
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(act, arrTime, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
if(transportCost > 10000 || actCost > 100000){
throw new IllegalStateException("aaaääähh");
}
totalOperationCost += transportCost;
totalOperationCost += actCost;
states.putActivityState(act, StateTypes.COSTS, new StateImpl(totalOperationCost));
prevAct = act;
startTimeAtPrevAct = endTime;
}
@Override
public void end(End end, double arrivalTime) {
// log.info(end + " arrTime=" + arrivalTime);
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), end.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(end, arrivalTime, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
if(transportCost > 10000 || actCost > 100000){
throw new IllegalStateException("aaaääähh");
}
totalOperationCost += transportCost;
totalOperationCost += actCost;
states.putRouteState(vehicleRoute, StateTypes.COSTS, new StateImpl(totalOperationCost));
//this is rather strange and likely to change
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().finish();
startTimeAtPrevAct = 0.0;
prevAct = null;
vehicleRoute = null;
totalOperationCost = 0.0;
}
}
static class UpdateEarliestStartTimeWindowAtActLocations implements ForwardInTimeListener{
private StateManagerImpl states;
public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void start(VehicleRoute route, Start start, double departureTime) {}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
states.putActivityState(act, StateTypes.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(arrTime, act.getTheoreticalEarliestOperationStartTime())));
}
@Override
public void end(End end, double arrivalTime) {}
}
static class UpdateLatestOperationStartTimeAtActLocations implements BackwardInTimeListener{
private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class);
private StateManagerImpl states;
public UpdateLatestOperationStartTimeAtActLocations(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void start(VehicleRoute route, End end, double latestArrivalTime) {}
@Override
public void prevActivity(TourActivity act,double latestDepartureTime, double latestOperationStartTime) {
// log.info(act + " jobId=" + ((JobActivity)act).getJob().getId() + " " + latestOperationStartTime);
states.putActivityState(act, StateTypes.LATEST_OPERATION_START_TIME, new StateImpl(latestOperationStartTime));
}
@Override
public void end(Start start, double latestDepartureTime) {}
}
static class UpdateLoadAtAllLevels implements ForwardInTimeListener{
private double load = 0.0;
private StateManagerImpl states;
private VehicleRoute vehicleRoute;
public UpdateLoadAtAllLevels(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void start(VehicleRoute route, Start start, double departureTime) { vehicleRoute = route; }
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
load += (double)act.getCapacityDemand();
states.putActivityState(act, StateTypes.LOAD, new StateImpl(load));
}
@Override
public void end(End end, double arrivalTime) {
states.putRouteState(vehicleRoute, StateTypes.LOAD, new StateImpl(load));
load=0;
vehicleRoute = null;
}
}
static class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener{
private StateManagerImpl states;
public UpdateLoadAtRouteLevel(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(!(job2insert instanceof Service)){
return;
}
double oldLoad = states.getRouteState(inRoute, StateTypes.LOAD).toDouble();
states.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(oldLoad + job2insert.getCapacityDemand()));
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
int load = 0;
for(Job j : route.getTourActivities().getJobs()){
load += j.getCapacityDemand();
}
states.putRouteState(route, StateTypes.LOAD, new StateImpl(load));
}
}
}
static class UpdateStates implements JobInsertedListener, RuinListener{
private IterateRouteForwardInTime iterateForward;
private IterateRouteBackwardInTime iterateBackward;
public UpdateStates(StateManagerImpl states, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) {
iterateForward = new IterateRouteForwardInTime(routingCosts);
iterateForward.addListener(new UpdateActivityTimes());
iterateForward.addListener(new UpdateCostsAtAllLevels(activityCosts, routingCosts, states));
iterateForward.addListener(new UpdateLoadAtAllLevels(states));
// iterateForward.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states));
iterateBackward = new IterateRouteBackwardInTime(routingCosts);
iterateBackward.addListener(new UpdateLatestOperationStartTimeAtActLocations(states));
}
public void update(VehicleRoute route){
iterateForward.iterate(route);
iterateBackward.iterate(route);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
iterateForward.iterate(inRoute);
iterateBackward.iterate(inRoute);
}
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
for(VehicleRoute route : routes) {
iterateForward.iterate(route);
iterateBackward.iterate(route);
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
}
static class UpdateFuturePickupsAtActivityLevel implements BackwardInTimeListener {
private StateManagerImpl stateManager;
private int futurePicks = 0;
private VehicleRoute route;
public UpdateFuturePickupsAtActivityLevel(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void start(VehicleRoute route, End end, double latestArrivalTime) {
this.route = route;
}
@Override
public void prevActivity(TourActivity act, double latestDepartureTime, double latestOperationStartTime) {
stateManager.putActivityState(act, StateTypes.FUTURE_PICKS, new StateImpl(futurePicks));
if(act instanceof PickupActivity || act instanceof ServiceActivity){
futurePicks += act.getCapacityDemand();
}
assert futurePicks <= route.getVehicle().getCapacity() : "sum of pickups must not be > vehicleCap";
assert futurePicks >= 0 : "sum of pickups must not < 0";
}
@Override
public void end(Start start, double latestDepartureTime) {
futurePicks = 0;
route = null;
}
}
static class UpdateOccuredDeliveriesAtActivityLevel implements ForwardInTimeListener {
private StateManagerImpl stateManager;
private int deliveries = 0;
private VehicleRoute route;
public UpdateOccuredDeliveriesAtActivityLevel(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void start(VehicleRoute route, Start start, double departureTime) {
this.route = route;
}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
if(act instanceof DeliveryActivity){
deliveries += Math.abs(act.getCapacityDemand());
}
stateManager.putActivityState(act, StateTypes.PAST_DELIVERIES, new StateImpl(deliveries));
assert deliveries >= 0 : "deliveries < 0";
assert deliveries <= route.getVehicle().getCapacity() : "deliveries > vehicleCap";
}
@Override
public void end(End end, double arrivalTime) {
deliveries = 0;
route = null;
}
}
/**
* Updates load at activity level. Note that this assumed 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.
*
* @author stefan
*
*/
static class UpdateLoadAtActivityLevel implements ForwardInTimeListener {
private StateManagerImpl stateManager;
private int currentLoad = 0;
private VehicleRoute route;
public UpdateLoadAtActivityLevel(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void start(VehicleRoute route, Start start, double departureTime) {
currentLoad = (int) stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT).toDouble();
this.route = route;
}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
currentLoad += act.getCapacityDemand();
stateManager.putActivityState(act, StateTypes.LOAD, new StateImpl(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 end(End end, double arrivalTime) {
currentLoad = 0;
}
}
static class ResetStateManager implements IterationStartsListener {
private StateManagerImpl stateManager;
public ResetStateManager(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
stateManager.clear();
}
}
static interface InsertionStarts {
void insertionStarts(VehicleRoute route);
}
static class UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts implements InsertionStarts {
private StateManagerImpl stateManager;
public UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void insertionStarts(VehicleRoute route) {
int loadAtDepot = 0;
int loadAtEnd = 0;
for(Job j : route.getTourActivities().getJobs()){
if(j instanceof Delivery){
loadAtDepot += j.getCapacityDemand();
}
else if(j instanceof Pickup || j instanceof Service){
loadAtEnd += j.getCapacityDemand();
}
}
stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot));
stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd));
}
}
static class UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted implements JobInsertedListener {
private StateManagerImpl stateManager;
public UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(job2insert instanceof Delivery){
int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble();
// log.info("loadAtDepot="+loadAtDepot);
stateManager.putRouteState(inRoute, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot + job2insert.getCapacityDemand()));
}
else if(job2insert instanceof Pickup || job2insert instanceof Service){
int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD).toDouble();
// log.info("loadAtEnd="+loadAtEnd);
stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand()));
}
}
}
static class UpdateRouteStatesOnceTheRouteHasBeenChanged implements InsertionStartsListener, JobInsertedListener {
private IterateRouteForwardInTime forwardInTimeIterator;
private IterateRouteBackwardInTime backwardInTimeIterator;
private Collection<InsertionStarts> insertionStartsListeners;
private Collection<JobInsertedListener> jobInsertionListeners;
public UpdateRouteStatesOnceTheRouteHasBeenChanged(VehicleRoutingTransportCosts routingCosts) {
forwardInTimeIterator = new IterateRouteForwardInTime(routingCosts);
backwardInTimeIterator = new IterateRouteBackwardInTime(routingCosts);
insertionStartsListeners = new ArrayList<InsertionStarts>();
jobInsertionListeners = new ArrayList<JobInsertedListener>();
}
void addListener(ForwardInTimeListener l){
forwardInTimeIterator.addListener(l);
}
void addListener(BackwardInTimeListener l){
backwardInTimeIterator.addListener(l);
}
void addInsertionStartsListener(InsertionStarts insertionStartListener){
insertionStartsListeners.add(insertionStartListener);
}
void addJobInsertedListener(JobInsertedListener jobInsertedListener){
jobInsertionListeners.add(jobInsertedListener);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
for(JobInsertedListener l : jobInsertionListeners){ l.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); }
forwardInTimeIterator.iterate(inRoute);
backwardInTimeIterator.iterate(inRoute);
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
for(InsertionStarts insertionsStartsHandler : insertionStartsListeners){
insertionsStartsHandler.insertionStarts(route);
}
forwardInTimeIterator.iterate(route);
backwardInTimeIterator.iterate(route);
}
}
}
}

View file

@ -1,62 +0,0 @@
package algorithms;
import java.util.Collection;
import algorithms.StateManager.StateImpl;
import basics.Job;
import basics.algo.InsertionEndsListener;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.VehicleRoute;
class UdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{
private StateManagerImpl states;
private VehicleRoutingTransportCosts tpCosts;
private VehicleRoutingActivityCosts actCosts;
public UdateCostsAtRouteLevel(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts, VehicleRoutingActivityCosts actCosts) {
super();
this.states = states;
this.tpCosts = tpCosts;
this.actCosts = actCosts;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
// inRoute.getVehicleRouteCostCalculator().addTransportCost(additionalCosts);
double oldCosts = states.getRouteState(inRoute, StateTypes.COSTS).toDouble();
oldCosts += additionalCosts;
states.putRouteState(inRoute, StateTypes.COSTS, new StateImpl(oldCosts));
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
for(VehicleRoute route : vehicleRoutes){
forwardInTime.iterate(route);
}
}
@Override
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
// IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
// forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
for(VehicleRoute route : vehicleRoutes){
if(route.isEmpty()) continue;
route.getVehicleRouteCostCalculator().reset();
route.getVehicleRouteCostCalculator().addOtherCost(states.getRouteState(route, StateTypes.COSTS).toDouble());
route.getVehicleRouteCostCalculator().price(route.getVehicle());
// forwardInTime.iterate(route);
}
}
}

View file

@ -1,31 +0,0 @@
package algorithms;
import org.apache.log4j.Logger;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateActivityTimes implements ForwardInTimeListener{
private Logger log = Logger.getLogger(UpdateActivityTimes.class);
@Override
public void start(VehicleRoute route, Start start, double departureTime) {
start.setEndTime(departureTime);
}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
act.setArrTime(arrTime);
act.setEndTime(endTime);
}
@Override
public void end(End end, double arrivalTime) {
end.setArrTime(arrivalTime);
}
}

View file

@ -1,84 +0,0 @@
package algorithms;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import algorithms.StateManager.StateImpl;
import basics.costs.ForwardTransportCost;
import basics.costs.VehicleRoutingActivityCosts;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateCostsAtAllLevels implements ForwardInTimeListener{
private VehicleRoutingActivityCosts activityCost;
private ForwardTransportCost transportCost;
private StateManagerImpl states;
private double totalOperationCost = 0.0;
private VehicleRoute vehicleRoute = null;
private TourActivity prevAct = null;
private double startTimeAtPrevAct = 0.0;
public UpdateCostsAtAllLevels(VehicleRoutingActivityCosts activityCost, ForwardTransportCost transportCost, StateManagerImpl states) {
super();
this.activityCost = activityCost;
this.transportCost = transportCost;
this.states = states;
}
@Override
public void start(VehicleRoute route, Start start, double departureTime) {
vehicleRoute = route;
vehicleRoute.getVehicleRouteCostCalculator().reset();
prevAct = start;
startTimeAtPrevAct = departureTime;
}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(act, arrTime, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
totalOperationCost += transportCost;
totalOperationCost += actCost;
states.putActivityState(act, StateTypes.COSTS, new StateImpl(totalOperationCost));
prevAct = act;
startTimeAtPrevAct = endTime;
}
@Override
public void end(End end, double arrivalTime) {
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), end.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(end, arrivalTime, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
totalOperationCost += transportCost;
totalOperationCost += actCost;
states.putRouteState(vehicleRoute, StateTypes.COSTS, new StateImpl(totalOperationCost));
//this is rather strange and likely to change
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().finish();
startTimeAtPrevAct = 0.0;
prevAct = null;
vehicleRoute = null;
totalOperationCost = 0.0;
}
}

View file

@ -1,30 +0,0 @@
package algorithms;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import algorithms.StateManager.StateImpl;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateEarliestStartTimeWindowAtActLocations implements ForwardInTimeListener{
private StateManagerImpl states;
public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void start(VehicleRoute route, Start start, double departureTime) {}
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
states.putActivityState(act, StateTypes.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(arrTime, act.getTheoreticalEarliestOperationStartTime())));
}
@Override
public void end(End end, double arrivalTime) {}
}

View file

@ -1,32 +0,0 @@
package algorithms;
import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
import algorithms.StateManager.StateImpl;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class UpdateLatestOperationStartTimeAtActLocations implements BackwardInTimeListener{
private StateManagerImpl states;
public UpdateLatestOperationStartTimeAtActLocations(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void start(VehicleRoute route, End end, double latestArrivalTime) {}
@Override
public void prevActivity(TourActivity act,double latestDepartureTime, double latestOperationStartTime) {
states.putActivityState(act, StateTypes.LATEST_OPERATION_START_TIME, new StateImpl(latestOperationStartTime));
}
@Override
public void end(Start start, double latestDepartureTime) {}
}

View file

@ -1,45 +0,0 @@
package algorithms;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import algorithms.StateManager.StateImpl;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
/**
* It does not update start and end activities.
*
* @author stefan
*
*/
class UpdateLoadAtAllLevels implements ForwardInTimeListener{
private double load = 0.0;
private StateManagerImpl states;
private VehicleRoute vehicleRoute;
public UpdateLoadAtAllLevels(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void start(VehicleRoute route, Start start, double departureTime) { vehicleRoute = route; }
@Override
public void nextActivity(TourActivity act, double arrTime, double endTime) {
load += (double)act.getCapacityDemand();
states.putActivityState(act, StateTypes.LOAD, new StateImpl(load));
}
@Override
public void end(End end, double arrivalTime) {
states.putRouteState(vehicleRoute, StateTypes.LOAD, new StateImpl(load));
load=0;
vehicleRoute = null;
}
}

View file

@ -1,42 +0,0 @@
package algorithms;
import java.util.Collection;
import algorithms.StateManager.StateImpl;
import basics.Job;
import basics.Service;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.route.VehicleRoute;
class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener{
private StateManagerImpl states;
public UpdateLoadAtRouteLevel(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(!(job2insert instanceof Service)){
return;
}
double oldLoad = states.getRouteState(inRoute, StateTypes.LOAD).toDouble();
states.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(oldLoad + job2insert.getCapacityDemand()));
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
int load = 0;
for(Job j : route.getTourActivities().getJobs()){
load += j.getCapacityDemand();
}
states.putRouteState(route, StateTypes.LOAD, new StateImpl(load));
}
}
}

View file

@ -1,55 +0,0 @@
package algorithms;
import java.util.Collection;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.algo.JobInsertedListener;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.VehicleRoute;
class UpdateStates implements JobInsertedListener, RuinListener{
private IterateRouteForwardInTime iterateForward;
private IterateRouteBackwardInTime iterateBackward;
public UpdateStates(StateManagerImpl states, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) {
iterateForward = new IterateRouteForwardInTime(routingCosts);
iterateForward.addListener(new UpdateActivityTimes());
iterateForward.addListener(new UpdateCostsAtAllLevels(activityCosts, routingCosts, states));
iterateForward.addListener(new UpdateLoadAtAllLevels(states));
// iterateForward.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states));
iterateBackward = new IterateRouteBackwardInTime(routingCosts);
iterateBackward.addListener(new UpdateLatestOperationStartTimeAtActLocations(states));
}
public void update(VehicleRoute route){
iterateForward.iterate(route);
iterateBackward.iterate(route);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
iterateForward.iterate(inRoute);
iterateBackward.iterate(inRoute);
}
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
for(VehicleRoute route : routes) {
iterateForward.iterate(route);
iterateBackward.iterate(route);
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
}

View file

@ -35,11 +35,16 @@ import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;
import util.RouteUtils;
import algorithms.RuinStrategy.RuinListener;
import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
import algorithms.HardConstraints.ConstraintManager;
import algorithms.HardConstraints.HardTimeWindowActivityLevelConstraint;
import algorithms.StateUpdates.UpdateActivityTimes;
import algorithms.StateUpdates.UpdateCostsAtAllLevels;
import algorithms.StateUpdates.UpdateEarliestStartTimeWindowAtActLocations;
import algorithms.StateUpdates.UpdateLatestOperationStartTimeAtActLocations;
import algorithms.StateUpdates.UpdateStates;
import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.RuinStrategyKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.SelectorKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.StrategyModuleKey;
@ -50,28 +55,25 @@ import algorithms.acceptors.SolutionAcceptor;
import algorithms.selectors.SelectBest;
import algorithms.selectors.SelectRandomly;
import algorithms.selectors.SolutionSelector;
import basics.Job;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblem.Constraint;
import basics.VehicleRoutingProblem.FleetSize;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmStartsListener;
import basics.algo.InsertionListener;
import basics.algo.IterationStartsListener;
import basics.algo.IterationWithoutImprovementBreaker;
import basics.algo.PrematureAlgorithmBreaker;
import basics.algo.SearchStrategy;
import basics.algo.SearchStrategy.DiscoveredSolution;
import basics.algo.SearchStrategyManager;
import basics.algo.SearchStrategyModule;
import basics.algo.SearchStrategyModuleListener;
import basics.algo.TimeBreaker;
import basics.algo.VariationCoefficientBreaker;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;
import basics.route.VehicleRoute;
@ -428,50 +430,43 @@ public class VehicleRoutingAlgorithms {
}
private static VehicleRoutingAlgorithm createAlgo(final VehicleRoutingProblem vrp, XMLConfiguration config, ExecutorService executorService, int nuOfThreads){
//fleetmanager
final VehicleFleetManager vehicleFleetManager;
if(vrp.getFleetSize().equals(FleetSize.INFINITE)){
vehicleFleetManager = new InfiniteVehicles(vrp.getVehicles());
}
else if(vrp.getFleetSize().equals(FleetSize.FINITE)){
vehicleFleetManager = new VehicleFleetManagerImpl(vrp.getVehicles());
}
else{
throw new IllegalStateException("fleet size can only be infinite or finite. " +
"makes sure your config file contains one of these options");
}
// map to store constructed modules
TypedMap definedClasses = new TypedMap();
// algorithm listeners
Set<PrioritizedVRAListener> algorithmListeners = new HashSet<PrioritizedVRAListener>();
// insertion listeners
List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
final StateManagerImpl routeStates = new StateManagerImpl();
IterationStartsListener resetStates = new IterationStartsListener() {
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
routeStates.clear();
}
};
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, resetStates));
//create fleetmanager
final VehicleFleetManager vehicleFleetManager = createFleetManager(vrp);
// insertionListeners.add(new UdateCostsAtRouteLevel(routeStates,vrp.getTransportCosts(),vrp.getActivityCosts()));
//create state-manager
final StateManagerImpl stateManager = new StateManagerImpl();
// RouteStates routeStates = new RouteStates();
// routeStates.initialiseStateOfJobs(vrp.getJobs().values());
// algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, routeStates));
TypedMap definedClasses = new TypedMap();
/*
* initial solution - construction
* define constraints
*/
AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,routeStates,algorithmListeners,definedClasses,executorService,nuOfThreads);
//constraint manager
ConstraintManager constraintManager = new ConstraintManager();
constraintManager.addConstraint(new HardConstraints.HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
if(vrp.getProblemConstraints().contains(Constraint.DELIVERIES_FIRST)){
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager));
}
else{
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryActivityLevelConstraint(stateManager));
}
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager));
//construct initial solution creator
AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,constraintManager);
if(createInitialSolution != null) algorithmListeners.add(new PrioritizedVRAListener(Priority.MEDIUM, createInitialSolution));
//construct algorithm, i.e. search-strategies and its modules
int solutionMemory = config.getInt("strategy.memory");
SearchStrategyManager searchStratManager = new SearchStrategyManager();
List<HierarchicalConfiguration> strategyConfigs = config.configurationsAt("strategy.searchStrategies.searchStrategy");
@ -483,26 +478,72 @@ public class VehicleRoutingAlgorithms {
strategy.setName(name);
List<HierarchicalConfiguration> modulesConfig = strategyConfig.configurationsAt("modules.module");
for(HierarchicalConfiguration moduleConfig : modulesConfig){
SearchStrategyModule module = buildModule(moduleConfig,vrp,vehicleFleetManager,routeStates,algorithmListeners,definedClasses,executorService,nuOfThreads);
SearchStrategyModule module = buildModule(moduleConfig,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads, constraintManager);
strategy.addModule(module);
}
searchStratManager.addStrategy(strategy, strategyConfig.getDouble("probability"));
}
//construct algorithm
VehicleRoutingAlgorithm metaAlgorithm = new VehicleRoutingAlgorithm(vrp, searchStratManager);
if(config.containsKey("iterations")){
int iter = config.getInt("iterations");
metaAlgorithm.setNuOfIterations(iter);
log.info("set nuOfIterations to " + iter);
}
//prematureBreak
/*
* define stateUpdates
*/
//reset stateManager
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new StateUpdates.ResetStateManager(stateManager)));
//update states
// metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateStates(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged routeChangedListener = new StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged(vrp.getTransportCosts());
routeChangedListener.addInsertionStartsListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
routeChangedListener.addJobInsertedListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
routeChangedListener.addListener(new StateUpdates.UpdateActivityTimes());
routeChangedListener.addListener(new StateUpdates.UpdateLoadAtActivityLevel(stateManager));
routeChangedListener.addListener(new StateUpdates.UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
routeChangedListener.addListener(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager));
routeChangedListener.addListener(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager));
routeChangedListener.addListener(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(routeChangedListener);
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(vehicleFleetManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new ResetAndIniFleetManager(vehicleFleetManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager));
//define prematureBreak
PrematureAlgorithmBreaker prematureAlgoBreaker = getPrematureBreaker(config,algorithmListeners);
metaAlgorithm.setPrematureAlgorithmBreaker(prematureAlgoBreaker);
//misc
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
//register listeners
registerListeners(metaAlgorithm,algorithmListeners);
registerInsertionListeners(definedClasses,insertionListeners);
return metaAlgorithm;
}
private static VehicleFleetManager createFleetManager(final VehicleRoutingProblem vrp) {
if(vrp.getFleetSize().equals(FleetSize.INFINITE)){
return new InfiniteVehicles(vrp.getVehicles());
}
else if(vrp.getFleetSize().equals(FleetSize.FINITE)){
return new VehicleFleetManagerImpl(vrp.getVehicles());
}
throw new IllegalStateException("fleet size can only be infinite or finite. " +
"makes sure your config file contains one of these options");
}
private static PrematureAlgorithmBreaker getPrematureBreaker(XMLConfiguration config, Set<PrioritizedVRAListener> algorithmListeners) {
String basedOn = config.getString("prematureBreak[@basedOn]");
if(basedOn == null){
@ -570,7 +611,7 @@ public class VehicleRoutingAlgorithms {
metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners);
}
private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
if(modConfigs == null) return null;
if(modConfigs.isEmpty()) return null;
@ -585,7 +626,7 @@ public class VehicleRoutingAlgorithms {
InsertionStrategy insertionStrategy = definedClasses.get(insertionStrategyKey);
if(insertionStrategy == null){
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
insertionStrategy = createInsertionStrategy(modConfig, vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads);
insertionStrategy = createInsertionStrategy(modConfig, vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads, constraintManager);
algorithmListeners.addAll(prioListeners);
definedClasses.put(insertionStrategyKey,insertionStrategy);
}
@ -667,7 +708,7 @@ public class VehicleRoutingAlgorithms {
}
private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
final StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads) {
final StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
String moduleName = moduleConfig.getString("[@name]");
if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
String moduleId = moduleConfig.getString("[@id]");
@ -716,49 +757,14 @@ public class VehicleRoutingAlgorithms {
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads);
insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads, constraintManager);
algorithmListeners.addAll(prioListeners);
}
final InsertionStrategy final_insertion = insertion;
SearchStrategyModule module = new SearchStrategyModule() {
private Logger logger = Logger.getLogger(SearchStrategyModule.class);
@Override
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
final_insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs);
double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
vrpSolution.setCost(totalCost);
return vrpSolution;
}
@Override
public String toString() {
return getName();
}
@Override
public String getName() {
return "[name=ruin_and_recreate][ruin="+ruin+"][recreate="+final_insertion+"]";
}
@Override
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
if(moduleListener instanceof InsertionListener){
InsertionListener iListener = (InsertionListener) moduleListener;
if(!final_insertion.getListeners().contains(iListener)){
logger.info("register moduleListener " + moduleListener);
final_insertion.addListener(iListener);
}
}
}
};
return module;
RuinAndRecreateModule rrModule = new RuinAndRecreateModule("ruin_and_recreate", final_insertion, ruin);
return rrModule;
}
if(moduleName.equals("gendreau")){
int iterations = moduleConfig.getInt("iterations");
double share = moduleConfig.getDouble("share");
@ -771,7 +777,6 @@ public class VehicleRoutingAlgorithms {
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
ruin = new RuinRadial(vrp, 0.3, new JobDistanceAvgCosts(vrp.getTransportCosts()));
ruin.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
definedClasses.put(stratKey, ruin);
}
@ -786,7 +791,7 @@ public class VehicleRoutingAlgorithms {
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads);
insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads, constraintManager);
algorithmListeners.addAll(prioListeners);
}
Gendreau gendreau = new Gendreau(vrp, ruin, insertion);
@ -810,7 +815,6 @@ public class VehicleRoutingAlgorithms {
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
ruin = new RuinRadial(vrp, shareToRuin, jobDistance);
ruin.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
definedClasses.put(stratKey, ruin);
}
return ruin;
@ -821,14 +825,13 @@ public class VehicleRoutingAlgorithms {
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
ruin = new RuinRandom(vrp, shareToRuin);
ruin.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
definedClasses.put(stratKey, ruin);
}
return ruin;
}
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads) {
InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads);
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads, constraintManager);
return insertion;
}

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import basics.algo.InsertionListener;

View file

@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package basics;
public final class Delivery extends Service{
public static class Builder extends Service.Builder {
public static Builder newInstance(String id, int size){
return new Builder(id,size);
}
Builder(String id, int size) {
super(id, size);
}
public Delivery build(){
if(locationId == null) {
if(coord == null) throw new IllegalStateException("either locationId or a coordinate must be given. But is not.");
locationId = coord.toString();
}
this.setType("delivery");
return new Delivery(this);
}
}
Delivery(Builder builder) {
super(builder);
}
}

View file

@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package basics;
public final class Pickup extends Service {
public static class Builder extends Service.Builder {
public static Builder newInstance(String id, int size){
return new Builder(id,size);
}
Builder(String id, int size) {
super(id, size);
}
public Pickup build(){
if(locationId == null) {
if(coord == null) throw new IllegalStateException("either locationId or a coordinate must be given. But is not.");
locationId = coord.toString();
}
this.setType("pickup");
return new Pickup(this);
}
}
Pickup(Builder builder) {
super(builder);
}
}

View file

@ -26,8 +26,6 @@ import util.Coordinate;
public class Service implements Job {
public static class Builder {
public static Builder newInstance(String id, int size){
@ -35,21 +33,21 @@ public class Service implements Job {
}
private String id;
private String locationId;
private String name = "service";
private Coordinate coord;
private double serviceTime;
private TimeWindow timeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);
private int demand;
protected String locationId;
private String type = "service";
protected Coordinate coord;
protected double serviceTime;
protected TimeWindow timeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);
protected int demand;
private Builder(String id, int size) {
super();
Builder(String id, int size) {
if(size < 0) throw new IllegalArgumentException("size must be greater than or equal to zero");
this.id = id;
this.demand = size;
}
public Builder setName(String name){
this.name = name;
protected Builder setType(String name){
this.type = name;
return this;
}
@ -64,6 +62,7 @@ public class Service implements Job {
}
public Builder setServiceTime(double serviceTime){
if(serviceTime < 0) throw new IllegalArgumentException("serviceTime must be greate than or equal to zero");
this.serviceTime = serviceTime;
return this;
}
@ -78,7 +77,7 @@ public class Service implements Job {
if(coord == null) throw new IllegalStateException("either locationId or a coordinate must be given. But is not.");
locationId = coord.toString();
}
this.setType("service");
return new Service(this);
}
@ -89,7 +88,7 @@ public class Service implements Job {
private final String locationId;
private final String name;
private final String type;
private final Coordinate coord;
@ -99,14 +98,14 @@ public class Service implements Job {
private final int demand;
private Service(Builder builder){
Service(Builder builder){
id = builder.id;
locationId = builder.locationId;
coord = builder.coord;
serviceTime = builder.serviceTime;
timeWindow = builder.timeWindow;
demand = builder.demand;
name = builder.name;
type = builder.type;
}
@Override
@ -139,7 +138,7 @@ public class Service implements Job {
* @return the name
*/
public String getType() {
return name;
return type;
}
@Override

View file

@ -49,6 +49,18 @@ import basics.route.VehicleTypeImpl;
*/
public class VehicleRoutingProblem {
/**
* Overall problem constraints.
*
* <p>DELIIVERIES_FIRST corresponds to the vehicle routing problem with back hauls, i.e. before a vehicle is not entirely unloaded, no pickup can be made.
*
* @author stefan
*
*/
public enum Constraint {
DELIVERIES_FIRST
}
/**
* Builder to build the routing-problem.
*
@ -81,6 +93,8 @@ public class VehicleRoutingProblem {
private FleetComposition fleetComposition = FleetComposition.HOMOGENEOUS;
private Collection<VehicleType> vehicleTypes;
private Collection<Constraint> problemConstraints;
/**
* by default all locations are neighbors
@ -99,6 +113,7 @@ public class VehicleRoutingProblem {
coordinates = new HashMap<String, Coordinate>();
vehicleTypes = new ArrayList<VehicleType>();
services = new ArrayList<Service>();
problemConstraints = new ArrayList<VehicleRoutingProblem.Constraint>();
}
/**
@ -117,6 +132,7 @@ public class VehicleRoutingProblem {
}
return id;
}
/**
* Returns the unmodifiable map of locations (mapped by their id).
@ -145,6 +161,12 @@ public class VehicleRoutingProblem {
};
}
public void addProblemConstraint(Constraint constraint){
if(!problemConstraints.contains(constraint)) problemConstraints.add(constraint);
}
/**
* Sets routing costs.
*
@ -387,6 +409,8 @@ public class VehicleRoutingProblem {
private FleetComposition fleetComposition;
private Collection<Constraint> problemConstraints;
private VehicleRoutingProblem(Builder builder) {
this.jobs = builder.jobs;
this.fleetComposition = builder.fleetComposition;
@ -396,6 +420,7 @@ public class VehicleRoutingProblem {
this.transportCosts = builder.transportCosts;
this.activityCosts = builder.activityCosts;
this.neighborhood = builder.neighborhood;
this.problemConstraints = builder.problemConstraints;
log.info("initialise " + this);
}
@ -441,6 +466,14 @@ public class VehicleRoutingProblem {
return Collections.unmodifiableMap(jobs);
}
/**
* Returns unmodifiable collection of problem-constraints.
*
* @return
*/
public Collection<Constraint> getProblemConstraints(){
return Collections.unmodifiableCollection(problemConstraints);
}
/**
* Returns the entire, unmodifiable collection of types.

View file

@ -20,6 +20,6 @@
******************************************************************************/
package basics.algo;
public class SearchStrategyListener {
public interface SearchStrategyListener extends VehicleRoutingAlgorithmListener{
}

View file

@ -20,6 +20,6 @@
******************************************************************************/
package basics.algo;
public interface SearchStrategyModuleListener {
public interface SearchStrategyModuleListener extends VehicleRoutingAlgorithmListener{
}

View file

@ -38,25 +38,52 @@ import org.xml.sax.SAXException;
import util.Coordinate;
import util.Resource;
import basics.Delivery;
import basics.Pickup;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblem.FleetComposition;
import basics.VehicleRoutingProblem.FleetSize;
import basics.VehicleRoutingProblemSolution;
import basics.route.DefaultTourActivityFactory;
import basics.route.DeliveryActivity;
import basics.route.Driver;
import basics.route.DriverImpl;
import basics.route.End;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TimeWindow;
import basics.route.TourActivity;
import basics.route.TourActivityFactory;
import basics.route.Vehicle;
import basics.route.VehicleImpl;
import basics.route.VehicleImpl.Builder;
import basics.route.VehicleRoute;
import basics.route.VehicleType;
import basics.route.VehicleTypeImpl;
public class VrpXMLReader{
public interface ServiceBuilderFactory {
Service.Builder createBuilder(String serviceType, String id, int size);
}
static class DefaultServiceBuilderFactory implements ServiceBuilderFactory{
@Override
public basics.Service.Builder createBuilder(String serviceType, String id, int size) {
if(serviceType.equals("pickup")){
return Pickup.Builder.newInstance(id, size);
}
else if(serviceType.equals("delivery")){
return Delivery.Builder.newInstance(id, size);
}
else{
return Service.Builder.newInstance(id, size);
}
}
}
private static Logger logger = Logger.getLogger(VrpXMLReader.class);
@ -70,6 +97,18 @@ public class VrpXMLReader{
private Collection<VehicleRoutingProblemSolution> solutions;
private ServiceBuilderFactory serviceBuilderFactory = new DefaultServiceBuilderFactory();
private TourActivityFactory tourActivityFactory = new DefaultTourActivityFactory();
public void setTourActivityFactory(TourActivityFactory tourActivityFactory){
this.tourActivityFactory = tourActivityFactory;
}
public void setServiceBuilderFactory(ServiceBuilderFactory serviceBuilderFactory){
this.serviceBuilderFactory=serviceBuilderFactory;
}
/**
* @param schemaValidation the schemaValidation to set
*/
@ -170,10 +209,10 @@ public class VrpXMLReader{
if(arrTime == null) throw new IllegalStateException("act.arrTime is missing.");
String endTime = actConfig.getString("endTime");
if(endTime == null) throw new IllegalStateException("act.endTime is missing.");
ServiceActivity serviceActivity = ServiceActivity.newInstance(service);
serviceActivity.setArrTime(Double.parseDouble(arrTime));
serviceActivity.setEndTime(Double.parseDouble(endTime));
routeBuilder.addActivity(serviceActivity);
TourActivity tourActivity = tourActivityFactory.createActivity(service);
tourActivity.setArrTime(Double.parseDouble(arrTime));
tourActivity.setEndTime(Double.parseDouble(endTime));
routeBuilder.addActivity(tourActivity);
}
routes.add(routeBuilder.build());
}
@ -210,13 +249,12 @@ public class VrpXMLReader{
for(HierarchicalConfiguration serviceConfig : serviceConfigs){
String id = serviceConfig.getString("[@id]");
if(id == null) throw new IllegalStateException("service[@id] is missing.");
String name = serviceConfig.getString("[@type]");
if(name == null) name = "service";
String type = serviceConfig.getString("[@type]");
if(type == null) type = "service";
String capacityDemand = serviceConfig.getString("capacity-demand");
int cap = 0;
if(capacityDemand != null) cap = Integer.parseInt(capacityDemand);
Service.Builder builder = Service.Builder.newInstance(id, cap);
builder.setName(name);
Service.Builder builder = serviceBuilderFactory.createBuilder(type, id, cap);
String serviceLocationId = serviceConfig.getString("locationId");
builder.setLocationId(serviceLocationId);
Coordinate serviceCoord = null;
@ -235,8 +273,6 @@ public class VrpXMLReader{
builder.setLocationId(serviceCoord.toString());
}
}
if(serviceConfig.containsKey("duration")){
builder.setServiceTime(serviceConfig.getDouble("duration"));
}
@ -264,15 +300,12 @@ public class VrpXMLReader{
Double fix = typeConfig.getDouble("costs.fixed");
Double timeC = typeConfig.getDouble("costs.time");
Double distC = typeConfig.getDouble("costs.distance");
// Double start = typeConfig.getDouble("timeSchedule.start");
// Double end = typeConfig.getDouble("timeSchedule.end");
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);
// if(start != null && end != null) typeBuilder.setTimeSchedule(new TimeSchedule(start, end));
VehicleTypeImpl type = typeBuilder.build();
types.put(type.getTypeId(), type);
vrpBuilder.addVehicleType(type);
@ -310,7 +343,6 @@ public class VrpXMLReader{
if(start != null) builder.setEarliestStart(Double.parseDouble(start));
if(end != null) builder.setLatestArrival(Double.parseDouble(end));
VehicleImpl vehicle = builder.build();
// vehicleMap.put(vehicle.getId(), vehicle);
vrpBuilder.addVehicle(vehicle);
vehicleMap.put(vehicleId, vehicle);
}

View file

@ -39,6 +39,7 @@ import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.route.ServiceActivity;
import basics.route.TourActivity;
import basics.route.TourActivity.JobActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.VehicleType;
@ -84,7 +85,6 @@ public class VrpXMLWriter {
writeProblemType(xmlConfig);
writeVehiclesAndTheirTypes(xmlConfig);
writerServices(xmlConfig);
// writeShipments(xmlConfig);
writeSolutions(xmlConfig);
OutputFormat format = new OutputFormat();
@ -133,8 +133,8 @@ public class VrpXMLWriter {
int actCounter = 0;
for(TourActivity act : route.getTourActivities().getActivities()){
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act("+actCounter+")[@type]", act.getName());
if(act instanceof ServiceActivity){
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act("+actCounter+").serviceId", ((ServiceActivity) act).getJob().getId());
if(act instanceof JobActivity){
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act("+actCounter+").serviceId", ((JobActivity) act).getJob().getId());
}
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act("+actCounter+").arrTime", act.getArrTime());
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act("+actCounter+").endTime", act.getEndTime());
@ -169,36 +169,6 @@ public class VrpXMLWriter {
}
// private void writeShipments(XMLConf xmlConfig) {
// String shipmentPathString = "shipments.shipment";
// int counter = 0;
// for(Job j : vrp.getJobs().values()){
// Shipment shipment = (Shipment) j;
// xmlConfig.setProperty(shipmentPathString + "("+counter+")[@id]", shipment.getId());
// if(shipment.getFromId() != null) xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.locationId", shipment.getFromId());
// if(shipment.getFromCoord() != null) {
// xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.coord[@x]", shipment.getFromCoord().getX());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.coord[@y]", shipment.getFromCoord().getY());
// }
// if(shipment.getToId() != null) xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.locationId", shipment.getToId());
// if(shipment.getFromCoord() != null) {
// xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.coord[@x]", shipment.getToCoord().getX());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.coord[@y]", shipment.getToCoord().getY());
// }
// xmlConfig.setProperty(shipmentPathString + "("+counter+").size", shipment.getSize());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.serviceTime", shipment.getPickupServiceTime());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.timeWindows.timeWindow(0).start", shipment.getPickupTW().getStart());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.timeWindows.timeWindow(0).end", shipment.getPickupTW().getEnd());
//
// xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.serviceTime", shipment.getDeliveryServiceTime());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.timeWindows.timeWindow(0).start", shipment.getDeliveryTW().getStart());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.timeWindows.timeWindow(0).end", shipment.getDeliveryTW().getEnd());
//
// counter++;
// }
//
// }
private void writeProblemType(XMLConfiguration xmlConfig){
xmlConfig.setProperty("problemType.fleetSize", vrp.getFleetSize());
@ -206,19 +176,6 @@ public class VrpXMLWriter {
}
private void writeVehiclesAndTheirTypes(XMLConfiguration xmlConfig) {
// //depots
// Map<Depot,Integer> depot2id = new HashMap<Depot, Integer>();
// int depotCounter = 0;
// for(Depot depot : vrp.getDepots()){
// int depotId = depotCounter+1;
// depot2id.put(depot, depotId);
// xmlConfig.setProperty("depots.depot" + "("+depotCounter+")[@id]", (depotId));
// xmlConfig.setProperty("depots.depot" + "("+depotCounter+").locationId", depot.getId());
// xmlConfig.setProperty("depots.depot" + "("+depotCounter+").coord[@x]", depot.getCoord().getX());
// xmlConfig.setProperty("depots.depot" + "("+depotCounter+").coord[@y]", depot.getCoord().getY());
// depotCounter++;
// }
//vehicles
String vehiclePathString = new StringBuilder().append(Schema.VEHICLES).append(".").
@ -234,13 +191,7 @@ public class VrpXMLWriter {
}
xmlConfig.setProperty(vehiclePathString + "("+counter+").timeSchedule.start", vehicle.getEarliestDeparture());
xmlConfig.setProperty(vehiclePathString + "("+counter+").timeSchedule.end", vehicle.getLatestArrival());
// if(vehicle.getLocationId() != null) xmlConfig.setProperty(vehiclePathString + "("+counter+").locationId", vehicle.getLocationId());
// if(vehicle.getCoord() != null) {
// xmlConfig.setProperty(vehiclePathString + "("+counter+").coord[@x]", vehicle.getCoord().getX());
// xmlConfig.setProperty(vehiclePathString + "("+counter+").coord[@y]", vehicle.getCoord().getY());
// }
// xmlConfig.setProperty(vehiclePathString + "("+counter+").earliestStart", vehicle.getEarliestDeparture());
// xmlConfig.setProperty(vehiclePathString + "("+counter+").latestEnd", vehicle.getLatestArrival());
counter++;
}
@ -250,44 +201,13 @@ public class VrpXMLWriter {
for(VehicleType type : vrp.getTypes()){
xmlConfig.setProperty(typePathString + "("+typeCounter+").id", type.getTypeId());
xmlConfig.setProperty(typePathString + "("+typeCounter+").capacity", type.getCapacity());
// xmlConfig.setProperty(typePathString + "("+typeCounter+").timeSchedule.start", type.getTimeSchedule().getEarliestStart());
// xmlConfig.setProperty(typePathString + "("+typeCounter+").timeSchedule.end", type.getTimeSchedule().getLatestEnd());
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);
typeCounter++;
}
// //type2depot assignments
// int assignmentCounter = 0;
// boolean first = true;
// for(Depot depot : vrp.getDepotToVehicleTypeAssignments().keySet()){
// if(first){
// xmlConfig.setProperty("assignments[@type]", "vehicleType2depot");
// }
// for(VehicleType type : vrp.getDepotToVehicleTypeAssignments().get(depot)){
// xmlConfig.setProperty("assignments.assignment" + "("+assignmentCounter+").depotId", depot2id.get(depot));
// xmlConfig.setProperty("assignments.assignment" + "("+assignmentCounter+").vehicleTypeId", type.getTypeId());
// assignmentCounter++;
// }
// }
//
// //vehicle2depot assignments
// int vehicleAssignmentCounter = 0;
// boolean first_ = true;
// for(Depot depot : vrp.getDepotToVehicleAssignments().keySet()){
// if(first_){
// xmlConfig.setProperty("assignments[@type]", "vehicle2depot");
// }
// for(Vehicle vehicle : vrp.getDepotToVehicleAssignments().get(depot)){
// xmlConfig.setProperty("assignments.assignment" + "("+vehicleAssignmentCounter+").depotId", depot2id.get(depot));
// xmlConfig.setProperty("assignments.assignment" + "("+vehicleAssignmentCounter+").vehicleId", vehicle.getId());
// vehicleAssignmentCounter++;
// }
// }
//
}

View file

@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package basics.route;
import basics.Delivery;
import basics.Pickup;
import basics.Service;
public class DefaultTourActivityFactory implements TourActivityFactory{
@Override
public TourActivity createActivity(Service service) {
TourActivity act;
if(service instanceof Pickup){
act = new PickupActivity((Pickup) service);
}
else if(service instanceof Delivery){
act = new DeliveryActivity((Delivery) service);
}
else{
act = ServiceActivity.newInstance(service);
}
return act;
}
}

View file

@ -0,0 +1,105 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package basics.route;
import basics.Delivery;
import basics.route.TourActivity.JobActivity;
public class DeliveryActivity implements JobActivity<Delivery>{
private Delivery delivery;
private double arrTime;
private double endTime;
public DeliveryActivity(Delivery delivery) {
super();
this.delivery = delivery;
}
private DeliveryActivity(DeliveryActivity deliveryActivity){
this.delivery=deliveryActivity.getJob();
this.arrTime=deliveryActivity.getArrTime();
this.endTime=deliveryActivity.getEndTime();
}
@Override
public int getCapacityDemand() {
return delivery.getCapacityDemand()*-1;
}
@Override
public String getName() {
return delivery.getType();
}
@Override
public String getLocationId() {
return delivery.getLocationId();
}
@Override
public double getTheoreticalEarliestOperationStartTime() {
return delivery.getTimeWindow().getStart();
}
@Override
public double getTheoreticalLatestOperationStartTime() {
return delivery.getTimeWindow().getEnd();
}
@Override
public double getOperationTime() {
return delivery.getServiceDuration();
}
@Override
public double getArrTime() {
return arrTime;
}
@Override
public double getEndTime() {
return endTime;
}
@Override
public void setArrTime(double arrTime) {
this.arrTime=arrTime;
}
@Override
public void setEndTime(double endTime) {
this.endTime=endTime;
}
@Override
public TourActivity duplicate() {
return new DeliveryActivity(this);
}
@Override
public Delivery getJob() {
return delivery;
}
}

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package basics.route;
import basics.route.VehicleTypeImpl.VehicleCostParams;

View file

@ -0,0 +1,106 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package basics.route;
import basics.Pickup;
import basics.route.TourActivity.JobActivity;
public class PickupActivity implements JobActivity<Pickup>{
private Pickup pickup;
private double arrTime;
private double depTime;
public PickupActivity(Pickup pickup) {
super();
this.pickup = pickup;
}
private PickupActivity(PickupActivity pickupActivity){
this.pickup=pickupActivity.getJob();
this.arrTime=pickupActivity.getArrTime();
this.depTime=pickupActivity.getEndTime();
}
@Override
public String getName() {
return pickup.getType();
}
@Override
public String getLocationId() {
return pickup.getLocationId();
}
@Override
public double getTheoreticalEarliestOperationStartTime() {
return pickup.getTimeWindow().getStart();
}
@Override
public double getTheoreticalLatestOperationStartTime() {
return pickup.getTimeWindow().getEnd();
}
@Override
public double getOperationTime() {
return pickup.getServiceDuration();
}
@Override
public double getArrTime() {
return arrTime;
}
@Override
public double getEndTime() {
return depTime;
}
@Override
public void setArrTime(double arrTime) {
this.arrTime=arrTime;
}
@Override
public void setEndTime(double endTime) {
this.depTime=endTime;
}
@Override
public TourActivity duplicate() {
return new PickupActivity(this);
}
@Override
public Pickup getJob() {
return pickup;
}
@Override
public int getCapacityDemand() {
return pickup.getCapacityDemand();
}
}

View file

@ -31,6 +31,8 @@ public class ServiceActivity implements JobActivity<Service>{
public double endTime;
public int capacityDemand;
/**
* @return the arrTime
*/
@ -67,18 +69,31 @@ public class ServiceActivity implements JobActivity<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;
private ServiceActivity(Service service) {
protected ServiceActivity(Service service) {
counter++;
this.service = service;
this.capacityDemand = service.getCapacityDemand();
}
private ServiceActivity(ServiceActivity serviceActivity) {
protected ServiceActivity(ServiceActivity serviceActivity) {
counter++;
this.service = serviceActivity.getJob();
this.arrTime = serviceActivity.getArrTime();
this.endTime = serviceActivity.getEndTime();
this.capacityDemand = serviceActivity.getCapacityDemand();
}
@ -123,7 +138,7 @@ public class ServiceActivity implements JobActivity<Service>{
@Override
public int getCapacityDemand() {
return service.getCapacityDemand();
return this.capacityDemand;
}
@Override

View file

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package basics.route;
import basics.Service;
public interface TourActivityFactory {
public TourActivity createActivity(Service service);
}

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package basics.route;
import basics.route.VehicleTypeImpl.VehicleCostParams;
@ -13,4 +33,4 @@ public interface VehicleType {
public VehicleCostParams getVehicleCostParams();
}
}

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package basics.route;
@ -148,4 +168,4 @@ public class VehicleTypeImpl implements VehicleType {
public double getMaxVelocity() {
return maxVelocity;
}
}
}

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package util;
import basics.VehicleRoutingProblem;
@ -14,4 +34,4 @@ public class BenchmarkInstance {
this.bestKnownResult = bestKnownResult;
this.bestKnownVehicles = bestKnowVehicles;
}
}
}

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package util;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
@ -53,4 +73,4 @@ public class BenchmarkResult {
return statsTimes;
}
}
}

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package util;
import java.util.HashMap;

View file

@ -1,6 +1,26 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import java.util.Collection;
@ -9,6 +29,8 @@ import org.junit.Test;
import util.Solutions;
import algorithms.HardConstraints.HardActivityLevelConstraint;
import algorithms.StateUpdates.UpdateCostsAtRouteLevel;
import algorithms.StateUpdates.UpdateLoadAtRouteLevel;
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
import algorithms.selectors.SelectBest;
import basics.VehicleRoutingAlgorithm;
@ -36,7 +58,7 @@ public class BuildCVRPAlgoFromScratchTest {
HardActivityLevelConstraint hardActLevelConstraint = new HardActivityLevelConstraint() {
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity act, double arrTime) {
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
return true;
}
};
@ -76,7 +98,7 @@ public class BuildCVRPAlgoFromScratchTest {
vra.getAlgorithmListeners().addListener(clearStateManager);
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(fleetManager));
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UdateCostsAtRouteLevel(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateCostsAtRouteLevel(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateLoadAtRouteLevel(stateManager));
VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion).createInitialSolution(vrp);

View file

@ -0,0 +1,192 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import java.util.Collection;
import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import util.Solutions;
import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import algorithms.HardConstraints.HardActivityLevelConstraintManager;
import algorithms.StateManager.StateImpl;
import algorithms.StateUpdates.UpdateActivityTimes;
import algorithms.StateUpdates.UpdateCostsAtAllLevels;
import algorithms.StateUpdates.UpdateEarliestStartTimeWindowAtActLocations;
import algorithms.StateUpdates.UpdateLatestOperationStartTimeAtActLocations;
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
import algorithms.selectors.SelectBest;
import basics.Delivery;
import basics.Job;
import basics.Pickup;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionStartsListener;
import basics.algo.IterationStartsListener;
import basics.algo.JobInsertedListener;
import basics.algo.SearchStrategy;
import basics.algo.SearchStrategyManager;
import basics.io.VrpXMLReader;
import basics.io.VrpXMLWriter;
import basics.route.DeliveryActivity;
import basics.route.End;
import basics.route.PickupActivity;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
public class BuildPDVRPAlgoFromScratchTest {
VehicleRoutingProblem vrp;
VehicleRoutingAlgorithm vra;
static Logger log = Logger.getLogger(BuildPDVRPAlgoFromScratchTest.class);
@Before
public void setup(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
new VrpXMLReader(builder).read("src/test/resources/pd_solomon_r101.xml");
vrp = builder.build();
final StateManagerImpl stateManager = new StateManagerImpl();
HardActivityLevelConstraintManager actLevelConstraintAccumulator = new HardActivityLevelConstraintManager();
actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardPickupAndDeliveryActivityLevelConstraint(stateManager));
actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
MarginalsCalculus marginalCalculus = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), actLevelConstraintAccumulator);
CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager));
// CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager));
VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles());
JobInsertionCalculator finalServiceInsertion = new CalculatesVehTypeDepServiceInsertion(fleetManager, serviceInsertion);
BestInsertion bestInsertion = new BestInsertion(finalServiceInsertion);
RuinRadial radial = new RuinRadial(vrp, 0.15, new JobDistanceAvgCosts(vrp.getTransportCosts()));
RuinRandom random = new RuinRandom(vrp, 0.25);
SearchStrategy randomStrategy = new SearchStrategy(new SelectBest(), new AcceptNewIfBetterThanWorst(1));
RuinAndRecreateModule randomModule = new RuinAndRecreateModule("randomRuin_bestInsertion", bestInsertion, random);
randomStrategy.addModule(randomModule);
SearchStrategy radialStrategy = new SearchStrategy(new SelectBest(), new AcceptNewIfBetterThanWorst(1));
RuinAndRecreateModule radialModule = new RuinAndRecreateModule("radialRuin_bestInsertion", bestInsertion, radial);
radialStrategy.addModule(radialModule);
SearchStrategyManager strategyManager = new SearchStrategyManager();
strategyManager.addStrategy(radialStrategy, 0.5);
strategyManager.addStrategy(randomStrategy, 0.5);
vra = new VehicleRoutingAlgorithm(vrp, strategyManager);
vra.getAlgorithmListeners().addListener(new StateUpdates.ResetStateManager(stateManager));
final IterateRouteForwardInTime iterateForward = new IterateRouteForwardInTime(vrp.getTransportCosts());
iterateForward.addListener(new UpdateActivityTimes());
iterateForward.addListener(new UpdateEarliestStartTimeWindowAtActLocations(stateManager));
iterateForward.addListener(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
iterateForward.addListener(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager));
iterateForward.addListener(new StateUpdates.UpdateLoadAtActivityLevel(stateManager));
final IterateRouteBackwardInTime iterateBackward = new IterateRouteBackwardInTime(vrp.getTransportCosts());
iterateBackward.addListener(new UpdateLatestOperationStartTimeAtActLocations(stateManager));
iterateBackward.addListener(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager));
InsertionStartsListener loadVehicleInDepot = new InsertionStartsListener() {
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
int loadAtDepot = 0;
int loadAtEnd = 0;
for(Job j : route.getTourActivities().getJobs()){
if(j instanceof Delivery){
loadAtDepot += j.getCapacityDemand();
}
if(j instanceof Pickup){
loadAtEnd += j.getCapacityDemand();
}
}
stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot));
stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd));
iterateForward.iterate(route);
iterateBackward.iterate(route);
}
}
};
vra.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(fleetManager));
JobInsertedListener updateLoadAfterJobHasBeenInserted = new JobInsertedListener() {
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
// log.info("insert job " + job2insert.getClass().toString() + " job " + job2insert + "" + job2insert.getCapacityDemand() + " in route " + inRoute.getTourActivities());
if(job2insert instanceof Delivery){
int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble();
// log.info("loadAtDepot="+loadAtDepot);
stateManager.putRouteState(inRoute, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot + job2insert.getCapacityDemand()));
}
if(job2insert instanceof Pickup){
int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD).toDouble();
// log.info("loadAtEnd="+loadAtEnd);
stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand()));
}
iterateForward.iterate(inRoute);
iterateBackward.iterate(inRoute);
}
};
bestInsertion.addListener(loadVehicleInDepot);
bestInsertion.addListener(updateLoadAfterJobHasBeenInserted);
VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion).createInitialSolution(vrp);
// System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size());
vra.addInitialSolution(iniSolution);
vra.setNuOfIterations(10000);
vra.setPrematureBreak(1000);
}
@Test
public void test(){
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
// System.out.println(Solutions.getBest(solutions).getCost());
// new VrpXMLWriter(vrp, solutions).write("output/pd_solomon_r101.xml");
}
}

View file

@ -33,6 +33,7 @@ import org.junit.Test;
import util.Coordinate;
import util.ManhattanDistanceCalculator;
import util.RouteUtils;
import algorithms.StateUpdates.UpdateStates;
import basics.Job;
import basics.Service;
import basics.VehicleRoutingProblem;
@ -151,7 +152,7 @@ public class GendreauPostOptTest {
activityCosts = new ExampleActivityCostFunction();
CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, new MarginalsCalculusTriangleInequality(cost, activityCosts, new HardConstraints.HardTimeWindowConstraint(states)), new HardConstraints.HardLoadConstraint(states));
CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, new MarginalsCalculusTriangleInequality(cost, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, cost)), new HardConstraints.HardLoadConstraint(states));
CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states);
withFixCost.setWeightOfFixCost(1.2);

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import static org.junit.Assert.*;

View file

@ -32,17 +32,18 @@ import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import algorithms.StateUpdates.UpdateStates;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DriverImpl;
import basics.route.DriverImpl.NoDriver;
import basics.route.ServiceActivity;
import basics.route.TimeWindow;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.DriverImpl.NoDriver;
@ -156,7 +157,7 @@ public class TestCalculatesServiceInsertion {
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
serviceInsertion = new CalculatesServiceInsertion(costs, new MarginalsCalculusTriangleInequality(costs, activityCosts, new HardConstraints.HardTimeWindowConstraint(states)), new HardConstraints.HardLoadConstraint(states));
serviceInsertion = new CalculatesServiceInsertion(costs, new MarginalsCalculusTriangleInequality(costs, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, costs)), new HardConstraints.HardLoadConstraint(states));
stateUpdater = new UpdateStates(states, costs, activityCosts);

View file

@ -34,18 +34,19 @@ import org.junit.Test;
import util.Coordinate;
import util.ManhattanDistanceCalculator;
import algorithms.StateUpdates.UpdateStates;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.DriverImpl;
import basics.route.DriverImpl.NoDriver;
import basics.route.ServiceActivity;
import basics.route.TimeWindow;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.DriverImpl.NoDriver;

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import static org.junit.Assert.assertEquals;
@ -10,6 +30,10 @@ import org.junit.Test;
import util.Coordinate;
import util.ManhattanDistanceCalculator;
import algorithms.StateUpdates.UpdateActivityTimes;
import algorithms.StateUpdates.UpdateCostsAtAllLevels;
import algorithms.StateUpdates.UpdateEarliestStartTimeWindowAtActLocations;
import algorithms.StateUpdates.UpdateLoadAtAllLevels;
import basics.Job;
import basics.Service;
import basics.costs.DefaultVehicleRoutingActivityCosts;
@ -34,10 +58,6 @@ public class TestIterateRouteForwardInTime {
TourActivities anotherTour;
RouteStates states;
private VehicleRoute vehicleRoute;
private VehicleRoutingTransportCosts cost;
@ -46,6 +66,8 @@ public class TestIterateRouteForwardInTime {
ServiceActivity secondAct;
StateManagerImpl stateManager;
@Before
public void setUp(){
cost = new VehicleRoutingTransportCosts() {
@ -99,6 +121,8 @@ public class TestIterateRouteForwardInTime {
tour.addActivity(secondAct);
vehicleRoute = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),vehicle);
stateManager = new StateManagerImpl();
}
@Test
@ -129,12 +153,11 @@ public class TestIterateRouteForwardInTime {
@Test
public void whenIteratingWithLoadUpdateAtActLocations_itShouldUpdateLoad() {
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StateManagerImpl states = new StateManagerImpl();
forwardInTime.addListener(new UpdateLoadAtAllLevels(states));
forwardInTime.addListener(new UpdateLoadAtAllLevels(stateManager));
forwardInTime.iterate(vehicleRoute);
assertEquals(5.0, states.getActivityStates(firstAct).getState(StateTypes.LOAD).toDouble(), 0.01);
assertEquals(10.0, states.getActivityStates(secondAct).getState(StateTypes.LOAD).toDouble(), 0.01);
assertEquals(5.0, stateManager.getActivityState(firstAct,StateTypes.LOAD).toDouble(), 0.01);
assertEquals(10.0, stateManager.getActivityState(secondAct,StateTypes.LOAD).toDouble(), 0.01);
}
@ -153,42 +176,41 @@ public class TestIterateRouteForwardInTime {
@Test
public void testStatesOfAct1(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StateManagerImpl states = new StateManagerImpl();
forwardInTime.addListener(new UpdateLoadAtAllLevels(states));
forwardInTime.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states));
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, states));
forwardInTime.addListener(new UpdateLoadAtAllLevels(stateManager));
forwardInTime.addListener(new UpdateEarliestStartTimeWindowAtActLocations(stateManager));
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager));
forwardInTime.iterate(vehicleRoute);
assertEquals(10.0, states.getActivityStates(firstAct).getState(StateTypes.COSTS).toDouble(),0.05);
assertEquals(5.0, states.getActivityStates(firstAct).getState(StateTypes.LOAD).toDouble(),0.05);
assertEquals(10.0, states.getActivityStates(firstAct).getState(StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
assertEquals(10.0, stateManager.getActivityState(firstAct, StateTypes.COSTS).toDouble(),0.05);
assertEquals(5.0, stateManager.getActivityState(firstAct, StateTypes.LOAD).toDouble(),0.05);
assertEquals(10.0, stateManager.getActivityState(firstAct, StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
// assertEquals(20.0, states.getState(tour.getActivities().get(0)).getLatestOperationStart(),0.05);
}
@Test
public void testStatesOfAct2(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StateManagerImpl states = new StateManagerImpl();
forwardInTime.addListener(new UpdateLoadAtAllLevels(states));
forwardInTime.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states));
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, states));
forwardInTime.addListener(new UpdateLoadAtAllLevels(stateManager));
forwardInTime.addListener(new UpdateEarliestStartTimeWindowAtActLocations(stateManager));
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager));
forwardInTime.iterate(vehicleRoute);
assertEquals(30.0, states.getActivityStates(secondAct).getState(StateTypes.COSTS).toDouble(),0.05);
assertEquals(10.0, states.getActivityStates(secondAct).getState(StateTypes.LOAD).toDouble(),0.05);
assertEquals(30.0, states.getActivityStates(secondAct).getState(StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
assertEquals(30.0, stateManager.getActivityState(secondAct, StateTypes.COSTS).toDouble(),0.05);
assertEquals(10.0, stateManager.getActivityState(secondAct, StateTypes.LOAD).toDouble(),0.05);
assertEquals(30.0, stateManager.getActivityState(secondAct, StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05);
// assertEquals(40.0, states.getState(tour.getActivities().get(1)).getLatestOperationStart(),0.05);
}
@Test
public void testStatesOfAct3(){
IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost);
StateManagerImpl states = new StateManagerImpl();
forwardInTime.addListener(new UpdateActivityTimes());
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, states));
forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager));
forwardInTime.iterate(vehicleRoute);
assertEquals(40.0, states.getRouteStates(vehicleRoute).getState(StateTypes.COSTS).toDouble(), 0.05);
assertEquals(40.0, stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble(), 0.05);
assertEquals(40.0, vehicleRoute.getEnd().getArrTime(),0.05);
assertEquals(50.0, vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime(),0.05);
}

View file

@ -1,3 +1,23 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
import org.junit.Test;

View file

@ -27,6 +27,7 @@ import org.junit.Test;
import util.Coordinate;
import util.ManhattanDistanceCalculator;
import algorithms.StateUpdates.UpdateStates;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
@ -38,7 +39,6 @@ import basics.route.TourActivities;
import basics.route.Vehicle;
import basics.route.VehicleImpl;
import basics.route.VehicleRoute;
import basics.route.VehicleType;
import basics.route.VehicleTypeImpl;

View file

@ -125,7 +125,7 @@ public class VrpReaderV2Test {
new VrpXMLReader(builder, null).read(inFileName);
VehicleRoutingProblem vrp = builder.build();
Service s1 = (Service) vrp.getJobs().get("1");
assertEquals("delivery",s1.getType());
assertEquals("service",s1.getType());
assertEquals(1,s1.getCapacityDemand());
assertEquals(0.0,s1.getServiceDuration(),0.01);
assertEquals(2, vrp.getJobs().size());

View file

@ -130,8 +130,8 @@ public class VrpWriterV2Test {
builder.addVehicle(v1);
builder.addVehicle(v2);
Service s1 = Service.Builder.newInstance("1", 1).setLocationId("loc").setName("delivery").setServiceTime(2.0).build();
Service s2 = Service.Builder.newInstance("2", 1).setLocationId("loc2").setName("delivery").setServiceTime(4.0).build();
Service s1 = Service.Builder.newInstance("1", 1).setLocationId("loc").setServiceTime(2.0).build();
Service s2 = Service.Builder.newInstance("2", 1).setLocationId("loc2").setServiceTime(4.0).build();
VehicleRoutingProblem vrp = builder.addService(s1).addService(s2).build();
new VrpXMLWriter(vrp, null).write(infileName);
@ -144,7 +144,7 @@ public class VrpWriterV2Test {
Service s1_read = (Service) vrp.getJobs().get("1");
assertEquals("1", s1_read.getId());
assertEquals("loc", s1_read.getLocationId());
assertEquals("delivery", s1_read.getType());
assertEquals("service", s1_read.getType());
assertEquals(2.0,s1_read.getServiceDuration(),0.01);
}
@ -162,8 +162,8 @@ public class VrpWriterV2Test {
builder.addVehicle(v1);
builder.addVehicle(v2);
Service s1 = Service.Builder.newInstance("1", 1).setLocationId("loc").setName("delivery").setServiceTime(2.0).build();
Service s2 = Service.Builder.newInstance("2", 1).setLocationId("loc2").setName("delivery").setServiceTime(4.0).build();
Service s1 = Service.Builder.newInstance("1", 1).setLocationId("loc").setServiceTime(2.0).build();
Service s2 = Service.Builder.newInstance("2", 1).setLocationId("loc2").setServiceTime(4.0).build();
builder.addService(s1).addService(s2);
VehicleRoutingProblem vrp = builder.build();

View file

@ -20,8 +20,6 @@
******************************************************************************/
package basics.io;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -31,19 +29,15 @@ import org.junit.Test;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.Service.Builder;
import basics.VehicleRoutingProblem.FleetComposition;
import basics.VehicleRoutingProblem.FleetSize;
import basics.io.VrpXMLReader;
import basics.io.VrpXMLWriter;
import basics.VehicleRoutingProblemSolution;
import basics.route.End;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.Vehicle;
import basics.route.VehicleImpl;
import basics.route.VehicleRoute;
import basics.route.VehicleType;
import basics.route.VehicleTypeImpl;
public class VrpWriterV3Test {
@ -69,8 +63,8 @@ public class VrpWriterV3Test {
builder.addVehicle(v1);
builder.addVehicle(v2);
Service s1 = Service.Builder.newInstance("1", 1).setLocationId("loc").setName("delivery").setServiceTime(2.0).build();
Service s2 = Service.Builder.newInstance("2", 1).setLocationId("loc2").setName("delivery").setServiceTime(4.0).build();
Service s1 = Service.Builder.newInstance("1", 1).setLocationId("loc").setServiceTime(2.0).build();
Service s2 = Service.Builder.newInstance("2", 1).setLocationId("loc2").setServiceTime(4.0).build();
builder.addService(s1).addService(s2);
VehicleRoutingProblem vrp = builder.build();

View file

@ -75,7 +75,7 @@
</vehicleTypes>
<services>
<service id="1" type="delivery">
<service id="1" type="service">
<locationId>j(1,5)</locationId>
<coord x="10.0" y="10.0"/>
<capacity-demand>1</capacity-demand>
@ -88,7 +88,7 @@
</timeWindows>
</service>
<service id="2" type="delivery">
<service id="2" type="service">
<locationId>i(3,9)</locationId>
<coord x="10.0" y="10.0"/>
<capacity-demand>1</capacity-demand>

View file

@ -50,7 +50,7 @@
</type>
</vehicleTypes>
<services>
<service id="2" type="delivery">
<service id="2" type="service">
<locationId>loc2</locationId>
<capacity-demand>1</capacity-demand>
<duration>4.0</duration>
@ -61,7 +61,7 @@
</timeWindow>
</timeWindows>
</service>
<service id="1" type="delivery">
<service id="1" type="service">
<locationId>loc</locationId>
<capacity-demand>1</capacity-demand>
<duration>2.0</duration>
@ -82,12 +82,12 @@
<driverId>noDriver</driverId>
<vehicleId>v1</vehicleId>
<start>10.0</start>
<act type="delivery">
<act type="service">
<serviceId>1</serviceId>
<arrTime>20.0</arrTime>
<endTime>30.0</endTime>
</act>
<act type="delivery">
<act type="service">
<serviceId>2</serviceId>
<arrTime>40.0</arrTime>
<endTime>80.0</endTime>

View file

@ -0,0 +1,635 @@
<?xml version="1.0" encoding="UTF-8"?>
<problem xmlns="http://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com vrp_xml_schema.xsd">
<problemType>
<fleetSize>INFINITE</fleetSize>
<fleetComposition>HOMOGENEOUS</fleetComposition>
</problemType>
<vehicles>
<vehicle>
<id>christophidesVehicle</id>
<typeId>christophidesType</typeId>
<location>
<id>[x=30.0][y=40.0]</id>
<coord x="30.0" y="40.0"/>
</location>
<timeSchedule>
<start>0.0</start>
<end>999999.0</end>
</timeSchedule>
</vehicle>
</vehicles>
<vehicleTypes>
<type>
<id>christophidesType</id>
<capacity>50</capacity>
<costs>
<fixed>0.0</fixed>
<distance>1.0</distance>
<time>0.0</time>
</costs>
</type>
</vehicleTypes>
<services>
<service id="35" type="delivery">
<locationId>[x=62.0][y=63.0]</locationId>
<coord x="62.0" y="63.0"/>
<capacity-demand>17</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="36" type="pickup">
<locationId>[x=63.0][y=69.0]</locationId>
<coord x="63.0" y="69.0"/>
<capacity-demand>6</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="33" type="pickup">
<locationId>[x=46.0][y=10.0]</locationId>
<coord x="46.0" y="10.0"/>
<capacity-demand>23</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="34" type="pickup">
<locationId>[x=61.0][y=33.0]</locationId>
<coord x="61.0" y="33.0"/>
<capacity-demand>26</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="39" type="pickup">
<locationId>[x=59.0][y=15.0]</locationId>
<coord x="59.0" y="15.0"/>
<capacity-demand>14</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="37" type="delivery">
<locationId>[x=32.0][y=22.0]</locationId>
<coord x="32.0" y="22.0"/>
<capacity-demand>9</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="38" type="delivery">
<locationId>[x=45.0][y=35.0]</locationId>
<coord x="45.0" y="35.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="43" type="delivery">
<locationId>[x=5.0][y=64.0]</locationId>
<coord x="5.0" y="64.0"/>
<capacity-demand>11</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="42" type="delivery">
<locationId>[x=21.0][y=10.0]</locationId>
<coord x="21.0" y="10.0"/>
<capacity-demand>13</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="41" type="delivery">
<locationId>[x=10.0][y=17.0]</locationId>
<coord x="10.0" y="17.0"/>
<capacity-demand>27</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="40" type="delivery">
<locationId>[x=5.0][y=6.0]</locationId>
<coord x="5.0" y="6.0"/>
<capacity-demand>7</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="22" type="pickup">
<locationId>[x=42.0][y=57.0]</locationId>
<coord x="42.0" y="57.0"/>
<capacity-demand>8</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="23" type="delivery">
<locationId>[x=16.0][y=57.0]</locationId>
<coord x="16.0" y="57.0"/>
<capacity-demand>16</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="24" type="delivery">
<locationId>[x=8.0][y=52.0]</locationId>
<coord x="8.0" y="52.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="25" type="pickup">
<locationId>[x=7.0][y=38.0]</locationId>
<coord x="7.0" y="38.0"/>
<capacity-demand>28</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="26" type="delivery">
<locationId>[x=27.0][y=68.0]</locationId>
<coord x="27.0" y="68.0"/>
<capacity-demand>7</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="27" type="pickup">
<locationId>[x=30.0][y=48.0]</locationId>
<coord x="30.0" y="48.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="28" type="pickup">
<locationId>[x=43.0][y=67.0]</locationId>
<coord x="43.0" y="67.0"/>
<capacity-demand>14</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="29" type="delivery">
<locationId>[x=58.0][y=48.0]</locationId>
<coord x="58.0" y="48.0"/>
<capacity-demand>6</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="3" type="delivery">
<locationId>[x=52.0][y=64.0]</locationId>
<coord x="52.0" y="64.0"/>
<capacity-demand>16</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="2" type="delivery">
<locationId>[x=49.0][y=49.0]</locationId>
<coord x="49.0" y="49.0"/>
<capacity-demand>30</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="1" type="delivery">
<locationId>[x=37.0][y=52.0]</locationId>
<coord x="37.0" y="52.0"/>
<capacity-demand>7</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="7" type="pickup">
<locationId>[x=17.0][y=63.0]</locationId>
<coord x="17.0" y="63.0"/>
<capacity-demand>19</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="30" type="delivery">
<locationId>[x=58.0][y=27.0]</locationId>
<coord x="58.0" y="27.0"/>
<capacity-demand>19</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="6" type="pickup">
<locationId>[x=21.0][y=47.0]</locationId>
<coord x="21.0" y="47.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="5" type="delivery">
<locationId>[x=40.0][y=30.0]</locationId>
<coord x="40.0" y="30.0"/>
<capacity-demand>21</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="32" type="pickup">
<locationId>[x=38.0][y=46.0]</locationId>
<coord x="38.0" y="46.0"/>
<capacity-demand>12</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="4" type="delivery">
<locationId>[x=20.0][y=26.0]</locationId>
<coord x="20.0" y="26.0"/>
<capacity-demand>9</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="31" type="delivery">
<locationId>[x=37.0][y=69.0]</locationId>
<coord x="37.0" y="69.0"/>
<capacity-demand>11</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="9" type="pickup">
<locationId>[x=52.0][y=33.0]</locationId>
<coord x="52.0" y="33.0"/>
<capacity-demand>11</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="8" type="pickup">
<locationId>[x=31.0][y=62.0]</locationId>
<coord x="31.0" y="62.0"/>
<capacity-demand>23</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="19" type="delivery">
<locationId>[x=13.0][y=13.0]</locationId>
<coord x="13.0" y="13.0"/>
<capacity-demand>9</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="17" type="pickup">
<locationId>[x=27.0][y=23.0]</locationId>
<coord x="27.0" y="23.0"/>
<capacity-demand>3</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="18" type="delivery">
<locationId>[x=17.0][y=33.0]</locationId>
<coord x="17.0" y="33.0"/>
<capacity-demand>41</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="15" type="pickup">
<locationId>[x=36.0][y=16.0]</locationId>
<coord x="36.0" y="16.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="16" type="delivery">
<locationId>[x=52.0][y=41.0]</locationId>
<coord x="52.0" y="41.0"/>
<capacity-demand>15</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="13" type="delivery">
<locationId>[x=5.0][y=25.0]</locationId>
<coord x="5.0" y="25.0"/>
<capacity-demand>23</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="14" type="pickup">
<locationId>[x=12.0][y=42.0]</locationId>
<coord x="12.0" y="42.0"/>
<capacity-demand>21</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="11" type="delivery">
<locationId>[x=42.0][y=41.0]</locationId>
<coord x="42.0" y="41.0"/>
<capacity-demand>19</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="12" type="pickup">
<locationId>[x=31.0][y=32.0]</locationId>
<coord x="31.0" y="32.0"/>
<capacity-demand>29</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="21" type="delivery">
<locationId>[x=62.0][y=42.0]</locationId>
<coord x="62.0" y="42.0"/>
<capacity-demand>8</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="20" type="delivery">
<locationId>[x=57.0][y=58.0]</locationId>
<coord x="57.0" y="58.0"/>
<capacity-demand>28</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="49" type="pickup">
<locationId>[x=48.0][y=28.0]</locationId>
<coord x="48.0" y="28.0"/>
<capacity-demand>18</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="48" type="pickup">
<locationId>[x=25.0][y=55.0]</locationId>
<coord x="25.0" y="55.0"/>
<capacity-demand>17</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="45" type="pickup">
<locationId>[x=39.0][y=10.0]</locationId>
<coord x="39.0" y="10.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="44" type="pickup">
<locationId>[x=30.0][y=15.0]</locationId>
<coord x="30.0" y="15.0"/>
<capacity-demand>16</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="47" type="pickup">
<locationId>[x=25.0][y=32.0]</locationId>
<coord x="25.0" y="32.0"/>
<capacity-demand>25</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="46" type="pickup">
<locationId>[x=32.0][y=39.0]</locationId>
<coord x="32.0" y="39.0"/>
<capacity-demand>5</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="10" type="delivery">
<locationId>[x=51.0][y=21.0]</locationId>
<coord x="51.0" y="21.0"/>
<capacity-demand>5</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="50" type="pickup">
<locationId>[x=56.0][y=37.0]</locationId>
<coord x="56.0" y="37.0"/>
<capacity-demand>10</capacity-demand>
<duration>0.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
</services>
</problem>

File diff suppressed because it is too large Load diff