mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
Compare commits
9 commits
47566d750c
...
d03906950f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d03906950f | ||
|
|
7351a05730 | ||
|
|
af69361cd4 | ||
|
|
d8bb1ca95a | ||
|
|
298210bb9c | ||
|
|
ac84b62651 | ||
|
|
ad851b1951 | ||
|
|
fe590fc9f8 | ||
|
|
dd3f29b5cc |
20 changed files with 363 additions and 322 deletions
|
|
@ -153,8 +153,6 @@ public class AlgorithmEventsViewer {
|
|||
|
||||
private long delayRuin = 5;
|
||||
|
||||
private long delay = 2;
|
||||
|
||||
public void setRecreationDelay(long delay_in_ms) {
|
||||
this.delayRecreation = delay_in_ms;
|
||||
}
|
||||
|
|
@ -174,6 +172,7 @@ public class AlgorithmEventsViewer {
|
|||
|
||||
DelayContainer delayContainer = new DelayContainer();
|
||||
DelaySink delaySink = new DelaySink(delayContainer);
|
||||
long delay = 2;
|
||||
delaySink.setDelay(delay);
|
||||
delaySink.setRecreateDelay(delayRecreation);
|
||||
delaySink.setRuinDelay(delayRuin);
|
||||
|
|
@ -197,7 +196,7 @@ public class AlgorithmEventsViewer {
|
|||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
public static void main(String[] args) {
|
||||
AlgorithmEventsViewer viewer = new AlgorithmEventsViewer();
|
||||
viewer.setRuinDelay(10);
|
||||
viewer.setRecreationDelay(5);
|
||||
|
|
|
|||
|
|
@ -19,9 +19,8 @@ package com.graphhopper.jsprit.analysis.toolbox;
|
|||
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.Activity;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
import com.graphhopper.jsprit.core.problem.job.Shipment;
|
||||
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.DeliveryActivity;
|
||||
|
|
@ -46,7 +45,7 @@ public class GraphStreamViewer {
|
|||
|
||||
public static class StyleSheets {
|
||||
|
||||
public static String BLUE_FOREST =
|
||||
static String BLUE_FOREST =
|
||||
"graph { fill-color: #141F2E; }" +
|
||||
"node {" +
|
||||
" size: 7px, 7px;" +
|
||||
|
|
@ -169,7 +168,7 @@ public class GraphStreamViewer {
|
|||
|
||||
}
|
||||
|
||||
public static Graph createMultiGraph(String name, String style) {
|
||||
static Graph createMultiGraph(String name, String style) {
|
||||
Graph g = new MultiGraph(name);
|
||||
g.addAttribute("ui.quality");
|
||||
g.addAttribute("ui.antialias");
|
||||
|
|
@ -177,66 +176,14 @@ public class GraphStreamViewer {
|
|||
return g;
|
||||
}
|
||||
|
||||
public static ViewPanel createEmbeddedView(Graph graph, double scaling) {
|
||||
private static ViewPanel createEmbeddedView(Graph graph, double scaling) {
|
||||
Viewer viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
|
||||
ViewPanel view = viewer.addDefaultView(false);
|
||||
view.setPreferredSize(new Dimension((int) (698 * scaling), (int) (440 * scaling)));
|
||||
return view;
|
||||
}
|
||||
|
||||
public static String STYLESHEET =
|
||||
"node {" +
|
||||
" size: 10px, 10px;" +
|
||||
" fill-color: #6CC644;" +
|
||||
" text-alignment: at-right;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #999;" +
|
||||
" stroke-width: 1.0;" +
|
||||
" text-font: couriernew;" +
|
||||
" text-offset: 2,-5;" +
|
||||
" text-size: 8;" +
|
||||
"}" +
|
||||
"node.pickup {" +
|
||||
" fill-color: #6CC644;" +
|
||||
"}" +
|
||||
"node.delivery {" +
|
||||
" fill-color: #f93;" +
|
||||
"}" +
|
||||
"node.pickupInRoute {" +
|
||||
" fill-color: #6CC644;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.deliveryInRoute {" +
|
||||
" fill-color: #f93;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.depot {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" shape: box;" +
|
||||
"}" +
|
||||
"node.removed {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
|
||||
"edge {" +
|
||||
" fill-color: #333;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" +
|
||||
"edge.shipment {" +
|
||||
" fill-color: #999;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}";
|
||||
|
||||
public static enum Label {
|
||||
public enum Label {
|
||||
NO_LABEL, ID, JOB_NAME, ARRIVAL_TIME, DEPARTURE_TIME, ACTIVITY
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +191,7 @@ public class GraphStreamViewer {
|
|||
final double x;
|
||||
final double y;
|
||||
|
||||
public Center(double x, double y) {
|
||||
Center(double x, double y) {
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
|
@ -319,13 +266,9 @@ public class GraphStreamViewer {
|
|||
|
||||
public void display() {
|
||||
System.setProperty("org.graphstream.ui.renderer", "org.graphstream.ui.j2dviewer.J2DGraphRenderer");
|
||||
|
||||
Graph g = createMultiGraph("g");
|
||||
|
||||
Graph g = createMultiGraph();
|
||||
ViewPanel view = createEmbeddedView(g, scaling);
|
||||
|
||||
createJFrame(view, scaling);
|
||||
|
||||
render(g, view);
|
||||
}
|
||||
|
||||
|
|
@ -369,8 +312,58 @@ public class GraphStreamViewer {
|
|||
return jframe;
|
||||
}
|
||||
|
||||
private Graph createMultiGraph(String name) {
|
||||
return GraphStreamViewer.createMultiGraph(name, STYLESHEET);
|
||||
private Graph createMultiGraph() {
|
||||
String STYLESHEET = "node {" +
|
||||
" size: 10px, 10px;" +
|
||||
" fill-color: #6CC644;" +
|
||||
" text-alignment: at-right;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #999;" +
|
||||
" stroke-width: 1.0;" +
|
||||
" text-font: couriernew;" +
|
||||
" text-offset: 2,-5;" +
|
||||
" text-size: 8;" +
|
||||
"}" +
|
||||
"node.pickup {" +
|
||||
" fill-color: #6CC644;" +
|
||||
"}" +
|
||||
"node.delivery {" +
|
||||
" fill-color: #f93;" +
|
||||
"}" +
|
||||
"node.pickupInRoute {" +
|
||||
" fill-color: #6CC644;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.deliveryInRoute {" +
|
||||
" fill-color: #f93;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
"node.depot {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" shape: box;" +
|
||||
"}" +
|
||||
"node.removed {" +
|
||||
" fill-color: #BD2C00;" +
|
||||
" size: 10px, 10px;" +
|
||||
" stroke-mode: plain;" +
|
||||
" stroke-color: #333;" +
|
||||
" stroke-width: 2.0;" +
|
||||
"}" +
|
||||
|
||||
"edge {" +
|
||||
" fill-color: #333;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}" +
|
||||
"edge.shipment {" +
|
||||
" fill-color: #999;" +
|
||||
" arrow-size: 6px,3px;" +
|
||||
"}";
|
||||
return GraphStreamViewer.createMultiGraph("g", STYLESHEET);
|
||||
}
|
||||
|
||||
private void render(Graph g, ViewPanel view) {
|
||||
|
|
@ -385,11 +378,7 @@ public class GraphStreamViewer {
|
|||
}
|
||||
|
||||
for (Job j : vrp.getJobs().values()) {
|
||||
if (j instanceof Service) {
|
||||
renderService(g, (Service) j, label);
|
||||
} else if (j instanceof Shipment) {
|
||||
renderShipment(g, (Shipment) j, label, renderShipments);
|
||||
}
|
||||
renderJob(g, j, label);
|
||||
sleep(renderDelay_in_ms);
|
||||
}
|
||||
|
||||
|
|
@ -404,6 +393,7 @@ public class GraphStreamViewer {
|
|||
|
||||
}
|
||||
|
||||
|
||||
private void alignCamera(View view) {
|
||||
view.getCamera().setViewCenter(center.x, center.y, 0);
|
||||
view.getCamera().setViewPercent(zoomFactor);
|
||||
|
|
@ -501,26 +491,22 @@ public class GraphStreamViewer {
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
private void renderShipment(Graph g, Shipment shipment, Label label, boolean renderShipments) {
|
||||
|
||||
Node n1 = g.addNode(makeId(shipment.getId(), shipment.getPickupLocation().getId()));
|
||||
if (label.equals(Label.ID)) n1.addAttribute("ui.label", shipment.getId());
|
||||
n1.addAttribute("x", shipment.getPickupLocation().getCoordinate().getX());
|
||||
n1.addAttribute("y", shipment.getPickupLocation().getCoordinate().getY());
|
||||
n1.setAttribute("ui.class", "pickup");
|
||||
|
||||
Node n2 = g.addNode(makeId(shipment.getId(), shipment.getDeliveryLocation().getId()));
|
||||
if (label.equals(Label.ID)) n2.addAttribute("ui.label", shipment.getId());
|
||||
n2.addAttribute("x", shipment.getDeliveryLocation().getCoordinate().getX());
|
||||
n2.addAttribute("y", shipment.getDeliveryLocation().getCoordinate().getY());
|
||||
n2.setAttribute("ui.class", "delivery");
|
||||
|
||||
if (renderShipments) {
|
||||
Edge s = g.addEdge(shipment.getId(), makeId(shipment.getId(), shipment.getPickupLocation().getId()),
|
||||
makeId(shipment.getId(), shipment.getDeliveryLocation().getId()), true);
|
||||
s.addAttribute("ui.class", "shipment");
|
||||
private void renderJob(Graph g, Job j, Label label) {
|
||||
String lastNodeId = null;
|
||||
for (Activity act : j.getActivities()) {
|
||||
String nodeId = makeId(j.getId(), act.getLocation().getId());
|
||||
Node n1 = g.addNode(nodeId);
|
||||
if (label.equals(Label.ID)) n1.addAttribute("ui.label", j.getId());
|
||||
n1.addAttribute("x", act.getLocation().getCoordinate().getX());
|
||||
n1.addAttribute("y", act.getLocation().getCoordinate().getY());
|
||||
if (act.getActivityType().equals(Activity.Type.PICKUP)) n1.setAttribute("ui.class", "pickup");
|
||||
else if (act.getActivityType().equals(Activity.Type.DELIVERY)) n1.setAttribute("ui.class", "delivery");
|
||||
if (renderShipments && lastNodeId != null) {
|
||||
Edge s = g.addEdge(j.getId(), lastNodeId, nodeId, true);
|
||||
s.addAttribute("ui.class", "shipment");
|
||||
}
|
||||
lastNodeId = nodeId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void sleep(long renderDelay_in_ms2) {
|
||||
|
|
@ -532,15 +518,6 @@ public class GraphStreamViewer {
|
|||
}
|
||||
}
|
||||
|
||||
private void renderService(Graph g, Service service, Label label) {
|
||||
Node n = g.addNode(makeId(service.getId(), service.getLocation().getId()));
|
||||
if (label.equals(Label.ID)) n.addAttribute("ui.label", service.getId());
|
||||
n.addAttribute("x", service.getLocation().getCoordinate().getX());
|
||||
n.addAttribute("y", service.getLocation().getCoordinate().getY());
|
||||
if (service.getType().equals("pickup")) n.setAttribute("ui.class", "pickup");
|
||||
if (service.getType().equals("delivery")) n.setAttribute("ui.class", "delivery");
|
||||
}
|
||||
|
||||
private String makeId(String id, String locationId) {
|
||||
return id + "_" + locationId;
|
||||
}
|
||||
|
|
@ -575,18 +552,24 @@ public class GraphStreamViewer {
|
|||
if (act instanceof JobActivity) {
|
||||
Job job = ((JobActivity) act).getJob();
|
||||
String currIdentifier = makeId(job.getId(), act.getLocation().getId());
|
||||
if (label.equals(Label.ACTIVITY)) {
|
||||
Node actNode = g.getNode(currIdentifier);
|
||||
actNode.addAttribute("ui.label", act.getName());
|
||||
} else if (label.equals(Label.JOB_NAME)) {
|
||||
Node actNode = g.getNode(currIdentifier);
|
||||
actNode.addAttribute("ui.label", job.getName());
|
||||
} else if (label.equals(Label.ARRIVAL_TIME)) {
|
||||
Node actNode = g.getNode(currIdentifier);
|
||||
actNode.addAttribute("ui.label", Time.parseSecondsToTime(act.getArrTime()));
|
||||
} else if (label.equals(Label.DEPARTURE_TIME)) {
|
||||
Node actNode = g.getNode(currIdentifier);
|
||||
actNode.addAttribute("ui.label", Time.parseSecondsToTime(act.getEndTime()));
|
||||
Node actNode = g.getNode(currIdentifier);
|
||||
switch (label) {
|
||||
case ACTIVITY: {
|
||||
actNode.addAttribute("ui.label", act.getName());
|
||||
break;
|
||||
}
|
||||
case JOB_NAME: {
|
||||
actNode.addAttribute("ui.label", job.getName());
|
||||
break;
|
||||
}
|
||||
case ARRIVAL_TIME: {
|
||||
actNode.addAttribute("ui.label", Time.parseSecondsToTime(act.getArrTime()));
|
||||
break;
|
||||
}
|
||||
case DEPARTURE_TIME: {
|
||||
actNode.addAttribute("ui.label", Time.parseSecondsToTime(act.getEndTime()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
g.addEdge(makeEdgeId(routeId, vehicle_edgeId), prevIdentifier, currIdentifier, true);
|
||||
if (act instanceof PickupActivity) g.getNode(currIdentifier).addAttribute("ui.class", "pickupInRoute");
|
||||
|
|
@ -607,7 +590,4 @@ public class GraphStreamViewer {
|
|||
return Integer.valueOf(routeId).toString() + "." + Integer.valueOf(vehicle_edgeId).toString();
|
||||
}
|
||||
|
||||
// public void saveAsPNG(String filename){
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package com.graphhopper.jsprit.analysis.toolbox;
|
|||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.*;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||
|
|
@ -27,14 +27,12 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
|||
import com.graphhopper.jsprit.core.util.Coordinate;
|
||||
import org.jfree.chart.*;
|
||||
import org.jfree.chart.axis.NumberAxis;
|
||||
import org.jfree.chart.labels.XYItemLabelGenerator;
|
||||
import org.jfree.chart.plot.XYPlot;
|
||||
import org.jfree.chart.renderer.xy.XYItemRenderer;
|
||||
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
|
||||
import org.jfree.chart.title.LegendTitle;
|
||||
import org.jfree.data.Range;
|
||||
import org.jfree.data.xy.XYDataItem;
|
||||
import org.jfree.data.xy.XYDataset;
|
||||
import org.jfree.data.xy.XYSeries;
|
||||
import org.jfree.data.xy.XYSeriesCollection;
|
||||
import org.jfree.ui.RectangleEdge;
|
||||
|
|
@ -79,7 +77,7 @@ public class Plotter {
|
|||
|
||||
private Set<XYDataItem> firstActivities;
|
||||
|
||||
public MyActivityRenderer(XYSeriesCollection seriesCollection, Map<XYDataItem, Activity> activities, Set<XYDataItem> firstActivities) {
|
||||
MyActivityRenderer(XYSeriesCollection seriesCollection, Map<XYDataItem, Activity> activities, Set<XYDataItem> firstActivities) {
|
||||
super(false, true);
|
||||
this.seriesCollection = seriesCollection;
|
||||
this.activities = activities;
|
||||
|
|
@ -126,7 +124,7 @@ public class Plotter {
|
|||
double maxX;
|
||||
double maxY;
|
||||
|
||||
public BoundingBox(double minX, double minY, double maxX, double maxY) {
|
||||
BoundingBox(double minX, double minY, double maxX, double maxY) {
|
||||
super();
|
||||
this.minX = minX;
|
||||
this.minY = minY;
|
||||
|
|
@ -148,7 +146,7 @@ public class Plotter {
|
|||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
public static enum Label {
|
||||
public enum Label {
|
||||
ID, SIZE, @SuppressWarnings("UnusedDeclaration")NO_LABEL
|
||||
}
|
||||
|
||||
|
|
@ -164,13 +162,13 @@ public class Plotter {
|
|||
|
||||
private BoundingBox boundingBox = null;
|
||||
|
||||
private Map<XYDataItem, Activity> activitiesByDataItem = new HashMap<XYDataItem, Plotter.Activity>();
|
||||
private Map<XYDataItem, Activity> activitiesByDataItem = new HashMap<>();
|
||||
|
||||
private Map<XYDataItem, String> labelsByDataItem = new HashMap<XYDataItem, String>();
|
||||
private Map<XYDataItem, String> labelsByDataItem = new HashMap<>();
|
||||
|
||||
private XYSeries activities;
|
||||
|
||||
private Set<XYDataItem> firstActivities = new HashSet<XYDataItem>();
|
||||
private Set<XYDataItem> firstActivities = new HashSet<>();
|
||||
|
||||
private boolean containsPickupAct = false;
|
||||
|
||||
|
|
@ -247,7 +245,7 @@ public class Plotter {
|
|||
* @param minY lower left y
|
||||
* @param maxX upper right x
|
||||
* @param maxY upper right y
|
||||
* @return
|
||||
* @return Plotter
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Plotter setBoundingBox(double minX, double minY, double maxX, double maxY) {
|
||||
|
|
@ -321,27 +319,15 @@ public class Plotter {
|
|||
@Override
|
||||
public LegendItemCollection getLegendItems() {
|
||||
LegendItemCollection lic = new LegendItemCollection();
|
||||
LegendItem vehLoc = new LegendItem("vehLoc", Color.RED);
|
||||
vehLoc.setShape(ELLIPSE);
|
||||
vehLoc.setShapeVisible(true);
|
||||
lic.add(vehLoc);
|
||||
addLegendItem(lic, "vehLoc", Color.RED);
|
||||
if (containsServiceAct) {
|
||||
LegendItem item = new LegendItem("service", Color.BLUE);
|
||||
item.setShape(ELLIPSE);
|
||||
item.setShapeVisible(true);
|
||||
lic.add(item);
|
||||
addLegendItem(lic, "service", Color.BLUE);
|
||||
}
|
||||
if (containsPickupAct) {
|
||||
LegendItem item = new LegendItem("pickup", Color.GREEN);
|
||||
item.setShape(ELLIPSE);
|
||||
item.setShapeVisible(true);
|
||||
lic.add(item);
|
||||
addLegendItem(lic, "pickup", Color.GREEN);
|
||||
}
|
||||
if (containsDeliveryAct) {
|
||||
LegendItem item = new LegendItem("delivery", Color.BLUE);
|
||||
item.setShape(ELLIPSE);
|
||||
item.setShapeVisible(true);
|
||||
lic.add(item);
|
||||
addLegendItem(lic, "delivery", Color.BLUE);
|
||||
}
|
||||
if (routes != null) {
|
||||
LegendItem item = new LegendItem("firstActivity", Color.BLACK);
|
||||
|
|
@ -363,6 +349,13 @@ public class Plotter {
|
|||
}
|
||||
return lic;
|
||||
}
|
||||
|
||||
private void addLegendItem(LegendItemCollection lic, String jobType, Color color) {
|
||||
LegendItem item = new LegendItem(jobType, color);
|
||||
item.setShape(ELLIPSE);
|
||||
item.setShapeVisible(true);
|
||||
lic.add(item);
|
||||
}
|
||||
};
|
||||
|
||||
LegendTitle legend = new LegendTitle(lis);
|
||||
|
|
@ -384,14 +377,9 @@ public class Plotter {
|
|||
|
||||
private MyActivityRenderer getProblemRenderer(final XYSeriesCollection problem) {
|
||||
MyActivityRenderer problemRenderer = new MyActivityRenderer(problem, activitiesByDataItem, firstActivities);
|
||||
problemRenderer.setBaseItemLabelGenerator(new XYItemLabelGenerator() {
|
||||
|
||||
@Override
|
||||
public String generateLabel(XYDataset arg0, int arg1, int arg2) {
|
||||
XYDataItem item = problem.getSeries(arg1).getDataItem(arg2);
|
||||
return labelsByDataItem.get(item);
|
||||
}
|
||||
|
||||
problemRenderer.setBaseItemLabelGenerator((arg0, arg1, arg2) -> {
|
||||
XYDataItem item = problem.getSeries(arg1).getDataItem(arg2);
|
||||
return labelsByDataItem.get(item);
|
||||
});
|
||||
problemRenderer.setBaseItemLabelsVisible(true);
|
||||
problemRenderer.setBaseItemLabelPaint(Color.BLACK);
|
||||
|
|
@ -467,7 +455,7 @@ public class Plotter {
|
|||
}
|
||||
}
|
||||
|
||||
private XYSeriesCollection makeSolutionSeries(VehicleRoutingProblem vrp, Collection<VehicleRoute> routes) throws NoLocationFoundException {
|
||||
private XYSeriesCollection makeSolutionSeries(VehicleRoutingProblem vrp, Collection<VehicleRoute> routes) {
|
||||
Map<String, Coordinate> coords = makeMap(vrp.getAllLocations());
|
||||
XYSeriesCollection coll = new XYSeriesCollection();
|
||||
int counter = 1;
|
||||
|
|
@ -493,22 +481,20 @@ public class Plotter {
|
|||
}
|
||||
|
||||
private Map<String, Coordinate> makeMap(Collection<Location> allLocations) {
|
||||
Map<String, Coordinate> coords = new HashMap<String, Coordinate>();
|
||||
Map<String, Coordinate> coords = new HashMap<>();
|
||||
for (Location l : allLocations) coords.put(l.getId(), l.getCoordinate());
|
||||
return coords;
|
||||
}
|
||||
|
||||
private XYSeriesCollection makeShipmentSeries(Collection<Job> jobs) throws NoLocationFoundException {
|
||||
private XYSeriesCollection makeShipmentSeries(Collection<Job> jobs) {
|
||||
XYSeriesCollection coll = new XYSeriesCollection();
|
||||
if (!plotShipments) return coll;
|
||||
int sCounter = 1;
|
||||
String ship = "shipment";
|
||||
boolean first = true;
|
||||
for (Job job : jobs) {
|
||||
if (!(job instanceof Shipment)) {
|
||||
continue;
|
||||
}
|
||||
Shipment shipment = (Shipment) job;
|
||||
if (job.getActivities().size() == 1) continue;
|
||||
// Shipment shipment = (Shipment) job;
|
||||
XYSeries shipmentSeries;
|
||||
if (first) {
|
||||
first = false;
|
||||
|
|
@ -517,57 +503,34 @@ public class Plotter {
|
|||
shipmentSeries = new XYSeries(sCounter, false, true);
|
||||
sCounter++;
|
||||
}
|
||||
Coordinate pickupCoordinate = getCoordinate(shipment.getPickupLocation().getCoordinate());
|
||||
Coordinate delCoordinate = getCoordinate(shipment.getDeliveryLocation().getCoordinate());
|
||||
shipmentSeries.add(pickupCoordinate.getX() * scalingFactor, pickupCoordinate.getY() * scalingFactor);
|
||||
shipmentSeries.add(delCoordinate.getX() * scalingFactor, delCoordinate.getY() * scalingFactor);
|
||||
for (com.graphhopper.jsprit.core.problem.job.Activity act : job.getActivities()) {
|
||||
Coordinate actCoordinate = getCoordinate(act.getLocation().getCoordinate());
|
||||
shipmentSeries.add(actCoordinate.getX() * scalingFactor, actCoordinate.getY() * scalingFactor);
|
||||
}
|
||||
coll.addSeries(shipmentSeries);
|
||||
}
|
||||
return coll;
|
||||
}
|
||||
|
||||
private void addJob(XYSeries activities, Job job) {
|
||||
if (job instanceof Shipment) {
|
||||
Shipment s = (Shipment) job;
|
||||
Coordinate pickupCoordinate = getCoordinate(s.getPickupLocation().getCoordinate());
|
||||
XYDataItem dataItem = new XYDataItem(pickupCoordinate.getX() * scalingFactor, pickupCoordinate.getY() * scalingFactor);
|
||||
for (com.graphhopper.jsprit.core.problem.job.Activity act : job.getActivities()) {
|
||||
XYDataItem dataItem = new XYDataItem(getCoordinate(act.getLocation().getCoordinate()).getX() * scalingFactor, getCoordinate(act.getLocation().getCoordinate()).getY() * scalingFactor);
|
||||
activities.add(dataItem);
|
||||
addLabel(s, dataItem);
|
||||
markItem(dataItem, Activity.PICKUP);
|
||||
containsPickupAct = true;
|
||||
|
||||
Coordinate deliveryCoordinate = getCoordinate(s.getDeliveryLocation().getCoordinate());
|
||||
XYDataItem dataItem2 = new XYDataItem(deliveryCoordinate.getX() * scalingFactor, deliveryCoordinate.getY() * scalingFactor);
|
||||
activities.add(dataItem2);
|
||||
addLabel(s, dataItem2);
|
||||
markItem(dataItem2, Activity.DELIVERY);
|
||||
containsDeliveryAct = true;
|
||||
} else if (job instanceof Pickup) {
|
||||
Pickup service = (Pickup) job;
|
||||
Coordinate coord = getCoordinate(service.getLocation().getCoordinate());
|
||||
XYDataItem dataItem = new XYDataItem(coord.getX() * scalingFactor, coord.getY() * scalingFactor);
|
||||
activities.add(dataItem);
|
||||
addLabel(service, dataItem);
|
||||
markItem(dataItem, Activity.PICKUP);
|
||||
containsPickupAct = true;
|
||||
} else if (job instanceof Delivery) {
|
||||
Delivery service = (Delivery) job;
|
||||
Coordinate coord = getCoordinate(service.getLocation().getCoordinate());
|
||||
XYDataItem dataItem = new XYDataItem(coord.getX() * scalingFactor, coord.getY() * scalingFactor);
|
||||
activities.add(dataItem);
|
||||
addLabel(service, dataItem);
|
||||
markItem(dataItem, Activity.DELIVERY);
|
||||
containsDeliveryAct = true;
|
||||
} else if (job instanceof Service) {
|
||||
Service service = (Service) job;
|
||||
Coordinate coord = getCoordinate(service.getLocation().getCoordinate());
|
||||
XYDataItem dataItem = new XYDataItem(coord.getX() * scalingFactor, coord.getY() * scalingFactor);
|
||||
activities.add(dataItem);
|
||||
addLabel(service, dataItem);
|
||||
markItem(dataItem, Activity.SERVICE);
|
||||
containsServiceAct = true;
|
||||
} else {
|
||||
throw new IllegalStateException("job instanceof " + job.getClass().toString() + ". this is not supported.");
|
||||
addLabel(job, dataItem);
|
||||
switch (act.getActivityType()) {
|
||||
case PICKUP:
|
||||
markItem(dataItem, Activity.PICKUP);
|
||||
containsPickupAct = true;
|
||||
break;
|
||||
case DELIVERY:
|
||||
markItem(dataItem, Activity.DELIVERY);
|
||||
containsDeliveryAct = true;
|
||||
break;
|
||||
case SERVICE:
|
||||
markItem(dataItem, Activity.SERVICE);
|
||||
containsServiceAct = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -585,11 +548,11 @@ public class Plotter {
|
|||
boolean firstDim = true;
|
||||
for (int i = 0; i < job.getSize().getNuOfDimensions(); i++) {
|
||||
if (firstDim) {
|
||||
builder.append(String.valueOf(job.getSize().get(i)));
|
||||
builder.append(job.getSize().get(i));
|
||||
firstDim = false;
|
||||
} else {
|
||||
builder.append(",");
|
||||
builder.append(String.valueOf(job.getSize().get(i)));
|
||||
builder.append(job.getSize().get(i));
|
||||
}
|
||||
}
|
||||
builder.append(")");
|
||||
|
|
@ -606,16 +569,16 @@ public class Plotter {
|
|||
private void retrieveActivities(VehicleRoutingProblem vrp) throws NoLocationFoundException {
|
||||
activities = new XYSeries("activities", false, true);
|
||||
for (Vehicle v : vrp.getVehicles()) {
|
||||
Coordinate start_coordinate = getCoordinate(v.getStartLocation().getCoordinate());
|
||||
if (start_coordinate == null) throw new NoLocationFoundException();
|
||||
XYDataItem item = new XYDataItem(start_coordinate.getX() * scalingFactor, start_coordinate.getY() * scalingFactor);
|
||||
Coordinate startCoordinate = getCoordinate(v.getStartLocation().getCoordinate());
|
||||
if (startCoordinate == null) throw new NoLocationFoundException();
|
||||
XYDataItem item = new XYDataItem(startCoordinate.getX() * scalingFactor, startCoordinate.getY() * scalingFactor);
|
||||
markItem(item, Activity.START);
|
||||
activities.add(item);
|
||||
|
||||
if (!v.getStartLocation().getId().equals(v.getEndLocation().getId())) {
|
||||
Coordinate end_coordinate = getCoordinate(v.getEndLocation().getCoordinate());
|
||||
if (end_coordinate == null) throw new NoLocationFoundException();
|
||||
XYDataItem end_item = new XYDataItem(end_coordinate.getX() * scalingFactor, end_coordinate.getY() * scalingFactor);
|
||||
Coordinate endCoordinate = getCoordinate(v.getEndLocation().getCoordinate());
|
||||
if (endCoordinate == null) throw new NoLocationFoundException();
|
||||
XYDataItem end_item = new XYDataItem(endCoordinate.getX() * scalingFactor, endCoordinate.getY() * scalingFactor);
|
||||
markItem(end_item, Activity.END);
|
||||
activities.add(end_item);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ package com.graphhopper.jsprit.core.algorithm.recreate;
|
|||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.Activity;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
import com.graphhopper.jsprit.core.problem.job.Shipment;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
|
||||
/**
|
||||
* Created by schroeder on 15/10/15.
|
||||
|
|
@ -41,52 +41,40 @@ public class DefaultScorer implements ScoringFunction {
|
|||
this.vrp = vrp;
|
||||
}
|
||||
|
||||
public void setTimeWindowParam(double tw_param) {
|
||||
this.timeWindowParam = tw_param;
|
||||
public void setTimeWindowParam(double twParam) {
|
||||
this.timeWindowParam = twParam;
|
||||
}
|
||||
|
||||
public void setDepotDistanceParam(double depotDistance_param) {
|
||||
this.depotDistanceParam = depotDistance_param;
|
||||
public void setDepotDistanceParam(double depotDistanceParam) {
|
||||
this.depotDistanceParam = depotDistanceParam;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double score(InsertionData best, Job job) {
|
||||
double score;
|
||||
if (job instanceof Service) {
|
||||
score = scoreService(best, job);
|
||||
} else if (job instanceof Shipment) {
|
||||
score = scoreShipment(best, job);
|
||||
} else throw new IllegalStateException("not supported");
|
||||
return score;
|
||||
return scoreJob(best, job);
|
||||
}
|
||||
|
||||
private double scoreShipment(InsertionData best, Job job) {
|
||||
Shipment shipment = (Shipment) job;
|
||||
double maxDepotDistance_1 = Math.max(
|
||||
getDistance(best.getSelectedVehicle().getStartLocation(), shipment.getPickupLocation()),
|
||||
getDistance(best.getSelectedVehicle().getStartLocation(), shipment.getDeliveryLocation())
|
||||
);
|
||||
double maxDepotDistance_2 = Math.max(
|
||||
getDistance(best.getSelectedVehicle().getEndLocation(), shipment.getPickupLocation()),
|
||||
getDistance(best.getSelectedVehicle().getEndLocation(), shipment.getDeliveryLocation())
|
||||
);
|
||||
double maxDepotDistance = Math.max(maxDepotDistance_1, maxDepotDistance_2);
|
||||
double minTimeToOperate = Math.min(shipment.getPickupTimeWindow().getEnd() - shipment.getPickupTimeWindow().getStart(),
|
||||
shipment.getDeliveryTimeWindow().getEnd() - shipment.getDeliveryTimeWindow().getStart());
|
||||
private double scoreJob(InsertionData best, Job job) {
|
||||
Location startLocation = best.getSelectedVehicle().getStartLocation();
|
||||
Location endLocation = best.getSelectedVehicle().getEndLocation();
|
||||
double maxDepotDistance = 0;
|
||||
double minTimeToOperate = Double.MAX_VALUE;
|
||||
for (Activity act : job.getActivities()) {
|
||||
maxDepotDistance = Math.max(maxDepotDistance, getDistance(startLocation, act.getLocation()));
|
||||
maxDepotDistance = Math.max(maxDepotDistance, getDistance(endLocation, act.getLocation()));
|
||||
TimeWindow tw = getLargestTimeWindow(act);
|
||||
minTimeToOperate = Math.min(minTimeToOperate, tw.getEnd() - tw.getStart());
|
||||
}
|
||||
return Math.max(timeWindowParam * minTimeToOperate, minTimeWindowScore) + depotDistanceParam * maxDepotDistance;
|
||||
}
|
||||
|
||||
private double scoreService(InsertionData best, Job job) {
|
||||
Location location = ((Service) job).getLocation();
|
||||
double maxDepotDistance = 0;
|
||||
if (location != null) {
|
||||
maxDepotDistance = Math.max(
|
||||
getDistance(best.getSelectedVehicle().getStartLocation(), location),
|
||||
getDistance(best.getSelectedVehicle().getEndLocation(), location)
|
||||
);
|
||||
private TimeWindow getLargestTimeWindow(Activity act) {
|
||||
TimeWindow timeWindow = null;
|
||||
for (TimeWindow tw : act.getTimeWindows()) {
|
||||
if (timeWindow == null) timeWindow = tw;
|
||||
else if (tw.larger(timeWindow)) timeWindow = tw;
|
||||
}
|
||||
return Math.max(timeWindowParam * (((Service) job).getTimeWindow().getEnd() - ((Service) job).getTimeWindow().getStart()), minTimeWindowScore) +
|
||||
depotDistanceParam * maxDepotDistance;
|
||||
return TimeWindow.newInstance(0, Double.MAX_VALUE);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,10 +52,6 @@ final class ServiceInsertionCalculator extends AbstractInsertionCalculator {
|
|||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ServiceInsertionCalculator.class);
|
||||
|
||||
// private HardRouteConstraint hardRouteLevelConstraint;
|
||||
|
||||
// private HardActivityConstraint hardActivityLevelConstraint;
|
||||
|
||||
private final SoftRouteConstraint softRouteConstraint;
|
||||
|
||||
private final SoftActivityConstraint softActivityConstraint;
|
||||
|
|
|
|||
|
|
@ -20,10 +20,7 @@ package com.graphhopper.jsprit.core.problem;
|
|||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||
import com.graphhopper.jsprit.core.problem.cost.WaitingTimeCosts;
|
||||
import com.graphhopper.jsprit.core.problem.job.Break;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
import com.graphhopper.jsprit.core.problem.job.Shipment;
|
||||
import com.graphhopper.jsprit.core.problem.job.*;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.BreakActivity;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.DefaultShipmentActivityFactory;
|
||||
|
|
@ -226,18 +223,8 @@ public class VehicleRoutingProblem {
|
|||
}
|
||||
|
||||
private void addLocationToTentativeLocations(Job job) {
|
||||
if (job instanceof Service) {
|
||||
Location location = ((Service) job).getLocation();
|
||||
// tentative_coordinates.put(location.getId(), location.getCoordinate());
|
||||
addLocationToTentativeLocations(location);
|
||||
} else if (job instanceof Shipment) {
|
||||
Shipment shipment = (Shipment) job;
|
||||
Location pickupLocation = shipment.getPickupLocation();
|
||||
addLocationToTentativeLocations(pickupLocation);
|
||||
// tentative_coordinates.put(pickupLocation.getId(), pickupLocation.getCoordinate());
|
||||
Location deliveryLocation = shipment.getDeliveryLocation();
|
||||
addLocationToTentativeLocations(deliveryLocation);
|
||||
// tentative_coordinates.put(deliveryLocation.getId(), deliveryLocation.getCoordinate());
|
||||
for (Activity act : job.getActivities()) {
|
||||
addLocationToTentativeLocations(act.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,13 +234,7 @@ public class VehicleRoutingProblem {
|
|||
}
|
||||
|
||||
private void addJobToFinalJobMapAndCreateActivities(Job job) {
|
||||
if (job instanceof Service) {
|
||||
Service service = (Service) job;
|
||||
addService(service);
|
||||
} else if (job instanceof Shipment) {
|
||||
Shipment shipment = (Shipment) job;
|
||||
addShipment(shipment);
|
||||
}
|
||||
addJobToFinalMap(job);
|
||||
List<AbstractActivity> jobActs = jobActivityFactory.createActivities(job);
|
||||
for (AbstractActivity act : jobActs) {
|
||||
act.setIndex(activityIndexCounter);
|
||||
|
|
@ -333,13 +314,11 @@ public class VehicleRoutingProblem {
|
|||
return this;
|
||||
}
|
||||
|
||||
private void addShipment(Shipment job) {
|
||||
private void addJobToFinalMap(Job job) {
|
||||
if (jobs.containsKey(job.getId())) {
|
||||
logger.warn("The job " + job + " has already been added to the job list. This overrides the existing job.");
|
||||
}
|
||||
addLocationToTentativeLocations(job);
|
||||
// tentative_coordinates.put(job.getPickupLocation().getId(), job.getPickupLocation().getCoordinate());
|
||||
// tentative_coordinates.put(job.getDeliveryLocation().getId(), job.getDeliveryLocation().getCoordinate());
|
||||
jobs.put(job.getId(), job);
|
||||
}
|
||||
|
||||
|
|
@ -516,15 +495,6 @@ public class VehicleRoutingProblem {
|
|||
return Collections.unmodifiableCollection(tentativeJobs.values());
|
||||
}
|
||||
|
||||
private Builder addService(Service service) {
|
||||
addLocationToTentativeLocations(service);
|
||||
if (jobs.containsKey(service.getId())) {
|
||||
logger.warn("The service " + service + " has already been added to job list. This overrides existing job.");
|
||||
}
|
||||
jobs.put(service.getId(), service);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Licensed to GraphHopper GmbH under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with this work for
|
||||
* additional information regarding copyright ownership.
|
||||
*
|
||||
* GraphHopper GmbH licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.graphhopper.jsprit.core.problem.job;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class Activity {
|
||||
|
||||
public enum Type {
|
||||
PICKUP, DELIVERY, SERVICE, BREAK;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private final Type activityType;
|
||||
|
||||
private Location location;
|
||||
|
||||
Collection<TimeWindow> timeWindows;
|
||||
|
||||
private double serviceTime;
|
||||
|
||||
public Builder(Location location, Type activityType) {
|
||||
this.location = location;
|
||||
this.activityType = activityType;
|
||||
}
|
||||
|
||||
public Builder setTimeWindows(Collection<TimeWindow> timeWindows) {
|
||||
this.timeWindows = timeWindows;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setServiceTime(double serviceTime) {
|
||||
this.serviceTime = serviceTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Activity build() {
|
||||
return new Activity(this);
|
||||
}
|
||||
}
|
||||
|
||||
private Location location;
|
||||
|
||||
private Collection<TimeWindow> timeWindows;
|
||||
|
||||
private double serviceTime;
|
||||
|
||||
private Activity.Type activityType;
|
||||
|
||||
Activity(Builder builder) {
|
||||
location = builder.location;
|
||||
timeWindows = builder.timeWindows;
|
||||
serviceTime = builder.serviceTime;
|
||||
activityType = builder.activityType;
|
||||
}
|
||||
|
||||
public Type getActivityType() {
|
||||
return activityType;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public Collection<TimeWindow> getTimeWindows() {
|
||||
return timeWindows;
|
||||
}
|
||||
|
||||
public double getServiceTime() {
|
||||
return serviceTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -61,12 +61,13 @@ public class Break extends Service {
|
|||
this.setType("break");
|
||||
super.capacity = Capacity.Builder.newInstance().build();
|
||||
super.skills = Skills.Builder.newInstance().build();
|
||||
super.activity = new Activity.Builder(null, Activity.Type.BREAK).setServiceTime(serviceTime).setTimeWindows(timeWindows.getTimeWindows()).build();
|
||||
return new Break(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean variableLocation = true;
|
||||
private boolean variableLocation;
|
||||
|
||||
Break(Builder builder) {
|
||||
super(builder);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ public class Delivery extends Service {
|
|||
this.setType("delivery");
|
||||
super.capacity = super.capacityBuilder.build();
|
||||
super.skills = super.skillBuilder.build();
|
||||
super.activity = new Activity.Builder(location, Activity.Type.DELIVERY).setTimeWindows(timeWindows.getTimeWindows()).setServiceTime(serviceTime).build();
|
||||
return new Delivery(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import com.graphhopper.jsprit.core.problem.HasId;
|
|||
import com.graphhopper.jsprit.core.problem.HasIndex;
|
||||
import com.graphhopper.jsprit.core.problem.Skills;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Basic interface for all jobs.
|
||||
*
|
||||
|
|
@ -36,23 +38,23 @@ public interface Job extends HasId, HasIndex {
|
|||
*
|
||||
* @return id
|
||||
*/
|
||||
public String getId();
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Returns size, i.e. capacity-demand, of this job which can consist of an arbitrary number of capacity dimensions.
|
||||
*
|
||||
* @return Capacity
|
||||
*/
|
||||
public Capacity getSize();
|
||||
Capacity getSize();
|
||||
|
||||
public Skills getRequiredSkills();
|
||||
Skills getRequiredSkills();
|
||||
|
||||
/**
|
||||
* Returns name.
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public String getName();
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Get priority of job. Only 1 (very high) to 10 (very low) are allowed.
|
||||
|
|
@ -61,8 +63,10 @@ public interface Job extends HasId, HasIndex {
|
|||
*
|
||||
* @return priority
|
||||
*/
|
||||
public int getPriority();
|
||||
int getPriority();
|
||||
|
||||
public double getMaxTimeInVehicle();
|
||||
double getMaxTimeInVehicle();
|
||||
|
||||
List<Activity> getActivities();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ public class Pickup extends Service {
|
|||
this.setType("pickup");
|
||||
super.capacity = super.capacityBuilder.build();
|
||||
super.skills = super.skillBuilder.build();
|
||||
super.activity = new Activity.Builder(location, Activity.Type.PICKUP).setTimeWindows(timeWindows.getTimeWindows()).setServiceTime(serviceTime).build();
|
||||
return new Pickup(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,10 @@ import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindows;
|
|||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindowsImpl;
|
||||
import com.graphhopper.jsprit.core.util.Coordinate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Service implementation of a job.
|
||||
|
|
@ -93,6 +96,8 @@ public class Service extends AbstractJob {
|
|||
|
||||
protected double maxTimeInVehicle = Double.MAX_VALUE;
|
||||
|
||||
protected Activity activity;
|
||||
|
||||
Builder(String id){
|
||||
this.id = id;
|
||||
timeWindows = new TimeWindowsImpl();
|
||||
|
|
@ -209,6 +214,7 @@ public class Service extends AbstractJob {
|
|||
this.setType("service");
|
||||
capacity = capacityBuilder.build();
|
||||
skills = skillBuilder.build();
|
||||
activity = new Activity.Builder(location, Activity.Type.SERVICE).setServiceTime(serviceTime).setTimeWindows(timeWindows.getTimeWindows()).build();
|
||||
return (T) new Service(this);
|
||||
}
|
||||
|
||||
|
|
@ -282,6 +288,8 @@ public class Service extends AbstractJob {
|
|||
|
||||
private final double maxTimeInVehicle;
|
||||
|
||||
private List<Activity> activities = new ArrayList<>();
|
||||
|
||||
Service(Builder<?> builder) {
|
||||
setUserData(builder.userData);
|
||||
id = builder.id;
|
||||
|
|
@ -294,6 +302,8 @@ public class Service extends AbstractJob {
|
|||
timeWindows = builder.timeWindows;
|
||||
priority = builder.priority;
|
||||
maxTimeInVehicle = builder.maxTimeInVehicle;
|
||||
activities.add(builder.activity);
|
||||
activities = Collections.unmodifiableList(activities);
|
||||
}
|
||||
|
||||
public Collection<TimeWindow> getTimeWindows(){
|
||||
|
|
@ -414,4 +424,9 @@ public class Service extends AbstractJob {
|
|||
return this.maxTimeInVehicle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Activity> getActivities() {
|
||||
return activities;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,10 @@ import com.graphhopper.jsprit.core.problem.Skills;
|
|||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindowsImpl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -46,8 +49,6 @@ import java.util.Collection;
|
|||
public class Shipment extends AbstractJob {
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Builder that builds the shipment.
|
||||
*
|
||||
|
|
@ -89,6 +90,10 @@ public class Shipment extends AbstractJob {
|
|||
|
||||
public double maxTimeInVehicle = Double.MAX_VALUE;
|
||||
|
||||
private Activity pickup;
|
||||
|
||||
private Activity delivery;
|
||||
|
||||
/**
|
||||
* Returns new instance of this builder.
|
||||
*
|
||||
|
|
@ -252,6 +257,8 @@ public class Shipment extends AbstractJob {
|
|||
if (deliveryLocation_ == null) throw new IllegalArgumentException("The delivery location is missing.");
|
||||
capacity = capacityBuilder.build();
|
||||
skills = skillBuilder.build();
|
||||
pickup = new Activity.Builder(pickupLocation_, Activity.Type.PICKUP).setServiceTime(pickupServiceTime).setTimeWindows(pickupTimeWindows.getTimeWindows()).build();
|
||||
delivery = new Activity.Builder(deliveryLocation_, Activity.Type.DELIVERY).setServiceTime(deliveryServiceTime).setTimeWindows(deliveryTimeWindows.getTimeWindows()).build();
|
||||
return new Shipment(this);
|
||||
}
|
||||
|
||||
|
|
@ -368,6 +375,8 @@ public class Shipment extends AbstractJob {
|
|||
|
||||
private final double maxTimeInVehicle;
|
||||
|
||||
private List<Activity> activities = new ArrayList<>();
|
||||
|
||||
Shipment(Builder builder) {
|
||||
setUserData(builder.userData);
|
||||
this.id = builder.id;
|
||||
|
|
@ -382,6 +391,9 @@ public class Shipment extends AbstractJob {
|
|||
this.pickupTimeWindows = builder.pickupTimeWindows;
|
||||
this.priority = builder.priority;
|
||||
this.maxTimeInVehicle = builder.maxTimeInVehicle;
|
||||
activities.add(builder.pickup);
|
||||
activities.add(builder.delivery);
|
||||
activities = Collections.unmodifiableList(activities);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -520,4 +532,9 @@ public class Shipment extends AbstractJob {
|
|||
public double getMaxTimeInVehicle() {
|
||||
return maxTimeInVehicle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Activity> getActivities() {
|
||||
return activities;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,10 @@ public class TimeWindow {
|
|||
return end;
|
||||
}
|
||||
|
||||
public boolean larger(TimeWindow timeWindow) {
|
||||
return (this.getEnd() - this.getStart()) > (timeWindow.getEnd() - timeWindow.getStart());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[start=" + start + "][end=" + end + "]";
|
||||
|
|
|
|||
|
|
@ -46,8 +46,7 @@ public class TourActivities {
|
|||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (currentIndex >= 0) return true;
|
||||
return false;
|
||||
return currentIndex >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -67,9 +66,9 @@ public class TourActivities {
|
|||
}
|
||||
}
|
||||
|
||||
private final ArrayList<TourActivity> tourActivities = new ArrayList<TourActivity>();
|
||||
private final ArrayList<TourActivity> tourActivities = new ArrayList<>();
|
||||
|
||||
private final Set<Job> jobs = new HashSet<Job>();
|
||||
private final Set<Job> jobs = new HashSet<>();
|
||||
|
||||
private ReverseActivityIterator backward;
|
||||
|
||||
|
|
@ -123,7 +122,7 @@ public class TourActivities {
|
|||
* @return true if job has been removed, otherwise false.
|
||||
*/
|
||||
public boolean removeJob(Job job) {
|
||||
boolean jobRemoved = false;
|
||||
boolean jobRemoved;
|
||||
if (!jobs.contains(job)) {
|
||||
return false;
|
||||
} else {
|
||||
|
|
@ -161,7 +160,7 @@ public class TourActivities {
|
|||
}
|
||||
boolean jobIsAlsoAssociateToOtherActs = false;
|
||||
boolean actRemoved = false;
|
||||
List<TourActivity> acts = new ArrayList<TourActivity>(tourActivities);
|
||||
List<TourActivity> acts = new ArrayList<>(tourActivities);
|
||||
for (TourActivity act : acts) {
|
||||
if (act == activity) {
|
||||
tourActivities.remove(act);
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ import com.graphhopper.jsprit.core.problem.job.Job;
|
|||
*/
|
||||
public interface TourActivity extends HasIndex {
|
||||
|
||||
public void setTheoreticalEarliestOperationStartTime(double earliest);
|
||||
void setTheoreticalEarliestOperationStartTime(double earliest);
|
||||
|
||||
public void setTheoreticalLatestOperationStartTime(double latest);
|
||||
void setTheoreticalLatestOperationStartTime(double latest);
|
||||
|
||||
/**
|
||||
* Basic interface of job-activies.
|
||||
|
|
@ -42,14 +42,14 @@ public interface TourActivity extends HasIndex {
|
|||
*
|
||||
* @author schroeder
|
||||
*/
|
||||
public interface JobActivity extends TourActivity {
|
||||
interface JobActivity extends TourActivity {
|
||||
|
||||
/**
|
||||
* Returns the job that is involved with this activity.
|
||||
*
|
||||
* @return job
|
||||
*/
|
||||
public Job getJob();
|
||||
Job getJob();
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -58,14 +58,14 @@ public interface TourActivity extends HasIndex {
|
|||
*
|
||||
* @return name
|
||||
*/
|
||||
public abstract String getName();
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns location.
|
||||
*
|
||||
* @return location
|
||||
*/
|
||||
public abstract Location getLocation();
|
||||
Location getLocation();
|
||||
|
||||
/**
|
||||
* Returns the theoretical earliest operation start time, which is the time that is just allowed
|
||||
|
|
@ -73,7 +73,7 @@ public interface TourActivity extends HasIndex {
|
|||
*
|
||||
* @return earliest start time
|
||||
*/
|
||||
public abstract double getTheoreticalEarliestOperationStartTime();
|
||||
double getTheoreticalEarliestOperationStartTime();
|
||||
|
||||
/**
|
||||
* Returns the theoretical latest operation start time, which is the time that is just allowed
|
||||
|
|
@ -81,7 +81,7 @@ public interface TourActivity extends HasIndex {
|
|||
*
|
||||
* @return latest start time
|
||||
*/
|
||||
public abstract double getTheoreticalLatestOperationStartTime();
|
||||
double getTheoreticalLatestOperationStartTime();
|
||||
|
||||
/**
|
||||
* Returns the operation-time this activity takes.
|
||||
|
|
@ -91,35 +91,35 @@ public interface TourActivity extends HasIndex {
|
|||
*
|
||||
* @return operation time
|
||||
*/
|
||||
public abstract double getOperationTime();
|
||||
double getOperationTime();
|
||||
|
||||
/**
|
||||
* Returns the arrival-time of this activity.
|
||||
*
|
||||
* @return arrival time
|
||||
*/
|
||||
public abstract double getArrTime();
|
||||
double getArrTime();
|
||||
|
||||
/**
|
||||
* Returns end-time of this activity.
|
||||
*
|
||||
* @return end time
|
||||
*/
|
||||
public abstract double getEndTime();
|
||||
double getEndTime();
|
||||
|
||||
/**
|
||||
* Sets the arrival time of that activity.
|
||||
*
|
||||
* @param arrTime
|
||||
*/
|
||||
public abstract void setArrTime(double arrTime);
|
||||
void setArrTime(double arrTime);
|
||||
|
||||
/**
|
||||
* Sets the end-time of this activity.
|
||||
*
|
||||
* @param endTime
|
||||
*/
|
||||
public abstract void setEndTime(double endTime);
|
||||
void setEndTime(double endTime);
|
||||
|
||||
/**
|
||||
* Returns the capacity-demand of that activity, in terms of what needs to be loaded or unloaded at
|
||||
|
|
@ -127,13 +127,13 @@ public interface TourActivity extends HasIndex {
|
|||
*
|
||||
* @return capacity
|
||||
*/
|
||||
public abstract Capacity getSize();
|
||||
Capacity getSize();
|
||||
|
||||
/**
|
||||
* Makes a deep copy of this activity.
|
||||
*
|
||||
* @return copied activity
|
||||
*/
|
||||
public abstract TourActivity duplicate();
|
||||
TourActivity duplicate();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,12 +130,8 @@ public class VehicleRoutingProblemTest {
|
|||
|
||||
@Test
|
||||
public void whenServicesAreAdded_vrpShouldContainThem() {
|
||||
Service s1 = mock(Service.class);
|
||||
when(s1.getId()).thenReturn("s1");
|
||||
when(s1.getLocation()).thenReturn(Location.Builder.newInstance().setIndex(1).build());
|
||||
Service s2 = mock(Service.class);
|
||||
when(s2.getId()).thenReturn("s2");
|
||||
when(s2.getLocation()).thenReturn(Location.Builder.newInstance().setIndex(1).build());
|
||||
Service s1 = Service.Builder.newInstance("s1").setLocation(Location.Builder.newInstance().setIndex(1).build()).build();
|
||||
Service s2 = Service.Builder.newInstance("s2").setLocation(Location.Builder.newInstance().setIndex(1).build()).build();
|
||||
|
||||
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||
vrpBuilder.addJob(s1).addJob(s2);
|
||||
|
|
|
|||
|
|
@ -307,4 +307,11 @@ public class ServiceTest {
|
|||
assertEquals(42, two.getUserData());
|
||||
assertNull(three.getUserData());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceActivity() {
|
||||
Service one = Service.Builder.newInstance("s").setLocation(Location.newInstance("loc")).build();
|
||||
assertEquals(1, one.getActivities().size());
|
||||
assertEquals(Activity.Type.SERVICE, one.getActivities().get(0).getActivityType());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -464,4 +464,13 @@ public class ShipmentTest {
|
|||
Assert.assertEquals(Double.MAX_VALUE, s.getMaxTimeInVehicle(),0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShipmentActivities() {
|
||||
Job job = Shipment.Builder.newInstance("s").setPickupLocation(Location.newInstance("loc")).setDeliveryLocation(Location.newInstance("loc"))
|
||||
.build();
|
||||
assertEquals(2, job.getActivities().size());
|
||||
assertEquals(Activity.Type.PICKUP, job.getActivities().get(0).getActivityType());
|
||||
assertEquals(Activity.Type.DELIVERY, job.getActivities().get(1).getActivityType());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import com.graphhopper.jsprit.analysis.toolbox.GraphStreamViewer.Label;
|
|||
import com.graphhopper.jsprit.analysis.toolbox.Plotter;
|
||||
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||
import com.graphhopper.jsprit.core.algorithm.box.Jsprit;
|
||||
import com.graphhopper.jsprit.core.algorithm.box.SchrimpfFactory;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue