From a0419ab3fdab6f297bb51598bbdac18ec6d90432 Mon Sep 17 00:00:00 2001 From: oblonski Date: Wed, 4 Feb 2015 08:46:31 +0100 Subject: [PATCH] bugfix #146 --- .../algorithm/PrettyAlgorithmBuilder.java | 16 +++++- .../io/VehicleRoutingAlgorithms.java | 29 +++++----- ...alyzeInsertionCostsWithPenaltyVehicle.java | 53 ------------------- .../recreate/ShipmentInsertionCalculator.java | 1 + ...VehicleDependentTimeWindowConstraints.java | 18 +++++-- .../java/jsprit/core/algorithm/PDTW_IT.java | 50 ++++++++++++++--- 6 files changed, 85 insertions(+), 82 deletions(-) delete mode 100644 jsprit-core/src/main/java/jsprit/core/algorithm/recreate/PenalyzeInsertionCostsWithPenaltyVehicle.java diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/PrettyAlgorithmBuilder.java b/jsprit-core/src/main/java/jsprit/core/algorithm/PrettyAlgorithmBuilder.java index 618e6fe4..55313c14 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/PrettyAlgorithmBuilder.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/PrettyAlgorithmBuilder.java @@ -30,10 +30,13 @@ import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.vehicle.Vehicle; import jsprit.core.problem.vehicle.VehicleFleetManager; +import jsprit.core.problem.vehicle.VehicleTypeKey; import jsprit.core.util.ActivityTimeTracker; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; /** * Created by schroeder on 10.12.14. @@ -88,11 +91,20 @@ public class PrettyAlgorithmBuilder { stateManager.updateTimeWindowStates(); UpdateVehicleDependentPracticalTimeWindows tw_updater = new UpdateVehicleDependentPracticalTimeWindows(stateManager, vrp.getTransportCosts()); tw_updater.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() { + + Map uniqueTypes = new HashMap(); + @Override public Collection get(VehicleRoute vehicleRoute) { + if(uniqueTypes.isEmpty()){ + for( Vehicle v : vrp.getVehicles()){ + if(!uniqueTypes.containsKey(v.getVehicleTypeIdentifier())){ + uniqueTypes.put(v.getVehicleTypeIdentifier(),v); + } + } + } Collection vehicles = new ArrayList(); - vehicles.add(vehicleRoute.getVehicle()); - vehicles.addAll(fleetManager.getAvailableVehicles(vehicleRoute.getVehicle())); + vehicles.addAll(uniqueTypes.values()); return vehicles; } }); diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java b/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java index f215f8bc..816329db 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java @@ -48,10 +48,7 @@ import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.activity.End; import jsprit.core.problem.solution.route.activity.ReverseActivityVisitor; import jsprit.core.problem.solution.route.activity.TourActivity; -import jsprit.core.problem.vehicle.FiniteFleetManagerFactory; -import jsprit.core.problem.vehicle.InfiniteFleetManagerFactory; -import jsprit.core.problem.vehicle.Vehicle; -import jsprit.core.problem.vehicle.VehicleFleetManager; +import jsprit.core.problem.vehicle.*; import jsprit.core.util.ActivityTimeTracker; import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.configuration.XMLConfiguration; @@ -549,17 +546,21 @@ public class VehicleRoutingAlgorithms { if(stateManager.timeWindowUpdateIsActivated()){ UpdateVehicleDependentPracticalTimeWindows timeWindowUpdater = new UpdateVehicleDependentPracticalTimeWindows(stateManager,vrp.getTransportCosts()); timeWindowUpdater.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() { + Map uniqueTypes = new HashMap(); - @Override - public Collection get(VehicleRoute route) { - Collection vehicles = new ArrayList(); - vehicles.add(route.getVehicle()); - if(switchAllowed) { - vehicles.addAll(vehicleFleetManager.getAvailableVehicles(route.getVehicle())); - } - return vehicles; - } - + @Override + public Collection get(VehicleRoute vehicleRoute) { + if(uniqueTypes.isEmpty()){ + for( Vehicle v : vrp.getVehicles()){ + if(!uniqueTypes.containsKey(v.getVehicleTypeIdentifier())){ + uniqueTypes.put(v.getVehicleTypeIdentifier(),v); + } + } + } + Collection vehicles = new ArrayList(); + vehicles.addAll(uniqueTypes.values()); + return vehicles; + } }); stateManager.addStateUpdater(timeWindowUpdater); activityPolicy = ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS; diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/PenalyzeInsertionCostsWithPenaltyVehicle.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/PenalyzeInsertionCostsWithPenaltyVehicle.java deleted file mode 100644 index 90b40c05..00000000 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/PenalyzeInsertionCostsWithPenaltyVehicle.java +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 Stefan Schroeder. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - * - * Contributors: - * Stefan Schroeder - initial API and implementation - ******************************************************************************/ -package jsprit.core.algorithm.recreate; - -import jsprit.core.problem.driver.Driver; -import jsprit.core.problem.job.Job; -import jsprit.core.problem.solution.route.VehicleRoute; -import jsprit.core.problem.vehicle.PenaltyVehicleType; -import jsprit.core.problem.vehicle.Vehicle; - -class PenalyzeInsertionCostsWithPenaltyVehicle implements JobInsertionCostsCalculator{ - - JobInsertionCostsCalculator base; - - public PenalyzeInsertionCostsWithPenaltyVehicle(JobInsertionCostsCalculator baseInsertionCostsCalculator) { - super(); - this.base = baseInsertionCostsCalculator; - } - - @Override - public InsertionData getInsertionData(VehicleRoute currentRoute,Job newJob, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownCosts) { - if(newVehicle.getType() instanceof PenaltyVehicleType){ - if(currentRoute.getVehicle().getType() instanceof PenaltyVehicleType){ - InsertionData iData = base.getInsertionData(currentRoute, newJob, newVehicle, newVehicleDepartureTime, newDriver, bestKnownCosts); - double penaltyC = iData.getInsertionCost()*((PenaltyVehicleType)newVehicle.getType()).getPenaltyFactor(); - InsertionData newData = new InsertionData(penaltyC, iData.getPickupInsertionIndex(), iData.getDeliveryInsertionIndex(), iData.getSelectedVehicle(), iData.getSelectedDriver()); - newData.setAdditionalTime(iData.getAdditionalTime()); - newData.setVehicleDepartureTime(iData.getVehicleDepartureTime()); - return newData; - } - } - return base.getInsertionData(currentRoute, newJob, newVehicle, newVehicleDepartureTime, newDriver, bestKnownCosts); - } - - - -} diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/ShipmentInsertionCalculator.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/ShipmentInsertionCalculator.java index 2ebe4eb2..b80ee1ca 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/ShipmentInsertionCalculator.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/ShipmentInsertionCalculator.java @@ -137,6 +137,7 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{ } double additionalPickupICosts = softActivityConstraint.getCosts(insertionContext, prevAct, pickupShipment, activities.get(i), prevActEndTime); double pickupAIC = calculate(insertionContext,prevAct,pickupShipment,activities.get(i),prevActEndTime); + TourActivity prevAct_deliveryLoop = pickupShipment; double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocation(), pickupShipment.getLocation(), prevActEndTime, newDriver, newVehicle); double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment); diff --git a/jsprit-core/src/main/java/jsprit/core/problem/constraint/VehicleDependentTimeWindowConstraints.java b/jsprit-core/src/main/java/jsprit/core/problem/constraint/VehicleDependentTimeWindowConstraints.java index 2a3251d1..b4ba95a7 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/constraint/VehicleDependentTimeWindowConstraints.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/constraint/VehicleDependentTimeWindowConstraints.java @@ -62,8 +62,11 @@ public class VehicleDependentTimeWindowConstraints implements HardActivityConstr latestArrTimeAtNextAct = states.getActivityState(nextAct, iFacts.getNewVehicle(), InternalStates.LATEST_OPERATION_START_TIME ,Double.class); // if(latestArrTimeAtNextAct == null) //try to get latest_operation_start_time of currVehicle // latestArrTimeAtNextAct = states.getActivityState(nextAct, iFacts.getRoute().getVehicle(), StateFactory.LATEST_OPERATION_START_TIME ,Double.class); - if(latestArrTimeAtNextAct == null) //otherwise set it to theoretical_latest_operation_startTime - latestArrTimeAtNextAct=nextAct.getTheoreticalLatestOperationStartTime(); + if(latestArrTimeAtNextAct == null) {//otherwise set it to theoretical_latest_operation_startTime + latestArrTimeAtNextAct = nextAct.getTheoreticalLatestOperationStartTime(); +// throw new IllegalStateException("this is strange and should not be"); + //ToDo here, there should be another solution + } nextActLocation = nextAct.getLocation(); } @@ -99,6 +102,7 @@ public class VehicleDependentTimeWindowConstraints implements HardActivityConstr if(arrTimeAtNextOnDirectRouteWithNewVehicle > latestArrTimeAtNextAct){ return ConstraintsStatus.NOT_FULFILLED_BREAK; } + /* * |--- newAct ---| * |--- nextAct ---| @@ -109,9 +113,13 @@ public class VehicleDependentTimeWindowConstraints implements HardActivityConstr // log.info("check insertion of " + newAct + " between " + prevAct + " and " + nextAct + ". prevActDepTime=" + prevActDepTime); double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocation(), newAct.getLocation(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); double endTimeAtNewAct = CalculationUtils.getActivityEndTime(arrTimeAtNewAct, newAct); - double latestArrTimeAtNewAct = Math.min(newAct.getTheoreticalLatestOperationStartTime(),latestArrTimeAtNextAct - routingCosts.getBackwardTransportTime(newAct.getLocation(),nextActLocation, - latestArrTimeAtNextAct,iFacts.getNewDriver(),iFacts.getNewVehicle())); - + double latestArrTimeAtNewAct = + Math.min(newAct.getTheoreticalLatestOperationStartTime(), + latestArrTimeAtNextAct - + routingCosts.getBackwardTransportTime(newAct.getLocation(),nextActLocation,latestArrTimeAtNextAct,iFacts.getNewDriver(),iFacts.getNewVehicle()) + - newAct.getOperationTime() + ); +//ToDo: SUSPICIOUS - hier muss noch operation time weg /* * |--- prevAct ---| * |--- vehicle's arrival @newAct diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/PDTW_IT.java b/jsprit-core/src/test/java/jsprit/core/algorithm/PDTW_IT.java index 637d895d..06163bff 100644 --- a/jsprit-core/src/test/java/jsprit/core/algorithm/PDTW_IT.java +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/PDTW_IT.java @@ -2,9 +2,11 @@ package jsprit.core.algorithm; import jsprit.core.algorithm.box.SchrimpfFactory; +import jsprit.core.problem.AbstractJob; import jsprit.core.problem.Location; import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.VehicleRoutingProblem.FleetSize; +import jsprit.core.problem.job.Service; import jsprit.core.problem.job.Shipment; import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.route.VehicleRoute; @@ -14,7 +16,6 @@ import jsprit.core.problem.vehicle.VehicleImpl; import jsprit.core.problem.vehicle.VehicleImpl.Builder; import jsprit.core.problem.vehicle.VehicleType; import jsprit.core.problem.vehicle.VehicleTypeImpl; -import jsprit.core.reporting.SolutionPrinter; import jsprit.core.util.Coordinate; import jsprit.core.util.Solutions; import org.junit.Test; @@ -27,26 +28,52 @@ import static org.junit.Assert.assertFalse; public class PDTW_IT { - int nShipments = 200; - int nVehicles = 15; + int nJobs = 200; + int nVehicles = 40; Random random = new Random(1623); int nextShipmentId=1; int nextVehicleId=1; @Test - public void timeWindowsShouldNOTbeBroken() { - + public void whenDealingWithShipments_timeWindowsShouldNOTbeBroken() { VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); for(int i =0 ; i < nVehicles ; i++){ vrpBuilder.addVehicle(createVehicle()); } - for(int i =0 ; i < nShipments ;i++){ + for(int i =0 ; i < nJobs;i++){ vrpBuilder.addJob(createShipment()); } vrpBuilder.setFleetSize(FleetSize.FINITE); VehicleRoutingProblem problem = vrpBuilder.build(); VehicleRoutingAlgorithm algorithm = new SchrimpfFactory().createAlgorithm(problem); - algorithm.setMaxIterations(10); + algorithm.setMaxIterations(0); + Collection solutions = algorithm.searchSolutions(); + VehicleRoutingProblemSolution bestSolution = Solutions.bestOf(solutions); + + for(VehicleRoute route : bestSolution.getRoutes()){ + Vehicle v = route.getVehicle(); + for(TourActivity ta : route.getActivities()){ + if(ta.getArrTime() > v.getLatestArrival() * 1.00001){ + assertFalse(true); + } + } + } + } + + + @Test + public void whenDealingWithServices_timeWindowsShouldNOTbeBroken() { + VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); + for(int i =0 ; i < nVehicles ; i++){ + vrpBuilder.addVehicle(createVehicle()); + } + for(int i =0 ; i < nJobs;i++){ + vrpBuilder.addJob(createService()); + } + vrpBuilder.setFleetSize(FleetSize.FINITE); + VehicleRoutingProblem problem = vrpBuilder.build(); + VehicleRoutingAlgorithm algorithm = new SchrimpfFactory().createAlgorithm(problem); + algorithm.setMaxIterations(100); Collection solutions = algorithm.searchSolutions(); VehicleRoutingProblemSolution bestSolution = Solutions.bestOf(solutions); @@ -58,13 +85,20 @@ public class PDTW_IT { } } } + } - SolutionPrinter.print(bestSolution); + private AbstractJob createService() { + Service.Builder b = Service.Builder.newInstance(Integer.toString(nextShipmentId++)); + b.addSizeDimension(0, 1); + b.setServiceTime(random.nextDouble() * 5); + b.setLocation(createLocation()); + return b.build(); } private Location createLocation(){ return loc(new Coordinate(50*random.nextDouble(), 50*random.nextDouble())); } + private Shipment createShipment(){ Shipment.Builder b = Shipment.Builder.newInstance(Integer.toString(nextShipmentId++)); b.addSizeDimension(0, 1);