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

javadoc for CustomJob + some visibility change to make the API more compact

This commit is contained in:
Balázs Vissy 2017-07-31 22:05:23 +02:00
parent bb35142a8f
commit 89570ad2e5
9 changed files with 438 additions and 92 deletions

View file

@ -47,7 +47,7 @@ public class GraphStreamViewerTest {
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setType(type).setBreak(Break.Builder.newInstance("myBreak").addTimeWindow(5, 10).build())
.setStartLocation(Location.newInstance(0, 0))
.build();
CustomJob cj = CustomJob.Builder.newInstance("job")
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addDelivery(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(0, 3).build())
@ -63,7 +63,7 @@ public class GraphStreamViewerTest {
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 3).build();
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocation(Location.newInstance(0, 0))
.setType(type).build();
CustomJob cj = CustomJob.Builder.newInstance("job")
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(-5, 4), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addDelivery(Location.newInstance(20, 10), SizeDimension.Builder.newInstance().addDimension(0, 3).build())
@ -78,7 +78,7 @@ public class GraphStreamViewerTest {
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 3).addCapacityDimension(1, 3).build();
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocation(Location.newInstance(0, 0))
.setType(type).build();
CustomJob cj = CustomJob.Builder.newInstance("job")
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).addDimension(1, 1).build())
.addExchange(Location.newInstance(-5, 4), SizeDimension.Builder.newInstance().addDimension(0, -1).addDimension(1, 1).build())
.addDelivery(Location.newInstance(20, 10), SizeDimension.Builder.newInstance().addDimension(0, 3).build())

View file

@ -45,7 +45,7 @@ public class PlotterTest {
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocation(Location.newInstance(0, 0))
.build();
CustomJob cj = CustomJob.Builder.newInstance("job")
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addDelivery(Location.newInstance(20, 00), SizeDimension.Builder.newInstance().addDimension(0, 3).build())
@ -59,7 +59,7 @@ public class PlotterTest {
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 3).build();
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocation(Location.newInstance(0, 0))
.setType(type).build();
CustomJob cj = CustomJob.Builder.newInstance("job")
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(-5, 4), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addDelivery(Location.newInstance(20, 10), SizeDimension.Builder.newInstance().addDimension(0, 3).build())
@ -74,7 +74,7 @@ public class PlotterTest {
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 3).addCapacityDimension(1, 3).build();
Vehicle vehicle = VehicleImpl.Builder.newInstance("vehicle").setStartLocation(Location.newInstance(0, 0))
.setType(type).build();
CustomJob cj = CustomJob.Builder.newInstance("job")
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).addDimension(1, 1).build())
.addExchange(Location.newInstance(-5, 4), SizeDimension.Builder.newInstance().addDimension(0, -1).addDimension(1, 1).build())
.addDelivery(Location.newInstance(20, 10), SizeDimension.Builder.newInstance().addDimension(0, 3).build())

View file

@ -54,44 +54,101 @@ import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindowsIm
*/
public class CustomJob extends AbstractJob {
/**
* Protected base builder class for {@linkplain CustomJob}.
* <p>
* The class is the protected part of the inheritable builder pattern. For
* more information, see {@linkplain AbstractJob.JobBuilder}.
* </p>
*
* @author Balage
*
* @param <T>
* The type of the job it creates.
* @param <B>
* Self-refering generic value.
*/
protected static abstract class BuilderBase<T extends CustomJob, B extends CustomJob.BuilderBase<T, B>>
extends JobBuilder<T, B> {
/**
* The possible activity types.
*
* <p>
* Note, that the set of activity types are final.
* </p>
*
* @author Balage
*
*/
public enum ActivityType {
/**
* Service activity type.
* <p>
* The service activity type represents an activity with no cargo
* change (nothing is loaded or unloaded).
* </p>
*/
SERVICE {
@Override
public JobActivity create(CustomJob job, BuilderActivityInfo info) {
protected JobActivity create(CustomJob job, BuilderActivityInfo info) {
return new ServiceActivity(job, info.getName() == null ? name().toLowerCase() : info.getName(),
info.getLocation(), info.getOperationTime(), info.getSize(), prepareTimeWindows(info));
}
},
/**
* Pickup activity type.
* <p>
* The pickup activity type represents an activity where something
* is picked up (loaded). It has a positive impact on the cargo
* size.
* </p>
*/
PICKUP {
@Override
public JobActivity create(CustomJob job, BuilderActivityInfo info) {
protected JobActivity create(CustomJob job, BuilderActivityInfo info) {
return new PickupActivity(job, info.getName() == null ? name().toLowerCase() : info.getName(),
info.getLocation(), info.getOperationTime(), info.getSize(), prepareTimeWindows(info));
}
},
/**
* Delivery activity type.
* <p>
* The delivery activity type represents an activity where something
* is delivered (unloaded). It has a negative impact on the cargo
* size.
* </p>
*/
DELIVERY {
@Override
public JobActivity create(CustomJob job, BuilderActivityInfo info) {
protected JobActivity create(CustomJob job, BuilderActivityInfo info) {
return new DeliveryActivity(job, info.getName() == null ? name().toLowerCase() : info.getName(),
info.getLocation(), info.getOperationTime(), info.getSize(), prepareTimeWindows(info));
}
},
/**
* Exchange activity type.
* <p>
* The exchange activity type represents an activity where something
* is delivered and something else is picked up at the same time.
* (loaded and unloaded). It has a mixed (may be even zero) impact
* on the cargo size. It may increase one dimension and reduce
* another one.
* </p>
*/
EXCHANGE {
@Override
public JobActivity create(CustomJob job, BuilderActivityInfo info) {
protected JobActivity create(CustomJob job, BuilderActivityInfo info) {
return new ExchangeActivity(job, info.getName() == null ? name().toLowerCase() : info.getName(),
info.getLocation(), info.getOperationTime(), info.getSize(), prepareTimeWindows(info));
}
};
public abstract JobActivity create(CustomJob job, BuilderActivityInfo builderActivityInfo);
protected abstract JobActivity create(CustomJob job, BuilderActivityInfo builderActivityInfo);
private static Collection<TimeWindow> prepareTimeWindows(BuilderActivityInfo info) {
TimeWindows tws = info.getTimeWindows();
@ -103,6 +160,18 @@ public class CustomJob extends AbstractJob {
}
/**
* Class for defining custom activities when the standard methods of
* {@linkplain Builder} are not enough. The class applies the fluent API
* pattern.
* <p>
* Note that this class is <b>NOT</b> immutable, so always create a new
* instance for each activity!
* </p>
*
* @author Balage
*
*/
public static class BuilderActivityInfo {
private ActivityType type;
private Location locs;
@ -112,69 +181,146 @@ public class CustomJob extends AbstractJob {
private TimeWindowsImpl timeWindows = new TimeWindowsImpl();
/**
* Constructs a new instance.
*
* @param type
* The type of the activity.
* @param locs
* The location of the activity.
*/
public BuilderActivityInfo(ActivityType type, Location locs) {
super();
this.type = type;
this.locs = locs;
}
/**
* @return The type of the activity.
*/
public ActivityType getType() {
return type;
}
/**
* @return The location of the activity.
*/
public Location getLocation() {
return locs;
}
/**
* @return The size dimensions (cargo change) of the activity.
*/
public SizeDimension getSize() {
return size;
}
/**
* Sets the size dimensions (cargo change) of the activity.
*
* @param size
* The size dimensions. (May be negative.)
* @return The info object.
*/
public BuilderActivityInfo withSize(SizeDimension size) {
this.size = size;
return this;
}
/**
* @return The name of the activity (for debug and reporting).
*/
public String getName() {
return name;
}
/**
* Sets the name of the activity for debugging and reporting
* purpose.
*
* @param name
* The name.
* @return The info object.
*/
public BuilderActivityInfo withName(String name) {
this.name = name;
return this;
}
/**
* @return The time windows of the activity.
*/
public TimeWindows getTimeWindows() {
return timeWindows;
}
/**
* Adds a time window to the activity.
*
* @param timeWindow
* A time window.
* @return The info object.
*/
public BuilderActivityInfo withTimeWindow(TimeWindow timeWindow) {
timeWindows.add(timeWindow);
return this;
}
public BuilderActivityInfo withTimeWindows(TimeWindow... tws) {
timeWindows.addAll(tws);
/**
* Adds several time windows to the activity.
*
* @param timeWindows
* The list of time windows.
* @return The info object.
*/
public BuilderActivityInfo withTimeWindows(TimeWindow... timeWindows) {
this.timeWindows.addAll(timeWindows);
return this;
}
/**
* Adds several time windows.
*
* @param tws
* The collection of time windows.
* @return The info object.
*/
public BuilderActivityInfo withTimeWindows(Collection<TimeWindow> tws) {
timeWindows.addAll(tws);
return this;
}
/**
* @return The operation time (time taken to fulfill the activity at
* the location) of the activity.
*/
public double getOperationTime() {
return operationTime;
}
/**
* Sets the operation time (time taken to fulfill the activity at
* the location).
*
* @param operationTime
* The operation time.
* @return The info object.
*/
public BuilderActivityInfo withOperationTime(double operationTime) {
this.operationTime = operationTime;
return this;
}
}
List<BuilderActivityInfo> acts = new ArrayList<>();
private List<BuilderActivityInfo> acts = new ArrayList<>();
/**
* Constructor.
*
* @param id
* The id of the job. Should be unique within the problem.
*/
public BuilderBase(String id) {
super(id);
}
@ -186,8 +332,28 @@ public class CustomJob extends AbstractJob {
}
/**
* General activity add method.
* <p>
* It constructs a {@linkplain BuilderActivityInfo} objects and calls
* the {@linkplain #addActivity(BuilderActivityInfo)} function.
* </p>
*
* @param type
* The type of the activity.
* @param location
* The location of the activity.
* @param operationTime
* The operation time of the activity.
* @param size
* The cargo change of the activity. May be null.
* @param name
* The name of the activity. May be null.
* @param timeWindows
* The time windows of the activity. May be null.
*/
private void add(ActivityType type, Location location, double operationTime, SizeDimension size, String name,
Collection<TimeWindow> tws) {
Collection<TimeWindow> timeWindows) {
BuilderActivityInfo builderActivityInfo = new BuilderActivityInfo(type, location);
builderActivityInfo.withOperationTime(operationTime);
if (name != null) {
@ -196,8 +362,8 @@ public class CustomJob extends AbstractJob {
if (size != null) {
builderActivityInfo.withSize(size);
}
if (tws != null) {
builderActivityInfo.withTimeWindows(tws);
if (timeWindows != null) {
builderActivityInfo.withTimeWindows(timeWindows);
}
acts.add(builderActivityInfo);
@ -205,79 +371,191 @@ public class CustomJob extends AbstractJob {
// Service
/**
* Adds a {@linkplain ActivityType#SERVICE} activity to the job with 0
* operation time, without time windows and name.
*
* @param location
* The location of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addService(Location location) {
add(ActivityType.SERVICE, location, 0d, null, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#SERVICE} activity to the job without
* time windows and name.
*
* @param location
* The location of the activity.
* @param operationTime
* The operation time of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addService(Location location, SizeDimension size) {
add(ActivityType.SERVICE, location, 0d, size, null, null);
public B addService(Location location, double operationTime) {
add(ActivityType.SERVICE, location, operationTime, null, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#SERVICE} activity to the job without
* name and with a single time window.
*
* @param location
* The location of the activity.
* @param operationTime
* The operation time of the activity.
* @param timeWindow
* The time window of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addService(Location location, SizeDimension size, double operationTime) {
add(ActivityType.SERVICE, location, operationTime, size, null, null);
return (B) this;
}
@SuppressWarnings("unchecked")
public B addService(Location location, SizeDimension size, double operationTime,
TimeWindow tw) {
add(ActivityType.SERVICE, location, operationTime, size, null, Collections.singleton(tw));
public B addService(Location location, double operationTime, TimeWindow timeWindow) {
add(ActivityType.SERVICE, location, operationTime, null, null, Collections.singleton(timeWindow));
return (B) this;
}
// Pickup
/**
* Adds a {@linkplain ActivityType#PICKUP} activity to the job with 0
* operation time, without cargo change, time windows and name.
*
* @param location
* The location of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addPickup(Location location) {
add(ActivityType.PICKUP, location, 0d, null, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#PICKUP} activity to the job with 0
* operation time, without time windows and name.
*
* @param location
* The location of the activity.
* @param size
* The cargo change of the pickup. Should be positive.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addPickup(Location location, SizeDimension size) {
add(ActivityType.PICKUP, location, 0d, size, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#PICKUP} activity to the job without
* time windows and name.
*
* @param location
* The location of the activity.
* @param size
* The cargo change of the pickup. Should be positive.
* @param operationTime
* The operation time of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addPickup(Location location, SizeDimension size, double operationTime) {
add(ActivityType.PICKUP, location, operationTime, size, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#PICKUP} activity to the job without
* name and with a single time window.
*
* @param location
* The location of the activity.
* @param size
* The cargo change of the pickup. Should be positive.
* @param operationTime
* The operation time of the activity.
* @param timeWindow
* The time window of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addPickup(Location location, SizeDimension size, double operationTime,
TimeWindow tw) {
add(ActivityType.PICKUP, location, operationTime, size, null, Collections.singleton(tw));
TimeWindow timeWindow) {
add(ActivityType.PICKUP, location, operationTime, size, null, Collections.singleton(timeWindow));
return (B) this;
}
// Delivery
/**
* Adds a {@linkplain ActivityType#DELIVERY} activity to the job with 0
* operation time, without cargo change, time windows and name.
*
* @param location
* The location of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addDelivery(Location location) {
add(ActivityType.DELIVERY, location, 0d, null, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#DELIVERY} activity to the job with 0
* operation time, without time windows and name.
*
* @param location
* The location of the activity.
* @param size
* The cargo change of the delivery. Should be negative.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addDelivery(Location location, SizeDimension size) {
add(ActivityType.DELIVERY, location, 0d, size, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#DELIVERY} activity to the job without
* time windows and name.
*
* @param location
* The location of the activity.
* @param size
* The cargo change of the delivery. Should be negative.
* @param operationTime
* The operation time of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addDelivery(Location location, SizeDimension size, double operationTime) {
add(ActivityType.DELIVERY, location, operationTime, size, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#DELIVERY} activity to the job without
* name and with a single time window.
*
* @param location
* The location of the activity.
* @param size
* The cargo change of the delivery. Should be negative.
* @param operationTime
* The operation time of the activity.
* @param timeWindow
* The time window of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addDelivery(Location location, SizeDimension size, double operationTime,
TimeWindow tw) {
@ -287,24 +565,71 @@ public class CustomJob extends AbstractJob {
// Exchange
/**
* Adds a {@linkplain ActivityType#EXCHANGE} activity to the job with 0
* operation time, without cargo change, time windows and name.
*
* @param location
* The location of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addExchange(Location location) {
add(ActivityType.EXCHANGE, location, 0d, null, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#EXCHANGE} activity to the job with 0
* operation time, without time windows and name.
*
* @param location
* The location of the activity.
* @param size
* The cargo change of the exchange. May be negative,
* positive or mixed.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addExchange(Location location, SizeDimension size) {
add(ActivityType.EXCHANGE, location, 0d, size, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#EXCHANGE} activity to the job without
* time windows and name.
*
* @param location
* The location of the activity.
* @param size
* The cargo change of the exchange. May be negative,
* positive or mixed.
* @param operationTime
* The operation time of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addExchange(Location location, SizeDimension size, double operationTime) {
add(ActivityType.EXCHANGE, location, operationTime, size, null, null);
return (B) this;
}
/**
* Adds a {@linkplain ActivityType#EXCHANGE} activity to the job without
* name and with a single time window.
*
* @param location
* The location of the activity.
* @param size
* The cargo change of the exchange. May be negative,
* positive or mixed.
* @param operationTime
* The operation time of the activity.
* @param timeWindow
* The time window of the activity.
* @return The builder instance.
*/
@SuppressWarnings("unchecked")
public B addExchange(Location location, SizeDimension size, double operationTime,
TimeWindow tw) {
@ -318,7 +643,7 @@ public class CustomJob extends AbstractJob {
throw new IllegalStateException("There is no activities defined on this job.");
}
public List<BuilderActivityInfo> getActs() {
public List<BuilderActivityInfo> getActivities() {
return Collections.unmodifiableList(acts);
}
@ -334,20 +659,53 @@ public class CustomJob extends AbstractJob {
* included into the solution.
* </p>
* <p>
* The builder contains methods for simply configuring basic activities. If
* more control needed on the activity creation, an ActivityBuild
* The main difference between the jobs and activities known from version 1
* and 2 is the bias shift from job to activity. Before version 2 the jobs
* has holden most of the business information and activities were
* second-class entities, meanwhile the algorithm worked on activities. This
* has driven to a state where the code had no indication which job field
* belonged to which activities.
* </p>
* <p>
* In the new concept a stronger encapsulation ensures the right behavior.
* This led to most of the business data to move from job to activity. These
* are:
* <ul>
* <li>Load change (how the cargo size change (increase or decrease) on the
* vehicle)</li>
* <li>Location (where the activity should be executed)</li>
* <li>Time windows (when the activity should be performed)</li>
* <li>Operation time (how much time it takes to fulfill the activity)</li>
* </ul>
* These parameters are now defined per activity.
* </p>
* <p>
* Some information has left in the scope of the job, because they affects
* the whole job:
* <ul>
* <li>Required skills</li>
* <li>Priority</li>
* </ul>
* </p>
* <p>
* The builder contains methods for simply configuring basic activities.
* They are the counterparts of the version 1 job builders. If more control
* is needed on the activity creation, an {@linkplain BuilderActivityInfo}
* record has to be created and passed to the builder. (<i>This indirection
* is required to keep immutable behavior of a job and its activities after
* creation.</i>)
* </p>
*
*
* @author Balage
*
*/
public static final class Builder extends CustomJob.BuilderBase<CustomJob, CustomJob.Builder> {
public static CustomJob.Builder newInstance(String id) {
return new CustomJob.Builder(id);
}
/**
* Constructor.
*
* @param id
* The id of the job. Should be unique within a problem.
*/
public Builder(String id) {
super(id);
}
@ -379,7 +737,7 @@ public class CustomJob extends AbstractJob {
protected void createActivities(JobBuilder<? extends AbstractJob, ?> jobBuilder) {
CustomJob.Builder builder = (CustomJob.Builder) jobBuilder;
JobActivityList list = new SequentialJobActivityList(this);
for (CustomJob.Builder.BuilderActivityInfo info : builder.getActs()) {
for (CustomJob.Builder.BuilderActivityInfo info : builder.getActivities()) {
JobActivity act = info.getType().create(this, info);
list.addActivity(act);
}

View file

@ -54,14 +54,10 @@ import com.graphhopper.jsprit.core.util.Coordinate;
*
* <ul>
* <li>{@linkplain CustomJob.Builder#addService(Location)}</li>
* <li>
* {@linkplain CustomJob.Builder#addService(Location, SizeDimension)}
* <li>{@linkplain CustomJob.Builder#addService(Location, double)}
* </li>
* <li>
* {@linkplain CustomJob.Builder#addService(Location, SizeDimension, double)}
* </li>
* <li>
* {@linkplain CustomJob.Builder#addService(Location, SizeDimension, double, TimeWindow)}
* {@linkplain CustomJob.Builder#addService(Location, double, TimeWindow)}
* </li>
* </ul>
*

View file

@ -17,7 +17,6 @@
*/
package com.graphhopper.jsprit.core.problem.job;
import com.graphhopper.jsprit.core.problem.SizeDimension;
import com.graphhopper.jsprit.core.problem.solution.route.activity.ServiceActivity;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
@ -35,9 +34,8 @@ import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
* @author Balage
*
* @see {@linkplain CustomJob.BuilderBase#addService(Location)}
* @see {@linkplain CustomJob.BuilderBase#addService(Location, SizeDimension)}
* @see {@linkplain CustomJob.BuilderBase#addService(Location, SizeDimension, double)}
* @see {@linkplain CustomJob.BuilderBase#addService(Location, SizeDimension, double, TimeWindow)}
* @see {@linkplain CustomJob.BuilderBase#addService(Location, double)}
* @see {@linkplain CustomJob.BuilderBase#addService(Location, double, TimeWindow)}
*/
public class ServiceJob extends AbstractSingleActivityJob<ServiceActivity> {

View file

@ -76,13 +76,7 @@ import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindowsIm
* <ul>
* <li>{@linkplain CustomJob.Builder#addService(Location)}</li>
* <li>
* {@linkplain CustomJob.Builder#addService(Location, SizeDimension)}
* </li>
* <li>
* {@linkplain CustomJob.Builder#addService(Location, SizeDimension, double)}
* </li>
* <li>
* {@linkplain CustomJob.Builder#addService(Location, SizeDimension, double, TimeWindow)}
* {@linkplain CustomJob.Builder#addService(Location, double, TimeWindow)}
* </li>
* </ul>
*

View file

@ -39,11 +39,11 @@ public class FirstCustomJobExample {
@Test
public void test() {
CustomJob cj = CustomJob.Builder.newInstance("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.EMPTY).build();
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.EMPTY).build();
Vehicle v = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(0, 0)).build();
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
.addJob(cj).addVehicle(v).build();
.addJob(cj).addVehicle(v).build();
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
SolutionPrinter.print(vrp, solution, SolutionPrinter.Print.VERBOSE);

View file

@ -45,15 +45,15 @@ public class FirstCustomJobWithMultipleActivitiesExample {
@Test
public void shouldRunOK() {
CustomJob cj = CustomJob.Builder.newInstance("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addPickup(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.build();
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addPickup(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.build();
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 4).build();
Vehicle v = VehicleImpl.Builder.newInstance("v").setType(type).setStartLocation(Location.newInstance(0, 0)).build();
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
.addJob(cj).addVehicle(v).build();
.addJob(cj).addVehicle(v).build();
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
vra.setMaxIterations(10);
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
@ -63,15 +63,15 @@ public class FirstCustomJobWithMultipleActivitiesExample {
@Test
public void shouldNotIgnoresCapacity() {
CustomJob cj = CustomJob.Builder.newInstance("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addPickup(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.build();
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addPickup(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.build();
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 2).build();
Vehicle v = VehicleImpl.Builder.newInstance("v").setType(type).setStartLocation(Location.newInstance(0, 0)).build();
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
.addJob(cj).addVehicle(v).build();
.addJob(cj).addVehicle(v).build();
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
vra.setMaxIterations(10);
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
@ -81,15 +81,15 @@ public class FirstCustomJobWithMultipleActivitiesExample {
@Test
public void shouldNotIgnoresCapacityWithMixedPicksAndDeliveries() {
CustomJob cj = CustomJob.Builder.newInstance("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addDelivery(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(0, 3).build())
.build();
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addDelivery(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(0, 3).build())
.build();
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 2).build();
Vehicle v = VehicleImpl.Builder.newInstance("v").setType(type).setStartLocation(Location.newInstance(0, 0)).build();
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
.addJob(cj).addVehicle(v).build();
.addJob(cj).addVehicle(v).build();
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
vra.setMaxIterations(10);
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
@ -99,17 +99,17 @@ public class FirstCustomJobWithMultipleActivitiesExample {
@Test
public void shouldNotIgnoresCapacityWithMixedPicksAndDeliveriesV2() {
CustomJob cj = CustomJob.Builder.newInstance("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addDelivery(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(0, 3).build())
.build();
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addDelivery(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(0, 3).build())
.build();
assertEquals(SizeDimension.Builder.newInstance().addDimension(0, 0).build(), cj.getSizeAtStart());
assertEquals(SizeDimension.Builder.newInstance().addDimension(0, 0).build(), cj.getSizeAtEnd());
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 3).build();
Vehicle v = VehicleImpl.Builder.newInstance("v").setType(type).setStartLocation(Location.newInstance(0, 0)).build();
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
.addJob(cj).addVehicle(v).build();
.addJob(cj).addVehicle(v).build();
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
vra.setMaxIterations(10);
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());
@ -119,15 +119,15 @@ public class FirstCustomJobWithMultipleActivitiesExample {
@Test
public void shouldNotIgnoresCapacityWithExchange() {
CustomJob cj = CustomJob.Builder.newInstance("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).addDimension(1, 0).build())
.addExchange(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, -3).addDimension(1, 2).build())
.addDelivery(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(1, 1).build())
.build();
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).addDimension(1, 0).build())
.addExchange(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, -3).addDimension(1, 2).build())
.addDelivery(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(1, 1).build())
.build();
VehicleType type = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 3).addCapacityDimension(1, 2).build();
Vehicle v = VehicleImpl.Builder.newInstance("v").setType(type).setStartLocation(Location.newInstance(0, 0)).build();
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
.addJob(cj).addVehicle(v).build();
.addJob(cj).addVehicle(v).build();
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
vra.setMaxIterations(10);
VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());

View file

@ -111,7 +111,7 @@ public class LoadConstraintTest {
@Test
public void whenCustomJob_itShouldNotIgnoreCapacity() {
CustomJob cj = CustomJob.Builder.newInstance("job")
CustomJob cj = new CustomJob.Builder("job")
.addPickup(Location.newInstance(10, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
.addPickup(Location.newInstance(5, 0), SizeDimension.Builder.newInstance().addDimension(0, 2).build())
.addPickup(Location.newInstance(20, 0), SizeDimension.Builder.newInstance().addDimension(0, 1).build())
@ -276,7 +276,7 @@ public class LoadConstraintTest {
public void whenPDRouteRouteAndNewDeliveryFitsIn_itShouldReturnFulfilled() {
stateManager.informInsertionStarts(Arrays.asList(pickupDeliveryRoute), Collections.emptyList());
DeliveryJob s = new DeliveryJob.Builder("del").addSizeDimension(0, 15).setLocation(Location.newInstance(0))
.build();
.build();
ServiceLoadRouteLevelConstraint loadConstraint = new ServiceLoadRouteLevelConstraint(stateManager);
JobInsertionContext context = new JobInsertionContext(pickupDeliveryRoute, s, serviceRoute.getVehicle(), null, 0.);
assertTrue(loadConstraint.fulfilled(context));