mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
internal experiments with serviceInsertion
This commit is contained in:
parent
c60ab8afd0
commit
922f360fe4
12 changed files with 200 additions and 328 deletions
|
|
@ -15,11 +15,9 @@ package algorithms;
|
|||
import org.apache.log4j.Logger;
|
||||
|
||||
import util.Neighborhood;
|
||||
import algorithms.StateManager.State;
|
||||
import algorithms.HardConstraints.HardRouteLevelConstraint;
|
||||
import basics.Job;
|
||||
import basics.Service;
|
||||
import basics.costs.VehicleRoutingActivityCosts;
|
||||
import basics.costs.VehicleRoutingTransportCosts;
|
||||
import basics.route.Driver;
|
||||
import basics.route.End;
|
||||
import basics.route.ServiceActivity;
|
||||
|
|
@ -34,25 +32,36 @@ import basics.route.VehicleRoute;
|
|||
|
||||
final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
||||
|
||||
static class Break {
|
||||
private Marginals marginals;
|
||||
private boolean breakLoop;
|
||||
public Break(Marginals marginals, boolean breakLoop) {
|
||||
super();
|
||||
this.marginals = marginals;
|
||||
this.breakLoop = breakLoop;
|
||||
}
|
||||
/**
|
||||
* @return the marginals
|
||||
*/
|
||||
public Marginals getMarginals() {
|
||||
return marginals;
|
||||
}
|
||||
/**
|
||||
* @return the breakLoop
|
||||
*/
|
||||
public boolean isBreakLoop() {
|
||||
return breakLoop;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertion.class);
|
||||
|
||||
private StateManager states;
|
||||
|
||||
private VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
private VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
private Start start;
|
||||
|
||||
private End end;
|
||||
|
||||
private HardConstraint hardConstraint = new HardConstraint() {
|
||||
|
||||
@Override
|
||||
public boolean fulfilled(InsertionScenario iScenario) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
private HardRouteLevelConstraint hardRouteLevelConstraint;
|
||||
|
||||
private Neighborhood neighborhood = new Neighborhood() {
|
||||
|
||||
|
|
@ -62,24 +71,17 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
|||
}
|
||||
};
|
||||
|
||||
void setHardConstraint(HardConstraint hardConstraint){
|
||||
this.hardConstraint = hardConstraint;
|
||||
}
|
||||
private MarginalsCalculus marginalCalculus;
|
||||
|
||||
public void setNeighborhood(Neighborhood neighborhood) {
|
||||
this.neighborhood = neighborhood;
|
||||
logger.info("initialise neighborhood " + neighborhood);
|
||||
}
|
||||
|
||||
|
||||
public void setStates(StateManager activityStates2){
|
||||
this.states = activityStates2;
|
||||
}
|
||||
|
||||
public CalculatesServiceInsertion(VehicleRoutingTransportCosts vehicleRoutingTransportCosts, VehicleRoutingActivityCosts vehicleRoutingActivityCosts) {
|
||||
public CalculatesServiceInsertion(MarginalsCalculus marginalsCalculus, HardRouteLevelConstraint hardRouteLevelConstraint) {
|
||||
super();
|
||||
this.routingCosts = vehicleRoutingTransportCosts;
|
||||
this.activityCosts = vehicleRoutingActivityCosts;
|
||||
this.marginalCalculus = marginalsCalculus;
|
||||
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
|
||||
logger.info("initialise " + this);
|
||||
}
|
||||
|
||||
|
|
@ -99,50 +101,48 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
|||
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
|
||||
|
||||
InsertionFacts iFacts = new InsertionFacts(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
|
||||
if(!hardConstraint.fulfilled(new InsertionScenario(iFacts, null))){
|
||||
if(!hardRouteLevelConstraint.fulfilled(new InsertionScenario(iFacts, null))){
|
||||
return InsertionData.noInsertionFound();
|
||||
}
|
||||
|
||||
TourActivities tour = currentRoute.getTourActivities();
|
||||
double bestCost = bestKnownCosts;
|
||||
Marginals bestMarginals = null;
|
||||
Service service = (Service)jobToInsert;
|
||||
|
||||
int insertionIndex = InsertionData.NO_INDEX;
|
||||
|
||||
TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service);
|
||||
|
||||
initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);
|
||||
|
||||
TourActivity prevAct = start;
|
||||
double prevCostInOriginalTour = 0.0;
|
||||
int actIndex = 0;
|
||||
// logger.debug(prevAct.toString());
|
||||
|
||||
for(TourActivity nextAct : tour.getActivities()){
|
||||
// logger.debug(prevAct.toString() + " arrTime=" + prevAct.getArrTime() + " endTime=" + prevAct.getEndTime());
|
||||
// logger.debug(deliveryAct2Insert.toString() + " arrTime=" + deliveryAct2Insert.getArrTime() + " endTime=" + deliveryAct2Insert.getEndTime());
|
||||
// logger.debug(nextAct.toString() + " arrTime=" + nextAct.getArrTime() + " endTime=" + nextAct.getEndTime());
|
||||
double nextCostInOriginalTour = states.getActivityState(nextAct,StateTypes.COSTS).toDouble();
|
||||
if(deliveryAct2Insert.getTheoreticalLatestOperationStartTime() < prevAct.getTheoreticalEarliestOperationStartTime()){
|
||||
break;
|
||||
}
|
||||
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
|
||||
double mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle, bestCost, nextCostInOriginalTour - prevCostInOriginalTour);
|
||||
if(mc < bestCost){
|
||||
bestCost = mc;
|
||||
insertionIndex = actIndex;
|
||||
Marginals mc = calculate(iFacts, prevAct, nextAct, deliveryAct2Insert);
|
||||
if(mc != null){
|
||||
if(mc.getAdditionalCosts() < bestCost){
|
||||
bestCost = mc.getAdditionalCosts();
|
||||
bestMarginals = mc;
|
||||
insertionIndex = actIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
prevCostInOriginalTour = nextCostInOriginalTour;
|
||||
prevAct = nextAct;
|
||||
actIndex++;
|
||||
}
|
||||
End nextAct = end;
|
||||
// logger.debug(prevAct.toString() + " arrTime=" + prevAct.getArrTime() + " endTime=" + prevAct.getEndTime());
|
||||
// logger.debug(deliveryAct2Insert.toString() + " arrTime=" + deliveryAct2Insert.getArrTime() + " endTime=" + deliveryAct2Insert.getEndTime());
|
||||
// logger.debug(nextAct.toString() + " arrTime=" + nextAct.getArrTime() + " endTime=" + nextAct.getEndTime());
|
||||
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
|
||||
double oldRouteCosts = states.getRouteState(currentRoute, StateTypes.COSTS).toDouble();
|
||||
double mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle, bestCost, oldRouteCosts - prevCostInOriginalTour);
|
||||
if(mc < bestCost){
|
||||
bestCost = mc;
|
||||
insertionIndex = actIndex;
|
||||
Marginals mc = calculate(iFacts, prevAct, nextAct, deliveryAct2Insert);
|
||||
if(mc != null) {
|
||||
if(mc.getAdditionalCosts() < bestCost){
|
||||
bestCost = mc.getAdditionalCosts();
|
||||
bestMarginals = mc;
|
||||
insertionIndex = actIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -151,6 +151,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
|||
}
|
||||
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
|
||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
insertionData.setAdditionalTime(bestMarginals.getAdditionalTime());
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
|
|
@ -177,47 +178,8 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
|||
}
|
||||
}
|
||||
|
||||
public double calculate(TourActivity prevAct, TourActivity nextAct, TourActivity newAct, Driver driver, Vehicle vehicle, double bestKnownCosts, double costWithoutNewJob) {
|
||||
|
||||
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle);
|
||||
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle);
|
||||
|
||||
double newAct_arrTime = prevAct.getEndTime() + tp_time_prevAct_newAct;
|
||||
double newAct_operationStartTime = Math.max(newAct_arrTime, newAct.getTheoreticalEarliestOperationStartTime());
|
||||
|
||||
double newAct_endTime = newAct_operationStartTime + newAct.getOperationTime();
|
||||
|
||||
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, driver, vehicle);
|
||||
|
||||
// if((tp_costs_prevAct_newAct + act_costs_newAct - costWithoutNewJob) > bestKnownCosts){
|
||||
// return Double.MAX_VALUE;
|
||||
// }
|
||||
|
||||
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle);
|
||||
double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle);
|
||||
|
||||
double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct;
|
||||
double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, driver, vehicle);
|
||||
|
||||
// logger.debug("nextActArrTime="+nextAct_arrTime);
|
||||
|
||||
double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct;
|
||||
|
||||
if(totalCosts - costWithoutNewJob > bestKnownCosts){
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
if(nextAct_arrTime > getLatestOperationStart(nextAct)){
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
return totalCosts - costWithoutNewJob;
|
||||
|
||||
}
|
||||
|
||||
private double getLatestOperationStart(TourActivity act) {
|
||||
if(act instanceof End) {
|
||||
return end.getTheoreticalLatestOperationStartTime();
|
||||
}
|
||||
return states.getActivityState(act, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
|
||||
public Marginals calculate(InsertionFacts iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct) {
|
||||
return marginalCalculus.calculate(iFacts, prevAct, nextAct, newAct);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,208 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Stefan Schroeder.
|
||||
* eMail: stefan.schroeder@kit.edu
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Public License v2.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* Stefan Schroeder - initial API and implementation
|
||||
******************************************************************************/
|
||||
package algorithms;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import util.Neighborhood;
|
||||
|
||||
import algorithms.RouteStates.ActivityState;
|
||||
import algorithms.StateManager.State;
|
||||
import algorithms.StateManager.States;
|
||||
import basics.Job;
|
||||
import basics.Service;
|
||||
import basics.costs.VehicleRoutingActivityCosts;
|
||||
import basics.costs.VehicleRoutingTransportCosts;
|
||||
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.Vehicle;
|
||||
import basics.route.VehicleRoute;
|
||||
import basics.route.VehicleImpl.NoVehicle;
|
||||
|
||||
|
||||
|
||||
final class CalculatesServiceInsertionWithTriangleInequality implements JobInsertionCalculator{
|
||||
|
||||
class Marginals {
|
||||
private double marginalCosts;
|
||||
private double marginalTime;
|
||||
public Marginals(double marginalCosts, double marginalTime) {
|
||||
super();
|
||||
this.marginalCosts = marginalCosts;
|
||||
this.marginalTime = marginalTime;
|
||||
}
|
||||
/**
|
||||
* @return the marginalCosts
|
||||
*/
|
||||
public double getMarginalCosts() {
|
||||
return marginalCosts;
|
||||
}
|
||||
/**
|
||||
* @return the marginalTime
|
||||
*/
|
||||
public double getMarginalTime() {
|
||||
return marginalTime;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionWithTriangleInequality.class);
|
||||
|
||||
private StateManager routeStates;
|
||||
|
||||
private VehicleRoutingTransportCosts routingCosts;
|
||||
|
||||
private Start start;
|
||||
|
||||
private End end;
|
||||
|
||||
private HardConstraint hardConstraint = new HardConstraint() {
|
||||
|
||||
@Override
|
||||
public boolean fulfilled(InsertionScenario iScenario) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
public void setHardConstraint(HardConstraint hardConstraint){
|
||||
this.hardConstraint = hardConstraint;
|
||||
}
|
||||
|
||||
private Neighborhood neighborhood = new Neighborhood() {
|
||||
|
||||
@Override
|
||||
public boolean areNeighbors(String location1, String location2) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
public void setNeighborhood(Neighborhood neighborhood) {
|
||||
this.neighborhood = neighborhood;
|
||||
logger.info("initialise neighborhood " + neighborhood);
|
||||
}
|
||||
|
||||
public void setActivityStates(StateManager activityStates2){
|
||||
this.routeStates = activityStates2;
|
||||
}
|
||||
|
||||
public CalculatesServiceInsertionWithTriangleInequality(VehicleRoutingTransportCosts vehicleRoutingTransportCosts, VehicleRoutingActivityCosts vehicleRoutingActivityCosts) {
|
||||
super();
|
||||
this.routingCosts = vehicleRoutingTransportCosts;
|
||||
logger.info("initialise " + this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertion]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the marginal cost of inserting job i locally. This is based on the
|
||||
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
|
||||
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
|
||||
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
|
||||
|
||||
TourActivities tour = currentRoute.getTourActivities();
|
||||
Marginals bestMarginals = new Marginals(bestKnownCosts,Double.MAX_VALUE);
|
||||
Service service = (Service)jobToInsert;
|
||||
|
||||
if(getCurrentLoad(currentRoute) + service.getCapacityDemand() > newVehicle.getCapacity()){
|
||||
return InsertionData.noInsertionFound();
|
||||
}
|
||||
int insertionIndex = InsertionData.NO_INDEX;
|
||||
|
||||
TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service);
|
||||
|
||||
initialiseStartAndEnd(newVehicle, newVehicleDepartureTime);
|
||||
|
||||
TourActivity prevAct = start;
|
||||
int actIndex = 0;
|
||||
for(TourActivity nextAct : tour.getActivities()){
|
||||
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
|
||||
Marginals mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle);
|
||||
if(mc.getMarginalCosts() < bestMarginals.getMarginalCosts()){
|
||||
bestMarginals = mc;
|
||||
insertionIndex = actIndex;
|
||||
}
|
||||
}
|
||||
prevAct = nextAct;
|
||||
actIndex++;
|
||||
}
|
||||
End nextAct = end;
|
||||
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
|
||||
Marginals mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle);
|
||||
if(mc.getMarginalCosts() < bestMarginals.getMarginalCosts()){
|
||||
bestMarginals = mc;
|
||||
insertionIndex = actIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if(insertionIndex == InsertionData.NO_INDEX) {
|
||||
return InsertionData.noInsertionFound();
|
||||
}
|
||||
InsertionData insertionData = new InsertionData(bestMarginals.getMarginalCosts(), InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
|
||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
insertionData.setAdditionalTime(bestMarginals.getMarginalTime());
|
||||
return insertionData;
|
||||
}
|
||||
|
||||
private int getCurrentLoad(VehicleRoute currentRoute) {
|
||||
return (int) routeStates.getRouteState(currentRoute, StateTypes.LOAD).toDouble();
|
||||
}
|
||||
|
||||
private void initialiseStartAndEnd(final Vehicle newVehicle, double newVehicleDepartureTime) {
|
||||
if(start == null){
|
||||
start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
}
|
||||
else{
|
||||
start.setLocationId(newVehicle.getLocationId());
|
||||
start.setTheoreticalEarliestOperationStartTime(newVehicle.getEarliestDeparture());
|
||||
start.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival());
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
}
|
||||
|
||||
if(end == null){
|
||||
end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
|
||||
}
|
||||
else{
|
||||
end.setLocationId(newVehicle.getLocationId());
|
||||
end.setTheoreticalEarliestOperationStartTime(newVehicleDepartureTime);
|
||||
end.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival());
|
||||
}
|
||||
}
|
||||
|
||||
public Marginals calculate(TourActivity prevAct, TourActivity nextAct, TourActivity newAct, Driver driver, Vehicle vehicle) {
|
||||
|
||||
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle);
|
||||
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle);
|
||||
|
||||
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle);
|
||||
double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle);
|
||||
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle);
|
||||
double tp_time_prevAct_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle);
|
||||
|
||||
return new Marginals(tp_costs_prevAct_newAct + tp_costs_newAct_nextAct - tp_costs_prevAct_nextAct, tp_time_prevAct_newAct + tp_time_newAct_nextAct - tp_time_prevAct_nextAct);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,18 +22,10 @@ package algorithms;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.configuration.XMLConfiguration;
|
||||
|
||||
import util.NeighborhoodImpl;
|
||||
|
||||
import basics.VehicleRoutingProblem;
|
||||
import basics.VehicleRoutingProblem.FleetComposition;
|
||||
import basics.algo.InsertionListener;
|
||||
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
||||
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
|
||||
import basics.costs.VehicleRoutingActivityCosts;
|
||||
|
||||
|
||||
|
||||
|
|
@ -222,11 +214,10 @@ class CalculatorBuilder {
|
|||
}
|
||||
|
||||
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager activityStates2){
|
||||
JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||
MarginalsCalculus defaultCalc = new MarginalsCalculusDefault(vrp.getTransportCosts(), vrp.getActivityCosts(), new HardConstraints.HardTimeWindowConstraint(activityStates2) );
|
||||
JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(defaultCalc, new HardConstraints.HardLoadConstraint(activityStates2));
|
||||
|
||||
((CalculatesServiceInsertion) standardServiceInsertion).setStates(activityStates2);
|
||||
((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
|
||||
((CalculatesServiceInsertion) standardServiceInsertion).setHardConstraint(new HardConstraints.HardLoadConstraint(activityStates2));
|
||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
|
||||
|
||||
return calcPlusListeners;
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
package algorithms;
|
||||
|
||||
interface HardConstraint {
|
||||
|
||||
public boolean fulfilled(InsertionScenario iScenario);
|
||||
|
||||
}
|
||||
|
|
@ -1,10 +1,23 @@
|
|||
package algorithms;
|
||||
|
||||
import basics.Service;
|
||||
import basics.route.TourActivity;
|
||||
|
||||
class HardConstraints {
|
||||
|
||||
static class HardLoadConstraint implements HardConstraint{
|
||||
interface HardRouteLevelConstraint {
|
||||
|
||||
public boolean fulfilled(InsertionScenario iScenario);
|
||||
|
||||
}
|
||||
|
||||
interface HardActivityLevelConstraint {
|
||||
|
||||
public boolean fulfilled(InsertionFacts iFacts, TourActivity act, double arrTime);
|
||||
|
||||
}
|
||||
|
||||
static class HardLoadConstraint implements HardRouteLevelConstraint{
|
||||
|
||||
private StateManager states;
|
||||
|
||||
|
|
@ -22,6 +35,24 @@ class HardConstraints {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class HardTimeWindowConstraint implements HardActivityLevelConstraint {
|
||||
|
||||
private StateManager states;
|
||||
|
||||
public HardTimeWindowConstraint(StateManager states) {
|
||||
super();
|
||||
this.states = states;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fulfilled(InsertionFacts iFacts, TourActivity act, double arrTime) {
|
||||
if(arrTime > states.getActivityState(act, StateTypes.LATEST_OPERATION_START_TIME).toDouble()){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
27
jsprit-core/src/main/java/algorithms/Marginals.java
Normal file
27
jsprit-core/src/main/java/algorithms/Marginals.java
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package algorithms;
|
||||
|
||||
class Marginals {
|
||||
|
||||
private double additionalCosts;
|
||||
private double additionalTime;
|
||||
public Marginals(double additionalCosts, double additionalTime) {
|
||||
super();
|
||||
this.additionalCosts = additionalCosts;
|
||||
this.additionalTime = additionalTime;
|
||||
}
|
||||
/**
|
||||
* @return the additionalCosts
|
||||
*/
|
||||
public double getAdditionalCosts() {
|
||||
return additionalCosts;
|
||||
}
|
||||
/**
|
||||
* @return the additionalTime
|
||||
*/
|
||||
public double getAdditionalTime() {
|
||||
return additionalTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package algorithms;
|
||||
|
||||
import basics.route.TourActivity;
|
||||
|
||||
interface MarginalsCalculus {
|
||||
|
||||
Marginals calculate(InsertionFacts iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package algorithms;
|
||||
|
||||
import algorithms.HardConstraints.HardActivityLevelConstraint;
|
||||
import basics.costs.VehicleRoutingActivityCosts;
|
||||
import basics.costs.VehicleRoutingTransportCosts;
|
||||
import basics.route.TourActivity;
|
||||
|
||||
class MarginalsCalculusDefault implements MarginalsCalculus{
|
||||
|
||||
private HardActivityLevelConstraint hardConstraint;
|
||||
|
||||
private VehicleRoutingTransportCosts routingCosts;
|
||||
private VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
public MarginalsCalculusDefault(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint) {
|
||||
super();
|
||||
this.routingCosts = routingCosts;
|
||||
this.activityCosts = actCosts;
|
||||
this.hardConstraint = hardActivityLevelConstraint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Marginals calculate(InsertionFacts iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct) {
|
||||
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
|
||||
double newAct_arrTime = prevAct.getEndTime() + tp_time_prevAct_newAct;
|
||||
|
||||
if(!hardConstraint.fulfilled(iFacts, newAct, newAct_arrTime)){
|
||||
return null;
|
||||
}
|
||||
|
||||
double newAct_operationStartTime = Math.max(newAct_arrTime, newAct.getTheoreticalEarliestOperationStartTime());
|
||||
|
||||
double newAct_endTime = newAct_operationStartTime + newAct.getOperationTime();
|
||||
|
||||
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
|
||||
double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
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;
|
||||
|
||||
double oldCosts;
|
||||
if(iFacts.getRoute().isEmpty()){
|
||||
oldCosts = 0.0;
|
||||
}
|
||||
else{
|
||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||
|
||||
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||
oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
|
||||
}
|
||||
|
||||
double additionalCosts = totalCosts - oldCosts;
|
||||
double additionalTime = nextAct_arrTime - nextAct.getArrTime();
|
||||
|
||||
return new Marginals(additionalCosts,additionalTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -151,8 +151,8 @@ public class GendreauPostOptTest {
|
|||
|
||||
activityCosts = new ExampleActivityCostFunction();
|
||||
|
||||
CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, activityCosts);
|
||||
standardServiceInsertion.setStates(states);
|
||||
CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(new MarginalsCalculusDefault(cost, activityCosts, new HardConstraints.HardTimeWindowConstraint(states)), new HardConstraints.HardLoadConstraint(states));
|
||||
|
||||
CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states);
|
||||
withFixCost.setWeightOfFixCost(1.2);
|
||||
|
||||
|
|
|
|||
|
|
@ -156,8 +156,7 @@ public class TestCalculatesServiceInsertion {
|
|||
|
||||
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
|
||||
|
||||
serviceInsertion = new CalculatesServiceInsertion(costs, activityCosts);
|
||||
serviceInsertion.setStates(states);
|
||||
serviceInsertion = new CalculatesServiceInsertion(new MarginalsCalculusDefault(costs, activityCosts, new HardConstraints.HardTimeWindowConstraint(states)), new HardConstraints.HardLoadConstraint(states));
|
||||
|
||||
stateUpdater = new UpdateStates(states, costs, activityCosts);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
<construction>
|
||||
<insertion name="bestInsertion">
|
||||
|
||||
</insertion>
|
||||
</construction>
|
||||
|
||||
|
|
|
|||
|
|
@ -24,19 +24,15 @@ import java.io.File;
|
|||
import java.util.Collection;
|
||||
|
||||
import readers.SolomonReader;
|
||||
import algorithms.GreedySchrimpfFactory;
|
||||
import algorithms.SchrimpfFactory;
|
||||
import algorithms.VehicleRoutingAlgorithms;
|
||||
import algorithms.selectors.SelectBest;
|
||||
import analysis.AlgorithmSearchProgressChartListener;
|
||||
import analysis.SolutionPlotter;
|
||||
import analysis.SolutionPrinter;
|
||||
import analysis.SolutionPrinter.Print;
|
||||
import analysis.StopWatch;
|
||||
import basics.VehicleRoutingAlgorithm;
|
||||
import basics.VehicleRoutingProblem;
|
||||
import basics.VehicleRoutingProblemSolution;
|
||||
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
|
||||
|
||||
public class SolomonExample {
|
||||
|
||||
|
|
@ -76,9 +72,10 @@ public class SolomonExample {
|
|||
*
|
||||
* The algorithm can be defined and configured in an xml-file.
|
||||
*/
|
||||
VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp);
|
||||
// VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_solomon.xml");
|
||||
vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png"));
|
||||
// VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp);
|
||||
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_solomon.xml");
|
||||
vra.setPrematureBreak(100);
|
||||
// vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png"));
|
||||
/*
|
||||
* Solve the problem.
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue