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 6b81a846..b46479d9 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 @@ -359,11 +359,11 @@ public class VehicleRoutingAlgorithms { private VehicleRoutingAlgorithms(){} /** - * Creates a {@link VehicleRoutingAlgorithm} from a AlgorithConfig based on the input vrp. + * Creates a {@link jsprit.core.algorithm.VehicleRoutingAlgorithm} from a AlgorithConfig based on the input vrp. * - * @param vrp - * @param algorithmConfig - * @return {@link VehicleRoutingAlgorithm} + * @param vrp the routing problem + * @param algorithmConfig the algorithm config + * @return {@link jsprit.core.algorithm.VehicleRoutingAlgorithm} */ public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp, final AlgorithmConfig algorithmConfig){ return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0, null); @@ -372,9 +372,9 @@ public class VehicleRoutingAlgorithms { /** * Read and creates a {@link VehicleRoutingAlgorithm} from an url. * - * @param vrp - * @param configURL - * @return {@link VehicleRoutingProblem} + * @param vrp the routing problem + * @param configURL config url + * @return {@link jsprit.core.algorithm.VehicleRoutingAlgorithm} */ public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final URL configURL){ AlgorithmConfig algorithmConfig = new AlgorithmConfig(); @@ -384,11 +384,11 @@ public class VehicleRoutingAlgorithms { } /** - * Read and creates {@link VehicleRoutingAlgorithm} from config-file. + * Read and creates {@link jsprit.core.problem.VehicleRoutingProblem} from config-file. * - * @param vrp - * @param configFileName - * @return + * @param vrp the routing problem + * @param configFileName the config filename (and location) + * @return {@link jsprit.core.algorithm.VehicleRoutingAlgorithm} */ public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final String configFileName){ AlgorithmConfig algorithmConfig = new AlgorithmConfig(); @@ -461,7 +461,7 @@ public class VehicleRoutingAlgorithms { } stateManager.updateLoadStates(); stateManager.updateTimeWindowStates(); - stateManager.updateSkillStates(); +// stateManager.updateSkillStates(); stateManager.addStateUpdater(new UpdateEndLocationIfRouteIsOpen()); stateManager.addStateUpdater(new OpenRouteStateVerifier()); stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts())); @@ -481,9 +481,6 @@ public class VehicleRoutingAlgorithms { public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, AlgorithmConfig config, int nuOfThreads, SolutionCostCalculator solutionCostCalculator, final StateManager stateManager, ConstraintManager constraintManager, boolean addDefaultCostCalculators) { -// AlgorithmConfig algorithmConfig = new AlgorithmConfig(); -// AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig); -// xmlReader.read(config); return readAndCreateAlgorithm(vrp, config.getXMLConfiguration(),nuOfThreads, solutionCostCalculator, stateManager, constraintManager, addDefaultCostCalculators); } @@ -881,49 +878,12 @@ public class VehicleRoutingAlgorithms { RuinAndRecreateModule rrModule = new RuinAndRecreateModule("ruin_and_recreate", final_insertion, ruin); return rrModule; } - if(moduleName.equals("gendreau")){ - throw new UnsupportedOperationException("gendreau is not supported yet"); -// int iterations = moduleConfig.getInt("iterations"); -// double share = moduleConfig.getDouble("share"); -// String ruinName = moduleConfig.getString("ruin[@name]"); -// if(ruinName == null) throw new IllegalStateException("gendreau.ruin[@name] is missing. set it to \"radialRuin\" or \"randomRuin\""); -// String ruinId = moduleConfig.getString("ruin[@id]"); -// if(ruinId == null) ruinId = "noId"; -// ModKey ruinKey = makeKey(ruinName,ruinId); -// RuinStrategyKey stratKey = new RuinStrategyKey(ruinKey); -// RuinStrategy ruin = definedClasses.get(stratKey); -// if(ruin == null){ -// ruin = new RadialRuinStrategyFactory(0.3, new AvgJobDistance(vrp.getTransportCosts())).createStrategy(vrp); -// definedClasses.put(stratKey, ruin); -// } -// -// String insertionName = moduleConfig.getString("insertion[@name]"); -// if(insertionName == null) throw new IllegalStateException("gendreau.insertion[@name] is missing. set it to \"regretInsertion\" or \"bestInsertion\""); -// String insertionId = moduleConfig.getString("insertion[@id]"); -// if(insertionId == null) insertionId = "noId"; -// ModKey insertionKey = makeKey(insertionName,insertionId); -// InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey); -// InsertionStrategy insertion = definedClasses.get(insertionStrategyKey); -// if(insertion == null){ -// List insertionConfigs = moduleConfig.configurationsAt("insertion"); -// if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1"); -// List prioListeners = new ArrayList(); -// insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads, constraintManager); -// algorithmListeners.addAll(prioListeners); -// } -// Gendreau gendreau = new Gendreau(vrp, ruin, insertion, vehicleFleetManager); -// gendreau.setShareOfJobsToRuin(share); -// gendreau.setNuOfIterations(iterations); -// definedClasses.put(strategyModuleKey, gendreau); -// return gendreau; - } throw new NullPointerException("no module found with moduleName=" + moduleName + "\n\tcheck config whether the correct names are used" + "\n\tcurrently there are following modules available: " + "\n\tbestInsertion" + "\n\trandomRuin" + - "\n\tradialRuin" + - "\n\tgendreauPostOpt"); + "\n\tradialRuin"); } private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) { diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/InternalStates.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/InternalStates.java index 36e4f8c3..66238f37 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/InternalStates.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/InternalStates.java @@ -43,5 +43,5 @@ public class InternalStates { public final static StateId PAST_MAXLOAD = new StateFactory.StateIdImpl("past_max_load", 9); - + public static final StateId SKILLS = new StateFactory.StateIdImpl("skills", 10); } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateFactory.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateFactory.java index fb3c95ec..0f17777f 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateFactory.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateFactory.java @@ -9,7 +9,7 @@ import java.util.List; class StateFactory { final static List reservedIds = Arrays.asList("max_load", "load", "costs", "load_at_beginning", "load_at_end", "duration", "latest_operation_start_time", "earliest_operation_start_time" - , "future_max_load", "past_max_load"); + , "future_max_load", "past_max_load", "skills"); static StateId createId(String name){ diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateManager.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateManager.java index d8e32454..ea7cc5b1 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateManager.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/StateManager.java @@ -22,7 +22,6 @@ import jsprit.core.algorithm.ruin.listener.RuinListener; import jsprit.core.algorithm.ruin.listener.RuinListeners; import jsprit.core.problem.Capacity; import jsprit.core.problem.VehicleRoutingProblem; -import jsprit.core.problem.cost.VehicleRoutingTransportCosts; import jsprit.core.problem.job.Job; import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.route.ReverseRouteActivityVisitor; @@ -93,18 +92,16 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart private Map defaultRouteStates_ = new HashMap(); private Map defaultActivityStates_ = new HashMap(); - - private VehicleRoutingTransportCosts routingCosts; - + private boolean updateLoad = false; private boolean updateTWs = false; - private int stateIndexCounter = 10; + private int stateIndexCounter = 21; private Map createdStateIds = new HashMap(); - private int initialNuStates = 20; + private int initialNuStates = 30; private int nuActivities; @@ -176,7 +173,6 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart * @param vehicleRoutingProblem the corresponding VehicleRoutingProblem */ public StateManager(VehicleRoutingProblem vehicleRoutingProblem){ - this.routingCosts = vehicleRoutingProblem.getTransportCosts(); this.vrp = vehicleRoutingProblem; nuActivities = Math.max(10, vrp.getNuActivities() + 1); nuVehicleTypeKeys = Math.max(3, getNuVehicleTypes(vrp) + 2); @@ -706,5 +702,12 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart return updateTWs; } + /** + * Updates skill states. + */ + public void updateSkillStates() { + addActivityVisitor(new UpdateSkills(this)); + } + } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateSkills.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateSkills.java index f49a3d92..940ebd05 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateSkills.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateSkills.java @@ -4,10 +4,9 @@ import jsprit.core.problem.Skills; import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.activity.ActivityVisitor; import jsprit.core.problem.solution.route.activity.TourActivity; -import jsprit.core.problem.solution.route.state.StateFactory; /** - * Created by schroeder on 01.07.14. + * Update to update required skills on route */ public class UpdateSkills implements StateUpdater, ActivityVisitor{ @@ -38,6 +37,6 @@ public class UpdateSkills implements StateUpdater, ActivityVisitor{ @Override public void finish() { Skills skills = skillBuilder.build(); - statesManager.putTypedInternalRouteState(route, StateFactory.SKILLS, Skills.class, skills); + statesManager.putTypedInternalRouteState(route, InternalStates.SKILLS, skills); } } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/Skills.java b/jsprit-core/src/main/java/jsprit/core/problem/Skills.java index 63aacf8d..5a5cf00e 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/Skills.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/Skills.java @@ -6,7 +6,7 @@ import java.util.HashSet; import java.util.Set; /** - * Created by schroeder on 01.07.14. + * Skill container managing skills */ public class Skills { @@ -15,7 +15,7 @@ public class Skills { /** * Returns new instance of skill-builder. * - * @return + * @return builder */ public static Builder newInstance(){ return new Builder(); @@ -26,19 +26,30 @@ public class Skills { /** * Adds skill. Skill is transformed into lowerCase. * - * @param skill - * @return + * @param skill skill to be added + * @return builder */ public Builder addSkill(String skill){ skills.add(skill.toLowerCase()); return this; } + /** + * Adds a collection of skills. + * + * @param skills collection of skills to be added + * @return builder + */ public Builder addAllSkills(Collection skills){ for(String skill : skills) this.skills.add(skill); return this; } + /** + * Builds the skill container and returns it. + * + * @return skills + */ public Skills build(){ return new Skills(this); } @@ -54,7 +65,7 @@ public class Skills { /** * Returns an unmodifiable set of skills. All skills are inLowerCase. * - * @return + * @return set of skills in this containter */ public Set values(){ return Collections.unmodifiableSet(skills); @@ -63,8 +74,8 @@ public class Skills { /** * Not case sensitive. * - * @param skill - * @return + * @param skill which is checked whether it is in skill container or not + * @return true if skill is included, false otherwise */ public boolean containsSkill(String skill){ return skills.contains(skill.toLowerCase()); diff --git a/jsprit-core/src/main/java/jsprit/core/problem/constraint/HardSkillConstraint.java b/jsprit-core/src/main/java/jsprit/core/problem/constraint/HardSkillConstraint.java index ded358bf..74db774b 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/constraint/HardSkillConstraint.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/constraint/HardSkillConstraint.java @@ -1,9 +1,9 @@ package jsprit.core.problem.constraint; +import jsprit.core.algorithm.state.InternalStates; import jsprit.core.problem.Skills; import jsprit.core.problem.misc.JobInsertionContext; import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter; -import jsprit.core.problem.solution.route.state.StateFactory; /** * SkillConstraint that ensures that only vehicles with according skills can serve route and job to be inserted. @@ -11,6 +11,8 @@ import jsprit.core.problem.solution.route.state.StateFactory; */ public class HardSkillConstraint implements HardRouteStateLevelConstraint{ + private static final Skills defaultSkills = Skills.Builder.newInstance().build(); + private RouteAndActivityStateGetter states; public HardSkillConstraint(RouteAndActivityStateGetter states) { @@ -24,7 +26,8 @@ public class HardSkillConstraint implements HardRouteStateLevelConstraint{ return false; } } - Skills requiredSkillsForRoute = states.getRouteState(insertionContext.getRoute(), StateFactory.SKILLS, Skills.class); + Skills requiredSkillsForRoute = states.getRouteState(insertionContext.getRoute(), InternalStates.SKILLS, Skills.class); + if(requiredSkillsForRoute == null) requiredSkillsForRoute = defaultSkills; for(String skill : requiredSkillsForRoute.values()){ if(!insertionContext.getNewVehicle().getSkills().containsSkill(skill)){ return false; diff --git a/jsprit-core/src/main/java/jsprit/core/problem/job/Delivery.java b/jsprit-core/src/main/java/jsprit/core/problem/job/Delivery.java index cf974113..6b069b5b 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/job/Delivery.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/job/Delivery.java @@ -30,24 +30,13 @@ public class Delivery extends Service{ /** * Returns a new instance of builder that builds a delivery. * - * @param id + * @param id the id of the delivery * @return the builder */ public static Builder newInstance(String id){ return new Builder(id); } - - /** - * Constructs the builder - * - * @param id - * @param size - * @throws IllegalArgumentException if size < 0 or id is null - */ - Builder(String id, int size) { - super(id, size); - } - + Builder(String id) { super(id); } @@ -56,7 +45,7 @@ public class Delivery extends Service{ * Builds Delivery. * * @return delivery - * @throw IllegalStateException if neither locationId nor coord is set + * @throws IllegalStateException if neither locationId nor coord is set */ public Delivery build(){ if(locationId == null) { @@ -65,16 +54,12 @@ public class Delivery extends Service{ } this.setType("delivery"); super.capacity = super.capacityBuilder.build(); + super.skills = super.skillBuilder.build(); return new Delivery(this); } } - - /** - * Constructs Delivery. - * - * @param builder - */ + Delivery(Builder builder) { super(builder); diff --git a/jsprit-core/src/main/java/jsprit/core/problem/job/Job.java b/jsprit-core/src/main/java/jsprit/core/problem/job/Job.java index 6d86fa0f..ba40b50e 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/job/Job.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/job/Job.java @@ -20,6 +20,7 @@ package jsprit.core.problem.job; import jsprit.core.problem.Capacity; import jsprit.core.problem.HasId; import jsprit.core.problem.HasIndex; +import jsprit.core.problem.Skills; /** * Basic interface for all jobs. @@ -42,5 +43,6 @@ public interface Job extends HasId, HasIndex { * @return Capacity */ public Capacity getSize(); - + + Skills getRequiredSkills(); } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/job/Pickup.java b/jsprit-core/src/main/java/jsprit/core/problem/job/Pickup.java index 261148b5..8efe2f04 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/job/Pickup.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/job/Pickup.java @@ -30,24 +30,13 @@ public class Pickup extends Service { /** * Returns a new instance of builder that builds a pickup. * - * @param id + * @param id the id of the pickup * @return the builder */ public static Builder newInstance(String id){ return new Builder(id); } - - /** - * Constructs the builder. - * - * @param id - * @param size - * @throws IllegalArgumentException if size < 0 or id is null - */ - Builder(String id, int size) { - super(id, size); - } - + Builder(String id) { super(id); } @@ -58,7 +47,7 @@ public class Pickup extends Service { *

Pickup type is "pickup" * * @return pickup - * @throw IllegalStateException if neither locationId nor coordinate has been set + * @throws IllegalStateException if neither locationId nor coordinate has been set */ public Pickup build(){ if(locationId == null) { @@ -67,16 +56,12 @@ public class Pickup extends Service { } this.setType("pickup"); super.capacity = super.capacityBuilder.build(); + super.skills = super.skillBuilder.build(); return new Pickup(this); } } - - /** - * Constructs the Pickup - * - * @param builder - */ + Pickup(Builder builder) { super(builder); } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java b/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java index b3f66328..c16d52c8 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/job/Service.java @@ -18,6 +18,7 @@ package jsprit.core.problem.job; import jsprit.core.problem.AbstractJob; import jsprit.core.problem.Capacity; +import jsprit.core.problem.Skills; import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.util.Coordinate; @@ -45,7 +46,7 @@ public class Service extends AbstractJob { /** * Returns a new instance of builder that builds a service. * - * @param id + * @param id the id of the service * @return the builder */ public static Builder newInstance(String id){ @@ -67,20 +68,11 @@ public class Service extends AbstractJob { protected Capacity.Builder capacityBuilder = Capacity.Builder.newInstance(); protected Capacity capacity; - - /** - * Constructs the builder. - * - * @param id - * @param size - * @throws IllegalArgumentException if size < 0 or id is null - */ - Builder(String id, int size) { - if(size < 0) throw new IllegalArgumentException("size must be greater than or equal to zero"); - if(id == null) throw new IllegalArgumentException("id must not be null"); - this.id = id; - } - + + protected Skills.Builder skillBuilder = Skills.Builder.newInstance(); + + protected Skills skills; + Builder(String id){ this.id = id; } @@ -90,7 +82,7 @@ public class Service extends AbstractJob { * *

Currently there are {@link Service}, {@link Pickup} and {@link Delivery}. * - * @param name + * @param name the name of service * @return the builder */ protected Builder setType(String name){ @@ -101,7 +93,7 @@ public class Service extends AbstractJob { /** * Sets the location-id of this service. * - * @param locationId + * @param locationId the location id of the service * @return builder */ public Builder setLocationId(String locationId){ @@ -112,7 +104,7 @@ public class Service extends AbstractJob { /** * Sets the coordinate of this service. * - * @param coord + * @param coord the coordinate of service * @return builder */ public Builder setCoord(Coordinate coord){ @@ -126,7 +118,7 @@ public class Service extends AbstractJob { *

It is understood as time that a service or its implied activity takes at the service-location, for instance * to unload goods. * - * @param serviceTime + * @param serviceTime the service time / duration of service to be set * @return builder * @throws IllegalArgumentException if serviceTime < 0 */ @@ -139,8 +131,8 @@ public class Service extends AbstractJob { /** * Adds capacity dimension. * - * @param dimensionIndex - * @param dimensionValue + * @param dimensionIndex the dimension index of the capacity value + * @param dimensionValue the capacity value * @return the builder * @throws IllegalArgumentException if dimensionValue < 0 */ @@ -155,9 +147,9 @@ public class Service extends AbstractJob { * *

The time-window indicates the time period a service/activity/operation is allowed to start. * - * @param tw + * @param tw the time-window to be set * @return builder - * @throw IllegalArgumentException if timeWindow is null + * @throws IllegalArgumentException if timeWindow is null */ public Builder setTimeWindow(TimeWindow tw){ if(tw == null) throw new IllegalArgumentException("time-window arg must not be null"); @@ -178,10 +170,15 @@ public class Service extends AbstractJob { } this.setType("service"); capacity = capacityBuilder.build(); + skills = skillBuilder.build(); return new Service(this); } - - } + + public Builder addSkill(String skill) { + skillBuilder.addSkill(skill); + return this; + } + } private final String id; @@ -198,6 +195,8 @@ public class Service extends AbstractJob { private final Capacity size; + private final Skills skills; + Service(Builder builder){ id = builder.id; locationId = builder.locationId; @@ -206,6 +205,7 @@ public class Service extends AbstractJob { timeWindow = builder.timeWindow; type = builder.type; size = builder.capacity; + skills = builder.skills; } @Override @@ -300,5 +300,10 @@ public class Service extends AbstractJob { public Capacity getSize() { return size; } - + + @Override + public Skills getRequiredSkills() { + return skills; + } + } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/job/Shipment.java b/jsprit-core/src/main/java/jsprit/core/problem/job/Shipment.java index 6a06db22..91be88db 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/job/Shipment.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/job/Shipment.java @@ -20,6 +20,7 @@ package jsprit.core.problem.job; import jsprit.core.problem.AbstractJob; import jsprit.core.problem.Capacity; +import jsprit.core.problem.Skills; import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.util.Coordinate; @@ -71,30 +72,21 @@ public class Shipment extends AbstractJob{ private Capacity.Builder capacityBuilder = Capacity.Builder.newInstance(); private Capacity capacity; - - /** + + private Skills.Builder skillBuilder = Skills.Builder.newInstance(); + + private Skills skills; + + /** * Returns new instance of this builder. * - * @param id - * @return + * @param id the id of the shipment which must be a unique identifier among all jobs + * @return the builder */ public static Builder newInstance(String id){ return new Builder(id); } - /** - * Constructs the builder - * - * @param id - * @param size - * @throws IllegalArgumentException if size < 0 or id is null - */ - Builder(String id, int size) { - if(size < 0) throw new IllegalArgumentException("size must be greater than or equal to zero"); - if(id == null) throw new IllegalArgumentException("id must not be null"); - this.id = id; - } - Builder(String id){ if(id == null) throw new IllegalArgumentException("id must not be null"); this.id = id; @@ -103,20 +95,20 @@ public class Shipment extends AbstractJob{ /** * Sets pickup-location. * - * @param pickupLocation + * @param pickupLocationId the location id of shipment's pickup * @return builder * @throws IllegalArgumentException if location is null */ - public Builder setPickupLocation(String pickupLocation){ - if(pickupLocation == null) throw new IllegalArgumentException("location must not be null"); - this.pickupLocation = pickupLocation; + public Builder setPickupLocation(String pickupLocationId){ + if(pickupLocationId == null) throw new IllegalArgumentException("location must not be null"); + this.pickupLocation = pickupLocationId; return this; } /** * Sets pickup-coordinate. * - * @param pickupCoord + * @param pickupCoord the coordinate of shipment's pickup location * @return builder * @throws IllegalArgumentException if pickupCoord is null */ @@ -131,7 +123,7 @@ public class Shipment extends AbstractJob{ * *

ServiceTime is intended to be the time the implied activity takes at the pickup-location. * - * @param serviceTime + * @param serviceTime the service time / duration the pickup of the associated shipment takes * @return builder * @throws IllegalArgumentException if servicTime < 0.0 */ @@ -143,11 +135,11 @@ public class Shipment extends AbstractJob{ /** * Sets the timeWindow for the pickup, i.e. the time-period in which a pickup operation is - * allowed to start. + * allowed to START. * *

By default timeWindow is [0.0, Double.MAX_VALUE} * - * @param timeWindow + * @param timeWindow the time window within the pickup operation/activity can START * @return builder * @throws IllegalArgumentException if timeWindow is null */ @@ -160,7 +152,7 @@ public class Shipment extends AbstractJob{ /** * Sets the delivery-location. * - * @param deliveryLocation + * @param deliveryLocation the delivery location id * @return builder * @throws IllegalArgumentException if location is null */ @@ -173,7 +165,7 @@ public class Shipment extends AbstractJob{ /** * Sets delivery-coord. * - * @param deliveryCoord + * @param deliveryCoord the coordinate of shipment's delivery location * @return builder * @throws IllegalArgumentException if coord is null; */ @@ -188,7 +180,7 @@ public class Shipment extends AbstractJob{ * *

ServiceTime is intended to be the time the implied activity takes at the delivery-location. * - * @param deliveryServiceTime + * @param deliveryServiceTime the service time / duration of shipment's delivery * @return builder * @throws IllegalArgumentException if serviceTime < 0.0 */ @@ -204,7 +196,7 @@ public class Shipment extends AbstractJob{ * *

By default timeWindow is [0.0, Double.MAX_VALUE} * - * @param timeWindow + * @param timeWindow the time window within the associated delivery is allowed to START * @return builder * @throws IllegalArgumentException if timeWindow is null */ @@ -217,8 +209,8 @@ public class Shipment extends AbstractJob{ /** * Adds capacity dimension. * - * @param dimensionIndex - * @param dimensionValue + * @param dimensionIndex the dimension index of the corresponding capacity value + * @param dimensionValue the capacity value * @return builder * @throws IllegalArgumentException if dimVal < 0 */ @@ -246,11 +238,16 @@ public class Shipment extends AbstractJob{ deliveryLocation = deliveryCoord.toString(); } capacity = capacityBuilder.build(); + skills = skillBuilder.build(); return new Shipment(this); } - - } + + public Builder addSkill(String skill) { + skillBuilder.addSkill(skill); + return this; + } + } private final String id; @@ -272,12 +269,8 @@ public class Shipment extends AbstractJob{ private final Capacity capacity; - - /** - * Constructs the shipment. - * - * @param builder - */ + private final Skills skills; + Shipment(Builder builder){ this.id = builder.id; this.pickupLocation = builder.pickupLocation; @@ -289,6 +282,7 @@ public class Shipment extends AbstractJob{ this.deliveryServiceTime = builder.deliveryServiceTime; this.deliveryTimeWindow = builder.deliveryTimeWindow; this.capacity = builder.capacity; + this.skills = builder.skills; } @Override @@ -405,5 +399,10 @@ public class Shipment extends AbstractJob{ return capacity; } - + @Override + public Skills getRequiredSkills() { + return skills; + } + + } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java index 4b5f9e34..1f46f93e 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/Vehicle.java @@ -18,6 +18,7 @@ package jsprit.core.problem.vehicle; import jsprit.core.problem.HasId; import jsprit.core.problem.HasIndex; +import jsprit.core.problem.Skills; import jsprit.core.util.Coordinate; /** @@ -86,4 +87,6 @@ public interface Vehicle extends HasId, HasIndex { public abstract Coordinate getEndLocationCoordinate(); public abstract VehicleTypeKey getVehicleTypeIdentifier(); + + public abstract Skills getSkills(); } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java index 875ae645..7f2f106c 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/vehicle/VehicleImpl.java @@ -17,6 +17,7 @@ package jsprit.core.problem.vehicle; import jsprit.core.problem.AbstractVehicle; +import jsprit.core.problem.Skills; import jsprit.core.util.Coordinate; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -32,7 +33,9 @@ import org.apache.logging.log4j.Logger; public class VehicleImpl extends AbstractVehicle{ - /** + + + /** * Extension of {@link VehicleImpl} representing an unspecified vehicle with the id 'noVehicle' * (to avoid null). * @@ -58,30 +61,36 @@ public class VehicleImpl extends AbstractVehicle{ * */ public static class Builder { - static Logger log = LogManager.getLogger(Builder.class.getName()); - private String id; + + static final Logger log = LogManager.getLogger(Builder.class.getName()); + + private String id; private String locationId; + private Coordinate locationCoord; + private double earliestStart = 0.0; + private double latestArrival = Double.MAX_VALUE; private String startLocationId; + private Coordinate startLocationCoord; private String endLocationId; + private Coordinate endLocationCoord; private boolean returnToDepot = true; private VehicleType type = VehicleTypeImpl.Builder.newInstance("default").build(); - - /** - * Constructs the builder with the vehicleId. - * - * @param id - */ - private Builder(String id) { + + private Skills.Builder skillBuilder = Skills.Builder.newInstance(); + + private Skills skills; + + private Builder(String id) { super(); this.id = id; } @@ -89,7 +98,7 @@ public class VehicleImpl extends AbstractVehicle{ /** * Sets the {@link VehicleType}.
* - * @param type + * @param type the type to be set * @throws IllegalStateException if type is null * @return this builder */ @@ -108,7 +117,7 @@ public class VehicleImpl extends AbstractVehicle{ * *

If returnToDepot is false, the end-location of the vehicle is endogenous. * - * @param returnToDepot + * @param returnToDepot true if vehicle need to return to depot, otherwise false * @return this builder */ public Builder setReturnToDepot(boolean returnToDepot){ @@ -119,7 +128,7 @@ public class VehicleImpl extends AbstractVehicle{ /** * Sets the start-location of this vehicle. * - * @param startLocationId + * @param startLocationId the location id of vehicle's start * @return this builder * @throws IllegalArgumentException if startLocationId is null */ @@ -133,7 +142,7 @@ public class VehicleImpl extends AbstractVehicle{ /** * Sets the start-coordinate of this vehicle. * - * @param coord + * @param coord the coordinate of vehicle's start location * @return this builder */ public Builder setStartLocationCoordinate(Coordinate coord){ @@ -145,7 +154,7 @@ public class VehicleImpl extends AbstractVehicle{ /** * Sets the end-locationId of this vehicle. * - * @param endLocationId + * @param endLocationId the location id of vehicle's end * @return this builder */ public Builder setEndLocationId(String endLocationId){ @@ -156,7 +165,7 @@ public class VehicleImpl extends AbstractVehicle{ /** * Sets the end-coordinate of this vehicle. * - * @param coord + * @param coord the coordinate of vehicle's end location * @return this builder */ public Builder setEndLocationCoordinate(Coordinate coord){ @@ -167,24 +176,29 @@ public class VehicleImpl extends AbstractVehicle{ /** * Sets earliest-start of vehicle which should be the lower bound of the vehicle's departure times. * - * @param start + * @param earliest_startTime the earliest start time / departure time of the vehicle at its start location * @return this builder */ - public Builder setEarliestStart(double start){ - this.earliestStart = start; + public Builder setEarliestStart(double earliest_startTime){ + this.earliestStart = earliest_startTime; return this; } /** * Sets the latest arrival at vehicle's end-location which is the upper bound of the vehicle's arrival times. * - * @param arr + * @param latest_arrTime the latest arrival time of the vehicle at its end location * @return this builder */ - public Builder setLatestArrival(double arr){ - this.latestArrival = arr; + public Builder setLatestArrival(double latest_arrTime){ + this.latestArrival = latest_arrTime; return this; } + + public Builder addSkill(String skill){ + skillBuilder.addSkill(skill); + return this; + } /** * Builds and returns the vehicle. @@ -217,15 +231,16 @@ public class VehicleImpl extends AbstractVehicle{ endLocationId = startLocationId; endLocationCoord = startLocationCoord; } - if( !startLocationId.equals(endLocationId) && returnToDepot == false) throw new IllegalStateException("this must not be. you specified both endLocationId and open-routes. this is contradictory.
" + + if( !startLocationId.equals(endLocationId) && !returnToDepot) throw new IllegalStateException("this must not be. you specified both endLocationId and open-routes. this is contradictory.
" + "if you set endLocation, returnToDepot must be true. if returnToDepot is false, endLocationCoord must not be specified."); - return new VehicleImpl(this); + skills = skillBuilder.build(); + return new VehicleImpl(this); } /** * Returns new instance of vehicle builder. * - * @param vehicleId + * @param vehicleId the id of the vehicle which must be a unique identifier among all vehicles * @return vehicle builder */ public static Builder newInstance(String vehicleId){ return new Builder(vehicleId); } @@ -265,6 +280,8 @@ public class VehicleImpl extends AbstractVehicle{ private final String startLocationId; + private Skills skills; + private VehicleImpl(Builder builder){ id = builder.id; type = builder.type; @@ -278,6 +295,7 @@ public class VehicleImpl extends AbstractVehicle{ endLocationId = builder.endLocationId; endLocationCoord = builder.endLocationCoord; setVehicleIdentifier(new VehicleTypeKey(type.getTypeId(),startLocationId,endLocationId,earliestDeparture,latestArrival)); + skills = builder.skills; } /** @@ -334,9 +352,14 @@ public class VehicleImpl extends AbstractVehicle{ return this.endLocationCoord; } - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ + @Override + public Skills getSkills() { + return skills; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ @Override public int hashCode() { final int prime = 31; diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/state/StateManagerTest.java b/jsprit-core/src/test/java/jsprit/core/algorithm/state/StateManagerTest.java index e281d4a6..669fdf92 100644 --- a/jsprit-core/src/test/java/jsprit/core/algorithm/state/StateManagerTest.java +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/state/StateManagerTest.java @@ -159,7 +159,7 @@ public class StateManagerTest { public void whenCreatingNewState_itShouldHaveAnIndex(){ StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); StateId stateId = stateManager.createStateId("foo-state"); - assertEquals(10,stateId.getIndex()); + assertEquals(21,stateId.getIndex()); } @Test @@ -167,8 +167,8 @@ public class StateManagerTest { StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); StateId fooState = stateManager.createStateId("foo-state"); StateId foofooState = stateManager.createStateId("foo-foo-state"); - assertEquals(10,fooState.getIndex()); - assertEquals(11,foofooState.getIndex()); + assertEquals(21,fooState.getIndex()); + assertEquals(22,foofooState.getIndex()); } @Test @@ -176,8 +176,8 @@ public class StateManagerTest { StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); StateId fooState = stateManager.createStateId("foo-state"); StateId foofooState = stateManager.createStateId("foo-state"); - assertEquals(10, fooState.getIndex()); - assertEquals(10, foofooState.getIndex()); + assertEquals(21, fooState.getIndex()); + assertEquals(21, foofooState.getIndex()); } @Test diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/state/UpdateRequiredSkillsTest.java b/jsprit-core/src/test/java/jsprit/core/algorithm/state/UpdateRequiredSkillsTest.java index d018be5a..76357a71 100644 --- a/jsprit-core/src/test/java/jsprit/core/algorithm/state/UpdateRequiredSkillsTest.java +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/state/UpdateRequiredSkillsTest.java @@ -1,27 +1,23 @@ package jsprit.core.algorithm.state; import jsprit.core.problem.Skills; -import jsprit.core.problem.cost.VehicleRoutingTransportCosts; +import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.job.Service; import jsprit.core.problem.solution.route.VehicleRoute; -import jsprit.core.problem.solution.route.state.StateFactory; -import jsprit.core.problem.vehicle.Vehicle; +import jsprit.core.problem.vehicle.VehicleImpl; +import jsprit.core.problem.vehicle.VehicleType; +import jsprit.core.problem.vehicle.VehicleTypeImpl; import junit.framework.Assert; import org.junit.Before; import org.junit.Test; import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** - * Created by schroeder on 01.07.14. + * Tests skill updater */ public class UpdateRequiredSkillsTest { @@ -31,24 +27,23 @@ public class UpdateRequiredSkillsTest { @Before public void doBefore(){ - Vehicle vehicle = mock(Vehicle.class); - Service service = mock(Service.class); - Service service2 = mock(Service.class); - Service service3 = mock(Service.class); - when(service.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").build()); - when(service2.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").addSkill("skill2") - .addSkill("skill3").build()); - when(service3.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4") - .addSkill("skill5").build()); - route = VehicleRoute.Builder.newInstance(vehicle).addService(service).addService(service2).addService(service3).build(); - stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); - stateManager.addStateUpdater(new UpdateSkills(stateManager)); + VehicleType type = VehicleTypeImpl.Builder.newInstance("t").build(); + VehicleImpl vehicle = VehicleImpl.Builder.newInstance("v").setStartLocationId("start").setType(type).build(); + Service service = Service.Builder.newInstance("s").setLocationId("loc").addSkill("skill1").build(); + Service service2 = Service.Builder.newInstance("s2").setLocationId("loc").addSkill("skill1").addSkill("skill2").addSkill("skill3").build(); + Service service3 = Service.Builder.newInstance("s3").setLocationId("loc").addSkill("skill4").addSkill("skill5").build(); + VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addVehicle(vehicle).addJob(service) + .addJob(service2).addJob(service3).build(); + route = VehicleRoute.Builder.newInstance(vehicle).setJobActivityFactory(vrp.getJobActivityFactory()).addService(service).addService(service2).addService(service3).build(); + + stateManager = new StateManager(vrp); + stateManager.updateSkillStates(); + stateManager.informInsertionStarts(Arrays.asList(route),null); } @Test public void whenUpdatingRoute_skillsAtRouteLevelShouldContainAllSkills(){ - stateManager.update(route); - Skills skills = stateManager.getRouteState(route, StateFactory.SKILLS, Skills.class); + Skills skills = stateManager.getRouteState(route, InternalStates.SKILLS, Skills.class); assertNotNull(skills); Assert.assertEquals(5,skills.values().size()); assertTrue(skills.containsSkill("skill1")); diff --git a/jsprit-core/src/test/java/jsprit/core/problem/constraint/SkillConstraintTest.java b/jsprit-core/src/test/java/jsprit/core/problem/constraint/SkillConstraintTest.java index c19ba569..eb3e795d 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/constraint/SkillConstraintTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/constraint/SkillConstraintTest.java @@ -1,13 +1,13 @@ package jsprit.core.problem.constraint; import jsprit.core.algorithm.state.StateManager; -import jsprit.core.algorithm.state.UpdateSkills; -import jsprit.core.problem.Skills; -import jsprit.core.problem.cost.VehicleRoutingTransportCosts; +import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.job.Service; import jsprit.core.problem.misc.JobInsertionContext; import jsprit.core.problem.solution.route.VehicleRoute; -import jsprit.core.problem.vehicle.Vehicle; +import jsprit.core.problem.vehicle.VehicleImpl; +import jsprit.core.problem.vehicle.VehicleType; +import jsprit.core.problem.vehicle.VehicleTypeImpl; import org.junit.Before; import org.junit.Test; @@ -15,115 +15,72 @@ import java.util.Arrays; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class SkillConstraintTest { private HardRouteStateLevelConstraint skillConstraint; - private StateManager stateManager; - private VehicleRoute route; - private Vehicle vehicle; + private VehicleImpl vehicle; + + private VehicleImpl vehicle2; + + private VehicleRoutingProblem vrp; @Before public void doBefore(){ - vehicle = mock(Vehicle.class); - Service service = mock(Service.class); - Service service2 = mock(Service.class); - Service service3 = mock(Service.class); - when(service.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").build()); - when(service2.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").addSkill("skill2") - .addSkill("skill3").build()); - when(service3.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4") - .addSkill("skill5").build()); - route = VehicleRoute.Builder.newInstance(vehicle).addService(service).addService(service2).addService(service3).build(); - stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); - stateManager.addStateUpdater(new UpdateSkills(stateManager)); - stateManager.update(route); + VehicleType type = VehicleTypeImpl.Builder.newInstance("t").build(); + vehicle = VehicleImpl.Builder.newInstance("v").addSkill("skill1").addSkill("skill2").addSkill("skill3").addSkill("skill4").setStartLocationId("start").setType(type).build(); + vehicle2 = VehicleImpl.Builder.newInstance("v").addSkill("skill4").addSkill("skill5").setStartLocationId("start").setType(type).build(); + + Service service = Service.Builder.newInstance("s").setLocationId("loc").addSkill("skill1").build(); + Service service2 = Service.Builder.newInstance("s2").setLocationId("loc").addSkill("skill1").addSkill("skill2").addSkill("skill3").build(); + + Service service3 = Service.Builder.newInstance("s3").setLocationId("loc").addSkill("skill4").addSkill("skill5").build(); + Service service4 = Service.Builder.newInstance("s4").setLocationId("loc").addSkill("skill1").build(); + + vrp = VehicleRoutingProblem.Builder.newInstance().addVehicle(vehicle).addVehicle(vehicle2).addJob(service) + .addJob(service2).addJob(service3).addJob(service4).build(); + + route = VehicleRoute.Builder.newInstance(vehicle).setJobActivityFactory(vrp.getJobActivityFactory()).addService(service).addService(service2).build(); + + StateManager stateManager = new StateManager(vrp); + stateManager.updateSkillStates(); + stateManager.informInsertionStarts(Arrays.asList(route),null); + skillConstraint = new HardSkillConstraint(stateManager); } @Test - public void whenJobToBeInsertedRequiresSkillsThatVehicleDoesNotHave_itShouldReturnFalse(){ - Service s4 = mock(Service.class); - when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill5").build()); - when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance() - .addAllSkills(Arrays.asList("skill1","skill2","skill3","skill4")).build()); - JobInsertionContext insertionContext = new JobInsertionContext(route,s4,vehicle,route.getDriver(),0.); - assertFalse(skillConstraint.fulfilled(insertionContext)); - } - - @Test - public void whenJobToBeInsertedRequiresSkillsThatVehicle2DoesNotHave_itShouldReturnFalse(){ - Service s4 = mock(Service.class); - when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill5").build()); - Vehicle vehicle2 = mock(Vehicle.class); - when(vehicle2.getSkills()).thenReturn(Skills.Builder.newInstance() - .addAllSkills(Arrays.asList("skill1","skill2","skill3","skill4")).build()); - JobInsertionContext insertionContext = new JobInsertionContext(route,s4,vehicle2,route.getDriver(),0.); + public void whenJobToBeInsertedRequiresSkillsThatNewVehicleDoesNotHave_itShouldReturnFalse(){ + JobInsertionContext insertionContext = new JobInsertionContext(route,vrp.getJobs().get("s3"),vehicle,route.getDriver(),0.); assertFalse(skillConstraint.fulfilled(insertionContext)); } @Test public void whenJobToBeInsertedRequiresSkillsThatVehicleHave_itShouldReturnTrue(){ - Service s4 = mock(Service.class); - when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4").build()); - when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance() - .addAllSkills(Arrays.asList("skill1","skill2","skill3","skill4","skill5")).build()); - JobInsertionContext insertionContext = new JobInsertionContext(route,s4,vehicle,route.getDriver(),0.); - assertTrue(skillConstraint.fulfilled(insertionContext)); - } - - @Test - public void whenJobToBeInsertedRequiresSkillsThatVehicle2Have_itShouldReturnTrue(){ - Service s4 = mock(Service.class); - when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4").build()); - Vehicle vehicle2 = mock(Vehicle.class); - when(vehicle2.getSkills()).thenReturn(Skills.Builder.newInstance() - .addAllSkills(Arrays.asList("skill1","skill2","skill3","skill4","skill5")).build()); - JobInsertionContext insertionContext = new JobInsertionContext(route,s4,vehicle2,route.getDriver(),0.); + JobInsertionContext insertionContext = new JobInsertionContext(route,vrp.getJobs().get("s4"),vehicle,route.getDriver(),0.); assertTrue(skillConstraint.fulfilled(insertionContext)); } @Test public void whenRouteToBeOvertakenRequiresSkillsThatVehicleDoesNotHave_itShouldReturnFalse(){ - Service s4 = mock(Service.class); - when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4").build()); - when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance() - .addAllSkills(Arrays.asList("skill1","skill2","skill6","skill4")).build()); - JobInsertionContext insertionContext = new JobInsertionContext(route,s4,vehicle,route.getDriver(),0.); + JobInsertionContext insertionContext = new JobInsertionContext(route,vrp.getJobs().get("s3"),vehicle2,route.getDriver(),0.); + assertFalse(skillConstraint.fulfilled(insertionContext)); + } + + @Test + public void whenRouteToBeOvertakenRequiresSkillsThatVehicleDoesNotHave2_itShouldReturnFalse(){ + JobInsertionContext insertionContext = new JobInsertionContext(route,vrp.getJobs().get("s4"),vehicle2,route.getDriver(),0.); assertFalse(skillConstraint.fulfilled(insertionContext)); } @Test public void whenRouteToBeOvertakenRequiresSkillsThatVehicleDoesHave_itShouldReturnTrue(){ - Service s4 = mock(Service.class); - when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4").build()); - when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance() - .addAllSkills(Arrays.asList("skill1","skill2","skill3","skill4","skill5")).build()); - JobInsertionContext insertionContext = new JobInsertionContext(route,s4,vehicle,route.getDriver(),0.); + JobInsertionContext insertionContext = new JobInsertionContext(route,vrp.getJobs().get("s4"),vehicle,route.getDriver(),0.); assertTrue(skillConstraint.fulfilled(insertionContext)); } - @Test - public void whenNoSkillsAreRequired_itShouldReturnTrue(){ - Service s4 = mock(Service.class); - when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().build()); - when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance().build()); - JobInsertionContext insertionContext = new JobInsertionContext(VehicleRoute.emptyRoute(),s4,vehicle,route.getDriver(),0.); - assertTrue(skillConstraint.fulfilled(insertionContext)); - } - - @Test - public void whenSkillsIsRequiredWhichVehicleDoesNotHave_itShouldReturnFalse(){ - Service s4 = mock(Service.class); - when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").build()); - when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance().build()); - JobInsertionContext insertionContext = new JobInsertionContext(VehicleRoute.emptyRoute(),s4,vehicle,route.getDriver(),0.); - assertFalse(skillConstraint.fulfilled(insertionContext)); - } } diff --git a/jsprit-core/src/test/java/jsprit/core/problem/job/DeliveryTest.java b/jsprit-core/src/test/java/jsprit/core/problem/job/DeliveryTest.java index 8741cc23..cda3c74e 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/job/DeliveryTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/job/DeliveryTest.java @@ -18,12 +18,10 @@ ******************************************************************************/ package jsprit.core.problem.job; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - import org.junit.Test; +import static org.junit.Assert.*; + public class DeliveryTest { @Test(expected=IllegalStateException.class) diff --git a/jsprit-core/src/test/java/jsprit/core/problem/job/PickupTest.java b/jsprit-core/src/test/java/jsprit/core/problem/job/PickupTest.java index d338c2fd..590a0770 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/job/PickupTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/job/PickupTest.java @@ -18,12 +18,10 @@ ******************************************************************************/ package jsprit.core.problem.job; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - import org.junit.Test; +import static org.junit.Assert.*; + public class PickupTest { @Test(expected=IllegalStateException.class) diff --git a/jsprit-core/src/test/java/jsprit/core/problem/job/ServiceTest.java b/jsprit-core/src/test/java/jsprit/core/problem/job/ServiceTest.java index 2a71d9c3..3aa8b85b 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/job/ServiceTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/job/ServiceTest.java @@ -16,16 +16,14 @@ ******************************************************************************/ package jsprit.core.problem.job; +import jsprit.core.problem.solution.route.activity.TimeWindow; +import jsprit.core.util.Coordinate; +import org.junit.Test; + import java.util.HashSet; import java.util.Set; -import jsprit.core.problem.solution.route.activity.TimeWindow; -import jsprit.core.util.Coordinate; - -import org.junit.Test; - import static org.junit.Assert.*; -import static org.junit.Assert.assertFalse; public class ServiceTest { diff --git a/jsprit-core/src/test/java/jsprit/core/problem/job/ShipmentTest.java b/jsprit-core/src/test/java/jsprit/core/problem/job/ShipmentTest.java index bb7df6ea..348e88e1 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/job/ShipmentTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/job/ShipmentTest.java @@ -20,7 +20,6 @@ package jsprit.core.problem.job; import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.util.Coordinate; - import org.junit.Test; import static org.junit.Assert.*; diff --git a/jsprit-core/src/test/java/jsprit/core/problem/vehicle/VehicleImplTest.java b/jsprit-core/src/test/java/jsprit/core/problem/vehicle/VehicleImplTest.java index 0b799f16..08ec14c7 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/vehicle/VehicleImplTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/vehicle/VehicleImplTest.java @@ -19,14 +19,12 @@ package jsprit.core.problem.vehicle; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle; import jsprit.core.util.Coordinate; - import org.junit.Test; +import static org.junit.Assert.*; + public class VehicleImplTest { diff --git a/jsprit-examples/src/main/java/jsprit/examples/SimpleExampleWithSkills.java b/jsprit-examples/src/main/java/jsprit/examples/SimpleExampleWithSkills.java index cab74eb5..b7524a3c 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/SimpleExampleWithSkills.java +++ b/jsprit-examples/src/main/java/jsprit/examples/SimpleExampleWithSkills.java @@ -21,12 +21,14 @@ import jsprit.analysis.toolbox.GraphStreamViewer.Label; import jsprit.analysis.toolbox.SolutionPrinter; import jsprit.analysis.toolbox.SolutionPrinter.Print; import jsprit.core.algorithm.VehicleRoutingAlgorithm; -import jsprit.core.algorithm.box.SchrimpfFactory; +import jsprit.core.algorithm.VehicleRoutingAlgorithmBuilder; +import jsprit.core.algorithm.state.StateManager; import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.constraint.ConstraintManager; import jsprit.core.problem.io.VrpXMLWriter; import jsprit.core.problem.job.Service; import jsprit.core.problem.solution.VehicleRoutingProblemSolution; -import jsprit.core.problem.vehicle.Vehicle; +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; @@ -66,13 +68,13 @@ public class SimpleExampleWithSkills { Builder vehicleBuilder = Builder.newInstance("vehicle"); vehicleBuilder.setStartLocationCoordinate(Coordinate.newInstance(10, 10)); vehicleBuilder.setType(vehicleType); - Vehicle vehicle = vehicleBuilder.build(); + VehicleImpl vehicle = vehicleBuilder.build(); Builder vehicle2Builder = Builder.newInstance("vehicle2"); vehicle2Builder.setStartLocationCoordinate(Coordinate.newInstance(1, 1)); vehicle2Builder.setType(vehicleType); vehicle2Builder.addSkill("drill"); - Vehicle vehicle2 = vehicle2Builder.build(); + VehicleImpl vehicle2 = vehicle2Builder.build(); /* * build services at the required locations, each with a capacity-demand of 1. @@ -94,7 +96,20 @@ public class SimpleExampleWithSkills { /* * get the algorithm out-of-the-box. */ - VehicleRoutingAlgorithm algorithm = new SchrimpfFactory().createAlgorithm(problem); + VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(problem,"input/algorithmConfig.xml"); + vraBuilder.addCoreConstraints(); + vraBuilder.addDefaultCostCalculators(); + + //activate skill state update and constraints - it is NOT default + StateManager stateManager = new StateManager(problem); + stateManager.updateSkillStates(); + + ConstraintManager constraintManager = new ConstraintManager(problem,stateManager); + constraintManager.addSkillsConstraint(); + + vraBuilder.setStateAndConstraintManager(stateManager,constraintManager); + + VehicleRoutingAlgorithm algorithm = vraBuilder.build(); /* * and search a solution