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

Merge branch 'restructureAPIinPreparationForV0.1.1'

Conflicts:
	CHANGELOG.md
This commit is contained in:
Stefan Schroeder 2013-11-26 10:42:47 +01:00
commit a0ad012768
369 changed files with 75965 additions and 6728 deletions

View file

@ -1,165 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View file

@ -1,90 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package analysis;
import basics.VehicleRoutingProblemSolution;
import basics.route.DefaultVehicleRouteCostCalculator;
import basics.route.VehicleRoute;
/**
* Printer to print the details of a vehicle-routing-problem solution.
*
* @author stefan schroeder
*
*/
public class SolutionPrinter {
/**
* Enum to indicate verbose-level.
*
* <p> Print.CONCISE and Print.VERBOSE are available.
*
* @author stefan schroeder
*
*/
public enum Print {
CONCISE,VERBOSE
}
/**
* Prints costs and #vehicles to stdout (System.out.println).
*
* @param solution
*/
public static void print(VehicleRoutingProblemSolution solution){
System.out.println("[costs="+solution.getCost() + "]");
System.out.println("[#vehicles="+solution.getRoutes().size() + "]");
}
/**
* Prints the details of the solution according to a print-level, i.e. Print.CONCISE or PRINT.VERBOSE.
*
* <p>CONCISE prints total-costs and #vehicles.
* <p>VERBOSE prints the route-details additionally. If the DefaultVehicleRouteCostCalculator (which is the standard-calculator)
* is used in VehicleRoute, then route-costs are differentiated further between transport, activity, vehicle, driver and other-costs.
*
* @param solution
* @param level
*
* @deprecated is not going to work anymore
*/
@Deprecated
public static void print(VehicleRoutingProblemSolution solution, Print level){
if(level.equals(Print.CONCISE)){
print(solution);
}
else{
print(solution);
System.out.println("routes");
int routeCount = 1;
for(VehicleRoute route : solution.getRoutes()){
System.out.println("[route="+routeCount+"][departureTime="+route.getStart().getEndTime()+"[total=" + route.getCost() + "]");
if(route.getVehicleRouteCostCalculator() instanceof DefaultVehicleRouteCostCalculator){
DefaultVehicleRouteCostCalculator defaultCalc = (DefaultVehicleRouteCostCalculator) route.getVehicleRouteCostCalculator();
System.out.println("[transport=" + defaultCalc.getTpCosts() + "][activity=" + defaultCalc.getActCosts() +
"][vehicle=" + defaultCalc.getVehicleCosts() + "][driver=" + defaultCalc.getDriverCosts() + "][other=" + defaultCalc.getOther() + "]");
}
routeCount++;
}
}
}
}

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package analysis;
package jsprit.analysis.toolbox;
import java.io.File;
import java.io.IOException;
@ -22,24 +22,24 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.algorithm.listener.IterationEndsListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import org.apache.log4j.Logger;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.Range;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmEndsListener;
import basics.algo.AlgorithmStartsListener;
import basics.algo.IterationEndsListener;
/**
@ -77,6 +77,9 @@ public class AlgorithmSearchProgressChartListener implements IterationEndsListen
public AlgorithmSearchProgressChartListener(String pngFileName) {
super();
this.filename = pngFileName;
if(!this.filename.endsWith("png")){
this.filename += ".png";
}
}
@ -118,8 +121,10 @@ public class AlgorithmSearchProgressChartListener implements IterationEndsListen
XYPlot plot = chart.getXYPlot();
NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
Range rangeY = new Range(minValue-0.05*minValue,maxValue + 0.05*maxValue);
yAxis.setRange(rangeY);
Range rangeBounds = coll.getRangeBounds(true);
double upper = Math.min(rangeBounds.getUpperBound(), rangeBounds.getLowerBound()*5);
if(upper == 0.0){ upper = 10000; }
yAxis.setRangeWithMargins(rangeBounds.getLowerBound(),upper);
try {
ChartUtilities.saveChartAsJPEG(new File(filename), chart, 1000, 600);
@ -143,9 +148,9 @@ public class AlgorithmSearchProgressChartListener implements IterationEndsListen
double best = Double.MAX_VALUE;
double sum = 0.0;
for(VehicleRoutingProblemSolution sol : solutions){
if(sol.getCost() > worst) worst = sol.getCost();
if(sol.getCost() > worst) worst = Math.min(sol.getCost(),Double.MAX_VALUE);
if(sol.getCost() < best) best = sol.getCost();
sum += sol.getCost();
sum += Math.min(sol.getCost(),Double.MAX_VALUE);
}
bestResultList.add(best);
worstResultList.add(worst);

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package analysis;
package jsprit.analysis.toolbox;
import java.util.ArrayList;
import java.util.Collection;
@ -25,19 +25,21 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import jsprit.analysis.util.BenchmarkWriter;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.VehicleRoutingAlgorithmFactory;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.Priority;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.util.BenchmarkInstance;
import jsprit.core.util.BenchmarkResult;
import jsprit.core.util.Solutions;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import util.BenchmarkInstance;
import util.BenchmarkResult;
import util.BenchmarkWriter;
import util.Solutions;
import algorithms.VehicleRoutingAlgorithms;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
public class ConcurrentBenchmarker {
@ -47,7 +49,7 @@ public class ConcurrentBenchmarker {
private String algorithmConfig;
private String algorithmConfig = null;
private List<BenchmarkInstance> benchmarkInstances = new ArrayList<BenchmarkInstance>();
@ -66,6 +68,8 @@ public class ConcurrentBenchmarker {
};
private VehicleRoutingAlgorithmFactory algorithmFactory;
public void setCost(Cost cost){ this.cost = cost; }
public ConcurrentBenchmarker(String algorithmConfig) {
@ -74,6 +78,10 @@ public class ConcurrentBenchmarker {
Logger.getRootLogger().setLevel(Level.ERROR);
}
public ConcurrentBenchmarker(VehicleRoutingAlgorithmFactory algorithmFactory){
this.algorithmFactory = algorithmFactory;
}
public void addBenchmarkWriter(BenchmarkWriter writer){
writers.add(writer);
}
@ -94,6 +102,12 @@ public class ConcurrentBenchmarker {
benchmarkInstances.add(new BenchmarkInstance(name,problem,bestKnownResult,bestKnownVehicles));
}
/**
* Sets nuOfRuns with same algorithm on same instance.
* <p>Default is 1
*
* @param runs
*/
public void setNuOfRuns(int runs){
this.runs = runs;
}
@ -142,11 +156,11 @@ public class ConcurrentBenchmarker {
double[] times = new double[runs];
for(int run=0;run<runs;run++){
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(p.vrp, algorithmConfig);
VehicleRoutingAlgorithm vra = createAlgorithm(p);
StopWatch stopwatch = new StopWatch();
vra.getAlgorithmListeners().addListener(stopwatch,Priority.HIGH);
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
VehicleRoutingProblemSolution best = Solutions.getBest(solutions);
VehicleRoutingProblemSolution best = Solutions.bestOf(solutions);
vehicles[run] = best.getRoutes().size();
results[run] = cost.getCost(best);
times[run] = stopwatch.getCompTimeInSeconds();
@ -155,6 +169,16 @@ public class ConcurrentBenchmarker {
return new BenchmarkResult(p, runs, results, times, vehicles);
}
private VehicleRoutingAlgorithm createAlgorithm(BenchmarkInstance p) {
if(algorithmConfig != null){
return VehicleRoutingAlgorithms.readAndCreateAlgorithm(p.vrp, algorithmConfig);
}
else{
return algorithmFactory.createAlgorithm(p.vrp);
}
}
private void print(Collection<BenchmarkResult> results) {
double sumTime=0.0;
double sumResult=0.0;

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package analysis;
package jsprit.analysis.toolbox;
import java.awt.BasicStroke;
import java.awt.Color;
@ -23,35 +23,39 @@ import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Delivery;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.util.Coordinate;
import jsprit.core.util.Locations;
import org.apache.log4j.Logger;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.LegendItemCollection;
import org.jfree.chart.LegendItemSource;
import org.jfree.chart.annotations.XYShapeAnnotation;
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.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;
import util.Coordinate;
import util.Locations;
import basics.Delivery;
import basics.Job;
import basics.Pickup;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
public class Plotter {
@ -77,10 +81,12 @@ public class Plotter {
private VehicleRoutingProblem vrp;
private VehicleRoutingProblemSolution solution;
private boolean plotSolutionAsWell = false;
private boolean plotShipments = true;
private Collection<VehicleRoute> routes;
public void setShowFirstActivity(boolean show){
showFirstActivity = show;
}
@ -97,53 +103,102 @@ public class Plotter {
public Plotter(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution) {
super();
this.vrp = vrp;
this.solution = solution;
this.routes = solution.getRoutes();
plotSolutionAsWell = true;
}
public Plotter(VehicleRoutingProblem vrp, Collection<VehicleRoute> routes) {
super();
this.vrp = vrp;
this.routes = routes;
plotSolutionAsWell = true;
}
public void plot(String pngFileName, String plotTitle){
String filename = pngFileName;
if(!pngFileName.endsWith(".png")) filename += ".png";
if(plotSolutionAsWell){
plotSolutionAsPNG(vrp, solution, pngFileName, plotTitle);
plotSolutionAsPNG(vrp, routes, filename, plotTitle);
}
else{
plotVrpAsPNG(vrp, pngFileName, plotTitle);
plotVrpAsPNG(vrp, filename, plotTitle);
}
}
private void plotVrpAsPNG(VehicleRoutingProblem vrp, String pngFile, String title){
log.info("plot routes to " + pngFile);
XYSeriesCollection problem;
final XYSeriesCollection shipments;
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
try {
problem = makeVrpSeries(vrp, labels);
shipments = makeShipmentSeries(vrp.getJobs().values(), null);
} catch (NoLocationFoundException e) {
log.warn("cannot plot vrp, since coord is missing");
return;
}
XYPlot plot = createPlot(problem, labels);
final XYPlot plot = createProblemPlot(problem, shipments, labels);
LegendItemSource lis = new LegendItemSource() {
@Override
public LegendItemCollection getLegendItems() {
LegendItemCollection lic = new LegendItemCollection();
lic.addAll(plot.getRenderer(0).getLegendItems());
if(!shipments.getSeries().isEmpty()){
lic.add(plot.getRenderer(1).getLegendItem(1, 0));
}
return lic;
}
};
JFreeChart chart = new JFreeChart(title, plot);
chart.removeLegend();
LegendTitle legend = new LegendTitle(lis);
legend.setPosition(RectangleEdge.BOTTOM);
chart.addLegend(legend);
save(chart,pngFile);
}
private void plotSolutionAsPNG(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution, String pngFile, String title){
private void plotSolutionAsPNG(VehicleRoutingProblem vrp, Collection<VehicleRoute> routes, String pngFile, String title){
log.info("plot solution to " + pngFile);
XYSeriesCollection problem;
XYSeriesCollection solutionColl;
final XYSeriesCollection shipments;
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
try {
problem = makeVrpSeries(vrp, labels);
solutionColl = makeSolutionSeries(vrp, solution);
shipments = makeShipmentSeries(vrp.getJobs().values(), null);
solutionColl = makeSolutionSeries(vrp, routes);
} catch (NoLocationFoundException e) {
log.warn("cannot plot vrp, since coord is missing");
return;
}
XYPlot plot = createPlot(problem, solutionColl, labels);
final XYPlot plot = createProblemSolutionPlot(problem, shipments, solutionColl, labels);
JFreeChart chart = new JFreeChart(title, plot);
LegendItemSource lis = new LegendItemSource() {
@Override
public LegendItemCollection getLegendItems() {
LegendItemCollection lic = new LegendItemCollection();
lic.addAll(plot.getRenderer(0).getLegendItems());
lic.addAll(plot.getRenderer(2).getLegendItems());
if(!shipments.getSeries().isEmpty()){
lic.add(plot.getRenderer(1).getLegendItem(1, 0));
}
return lic;
}
};
chart.removeLegend();
LegendTitle legend = new LegendTitle(lis);
legend.setPosition(RectangleEdge.BOTTOM);
chart.addLegend(legend);
save(chart,pngFile);
}
private static XYPlot createPlot(final XYSeriesCollection problem, final Map<XYDataItem, String> labels) {
private static XYPlot createProblemPlot(final XYSeriesCollection problem, XYSeriesCollection shipments, final Map<XYDataItem, String> labels) {
XYPlot plot = new XYPlot();
plot.setBackgroundPaint(Color.LIGHT_GRAY);
plot.setRangeGridlinePaint(Color.WHITE);
@ -172,10 +227,25 @@ public class Plotter {
plot.setDomainAxis(0, xAxis);
plot.setRangeAxis(0, yAxis);
XYItemRenderer shipmentsRenderer = new XYLineAndShapeRenderer(true, false); // Shapes only
for(int i=0;i<shipments.getSeriesCount();i++){
shipmentsRenderer.setSeriesPaint(i, Color.BLUE);
shipmentsRenderer.setSeriesStroke(i, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f
));
}
// shipmentsRenderer.getLegendItems().
plot.setDataset(1, shipments);
plot.setRenderer(1, shipmentsRenderer);
// plot.setDomainAxis(1, xAxis);
// plot.setRangeAxis(1, yAxis);
// plot.addl
return plot;
}
private XYPlot createPlot(final XYSeriesCollection problem, XYSeriesCollection solutionColl, final Map<XYDataItem, String> labels) {
private XYPlot createProblemSolutionPlot(final XYSeriesCollection problem, XYSeriesCollection shipments, XYSeriesCollection solutionColl, final Map<XYDataItem, String> labels) {
XYPlot plot = new XYPlot();
plot.setBackgroundPaint(Color.LIGHT_GRAY);
plot.setRangeGridlinePaint(Color.WHITE);
@ -193,7 +263,6 @@ public class Plotter {
problemRenderer.setBaseItemLabelsVisible(true);
problemRenderer.setBaseItemLabelPaint(Color.BLACK);
NumberAxis xAxis = new NumberAxis();
xAxis.setRangeWithMargins(problem.getDomainBounds(true));
@ -204,8 +273,22 @@ public class Plotter {
plot.setRenderer(0, problemRenderer);
plot.setDomainAxis(0, xAxis);
plot.setRangeAxis(0, yAxis);
// plot.mapDatasetToDomainAxis(0, 0);
XYItemRenderer shipmentsRenderer = new XYLineAndShapeRenderer(true, false); // Shapes only
for(int i=0;i<shipments.getSeriesCount();i++){
shipmentsRenderer.setSeriesPaint(i, Color.BLUE);
shipmentsRenderer.setSeriesStroke(i, new BasicStroke(
1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
1.0f, new float[] {6.0f, 6.0f}, 0.0f
));
}
plot.setDataset(1, shipments);
plot.setRenderer(1, shipmentsRenderer);
// plot.setDomainAxis(1, xAxis);
// plot.setRangeAxis(1, yAxis);
XYItemRenderer solutionRenderer = new XYLineAndShapeRenderer(true, false); // Lines only
if(showFirstActivity){
for(int i=0;i<solutionColl.getSeriesCount();i++){
@ -214,10 +297,10 @@ public class Plotter {
solutionRenderer.addAnnotation(new XYShapeAnnotation( new Ellipse2D.Double(firstCustomer.getXValue()-0.7, firstCustomer.getYValue()-0.7, 1.5, 1.5), new BasicStroke(1.0f), Color.RED));
}
}
plot.setDataset(1, solutionColl);
plot.setRenderer(1, solutionRenderer);
plot.setDomainAxis(1, xAxis);
plot.setRangeAxis(1, yAxis);
plot.setDataset(2, solutionColl);
plot.setRenderer(2, solutionRenderer);
// plot.setDomainAxis(2, xAxis);
// plot.setRangeAxis(2, yAxis);
return plot;
}
@ -232,32 +315,8 @@ public class Plotter {
}
}
private XYSeriesCollection makeSolutionSeries(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution) throws NoLocationFoundException{
private XYSeriesCollection makeSolutionSeries(VehicleRoutingProblem vrp, Collection<VehicleRoute> routes) throws NoLocationFoundException{
Locations locations = retrieveLocations(vrp);
XYSeriesCollection coll = new XYSeriesCollection();
int counter = 1;
for(VehicleRoute route : solution.getRoutes()){
if(route.isEmpty()) continue;
XYSeries series = new XYSeries(counter, false, true);
Coordinate startCoord = locations.getCoord(route.getStart().getLocationId());
series.add(startCoord.getX(), startCoord.getY());
for(TourActivity act : route.getTourActivities().getActivities()){
Coordinate coord = locations.getCoord(act.getLocationId());
series.add(coord.getX(), coord.getY());
}
Coordinate endCoord = locations.getCoord(route.getEnd().getLocationId());
series.add(endCoord.getX(), endCoord.getY());
coll.addSeries(series);
counter++;
}
return coll;
}
private XYSeriesCollection makeSolutionSeries(Collection<VehicleRoute> routes, Locations locations){
XYSeriesCollection coll = new XYSeriesCollection();
int counter = 1;
for(VehicleRoute route : routes){
@ -281,7 +340,34 @@ public class Plotter {
return coll;
}
private XYSeriesCollection makeVrpSeries(Collection<Vehicle> vehicles, Collection<Job> services, Map<XYDataItem, String> labels) throws NoLocationFoundException{
private XYSeriesCollection makeShipmentSeries(Collection<Job> jobs, Map<XYDataItem, String> labels) throws NoLocationFoundException{
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;
XYSeries shipmentSeries;
if(first){
first = false;
shipmentSeries = new XYSeries(ship, false, true);
}
else{
shipmentSeries = new XYSeries(sCounter, false, true);
sCounter++;
}
shipmentSeries.add(shipment.getPickupCoord().getX(), shipment.getPickupCoord().getY());
shipmentSeries.add(shipment.getDeliveryCoord().getX(), shipment.getDeliveryCoord().getY());
coll.addSeries(shipmentSeries);
}
return coll;
}
private XYSeriesCollection makeVrpSeries(Collection<Vehicle> vehicles, Collection<Job> jobs, Map<XYDataItem, String> labels) throws NoLocationFoundException{
XYSeriesCollection coll = new XYSeriesCollection();
XYSeries vehicleSeries = new XYSeries("depot", false, true);
for(Vehicle v : vehicles){
@ -294,13 +380,24 @@ public class Plotter {
XYSeries serviceSeries = new XYSeries("service", false, true);
XYSeries pickupSeries = new XYSeries("pickup", false, true);
XYSeries deliverySeries = new XYSeries("delivery", false, true);
for(Job job : services){
if(job instanceof Pickup){
for(Job job : jobs){
if(job instanceof Shipment){
Shipment s = (Shipment)job;
XYDataItem dataItem = new XYDataItem(s.getPickupCoord().getX(), s.getPickupCoord().getY());
pickupSeries.add(dataItem);
addLabel(labels, s, dataItem);
XYDataItem dataItem2 = new XYDataItem(s.getDeliveryCoord().getX(), s.getDeliveryCoord().getY());
deliverySeries.add(dataItem2);
addLabel(labels, s, dataItem2);
}
else if(job instanceof Pickup){
Pickup service = (Pickup)job;
Coordinate coord = service.getCoord();
XYDataItem dataItem = new XYDataItem(coord.getX(), coord.getY());
pickupSeries.add(dataItem);
addLabel(labels, service, dataItem);
}
else if(job instanceof Delivery){
Delivery service = (Delivery)job;
@ -327,25 +424,15 @@ public class Plotter {
return coll;
}
private void addLabel(Map<XYDataItem, String> labels, Service service, XYDataItem dataItem) {
private void addLabel(Map<XYDataItem, String> labels, Job job, XYDataItem dataItem) {
if(this.label.equals(Label.SIZE)){
labels.put(dataItem, String.valueOf(service.getCapacityDemand()));
labels.put(dataItem, String.valueOf(job.getCapacityDemand()));
}
else if(this.label.equals(Label.ID)){
labels.put(dataItem, String.valueOf(service.getId()));
labels.put(dataItem, String.valueOf(job.getId()));
}
}
private XYSeriesCollection makeVrpSeries(Collection<VehicleRoute> routes, Map<XYDataItem, String> labels) throws NoLocationFoundException{
Set<Vehicle> vehicles = new HashSet<Vehicle>();
Set<Job> jobs = new HashSet<Job>();
for(VehicleRoute route : routes){
vehicles.add(route.getVehicle());
jobs.addAll(route.getTourActivities().getJobs());
}
return makeVrpSeries(vehicles, jobs, labels);
}
private XYSeriesCollection makeVrpSeries(VehicleRoutingProblem vrp, Map<XYDataItem, String> labels) throws NoLocationFoundException{
return makeVrpSeries(vrp.getVehicles(), vrp.getJobs().values(), labels);
}
@ -367,6 +454,22 @@ public class Plotter {
if(coord == null) throw new NoLocationFoundException();
locs.put(locationId, coord);
}
else if(j instanceof Shipment){
{
String locationId = ((Shipment) j).getPickupLocation();
if(locationId == null) throw new NoLocationFoundException();
Coordinate coord = ((Shipment) j).getPickupCoord();
if(coord == null) throw new NoLocationFoundException();
locs.put(locationId, coord);
}
{
String locationId = ((Shipment) j).getDeliveryLocation();
if(locationId == null) throw new NoLocationFoundException();
Coordinate coord = ((Shipment) j).getDeliveryCoord();
if(coord == null) throw new NoLocationFoundException();
locs.put(locationId, coord);
}
}
else{
throw new IllegalStateException("job is not a service. this is not supported yet.");
}
@ -380,4 +483,8 @@ public class Plotter {
};
}
public void plotShipments(boolean plotShipments) {
this.plotShipments = plotShipments;
}
}

View file

@ -14,11 +14,9 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package analysis;
package jsprit.analysis.toolbox;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.geom.Ellipse2D;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
@ -27,31 +25,29 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Delivery;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.util.Coordinate;
import jsprit.core.util.Locations;
import org.apache.log4j.Logger;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYShapeAnnotation;
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.data.xy.XYDataItem;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import util.Coordinate;
import util.Locations;
import basics.Delivery;
import basics.Job;
import basics.Pickup;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
/**
@ -82,7 +78,9 @@ public class SolutionPlotter {
* @see VehicleRoutingProblem, VehicleRoutingProblemSolution
*/
public static void plotVrpAsPNG(VehicleRoutingProblem vrp, String pngFile, String title){
log.info("plot routes to " + pngFile);
String filename = pngFile;
if(!pngFile.endsWith(".png")) filename += ".png";
log.info("plot routes to " + filename);
XYSeriesCollection problem;
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
try {
@ -93,7 +91,7 @@ public class SolutionPlotter {
}
XYPlot plot = createPlot(problem, labels);
JFreeChart chart = new JFreeChart(title, plot);
save(chart,pngFile);
save(chart,filename);
}
/**
@ -106,7 +104,9 @@ public class SolutionPlotter {
* @see VehicleRoute
*/
public static void plotRoutesAsPNG(Collection<VehicleRoute> routes, Locations locations, String pngFile, String title) {
log.info("plot routes to " + pngFile);
String filename = pngFile;
if(!pngFile.endsWith(".png")) filename += ".png";
log.info("plot routes to " + filename);
XYSeriesCollection problem;
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
try {
@ -118,7 +118,7 @@ public class SolutionPlotter {
XYSeriesCollection solutionColl = makeSolutionSeries(routes,locations);
XYPlot plot = createPlot(problem, solutionColl, labels);
JFreeChart chart = new JFreeChart(title, plot);
save(chart,pngFile);
save(chart,filename);
}
/**
@ -133,7 +133,9 @@ public class SolutionPlotter {
* @see VehicleRoutingProblem, VehicleRoutingProblemSolution
*/
public static void plotSolutionAsPNG(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution, String pngFile, String title){
log.info("plot solution to " + pngFile);
String filename = pngFile;
if(!pngFile.endsWith(".png")) filename += ".png";
log.info("plot solution to " + filename);
XYSeriesCollection problem;
XYSeriesCollection solutionColl;
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
@ -146,7 +148,7 @@ public class SolutionPlotter {
}
XYPlot plot = createPlot(problem, solutionColl, labels);
JFreeChart chart = new JFreeChart(title, plot);
save(chart,pngFile);
save(chart,filename);
}

View file

@ -0,0 +1,88 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.analysis.toolbox;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
/**
* Printer to print the details of a vehicle-routing-problem solution.
*
* @author stefan schroeder
*
*/
public class SolutionPrinter {
/**
* Enum to indicate verbose-level.
*
* <p> Print.CONCISE and Print.VERBOSE are available.
*
* @author stefan schroeder
*
*/
public enum Print {
CONCISE,VERBOSE
}
/**
* Prints costs and #vehicles to stdout (System.out.println).
*
* @param solution
*/
public static void print(VehicleRoutingProblemSolution solution){
System.out.println("[costs="+solution.getCost() + "]");
System.out.println("[#vehicles="+solution.getRoutes().size() + "]");
}
// /**
// * Prints the details of the solution according to a print-level, i.e. Print.CONCISE or PRINT.VERBOSE.
// *
// * <p>CONCISE prints total-costs and #vehicles.
// * <p>VERBOSE prints the route-details additionally. If the DefaultVehicleRouteCostCalculator (which is the standard-calculator)
// * is used in VehicleRoute, then route-costs are differentiated further between transport, activity, vehicle, driver and other-costs.
// *
// * @param solution
// * @param level
// *
// * @deprecated is not going to work anymore
// */
// @Deprecated
// public static void print(VehicleRoutingProblemSolution solution, Print level){
// if(level.equals(Print.CONCISE)){
// print(solution);
// }
// else{
// print(solution);
// System.out.println("routes");
// int routeCount = 1;
// for(VehicleRoute route : solution.getRoutes()){
// System.out.println("[route="+routeCount+"][departureTime="+route.getStart().getEndTime()+"[total=" + route.getCost() + "]");
// if(route.getVehicleRouteCostCalculator() instanceof DefaultVehicleRouteCostCalculator){
// DefaultVehicleRouteCostCalculator defaultCalc = (DefaultVehicleRouteCostCalculator) route.getVehicleRouteCostCalculator();
// System.out.println("[transport=" + defaultCalc.getTpCosts() + "][activity=" + defaultCalc.getActCosts() +
// "][vehicle=" + defaultCalc.getVehicleCosts() + "][driver=" + defaultCalc.getDriverCosts() + "][other=" + defaultCalc.getOther() + "]");
// }
// routeCount++;
// }
// }
//
//
// }
}

View file

@ -14,17 +14,18 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package analysis;
package jsprit.analysis.toolbox;
import java.util.Collection;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import org.apache.log4j.Logger;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmEndsListener;
import basics.algo.AlgorithmStartsListener;
public class StopWatch implements AlgorithmStartsListener, AlgorithmEndsListener{

View file

@ -14,10 +14,12 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package util;
package jsprit.analysis.util;
import java.util.Collection;
import jsprit.core.util.BenchmarkResult;
public interface BenchmarkWriter {
public void write(Collection<BenchmarkResult> results);
}

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package util;
package jsprit.analysis.util;
import java.io.BufferedWriter;
import java.io.File;
@ -22,6 +22,8 @@ import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import jsprit.core.util.BenchmarkResult;
import org.jfree.chart.renderer.xy.DeviationRenderer;
public class HtmlBenchmarkTableWriter implements BenchmarkWriter{

View file

@ -1,72 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class BackwardInTimeListeners {
interface BackwardInTimeListener{
public void start(VehicleRoute route, End end, double latestArrivalTime);
public void prevActivity(TourActivity act, double latestDepartureTime, double latestOperationStartTime);
public void end(Start start, double latestDepartureTime);
}
private Collection<BackwardInTimeListener> listeners = new ArrayList<BackwardInTimeListener>();
public void addListener(BackwardInTimeListener l){
listeners.add(l);
}
public void start(VehicleRoute route, End end, double latestArrivalTime){
for(BackwardInTimeListener l : listeners){ l.start(route, end, latestArrivalTime); }
}
/**
* Informs listener about nextActivity.
*
* <p>LatestDepartureTime is the theoretical latest departureTime to meet the latestOperationStartTimeWindow at the nextActivity (forward in time), i.e.
* assume act_i and act_j are two successive activities and the latestDepTime of act_j is 10pm. With a travelTime from act_i to act_j of 1h the latestDepartureTime at act_i is 9pm.
* However, the latestOperationStartTime of act_i is 8pm, then (with a serviceTime of 0) the latestOperationStartTime at act_i amounts to 8pm.
*
* @param act
* @param latestDepartureTime
* @param latestArrivalTime
*/
public void prevActivity(TourActivity act, double latestDepartureTime, double latestArrivalTime){
for(BackwardInTimeListener l : listeners){ l.prevActivity(act,latestDepartureTime,latestArrivalTime); }
}
public void end(Start start, double latestDepartureTime){
for(BackwardInTimeListener l : listeners){ l.end(start, latestDepartureTime); }
}
public boolean isEmpty() {
return listeners.isEmpty();
}
}

View file

@ -1,198 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
//
//
///**
// *
// * @author stefan schroeder
// *
// */
//
//final class BestInsertionConcurrent implements InsertionStrategy{
//
// public static BestInsertionConcurrent newInstance(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads){
// return new BestInsertionConcurrent(routeAlgorithm, executor, nuOfThreads);
// }
//
// static class Batch {
// List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
//
// }
//
// private static Logger logger = Logger.getLogger(BestInsertionConcurrent.class);
//
// private Random random = RandomNumberGeneration.getRandom();
//
// private RouteAlgorithm routeAlgorithm;
//
//// private ExecutorService executor;
//
// private int nuOfBatches;
//
// private ExecutorCompletionService<Insertion> completionService;
//
// public void setRandom(Random random) {
// this.random = random;
// }
//
// private BestInsertionConcurrent(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads) {
// super();
// this.routeAlgorithm = routeAlgorithm;
//// this.executor = executor;
// logger.info("initialise " + this);
// this.nuOfBatches = nuOfThreads;
// completionService = new ExecutorCompletionService<Insertion>(executor);
// }
//
// @Override
// public String toString() {
// return "[name=concurrentBestInsertion]";
// }
//
// @Override
// public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
// List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
// Collections.shuffle(unassignedJobList, random);
//// informInsertionStarts(vehicleRoutes,unassignedJobs.size());
// int inserted = 0;
// for(final Job unassignedJob : unassignedJobList){
// VehicleRoute insertIn = null;
// Insertion bestInsertion = null;
// double bestInsertionCost = Double.MAX_VALUE;
//
// List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
//
// for(final Batch batch : batches){
// completionService.submit(new Callable<Insertion>() {
//
// @Override
// public Insertion call() throws Exception {
// return getBestInsertion(batch,unassignedJob);
// }
//
// });
//
// }
//
// try{
// for(int i=0;i<batches.size();i++){
// Future<Insertion> futureIData = completionService.take();
// Insertion insertion = futureIData.get();
// if(insertion == null) continue;
// if(insertion.getInsertionData().getInsertionCost() < bestInsertionCost){
// bestInsertion = insertion;
// bestInsertionCost = insertion.getInsertionData().getInsertionCost();
// }
// }
// }
// catch(InterruptedException e){
// Thread.currentThread().interrupt();
// }
// catch (ExecutionException e) {
// e.printStackTrace();
// logger.error(e.getCause().toString());
// System.exit(1);
// }
//
// if(bestInsertion != null){
//// informBeforeJobInsertion(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
// insertIn = bestInsertion.getRoute();
//// logger.debug("insert job="+unassignedJob+" at index=" + bestInsertion.getInsertionData().getInsertionIndex() + " delta cost=" + bestInsertion.getInsertionData().getInsertionCost());
// routeAlgorithm.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
// }
// else {
//// VehicleRoute newRoute = VehicleRoute.emptyRoute();
//// InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE);
//// if(bestI instanceof InsertionData.NoInsertionFound)
// throw new IllegalStateException("given the vehicles, could not create a valid solution.\n\tthe reason might be" +
// " inappropriate vehicle capacity.\n\tthe job that does not fit in any vehicle anymore is \n\t" + unassignedJob);
//// insertIn = newRoute;
//// informBeforeJobInsertion(unassignedJob,bestI,newRoute);
//// routeAlgorithm.insertJob(unassignedJob,bestI,newRoute);
//// vehicleRoutes.add(newRoute);
// }
// inserted++;
//// informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn);
// }
//// informInsertionEndsListeners(vehicleRoutes);
// }
//
// private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
// Insertion bestInsertion = null;
// double bestInsertionCost = Double.MAX_VALUE;
// for(VehicleRoute vehicleRoute : batch.routes){
// InsertionData iData = routeAlgorithm.calculateBestInsertion(vehicleRoute, unassignedJob, bestInsertionCost);
// if(iData instanceof NoInsertionFound) continue;
// if(iData.getInsertionCost() < bestInsertionCost){
// bestInsertion = new Insertion(vehicleRoute,iData);
// bestInsertionCost = iData.getInsertionCost();
// }
// }
// return bestInsertion;
// }
//
// private List<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
// List<Batch> batches = new ArrayList<Batch>();
// for(int i=0;i<nuOfBatches;i++) batches.add(new Batch());
// /*
// * if route.size < nuOfBatches add as much routes as empty batches are available
// * else add one empty route anyway
// */
//// if(vehicleRoutes.size()<nuOfBatches){
//// int nOfNewRoutes = nuOfBatches-vehicleRoutes.size();
//// for(int i=0;i<nOfNewRoutes;i++){
//// vehicleRoutes.add(VehicleRoute.emptyRoute());
//// }
//// }
//// else{
// vehicleRoutes.add(VehicleRoute.emptyRoute());
//// }
// /*
// * distribute routes to batches equally
// */
// int count = 0;
// for(VehicleRoute route : vehicleRoutes){
// if(count == nuOfBatches) count=0;
// batches.get(count).routes.add(route);
// count++;
// }
// return batches;
// }
//
//
// @Override
// public void removeListener(InsertionListener insertionListener) {
// // TODO Auto-generated method stub
//
// }
//
// @Override
// public Collection<InsertionListener> getListeners() {
// // TODO Auto-generated method stub
// return null;
// }
//
// @Override
// public void addListener(InsertionListener insertionListener) {
// // TODO Auto-generated method stub
//
// }
//
//}

View file

@ -1,97 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
/* *********************************************************************** *
* project: org.matsim.*
* IniSolution.java
* *
* *********************************************************************** *
* *
* copyright : (C) 2011 by the members listed in the COPYING, *
* LICENSE and WARRANTY file. *
* email : info at matsim dot org *
* *
* *********************************************************************** *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* See also COPYING, LICENSE and WARRANTY file *
* *
* *********************************************************************** */
package algorithms;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.SolutionCostCalculator;
import basics.route.DriverImpl;
import basics.route.TourActivities;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
final class CreateInitialSolution implements InitialSolutionFactory {
private static final Logger logger = Logger.getLogger(CreateInitialSolution.class);
private final InsertionStrategy insertion;
private SolutionCostCalculator solutionCostCalculator;
private boolean generateAsMuchAsRoutesAsVehiclesExist = false;
public void setGenerateAsMuchAsRoutesAsVehiclesExist(boolean generateAsMuchAsRoutesAsVehiclesExist) {
this.generateAsMuchAsRoutesAsVehiclesExist = generateAsMuchAsRoutesAsVehiclesExist;
}
public CreateInitialSolution(InsertionStrategy insertionStrategy, SolutionCostCalculator solutionCostCalculator) {
super();
this.insertion = insertionStrategy;
this.solutionCostCalculator = solutionCostCalculator;
}
@Override
public VehicleRoutingProblemSolution createInitialSolution(final VehicleRoutingProblem vrp) {
logger.info("create initial solution.");
List<VehicleRoute> vehicleRoutes = new ArrayList<VehicleRoute>();
if(generateAsMuchAsRoutesAsVehiclesExist){
for(Vehicle vehicle : vrp.getVehicles()){
vehicleRoutes.add(VehicleRoute.newInstance(TourActivities.emptyTour(), DriverImpl.noDriver(), vehicle));
}
}
insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
// double totalCost = getTotalCost(vehicleRoutes);
logger.info("creation done");
VehicleRoutingProblemSolution vehicleRoutingProblemSolution = new VehicleRoutingProblemSolution(vehicleRoutes, 0.0);
solutionCostCalculator.calculateCosts(vehicleRoutingProblemSolution);
return vehicleRoutingProblemSolution;
}
private List<Job> getUnassignedJobs(VehicleRoutingProblem vrp) {
List<Job> jobs = new ArrayList<Job>(vrp.getJobs().values());
return jobs;
}
}

View file

@ -1,53 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import basics.Job;
import basics.algo.InsertionStartsListener;
import basics.route.VehicleRoute;
class FindCheaperVehicle implements InsertionStartsListener{
FindCheaperVehicleAlgo findCheaperVehicle;
public FindCheaperVehicle(FindCheaperVehicleAlgo findCheaperVehicle) {
super();
this.findCheaperVehicle = findCheaperVehicle;
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
List<VehicleRoute> newRoutes = new ArrayList<VehicleRoute>();
for(VehicleRoute route : vehicleRoutes){
if(route.isEmpty()) continue;
VehicleRoute cheaperRoute = findCheaperVehicle.runAndGetVehicleRoute(route);
newRoutes.add(cheaperRoute);
}
vehicleRoutes.clear();
vehicleRoutes.addAll(newRoutes);
}
@Override
public String toString() {
return "[name=findCheaperVehicle]";
}
}

View file

@ -1,109 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class FindCheaperVehicleAlgo {
private static Logger log = Logger.getLogger(FindCheaperVehicleAlgo.class);
private VehicleFleetManager fleetManager;
private VehicleRouteUpdater tourStateCalculator;
private AuxilliaryCostCalculator auxilliaryCostCalculator;
private double weightFixCosts = 1.0;
private StateManager states;
public void setWeightFixCosts(double weightFixCosts) {
this.weightFixCosts = weightFixCosts;
}
public void setStates(StateManager states) {
this.states = states;
}
public FindCheaperVehicleAlgo(VehicleFleetManager fleetManager, VehicleRouteUpdater tourStateCalculator, AuxilliaryCostCalculator auxilliaryCostCalculator) {
super();
this.fleetManager = fleetManager;
this.tourStateCalculator = tourStateCalculator;
this.auxilliaryCostCalculator = auxilliaryCostCalculator;
}
public VehicleRoute runAndGetVehicleRoute(VehicleRoute vehicleRoute) {
if(vehicleRoute.getVehicle() instanceof NoVehicle){
return vehicleRoute;
}
if(vehicleRoute.getTourActivities() == null || vehicleRoute.getVehicle() == null){
return vehicleRoute;
}
// Collection<TypeKey> availableVehicleTypes = fleetManager.getAvailableVehicleTypes(new TypeKey(vehicleRoute.getVehicle().getType(),vehicleRoute.getVehicle().getLocationId()));
double bestSaving = 0.0;
Vehicle bestVehicle = null;
List<TourActivity> path = new ArrayList<TourActivity>();
path.add(vehicleRoute.getStart());
path.addAll(vehicleRoute.getTourActivities().getActivities());
path.add(vehicleRoute.getEnd());
for(Vehicle vehicle : fleetManager.getAvailableVehicles(vehicleRoute.getVehicle().getType().getTypeId(), vehicleRoute.getVehicle().getLocationId())){
// Vehicle vehicle = fleetManager.getEmptyVehicle(vehicleType);
if(vehicle.getType().getTypeId().equals(vehicleRoute.getVehicle().getType().getTypeId())){
continue;
}
if(states.getRouteState(vehicleRoute,StateTypes.LOAD).toDouble() <= vehicle.getCapacity()){
double fixCostSaving = vehicleRoute.getVehicle().getType().getVehicleCostParams().fix - vehicle.getType().getVehicleCostParams().fix;
double departureTime = vehicleRoute.getStart().getEndTime();
double newCost = auxilliaryCostCalculator.costOfPath(path, departureTime, vehicleRoute.getDriver(), vehicle);
double varCostSaving = states.getRouteState(vehicleRoute, StateTypes.COSTS).toDouble() - newCost;
double totalCostSaving = varCostSaving + weightFixCosts*fixCostSaving;
if(totalCostSaving > bestSaving){
bestSaving = totalCostSaving;
bestVehicle = vehicle;
}
}
}
if(bestVehicle != null){
try{
fleetManager.unlock(vehicleRoute.getVehicle());
fleetManager.lock(bestVehicle);
}
catch(IllegalStateException e){
throw new IllegalStateException(e);
}
TourActivities newTour = TourActivities.copyOf(vehicleRoute.getTourActivities());
tourStateCalculator.iterate(vehicleRoute);
return VehicleRoute.newInstance(newTour,vehicleRoute.getDriver(),bestVehicle);
}
return vehicleRoute;
}
}

View file

@ -1,61 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class ForwardInTimeListeners {
interface ForwardInTimeListener{
public void start(VehicleRoute route, Start start, double departureTime);
public void nextActivity(TourActivity act, double arrTime,double endTime);
public void end(End end, double arrivalTime);
}
private Collection<ForwardInTimeListener> listeners = new ArrayList<ForwardInTimeListeners.ForwardInTimeListener>();
public void addListener(ForwardInTimeListener l){
listeners.add(l);
}
public void start(VehicleRoute route, Start start, double departureTime){
for(ForwardInTimeListener l : listeners){ l.start(route, start, departureTime); }
}
public void nextActivity(TourActivity act, double arrTime, double endTime){
for(ForwardInTimeListener l : listeners){ l.nextActivity(act,arrTime,endTime); }
}
public void end(End end, double arrivalTime){
for(ForwardInTimeListener l : listeners){ l.end(end, arrivalTime); }
}
public boolean isEmpty() {
return listeners.isEmpty();
}
}

View file

@ -1,218 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import org.apache.log4j.Logger;
import util.RandomNumberGeneration;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionListener;
import basics.algo.SearchStrategyModule;
import basics.algo.SearchStrategyModuleListener;
import basics.route.TourActivity;
import basics.route.TourActivity.JobActivity;
import basics.route.VehicleRoute;
final class Gendreau implements SearchStrategyModule{
private final static Logger log = Logger.getLogger(Gendreau.class);
private final static String NAME = "gendreauPostOpt";
private final RuinStrategy ruin;
private final VehicleRoutingProblem vrp;
private final InsertionStrategy insertionStrategy;
private VehicleFleetManager fleetManager;
private Random random = RandomNumberGeneration.getRandom();
private int nOfIterations = 10;
private double shareOfJobsToRuin = 0.15;
public void setShareOfJobsToRuin(double shareOfJobsToRuin) {
this.shareOfJobsToRuin = shareOfJobsToRuin;
}
public Gendreau(VehicleRoutingProblem vrp, RuinStrategy ruin, InsertionStrategy insertionStrategy) {
super();
InsertionListeners insertionListeners = new InsertionListeners();
insertionListeners.addAllListeners(insertionStrategy.getListeners());
new Inserter(insertionListeners);
this.ruin = ruin;
this.vrp = vrp;
this.insertionStrategy = insertionStrategy;
}
@Override
public String toString() {
return "[name=gendreau][iterations="+nOfIterations+"][share2ruin="+shareOfJobsToRuin+"]";
}
public void setRandom(Random random) {
this.random = random;
}
public void setNuOfIterations(int nOfIterations) {
this.nOfIterations = nOfIterations;
}
public void setFleetManager(VehicleFleetManager vehicleFleetManager) {
this.fleetManager = vehicleFleetManager;
}
@Override
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
// log.info("run gendreau postopt");
VehicleRoutingProblemSolution bestSolution = vrpSolution;
int itersWithoutImprovement = 0;
for(int i=0;i<nOfIterations;i++){
List<VehicleRoute> copiedRoutes = copyRoutes(bestSolution.getRoutes());
iniFleet(copiedRoutes);
VehicleRoute route2split = pickRouteThatHasAtLeastTwoJobs(copiedRoutes);
if(route2split == null) continue;
List<Job> jobsInRoute = getJobs(route2split);
Set<Job> unassignedJobs = new HashSet<Job>();
unassignedJobs.addAll(jobsInRoute);
copiedRoutes.remove(route2split);
Collections.shuffle(jobsInRoute,random);
Job targetJob = jobsInRoute.get(0);
int nOfJobs2BeRemovedAdditionally = (int) (shareOfJobsToRuin*(double)vrp.getJobs().size());
Collection<Job> unassignedJobsList = ruin.ruin(copiedRoutes, targetJob, nOfJobs2BeRemovedAdditionally);
unassignedJobs.addAll(unassignedJobsList);
VehicleRoute emptyRoute1 = VehicleRoute.emptyRoute();
copiedRoutes.add(emptyRoute1);
insertionStrategy.insertJobs(Arrays.asList(emptyRoute1), Arrays.asList(targetJob));
// routeAlgorithm.insertJob(targetJob, routeAlgorithm.calculateBestInsertion(emptyRoute1, targetJob, Double.MAX_VALUE), emptyRoute1);
unassignedJobs.remove(targetJob);
VehicleRoute emptyRoute2 = VehicleRoute.emptyRoute();
copiedRoutes.add(emptyRoute2);
Job job2 = jobsInRoute.get(1);
insertionStrategy.insertJobs(Arrays.asList(emptyRoute2), Arrays.asList(job2));
// routeAlgorithm.insertJob(job2, routeAlgorithm.calculateBestInsertion(emptyRoute2, job2, Double.MAX_VALUE), emptyRoute2);
unassignedJobs.remove(job2);
insertionStrategy.insertJobs(copiedRoutes, unassignedJobs);
double cost = getCost(copiedRoutes);
if(cost < bestSolution.getCost()){
// log.info("BING - new: " + cost + " old: " + bestSolution.getCost());
bestSolution = new VehicleRoutingProblemSolution(copiedRoutes, cost);
itersWithoutImprovement=0;
}
else{
itersWithoutImprovement++;
if(itersWithoutImprovement > 200){
// log.info("BREAK i="+i);
break;
}
}
}
return bestSolution;
}
private List<VehicleRoute> copyRoutes(Collection<VehicleRoute> routes) {
List<VehicleRoute> routeList = new ArrayList<VehicleRoute>();
for(VehicleRoute r : routes){
routeList.add(VehicleRoute.copyOf(r));
}
return routeList;
}
private void iniFleet(Collection<VehicleRoute> routes) {
fleetManager.unlockAll();
for(VehicleRoute route : routes){
if(!route.isEmpty()){
fleetManager.lock(route.getVehicle());
}
}
}
private double getCost(Collection<VehicleRoute> routes) {
double c = 0.0;
for(VehicleRoute r : routes){
c+=r.getCost();
}
return c;
}
private List<Job> getJobs(VehicleRoute route2split) {
Set<Job> jobs = new HashSet<Job>();
for(TourActivity act : route2split.getTourActivities().getActivities()){
if(act instanceof JobActivity){
jobs.add(((JobActivity) act).getJob());
}
}
return new ArrayList<Job>(jobs);
}
private VehicleRoute pickRouteThatHasAtLeastTwoJobs(Collection<VehicleRoute> routeList) {
List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
for(VehicleRoute r : routeList){
if(getJobs(r).size() > 1){
routes.add(r);
}
}
if(routes.isEmpty()) return null;
Collections.shuffle(routes,random);
return routes.get(0);
}
@Override
public String getName() {
return NAME;
}
@Override
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
if(moduleListener instanceof InsertionListener){
InsertionListener iListener = (InsertionListener) moduleListener;
if(!insertionStrategy.getListeners().contains(iListener)){
insertionStrategy.addListener(iListener);
}
}
if(moduleListener instanceof RuinListener){
RuinListener rListener = (RuinListener) moduleListener;
if(!ruin.getListeners().contains(rListener)){
ruin.addListener(rListener);
}
}
}
}

View file

@ -1,307 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import basics.Delivery;
import basics.Pickup;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DeliveryActivity;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TourActivity;
/**
* collection of hard constrainters bot at activity and at route level.
*
* <p>HardPickupAndDeliveryLoadConstraint requires LOAD_AT_DEPOT and LOAD (i.e. load at end) at route-level
*
* <p>HardTimeWindowConstraint requires LATEST_OPERATION_START_TIME
*
* <p>HardPickupAndDeliveryConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level
*
* <p>HardPickupAndDeliveryBackhaulConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level
*
* @author stefan
*
*/
class HardConstraints {
interface HardRouteLevelConstraint {
public boolean fulfilled(InsertionContext insertionContext);
}
interface HardActivityLevelConstraint {
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime);
}
static class HardRouteLevelConstraintManager implements HardRouteLevelConstraint {
private Collection<HardRouteLevelConstraint> hardConstraints = new ArrayList<HardRouteLevelConstraint>();
public void addConstraint(HardRouteLevelConstraint constraint){
hardConstraints.add(constraint);
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
for(HardRouteLevelConstraint constraint : hardConstraints){
if(!constraint.fulfilled(insertionContext)){
return false;
}
}
return true;
}
}
static class ConstraintManager implements HardActivityLevelConstraint, HardRouteLevelConstraint{
private HardActivityLevelConstraintManager actLevelConstraintManager = new HardActivityLevelConstraintManager();
private HardRouteLevelConstraintManager routeLevelConstraintManager = new HardRouteLevelConstraintManager();
public void addConstraint(HardActivityLevelConstraint actLevelConstraint){
actLevelConstraintManager.addConstraint(actLevelConstraint);
}
public void addConstraint(HardRouteLevelConstraint routeLevelConstraint){
routeLevelConstraintManager.addConstraint(routeLevelConstraint);
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
return routeLevelConstraintManager.fulfilled(insertionContext);
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
return actLevelConstraintManager.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
}
}
static class HardActivityLevelConstraintManager implements HardActivityLevelConstraint {
private Collection<HardActivityLevelConstraint> hardConstraints = new ArrayList<HardActivityLevelConstraint>();
public void addConstraint(HardActivityLevelConstraint constraint){
hardConstraints.add(constraint);
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
for(HardActivityLevelConstraint constraint : hardConstraints){
if(!constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime)){
return false;
}
}
return true;
}
}
static class HardLoadConstraint implements HardRouteLevelConstraint{
private StateManager states;
public HardLoadConstraint(StateManager states) {
super();
this.states = states;
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
int currentLoad = (int) states.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble();
Service service = (Service) insertionContext.getJob();
if(currentLoad + service.getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
return false;
}
return true;
}
}
/**
* lsjdfjsdlfjsa
*
* @author stefan
*
*/
static class HardPickupAndDeliveryLoadConstraint implements HardRouteLevelConstraint {
private StateManager stateManager;
public HardPickupAndDeliveryLoadConstraint(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public boolean fulfilled(InsertionContext insertionContext) {
if(insertionContext.getJob() instanceof Delivery){
int loadAtDepot = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
if(loadAtDepot + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
return false;
}
}
else if(insertionContext.getJob() instanceof Pickup || insertionContext.getJob() instanceof Service){
int loadAtEnd = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble();
if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}
/**
* ljsljslfjs
* @author stefan
*
*/
public static class HardTimeWindowActivityLevelConstraint implements HardActivityLevelConstraint {
private static Logger log = Logger.getLogger(HardTimeWindowActivityLevelConstraint.class);
private StateManager states;
private VehicleRoutingTransportCosts routingCosts;
public HardTimeWindowActivityLevelConstraint(StateManager states, VehicleRoutingTransportCosts routingCosts) {
super();
this.states = states;
this.routingCosts = routingCosts;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
// log.info("check insertion of " + newAct + " between " + prevAct + " and " + nextAct + ". prevActDepTime=" + prevActDepTime);
double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double latestArrTimeAtNewAct = states.getActivityState(newAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
if(arrTimeAtNewAct > latestArrTimeAtNewAct){
return false;
}
// log.info(newAct + " arrTime=" + arrTimeAtNewAct);
double endTimeAtNewAct = CalcUtils.getActivityEndTime(arrTimeAtNewAct, newAct);
double arrTimeAtNextAct = endTimeAtNewAct + routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), endTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double latestArrTimeAtNextAct = states.getActivityState(nextAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble();
if(arrTimeAtNextAct > latestArrTimeAtNextAct){
return false;
}
// log.info(nextAct + " arrTime=" + arrTimeAtNextAct);
return true;
}
}
static class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelConstraint {
private StateManager stateManager;
public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
int loadAtPrevAct;
int futurePicks;
int pastDeliveries;
if(prevAct instanceof Start){
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
pastDeliveries = 0;
}
else{
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble();
futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble();
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble();
}
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
if(newAct instanceof DeliveryActivity){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}
static class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivityLevelConstraint {
private StateManager stateManager;
public HardPickupAndDeliveryBackhaulActivityLevelConstraint(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(newAct instanceof PickupActivity && nextAct instanceof DeliveryActivity){ return false; }
if(newAct instanceof ServiceActivity && nextAct instanceof DeliveryActivity){ return false; }
if(newAct instanceof DeliveryActivity && prevAct instanceof PickupActivity){ return false; }
if(newAct instanceof DeliveryActivity && prevAct instanceof ServiceActivity){ return false; }
int loadAtPrevAct;
int futurePicks;
int pastDeliveries;
if(prevAct instanceof Start){
loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble();
futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble();
pastDeliveries = 0;
}
else{
loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble();
futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble();
pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble();
}
if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){
if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
if(newAct instanceof DeliveryActivity){
if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){
return false;
}
}
return true;
}
}
}

View file

@ -1,56 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.Service;
import basics.route.DefaultTourActivityFactory;
import basics.route.TourActivityFactory;
import basics.route.VehicleRoute;
class Inserter {
private InsertionListeners insertionListeners;
private TourActivityFactory activityFactory;
public Inserter(InsertionListeners insertionListeners) {
this.insertionListeners = insertionListeners;
activityFactory = new DefaultTourActivityFactory();
}
public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute){
insertionListeners.informBeforeJobInsertion(job, insertionData, vehicleRoute);
if(insertionData == null || (insertionData instanceof NoInsertionFound)) throw new IllegalStateException("insertionData null. cannot insert job.");
if(job == null) throw new IllegalStateException("cannot insert null-job");
if(!(vehicleRoute.getVehicle().getId().toString().equals(insertionData.getSelectedVehicle().getId().toString()))){
insertionListeners.informVehicleSwitched(vehicleRoute, vehicleRoute.getVehicle(), insertionData.getSelectedVehicle());
vehicleRoute.setVehicle(insertionData.getSelectedVehicle(), insertionData.getVehicleDepartureTime());
}
// if(vehicleRoute.getDepartureTime() != vehicleRoute.g)
if(job instanceof Service) {
vehicleRoute.getTourActivities().addActivity(insertionData.getDeliveryInsertionIndex(), activityFactory.createActivity((Service)job));
vehicleRoute.setDepartureTime(insertionData.getVehicleDepartureTime());
}
else throw new IllegalStateException("neither service nor shipment. this is not supported.");
insertionListeners.informJobInserted(job, vehicleRoute, insertionData.getInsertionCost(), insertionData.getAdditionalTime());
// updateTour(vehicleRoute);
}
}

View file

@ -1,82 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.Iterator;
import org.apache.log4j.Logger;
import algorithms.BackwardInTimeListeners.BackwardInTimeListener;
import basics.costs.BackwardTransportTime;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
/**
*
* @author stefan schroeder
*
*/
class IterateRouteBackwardInTime implements VehicleRouteUpdater{
private static Logger log = Logger.getLogger(IterateRouteBackwardInTime.class);
private BackwardTransportTime transportTime;
private BackwardInTimeListeners listeners;
public IterateRouteBackwardInTime(BackwardTransportTime transportTime) {
super();
this.transportTime = transportTime;
listeners = new BackwardInTimeListeners();
}
/*
*
*/
public void iterate(VehicleRoute vehicleRoute) {
if(listeners.isEmpty()) return;
if(vehicleRoute.isEmpty()) return;
listeners.start(vehicleRoute, vehicleRoute.getEnd(), vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime());
Iterator<TourActivity> reverseActIter = vehicleRoute.getTourActivities().reverseActivityIterator();
TourActivity prevAct;
prevAct = vehicleRoute.getEnd();
double latestArrivalTimeAtPrevAct = prevAct.getTheoreticalLatestOperationStartTime();
while(reverseActIter.hasNext()){
TourActivity currAct = reverseActIter.next();
double latestDepTimeAtCurrAct = latestArrivalTimeAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), latestArrivalTimeAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
double potentialLatestArrivalTimeAtCurrAct = latestDepTimeAtCurrAct - currAct.getOperationTime();
double latestArrivalTime = Math.min(currAct.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct);
listeners.prevActivity(currAct, latestDepTimeAtCurrAct, latestArrivalTime);
prevAct = currAct;
latestArrivalTimeAtPrevAct = latestArrivalTime;
}
TourActivity currAct = vehicleRoute.getStart();
double latestDepTimeAtCurrAct = latestArrivalTimeAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), latestArrivalTimeAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle());
listeners.end(vehicleRoute.getStart(), latestDepTimeAtCurrAct);
}
public void addListener(BackwardInTimeListener l){ listeners.addListener(l); }
}

View file

@ -1,87 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import org.apache.log4j.Logger;
import algorithms.ForwardInTimeListeners.ForwardInTimeListener;
import basics.costs.ForwardTransportTime;
import basics.route.Driver;
import basics.route.End;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
/**
*
* @author sschroeder
*
*/
class IterateRouteForwardInTime implements VehicleRouteUpdater{
private static Logger log = Logger.getLogger(IterateRouteForwardInTime.class);
private ForwardTransportTime transportTime;
private ForwardInTimeListeners listeners;
public IterateRouteForwardInTime(ForwardTransportTime transportTime) {
super();
this.transportTime = transportTime;
listeners = new ForwardInTimeListeners();
}
/**
*
*
*/
public void iterate(VehicleRoute vehicleRoute) {
if(listeners.isEmpty()) return;
if(vehicleRoute.isEmpty()) return;
listeners.start(vehicleRoute, vehicleRoute.getStart(), vehicleRoute.getStart().getEndTime());
Vehicle vehicle = vehicleRoute.getVehicle();
Driver driver = vehicleRoute.getDriver();
TourActivity prevAct = vehicleRoute.getStart();
double startAtPrevAct = prevAct.getEndTime();
for(TourActivity currentAct : vehicleRoute.getTourActivities().getActivities()){
double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
double operationStartTime = Math.max(currentAct.getTheoreticalEarliestOperationStartTime(), arrivalTimeAtCurrAct);
double operationEndTime = operationStartTime + currentAct.getOperationTime();
listeners.nextActivity(currentAct,arrivalTimeAtCurrAct,operationEndTime);
prevAct = currentAct;
startAtPrevAct = operationEndTime;
}
End currentAct = vehicleRoute.getEnd();
double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle);
double arrivalTimeAtCurrAct = startAtPrevAct + transportTime;
listeners.end(vehicleRoute.getEnd(), arrivalTimeAtCurrAct);
}
public void addListener(ForwardInTimeListener l){
listeners.addListener(l);
}
}

View file

@ -1,57 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import util.CrowFlyCosts;
import util.Locations;
import basics.Job;
import basics.Service;
class JobDistanceBeeline implements JobDistance {
private Locations locations;
public JobDistanceBeeline(Locations locations) {
super();
this.locations = locations;
}
@Override
public double calculateDistance(Job i, Job j) {
double avgCost = 0.0;
if (i instanceof Service && j instanceof Service) {
if (i.equals(j)) {
avgCost = 0.0;
} else {
Service s_i = (Service) i;
Service s_j = (Service) j;
avgCost = calcDist(s_i.getLocationId(), s_j.getLocationId());
}
} else {
throw new UnsupportedOperationException(
"currently, this class just works with shipments and services.");
}
return avgCost;
}
private double calcDist(String from, String to) {
return new CrowFlyCosts(locations).getTransportCost(from, to, 0.0,null, null);
}
}

View file

@ -1,54 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.route.VehicleRoute;
class RuinListeners {
private Collection<RuinListener> ruinListeners = new ArrayList<RuinListener>();
void ruinStarts(Collection<VehicleRoute> routes){
for(RuinListener l : ruinListeners) l.ruinStarts(routes);
}
void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs){
for(RuinListener l : ruinListeners) l.ruinEnds(routes, unassignedJobs);
}
void removed(Job job, VehicleRoute fromRoute){
for(RuinListener l : ruinListeners) l.removed(job, fromRoute);
}
void addListener(RuinListener ruinListener){
ruinListeners.add(ruinListener);
}
void removeListener(RuinListener ruinListener){
ruinListeners.remove(ruinListener);
}
Collection<RuinListener> getListeners(){
return Collections.unmodifiableCollection(ruinListeners);
}
}

View file

@ -1,59 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import basics.Job;
import basics.route.VehicleRoute;
class ScoredJob {
private final Job job;
private final double score;
private final InsertionData insertionData;
private final VehicleRoute route;
public ScoredJob(final Job job, final double score, final InsertionData insertionData, final VehicleRoute route) {
super();
this.job = job;
this.score = score;
this.insertionData = insertionData;
this.route = route;
}
public InsertionData getInsertionData() {
return insertionData;
}
public VehicleRoute getRoute() {
return route;
}
public Job getJob() {
return job;
}
public double getScore() {
return score;
}
}

View file

@ -1,53 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
interface StateManager {
interface State {
double toDouble();
}
class StateImpl implements State{
double state;
public StateImpl(double state) {
super();
this.state = state;
}
@Override
public double toDouble() {
return state;
}
}
interface States {
State getState(String key);
}
State getActivityState(TourActivity act, String stateType);
State getRouteState(VehicleRoute route, String stateType);
}

View file

@ -1,151 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import basics.Job;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
class StateManagerImpl implements StateManager, InsertionStartsListener, JobInsertedListener {
static class StatesImpl implements States{
private Map<String,State> states = new HashMap<String, State>();
public void putState(String key, State state) {
states.put(key, state);
}
@Override
public State getState(String key) {
return states.get(key);
}
}
private Map<VehicleRoute,States> vehicleRouteStates = new HashMap<VehicleRoute, StateManager.States>();
private Map<TourActivity,States> activityStates = new HashMap<TourActivity, StateManager.States>();
private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor();
private ReverseRouteActivityVisitor revRouteActivityVisitor = new ReverseRouteActivityVisitor();
private Collection<RouteVisitor> routeVisitors = new ArrayList<RouteVisitor>();
public void clear(){
vehicleRouteStates.clear();
activityStates.clear();
}
@Override
public State getActivityState(TourActivity act, String stateType) {
if(!activityStates.containsKey(act)){
return getDefaultActState(stateType,act);
}
StatesImpl actStates = (StatesImpl) activityStates.get(act);
State state = actStates.getState(stateType);
if(state == null){
return getDefaultActState(stateType,act);
}
return state;
}
public void putActivityState(TourActivity act, String stateType, State state){
if(!activityStates.containsKey(act)){
activityStates.put(act, new StatesImpl());
}
StatesImpl actStates = (StatesImpl) activityStates.get(act);
actStates.putState(stateType, state);
}
private State getDefaultActState(String stateType, TourActivity act){
if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0);
if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0);
if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0);
if(stateType.equals(StateTypes.EARLIEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalEarliestOperationStartTime());
if(stateType.equals(StateTypes.LATEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalLatestOperationStartTime());
if(stateType.equals(StateTypes.FUTURE_PICKS)) return new StateImpl(0);
if(stateType.equals(StateTypes.PAST_DELIVERIES)) return new StateImpl(0);
return null;
}
private State getDefaultRouteState(String stateType, VehicleRoute route){
if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0);
if(stateType.equals(StateTypes.LOAD_AT_DEPOT)) return new StateImpl(0);
if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0);
if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0);
return null;
}
@Override
public State getRouteState(VehicleRoute route, String stateType) {
if(!vehicleRouteStates.containsKey(route)){
return getDefaultRouteState(stateType,route);
}
StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route);
State state = routeStates.getState(stateType);
if(state == null){
return getDefaultRouteState(stateType, route);
}
return state;
}
public void putRouteState(VehicleRoute route, String stateType, State state){
if(!vehicleRouteStates.containsKey(route)){
vehicleRouteStates.put(route, new StatesImpl());
}
StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route);
routeStates.putState(stateType, state);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
for(RouteVisitor v : routeVisitors){ v.visit(inRoute); }
routeActivityVisitor.visit(inRoute);
revRouteActivityVisitor.visit(inRoute);
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes,Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
for(RouteVisitor v : routeVisitors){ v.visit(route); }
routeActivityVisitor.visit(route);
revRouteActivityVisitor.visit(route);
}
}
public void addActivityVisitor(ActivityVisitor activityVistor){
routeActivityVisitor.addActivityVisitor(activityVistor);
}
public void addActivityVisitor(ReverseActivityVisitor activityVistor){
revRouteActivityVisitor.addActivityVisitor(activityVistor);
}
public void addRouteVisitor(RouteVisitor routeVisitor){
routeVisitors.add(routeVisitor);
}
}

View file

@ -1,40 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
class StateTypes {
// final static StateId LOAD = new StateIdImpl("load");
final static String LOAD = "load";
final static String LOAD_AT_DEPOT = "loadAtDepot";
final static String DURATION = "duration";
final static String LATEST_OPERATION_START_TIME = "latestOST";
final static String EARLIEST_OPERATION_START_TIME = "earliestOST";
static final String COSTS = "costs";
final static String FUTURE_PICKS = "futurePicks";
final static String PAST_DELIVERIES = "pastDeliveries";
}

View file

@ -1,633 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import algorithms.RuinStrategy.RuinListener;
import algorithms.StateManager.StateImpl;
import basics.Delivery;
import basics.Job;
import basics.Pickup;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionEndsListener;
import basics.algo.InsertionStartsListener;
import basics.algo.IterationStartsListener;
import basics.algo.JobInsertedListener;
import basics.costs.ForwardTransportCost;
import basics.costs.ForwardTransportTime;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DeliveryActivity;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.TourActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.VehicleType;
class StateUpdates {
static class UpdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{
private StateManagerImpl states;
private VehicleRoutingTransportCosts tpCosts;
private VehicleRoutingActivityCosts actCosts;
public UpdateCostsAtRouteLevel(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts, VehicleRoutingActivityCosts actCosts) {
super();
this.states = states;
this.tpCosts = tpCosts;
this.actCosts = actCosts;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
// inRoute.getVehicleRouteCostCalculator().addTransportCost(additionalCosts);
double oldCosts = states.getRouteState(inRoute, StateTypes.COSTS).toDouble();
oldCosts += additionalCosts;
states.putRouteState(inRoute, StateTypes.COSTS, new StateImpl(oldCosts));
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
RouteActivityVisitor forwardInTime = new RouteActivityVisitor();
forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
for(VehicleRoute route : vehicleRoutes){
forwardInTime.visit(route);
}
}
@Override
public void informInsertionEnds(Collection<VehicleRoute> vehicleRoutes) {
// IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts);
// forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states));
// for(VehicleRoute route : vehicleRoutes){
// if(route.isEmpty()) continue;
// route.getVehicleRouteCostCalculator().reset();
// route.getVehicleRouteCostCalculator().addOtherCost(states.getRouteState(route, StateTypes.COSTS).toDouble());
// route.getVehicleRouteCostCalculator().price(route.getVehicle());
// forwardInTime.iterate(route);
// }
}
}
static class UpdateActivityTimes implements ActivityVisitor{
private Logger log = Logger.getLogger(UpdateActivityTimes.class);
private ActivityTimeTracker timeTracker;
private VehicleRoute route;
public UpdateActivityTimes(ForwardTransportTime transportTime) {
super();
timeTracker = new ActivityTimeTracker(transportTime);
}
@Override
public void begin(VehicleRoute route) {
timeTracker.begin(route);
this.route = route;
route.getStart().setEndTime(timeTracker.getActEndTime());
}
@Override
public void visit(TourActivity activity) {
timeTracker.visit(activity);
activity.setArrTime(timeTracker.getActArrTime());
activity.setEndTime(timeTracker.getActEndTime());
}
@Override
public void finish() {
timeTracker.finish();
route.getEnd().setArrTime(timeTracker.getActArrTime());
}
}
static class UpdateCostsAtAllLevels implements ActivityVisitor{
private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class);
private VehicleRoutingActivityCosts activityCost;
private ForwardTransportCost transportCost;
private StateManagerImpl states;
private double totalOperationCost = 0.0;
private VehicleRoute vehicleRoute = null;
private TourActivity prevAct = null;
private double startTimeAtPrevAct = 0.0;
private ActivityTimeTracker timeTracker;
public UpdateCostsAtAllLevels(VehicleRoutingActivityCosts activityCost, VehicleRoutingTransportCosts transportCost, StateManagerImpl states) {
super();
this.activityCost = activityCost;
this.transportCost = transportCost;
this.states = states;
timeTracker = new ActivityTimeTracker(transportCost);
}
@Override
public void begin(VehicleRoute route) {
vehicleRoute = route;
vehicleRoute.getVehicleRouteCostCalculator().reset();
timeTracker.begin(route);
prevAct = route.getStart();
startTimeAtPrevAct = timeTracker.getActEndTime();
}
@Override
public void visit(TourActivity act) {
timeTracker.visit(act);
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(act, timeTracker.getActArrTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
totalOperationCost += transportCost;
totalOperationCost += actCost;
states.putActivityState(act, StateTypes.COSTS, new StateImpl(totalOperationCost));
prevAct = act;
startTimeAtPrevAct = timeTracker.getActEndTime();
}
@Override
public void finish() {
timeTracker.finish();
double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), vehicleRoute.getEnd().getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle());
double actCost = activityCost.getActivityCost(vehicleRoute.getEnd(), timeTracker.getActEndTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost);
vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost);
totalOperationCost += transportCost;
totalOperationCost += actCost;
// totalOperationCost += getFixCosts();
states.putRouteState(vehicleRoute, StateTypes.COSTS, new StateImpl(totalOperationCost));
// this is rather strange and likely to change
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver());
vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle());
vehicleRoute.getVehicleRouteCostCalculator().finish();
startTimeAtPrevAct = 0.0;
prevAct = null;
vehicleRoute = null;
totalOperationCost = 0.0;
}
private double getFixCosts() {
Vehicle vehicle = vehicleRoute.getVehicle();
if(vehicle == null) return 0.0;
VehicleType type = vehicle.getType();
if(type == null) return 0.0;
return type.getVehicleCostParams().fix;
}
}
static class UpdateEarliestStartTimeWindowAtActLocations implements ActivityVisitor{
private StateManagerImpl states;
private ActivityTimeTracker timeTracker;
public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts transportCosts) {
super();
this.states = states;
timeTracker = new ActivityTimeTracker(transportCosts);
}
@Override
public void begin(VehicleRoute route) {
timeTracker.begin(route);
}
@Override
public void visit(TourActivity activity) {
timeTracker.visit(activity);
states.putActivityState(activity, StateTypes.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(timeTracker.getActArrTime(), activity.getTheoreticalEarliestOperationStartTime())));
}
@Override
public void finish() {}
}
static class UpdateLatestOperationStartTimeAtActLocations implements ReverseActivityVisitor{
private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class);
private StateManagerImpl states;
private VehicleRoute route;
private VehicleRoutingTransportCosts transportCosts;
private double latestArrTimeAtPrevAct;
private TourActivity prevAct;
public UpdateLatestOperationStartTimeAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts) {
super();
this.states = states;
this.transportCosts = tpCosts;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
latestArrTimeAtPrevAct = route.getEnd().getTheoreticalLatestOperationStartTime();
prevAct = route.getEnd();
}
@Override
public void visit(TourActivity activity) {
double potentialLatestArrivalTimeAtCurrAct = latestArrTimeAtPrevAct - transportCosts.getBackwardTransportTime(activity.getLocationId(), prevAct.getLocationId(), latestArrTimeAtPrevAct, route.getDriver(),route.getVehicle()) - activity.getOperationTime();
double latestArrivalTime = Math.min(activity.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct);
states.putActivityState(activity, StateTypes.LATEST_OPERATION_START_TIME, new StateImpl(latestArrivalTime));
latestArrTimeAtPrevAct = latestArrivalTime;
prevAct = activity;
}
@Override
public void finish() {}
}
static class UpdateLoadAtAllLevels implements ActivityVisitor{
private double load = 0.0;
private StateManagerImpl states;
private VehicleRoute vehicleRoute;
public UpdateLoadAtAllLevels(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void begin(VehicleRoute route) {
vehicleRoute = route;
}
@Override
public void visit(TourActivity activity) {
load += (double)activity.getCapacityDemand();
states.putActivityState(activity, StateTypes.LOAD, new StateImpl(load));
}
@Override
public void finish() {
states.putRouteState(vehicleRoute, StateTypes.LOAD, new StateImpl(load));
load=0;
vehicleRoute = null;
}
}
static class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener{
private StateManagerImpl states;
public UpdateLoadAtRouteLevel(StateManagerImpl states) {
super();
this.states = states;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(!(job2insert instanceof Service)){
return;
}
double oldLoad = states.getRouteState(inRoute, StateTypes.LOAD).toDouble();
states.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(oldLoad + job2insert.getCapacityDemand()));
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
int load = 0;
for(Job j : route.getTourActivities().getJobs()){
load += j.getCapacityDemand();
}
states.putRouteState(route, StateTypes.LOAD, new StateImpl(load));
}
}
}
static class UpdateStates implements JobInsertedListener, RuinListener{
private RouteActivityVisitor routeActivityVisitor;
private ReverseRouteActivityVisitor revRouteActivityVisitor;
public UpdateStates(StateManagerImpl states, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) {
routeActivityVisitor = new RouteActivityVisitor();
routeActivityVisitor.addActivityVisitor(new UpdateActivityTimes(routingCosts));
routeActivityVisitor.addActivityVisitor(new UpdateCostsAtAllLevels(activityCosts, routingCosts, states));
routeActivityVisitor.addActivityVisitor(new UpdateLoadAtAllLevels(states));
revRouteActivityVisitor = new ReverseRouteActivityVisitor();
revRouteActivityVisitor.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(states, routingCosts));
}
public void update(VehicleRoute route){
routeActivityVisitor.visit(route);
revRouteActivityVisitor.visit(route);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
routeActivityVisitor.visit(inRoute);
revRouteActivityVisitor.visit(inRoute);
}
@Override
public void ruinStarts(Collection<VehicleRoute> routes) {}
@Override
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
for(VehicleRoute route : routes) {
routeActivityVisitor.visit(route);
revRouteActivityVisitor.visit(route);
}
}
@Override
public void removed(Job job, VehicleRoute fromRoute) {}
}
static class UpdateFuturePickupsAtActivityLevel implements ReverseActivityVisitor {
private StateManagerImpl stateManager;
private int futurePicks = 0;
private VehicleRoute route;
public UpdateFuturePickupsAtActivityLevel(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
}
@Override
public void visit(TourActivity act) {
stateManager.putActivityState(act, StateTypes.FUTURE_PICKS, new StateImpl(futurePicks));
if(act instanceof PickupActivity || act instanceof ServiceActivity){
futurePicks += act.getCapacityDemand();
}
assert futurePicks <= route.getVehicle().getCapacity() : "sum of pickups must not be > vehicleCap";
assert futurePicks >= 0 : "sum of pickups must not < 0";
}
@Override
public void finish() {
futurePicks = 0;
route = null;
}
}
static class UpdateOccuredDeliveriesAtActivityLevel implements ActivityVisitor {
private StateManagerImpl stateManager;
private int deliveries = 0;
private VehicleRoute route;
public UpdateOccuredDeliveriesAtActivityLevel(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
this.route = route;
}
@Override
public void visit(TourActivity act) {
if(act instanceof DeliveryActivity){
deliveries += Math.abs(act.getCapacityDemand());
}
stateManager.putActivityState(act, StateTypes.PAST_DELIVERIES, new StateImpl(deliveries));
assert deliveries >= 0 : "deliveries < 0";
assert deliveries <= route.getVehicle().getCapacity() : "deliveries > vehicleCap";
}
@Override
public void finish() {
deliveries = 0;
route = null;
}
}
/**
* Updates load at activity level. Note that this assumed that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT.
* If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot.
*
* @author stefan
*
*/
static class UpdateLoadAtActivityLevel implements ActivityVisitor {
private StateManagerImpl stateManager;
private int currentLoad = 0;
private VehicleRoute route;
public UpdateLoadAtActivityLevel(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void begin(VehicleRoute route) {
currentLoad = (int) stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT).toDouble();
this.route = route;
}
@Override
public void visit(TourActivity act) {
currentLoad += act.getCapacityDemand();
stateManager.putActivityState(act, StateTypes.LOAD, new StateImpl(currentLoad));
assert currentLoad <= route.getVehicle().getCapacity() : "currentLoad at activity must not be > vehicleCapacity";
assert currentLoad >= 0 : "currentLoad at act must not be < 0";
}
@Override
public void finish() {
currentLoad = 0;
}
}
static class ResetStateManager implements IterationStartsListener {
private StateManagerImpl stateManager;
public ResetStateManager(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
stateManager.clear();
}
}
static interface InsertionStarts {
void insertionStarts(VehicleRoute route);
}
static class UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts implements InsertionStarts {
private StateManagerImpl stateManager;
public UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void insertionStarts(VehicleRoute route) {
int loadAtDepot = 0;
int loadAtEnd = 0;
for(Job j : route.getTourActivities().getJobs()){
if(j instanceof Delivery){
loadAtDepot += j.getCapacityDemand();
}
else if(j instanceof Pickup || j instanceof Service){
loadAtEnd += j.getCapacityDemand();
}
}
stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot));
stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd));
}
}
static class UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted implements JobInsertedListener {
private StateManagerImpl stateManager;
public UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(StateManagerImpl stateManager) {
super();
this.stateManager = stateManager;
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
if(job2insert instanceof Delivery){
int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble();
// log.info("loadAtDepot="+loadAtDepot);
stateManager.putRouteState(inRoute, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot + job2insert.getCapacityDemand()));
}
else if(job2insert instanceof Pickup || job2insert instanceof Service){
int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD).toDouble();
// log.info("loadAtEnd="+loadAtEnd);
stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand()));
}
}
}
static class UpdateRouteStatesOnceTheRouteHasBeenChanged implements InsertionStartsListener, JobInsertedListener {
private RouteActivityVisitor forwardInTimeIterator;
private ReverseRouteActivityVisitor backwardInTimeIterator;
private Collection<InsertionStarts> insertionStartsListeners;
private Collection<JobInsertedListener> jobInsertionListeners;
public UpdateRouteStatesOnceTheRouteHasBeenChanged(VehicleRoutingTransportCosts routingCosts) {
forwardInTimeIterator = new RouteActivityVisitor();
backwardInTimeIterator = new ReverseRouteActivityVisitor();
insertionStartsListeners = new ArrayList<InsertionStarts>();
jobInsertionListeners = new ArrayList<JobInsertedListener>();
}
void addVisitor(ActivityVisitor vis){
forwardInTimeIterator.addActivityVisitor(vis);
}
void addVisitor(ReverseActivityVisitor revVis){
backwardInTimeIterator.addActivityVisitor(revVis);
}
void addInsertionStartsListener(InsertionStarts insertionStartListener){
insertionStartsListeners.add(insertionStartListener);
}
void addJobInsertedListener(JobInsertedListener jobInsertedListener){
jobInsertionListeners.add(jobInsertedListener);
}
@Override
public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) {
for(JobInsertedListener l : jobInsertionListeners){ l.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); }
forwardInTimeIterator.visit(inRoute);
backwardInTimeIterator.visit(inRoute);
}
@Override
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
for(VehicleRoute route : vehicleRoutes){
for(InsertionStarts insertionsStartsHandler : insertionStartsListeners){
insertionsStartsHandler.insertionStarts(route);
}
forwardInTimeIterator.visit(route);
backwardInTimeIterator.visit(route);
}
}
}
}

View file

@ -1,84 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
import java.util.Collection;
import basics.route.Vehicle;
interface VehicleFleetManager {
static class TypeKey {
public final String type;
public final String locationId;
public TypeKey(String typeId, String locationId) {
super();
this.type = typeId;
this.locationId = locationId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((locationId == null) ? 0 : locationId.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TypeKey other = (TypeKey) obj;
if (locationId == null) {
if (other.locationId != null)
return false;
} else if (!locationId.equals(other.locationId))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
}
abstract void lock(Vehicle vehicle);
abstract void unlock(Vehicle vehicle);
abstract boolean isLocked(Vehicle vehicle);
abstract void unlockAll();
abstract Collection<Vehicle> getAvailableVehicles();
Collection<Vehicle> getAvailableVehicles(String withoutThisType, String locationId);
}

View file

@ -1,45 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.costs;
import basics.route.Driver;
import basics.route.TourActivity;
import basics.route.Vehicle;
/**
* Function that basically does not allow soft time-windows. Actually, it is allowed but it is penalized with Double.MaxValue().
*
* @author schroeder
*
*/
public class DefaultVehicleRoutingActivityCosts implements VehicleRoutingActivityCosts{
@Override
public double getActivityCost(TourActivity tourAct, double arrivalTime, Driver driver, Vehicle vehicle) {
if(arrivalTime > tourAct.getTheoreticalLatestOperationStartTime()){
return Double.MAX_VALUE;
}
return 0;
}
@Override
public String toString() {
return "[name=hardTimeWindowActCosts]";
}
}

View file

@ -1,128 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.route;
public class DefaultVehicleRouteCostCalculator implements VehicleRouteCostCalculator {
private double tpCosts = 0.0;
private double actCosts = 0.0;
private double vehicleCosts = 0.0;
private double driverCosts = 0.0;
private double other = 0.0;
public DefaultVehicleRouteCostCalculator(){}
private DefaultVehicleRouteCostCalculator(DefaultVehicleRouteCostCalculator costCalc){
this.tpCosts=costCalc.getTpCosts();
this.actCosts = costCalc.getActCosts();
this.driverCosts = costCalc.getDriverCosts();
this.other = costCalc.getOther();
this.vehicleCosts = costCalc.getVehicleCosts();
}
public void addTransportCost(double tpCost) {
this.tpCosts+=tpCost;
}
public void addActivityCost(double actCost){
this.actCosts+=actCost;
}
public void price(Vehicle vehicle){
if(vehicle != null){
VehicleType type = vehicle.getType();
if(type != null){
this.vehicleCosts = type.getVehicleCostParams().fix;
}
}
}
public void price(Driver driver){
}
@Override
public void finish() {
// TODO Auto-generated method stub
}
@Override
public void reset() {
tpCosts = 0.0;
actCosts = 0.0;
vehicleCosts = 0.0;
driverCosts = 0.0;
other = 0.0;
}
@Override
public void addOtherCost(double cost) {
this.other = cost;
}
@Override
public double getCosts() {
return tpCosts + actCosts + vehicleCosts + driverCosts + other;
}
/**
* @return the tpCosts
*/
public double getTpCosts() {
return tpCosts;
}
/**
* @return the actCosts
*/
public double getActCosts() {
return actCosts;
}
/**
* @return the vehicleCosts
*/
public double getVehicleCosts() {
return vehicleCosts;
}
/**
* @return the driverCosts
*/
public double getDriverCosts() {
return driverCosts;
}
/**
* @return the other
*/
public double getOther() {
return other;
}
@Override
public VehicleRouteCostCalculator duplicate() {
return new DefaultVehicleRouteCostCalculator(this);
}
}

View file

@ -1,102 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.route;
import basics.Pickup;
import basics.route.TourActivity.JobActivity;
public class PickupActivity implements JobActivity<Pickup>{
private Pickup pickup;
private double arrTime;
private double depTime;
public PickupActivity(Pickup pickup) {
super();
this.pickup = pickup;
}
private PickupActivity(PickupActivity pickupActivity){
this.pickup=pickupActivity.getJob();
this.arrTime=pickupActivity.getArrTime();
this.depTime=pickupActivity.getEndTime();
}
@Override
public String getName() {
return pickup.getType();
}
@Override
public String getLocationId() {
return pickup.getLocationId();
}
@Override
public double getTheoreticalEarliestOperationStartTime() {
return pickup.getTimeWindow().getStart();
}
@Override
public double getTheoreticalLatestOperationStartTime() {
return pickup.getTimeWindow().getEnd();
}
@Override
public double getOperationTime() {
return pickup.getServiceDuration();
}
@Override
public double getArrTime() {
return arrTime;
}
@Override
public double getEndTime() {
return depTime;
}
@Override
public void setArrTime(double arrTime) {
this.arrTime=arrTime;
}
@Override
public void setEndTime(double endTime) {
this.depTime=endTime;
}
@Override
public TourActivity duplicate() {
return new PickupActivity(this);
}
@Override
public Pickup getJob() {
return pickup;
}
@Override
public int getCapacityDemand() {
return pickup.getCapacityDemand();
}
}

View file

@ -1,204 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.route;
import basics.route.VehicleImpl.NoVehicle;
public class VehicleRoute {
public static VehicleRoute copyOf(VehicleRoute route) {
return new VehicleRoute(route);
}
public static VehicleRoute newInstance(TourActivities tour, Driver driver, Vehicle vehicle) {
return new VehicleRoute(tour,driver,vehicle);
}
public static VehicleRoute emptyRoute() {
return new VehicleRoute(TourActivities.emptyTour(), DriverImpl.noDriver(), VehicleImpl.noVehicle());
}
public static class Builder {
public static Builder newInstance(Start start, End end){
return new Builder(start,end);
}
private Start start;
private End end;
private Vehicle vehicle = VehicleImpl.noVehicle();
private Driver driver = DriverImpl.noDriver();
private TourActivities tour;
private Builder(Start start, End end) {
super();
this.start = start;
this.end = end;
this.tour = TourActivities.emptyTour();
}
public Builder setVehicle(Vehicle vehicle){
this.vehicle = vehicle;
return this;
}
public Builder setDriver(Driver driver){
this.driver = driver;
return this;
}
public Builder addActivity(TourActivity act){
if(act instanceof Start || act instanceof End){
throw new IllegalStateException("tourActivity should be of type Delivery or Pickup, but is of type " + act.getName());
}
tour.addActivity(act);
return this;
}
public VehicleRoute build(){
return new VehicleRoute(this);
}
}
private TourActivities tourActivities;
private Vehicle vehicle;
private Driver driver;
private Start start;
private End end;
@Deprecated
private VehicleRouteCostCalculator costCalculator = new DefaultVehicleRouteCostCalculator();
@Deprecated
public VehicleRouteCostCalculator getVehicleRouteCostCalculator(){
return costCalculator;
}
private VehicleRoute(VehicleRoute route){
this.start = Start.copyOf(route.getStart());
this.end = End.copyOf(route.getEnd());
this.tourActivities = TourActivities.copyOf(route.getTourActivities());
this.vehicle = route.getVehicle();
this.driver = route.getDriver();
this.costCalculator = route.getVehicleRouteCostCalculator().duplicate();
}
private VehicleRoute(TourActivities tour, Driver driver, Vehicle vehicle) {
super();
verify(tour, driver, vehicle);
this.tourActivities = tour;
this.vehicle = vehicle;
this.driver = driver;
setStartAndEnd(vehicle, vehicle.getEarliestDeparture());
}
private VehicleRoute(Builder builder){
this.tourActivities = builder.tour;
this.vehicle = builder.vehicle;
this.driver = builder.driver;
this.start = builder.start;
this.end = builder.end;
}
private void verify(TourActivities tour, Driver driver, Vehicle vehicle) {
if(tour == null || driver == null || vehicle == null) throw new IllegalStateException("null is not allowed for tour, driver or vehicle. use emptyRoute. use Tour.emptyTour, DriverImpl.noDriver() and VehicleImpl.noVehicle() instead." +
"\n\tor make it easier and use VehicleRoute.emptyRoute()");
if(!tour.isEmpty() && vehicle instanceof NoVehicle){
throw new IllegalStateException("if tour is not empty. there must be a vehicle for this tour, but there is no vehicle.");
}
}
public TourActivities getTourActivities() {
return tourActivities;
}
public Vehicle getVehicle() {
return vehicle;
}
public Driver getDriver() {
return driver;
}
public void setVehicle(Vehicle vehicle, double vehicleDepTime){
this.vehicle = vehicle;
setStartAndEnd(vehicle, vehicleDepTime);
}
public void setDepartureTime(double vehicleDepTime){
if(start == null) throw new IllegalStateException("cannot set departureTime without having a vehicle on this route. use setVehicle(vehicle,departureTime) instead.");
start.setEndTime(vehicleDepTime);
}
public double getDepartureTime(){
if(start == null) throw new IllegalStateException("cannot get departureTime without having a vehicle on this route. use setVehicle(vehicle,departureTime) instead.");
return start.getEndTime();
}
private void setStartAndEnd(Vehicle vehicle, double vehicleDepTime) {
if(!(vehicle instanceof NoVehicle)){
if(start == null && end == null){
start = Start.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
end = End.newInstance(vehicle.getLocationId(), vehicle.getEarliestDeparture(), vehicle.getLatestArrival());
}
start.setEndTime(vehicleDepTime);
start.setTheoreticalEarliestOperationStartTime(vehicle.getEarliestDeparture());
start.setTheoreticalLatestOperationStartTime(vehicle.getLatestArrival());
start.setLocationId(vehicle.getLocationId());
end.setLocationId(vehicle.getLocationId());
end.setTheoreticalEarliestOperationStartTime(vehicle.getEarliestDeparture());
end.setTheoreticalLatestOperationStartTime(vehicle.getLatestArrival());
}
}
public boolean isEmpty() {
return tourActivities.isEmpty();
}
public Start getStart() {
return start;
}
public End getEnd() {
return end;
}
@Deprecated
public void setVehicleRouteCostCalculator(VehicleRouteCostCalculator costAccumulator){
this.costCalculator = costAccumulator;
}
@Deprecated
public double getCost() {
if(tourActivities.isEmpty()){
return 0.0;
}
return costCalculator.getCosts();
}
}

View file

@ -1,40 +0,0 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.route;
@Deprecated
public interface VehicleRouteCostCalculator {
public void addTransportCost(double cost);
public void addActivityCost(double cost);
public void addOtherCost(double cost);
public void price(Vehicle vehicle);
public void price(Driver driver);
public double getCosts();
public void finish();
public void reset();
public VehicleRouteCostCalculator duplicate();
}

View file

@ -0,0 +1,54 @@
///*******************************************************************************
// * Copyright (C) 2013 Stefan Schroeder
// *
// * This library is free software; you can redistribute it and/or
// * modify it under the terms of the GNU Lesser General Public
// * License as published by the Free Software Foundation; either
// * version 3.0 of the License, or (at your option) any later version.
// *
// * This library is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// * Lesser General Public License for more details.
// *
// * You should have received a copy of the GNU Lesser General Public
// * License along with this library. If not, see <http://www.gnu.org/licenses/>.
// ******************************************************************************/
//package jsprit.core.algorithm;
//
//import java.util.ArrayList;
//import java.util.Collection;
//import java.util.List;
//
//import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
//import jsprit.core.problem.job.Job;
//import jsprit.core.problem.solution.route.VehicleRoute;
//
//
//class FindCheaperVehicle implements InsertionStartsListener{
//
// FindCheaperVehicleAlgo findCheaperVehicle;
//
// public FindCheaperVehicle(FindCheaperVehicleAlgo findCheaperVehicle) {
// super();
// this.findCheaperVehicle = findCheaperVehicle;
// }
//
// @Override
// public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
// List<VehicleRoute> newRoutes = new ArrayList<VehicleRoute>();
// for(VehicleRoute route : vehicleRoutes){
// if(route.isEmpty()) continue;
// VehicleRoute cheaperRoute = findCheaperVehicle.runAndGetVehicleRoute(route);
// newRoutes.add(cheaperRoute);
// }
// vehicleRoutes.clear();
// vehicleRoutes.addAll(newRoutes);
// }
//
// @Override
// public String toString() {
// return "[name=findCheaperVehicle]";
// }
//
//}

View file

@ -0,0 +1,114 @@
///*******************************************************************************
// * Copyright (C) 2013 Stefan Schroeder
// *
// * This library is free software; you can redistribute it and/or
// * modify it under the terms of the GNU Lesser General Public
// * License as published by the Free Software Foundation; either
// * version 3.0 of the License, or (at your option) any later version.
// *
// * This library is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// * Lesser General Public License for more details.
// *
// * You should have received a copy of the GNU Lesser General Public
// * License along with this library. If not, see <http://www.gnu.org/licenses/>.
// ******************************************************************************/
//package jsprit.core.algorithm;
//
//import java.util.ArrayList;
//import java.util.List;
//
//import jsprit.core.algorithm.recreate.AuxilliaryCostCalculator;
//import jsprit.core.algorithm.state.StateFactory;
//import jsprit.core.algorithm.state.StateGetter;
//import jsprit.core.problem.solution.route.VehicleRoute;
//import jsprit.core.problem.solution.route.activity.TourActivities;
//import jsprit.core.problem.solution.route.activity.TourActivity;
//import jsprit.core.problem.vehicle.Vehicle;
//import jsprit.core.problem.vehicle.VehicleFleetManager;
//import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
//
//import org.apache.log4j.Logger;
//
//
//
//
//final class FindCheaperVehicleAlgo {
//
// private static Logger log = Logger.getLogger(FindCheaperVehicleAlgo.class);
//
// private VehicleFleetManager fleetManager;
//
// private VehicleRouteUpdater tourStateCalculator;
//
// private AuxilliaryCostCalculator auxilliaryCostCalculator;
//
// private double weightFixCosts = 1.0;
//
// private StateGetter states;
//
// public void setWeightFixCosts(double weightFixCosts) {
// this.weightFixCosts = weightFixCosts;
// }
//
// public void setStates(StateGetter states) {
// this.states = states;
// }
//
// public FindCheaperVehicleAlgo(VehicleFleetManager fleetManager, VehicleRouteUpdater tourStateCalculator, AuxilliaryCostCalculator auxilliaryCostCalculator) {
// super();
// this.fleetManager = fleetManager;
// this.tourStateCalculator = tourStateCalculator;
// this.auxilliaryCostCalculator = auxilliaryCostCalculator;
// }
//
//
// public VehicleRoute runAndGetVehicleRoute(VehicleRoute vehicleRoute) {
// if(vehicleRoute.getVehicle() instanceof NoVehicle){
// return vehicleRoute;
// }
// if(vehicleRoute.getTourActivities() == null || vehicleRoute.getVehicle() == null){
// return vehicleRoute;
// }
//// Collection<TypeKey> availableVehicleTypes = fleetManager.getAvailableVehicleTypes(new TypeKey(vehicleRoute.getVehicle().getType(),vehicleRoute.getVehicle().getLocationId()));
// double bestSaving = 0.0;
// Vehicle bestVehicle = null;
// List<TourActivity> path = new ArrayList<TourActivity>();
// path.add(vehicleRoute.getStart());
// path.addAll(vehicleRoute.getTourActivities().getActivities());
// path.add(vehicleRoute.getEnd());
//
// for(Vehicle vehicle : fleetManager.getAvailableVehicles(vehicleRoute.getVehicle().getType().getTypeId(), vehicleRoute.getVehicle().getLocationId())){
//// Vehicle vehicle = fleetManager.getEmptyVehicle(vehicleType);
// if(vehicle.getType().getTypeId().equals(vehicleRoute.getVehicle().getType().getTypeId())){
// continue;
// }
// if(states.getRouteState(vehicleRoute,StateFactory.LOAD).toDouble() <= vehicle.getCapacity()){
// double fixCostSaving = vehicleRoute.getVehicle().getType().getVehicleCostParams().fix - vehicle.getType().getVehicleCostParams().fix;
// double departureTime = vehicleRoute.getStart().getEndTime();
// double newCost = auxilliaryCostCalculator.costOfPath(path, departureTime, vehicleRoute.getDriver(), vehicle);
// double varCostSaving = states.getRouteState(vehicleRoute, StateFactory.COSTS).toDouble() - newCost;
// double totalCostSaving = varCostSaving + weightFixCosts*fixCostSaving;
// if(totalCostSaving > bestSaving){
// bestSaving = totalCostSaving;
// bestVehicle = vehicle;
// }
// }
// }
// if(bestVehicle != null){
// try{
// fleetManager.unlock(vehicleRoute.getVehicle());
// fleetManager.lock(bestVehicle);
// }
// catch(IllegalStateException e){
// throw new IllegalStateException(e);
// }
// TourActivities newTour = TourActivities.copyOf(vehicleRoute.getTourActivities());
// tourStateCalculator.iterate(vehicleRoute);
// return VehicleRoute.newInstance(newTour,vehicleRoute.getDriver(),bestVehicle);
// }
// return vehicleRoute;
// }
//
//}

View file

@ -0,0 +1,82 @@
/*******************************************************************************
* Copyright (c) 2011 Stefan Schroeder.
* eMail: stefan.schroeder@kit.edu
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
/* *********************************************************************** *
* project: org.matsim.*
* IniSolution.java
* *
* *********************************************************************** *
* *
* copyright : (C) 2011 by the members listed in the COPYING, *
* LICENSE and WARRANTY file. *
* email : info at matsim dot org *
* *
* *********************************************************************** *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* See also COPYING, LICENSE and WARRANTY file *
* *
* *********************************************************************** */
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.List;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.InitialSolutionFactory;
import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import org.apache.log4j.Logger;
public final class InsertionInitialSolutionFactory implements InitialSolutionFactory {
private static final Logger logger = Logger.getLogger(InsertionInitialSolutionFactory.class);
private final InsertionStrategy insertion;
private SolutionCostCalculator solutionCostsCalculator;
public InsertionInitialSolutionFactory(InsertionStrategy insertionStrategy, SolutionCostCalculator solutionCostCalculator) {
super();
this.insertion = insertionStrategy;
this.solutionCostsCalculator = solutionCostCalculator;
}
@Override
public VehicleRoutingProblemSolution createSolution(final VehicleRoutingProblem vrp) {
logger.info("create initial solution.");
List<VehicleRoute> vehicleRoutes = new ArrayList<VehicleRoute>();
insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(vehicleRoutes, Double.MAX_VALUE);
double costs = solutionCostsCalculator.getCosts(solution);
solution.setCost(costs);
logger.info("creation done");
return solution;
}
private List<Job> getUnassignedJobs(VehicleRoutingProblem vrp) {
List<Job> jobs = new ArrayList<Job>(vrp.getJobs().values());
return jobs;
}
}

View file

@ -14,28 +14,28 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm;
import java.util.Collection;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.util.CrowFlyCosts;
import jsprit.core.util.EuclideanDistanceCalculator;
import jsprit.core.util.Locations;
import jsprit.core.util.NeighborhoodImpl;
import jsprit.core.util.Solutions;
import org.apache.commons.math.stat.descriptive.moment.Mean;
import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
import org.apache.log4j.Logger;
import util.CrowFlyCosts;
import util.EuclideanDistanceCalculator;
import util.Locations;
import util.NeighborhoodImpl;
import util.Solutions;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmStartsListener;
import basics.algo.VehicleRoutingAlgorithmFactory;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
public class NeighborhoodThresholdInitialiser implements AlgorithmStartsListener{
class NeighborhoodThresholdInitialiser implements AlgorithmStartsListener{
private static Logger log = Logger.getLogger(NeighborhoodThresholdInitialiser.class);

View file

@ -14,24 +14,22 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.log4j.Logger;
import jsprit.core.algorithm.recreate.listener.InsertionEndsListener;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import basics.algo.InsertionEndsListener;
import basics.route.VehicleRoute;
class RemoveEmptyVehicles implements InsertionEndsListener{
private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class);
public class RemoveEmptyVehicles implements InsertionEndsListener{
private VehicleFleetManager fleetManager;
RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
public RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
super();
this.fleetManager = fleetManager;
}

View file

@ -14,24 +14,22 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import basics.Job;
import basics.algo.InsertionStartsListener;
import basics.route.VehicleRoute;
class ResetAndIniFleetManager implements InsertionStartsListener{
private static Logger log = Logger.getLogger(ResetAndIniFleetManager.class);
public class ResetAndIniFleetManager implements InsertionStartsListener{
private VehicleFleetManager vehicleFleetManager;
ResetAndIniFleetManager(VehicleFleetManager vehicleFleetManager) {
public ResetAndIniFleetManager(VehicleFleetManager vehicleFleetManager) {
super();
this.vehicleFleetManager = vehicleFleetManager;
}
@ -41,12 +39,7 @@ class ResetAndIniFleetManager implements InsertionStartsListener{
vehicleFleetManager.unlockAll();
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
for(VehicleRoute route : routes){
// if(route.isEmpty()){
// vehicleRoutes.remove(route);
// }
// else{
vehicleFleetManager.lock(route.getVehicle());
// }
}
}

View file

@ -14,18 +14,21 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import jsprit.core.algorithm.acceptor.SolutionAcceptor;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.algorithm.selector.SolutionSelector;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import org.apache.log4j.Logger;
import algorithms.acceptors.SolutionAcceptor;
import algorithms.selectors.SolutionSelector;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
@ -125,7 +128,8 @@ public class SearchStrategy {
VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(lastSolution);
lastSolution = newSolution;
}
solutionCostCalculator.calculateCosts(lastSolution);
double costs = solutionCostCalculator.getCosts(lastSolution);
lastSolution.setCost(costs);
boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution);
DiscoveredSolution discoveredSolution = new DiscoveredSolution(lastSolution, solutionAccepted, getName());
return discoveredSolution;

View file

@ -14,14 +14,17 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import util.RandomNumberGeneration;
import jsprit.core.algorithm.listener.SearchStrategyListener;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.util.RandomNumberGeneration;
public class SearchStrategyManager {

View file

@ -14,9 +14,10 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
public interface SearchStrategyModule {

View file

@ -0,0 +1,33 @@
package jsprit.core.algorithm;
import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.solution.route.state.StateFactory;
public class VariablePlusFixedSolutionCostCalculatorFactory {
private RouteAndActivityStateGetter stateManager;
public VariablePlusFixedSolutionCostCalculatorFactory(RouteAndActivityStateGetter stateManager) {
super();
this.stateManager = stateManager;
}
public SolutionCostCalculator createCalculator(){
return new SolutionCostCalculator() {
@Override
public double getCosts(VehicleRoutingProblemSolution solution) {
double c = 0.0;
for(VehicleRoute r : solution.getRoutes()){
c += stateManager.getRouteState(r, StateFactory.COSTS).toDouble();
c += r.getVehicle().getType().getVehicleCostParams().fix;
}
return c;
}
};
}
}

View file

@ -14,26 +14,29 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics;
package jsprit.core.algorithm;
import java.util.ArrayList;
import java.util.Collection;
import jsprit.core.algorithm.SearchStrategy.DiscoveredSolution;
import jsprit.core.algorithm.acceptor.SolutionAcceptor;
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.algorithm.listener.IterationEndsListener;
import jsprit.core.algorithm.listener.IterationStartsListener;
import jsprit.core.algorithm.listener.SearchStrategyListener;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.algorithm.listener.StrategySelectedListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners;
import jsprit.core.algorithm.termination.IterationWithoutImprovementTermination;
import jsprit.core.algorithm.termination.PrematureAlgorithmTermination;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import org.apache.log4j.Logger;
import util.Counter;
import algorithms.acceptors.SolutionAcceptor;
import basics.algo.AlgorithmEndsListener;
import basics.algo.AlgorithmStartsListener;
import basics.algo.IterationEndsListener;
import basics.algo.IterationStartsListener;
import basics.algo.IterationWithoutImprovementBreaker;
import basics.algo.PrematureAlgorithmBreaker;
import basics.algo.SearchStrategy;
import basics.algo.SearchStrategy.DiscoveredSolution;
import basics.algo.SearchStrategyManager;
import basics.algo.VehicleRoutingAlgorithmListener;
import basics.algo.VehicleRoutingAlgorithmListeners;
/**
* Algorithm that solves a {@link VehicleRoutingProblem}.
@ -43,7 +46,36 @@ import basics.algo.VehicleRoutingAlgorithmListeners;
*/
public class VehicleRoutingAlgorithm {
private static class Counter {
private final String name;
private long counter = 0;
private long nextCounter = 1;
private static final Logger log = Logger.getLogger(Counter.class);
public Counter(final String name) {
this.name = name;
}
public void incCounter() {
long i = counter++;
long n = nextCounter;
if (i >= n) {
if (nextCounter==n) {
nextCounter=n*2;
log.info(this.name + n);
}
}
}
public void print() {
log.info(this.name + counter);
}
public void reset() {
counter=0;
nextCounter=1;
}
}
public static final int NOBREAK = Integer.MAX_VALUE;
@ -61,7 +93,7 @@ public class VehicleRoutingAlgorithm {
private Collection<VehicleRoutingProblemSolution> initialSolutions;
private PrematureAlgorithmBreaker prematureAlgorithmBreaker = new PrematureAlgorithmBreaker() {
private PrematureAlgorithmTermination prematureAlgorithmTermination = new PrematureAlgorithmTermination() {
@Override
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
@ -100,15 +132,16 @@ public class VehicleRoutingAlgorithm {
* Improvement is what {@link SolutionAcceptor} understands about improvement. Or to put it in other words, the algo breaks prematurely after
* the assigned number of iterations without solution-acceptance.
*
*
* @deprecated use setPrematureAlgorithmTermination(new IterationWithoutImprovementTermination(int nuIterationsWithoutImprovement));
* @param nuIterationsWithoutImprovement
*/
@Deprecated
public void setPrematureBreak(int nuIterationsWithoutImprovement){
prematureAlgorithmBreaker = new IterationWithoutImprovementBreaker(nuIterationsWithoutImprovement);
prematureAlgorithmTermination = new IterationWithoutImprovementTermination(nuIterationsWithoutImprovement);
}
public void setPrematureAlgorithmBreaker(PrematureAlgorithmBreaker prematureAlgorithmBreaker){
this.prematureAlgorithmBreaker = prematureAlgorithmBreaker;
public void setPrematureAlgorithmTermination(PrematureAlgorithmTermination prematureAlgorithmTermination){
this.prematureAlgorithmTermination = prematureAlgorithmTermination;
}
/**
@ -146,7 +179,7 @@ public class VehicleRoutingAlgorithm {
SearchStrategy strategy = searchStrategyManager.getRandomStrategy();
DiscoveredSolution discoveredSolution = strategy.run(problem, solutions);
selectedStrategy(strategy.getName(),problem, solutions);
if(prematureAlgorithmBreaker.isPrematureBreak(discoveredSolution)){
if(prematureAlgorithmTermination.isPrematureBreak(discoveredSolution)){
logger.info("premature break at iteration "+ (i+1));
nuOfIterationsThisAlgoIsRunning = (i+1);
break;
@ -194,6 +227,12 @@ public class VehicleRoutingAlgorithm {
return algoListeners;
}
public void addListener(VehicleRoutingAlgorithmListener l){
algoListeners.addListener(l);
if(l instanceof SearchStrategyListener) searchStrategyManager.addSearchStrategyListener((SearchStrategyListener) l);
if(l instanceof SearchStrategyModuleListener) searchStrategyManager.addSearchStrategyModuleListener((SearchStrategyModuleListener) l);
}
private void iterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
algoListeners.iterationEnds(i,problem, solutions);
}

View file

@ -14,10 +14,9 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem;
public interface VehicleRoutingAlgorithmFactory {

View file

@ -14,11 +14,12 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms.acceptors;
package jsprit.core.algorithm.acceptor;
import java.util.Collection;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
public class AcceptNewRemoveFirst implements SolutionAcceptor{

View file

@ -0,0 +1,158 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.algorithm.acceptor;
import java.net.URL;
import java.util.Collection;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.io.AlgorithmConfig;
import jsprit.core.algorithm.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.algorithm.listener.IterationEndsListener;
import jsprit.core.algorithm.listener.IterationStartsListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.util.Resource;
import jsprit.core.util.Solutions;
import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
import org.apache.log4j.Logger;
public class ExperimentalSchrimpfAcceptance implements SolutionAcceptor, IterationStartsListener, AlgorithmStartsListener{
private static Logger logger = Logger.getLogger(ExperimentalSchrimpfAcceptance.class);
private final double alpha;
private int nOfTotalIterations = 1000;
private int currentIteration = 0;
private double initialThreshold = 0.0;
private final int nOfRandomWalks;
private final int solutionMemory;
public ExperimentalSchrimpfAcceptance(int solutionMemory, double alpha, int nOfWarmupIterations) {
super();
this.alpha = alpha;
this.nOfRandomWalks = nOfWarmupIterations;
this.solutionMemory = solutionMemory;
logger.info("initialise " + this);
}
@Override
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
boolean solutionAccepted = false;
if (solutions.size() < solutionMemory) {
solutions.add(newSolution);
solutionAccepted = true;
} else {
VehicleRoutingProblemSolution worst = null;
double threshold = getThreshold(currentIteration);
for(VehicleRoutingProblemSolution solutionInMemory : solutions){
if(worst == null) worst = solutionInMemory;
else if(solutionInMemory.getCost() > worst.getCost()) worst = solutionInMemory;
}
if(newSolution.getRoutes().size() < worst.getRoutes().size()){
solutions.remove(worst);
solutions.add(newSolution);
solutionAccepted = true;
}
else if(newSolution.getRoutes().size() == worst.getRoutes().size() && newSolution.getCost() < worst.getCost() + threshold){
solutions.remove(worst);
solutions.add(newSolution);
solutionAccepted = true;
}
}
return solutionAccepted;
}
@Override
public String toString() {
return "[name=schrimpfAcceptanceFunction][alpha="+alpha+"][warmup=" + nOfRandomWalks + "]";
}
private double getThreshold(int iteration) {
double scheduleVariable = (double) iteration / (double) nOfTotalIterations;
// logger.debug("iter="+iteration+" totalIter="+nOfTotalIterations+" scheduling="+scheduleVariable);
double currentThreshold = initialThreshold * Math.exp(-Math.log(2) * scheduleVariable / alpha);
return currentThreshold;
}
@Override
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
reset();
logger.info("---------------------------------------------------------------------");
logger.info("prepare schrimpfAcceptanceFunction, i.e. determine initial threshold");
logger.info("start random-walk (see randomWalk.xml)");
double now = System.currentTimeMillis();
this.nOfTotalIterations = algorithm.getNuOfIterations();
/*
* randomWalk to determine standardDev
*/
final double[] results = new double[nOfRandomWalks];
URL resource = Resource.getAsURL("randomWalk.xml");
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
new AlgorithmConfigXmlReader(algorithmConfig).read(resource);
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.createAlgorithm(problem, algorithmConfig);
vra.setNuOfIterations(nOfRandomWalks);
vra.getAlgorithmListeners().addListener(new IterationEndsListener() {
@Override
public void informIterationEnds(int iteration, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
double result = Solutions.getBest(solutions).getCost();
// logger.info("result="+result);
results[iteration-1] = result;
}
});
vra.searchSolutions();
StandardDeviation dev = new StandardDeviation();
double standardDeviation = dev.evaluate(results);
initialThreshold = standardDeviation / 2;
logger.info("warmup done");
logger.info("total time: " + ((System.currentTimeMillis()-now)/1000.0) + "s");
logger.info("initial threshold: " + initialThreshold);
logger.info("---------------------------------------------------------------------");
}
private void reset() {
currentIteration = 0;
}
@Override
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
currentIteration = i;
}
}

View file

@ -14,18 +14,19 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms.acceptors;
package jsprit.core.algorithm.acceptor;
import java.util.Collection;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
public class AcceptNewIfBetterThanWorst implements SolutionAcceptor{
public class GreedyAcceptance implements SolutionAcceptor{
private final int solutionMemory;
public AcceptNewIfBetterThanWorst(int solutionMemory){
public GreedyAcceptance(int solutionMemory){
this.solutionMemory = solutionMemory;
}
@ -47,6 +48,12 @@ public class AcceptNewIfBetterThanWorst implements SolutionAcceptor{
if (worstSolution == null) worstSolution = s;
else if (s.getCost() > worstSolution.getCost()) worstSolution = s;
}
// if(newSolution.getRoutes().size() < worstSolution.getRoutes().size()){
// solutions.remove(worstSolution);
// solutions.add(newSolution);
// solutionAccepted = true;
// }
// else
if(newSolution.getCost() < worstSolution.getCost()){
solutions.remove(worstSolution);
solutions.add(newSolution);

View file

@ -0,0 +1,73 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.algorithm.acceptor;
import java.util.Collection;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
public class GreedyAcceptance_minVehFirst implements SolutionAcceptor{
private final int solutionMemory;
public GreedyAcceptance_minVehFirst(int solutionMemory){
this.solutionMemory = solutionMemory;
}
/**
* Accepts every solution if solution memory allows. If memory occupied, than accepts new solution only if better than the worst in memory.
* Consequently, the worst solution is removed from solutions, and the new solution added.
*
* <p>Note that this modifies Collection<VehicleRoutingProblemSolution> solutions.
*/
@Override
public boolean acceptSolution(Collection<VehicleRoutingProblemSolution> solutions, VehicleRoutingProblemSolution newSolution) {
boolean solutionAccepted = false;
if (solutions.size() < solutionMemory) {
solutions.add(newSolution);
solutionAccepted = true;
} else {
VehicleRoutingProblemSolution worstSolution = null;
for (VehicleRoutingProblemSolution s : solutions) {
if (worstSolution == null) worstSolution = s;
else if (s.getRoutes().size() > worstSolution.getRoutes().size()) worstSolution = s;
}
if(newSolution.getRoutes().size() < worstSolution.getRoutes().size()){
solutions.remove(worstSolution);
solutions.add(newSolution);
solutionAccepted = true;
}
else if(newSolution.getRoutes().size() == worstSolution.getRoutes().size() && newSolution.getCost() < worstSolution.getCost()){
solutions.remove(worstSolution);
solutions.add(newSolution);
solutionAccepted = true;
}
}
return solutionAccepted;
}
@Override
public String toString() {
return "[name=greedyAcceptance_minVehFirst]";
}
}

View file

@ -14,25 +14,26 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms.acceptors;
package jsprit.core.algorithm.acceptor;
import java.net.URL;
import java.util.Collection;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.io.AlgorithmConfig;
import jsprit.core.algorithm.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.algorithm.listener.IterationEndsListener;
import jsprit.core.algorithm.listener.IterationStartsListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.util.Resource;
import jsprit.core.util.Solutions;
import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
import org.apache.log4j.Logger;
import util.Resource;
import util.Solutions;
import algorithms.VehicleRoutingAlgorithms;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmStartsListener;
import basics.algo.IterationEndsListener;
import basics.algo.IterationStartsListener;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;

View file

@ -14,11 +14,12 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms.acceptors;
package jsprit.core.algorithm.acceptor;
import java.util.Collection;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
/**
* Acceptor that decides whether the newSolution is accepted or not.

View file

@ -14,15 +14,17 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.box;
import java.net.URL;
import util.Resource;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.io.AlgorithmConfig;
import jsprit.core.algorithm.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.util.Resource;
/**

View file

@ -14,15 +14,17 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.box;
import java.net.URL;
import util.Resource;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.io.AlgorithmConfig;
import jsprit.core.algorithm.io.AlgorithmConfigXmlReader;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.util.Resource;
/**

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.io;
package jsprit.core.algorithm.io;
import org.apache.commons.configuration.XMLConfiguration;

View file

@ -14,19 +14,20 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.io;
package jsprit.core.algorithm.io;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import jsprit.core.util.Resource;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import util.Resource;
public class AlgorithmConfigXmlReader {

View file

@ -14,28 +14,32 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.io;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.recreate.BestInsertionBuilder;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.state.StateManager;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.log4j.Logger;
import algorithms.HardConstraints.ConstraintManager;
import basics.VehicleRoutingProblem;
import basics.algo.InsertionListener;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
class InsertionFactory {
private static Logger log = Logger.getLogger(InsertionFactory.class);
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
boolean concurrentInsertion = false;
if(executorService != null) concurrentInsertion = true;
VehicleFleetManager vehicleFleetManager, StateManager routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
if(config.containsKey("[@name]")){
String insertionName = config.getString("[@name]");
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
@ -45,16 +49,17 @@ class InsertionFactory {
List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>();
CalculatorBuilder calcBuilder = new CalculatorBuilder(insertionListeners, algorithmListeners);
calcBuilder.setStates(routeStates);
calcBuilder.setVehicleRoutingProblem(vrp);
calcBuilder.setVehicleFleetManager(vehicleFleetManager);
calcBuilder.setConstraintManager(constraintManager);
BestInsertionBuilder iBuilder = new BestInsertionBuilder(vrp, vehicleFleetManager, routeStates, constraintManager);
if(executorService != null){
iBuilder.setConcurrentMode(executorService, nuOfThreads);
}
if(config.containsKey("level")){
String level = config.getString("level");
if(level.equals("local")){
calcBuilder.setLocalLevel();
iBuilder.setLocalLevel();
// calcBuilder.setLocalLevel();
}
else if(level.equals("route")){
int forwardLooking = 0;
@ -65,11 +70,12 @@ class InsertionFactory {
else log.warn("parameter route[@forwardLooking] is missing. by default it is 0 which equals to local level");
if(mem != null) memory = Integer.parseInt(mem);
else log.warn("parameter route[@memory] is missing. by default it is 1");
calcBuilder.setRouteLevel(forwardLooking, memory);
iBuilder.setRouteLevel(forwardLooking, memory);
// calcBuilder.setRouteLevel(forwardLooking, memory);
}
else throw new IllegalStateException("level " + level + " is not known. currently it only knows \"local\" or \"route\"");
}
else calcBuilder.setLocalLevel();
else iBuilder.setLocalLevel();
if(config.containsKey("considerFixedCosts") || config.containsKey("considerFixedCost")){
String val = config.getString("considerFixedCosts");
@ -80,35 +86,20 @@ class InsertionFactory {
if(weight == null) weight = config.getString("considerFixedCost[@weight]");
if(weight != null) fixedCostWeight = Double.parseDouble(weight);
else log.warn("parameter considerFixedCosts[@weight] is missing. by default, it is 0.5.");
calcBuilder.considerFixedCosts(fixedCostWeight);
iBuilder.considerFixedCosts(fixedCostWeight);
}
}
String timeSliceString = config.getString("experimental[@timeSlice]");
String neighbors = config.getString("experimental[@neighboringSlices]");
if(timeSliceString != null && neighbors != null){
calcBuilder.experimentalTimeScheduler(Double.parseDouble(timeSliceString),Integer.parseInt(neighbors));
iBuilder.experimentalTimeScheduler(Double.parseDouble(timeSliceString),Integer.parseInt(neighbors));
}
JobInsertionCalculator jic = calcBuilder.build();
if(insertionName.equals("bestInsertion")){
insertionStrategy = new BestInsertion(jic);
insertionStrategy = iBuilder.build();
}
// else if(insertionName.equals("regretInsertion")){
// insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
// }
// insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
// insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager));
// insertionStrategy.addListener(new VehicleSwitched(vehicleFleetManager));
// insertionStrategy.addListener(new UpdateLoadAtRouteLevel(routeStates));
// insertionStrategy.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
else throw new IllegalStateException("currently only 'bestInsertion' is supported");
for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l);
// insertionStrategy.addListener(new FindCheaperVehicle(
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));
algorithmListeners.addAll(algoListeners);

View file

@ -14,9 +14,10 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.io;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
@ -26,47 +27,68 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import jsprit.core.algorithm.InsertionInitialSolutionFactory;
import jsprit.core.algorithm.RemoveEmptyVehicles;
import jsprit.core.algorithm.ResetAndIniFleetManager;
import jsprit.core.algorithm.SearchStrategy;
import jsprit.core.algorithm.SearchStrategy.DiscoveredSolution;
import jsprit.core.algorithm.SearchStrategyManager;
import jsprit.core.algorithm.SearchStrategyModule;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.algorithm.acceptor.AcceptNewRemoveFirst;
import jsprit.core.algorithm.acceptor.ExperimentalSchrimpfAcceptance;
import jsprit.core.algorithm.acceptor.GreedyAcceptance;
import jsprit.core.algorithm.acceptor.GreedyAcceptance_minVehFirst;
import jsprit.core.algorithm.acceptor.SchrimpfAcceptance;
import jsprit.core.algorithm.acceptor.SolutionAcceptor;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.RuinStrategyKey;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.SelectorKey;
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.StrategyModuleKey;
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.Priority;
import jsprit.core.algorithm.module.RuinAndRecreateModule;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.algorithm.recreate.VehicleSwitched;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.ruin.RadialRuinStrategyFactory;
import jsprit.core.algorithm.ruin.RandomRuinStrategyFactory;
import jsprit.core.algorithm.ruin.RuinStrategy;
import jsprit.core.algorithm.ruin.distance.AvgServiceAndShipmentDistance;
import jsprit.core.algorithm.ruin.distance.JobDistance;
import jsprit.core.algorithm.selector.SelectBest;
import jsprit.core.algorithm.selector.SelectRandomly;
import jsprit.core.algorithm.selector.SolutionSelector;
import jsprit.core.algorithm.state.StateManager;
import jsprit.core.algorithm.state.UpdateActivityTimes;
import jsprit.core.algorithm.state.UpdateVariableCosts;
import jsprit.core.algorithm.termination.IterationWithoutImprovementTermination;
import jsprit.core.algorithm.termination.PrematureAlgorithmTermination;
import jsprit.core.algorithm.termination.TimeTermination;
import jsprit.core.algorithm.termination.VariationCoefficientTermination;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem.FleetSize;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.solution.SolutionCostCalculator;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.state.StateFactory;
import jsprit.core.problem.vehicle.FiniteFleetManagerFactory;
import jsprit.core.problem.vehicle.InfiniteFleetManagerFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import jsprit.core.util.SolutionVerifier;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;
import algorithms.HardConstraints.ConstraintManager;
import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.RuinStrategyKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.SelectorKey;
import algorithms.VehicleRoutingAlgorithms.TypedMap.StrategyModuleKey;
import algorithms.acceptors.AcceptNewIfBetterThanWorst;
import algorithms.acceptors.AcceptNewRemoveFirst;
import algorithms.acceptors.SchrimpfAcceptance;
import algorithms.acceptors.SolutionAcceptor;
import algorithms.selectors.SelectBest;
import algorithms.selectors.SelectRandomly;
import algorithms.selectors.SolutionSelector;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblem.Constraint;
import basics.VehicleRoutingProblem.FleetSize;
import basics.VehicleRoutingProblemSolution;
import basics.algo.AlgorithmStartsListener;
import basics.algo.InsertionListener;
import basics.algo.IterationWithoutImprovementBreaker;
import basics.algo.PrematureAlgorithmBreaker;
import basics.algo.SearchStrategy;
import basics.algo.SearchStrategy.DiscoveredSolution;
import basics.algo.SearchStrategyManager;
import basics.algo.SearchStrategyModule;
import basics.algo.SolutionCostCalculator;
import basics.algo.TimeBreaker;
import basics.algo.VariationCoefficientBreaker;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import basics.algo.VehicleRoutingAlgorithmListeners.Priority;
import basics.io.AlgorithmConfig;
import basics.io.AlgorithmConfigXmlReader;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
@ -370,12 +392,12 @@ public class VehicleRoutingAlgorithms {
* @return {@link VehicleRoutingAlgorithm}
*/
public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp, final AlgorithmConfig algorithmConfig){
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),null,0);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0);
}
@Deprecated
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final XMLConfiguration config){
return createAlgo(vrp,config,null,0);
return createAlgo(vrp,config,0);
}
/**
@ -389,7 +411,7 @@ public class VehicleRoutingAlgorithms {
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
xmlReader.read(configURL);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),null,0);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0);
}
/**
@ -403,26 +425,18 @@ public class VehicleRoutingAlgorithms {
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
xmlReader.read(configFileName);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),null, 0);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0);
}
/**
* Read and creates {@link VehicleRoutingAlgorithm} from config-file.
*
* @param vrp
* @param configFileName
* @param nuOfThreads TODO
* @param {@link ExecutorService}
* @return {@link VehicleRoutingAlgorithm}
*/
private static VehicleRoutingAlgorithm readAndCreateConcurrentAlgorithm(final VehicleRoutingProblem vrp, final String configFileName, final ExecutorService executorService, int nuOfThreads){
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(VehicleRoutingProblem vrp, int nThreads, String configFileName) {
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
xmlReader.read(configFileName);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(), executorService, nuOfThreads);
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),nThreads);
}
private static VehicleRoutingAlgorithm createAlgo(final VehicleRoutingProblem vrp, XMLConfiguration config, ExecutorService executorService, int nuOfThreads){
private static VehicleRoutingAlgorithm createAlgo(final VehicleRoutingProblem vrp, XMLConfiguration config, int nuOfThreads){
// map to store constructed modules
TypedMap definedClasses = new TypedMap();
@ -433,27 +447,54 @@ public class VehicleRoutingAlgorithms {
// insertion listeners
List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
//threading
final ExecutorService executorService;
if(nuOfThreads > 0){
log.info("setup executor-service with " + nuOfThreads + " threads");
executorService = Executors.newFixedThreadPool(nuOfThreads);
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new AlgorithmEndsListener() {
@Override
public void informAlgorithmEnds(VehicleRoutingProblem problem,Collection<VehicleRoutingProblemSolution> solutions) {
log.info("shutdown executor-service");
executorService.shutdown();
}
}));
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread arg0, Throwable arg1) {
System.err.println(arg1.toString());
System.exit(0);
}
});
Runtime.getRuntime().addShutdownHook(new Thread(){
public void run(){
if(!executorService.isShutdown()){
System.err.println("shutdowHook shuts down executorService");
executorService.shutdown();
}
}
});
}
else executorService = null;
//create fleetmanager
final VehicleFleetManager vehicleFleetManager = createFleetManager(vrp);
//create state-manager
final StateManagerImpl stateManager = new StateManagerImpl();
final StateManager stateManager = new StateManager(vrp);
stateManager.updateLoadStates();
stateManager.updateTimeWindowStates();
/*
* define constraints
*/
//constraint manager
ConstraintManager constraintManager = new ConstraintManager();
constraintManager.addConstraint(new HardConstraints.HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
if(vrp.getProblemConstraints().contains(Constraint.DELIVERIES_FIRST)){
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager));
}
else{
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryActivityLevelConstraint(stateManager));
}
constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager));
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
constraintManager.addTimeWindowConstraint();
constraintManager.addLoadConstraint();
//construct initial solution creator
AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,constraintManager);
@ -490,32 +531,26 @@ public class VehicleRoutingAlgorithms {
/*
* define stateUpdates
*/
// UpdateLoads loadUpdater = new UpdateLoads(stateManager);
// stateManager.addListener(loadUpdater);
// stateManager.addActivityVisitor(loadUpdater);
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts()));
stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
//reset stateManager
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new StateUpdates.ResetStateManager(stateManager)));
//update states
// metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateStates(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged routeChangedListener = new StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged(vrp.getTransportCosts());
// stateManager.addActivityVisitor(new UpdateOccuredDeliveries(stateManager));
// stateManager.addActivityVisitor(new TimeWindowUpdater(stateManager, vrp.getTransportCosts()));
// stateManager.addActivityVisitor(new UpdateFuturePickups(stateManager));
routeChangedListener.addInsertionStartsListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
routeChangedListener.addJobInsertedListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(stateManager);
metaAlgorithm.getAlgorithmListeners().addListener(stateManager);
routeChangedListener.addVisitor(new StateUpdates.UpdateActivityTimes(vrp.getTransportCosts()));
routeChangedListener.addVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager));
routeChangedListener.addVisitor(new StateUpdates.UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
routeChangedListener.addVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager));
routeChangedListener.addVisitor(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts()));
routeChangedListener.addVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(routeChangedListener);
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(vehicleFleetManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new ResetAndIniFleetManager(vehicleFleetManager));
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager));
//define prematureBreak
PrematureAlgorithmBreaker prematureAlgoBreaker = getPrematureBreaker(config,algorithmListeners);
metaAlgorithm.setPrematureAlgorithmBreaker(prematureAlgoBreaker);
PrematureAlgorithmTermination prematureAlgoBreaker = getPrematureBreaker(config,algorithmListeners);
metaAlgorithm.setPrematureAlgorithmTermination(prematureAlgoBreaker);
//misc
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
@ -526,16 +561,16 @@ public class VehicleRoutingAlgorithms {
return metaAlgorithm;
}
private static SolutionCostCalculator getCostCalculator(final StateManagerImpl stateManager) {
private static SolutionCostCalculator getCostCalculator(final StateManager stateManager) {
SolutionCostCalculator calc = new SolutionCostCalculator() {
@Override
public void calculateCosts(VehicleRoutingProblemSolution solution) {
public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.0;
for(VehicleRoute route : solution.getRoutes()){
costs += stateManager.getRouteState(route, StateTypes.COSTS).toDouble() + getFixedCosts(route.getVehicle());
costs += stateManager.getRouteState(route, StateFactory.COSTS).toDouble() + getFixedCosts(route.getVehicle());
}
solution.setCost(costs);
return costs;
}
private double getFixedCosts(Vehicle vehicle) {
@ -549,21 +584,21 @@ public class VehicleRoutingAlgorithms {
private static VehicleFleetManager createFleetManager(final VehicleRoutingProblem vrp) {
if(vrp.getFleetSize().equals(FleetSize.INFINITE)){
return new InfiniteVehicles(vrp.getVehicles());
return new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
}
else if(vrp.getFleetSize().equals(FleetSize.FINITE)){
return new VehicleFleetManagerImpl(vrp.getVehicles());
return new FiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
}
throw new IllegalStateException("fleet size can only be infinite or finite. " +
"makes sure your config file contains one of these options");
}
private static PrematureAlgorithmBreaker getPrematureBreaker(XMLConfiguration config, Set<PrioritizedVRAListener> algorithmListeners) {
private static PrematureAlgorithmTermination getPrematureBreaker(XMLConfiguration config, Set<PrioritizedVRAListener> algorithmListeners) {
String basedOn = config.getString("prematureBreak[@basedOn]");
if(basedOn == null){
log.info("set default prematureBreak, i.e. no premature break at all.");
return new PrematureAlgorithmBreaker() {
return new PrematureAlgorithmTermination() {
@Override
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
@ -576,14 +611,14 @@ public class VehicleRoutingAlgorithms {
String iter = config.getString("prematureBreak.iterations");
if(iter == null) throw new IllegalStateException("prematureBreak.iterations is missing");
int iterations = Integer.valueOf(iter);
return new IterationWithoutImprovementBreaker(iterations);
return new IterationWithoutImprovementTermination(iterations);
}
if(basedOn.equals("time")){
log.info("set prematureBreak based on time");
String timeString = config.getString("prematureBreak.time");
if(timeString == null) throw new IllegalStateException("prematureBreak.time is missing");
double time = Double.valueOf(timeString);
TimeBreaker timeBreaker = new TimeBreaker(time);
TimeTermination timeBreaker = new TimeTermination(time);
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, timeBreaker));
return timeBreaker;
}
@ -595,7 +630,7 @@ public class VehicleRoutingAlgorithms {
if(iterationsString == null) throw new IllegalStateException("prematureBreak.iterations is missing");
double threshold = Double.valueOf(thresholdString);
int iterations = Integer.valueOf(iterationsString);
VariationCoefficientBreaker variationCoefficientBreaker = new VariationCoefficientBreaker(iterations, threshold);
VariationCoefficientTermination variationCoefficientBreaker = new VariationCoefficientTermination(iterations, threshold);
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, variationCoefficientBreaker));
return variationCoefficientBreaker;
}
@ -626,7 +661,7 @@ public class VehicleRoutingAlgorithms {
metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners);
}
private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManager routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
if(modConfigs == null) return null;
if(modConfigs.isEmpty()) return null;
@ -651,9 +686,11 @@ public class VehicleRoutingAlgorithms {
@Override
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy, getCostCalculator(routeStates));
createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false);
VehicleRoutingProblemSolution vrpSol = createInitialSolution.createInitialSolution(vrp);
InsertionInitialSolutionFactory insertionInitialSolutionFactory = new InsertionInitialSolutionFactory(finalInsertionStrategy, getCostCalculator(routeStates));
// CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy, getCostCalculator(routeStates));
//
// createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false);
VehicleRoutingProblemSolution vrpSol = insertionInitialSolutionFactory.createSolution(vrp);
solutions.add(vrpSol);
}
};
@ -698,7 +735,7 @@ public class VehicleRoutingAlgorithms {
SolutionAcceptor definedAcceptor = typedMap.get(acceptorKey);
if(definedAcceptor != null) return definedAcceptor;
if(acceptorName.equals("acceptNewRemoveWorst")){
AcceptNewIfBetterThanWorst acceptor = new AcceptNewIfBetterThanWorst(solutionMemory);
GreedyAcceptance acceptor = new GreedyAcceptance(solutionMemory);
typedMap.put(acceptorKey, acceptor);
return acceptor;
}
@ -707,6 +744,16 @@ public class VehicleRoutingAlgorithms {
typedMap.put(acceptorKey, acceptor);
return acceptor;
}
if(acceptorName.equals("greedyAcceptance")){
GreedyAcceptance acceptor = new GreedyAcceptance(solutionMemory);
typedMap.put(acceptorKey, acceptor);
return acceptor;
}
if(acceptorName.equals("greedyAcceptance_minVehFirst")){
GreedyAcceptance_minVehFirst acceptor = new GreedyAcceptance_minVehFirst(solutionMemory);
typedMap.put(acceptorKey, acceptor);
return acceptor;
}
if(acceptorName.equals("schrimpfAcceptance")){
int iterOfSchrimpf = strategyConfig.getInt("acceptor.warmup");
double alpha = strategyConfig.getDouble("acceptor.alpha");
@ -715,13 +762,21 @@ public class VehicleRoutingAlgorithms {
typedMap.put(acceptorKey, schrimpf);
return schrimpf;
}
if(acceptorName.equals("experimentalSchrimpfAcceptance")){
int iterOfSchrimpf = strategyConfig.getInt("acceptor.warmup");
double alpha = strategyConfig.getDouble("acceptor.alpha");
ExperimentalSchrimpfAcceptance schrimpf = new ExperimentalSchrimpfAcceptance(solutionMemory, alpha, iterOfSchrimpf);
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, schrimpf));
typedMap.put(acceptorKey, schrimpf);
return schrimpf;
}
else{
throw new IllegalStateException("solution acceptor " + acceptorName + " is not known");
}
}
private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
final StateManagerImpl routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
final StateManager routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
String moduleName = moduleConfig.getString("[@name]");
if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
String moduleId = moduleConfig.getString("[@id]");
@ -746,15 +801,15 @@ public class VehicleRoutingAlgorithms {
}
else if(ruin_name.equals("radialRuin")){
String ruin_distance = moduleConfig.getString("ruin.distance");
JobDistance jobDistance;
if(ruin_distance == null) jobDistance = new JobDistanceAvgCosts(vrp.getTransportCosts());
else {
if(ruin_distance.equals("euclidean")){
jobDistance = new EuclideanServiceDistance();
}
else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
+ "default is used or use 'euclidean'");
}
JobDistance jobDistance = new AvgServiceAndShipmentDistance(vrp.getTransportCosts());
// if(ruin_distance == null) jobDistance
// else {
// if(ruin_distance.equals("euclidean")){
// jobDistance = new EuclideanServiceDistance();
// }
// else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
// + "default is used or use 'euclidean'");
// }
ruin = getRadialRuin(vrp, routeStates, definedClasses, ruinKey, shareToRuin, jobDistance);
}
else throw new IllegalStateException("ruin[@name] " + ruin_name + " is not known. Use either randomRuin or radialRuin.");
@ -779,40 +834,40 @@ public class VehicleRoutingAlgorithms {
return rrModule;
}
if(moduleName.equals("gendreau")){
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 RuinRadial(vrp, 0.3, new JobDistanceAvgCosts(vrp.getTransportCosts()));
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);
gendreau.setShareOfJobsToRuin(share);
gendreau.setNuOfIterations(iterations);
gendreau.setFleetManager(vehicleFleetManager);
definedClasses.put(strategyModuleKey, gendreau);
return 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 +
"\n\tcheck config whether the correct names are used" +
@ -823,30 +878,32 @@ public class VehicleRoutingAlgorithms {
"\n\tgendreauPostOpt");
}
private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManagerImpl 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) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
ruin = new RuinRadial(vrp, shareToRuin, jobDistance);
ruin = new RadialRuinStrategyFactory(shareToRuin, jobDistance).createStrategy(vrp);
definedClasses.put(stratKey, ruin);
}
return ruin;
}
private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManagerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) {
private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) {
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
RuinStrategy ruin = definedClasses.get(stratKey);
if(ruin == null){
ruin = new RuinRandom(vrp, shareToRuin);
ruin = new RandomRuinStrategyFactory(shareToRuin).createStrategy(vrp);
definedClasses.put(stratKey, ruin);
}
return ruin;
}
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManager routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) {
InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads, constraintManager);
return insertion;
}
}

View file

@ -14,12 +14,13 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.listener;
import java.util.Collection;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -14,13 +14,14 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.listener;
import java.util.Collection;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -14,12 +14,13 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.listener;
import java.util.Collection;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -14,12 +14,13 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.listener;
import java.util.Collection;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.listener;
public interface SearchStrategyListener extends VehicleRoutingAlgorithmListener{

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.listener;
public interface SearchStrategyModuleListener extends VehicleRoutingAlgorithmListener{

View file

@ -14,12 +14,13 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.listener;
import java.util.Collection;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.listener;
public interface VehicleRoutingAlgorithmListener {

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.listener;
import java.util.ArrayList;
import java.util.Collection;
@ -23,9 +23,10 @@ import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import basics.VehicleRoutingAlgorithm;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;

View file

@ -0,0 +1,224 @@
///*******************************************************************************
// * Copyright (C) 2013 Stefan Schroeder
// *
// * This library is free software; you can redistribute it and/or
// * modify it under the terms of the GNU Lesser General Public
// * License as published by the Free Software Foundation; either
// * version 3.0 of the License, or (at your option) any later version.
// *
// * This library is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// * Lesser General Public License for more details.
// *
// * You should have received a copy of the GNU Lesser General Public
// * License along with this library. If not, see <http://www.gnu.org/licenses/>.
// ******************************************************************************/
//package jsprit.core.algorithm.module;
//
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.Collection;
//import java.util.Collections;
//import java.util.HashSet;
//import java.util.List;
//import java.util.Random;
//import java.util.Set;
//
//import jsprit.core.algorithm.SearchStrategyModule;
//import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
//import jsprit.core.algorithm.recreate.InsertionStrategy;
//import jsprit.core.algorithm.recreate.listener.InsertionListener;
//import jsprit.core.algorithm.recreate.listener.InsertionListeners;
//import jsprit.core.algorithm.ruin.RuinStrategy;
//import jsprit.core.algorithm.ruin.listener.RuinListener;
//import jsprit.core.problem.Job;
//import jsprit.core.problem.VehicleRoutingProblem;
//import jsprit.core.problem.VehicleRoutingProblemSolution;
//import jsprit.core.problem.route.TourActivity;
//import jsprit.core.problem.route.TourActivity.JobActivity;
//import jsprit.core.problem.route.VehicleFleetManager;
//import jsprit.core.problem.route.VehicleRoute;
//import jsprit.core.util.RandomNumberGeneration;
//
//import org.apache.log4j.Logger;
//
//
//final class Gendreau implements SearchStrategyModule{
//
// private final static Logger log = Logger.getLogger(Gendreau.class);
//
// private final static String NAME = "gendreauPostOpt";
//
// private final RuinStrategy ruin;
//
// private final VehicleRoutingProblem vrp;
//
// private final InsertionStrategy insertionStrategy;
//
// private VehicleFleetManager fleetManager;
//
// private Random random = RandomNumberGeneration.getRandom();
//
// private int nOfIterations = 10;
//
// private double shareOfJobsToRuin = 0.15;
//
// public void setShareOfJobsToRuin(double shareOfJobsToRuin) {
// this.shareOfJobsToRuin = shareOfJobsToRuin;
// }
//
// public Gendreau(VehicleRoutingProblem vrp, RuinStrategy ruin, InsertionStrategy insertionStrategy, VehicleFleetManager vehicleFleetManager) {
// super();
// InsertionListeners insertionListeners = new InsertionListeners();
// insertionListeners.addAllListeners(insertionStrategy.getListeners());
// new Inserter(insertionListeners);
// this.ruin = ruin;
// this.vrp = vrp;
// this.insertionStrategy = insertionStrategy;
// this.fleetManager = vehicleFleetManager;
// }
//
// @Override
// public String toString() {
// return "[name=gendreau][iterations="+nOfIterations+"][share2ruin="+shareOfJobsToRuin+"]";
// }
//
// public void setRandom(Random random) {
// this.random = random;
// }
//
//
// public void setNuOfIterations(int nOfIterations) {
// this.nOfIterations = nOfIterations;
// }
//
//// public void setFleetManager(VehicleFleetManager vehicleFleetManager) {
//// this.fleetManager = vehicleFleetManager;
////
//// }
//
// @Override
// public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
//// log.info("run gendreau postopt");
// VehicleRoutingProblemSolution bestSolution = vrpSolution;
// int itersWithoutImprovement = 0;
//
// for(int i=0;i<nOfIterations;i++){
// List<VehicleRoute> copiedRoutes = copyRoutes(bestSolution.getRoutes());
// iniFleet(copiedRoutes);
//
// VehicleRoute route2split = pickRouteThatHasAtLeastTwoJobs(copiedRoutes);
// if(route2split == null) continue;
// List<Job> jobsInRoute = getJobs(route2split);
// Set<Job> unassignedJobs = new HashSet<Job>();
// unassignedJobs.addAll(jobsInRoute);
// copiedRoutes.remove(route2split);
//
// Collections.shuffle(jobsInRoute,random);
// Job targetJob = jobsInRoute.get(0);
// int nOfJobs2BeRemovedAdditionally = (int) (shareOfJobsToRuin*(double)vrp.getJobs().size());
// Collection<Job> unassignedJobsList = ruin.ruin(copiedRoutes, targetJob, nOfJobs2BeRemovedAdditionally);
// unassignedJobs.addAll(unassignedJobsList);
//
// VehicleRoute emptyRoute1 = VehicleRoute.emptyRoute();
// copiedRoutes.add(emptyRoute1);
// insertionStrategy.insertJobs(Arrays.asList(emptyRoute1), Arrays.asList(targetJob));
//
// unassignedJobs.remove(targetJob);
//
// VehicleRoute emptyRoute2 = VehicleRoute.emptyRoute();
// copiedRoutes.add(emptyRoute2);
// Job job2 = jobsInRoute.get(1);
// insertionStrategy.insertJobs(Arrays.asList(emptyRoute2), Arrays.asList(job2));
//
// unassignedJobs.remove(job2);
//
// insertionStrategy.insertJobs(copiedRoutes, unassignedJobs);
// double cost = getCost(copiedRoutes);
//
// if(cost < bestSolution.getCost()){
//// log.info("BING - new: " + cost + " old: " + bestSolution.getCost());
// bestSolution = new VehicleRoutingProblemSolution(copiedRoutes, cost);
// itersWithoutImprovement=0;
// }
// else{
// itersWithoutImprovement++;
// if(itersWithoutImprovement > 200){
//// log.info("BREAK i="+i);
// break;
// }
// }
// }
// return bestSolution;
// }
//
// private List<VehicleRoute> copyRoutes(Collection<VehicleRoute> routes) {
// List<VehicleRoute> routeList = new ArrayList<VehicleRoute>();
// for(VehicleRoute r : routes){
// routeList.add(VehicleRoute.copyOf(r));
// }
// return routeList;
// }
//
// private void iniFleet(Collection<VehicleRoute> routes) {
// fleetManager.unlockAll();
// for(VehicleRoute route : routes){
// if(!route.isEmpty()){
// fleetManager.lock(route.getVehicle());
// }
// }
// }
//
// private double getCost(Collection<VehicleRoute> routes) {
// double c = 0.0;
// for(VehicleRoute r : routes){
// c+=r.getCost();
// }
// return c;
// }
//
// private List<Job> getJobs(VehicleRoute route2split) {
// Set<Job> jobs = new HashSet<Job>();
// for(TourActivity act : route2split.getTourActivities().getActivities()){
// if(act instanceof JobActivity){
// jobs.add(((JobActivity) act).getJob());
// }
// }
// return new ArrayList<Job>(jobs);
// }
//
// private VehicleRoute pickRouteThatHasAtLeastTwoJobs(Collection<VehicleRoute> routeList) {
// List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
// for(VehicleRoute r : routeList){
// if(getJobs(r).size() > 1){
// routes.add(r);
// }
// }
// if(routes.isEmpty()) return null;
// Collections.shuffle(routes,random);
// return routes.get(0);
// }
//
// @Override
// public String getName() {
// return NAME;
// }
//
// @Override
// public void addModuleListener(SearchStrategyModuleListener moduleListener) {
// if(moduleListener instanceof InsertionListener){
// InsertionListener iListener = (InsertionListener) moduleListener;
// if(!insertionStrategy.getListeners().contains(iListener)){
// insertionStrategy.addListener(iListener);
// }
// }
// if(moduleListener instanceof RuinListener){
// RuinListener rListener = (RuinListener) moduleListener;
// if(!ruin.getListeners().contains(rListener)){
// ruin.addListener(rListener);
// }
// }
//
// }
//}

View file

@ -14,18 +14,21 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.module;
import java.util.Collection;
import algorithms.RuinStrategy.RuinListener;
import basics.Job;
import basics.VehicleRoutingProblemSolution;
import basics.algo.InsertionListener;
import basics.algo.SearchStrategyModule;
import basics.algo.SearchStrategyModuleListener;
import jsprit.core.algorithm.SearchStrategyModule;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.algorithm.recreate.InsertionStrategy;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.ruin.RuinStrategy;
import jsprit.core.algorithm.ruin.listener.RuinListener;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
class RuinAndRecreateModule implements SearchStrategyModule{
public class RuinAndRecreateModule implements SearchStrategyModule{
private InsertionStrategy insertion;
@ -44,9 +47,8 @@ class RuinAndRecreateModule implements SearchStrategyModule{
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs);
// double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
// vrpSolution.setCost(totalCost);
return vrpSolution;
}
@Override

View file

@ -18,13 +18,14 @@
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import basics.route.TourActivity;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.activity.TourActivity;
interface ActivityInsertionCostsCalculator {
public interface ActivityInsertionCostsCalculator {
class ActivityInsertionCosts {
public class ActivityInsertionCosts {
private double additionalCosts;
private double additionalTime;
@ -50,6 +51,6 @@ interface ActivityInsertionCostsCalculator {
}
ActivityInsertionCosts calculate(InsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct);
public ActivityInsertionCosts getCosts(JobInsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct);
}

View file

@ -14,16 +14,17 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import java.util.Iterator;
import java.util.List;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.Driver;
import basics.route.TourActivity;
import basics.route.Vehicle;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
final class AuxilliaryCostCalculator {

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.Collection;
@ -22,15 +22,17 @@ import java.util.Collections;
import java.util.List;
import java.util.Random;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.recreate.listener.InsertionListeners;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.util.RandomNumberGeneration;
import org.apache.log4j.Logger;
import util.RandomNumberGeneration;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.algo.InsertionListener;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
@ -42,6 +44,28 @@ import basics.route.VehicleRoute;
final class BestInsertion implements InsertionStrategy{
class Insertion {
private final VehicleRoute route;
private final InsertionData insertionData;
public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) {
super();
this.route = vehicleRoute;
this.insertionData = insertionData;
}
public VehicleRoute getRoute() {
return route;
}
public InsertionData getInsertionData() {
return insertionData;
}
}
private static Logger logger = Logger.getLogger(BestInsertion.class);
private Random random = RandomNumberGeneration.getRandom();
@ -56,7 +80,7 @@ final class BestInsertion implements InsertionStrategy{
private Inserter inserter;
private JobInsertionCalculator bestInsertionCostCalculator;
private JobInsertionCostsCalculator bestInsertionCostCalculator;
private boolean minVehiclesFirst = false;
@ -64,7 +88,7 @@ final class BestInsertion implements InsertionStrategy{
this.random = random;
}
public BestInsertion(JobInsertionCalculator jobInsertionCalculator) {
public BestInsertion(JobInsertionCostsCalculator jobInsertionCalculator) {
super();
this.insertionsListeners = new InsertionListeners();
inserter = new Inserter(insertionsListeners);
@ -86,7 +110,7 @@ final class BestInsertion implements InsertionStrategy{
Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE;
for(VehicleRoute vehicleRoute : vehicleRoutes){
InsertionData iData = bestInsertionCostCalculator.calculate(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(iData instanceof NoInsertionFound) {
continue;
}
@ -97,7 +121,7 @@ final class BestInsertion implements InsertionStrategy{
}
if(!minVehiclesFirst){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
InsertionData newIData = bestInsertionCostCalculator.calculate(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(newIData.getInsertionCost() < bestInsertionCost){
bestInsertion = new Insertion(newRoute,newIData);
bestInsertionCost = newIData.getInsertionCost();
@ -106,7 +130,7 @@ final class BestInsertion implements InsertionStrategy{
}
if(bestInsertion == null){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
InsertionData bestI = bestInsertionCostCalculator.calculate(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
InsertionData bestI = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
if(bestI instanceof InsertionData.NoInsertionFound){
throw new IllegalStateException(getErrorMsg(unassignedJob));
}
@ -115,9 +139,8 @@ final class BestInsertion implements InsertionStrategy{
vehicleRoutes.add(newRoute);
}
}
// logger.info("insert " + unassignedJob + " pickup@" + bestInsertion.getInsertionData().getPickupInsertionIndex() + " delivery@" + bestInsertion.getInsertionData().getDeliveryInsertionIndex());
inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
}
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
}

View file

@ -0,0 +1,137 @@
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.state.StateManager;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.vehicle.VehicleFleetManager;
public class BestInsertionBuilder {
private VehicleRoutingProblem vrp;
private StateManager stateManager;
private boolean local = true;
private ConstraintManager constraintManager;
private VehicleFleetManager fleetManager;
private double weightOfFixedCosts;
private boolean considerFixedCosts = false;
private ActivityInsertionCostsCalculator actInsertionCostsCalculator = null;
private int forwaredLooking;
private int memory;
private ExecutorService executor;
private int nuOfThreads;
private double timeSlice;
private int nNeighbors;
private boolean timeScheduling=false;
public BestInsertionBuilder(VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManager stateManager, ConstraintManager constraintManager) {
super();
this.vrp = vrp;
this.stateManager = stateManager;
this.constraintManager = constraintManager;
this.fleetManager = vehicleFleetManager;
}
public BestInsertionBuilder setRouteLevel(int forwardLooking, int memory){
local = false;
this.forwaredLooking = forwardLooking;
this.memory = memory;
return this;
};
public BestInsertionBuilder setLocalLevel(){
local = true;
return this;
};
public BestInsertionBuilder considerFixedCosts(double weightOfFixedCosts){
this.weightOfFixedCosts = weightOfFixedCosts;
this.considerFixedCosts = true;
return this;
}
public BestInsertionBuilder setActivityInsertionCostCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){
this.actInsertionCostsCalculator = activityInsertionCostsCalculator;
return this;
};
public BestInsertionBuilder setConcurrentMode(ExecutorService executor, int nuOfThreads){
this.executor = executor;
this.nuOfThreads = nuOfThreads;
return this;
}
public InsertionStrategy build() {
List<InsertionListener> iListeners = new ArrayList<InsertionListener>();
List<PrioritizedVRAListener> algorithmListeners = new ArrayList<PrioritizedVRAListener>();
CalculatorBuilder calcBuilder = new CalculatorBuilder(iListeners, algorithmListeners);
if(local){
calcBuilder.setLocalLevel();
}
else {
calcBuilder.setRouteLevel(forwaredLooking, memory);
}
calcBuilder.setConstraintManager(constraintManager);
calcBuilder.setStates(stateManager);
calcBuilder.setVehicleRoutingProblem(vrp);
calcBuilder.setVehicleFleetManager(fleetManager);
calcBuilder.setActivityInsertionCostsCalculator(actInsertionCostsCalculator);
if(considerFixedCosts) {
calcBuilder.considerFixedCosts(weightOfFixedCosts);
}
if(timeScheduling){
calcBuilder.experimentalTimeScheduler(timeSlice, nNeighbors);
}
JobInsertionCostsCalculator jobInsertions = calcBuilder.build();
InsertionStrategy bestInsertion;
if(executor == null){
bestInsertion = new BestInsertion(jobInsertions);
}
else{
bestInsertion = new BestInsertionConcurrent(jobInsertions,executor,nuOfThreads);
}
for(InsertionListener l : iListeners) bestInsertion.addListener(l);
return bestInsertion;
}
/**
* @deprecated this is experimental and can disappear.
* @param parseDouble
* @param parseInt
*/
@Deprecated
public void experimentalTimeScheduler(double timeSlice, int nNeighbors) {
this.timeSlice=timeSlice;
this.nNeighbors=nNeighbors;
timeScheduling=true;
}
}

View file

@ -0,0 +1,266 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.algorithm.recreate.listener.InsertionListeners;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.util.RandomNumberGeneration;
import org.apache.log4j.Logger;
/**
*
* @author stefan schroeder
*
*/
final class BestInsertionConcurrent implements InsertionStrategy{
static class Batch {
List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
}
class Insertion {
private final VehicleRoute route;
private final InsertionData insertionData;
public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) {
super();
this.route = vehicleRoute;
this.insertionData = insertionData;
}
public VehicleRoute getRoute() {
return route;
}
public InsertionData getInsertionData() {
return insertionData;
}
}
private static Logger logger = Logger.getLogger(BestInsertionConcurrent.class);
private Random random = RandomNumberGeneration.getRandom();
private final static double NO_NEW_DEPARTURE_TIME_YET = -12345.12345;
private final static Vehicle NO_NEW_VEHICLE_YET = null;
private final static Driver NO_NEW_DRIVER_YET = null;
private InsertionListeners insertionsListeners;
private Inserter inserter;
private JobInsertionCostsCalculator bestInsertionCostCalculator;
private boolean minVehiclesFirst = false;
private int nuOfBatches;
private ExecutorService executor;
private ExecutorCompletionService<Insertion> completionService;
public void setRandom(Random random) {
this.random = random;
}
public BestInsertionConcurrent(JobInsertionCostsCalculator jobInsertionCalculator, ExecutorService executorService, int nuOfBatches) {
super();
this.insertionsListeners = new InsertionListeners();
this.executor = executorService;
this.nuOfBatches = nuOfBatches;
inserter = new Inserter(insertionsListeners);
bestInsertionCostCalculator = jobInsertionCalculator;
completionService = new ExecutorCompletionService<Insertion>(executor);
logger.info("initialise " + this);
}
@Override
public String toString() {
return "[name=bestInsertion]";
}
@Override
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs);
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
Collections.shuffle(unassignedJobList, random);
List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
for(final Job unassignedJob : unassignedJobList){
Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE;
for(final Batch batch : batches){
completionService.submit(new Callable<Insertion>() {
@Override
public Insertion call() throws Exception {
return getBestInsertion(batch,unassignedJob);
}
});
}
try{
for(int i=0;i<batches.size();i++){
Future<Insertion> futureIData = completionService.take();
Insertion insertion = futureIData.get();
if(insertion == null) continue;
if(insertion.getInsertionData().getInsertionCost() < bestInsertionCost){
bestInsertion = insertion;
bestInsertionCost = insertion.getInsertionData().getInsertionCost();
}
}
}
catch(InterruptedException e){
Thread.currentThread().interrupt();
}
catch (ExecutionException e) {
e.printStackTrace();
logger.error(e.getCause().toString());
System.exit(1);
}
if(!minVehiclesFirst){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(newIData.getInsertionCost() < bestInsertionCost){
bestInsertion = new Insertion(newRoute,newIData);
bestInsertionCost = newIData.getInsertionCost();
vehicleRoutes.add(newRoute);
batches.get(random.nextInt(batches.size())).routes.add(newRoute);
}
}
if(bestInsertion == null){
VehicleRoute newRoute = VehicleRoute.emptyRoute();
InsertionData bestI = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
if(bestI instanceof InsertionData.NoInsertionFound){
throw new IllegalStateException(getErrorMsg(unassignedJob));
}
else{
bestInsertion = new Insertion(newRoute,bestI);
vehicleRoutes.add(newRoute);
}
}
// logger.info("insert " + unassignedJob + " pickup@" + bestInsertion.getInsertionData().getPickupInsertionIndex() + " delivery@" + bestInsertion.getInsertionData().getDeliveryInsertionIndex());
inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
}
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
}
private String getErrorMsg(Job unassignedJob) {
return "given the vehicles, could not insert job\n" +
"\t" + unassignedJob +
"\n\tthis might have the following reasons:\n" +
"\t- no vehicle has the capacity to transport the job [check whether there is at least one vehicle that is capable to transport the job]\n" +
"\t- the time-window cannot be met, even in a commuter tour the time-window is missed [check whether it is possible to reach the time-window on the shortest path or make hard time-windows soft]\n" +
"\t- if you deal with finite vehicles, and the available vehicles are already fully employed, no vehicle can be found anymore to transport the job [add penalty-vehicles]";
}
@Override
public void removeListener(InsertionListener insertionListener) {
insertionsListeners.removeListener(insertionListener);
}
@Override
public Collection<InsertionListener> getListeners() {
return Collections.unmodifiableCollection(insertionsListeners.getListeners());
}
@Override
public void addListener(InsertionListener insertionListener) {
insertionsListeners.addListener(insertionListener);
}
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE;
for(VehicleRoute vehicleRoute : batch.routes){
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if(iData instanceof NoInsertionFound) {
continue;
}
if(iData.getInsertionCost() < bestInsertionCost){
bestInsertion = new Insertion(vehicleRoute,iData);
bestInsertionCost = iData.getInsertionCost();
}
}
return bestInsertion;
}
private List<Batch> distributeRoutes(Collection<VehicleRoute> vehicleRoutes, int nuOfBatches) {
List<Batch> batches = new ArrayList<Batch>();
for(int i=0;i<nuOfBatches;i++) batches.add(new Batch());
/*
* if route.size < nuOfBatches add as much routes as empty batches are available
* else add one empty route anyway
*/
if(vehicleRoutes.size()<nuOfBatches){
int nOfNewRoutes = nuOfBatches-vehicleRoutes.size();
for(int i=0;i<nOfNewRoutes;i++){
vehicleRoutes.add(VehicleRoute.emptyRoute());
}
}
else{
vehicleRoutes.add(VehicleRoute.emptyRoute());
}
/*
* distribute routes to batches equally
*/
int count = 0;
for(VehicleRoute route : vehicleRoutes){
if(count == nuOfBatches) count=0;
batches.get(count).routes.add(route);
count++;
}
return batches;
}
}

View file

@ -14,30 +14,27 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import org.apache.log4j.Logger;
import basics.Job;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
/**
* This is experimental. It ignores vehicles' earliestStartTime.
*
* @author schroeder
*
*/
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalculator{
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator{
private static Logger log = Logger.getLogger(CalculatesServiceInsertionWithTimeScheduling.class);
private JobInsertionCalculator jic;
private JobInsertionCostsCalculator jic;
private Random random = new Random();
@ -45,7 +42,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
private double timeSlice = 900.0;
public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCalculator jic, double timeSlice, int neighbors) {
public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCostsCalculator jic, double timeSlice, int neighbors) {
super();
this.jic = jic;
this.timeSlice = timeSlice;
@ -59,7 +56,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
}
@Override
public InsertionData calculate(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) {
List<Double> vehicleDepartureTimes = new ArrayList<Double>();
double currentStart;
if(currentRoute.getStart() == null){
@ -84,7 +81,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
InsertionData bestIData = null;
for(Double departureTime : vehicleDepartureTimes){
InsertionData iData = jic.calculate(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
InsertionData iData = jic.getInsertionData(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore);
if(bestIData == null) bestIData = iData;
else if(iData.getInsertionCost() < bestIData.getInsertionCost()){
iData.setVehicleDepartureTime(departureTime);

View file

@ -14,15 +14,23 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.List;
import algorithms.HardConstraints.ConstraintManager;
import basics.VehicleRoutingProblem;
import basics.algo.InsertionListener;
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.constraint.ConstraintManager;
import jsprit.core.problem.job.Delivery;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.vehicle.VehicleFleetManager;
@ -30,16 +38,16 @@ class CalculatorBuilder {
private static class CalculatorPlusListeners {
private JobInsertionCalculator calculator;
private JobInsertionCostsCalculator calculator;
public JobInsertionCalculator getCalculator() {
public JobInsertionCostsCalculator getCalculator() {
return calculator;
}
private List<PrioritizedVRAListener> algorithmListener = new ArrayList<PrioritizedVRAListener>();
private List<InsertionListener> insertionListener = new ArrayList<InsertionListener>();
public CalculatorPlusListeners(JobInsertionCalculator calculator) {
public CalculatorPlusListeners(JobInsertionCostsCalculator calculator) {
super();
this.calculator = calculator;
}
@ -59,7 +67,7 @@ class CalculatorBuilder {
private VehicleRoutingProblem vrp;
private StateManager states;
private RouteAndActivityStateGetter states;
private boolean local = true;
@ -81,6 +89,8 @@ class CalculatorBuilder {
private ConstraintManager constraintManager;
private ActivityInsertionCostsCalculator activityInsertionCostCalculator = null;
/**
* Constructs the builder.
*
@ -102,7 +112,7 @@ class CalculatorBuilder {
*
* @return
*/
public CalculatorBuilder setStates(StateManager states){
public CalculatorBuilder setStates(RouteAndActivityStateGetter states){
this.states = states;
return this;
}
@ -138,6 +148,10 @@ class CalculatorBuilder {
local = true;
}
public void setActivityInsertionCostsCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){
this.activityInsertionCostCalculator = activityInsertionCostsCalculator;
}
/**
* Sets a flag to build a calculator that evaluates job insertion on route-level.
*
@ -173,16 +187,17 @@ class CalculatorBuilder {
* @return jobInsertionCalculator.
* @throws IllegalStateException if vrp == null or activityStates == null or fleetManager == null.
*/
public JobInsertionCalculator build(){
public JobInsertionCostsCalculator build(){
if(vrp == null) throw new IllegalStateException("vehicle-routing-problem is null, but it must be set (this.setVehicleRoutingProblem(vrp))");
if(states == null) throw new IllegalStateException("states is null, but is must be set (this.setStates(states))");
if(fleetManager == null) throw new IllegalStateException("fleetManager is null, but it must be set (this.setVehicleFleetManager(fleetManager))");
JobInsertionCalculator baseCalculator = null;
JobInsertionCostsCalculator baseCalculator = null;
CalculatorPlusListeners standardLocal = null;
if(local){
standardLocal = createStandardLocal(vrp, states);
}
else{
checkServicesOnly();
standardLocal = createStandardRoute(vrp, states,forwardLooking,memory);
}
baseCalculator = standardLocal.getCalculator();
@ -200,6 +215,17 @@ class CalculatorBuilder {
return createFinalInsertion(fleetManager, baseCalculator, states);
}
private void checkServicesOnly() {
for(Job j : vrp.getJobs().values()){
if(j instanceof Shipment){
throw new UnsupportedOperationException("currently the 'insert-on-route-level' option is only available for services (i.e. service, pickup, delivery), \n" +
"if you want to deal with shipments switch to option 'local-level' by either setting bestInsertionBuilder.setLocalLevel() or \n"
+ "by omitting the xml-tag '<level forwardLooking=2 memory=1>route</level>' when defining your insertionStrategy in algo-config.xml file");
}
}
}
private void addInsertionListeners(List<InsertionListener> list) {
for(InsertionListener iL : list){
insertionListeners.add(iL);
@ -212,40 +238,62 @@ class CalculatorBuilder {
}
}
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager statesManager){
private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, RouteAndActivityStateGetter statesManager){
if(constraintManager == null) throw new IllegalStateException("constraint-manager is null");
ActivityInsertionCostsCalculator defaultCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager);
JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), defaultCalc, constraintManager);
((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
ActivityInsertionCostsCalculator actInsertionCalc;
if(activityInsertionCostCalculator == null){
actInsertionCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts());
}
else{
actInsertionCalc = activityInsertionCostCalculator;
}
ShipmentInsertionCalculator shipmentInsertion = new ShipmentInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
switcher.put(Shipment.class, shipmentInsertion);
switcher.put(Service.class, serviceInsertion);
switcher.put(Pickup.class, serviceInsertion);
switcher.put(Delivery.class, serviceInsertion);
// JobInsertionCostsCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager);
// ((ServiceInsertionCalculator) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood());
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(switcher);
return calcPlusListeners;
}
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, StateManager activityStates2, double weightOfFixedCosts){
final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates2);
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCostsCalculator baseCalculator, RouteAndActivityStateGetter activityStates2, double weightOfFixedCosts){
final JobInsertionConsideringFixCostsCalculator withFixCost = new JobInsertionConsideringFixCostsCalculator(baseCalculator, activityStates2);
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
return calcPlusListeners;
}
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StateManager activityStates2, int forwardLooking, int solutionMemory){
private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, RouteAndActivityStateGetter activityStates2, int forwardLooking, int solutionMemory){
int after = forwardLooking;
ActivityInsertionCostsCalculator routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, activityStates2);
JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, routeLevelCostEstimator);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNuOfActsForwardLooking(after);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setMemorySize(solutionMemory);
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setStates(activityStates2);
ActivityInsertionCostsCalculator routeLevelCostEstimator;
if(activityInsertionCostCalculator == null){
routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityStates2);
}
else{
routeLevelCostEstimator = activityInsertionCostCalculator;
}
JobInsertionCostsCalculator jobInsertionCalculator = new ServiceInsertionOnRouteLevelCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), routeLevelCostEstimator, constraintManager, constraintManager);
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setNuOfActsForwardLooking(after);
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setMemorySize(solutionMemory);
((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
((ServiceInsertionOnRouteLevelCalculator) jobInsertionCalculator).setStates(activityStates2);
CalculatorPlusListeners calcPlusListener = new CalculatorPlusListeners(jobInsertionCalculator);
return calcPlusListener;
}
private JobInsertionCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCalculator baseCalc, StateManager activityStates2){
return new CalculatesVehTypeDepServiceInsertion(fleetManager, baseCalc);
private JobInsertionCostsCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCostsCalculator baseCalc, RouteAndActivityStateGetter activityStates2){
return new VehicleTypeDependentJobInsertionCalculator(fleetManager, baseCalc);
}
public void setConstraintManager(ConstraintManager constraintManager) {

View file

@ -14,18 +14,19 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import java.util.Collection;
import jsprit.core.algorithm.recreate.listener.InsertionStartsListener;
import jsprit.core.algorithm.recreate.listener.JobInsertedListener;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import org.apache.log4j.Logger;
import basics.Job;
import basics.VehicleRoutingProblem;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.route.VehicleRoute;
@ -37,11 +38,11 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn
VehicleRoutingProblem vrp;
CalculatesServiceInsertionConsideringFixCost calcConsideringFix;
JobInsertionConsideringFixCostsCalculator calcConsideringFix;
private int nuOfJobsToRecreate;
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, CalculatesServiceInsertionConsideringFixCost calcConsideringFix) {
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, JobInsertionConsideringFixCostsCalculator calcConsideringFix) {
super();
this.vrp = vrp;
this.calcConsideringFix = calcConsideringFix;

View file

@ -0,0 +1,122 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.algorithm.recreate;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.algorithm.recreate.listener.InsertionListeners;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.DefaultShipmentActivityFactory;
import jsprit.core.problem.solution.route.activity.DefaultTourActivityFactory;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.activity.TourActivityFactory;
import jsprit.core.problem.solution.route.activity.TourShipmentActivityFactory;
class Inserter {
interface JobInsertionHandler {
void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route);
void setNextHandler(JobInsertionHandler handler);
}
class JobExceptionHandler implements JobInsertionHandler{
@Override
public void handleJobInsertion(Job job, InsertionData iData,VehicleRoute route) {
throw new IllegalStateException("job insertion is not supported. Do not know job type.");
}
@Override
public void setNextHandler(JobInsertionHandler handler) {
// TODO Auto-generated method stub
}
}
class ServiceInsertionHandler implements JobInsertionHandler{
private TourActivityFactory activityFactory = new DefaultTourActivityFactory();
private JobInsertionHandler delegator = new JobExceptionHandler();
@Override
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
if(job instanceof Service){
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), this.activityFactory.createActivity((Service)job));
route.setDepartureTime(iData.getVehicleDepartureTime());
}
else delegator.handleJobInsertion(job, iData, route);
}
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
this.delegator = jobInsertionHandler;
}
}
class ShipmentInsertionHandler implements JobInsertionHandler {
private TourShipmentActivityFactory activityFactory = new DefaultShipmentActivityFactory();
private JobInsertionHandler delegator = new JobExceptionHandler();
@Override
public void handleJobInsertion(Job job, InsertionData iData, VehicleRoute route) {
if(job instanceof Shipment){
TourActivity pickupShipment = this.activityFactory.createPickup((Shipment)job);
TourActivity deliverShipment = this.activityFactory.createDelivery((Shipment)job);
route.getTourActivities().addActivity(iData.getDeliveryInsertionIndex(), deliverShipment);
route.getTourActivities().addActivity(iData.getPickupInsertionIndex(), pickupShipment);
route.setDepartureTime(iData.getVehicleDepartureTime());
}
else delegator.handleJobInsertion(job, iData, route);
}
public void setNextHandler(JobInsertionHandler jobInsertionHandler){
this.delegator = jobInsertionHandler;
}
}
private InsertionListeners insertionListeners;
private JobInsertionHandler jobInsertionHandler;
public Inserter(InsertionListeners insertionListeners) {
this.insertionListeners = insertionListeners;
new DefaultTourActivityFactory();
jobInsertionHandler = new ServiceInsertionHandler();
jobInsertionHandler.setNextHandler(new ShipmentInsertionHandler());
}
public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute){
insertionListeners.informBeforeJobInsertion(job, insertionData, vehicleRoute);
if(insertionData == null || (insertionData instanceof NoInsertionFound)) throw new IllegalStateException("insertionData null. cannot insert job.");
if(job == null) throw new IllegalStateException("cannot insert null-job");
if(!(vehicleRoute.getVehicle().getId().toString().equals(insertionData.getSelectedVehicle().getId().toString()))){
insertionListeners.informVehicleSwitched(vehicleRoute, vehicleRoute.getVehicle(), insertionData.getSelectedVehicle());
vehicleRoute.setVehicle(insertionData.getSelectedVehicle(), insertionData.getVehicleDepartureTime());
}
jobInsertionHandler.handleJobInsertion(job, insertionData, vehicleRoute);
insertionListeners.informJobInserted(job, vehicleRoute, insertionData.getInsertionCost(), insertionData.getAdditionalTime());
}
}

View file

@ -14,14 +14,19 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import basics.route.Driver;
import basics.route.Vehicle;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.vehicle.Vehicle;
class InsertionData {
/**
* Data object that collects insertion information. It collects insertionCosts, insertionIndeces, vehicle and driver to be employed
* and departureTime of vehicle at vehicle's start location (e.g. depot).
*
* @author stefan
*
*/
public class InsertionData {
static class NoInsertionFound extends InsertionData{
@ -33,7 +38,15 @@ class InsertionData {
private static InsertionData noInsertion = new NoInsertionFound();
public static InsertionData noInsertionFound(){
/**
* Returns an instance of InsertionData that represents an EmptyInsertionData (which might indicate
* that no insertion has been found). It is internally instantiated as follows:<br>
* <code>new InsertionData(Double.MAX_VALUE, NO_INDEX, NO_INDEX, null, null);</code><br>
* where NO_INDEX=-1.
*
* @return
*/
public static InsertionData createEmptyInsertionData(){
return noInsertion;
}
@ -80,22 +93,47 @@ class InsertionData {
return "[iCost="+insertionCost+"][iIndex="+deliveryInsertionIndex+"][depTime="+departureTime+"][vehicle="+selectedVehicle+"][driver="+selectedDriver+"]";
}
/**
* Returns insertionIndex of deliveryActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
*
* @return
*/
public int getDeliveryInsertionIndex(){
return deliveryInsertionIndex;
}
/**
* Returns insertionIndex of pickkupActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
*
* @return
*/
public int getPickupInsertionIndex(){
return pickupInsertionIndex;
}
/**
* Returns insertion costs (which might be the additional costs of inserting the corresponding job).
*
* @return
*/
public double getInsertionCost() {
return insertionCost;
}
/**
* Returns the vehicle to be employed.
*
* @return
*/
public Vehicle getSelectedVehicle() {
return selectedVehicle;
}
/**
* Returns the vehicle to be employed.
*
* @return
*/
public Driver getSelectedDriver(){
return selectedDriver;
}

View file

@ -14,13 +14,14 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import java.util.Collection;
import basics.Job;
import basics.algo.InsertionListener;
import basics.route.VehicleRoute;
import jsprit.core.algorithm.recreate.listener.InsertionListener;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
@ -31,33 +32,7 @@ import basics.route.VehicleRoute;
*
*/
interface InsertionStrategy {
class Insertion {
private final VehicleRoute route;
private final InsertionData insertionData;
public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) {
super();
this.route = vehicleRoute;
this.insertionData = insertionData;
}
public VehicleRoute getRoute() {
return route;
}
public InsertionData getInsertionData() {
return insertionData;
}
}
public interface InsertionStrategy {
/**
* Assigns the unassigned jobs to service-providers

View file

@ -14,11 +14,11 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import basics.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem;
interface InsertionStrategyFactory {
public interface InsertionStrategyFactory {
public InsertionStrategy createStrategy(VehicleRoutingProblem vrp);

View file

@ -0,0 +1,26 @@
package jsprit.core.algorithm.recreate;
import java.util.HashMap;
import java.util.Map;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
class JobCalculatorSwitcher implements JobInsertionCostsCalculator{
private Map<Class<? extends Job>,JobInsertionCostsCalculator> calcMap = new HashMap<Class<? extends Job>, JobInsertionCostsCalculator>();
void put(Class<? extends Job> jobClass, JobInsertionCostsCalculator jic){
calcMap.put(jobClass, jic);
}
public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore){
JobInsertionCostsCalculator jic = calcMap.get(jobToInsert.getClass());
if(jic==null) throw new IllegalStateException("cannot find calculator for " + jobToInsert.getClass());
return jic.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownScore);
}
}

View file

@ -14,48 +14,51 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.solution.route.state.StateFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import org.apache.log4j.Logger;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class CalculatesServiceInsertionConsideringFixCost implements JobInsertionCalculator{
final class JobInsertionConsideringFixCostsCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionConsideringFixCost.class);
private static final Logger logger = Logger.getLogger(JobInsertionConsideringFixCostsCalculator.class);
private final JobInsertionCalculator standardServiceInsertion;
private final JobInsertionCostsCalculator standardServiceInsertion;
private double weight_deltaFixCost = 0.5;
private double solution_completeness_ratio = 0.5;
private StateManager states;
private RouteAndActivityStateGetter stateGetter;
public CalculatesServiceInsertionConsideringFixCost(final JobInsertionCalculator standardInsertionCalculator, StateManager activityStates2) {
public JobInsertionConsideringFixCostsCalculator(final JobInsertionCostsCalculator standardInsertionCalculator, RouteAndActivityStateGetter stateGetter) {
super();
this.standardServiceInsertion = standardInsertionCalculator;
this.states = activityStates2;
this.stateGetter = stateGetter;
logger.info("inialise " + this);
}
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) {
double relFixCost = getDeltaRelativeFixCost(currentRoute, newVehicle, jobToInsert);
double absFixCost = getDeltaAbsoluteFixCost(currentRoute, newVehicle, jobToInsert);
double deltaFixCost = (1-solution_completeness_ratio)*relFixCost + solution_completeness_ratio*absFixCost;
double fixcost_contribution = weight_deltaFixCost*solution_completeness_ratio*deltaFixCost;
if(fixcost_contribution > bestKnownPrice){
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
InsertionData iData = standardServiceInsertion.calculate(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice);
InsertionData iData = standardServiceInsertion.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice);
if(iData instanceof NoInsertionFound){
return iData;
}
@ -80,7 +83,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
}
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
double load = getCurrentLoad(route) + job.getCapacityDemand();
double load = getCurrentMaxLoadInRoute(route) + job.getCapacityDemand();
double currentFix = 0.0;
if(route.getVehicle() != null){
if(!(route.getVehicle() instanceof NoVehicle)){
@ -94,7 +97,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
}
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
int currentLoad = getCurrentLoad(route);
int currentLoad = getCurrentMaxLoadInRoute(route);
double load = currentLoad + job.getCapacityDemand();
double currentRelFix = 0.0;
if(route.getVehicle() != null){
@ -109,8 +112,8 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
return relativeFixCost;
}
private int getCurrentLoad(VehicleRoute route) {
return (int) states.getRouteState(route, StateTypes.LOAD).toDouble();
private int getCurrentMaxLoadInRoute(VehicleRoute route) {
return (int) stateGetter.getRouteState(route, StateFactory.MAXLOAD).toDouble();
}
}

View file

@ -14,22 +14,16 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.io;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import org.junit.Test;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
public class ReaderTest {
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
@Test
public void testRead_ifReaderIsCalled_itReadsSuccessfully(){
new VrpXMLReader(VehicleRoutingProblem.Builder.newInstance(), new ArrayList<VehicleRoutingProblemSolution>()).read("src/test/resources/lui-shen-solution.xml");
public interface JobInsertionCostsCalculator {
}
public InsertionData getInsertionData(VehicleRoute currentRoute, Job newJob, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownCosts);
}

View file

@ -18,39 +18,46 @@
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import algorithms.HardConstraints.HardActivityLevelConstraint;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.TourActivity;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.util.CalculationUtils;
/**
* Calculates activity insertion costs locally, i.e. by comparing the additional costs of insertion the new activity k between
* activity i (prevAct) and j (nextAct).
* Additional costs are then basically calculated as delta c = c_ik + c_kj - c_ij.
*
* <p>Note once time has an effect on costs this class requires activity endTimes.
*
* @author stefan
*
*/
class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator{
private HardActivityLevelConstraint hardConstraint;
private VehicleRoutingTransportCosts routingCosts;
private VehicleRoutingActivityCosts activityCosts;
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint) {
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts) {
super();
this.routingCosts = routingCosts;
this.activityCosts = actCosts;
this.hardConstraint = hardActivityLevelConstraint;
}
@Override
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){
return null;
}
public ActivityInsertionCosts getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct;
double newAct_endTime = CalcUtils.getActivityEndTime(newAct_arrTime, newAct);
double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct);
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
@ -66,8 +73,12 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
double oldCosts;
double oldTime;
if(iFacts.getRoute().isEmpty()){
oldCosts = 0.0;
oldTime = 0.0;
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct;
oldTime = (nextAct.getArrTime() - depTimeAtPrevAct);
}
else{
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());

View file

@ -1,3 +1,4 @@
package jsprit.core.algorithm.recreate;
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*

View file

@ -1,3 +1,4 @@
package jsprit.core.algorithm.recreate;
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*

View file

@ -18,45 +18,41 @@
* Contributors:
* Stefan Schroeder - initial API and implementation
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.List;
import algorithms.HardConstraints.HardActivityLevelConstraint;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.VehicleRoute;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.Start;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.solution.route.state.StateFactory;
class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCostsCalculator{
private HardActivityLevelConstraint hardConstraint;
private VehicleRoutingActivityCosts activityCosts;
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
private StateManager stateManager;
private RouteAndActivityStateGetter stateManager;
private int nuOfActivities2LookForward = 0;
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint, StateManager stateManager) {
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, RouteAndActivityStateGetter stateManager) {
super();
this.activityCosts = actCosts;
this.hardConstraint = hardActivityLevelConstraint;
this.stateManager = stateManager;
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts);
}
@Override
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){
return null;
}
public ActivityInsertionCosts getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
List<TourActivity> path = new ArrayList<TourActivity>();
path.add(prevAct); path.add(newAct); path.add(nextAct);
int actIndex;
@ -77,9 +73,9 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) {
if(act instanceof End){
return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble();
return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble();
}
return stateManager.getActivityState(act,StateTypes.COSTS).toDouble();
return stateManager.getActivityState(act,StateFactory.COSTS).toDouble();
}
private List<TourActivity> getForwardLookingPath(VehicleRoute route, int actIndex) {

View file

@ -14,33 +14,40 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import jsprit.core.algorithm.recreate.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint.ConstraintsStatus;
import jsprit.core.problem.constraint.HardRouteStateLevelConstraint;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.DefaultTourActivityFactory;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.Start;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.activity.TourActivityFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import jsprit.core.util.CalculationUtils;
import jsprit.core.util.Neighborhood;
import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import algorithms.HardConstraints.HardRouteLevelConstraint;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DefaultTourActivityFactory;
import basics.route.Driver;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivity;
import basics.route.TourActivityFactory;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class CalculatesServiceInsertion implements JobInsertionCalculator{
final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertion.class);
private static final Logger logger = Logger.getLogger(ServiceInsertionCalculator.class);
private HardRouteLevelConstraint hardRouteLevelConstraint;
private HardRouteStateLevelConstraint hardRouteLevelConstraint;
private HardActivityStateLevelConstraint hardActivityLevelConstraint;
private Neighborhood neighborhood = new Neighborhood() {
@ -61,10 +68,12 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
logger.info("initialise neighborhood " + neighborhood);
}
public CalculatesServiceInsertion(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint) {
public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteStateLevelConstraint hardRouteLevelConstraint, HardActivityStateLevelConstraint hardActivityLevelConstraint) {
super();
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
this.transportCosts = routingCosts;
activityFactory = new DefaultTourActivityFactory();
logger.info("initialise " + this);
@ -81,13 +90,13 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
*
*/
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
double bestCost = bestKnownCosts;
@ -99,36 +108,40 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
End end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
TourActivity prevAct = start;
double prevActStartTime = newVehicleDepartureTime;
int actIndex = 0;
boolean loopBroken = false;
for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc != null){
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
bestMarginals = mc;
insertionIndex = actIndex;
}
}
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
loopBroken = true;
break;
}
}
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle);
double nextActEndTime = CalcUtils.getActivityEndTime(nextActArrTime, nextAct);
double nextActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct);
prevActStartTime = nextActEndTime;
prevAct = nextAct;
actIndex++;
}
End nextAct = end;
if(!loopBroken){
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if(mc != null) {
if(mc.getAdditionalCosts() < bestCost){
bestCost = mc.getAdditionalCosts();
bestMarginals = mc;
@ -136,9 +149,10 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
}
}
}
}
if(insertionIndex == InsertionData.NO_INDEX) {
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
@ -146,8 +160,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
return insertionData;
}
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) {
return activityInsertionCostsCalculator.calculate(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
public ActivityInsertionCosts calculate(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) {
return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
}
}

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.Comparator;
@ -23,31 +23,37 @@ import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import jsprit.core.algorithm.recreate.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint.ConstraintsStatus;
import jsprit.core.problem.constraint.HardRouteStateLevelConstraint;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.DefaultTourActivityFactory;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.Start;
import jsprit.core.problem.solution.route.activity.TourActivities;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.activity.TourActivityFactory;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import jsprit.core.problem.solution.route.state.StateFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import jsprit.core.util.Neighborhood;
import org.apache.log4j.Logger;
import util.Neighborhood;
import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import algorithms.HardConstraints.HardRouteLevelConstraint;
import basics.Job;
import basics.Service;
import basics.costs.VehicleRoutingActivityCosts;
import basics.costs.VehicleRoutingTransportCosts;
import basics.route.DefaultTourActivityFactory;
import basics.route.Driver;
import basics.route.End;
import basics.route.Start;
import basics.route.TourActivities;
import basics.route.TourActivity;
import basics.route.TourActivityFactory;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalculator{
final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionOnRouteLevel.class);
private static final Logger logger = Logger.getLogger(ServiceInsertionOnRouteLevelCalculator.class);
private final VehicleRoutingTransportCosts transportCosts;
@ -57,9 +63,11 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private TourActivityFactory tourActivityFactory = new DefaultTourActivityFactory();
private StateManager stateManager;
private RouteAndActivityStateGetter stateManager;
private HardRouteLevelConstraint hardRouteLevelConstraint;
private HardRouteStateLevelConstraint hardRouteLevelConstraint;
private HardActivityStateLevelConstraint hardActivityLevelConstraint;
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
@ -94,18 +102,19 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
logger.info("set [solutionMemory="+memorySize+"]");
}
public CalculatesServiceInsertionOnRouteLevel(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, HardRouteLevelConstraint hardRouteLevelConstraint, ActivityInsertionCostsCalculator activityInsertionCostsCalculator) {
public ServiceInsertionOnRouteLevelCalculator(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteStateLevelConstraint hardRouteLevelConstraint, HardActivityStateLevelConstraint hardActivityLevelConstraint) {
super();
this.transportCosts = vehicleRoutingCosts;
this.activityCosts = costFunc;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts);
logger.info("initialise " + this);
}
public void setStates(StateManager stateManager){
public void setStates(RouteAndActivityStateGetter stateManager){
this.stateManager = stateManager;
}
@ -128,13 +137,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
*
*/
@Override
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double best_known_insertion_costs) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double best_known_insertion_costs) {
if(jobToInsert == null) throw new IllegalStateException("job is null. cannot calculate the insertion of a null-job.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("no vehicle given. set para vehicle!");
InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.noInsertionFound();
return InsertionData.createEmptyInsertionData();
}
/**
@ -151,6 +160,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
double best_insertion_costs = best_known_insertion_costs;
Service service = (Service)jobToInsert;
/**
* some inis
*/
@ -164,6 +174,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
double sumOf_prevCosts_newVehicle = 0.0;
double prevActDepTime_newVehicle = start.getEndTime();
boolean loopBroken = false;
/**
* inserting serviceAct2Insert in route r={0,1,...,i-1,i,j,j+1,...,n(r),n(r)+1}
* i=prevAct
@ -172,12 +183,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
*/
for(TourActivity nextAct : tour.getActivities()){
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
if(status.equals(ConstraintsStatus.FULFILLED)){
/**
* builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking}
*/
InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle);
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
if(actInsertionCosts != null){
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
/**
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
*/
@ -190,6 +202,10 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver));
}
}
else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
loopBroken = true;
break;
}
}
/**
@ -219,11 +235,12 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
actIndex++;
}
if(!loopBroken){
End nextAct = end;
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle);
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
if(status.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
if(actInsertionCosts != null){
/**
* insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle)
@ -238,6 +255,8 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
}
}
}
}
}
/**
@ -254,6 +273,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
}
}
else{
for(int i=0;i<memorySize;i++){
InsertionData data = bestInsertionsQueue.poll();
if(data == null){
@ -271,7 +291,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
/**
* compute cost-diff of tour with and without new activity --> insertion_costs
*/
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateTypes.COSTS).toDouble();
double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateFactory.COSTS).toDouble();
/**
* if better than best known, make it the best known
@ -282,10 +302,8 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
}
}
}
if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.noInsertionFound();
InsertionData insertionData = new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
return insertionData;
if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.createEmptyInsertionData();
return new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
}
/**
@ -318,9 +336,9 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) {
if(act instanceof End){
return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble();
return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble();
}
return stateManager.getActivityState(act,StateTypes.COSTS).toDouble();
return stateManager.getActivityState(act,StateFactory.COSTS).toDouble();
}
/**

View file

@ -0,0 +1,213 @@
/*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package jsprit.core.algorithm.recreate;
import java.util.List;
import jsprit.core.algorithm.recreate.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint.ConstraintsStatus;
import jsprit.core.problem.constraint.HardRouteStateLevelConstraint;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.DefaultShipmentActivityFactory;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.Start;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.activity.TourShipmentActivityFactory;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import jsprit.core.util.CalculationUtils;
import jsprit.core.util.Neighborhood;
import org.apache.log4j.Logger;
final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
private static final Logger logger = Logger.getLogger(ShipmentInsertionCalculator.class);
private HardRouteStateLevelConstraint hardRouteLevelConstraint;
private HardActivityStateLevelConstraint hardActivityLevelConstraint;
private Neighborhood neighborhood = new Neighborhood() {
@Override
public boolean areNeighbors(String location1, String location2) {
return true;
}
};
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
private VehicleRoutingTransportCosts transportCosts;
private TourShipmentActivityFactory activityFactory;
public void setNeighborhood(Neighborhood neighborhood) {
this.neighborhood = neighborhood;
logger.info("initialise neighborhood " + neighborhood);
}
public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteStateLevelConstraint hardRouteLevelConstraint, HardActivityStateLevelConstraint hardActivityLevelConstraint) {
super();
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
this.transportCosts = routingCosts;
activityFactory = new DefaultShipmentActivityFactory();
logger.info("initialise " + this);
}
@Override
public String toString() {
return "[name=calculatesServiceInsertion]";
}
/**
* Calculates the marginal cost of inserting job i locally. This is based on the
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
*
*/
@Override
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing.");
if(!(jobToInsert instanceof Shipment)) throw new IllegalStateException("jobToInsert should be of type Shipment!");
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
return InsertionData.createEmptyInsertionData();
}
double bestCost = bestKnownCosts;
Shipment shipment = (Shipment)jobToInsert;
TourActivity pickupShipment = activityFactory.createPickup(shipment);
TourActivity deliverShipment = activityFactory.createDelivery(shipment);
int pickupInsertionIndex = InsertionData.NO_INDEX;
int deliveryInsertionIndex = InsertionData.NO_INDEX;
Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
End end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
TourActivity prevAct = start;
double prevActEndTime = newVehicleDepartureTime;
boolean pickupShipmentLoopBroken = false;
//pickupShipmentLoop
List<TourActivity> activities = currentRoute.getTourActivities().getActivities();
for(int i=0;i<activities.size();i++){
ConstraintsStatus pickupShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, pickupShipment, activities.get(i), prevActEndTime);
if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED)){
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), activities.get(i).getLocationId(), prevActEndTime, newDriver, newVehicle);
prevActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, activities.get(i));
prevAct = activities.get(i);
continue;
}
else if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
pickupShipmentLoopBroken = true;
break;
}
ActivityInsertionCosts pickupAIC = calculate(insertionContext,prevAct,pickupShipment,activities.get(i),prevActEndTime);
TourActivity prevAct_deliveryLoop = pickupShipment;
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), pickupShipment.getLocationId(), prevActEndTime, newDriver, newVehicle);
double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
boolean deliverShipmentLoopBroken = false;
//deliverShipmentLoop
for(int j=i;j<activities.size();j++){
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, activities.get(j), prevActEndTime_deliveryLoop);
if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,activities.get(j),prevActEndTime_deliveryLoop);
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = i;
deliveryInsertionIndex = j;
}
}
else if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){
deliverShipmentLoopBroken = true;
break;
}
//update prevAct and endTime
double nextActArrTime = prevActEndTime_deliveryLoop + transportCosts.getTransportTime(prevAct_deliveryLoop.getLocationId(), activities.get(j).getLocationId(), prevActEndTime_deliveryLoop, newDriver, newVehicle);
prevActEndTime_deliveryLoop = CalculationUtils.getActivityEndTime(nextActArrTime, activities.get(j));
prevAct_deliveryLoop = activities.get(j);
}
if(!deliverShipmentLoopBroken){ //check insertion between lastAct and endOfTour
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, end, prevActEndTime_deliveryLoop);
if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,end,prevActEndTime_deliveryLoop);
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = i;
deliveryInsertionIndex = activities.size();
}
}
}
//update prevAct and endTime
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), activities.get(i).getLocationId(), prevActEndTime, newDriver, newVehicle);
prevActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, activities.get(i));
prevAct = activities.get(i);
}
if(!pickupShipmentLoopBroken){ //check insertion of pickupShipment and deliverShipment at just before tour ended
ConstraintsStatus pickupShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, pickupShipment, end, prevActEndTime);
if(pickupShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts pickupAIC = calculate(insertionContext,prevAct,pickupShipment,end,prevActEndTime);
TourActivity prevAct_deliveryLoop = pickupShipment;
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocationId(), pickupShipment.getLocationId(), prevActEndTime, newDriver, newVehicle);
double shipmentPickupEndTime = CalculationUtils.getActivityEndTime(shipmentPickupArrTime, pickupShipment);
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
ConstraintsStatus deliverShipmentConstraintStatus = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct_deliveryLoop, deliverShipment, end, prevActEndTime_deliveryLoop);
if(deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)){
ActivityInsertionCosts deliveryAIC = calculate(insertionContext,prevAct_deliveryLoop,deliverShipment,end,prevActEndTime_deliveryLoop);
double totalActivityInsertionCosts = pickupAIC.getAdditionalCosts() + deliveryAIC.getAdditionalCosts();
if(totalActivityInsertionCosts < bestCost){
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = activities.size();
deliveryInsertionIndex = activities.size();
}
}
}
}
if(pickupInsertionIndex == InsertionData.NO_INDEX) {
return InsertionData.createEmptyInsertionData();
}
InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver);
// logger.info("pickupIndex="+pickupInsertionIndex + ";deliveryIndex=" + deliveryInsertionIndex);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
return insertionData;
}
private ActivityInsertionCosts calculate(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double departureTimeAtPrevAct) {
return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
}
}

View file

@ -14,17 +14,19 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import jsprit.core.algorithm.recreate.listener.VehicleSwitchedListener;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleFleetManager;
class VehicleSwitched implements VehicleSwitchedListener{
public class VehicleSwitched implements VehicleSwitchedListener{
private VehicleFleetManager fleetManager;
VehicleSwitched(VehicleFleetManager fleetManager){
public VehicleSwitched(VehicleFleetManager fleetManager){
this.fleetManager = fleetManager;
}

View file

@ -14,31 +14,33 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.Collection;
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleFleetManager;
import jsprit.core.problem.vehicle.VehicleImpl.NoVehicle;
import org.apache.log4j.Logger;
import algorithms.InsertionData.NoInsertionFound;
import basics.Job;
import basics.route.Driver;
import basics.route.Vehicle;
import basics.route.VehicleImpl.NoVehicle;
import basics.route.VehicleRoute;
final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculator{
final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCostsCalculator{
private Logger logger = Logger.getLogger(CalculatesVehTypeDepServiceInsertion.class);
private Logger logger = Logger.getLogger(VehicleTypeDependentJobInsertionCalculator.class);
private final VehicleFleetManager fleetManager;
private final JobInsertionCalculator insertionCalculator;
private final JobInsertionCostsCalculator insertionCalculator;
public CalculatesVehTypeDepServiceInsertion(final VehicleFleetManager fleetManager, final JobInsertionCalculator jobInsertionCalc) {
public VehicleTypeDependentJobInsertionCalculator(final VehicleFleetManager fleetManager, final JobInsertionCostsCalculator jobInsertionCalc) {
this.fleetManager = fleetManager;
this.insertionCalculator = jobInsertionCalc;
logger.info("inialise " + this);
@ -49,10 +51,10 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
return "[name=vehicleTypeDependentServiceInsertion]";
}
public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) {
Vehicle selectedVehicle = currentRoute.getVehicle();
Driver selectedDriver = currentRoute.getDriver();
InsertionData bestIData = InsertionData.noInsertionFound();
InsertionData bestIData = InsertionData.createEmptyInsertionData();
double bestKnownCost_ = bestKnownCost;
Collection<Vehicle> relevantVehicles = new ArrayList<Vehicle>();
if(!(selectedVehicle instanceof NoVehicle)) {
@ -65,7 +67,7 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
for(Vehicle v : relevantVehicles){
double depTime = v.getEarliestDeparture();
InsertionData iData = insertionCalculator.calculate(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
InsertionData iData = insertionCalculator.getInsertionData(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_);
if(iData instanceof NoInsertionFound) {
if(bestIData instanceof NoInsertionFound) bestIData = iData;
continue;

View file

@ -14,11 +14,11 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate.listener;
import basics.Job;
import basics.algo.InsertionListener;
import basics.route.VehicleRoute;
import jsprit.core.algorithm.recreate.InsertionData;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
interface BeforeJobInsertionListener extends InsertionListener{

View file

@ -14,11 +14,12 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.recreate.listener;
import java.util.Collection;
import basics.route.VehicleRoute;
import jsprit.core.problem.solution.route.VehicleRoute;
public interface InsertionEndsListener extends InsertionListener {

View file

@ -14,7 +14,9 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.recreate.listener;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;

View file

@ -14,20 +14,18 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate.listener;
import java.util.ArrayList;
import java.util.Collection;
import basics.Job;
import basics.algo.InsertionEndsListener;
import basics.algo.InsertionListener;
import basics.algo.InsertionStartsListener;
import basics.algo.JobInsertedListener;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import jsprit.core.algorithm.recreate.InsertionData;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
class InsertionListeners {
public class InsertionListeners {
private Collection<InsertionListener> listeners = new ArrayList<InsertionListener>();

View file

@ -14,15 +14,17 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.recreate.listener;
import java.util.Collection;
import basics.Job;
import basics.route.VehicleRoute;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;
public interface InsertionStartsListener extends InsertionListener {
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
}

View file

@ -14,10 +14,10 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package basics.algo;
package jsprit.core.algorithm.recreate.listener;
import basics.Job;
import basics.route.VehicleRoute;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.solution.route.VehicleRoute;

View file

@ -14,13 +14,12 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algorithms;
package jsprit.core.algorithm.recreate.listener;
import basics.algo.InsertionListener;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
interface VehicleSwitchedListener extends InsertionListener{
public interface VehicleSwitchedListener extends InsertionListener{
public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle);

Some files were not shown because too many files have changed in this diff Show more