From 2abf5f5c9da930139be271cbca22fe9076ca3acc Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Wed, 3 Sep 2014 08:32:27 +0200 Subject: [PATCH] add MultipleProductsWithLoadConstraint example --- jsprit-examples/input/algorithmConfig.xml | 21 +- ...ipleProductsWithLoadConstraintExample.java | 195 ++++++++++++++++++ pom.xml | 21 +- 3 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 jsprit-examples/src/main/java/jsprit/examples/MultipleProductsWithLoadConstraintExample.java diff --git a/jsprit-examples/input/algorithmConfig.xml b/jsprit-examples/input/algorithmConfig.xml index f12d94cb..3d82d3a7 100755 --- a/jsprit-examples/input/algorithmConfig.xml +++ b/jsprit-examples/input/algorithmConfig.xml @@ -1,5 +1,22 @@ + + @@ -23,7 +40,7 @@ - 0.4 + 0.5 @@ -39,7 +56,7 @@ - 0.2 + 0.3 diff --git a/jsprit-examples/src/main/java/jsprit/examples/MultipleProductsWithLoadConstraintExample.java b/jsprit-examples/src/main/java/jsprit/examples/MultipleProductsWithLoadConstraintExample.java new file mode 100644 index 00000000..15ecb612 --- /dev/null +++ b/jsprit-examples/src/main/java/jsprit/examples/MultipleProductsWithLoadConstraintExample.java @@ -0,0 +1,195 @@ +/******************************************************************************* + * 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 . + ******************************************************************************/ + +package jsprit.examples; + +import jsprit.analysis.toolbox.GraphStreamViewer; +import jsprit.core.algorithm.VehicleRoutingAlgorithm; +import jsprit.core.algorithm.VehicleRoutingAlgorithmBuilder; +import jsprit.core.algorithm.state.InternalStates; +import jsprit.core.algorithm.state.StateManager; +import jsprit.core.problem.Capacity; +import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.constraint.ConstraintManager; +import jsprit.core.problem.constraint.HardActivityStateLevelConstraint; +import jsprit.core.problem.job.Shipment; +import jsprit.core.problem.misc.JobInsertionContext; +import jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import jsprit.core.problem.solution.route.activity.TourActivity; +import jsprit.core.problem.vehicle.VehicleImpl; +import jsprit.core.problem.vehicle.VehicleType; +import jsprit.core.problem.vehicle.VehicleTypeImpl; +import jsprit.core.reporting.SolutionPrinter; +import jsprit.core.util.Coordinate; +import jsprit.core.util.Solutions; + +import java.util.Collection; + +//import jsprit.core.problem.solution.route.state.StateFactory; //v1.3.1 + +public class MultipleProductsWithLoadConstraintExample { + + static final int BANANAS_DIMENSION_INDEX = 0; + + static final int APPLES_DIMENSION_INDEX = 1; + + static class BananasFirst implements HardActivityStateLevelConstraint { + + @Override + public ConstraintsStatus fulfilled(JobInsertionContext jobInsertionContext, TourActivity prevActivity, TourActivity newActivity, TourActivity nextActivity, double departureTimeAtPrevActivity) { + if(isBananaPickup(newActivity) && isApplePickup(prevActivity)) return ConstraintsStatus.NOT_FULFILLED_BREAK; + if(isBananaPickup(nextActivity) && isApplePickup(newActivity)) return ConstraintsStatus.NOT_FULFILLED; + return ConstraintsStatus.FULFILLED; + } + + private boolean isApplePickup(TourActivity act){ + return act.getSize().get(APPLES_DIMENSION_INDEX) > 0; + } + + private boolean isBananaPickup(TourActivity act){ + return act.getSize().get(BANANAS_DIMENSION_INDEX) > 0; + } + } + + static class NoBananasANDApplesConstraint implements HardActivityStateLevelConstraint { + + private StateManager stateManager; + + NoBananasANDApplesConstraint(StateManager stateManager) { + this.stateManager = stateManager; + } + + @Override + public ConstraintsStatus fulfilled(JobInsertionContext jobInsertionContext, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double departureTimeAtPrevAct) { + Capacity loadAtPrevAct = getLoadAtPreviousAct(prevAct); + + if( isPickup(newAct) ){ + if( ( isApplePickup(newAct) && hasBananasInVehicle(loadAtPrevAct) ) || + ( isBananaPickup(newAct) && hasApplesInVehicle(loadAtPrevAct) ) ){ + return ConstraintsStatus.NOT_FULFILLED; + } + if( ( isApplePickup(newAct) && isBananaPickup(nextAct) ) || + ( isBananaPickup(newAct) && isApplePickup(nextAct) ) ){ + return ConstraintsStatus.NOT_FULFILLED; + } + return ConstraintsStatus.FULFILLED; + } + + if( isDelivery(newAct) ){ + if( ( isAppleDelivery(newAct) && hasBananasInVehicle(loadAtPrevAct) ) || + ( isBananaDelivery(newAct) && hasApplesInVehicle(loadAtPrevAct) ) ){ + return ConstraintsStatus.NOT_FULFILLED_BREAK; // if so constraint is broken forever -> break here + } + return ConstraintsStatus.FULFILLED; + } + throw new IllegalStateException("can only constraint shipments"); + } + + private boolean hasApplesInVehicle(Capacity loadAtPrevAct) { + return loadAtPrevAct.get(APPLES_DIMENSION_INDEX) > 0; + } + + private boolean hasBananasInVehicle(Capacity loadAtPrevAct){ + return loadAtPrevAct.get(BANANAS_DIMENSION_INDEX) > 0; + } + + private boolean isBananaPickup(TourActivity act){ + return act.getSize().get(BANANAS_DIMENSION_INDEX) > 0; + } + + private boolean isBananaDelivery(TourActivity act){ + return act.getSize().get(BANANAS_DIMENSION_INDEX) < 0; + } + + private boolean isApplePickup(TourActivity act){ + return act.getSize().get(APPLES_DIMENSION_INDEX) > 0; + } + + private boolean isAppleDelivery(TourActivity act){ + return act.getSize().get(APPLES_DIMENSION_INDEX) < 0; + } + + private boolean isPickup(TourActivity newAct) { + return newAct.getName().equals("pickupShipment"); + } + + private boolean isDelivery(TourActivity newAct) { + return newAct.getName().equals("deliverShipment"); + } + + private Capacity getLoadAtPreviousAct(TourActivity prevAct) { +// Capacity prevLoad = stateManager.getActivityState(prevAct, StateFactory.LOAD, Capacity.class); //v1.3.1 + Capacity prevLoad = stateManager.getActivityState(prevAct, InternalStates.LOAD, Capacity.class); //1.3.2-SNAPSHOT & upcoming release v1.4 + if(prevLoad != null) return prevLoad; + else return Capacity.Builder.newInstance().build(); + } + } + + + + public static void main(String[] args) { + + + VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(BANANAS_DIMENSION_INDEX,10) + .addCapacityDimension(APPLES_DIMENSION_INDEX, 20).build(); + VehicleImpl vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocationCoordinate(Coordinate.newInstance(0, 0)) + .setType(type).build(); + + Shipment bananas = Shipment.Builder.newInstance("bananas_1").addSizeDimension(BANANAS_DIMENSION_INDEX,1) + .setPickupCoord(Coordinate.newInstance(1, 8)).setDeliveryCoord(Coordinate.newInstance(10, 8)).build(); + + Shipment bananas_2 = Shipment.Builder.newInstance("bananas_2").addSizeDimension(BANANAS_DIMENSION_INDEX,1) + .setPickupCoord(Coordinate.newInstance(2, 8)).setDeliveryCoord(Coordinate.newInstance(11, 8)).build(); + + Shipment bananas_3 = Shipment.Builder.newInstance("bananas_3").addSizeDimension(BANANAS_DIMENSION_INDEX,1) + .setPickupCoord(Coordinate.newInstance(3, 8)).setDeliveryCoord(Coordinate.newInstance(12, 8)).build(); + + Shipment apples = Shipment.Builder.newInstance("apples_1").addSizeDimension(APPLES_DIMENSION_INDEX,1) + .setPickupCoord(Coordinate.newInstance(1, 6)).setDeliveryCoord(Coordinate.newInstance(10, 12)).build(); + + Shipment apples_2 = Shipment.Builder.newInstance("apples_2").addSizeDimension(APPLES_DIMENSION_INDEX,1) + .setPickupCoord(Coordinate.newInstance(1, 5)).setDeliveryCoord(Coordinate.newInstance(10, 11)).build(); + + VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().setFleetSize(VehicleRoutingProblem.FleetSize.INFINITE) + .addVehicle(vehicle) + .addJob(bananas).addJob(apples).addJob(bananas_2).addJob(bananas_3).addJob(apples_2).build(); + + VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(vrp,"input/algorithmConfig.xml"); + vraBuilder.addCoreConstraints(); + vraBuilder.addDefaultCostCalculators(); + + StateManager stateManager = new StateManager(vrp); //1.3.2-SNAPSHOT & upcoming release v1.4 +// StateManager stateManager = new StateManager(vrp.getTransportCosts()); //v1.3.1 + + ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager); + constraintManager.addConstraint(new NoBananasANDApplesConstraint(stateManager), ConstraintManager.Priority.CRITICAL); +// constraintManager.addConstraint(new BananasFirst(),ConstraintManager.Priority.CRITICAL); + + vraBuilder.setStateAndConstraintManager(stateManager,constraintManager); + VehicleRoutingAlgorithm vra = vraBuilder.build(); +// vra.setNuOfIterations(100); //1.3.2-SNAPSHOT +// vra.setMaxIterations(100); + + Collection solutions = vra.searchSolutions(); + + SolutionPrinter.print(vrp, Solutions.bestOf(solutions), SolutionPrinter.Print.VERBOSE); + + new GraphStreamViewer(vrp, Solutions.bestOf(solutions)).labelWith(GraphStreamViewer.Label.ID).setRenderShipments(true).display(); + + + } +} diff --git a/pom.xml b/pom.xml index c754a71f..6e4648aa 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,21 @@ + + 4.0.0 @@ -238,7 +255,8 @@ v@{project.version} - + + @@ -251,6 +269,7 @@ maven-javadoc-plugin 2.9.1 +