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

merged skills

This commit is contained in:
oblonski 2014-07-29 11:35:40 +02:00
parent 9c4bd498c4
commit c04d3acd51
23 changed files with 279 additions and 343 deletions

View file

@ -359,11 +359,11 @@ public class VehicleRoutingAlgorithms {
private 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 vrp the routing problem
* @param algorithmConfig * @param algorithmConfig the algorithm config
* @return {@link VehicleRoutingAlgorithm} * @return {@link jsprit.core.algorithm.VehicleRoutingAlgorithm}
*/ */
public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp, final AlgorithmConfig algorithmConfig){ public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp, final AlgorithmConfig algorithmConfig){
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0, null); return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0, null);
@ -372,9 +372,9 @@ public class VehicleRoutingAlgorithms {
/** /**
* Read and creates a {@link VehicleRoutingAlgorithm} from an url. * Read and creates a {@link VehicleRoutingAlgorithm} from an url.
* *
* @param vrp * @param vrp the routing problem
* @param configURL * @param configURL config url
* @return {@link VehicleRoutingProblem} * @return {@link jsprit.core.algorithm.VehicleRoutingAlgorithm}
*/ */
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final URL configURL){ public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final URL configURL){
AlgorithmConfig algorithmConfig = new AlgorithmConfig(); 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 vrp the routing problem
* @param configFileName * @param configFileName the config filename (and location)
* @return * @return {@link jsprit.core.algorithm.VehicleRoutingAlgorithm}
*/ */
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final String configFileName){ public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final String configFileName){
AlgorithmConfig algorithmConfig = new AlgorithmConfig(); AlgorithmConfig algorithmConfig = new AlgorithmConfig();
@ -461,7 +461,7 @@ public class VehicleRoutingAlgorithms {
} }
stateManager.updateLoadStates(); stateManager.updateLoadStates();
stateManager.updateTimeWindowStates(); stateManager.updateTimeWindowStates();
stateManager.updateSkillStates(); // stateManager.updateSkillStates();
stateManager.addStateUpdater(new UpdateEndLocationIfRouteIsOpen()); stateManager.addStateUpdater(new UpdateEndLocationIfRouteIsOpen());
stateManager.addStateUpdater(new OpenRouteStateVerifier()); stateManager.addStateUpdater(new OpenRouteStateVerifier());
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts())); stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts()));
@ -481,9 +481,6 @@ public class VehicleRoutingAlgorithms {
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, AlgorithmConfig config, public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, AlgorithmConfig config,
int nuOfThreads, SolutionCostCalculator solutionCostCalculator, final StateManager stateManager, ConstraintManager constraintManager, boolean addDefaultCostCalculators) { 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); 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); RuinAndRecreateModule rrModule = new RuinAndRecreateModule("ruin_and_recreate", final_insertion, ruin);
return rrModule; 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<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
// if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
// List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
// insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads, 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 + throw new NullPointerException("no module found with moduleName=" + moduleName +
"\n\tcheck config whether the correct names are used" + "\n\tcheck config whether the correct names are used" +
"\n\tcurrently there are following modules available: " + "\n\tcurrently there are following modules available: " +
"\n\tbestInsertion" + "\n\tbestInsertion" +
"\n\trandomRuin" + "\n\trandomRuin" +
"\n\tradialRuin" + "\n\tradialRuin");
"\n\tgendreauPostOpt");
} }
private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) { private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) {

View file

@ -43,5 +43,5 @@ public class InternalStates {
public final static StateId PAST_MAXLOAD = new StateFactory.StateIdImpl("past_max_load", 9); public final static StateId PAST_MAXLOAD = new StateFactory.StateIdImpl("past_max_load", 9);
public static final StateId SKILLS = new StateFactory.StateIdImpl("skills", 10);
} }

View file

@ -9,7 +9,7 @@ import java.util.List;
class StateFactory { class StateFactory {
final static List<String> reservedIds = Arrays.asList("max_load", "load", "costs", "load_at_beginning", "load_at_end", "duration", "latest_operation_start_time", "earliest_operation_start_time" final static List<String> 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){ static StateId createId(String name){

View file

@ -22,7 +22,6 @@ import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.algorithm.ruin.listener.RuinListeners; import jsprit.core.algorithm.ruin.listener.RuinListeners;
import jsprit.core.problem.Capacity; import jsprit.core.problem.Capacity;
import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.job.Job; import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.ReverseRouteActivityVisitor; import jsprit.core.problem.solution.route.ReverseRouteActivityVisitor;
@ -93,18 +92,16 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart
private Map<StateId,Object> defaultRouteStates_ = new HashMap<StateId,Object>(); private Map<StateId,Object> defaultRouteStates_ = new HashMap<StateId,Object>();
private Map<StateId,Object> defaultActivityStates_ = new HashMap<StateId,Object>(); private Map<StateId,Object> defaultActivityStates_ = new HashMap<StateId,Object>();
private VehicleRoutingTransportCosts routingCosts;
private boolean updateLoad = false; private boolean updateLoad = false;
private boolean updateTWs = false; private boolean updateTWs = false;
private int stateIndexCounter = 10; private int stateIndexCounter = 21;
private Map<String,StateId> createdStateIds = new HashMap<String, StateId>(); private Map<String,StateId> createdStateIds = new HashMap<String, StateId>();
private int initialNuStates = 20; private int initialNuStates = 30;
private int nuActivities; private int nuActivities;
@ -176,7 +173,6 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart
* @param vehicleRoutingProblem the corresponding VehicleRoutingProblem * @param vehicleRoutingProblem the corresponding VehicleRoutingProblem
*/ */
public StateManager(VehicleRoutingProblem vehicleRoutingProblem){ public StateManager(VehicleRoutingProblem vehicleRoutingProblem){
this.routingCosts = vehicleRoutingProblem.getTransportCosts();
this.vrp = vehicleRoutingProblem; this.vrp = vehicleRoutingProblem;
nuActivities = Math.max(10, vrp.getNuActivities() + 1); nuActivities = Math.max(10, vrp.getNuActivities() + 1);
nuVehicleTypeKeys = Math.max(3, getNuVehicleTypes(vrp) + 2); nuVehicleTypeKeys = Math.max(3, getNuVehicleTypes(vrp) + 2);
@ -706,5 +702,12 @@ public class StateManager implements RouteAndActivityStateGetter, IterationStart
return updateTWs; return updateTWs;
} }
/**
* Updates skill states.
*/
public void updateSkillStates() {
addActivityVisitor(new UpdateSkills(this));
}
} }

View file

@ -4,10 +4,9 @@ import jsprit.core.problem.Skills;
import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.ActivityVisitor; import jsprit.core.problem.solution.route.activity.ActivityVisitor;
import jsprit.core.problem.solution.route.activity.TourActivity; 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{ public class UpdateSkills implements StateUpdater, ActivityVisitor{
@ -38,6 +37,6 @@ public class UpdateSkills implements StateUpdater, ActivityVisitor{
@Override @Override
public void finish() { public void finish() {
Skills skills = skillBuilder.build(); Skills skills = skillBuilder.build();
statesManager.putTypedInternalRouteState(route, StateFactory.SKILLS, Skills.class, skills); statesManager.putTypedInternalRouteState(route, InternalStates.SKILLS, skills);
} }
} }

View file

@ -6,7 +6,7 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
/** /**
* Created by schroeder on 01.07.14. * Skill container managing skills
*/ */
public class Skills { public class Skills {
@ -15,7 +15,7 @@ public class Skills {
/** /**
* Returns new instance of skill-builder. * Returns new instance of skill-builder.
* *
* @return * @return builder
*/ */
public static Builder newInstance(){ public static Builder newInstance(){
return new Builder(); return new Builder();
@ -26,19 +26,30 @@ public class Skills {
/** /**
* Adds skill. Skill is transformed into lowerCase. * Adds skill. Skill is transformed into lowerCase.
* *
* @param skill * @param skill skill to be added
* @return * @return builder
*/ */
public Builder addSkill(String skill){ public Builder addSkill(String skill){
skills.add(skill.toLowerCase()); skills.add(skill.toLowerCase());
return this; return this;
} }
/**
* Adds a collection of skills.
*
* @param skills collection of skills to be added
* @return builder
*/
public Builder addAllSkills(Collection<String> skills){ public Builder addAllSkills(Collection<String> skills){
for(String skill : skills) this.skills.add(skill); for(String skill : skills) this.skills.add(skill);
return this; return this;
} }
/**
* Builds the skill container and returns it.
*
* @return skills
*/
public Skills build(){ public Skills build(){
return new Skills(this); return new Skills(this);
} }
@ -54,7 +65,7 @@ public class Skills {
/** /**
* Returns an unmodifiable set of skills. All skills are inLowerCase. * Returns an unmodifiable set of skills. All skills are inLowerCase.
* *
* @return * @return set of skills in this containter
*/ */
public Set<String> values(){ public Set<String> values(){
return Collections.unmodifiableSet(skills); return Collections.unmodifiableSet(skills);
@ -63,8 +74,8 @@ public class Skills {
/** /**
* Not case sensitive. * Not case sensitive.
* *
* @param skill * @param skill which is checked whether it is in skill container or not
* @return * @return true if skill is included, false otherwise
*/ */
public boolean containsSkill(String skill){ public boolean containsSkill(String skill){
return skills.contains(skill.toLowerCase()); return skills.contains(skill.toLowerCase());

View file

@ -1,9 +1,9 @@
package jsprit.core.problem.constraint; package jsprit.core.problem.constraint;
import jsprit.core.algorithm.state.InternalStates;
import jsprit.core.problem.Skills; import jsprit.core.problem.Skills;
import jsprit.core.problem.misc.JobInsertionContext; import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter; 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. * 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{ public class HardSkillConstraint implements HardRouteStateLevelConstraint{
private static final Skills defaultSkills = Skills.Builder.newInstance().build();
private RouteAndActivityStateGetter states; private RouteAndActivityStateGetter states;
public HardSkillConstraint(RouteAndActivityStateGetter states) { public HardSkillConstraint(RouteAndActivityStateGetter states) {
@ -24,7 +26,8 @@ public class HardSkillConstraint implements HardRouteStateLevelConstraint{
return false; 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()){ for(String skill : requiredSkillsForRoute.values()){
if(!insertionContext.getNewVehicle().getSkills().containsSkill(skill)){ if(!insertionContext.getNewVehicle().getSkills().containsSkill(skill)){
return false; return false;

View file

@ -30,24 +30,13 @@ public class Delivery extends Service{
/** /**
* Returns a new instance of builder that builds a delivery. * Returns a new instance of builder that builds a delivery.
* *
* @param id * @param id the id of the delivery
* @return the builder * @return the builder
*/ */
public static Builder newInstance(String id){ public static Builder newInstance(String id){
return new Builder(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) { Builder(String id) {
super(id); super(id);
} }
@ -56,7 +45,7 @@ public class Delivery extends Service{
* Builds Delivery. * Builds Delivery.
* *
* @return delivery * @return delivery
* @throw IllegalStateException if neither locationId nor coord is set * @throws IllegalStateException if neither locationId nor coord is set
*/ */
public Delivery build(){ public Delivery build(){
if(locationId == null) { if(locationId == null) {
@ -65,16 +54,12 @@ public class Delivery extends Service{
} }
this.setType("delivery"); this.setType("delivery");
super.capacity = super.capacityBuilder.build(); super.capacity = super.capacityBuilder.build();
super.skills = super.skillBuilder.build();
return new Delivery(this); return new Delivery(this);
} }
} }
/**
* Constructs Delivery.
*
* @param builder
*/
Delivery(Builder builder) { Delivery(Builder builder) {
super(builder); super(builder);

View file

@ -20,6 +20,7 @@ package jsprit.core.problem.job;
import jsprit.core.problem.Capacity; import jsprit.core.problem.Capacity;
import jsprit.core.problem.HasId; import jsprit.core.problem.HasId;
import jsprit.core.problem.HasIndex; import jsprit.core.problem.HasIndex;
import jsprit.core.problem.Skills;
/** /**
* Basic interface for all jobs. * Basic interface for all jobs.
@ -42,5 +43,6 @@ public interface Job extends HasId, HasIndex {
* @return Capacity * @return Capacity
*/ */
public Capacity getSize(); public Capacity getSize();
Skills getRequiredSkills();
} }

View file

@ -30,24 +30,13 @@ public class Pickup extends Service {
/** /**
* Returns a new instance of builder that builds a pickup. * Returns a new instance of builder that builds a pickup.
* *
* @param id * @param id the id of the pickup
* @return the builder * @return the builder
*/ */
public static Builder newInstance(String id){ public static Builder newInstance(String id){
return new Builder(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) { Builder(String id) {
super(id); super(id);
} }
@ -58,7 +47,7 @@ public class Pickup extends Service {
*<p>Pickup type is "pickup" *<p>Pickup type is "pickup"
* *
* @return 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(){ public Pickup build(){
if(locationId == null) { if(locationId == null) {
@ -67,16 +56,12 @@ public class Pickup extends Service {
} }
this.setType("pickup"); this.setType("pickup");
super.capacity = super.capacityBuilder.build(); super.capacity = super.capacityBuilder.build();
super.skills = super.skillBuilder.build();
return new Pickup(this); return new Pickup(this);
} }
} }
/**
* Constructs the Pickup
*
* @param builder
*/
Pickup(Builder builder) { Pickup(Builder builder) {
super(builder); super(builder);
} }

View file

@ -18,6 +18,7 @@ package jsprit.core.problem.job;
import jsprit.core.problem.AbstractJob; import jsprit.core.problem.AbstractJob;
import jsprit.core.problem.Capacity; import jsprit.core.problem.Capacity;
import jsprit.core.problem.Skills;
import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.util.Coordinate; import jsprit.core.util.Coordinate;
@ -45,7 +46,7 @@ public class Service extends AbstractJob {
/** /**
* Returns a new instance of builder that builds a service. * Returns a new instance of builder that builds a service.
* *
* @param id * @param id the id of the service
* @return the builder * @return the builder
*/ */
public static Builder newInstance(String id){ public static Builder newInstance(String id){
@ -67,20 +68,11 @@ public class Service extends AbstractJob {
protected Capacity.Builder capacityBuilder = Capacity.Builder.newInstance(); protected Capacity.Builder capacityBuilder = Capacity.Builder.newInstance();
protected Capacity capacity; protected Capacity capacity;
/** protected Skills.Builder skillBuilder = Skills.Builder.newInstance();
* Constructs the builder.
* protected Skills skills;
* @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){ Builder(String id){
this.id = id; this.id = id;
} }
@ -90,7 +82,7 @@ public class Service extends AbstractJob {
* *
* <p>Currently there are {@link Service}, {@link Pickup} and {@link Delivery}. * <p>Currently there are {@link Service}, {@link Pickup} and {@link Delivery}.
* *
* @param name * @param name the name of service
* @return the builder * @return the builder
*/ */
protected Builder setType(String name){ protected Builder setType(String name){
@ -101,7 +93,7 @@ public class Service extends AbstractJob {
/** /**
* Sets the location-id of this service. * Sets the location-id of this service.
* *
* @param locationId * @param locationId the location id of the service
* @return builder * @return builder
*/ */
public Builder setLocationId(String locationId){ public Builder setLocationId(String locationId){
@ -112,7 +104,7 @@ public class Service extends AbstractJob {
/** /**
* Sets the coordinate of this service. * Sets the coordinate of this service.
* *
* @param coord * @param coord the coordinate of service
* @return builder * @return builder
*/ */
public Builder setCoord(Coordinate coord){ public Builder setCoord(Coordinate coord){
@ -126,7 +118,7 @@ public class Service extends AbstractJob {
* <p>It is understood as time that a service or its implied activity takes at the service-location, for instance * <p>It is understood as time that a service or its implied activity takes at the service-location, for instance
* to unload goods. * to unload goods.
* *
* @param serviceTime * @param serviceTime the service time / duration of service to be set
* @return builder * @return builder
* @throws IllegalArgumentException if serviceTime < 0 * @throws IllegalArgumentException if serviceTime < 0
*/ */
@ -139,8 +131,8 @@ public class Service extends AbstractJob {
/** /**
* Adds capacity dimension. * Adds capacity dimension.
* *
* @param dimensionIndex * @param dimensionIndex the dimension index of the capacity value
* @param dimensionValue * @param dimensionValue the capacity value
* @return the builder * @return the builder
* @throws IllegalArgumentException if dimensionValue < 0 * @throws IllegalArgumentException if dimensionValue < 0
*/ */
@ -155,9 +147,9 @@ public class Service extends AbstractJob {
* *
* <p>The time-window indicates the time period a service/activity/operation is allowed to start. * <p>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 * @return builder
* @throw IllegalArgumentException if timeWindow is null * @throws IllegalArgumentException if timeWindow is null
*/ */
public Builder setTimeWindow(TimeWindow tw){ public Builder setTimeWindow(TimeWindow tw){
if(tw == null) throw new IllegalArgumentException("time-window arg must not be null"); 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"); this.setType("service");
capacity = capacityBuilder.build(); capacity = capacityBuilder.build();
skills = skillBuilder.build();
return new Service(this); return new Service(this);
} }
} public Builder addSkill(String skill) {
skillBuilder.addSkill(skill);
return this;
}
}
private final String id; private final String id;
@ -198,6 +195,8 @@ public class Service extends AbstractJob {
private final Capacity size; private final Capacity size;
private final Skills skills;
Service(Builder builder){ Service(Builder builder){
id = builder.id; id = builder.id;
locationId = builder.locationId; locationId = builder.locationId;
@ -206,6 +205,7 @@ public class Service extends AbstractJob {
timeWindow = builder.timeWindow; timeWindow = builder.timeWindow;
type = builder.type; type = builder.type;
size = builder.capacity; size = builder.capacity;
skills = builder.skills;
} }
@Override @Override
@ -300,5 +300,10 @@ public class Service extends AbstractJob {
public Capacity getSize() { public Capacity getSize() {
return size; return size;
} }
@Override
public Skills getRequiredSkills() {
return skills;
}
} }

View file

@ -20,6 +20,7 @@ package jsprit.core.problem.job;
import jsprit.core.problem.AbstractJob; import jsprit.core.problem.AbstractJob;
import jsprit.core.problem.Capacity; import jsprit.core.problem.Capacity;
import jsprit.core.problem.Skills;
import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.util.Coordinate; import jsprit.core.util.Coordinate;
@ -71,30 +72,21 @@ public class Shipment extends AbstractJob{
private Capacity.Builder capacityBuilder = Capacity.Builder.newInstance(); private Capacity.Builder capacityBuilder = Capacity.Builder.newInstance();
private Capacity capacity; private Capacity capacity;
/** private Skills.Builder skillBuilder = Skills.Builder.newInstance();
private Skills skills;
/**
* Returns new instance of this builder. * Returns new instance of this builder.
* *
* @param id * @param id the id of the shipment which must be a unique identifier among all jobs
* @return * @return the builder
*/ */
public static Builder newInstance(String id){ public static Builder newInstance(String id){
return new Builder(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){ Builder(String id){
if(id == null) throw new IllegalArgumentException("id must not be null"); if(id == null) throw new IllegalArgumentException("id must not be null");
this.id = id; this.id = id;
@ -103,20 +95,20 @@ public class Shipment extends AbstractJob{
/** /**
* Sets pickup-location. * Sets pickup-location.
* *
* @param pickupLocation * @param pickupLocationId the location id of shipment's pickup
* @return builder * @return builder
* @throws IllegalArgumentException if location is null * @throws IllegalArgumentException if location is null
*/ */
public Builder setPickupLocation(String pickupLocation){ public Builder setPickupLocation(String pickupLocationId){
if(pickupLocation == null) throw new IllegalArgumentException("location must not be null"); if(pickupLocationId == null) throw new IllegalArgumentException("location must not be null");
this.pickupLocation = pickupLocation; this.pickupLocation = pickupLocationId;
return this; return this;
} }
/** /**
* Sets pickup-coordinate. * Sets pickup-coordinate.
* *
* @param pickupCoord * @param pickupCoord the coordinate of shipment's pickup location
* @return builder * @return builder
* @throws IllegalArgumentException if pickupCoord is null * @throws IllegalArgumentException if pickupCoord is null
*/ */
@ -131,7 +123,7 @@ public class Shipment extends AbstractJob{
* *
* <p>ServiceTime is intended to be the time the implied activity takes at the pickup-location. * <p>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 * @return builder
* @throws IllegalArgumentException if servicTime < 0.0 * @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 * Sets the timeWindow for the pickup, i.e. the time-period in which a pickup operation is
* allowed to start. * allowed to START.
* *
* <p>By default timeWindow is [0.0, Double.MAX_VALUE} * <p>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 * @return builder
* @throws IllegalArgumentException if timeWindow is null * @throws IllegalArgumentException if timeWindow is null
*/ */
@ -160,7 +152,7 @@ public class Shipment extends AbstractJob{
/** /**
* Sets the delivery-location. * Sets the delivery-location.
* *
* @param deliveryLocation * @param deliveryLocation the delivery location id
* @return builder * @return builder
* @throws IllegalArgumentException if location is null * @throws IllegalArgumentException if location is null
*/ */
@ -173,7 +165,7 @@ public class Shipment extends AbstractJob{
/** /**
* Sets delivery-coord. * Sets delivery-coord.
* *
* @param deliveryCoord * @param deliveryCoord the coordinate of shipment's delivery location
* @return builder * @return builder
* @throws IllegalArgumentException if coord is null; * @throws IllegalArgumentException if coord is null;
*/ */
@ -188,7 +180,7 @@ public class Shipment extends AbstractJob{
* *
* <p>ServiceTime is intended to be the time the implied activity takes at the delivery-location. * <p>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 * @return builder
* @throws IllegalArgumentException if serviceTime < 0.0 * @throws IllegalArgumentException if serviceTime < 0.0
*/ */
@ -204,7 +196,7 @@ public class Shipment extends AbstractJob{
* *
* <p>By default timeWindow is [0.0, Double.MAX_VALUE} * <p>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 * @return builder
* @throws IllegalArgumentException if timeWindow is null * @throws IllegalArgumentException if timeWindow is null
*/ */
@ -217,8 +209,8 @@ public class Shipment extends AbstractJob{
/** /**
* Adds capacity dimension. * Adds capacity dimension.
* *
* @param dimensionIndex * @param dimensionIndex the dimension index of the corresponding capacity value
* @param dimensionValue * @param dimensionValue the capacity value
* @return builder * @return builder
* @throws IllegalArgumentException if dimVal < 0 * @throws IllegalArgumentException if dimVal < 0
*/ */
@ -246,11 +238,16 @@ public class Shipment extends AbstractJob{
deliveryLocation = deliveryCoord.toString(); deliveryLocation = deliveryCoord.toString();
} }
capacity = capacityBuilder.build(); capacity = capacityBuilder.build();
skills = skillBuilder.build();
return new Shipment(this); return new Shipment(this);
} }
} public Builder addSkill(String skill) {
skillBuilder.addSkill(skill);
return this;
}
}
private final String id; private final String id;
@ -272,12 +269,8 @@ public class Shipment extends AbstractJob{
private final Capacity capacity; private final Capacity capacity;
private final Skills skills;
/**
* Constructs the shipment.
*
* @param builder
*/
Shipment(Builder builder){ Shipment(Builder builder){
this.id = builder.id; this.id = builder.id;
this.pickupLocation = builder.pickupLocation; this.pickupLocation = builder.pickupLocation;
@ -289,6 +282,7 @@ public class Shipment extends AbstractJob{
this.deliveryServiceTime = builder.deliveryServiceTime; this.deliveryServiceTime = builder.deliveryServiceTime;
this.deliveryTimeWindow = builder.deliveryTimeWindow; this.deliveryTimeWindow = builder.deliveryTimeWindow;
this.capacity = builder.capacity; this.capacity = builder.capacity;
this.skills = builder.skills;
} }
@Override @Override
@ -405,5 +399,10 @@ public class Shipment extends AbstractJob{
return capacity; return capacity;
} }
@Override
public Skills getRequiredSkills() {
return skills;
}
} }

View file

@ -18,6 +18,7 @@ package jsprit.core.problem.vehicle;
import jsprit.core.problem.HasId; import jsprit.core.problem.HasId;
import jsprit.core.problem.HasIndex; import jsprit.core.problem.HasIndex;
import jsprit.core.problem.Skills;
import jsprit.core.util.Coordinate; import jsprit.core.util.Coordinate;
/** /**
@ -86,4 +87,6 @@ public interface Vehicle extends HasId, HasIndex {
public abstract Coordinate getEndLocationCoordinate(); public abstract Coordinate getEndLocationCoordinate();
public abstract VehicleTypeKey getVehicleTypeIdentifier(); public abstract VehicleTypeKey getVehicleTypeIdentifier();
public abstract Skills getSkills();
} }

View file

@ -17,6 +17,7 @@
package jsprit.core.problem.vehicle; package jsprit.core.problem.vehicle;
import jsprit.core.problem.AbstractVehicle; import jsprit.core.problem.AbstractVehicle;
import jsprit.core.problem.Skills;
import jsprit.core.util.Coordinate; import jsprit.core.util.Coordinate;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -32,7 +33,9 @@ import org.apache.logging.log4j.Logger;
public class VehicleImpl extends AbstractVehicle{ public class VehicleImpl extends AbstractVehicle{
/**
/**
* Extension of {@link VehicleImpl} representing an unspecified vehicle with the id 'noVehicle' * Extension of {@link VehicleImpl} representing an unspecified vehicle with the id 'noVehicle'
* (to avoid null). * (to avoid null).
* *
@ -58,30 +61,36 @@ public class VehicleImpl extends AbstractVehicle{
* *
*/ */
public static class Builder { 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 String locationId;
private Coordinate locationCoord; private Coordinate locationCoord;
private double earliestStart = 0.0; private double earliestStart = 0.0;
private double latestArrival = Double.MAX_VALUE; private double latestArrival = Double.MAX_VALUE;
private String startLocationId; private String startLocationId;
private Coordinate startLocationCoord; private Coordinate startLocationCoord;
private String endLocationId; private String endLocationId;
private Coordinate endLocationCoord; private Coordinate endLocationCoord;
private boolean returnToDepot = true; private boolean returnToDepot = true;
private VehicleType type = VehicleTypeImpl.Builder.newInstance("default").build(); private VehicleType type = VehicleTypeImpl.Builder.newInstance("default").build();
/** private Skills.Builder skillBuilder = Skills.Builder.newInstance();
* Constructs the builder with the vehicleId.
* private Skills skills;
* @param id
*/ private Builder(String id) {
private Builder(String id) {
super(); super();
this.id = id; this.id = id;
} }
@ -89,7 +98,7 @@ public class VehicleImpl extends AbstractVehicle{
/** /**
* Sets the {@link VehicleType}.<br> * Sets the {@link VehicleType}.<br>
* *
* @param type * @param type the type to be set
* @throws IllegalStateException if type is null * @throws IllegalStateException if type is null
* @return this builder * @return this builder
*/ */
@ -108,7 +117,7 @@ public class VehicleImpl extends AbstractVehicle{
* *
* <p>If returnToDepot is false, the end-location of the vehicle is endogenous. * <p>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 * @return this builder
*/ */
public Builder setReturnToDepot(boolean returnToDepot){ public Builder setReturnToDepot(boolean returnToDepot){
@ -119,7 +128,7 @@ public class VehicleImpl extends AbstractVehicle{
/** /**
* Sets the start-location of this vehicle. * Sets the start-location of this vehicle.
* *
* @param startLocationId * @param startLocationId the location id of vehicle's start
* @return this builder * @return this builder
* @throws IllegalArgumentException if startLocationId is null * @throws IllegalArgumentException if startLocationId is null
*/ */
@ -133,7 +142,7 @@ public class VehicleImpl extends AbstractVehicle{
/** /**
* Sets the start-coordinate of this vehicle. * Sets the start-coordinate of this vehicle.
* *
* @param coord * @param coord the coordinate of vehicle's start location
* @return this builder * @return this builder
*/ */
public Builder setStartLocationCoordinate(Coordinate coord){ public Builder setStartLocationCoordinate(Coordinate coord){
@ -145,7 +154,7 @@ public class VehicleImpl extends AbstractVehicle{
/** /**
* Sets the end-locationId of this vehicle. * Sets the end-locationId of this vehicle.
* *
* @param endLocationId * @param endLocationId the location id of vehicle's end
* @return this builder * @return this builder
*/ */
public Builder setEndLocationId(String endLocationId){ public Builder setEndLocationId(String endLocationId){
@ -156,7 +165,7 @@ public class VehicleImpl extends AbstractVehicle{
/** /**
* Sets the end-coordinate of this vehicle. * Sets the end-coordinate of this vehicle.
* *
* @param coord * @param coord the coordinate of vehicle's end location
* @return this builder * @return this builder
*/ */
public Builder setEndLocationCoordinate(Coordinate coord){ 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. * 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 * @return this builder
*/ */
public Builder setEarliestStart(double start){ public Builder setEarliestStart(double earliest_startTime){
this.earliestStart = start; this.earliestStart = earliest_startTime;
return this; return this;
} }
/** /**
* Sets the latest arrival at vehicle's end-location which is the upper bound of the vehicle's arrival times. * 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 * @return this builder
*/ */
public Builder setLatestArrival(double arr){ public Builder setLatestArrival(double latest_arrTime){
this.latestArrival = arr; this.latestArrival = latest_arrTime;
return this; return this;
} }
public Builder addSkill(String skill){
skillBuilder.addSkill(skill);
return this;
}
/** /**
* Builds and returns the vehicle. * Builds and returns the vehicle.
@ -217,15 +231,16 @@ public class VehicleImpl extends AbstractVehicle{
endLocationId = startLocationId; endLocationId = startLocationId;
endLocationCoord = startLocationCoord; 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. <br>" + if( !startLocationId.equals(endLocationId) && !returnToDepot) throw new IllegalStateException("this must not be. you specified both endLocationId and open-routes. this is contradictory. <br>" +
"if you set endLocation, returnToDepot must be true. if returnToDepot is false, endLocationCoord must not be specified."); "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. * 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 * @return vehicle builder
*/ */
public static Builder newInstance(String vehicleId){ return new Builder(vehicleId); } public static Builder newInstance(String vehicleId){ return new Builder(vehicleId); }
@ -265,6 +280,8 @@ public class VehicleImpl extends AbstractVehicle{
private final String startLocationId; private final String startLocationId;
private Skills skills;
private VehicleImpl(Builder builder){ private VehicleImpl(Builder builder){
id = builder.id; id = builder.id;
type = builder.type; type = builder.type;
@ -278,6 +295,7 @@ public class VehicleImpl extends AbstractVehicle{
endLocationId = builder.endLocationId; endLocationId = builder.endLocationId;
endLocationCoord = builder.endLocationCoord; endLocationCoord = builder.endLocationCoord;
setVehicleIdentifier(new VehicleTypeKey(type.getTypeId(),startLocationId,endLocationId,earliestDeparture,latestArrival)); setVehicleIdentifier(new VehicleTypeKey(type.getTypeId(),startLocationId,endLocationId,earliestDeparture,latestArrival));
skills = builder.skills;
} }
/** /**
@ -334,9 +352,14 @@ public class VehicleImpl extends AbstractVehicle{
return this.endLocationCoord; return this.endLocationCoord;
} }
/* (non-Javadoc) @Override
* @see java.lang.Object#hashCode() public Skills getSkills() {
*/ return skills;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;

View file

@ -159,7 +159,7 @@ public class StateManagerTest {
public void whenCreatingNewState_itShouldHaveAnIndex(){ public void whenCreatingNewState_itShouldHaveAnIndex(){
StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class));
StateId stateId = stateManager.createStateId("foo-state"); StateId stateId = stateManager.createStateId("foo-state");
assertEquals(10,stateId.getIndex()); assertEquals(21,stateId.getIndex());
} }
@Test @Test
@ -167,8 +167,8 @@ public class StateManagerTest {
StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class));
StateId fooState = stateManager.createStateId("foo-state"); StateId fooState = stateManager.createStateId("foo-state");
StateId foofooState = stateManager.createStateId("foo-foo-state"); StateId foofooState = stateManager.createStateId("foo-foo-state");
assertEquals(10,fooState.getIndex()); assertEquals(21,fooState.getIndex());
assertEquals(11,foofooState.getIndex()); assertEquals(22,foofooState.getIndex());
} }
@Test @Test
@ -176,8 +176,8 @@ public class StateManagerTest {
StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class)); StateManager stateManager = new StateManager(mock(VehicleRoutingProblem.class));
StateId fooState = stateManager.createStateId("foo-state"); StateId fooState = stateManager.createStateId("foo-state");
StateId foofooState = stateManager.createStateId("foo-state"); StateId foofooState = stateManager.createStateId("foo-state");
assertEquals(10, fooState.getIndex()); assertEquals(21, fooState.getIndex());
assertEquals(10, foofooState.getIndex()); assertEquals(21, foofooState.getIndex());
} }
@Test @Test

View file

@ -1,27 +1,23 @@
package jsprit.core.algorithm.state; package jsprit.core.algorithm.state;
import jsprit.core.problem.Skills; 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.job.Service;
import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.state.StateFactory; import jsprit.core.problem.vehicle.VehicleImpl;
import jsprit.core.problem.vehicle.Vehicle; import jsprit.core.problem.vehicle.VehicleType;
import jsprit.core.problem.vehicle.VehicleTypeImpl;
import junit.framework.Assert; import junit.framework.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.util.Arrays; 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.assertNotNull;
import static org.junit.Assert.assertTrue; 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 { public class UpdateRequiredSkillsTest {
@ -31,24 +27,23 @@ public class UpdateRequiredSkillsTest {
@Before @Before
public void doBefore(){ public void doBefore(){
Vehicle vehicle = mock(Vehicle.class); VehicleType type = VehicleTypeImpl.Builder.newInstance("t").build();
Service service = mock(Service.class); VehicleImpl vehicle = VehicleImpl.Builder.newInstance("v").setStartLocationId("start").setType(type).build();
Service service2 = mock(Service.class); Service service = Service.Builder.newInstance("s").setLocationId("loc").addSkill("skill1").build();
Service service3 = mock(Service.class); Service service2 = Service.Builder.newInstance("s2").setLocationId("loc").addSkill("skill1").addSkill("skill2").addSkill("skill3").build();
when(service.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").build()); Service service3 = Service.Builder.newInstance("s3").setLocationId("loc").addSkill("skill4").addSkill("skill5").build();
when(service2.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").addSkill("skill2") VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addVehicle(vehicle).addJob(service)
.addSkill("skill3").build()); .addJob(service2).addJob(service3).build();
when(service3.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4") route = VehicleRoute.Builder.newInstance(vehicle).setJobActivityFactory(vrp.getJobActivityFactory()).addService(service).addService(service2).addService(service3).build();
.addSkill("skill5").build());
route = VehicleRoute.Builder.newInstance(vehicle).addService(service).addService(service2).addService(service3).build(); stateManager = new StateManager(vrp);
stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); stateManager.updateSkillStates();
stateManager.addStateUpdater(new UpdateSkills(stateManager)); stateManager.informInsertionStarts(Arrays.asList(route),null);
} }
@Test @Test
public void whenUpdatingRoute_skillsAtRouteLevelShouldContainAllSkills(){ public void whenUpdatingRoute_skillsAtRouteLevelShouldContainAllSkills(){
stateManager.update(route); Skills skills = stateManager.getRouteState(route, InternalStates.SKILLS, Skills.class);
Skills skills = stateManager.getRouteState(route, StateFactory.SKILLS, Skills.class);
assertNotNull(skills); assertNotNull(skills);
Assert.assertEquals(5,skills.values().size()); Assert.assertEquals(5,skills.values().size());
assertTrue(skills.containsSkill("skill1")); assertTrue(skills.containsSkill("skill1"));

View file

@ -1,13 +1,13 @@
package jsprit.core.problem.constraint; package jsprit.core.problem.constraint;
import jsprit.core.algorithm.state.StateManager; import jsprit.core.algorithm.state.StateManager;
import jsprit.core.algorithm.state.UpdateSkills; import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.Skills;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.job.Service; import jsprit.core.problem.job.Service;
import jsprit.core.problem.misc.JobInsertionContext; import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute; 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.Before;
import org.junit.Test; import org.junit.Test;
@ -15,115 +15,72 @@ import java.util.Arrays;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class SkillConstraintTest { public class SkillConstraintTest {
private HardRouteStateLevelConstraint skillConstraint; private HardRouteStateLevelConstraint skillConstraint;
private StateManager stateManager;
private VehicleRoute route; private VehicleRoute route;
private Vehicle vehicle; private VehicleImpl vehicle;
private VehicleImpl vehicle2;
private VehicleRoutingProblem vrp;
@Before @Before
public void doBefore(){ public void doBefore(){
vehicle = mock(Vehicle.class); VehicleType type = VehicleTypeImpl.Builder.newInstance("t").build();
Service service = mock(Service.class); vehicle = VehicleImpl.Builder.newInstance("v").addSkill("skill1").addSkill("skill2").addSkill("skill3").addSkill("skill4").setStartLocationId("start").setType(type).build();
Service service2 = mock(Service.class); vehicle2 = VehicleImpl.Builder.newInstance("v").addSkill("skill4").addSkill("skill5").setStartLocationId("start").setType(type).build();
Service service3 = mock(Service.class);
when(service.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").build()); Service service = Service.Builder.newInstance("s").setLocationId("loc").addSkill("skill1").build();
when(service2.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").addSkill("skill2") Service service2 = Service.Builder.newInstance("s2").setLocationId("loc").addSkill("skill1").addSkill("skill2").addSkill("skill3").build();
.addSkill("skill3").build());
when(service3.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4") Service service3 = Service.Builder.newInstance("s3").setLocationId("loc").addSkill("skill4").addSkill("skill5").build();
.addSkill("skill5").build()); Service service4 = Service.Builder.newInstance("s4").setLocationId("loc").addSkill("skill1").build();
route = VehicleRoute.Builder.newInstance(vehicle).addService(service).addService(service2).addService(service3).build();
stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); vrp = VehicleRoutingProblem.Builder.newInstance().addVehicle(vehicle).addVehicle(vehicle2).addJob(service)
stateManager.addStateUpdater(new UpdateSkills(stateManager)); .addJob(service2).addJob(service3).addJob(service4).build();
stateManager.update(route);
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); skillConstraint = new HardSkillConstraint(stateManager);
} }
@Test @Test
public void whenJobToBeInsertedRequiresSkillsThatVehicleDoesNotHave_itShouldReturnFalse(){ public void whenJobToBeInsertedRequiresSkillsThatNewVehicleDoesNotHave_itShouldReturnFalse(){
Service s4 = mock(Service.class); JobInsertionContext insertionContext = new JobInsertionContext(route,vrp.getJobs().get("s3"),vehicle,route.getDriver(),0.);
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.);
assertFalse(skillConstraint.fulfilled(insertionContext)); assertFalse(skillConstraint.fulfilled(insertionContext));
} }
@Test @Test
public void whenJobToBeInsertedRequiresSkillsThatVehicleHave_itShouldReturnTrue(){ public void whenJobToBeInsertedRequiresSkillsThatVehicleHave_itShouldReturnTrue(){
Service s4 = mock(Service.class); JobInsertionContext insertionContext = new JobInsertionContext(route,vrp.getJobs().get("s4"),vehicle,route.getDriver(),0.);
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.);
assertTrue(skillConstraint.fulfilled(insertionContext)); assertTrue(skillConstraint.fulfilled(insertionContext));
} }
@Test @Test
public void whenRouteToBeOvertakenRequiresSkillsThatVehicleDoesNotHave_itShouldReturnFalse(){ public void whenRouteToBeOvertakenRequiresSkillsThatVehicleDoesNotHave_itShouldReturnFalse(){
Service s4 = mock(Service.class); JobInsertionContext insertionContext = new JobInsertionContext(route,vrp.getJobs().get("s3"),vehicle2,route.getDriver(),0.);
when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4").build()); assertFalse(skillConstraint.fulfilled(insertionContext));
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.); @Test
public void whenRouteToBeOvertakenRequiresSkillsThatVehicleDoesNotHave2_itShouldReturnFalse(){
JobInsertionContext insertionContext = new JobInsertionContext(route,vrp.getJobs().get("s4"),vehicle2,route.getDriver(),0.);
assertFalse(skillConstraint.fulfilled(insertionContext)); assertFalse(skillConstraint.fulfilled(insertionContext));
} }
@Test @Test
public void whenRouteToBeOvertakenRequiresSkillsThatVehicleDoesHave_itShouldReturnTrue(){ public void whenRouteToBeOvertakenRequiresSkillsThatVehicleDoesHave_itShouldReturnTrue(){
Service s4 = mock(Service.class); JobInsertionContext insertionContext = new JobInsertionContext(route,vrp.getJobs().get("s4"),vehicle,route.getDriver(),0.);
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)); 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));
}
} }

View file

@ -18,12 +18,10 @@
******************************************************************************/ ******************************************************************************/
package jsprit.core.problem.job; 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 org.junit.Test;
import static org.junit.Assert.*;
public class DeliveryTest { public class DeliveryTest {
@Test(expected=IllegalStateException.class) @Test(expected=IllegalStateException.class)

View file

@ -18,12 +18,10 @@
******************************************************************************/ ******************************************************************************/
package jsprit.core.problem.job; 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 org.junit.Test;
import static org.junit.Assert.*;
public class PickupTest { public class PickupTest {
@Test(expected=IllegalStateException.class) @Test(expected=IllegalStateException.class)

View file

@ -16,16 +16,14 @@
******************************************************************************/ ******************************************************************************/
package jsprit.core.problem.job; 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.HashSet;
import java.util.Set; 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.*;
import static org.junit.Assert.assertFalse;
public class ServiceTest { public class ServiceTest {

View file

@ -20,7 +20,6 @@ package jsprit.core.problem.job;
import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.problem.solution.route.activity.TimeWindow;
import jsprit.core.util.Coordinate; import jsprit.core.util.Coordinate;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*; import static org.junit.Assert.*;

View file

@ -19,14 +19,12 @@
package jsprit.core.problem.vehicle; 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.problem.vehicle.VehicleImpl.NoVehicle;
import jsprit.core.util.Coordinate; import jsprit.core.util.Coordinate;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*;
public class VehicleImplTest { public class VehicleImplTest {

View file

@ -21,12 +21,14 @@ import jsprit.analysis.toolbox.GraphStreamViewer.Label;
import jsprit.analysis.toolbox.SolutionPrinter; import jsprit.analysis.toolbox.SolutionPrinter;
import jsprit.analysis.toolbox.SolutionPrinter.Print; import jsprit.analysis.toolbox.SolutionPrinter.Print;
import jsprit.core.algorithm.VehicleRoutingAlgorithm; 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.VehicleRoutingProblem;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.io.VrpXMLWriter; import jsprit.core.problem.io.VrpXMLWriter;
import jsprit.core.problem.job.Service; import jsprit.core.problem.job.Service;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution; 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.VehicleImpl.Builder;
import jsprit.core.problem.vehicle.VehicleType; import jsprit.core.problem.vehicle.VehicleType;
import jsprit.core.problem.vehicle.VehicleTypeImpl; import jsprit.core.problem.vehicle.VehicleTypeImpl;
@ -66,13 +68,13 @@ public class SimpleExampleWithSkills {
Builder vehicleBuilder = Builder.newInstance("vehicle"); Builder vehicleBuilder = Builder.newInstance("vehicle");
vehicleBuilder.setStartLocationCoordinate(Coordinate.newInstance(10, 10)); vehicleBuilder.setStartLocationCoordinate(Coordinate.newInstance(10, 10));
vehicleBuilder.setType(vehicleType); vehicleBuilder.setType(vehicleType);
Vehicle vehicle = vehicleBuilder.build(); VehicleImpl vehicle = vehicleBuilder.build();
Builder vehicle2Builder = Builder.newInstance("vehicle2"); Builder vehicle2Builder = Builder.newInstance("vehicle2");
vehicle2Builder.setStartLocationCoordinate(Coordinate.newInstance(1, 1)); vehicle2Builder.setStartLocationCoordinate(Coordinate.newInstance(1, 1));
vehicle2Builder.setType(vehicleType); vehicle2Builder.setType(vehicleType);
vehicle2Builder.addSkill("drill"); vehicle2Builder.addSkill("drill");
Vehicle vehicle2 = vehicle2Builder.build(); VehicleImpl vehicle2 = vehicle2Builder.build();
/* /*
* build services at the required locations, each with a capacity-demand of 1. * 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. * 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 * and search a solution