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:
commit
a0ad012768
369 changed files with 75965 additions and 6728 deletions
165
LICENSE.txt
165
LICENSE.txt
|
|
@ -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.
|
|
||||||
|
|
@ -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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -22,24 +22,24 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
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.apache.log4j.Logger;
|
||||||
import org.jfree.chart.ChartFactory;
|
import org.jfree.chart.ChartFactory;
|
||||||
import org.jfree.chart.ChartUtilities;
|
import org.jfree.chart.ChartUtilities;
|
||||||
import org.jfree.chart.JFreeChart;
|
import org.jfree.chart.JFreeChart;
|
||||||
import org.jfree.chart.axis.NumberAxis;
|
import org.jfree.chart.axis.NumberAxis;
|
||||||
import org.jfree.chart.axis.NumberTickUnit;
|
|
||||||
import org.jfree.chart.plot.PlotOrientation;
|
import org.jfree.chart.plot.PlotOrientation;
|
||||||
import org.jfree.chart.plot.XYPlot;
|
import org.jfree.chart.plot.XYPlot;
|
||||||
import org.jfree.data.Range;
|
import org.jfree.data.Range;
|
||||||
import org.jfree.data.xy.XYSeries;
|
import org.jfree.data.xy.XYSeries;
|
||||||
import org.jfree.data.xy.XYSeriesCollection;
|
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) {
|
public AlgorithmSearchProgressChartListener(String pngFileName) {
|
||||||
super();
|
super();
|
||||||
this.filename = pngFileName;
|
this.filename = pngFileName;
|
||||||
|
if(!this.filename.endsWith("png")){
|
||||||
|
this.filename += ".png";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -118,8 +121,10 @@ public class AlgorithmSearchProgressChartListener implements IterationEndsListen
|
||||||
XYPlot plot = chart.getXYPlot();
|
XYPlot plot = chart.getXYPlot();
|
||||||
|
|
||||||
NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
|
NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
|
||||||
Range rangeY = new Range(minValue-0.05*minValue,maxValue + 0.05*maxValue);
|
Range rangeBounds = coll.getRangeBounds(true);
|
||||||
yAxis.setRange(rangeY);
|
double upper = Math.min(rangeBounds.getUpperBound(), rangeBounds.getLowerBound()*5);
|
||||||
|
if(upper == 0.0){ upper = 10000; }
|
||||||
|
yAxis.setRangeWithMargins(rangeBounds.getLowerBound(),upper);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ChartUtilities.saveChartAsJPEG(new File(filename), chart, 1000, 600);
|
ChartUtilities.saveChartAsJPEG(new File(filename), chart, 1000, 600);
|
||||||
|
|
@ -143,9 +148,9 @@ public class AlgorithmSearchProgressChartListener implements IterationEndsListen
|
||||||
double best = Double.MAX_VALUE;
|
double best = Double.MAX_VALUE;
|
||||||
double sum = 0.0;
|
double sum = 0.0;
|
||||||
for(VehicleRoutingProblemSolution sol : solutions){
|
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();
|
if(sol.getCost() < best) best = sol.getCost();
|
||||||
sum += sol.getCost();
|
sum += Math.min(sol.getCost(),Double.MAX_VALUE);
|
||||||
}
|
}
|
||||||
bestResultList.add(best);
|
bestResultList.add(best);
|
||||||
worstResultList.add(worst);
|
worstResultList.add(worst);
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -25,19 +25,21 @@ import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
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.commons.math.stat.descriptive.DescriptiveStatistics;
|
||||||
import org.apache.log4j.Level;
|
import org.apache.log4j.Level;
|
||||||
import org.apache.log4j.Logger;
|
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 {
|
public class ConcurrentBenchmarker {
|
||||||
|
|
||||||
|
|
@ -47,7 +49,7 @@ public class ConcurrentBenchmarker {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private String algorithmConfig;
|
private String algorithmConfig = null;
|
||||||
|
|
||||||
private List<BenchmarkInstance> benchmarkInstances = new ArrayList<BenchmarkInstance>();
|
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 void setCost(Cost cost){ this.cost = cost; }
|
||||||
|
|
||||||
public ConcurrentBenchmarker(String algorithmConfig) {
|
public ConcurrentBenchmarker(String algorithmConfig) {
|
||||||
|
|
@ -74,6 +78,10 @@ public class ConcurrentBenchmarker {
|
||||||
Logger.getRootLogger().setLevel(Level.ERROR);
|
Logger.getRootLogger().setLevel(Level.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConcurrentBenchmarker(VehicleRoutingAlgorithmFactory algorithmFactory){
|
||||||
|
this.algorithmFactory = algorithmFactory;
|
||||||
|
}
|
||||||
|
|
||||||
public void addBenchmarkWriter(BenchmarkWriter writer){
|
public void addBenchmarkWriter(BenchmarkWriter writer){
|
||||||
writers.add(writer);
|
writers.add(writer);
|
||||||
}
|
}
|
||||||
|
|
@ -94,6 +102,12 @@ public class ConcurrentBenchmarker {
|
||||||
benchmarkInstances.add(new BenchmarkInstance(name,problem,bestKnownResult,bestKnownVehicles));
|
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){
|
public void setNuOfRuns(int runs){
|
||||||
this.runs = runs;
|
this.runs = runs;
|
||||||
}
|
}
|
||||||
|
|
@ -142,11 +156,11 @@ public class ConcurrentBenchmarker {
|
||||||
double[] times = new double[runs];
|
double[] times = new double[runs];
|
||||||
|
|
||||||
for(int run=0;run<runs;run++){
|
for(int run=0;run<runs;run++){
|
||||||
VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(p.vrp, algorithmConfig);
|
VehicleRoutingAlgorithm vra = createAlgorithm(p);
|
||||||
StopWatch stopwatch = new StopWatch();
|
StopWatch stopwatch = new StopWatch();
|
||||||
vra.getAlgorithmListeners().addListener(stopwatch,Priority.HIGH);
|
vra.getAlgorithmListeners().addListener(stopwatch,Priority.HIGH);
|
||||||
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
|
||||||
VehicleRoutingProblemSolution best = Solutions.getBest(solutions);
|
VehicleRoutingProblemSolution best = Solutions.bestOf(solutions);
|
||||||
vehicles[run] = best.getRoutes().size();
|
vehicles[run] = best.getRoutes().size();
|
||||||
results[run] = cost.getCost(best);
|
results[run] = cost.getCost(best);
|
||||||
times[run] = stopwatch.getCompTimeInSeconds();
|
times[run] = stopwatch.getCompTimeInSeconds();
|
||||||
|
|
@ -155,6 +169,16 @@ public class ConcurrentBenchmarker {
|
||||||
return new BenchmarkResult(p, runs, results, times, vehicles);
|
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) {
|
private void print(Collection<BenchmarkResult> results) {
|
||||||
double sumTime=0.0;
|
double sumTime=0.0;
|
||||||
double sumResult=0.0;
|
double sumResult=0.0;
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
|
@ -23,35 +23,39 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
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.apache.log4j.Logger;
|
||||||
import org.jfree.chart.ChartUtilities;
|
import org.jfree.chart.ChartUtilities;
|
||||||
import org.jfree.chart.JFreeChart;
|
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.annotations.XYShapeAnnotation;
|
||||||
import org.jfree.chart.axis.NumberAxis;
|
import org.jfree.chart.axis.NumberAxis;
|
||||||
import org.jfree.chart.labels.XYItemLabelGenerator;
|
import org.jfree.chart.labels.XYItemLabelGenerator;
|
||||||
import org.jfree.chart.plot.XYPlot;
|
import org.jfree.chart.plot.XYPlot;
|
||||||
import org.jfree.chart.renderer.xy.XYItemRenderer;
|
import org.jfree.chart.renderer.xy.XYItemRenderer;
|
||||||
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
|
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
|
||||||
|
import org.jfree.chart.title.LegendTitle;
|
||||||
import org.jfree.data.xy.XYDataItem;
|
import org.jfree.data.xy.XYDataItem;
|
||||||
import org.jfree.data.xy.XYDataset;
|
import org.jfree.data.xy.XYDataset;
|
||||||
import org.jfree.data.xy.XYSeries;
|
import org.jfree.data.xy.XYSeries;
|
||||||
import org.jfree.data.xy.XYSeriesCollection;
|
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 {
|
public class Plotter {
|
||||||
|
|
||||||
|
|
@ -77,10 +81,12 @@ public class Plotter {
|
||||||
|
|
||||||
private VehicleRoutingProblem vrp;
|
private VehicleRoutingProblem vrp;
|
||||||
|
|
||||||
private VehicleRoutingProblemSolution solution;
|
|
||||||
|
|
||||||
private boolean plotSolutionAsWell = false;
|
private boolean plotSolutionAsWell = false;
|
||||||
|
|
||||||
|
private boolean plotShipments = true;
|
||||||
|
|
||||||
|
private Collection<VehicleRoute> routes;
|
||||||
|
|
||||||
public void setShowFirstActivity(boolean show){
|
public void setShowFirstActivity(boolean show){
|
||||||
showFirstActivity = show;
|
showFirstActivity = show;
|
||||||
}
|
}
|
||||||
|
|
@ -97,53 +103,102 @@ public class Plotter {
|
||||||
public Plotter(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution) {
|
public Plotter(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution) {
|
||||||
super();
|
super();
|
||||||
this.vrp = vrp;
|
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;
|
plotSolutionAsWell = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void plot(String pngFileName, String plotTitle){
|
public void plot(String pngFileName, String plotTitle){
|
||||||
|
String filename = pngFileName;
|
||||||
|
if(!pngFileName.endsWith(".png")) filename += ".png";
|
||||||
if(plotSolutionAsWell){
|
if(plotSolutionAsWell){
|
||||||
plotSolutionAsPNG(vrp, solution, pngFileName, plotTitle);
|
plotSolutionAsPNG(vrp, routes, filename, plotTitle);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
plotVrpAsPNG(vrp, pngFileName, plotTitle);
|
plotVrpAsPNG(vrp, filename, plotTitle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void plotVrpAsPNG(VehicleRoutingProblem vrp, String pngFile, String title){
|
private void plotVrpAsPNG(VehicleRoutingProblem vrp, String pngFile, String title){
|
||||||
log.info("plot routes to " + pngFile);
|
log.info("plot routes to " + pngFile);
|
||||||
XYSeriesCollection problem;
|
XYSeriesCollection problem;
|
||||||
|
final XYSeriesCollection shipments;
|
||||||
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
|
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
|
||||||
try {
|
try {
|
||||||
problem = makeVrpSeries(vrp, labels);
|
problem = makeVrpSeries(vrp, labels);
|
||||||
|
shipments = makeShipmentSeries(vrp.getJobs().values(), null);
|
||||||
} catch (NoLocationFoundException e) {
|
} catch (NoLocationFoundException e) {
|
||||||
log.warn("cannot plot vrp, since coord is missing");
|
log.warn("cannot plot vrp, since coord is missing");
|
||||||
return;
|
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);
|
JFreeChart chart = new JFreeChart(title, plot);
|
||||||
|
chart.removeLegend();
|
||||||
|
LegendTitle legend = new LegendTitle(lis);
|
||||||
|
legend.setPosition(RectangleEdge.BOTTOM);
|
||||||
|
chart.addLegend(legend);
|
||||||
save(chart,pngFile);
|
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);
|
log.info("plot solution to " + pngFile);
|
||||||
XYSeriesCollection problem;
|
XYSeriesCollection problem;
|
||||||
XYSeriesCollection solutionColl;
|
XYSeriesCollection solutionColl;
|
||||||
|
final XYSeriesCollection shipments;
|
||||||
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
|
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
|
||||||
try {
|
try {
|
||||||
problem = makeVrpSeries(vrp, labels);
|
problem = makeVrpSeries(vrp, labels);
|
||||||
solutionColl = makeSolutionSeries(vrp, solution);
|
shipments = makeShipmentSeries(vrp.getJobs().values(), null);
|
||||||
|
solutionColl = makeSolutionSeries(vrp, routes);
|
||||||
} catch (NoLocationFoundException e) {
|
} catch (NoLocationFoundException e) {
|
||||||
log.warn("cannot plot vrp, since coord is missing");
|
log.warn("cannot plot vrp, since coord is missing");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
XYPlot plot = createPlot(problem, solutionColl, labels);
|
final XYPlot plot = createProblemSolutionPlot(problem, shipments, solutionColl, labels);
|
||||||
JFreeChart chart = new JFreeChart(title, plot);
|
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);
|
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();
|
XYPlot plot = new XYPlot();
|
||||||
plot.setBackgroundPaint(Color.LIGHT_GRAY);
|
plot.setBackgroundPaint(Color.LIGHT_GRAY);
|
||||||
plot.setRangeGridlinePaint(Color.WHITE);
|
plot.setRangeGridlinePaint(Color.WHITE);
|
||||||
|
|
@ -172,10 +227,25 @@ public class Plotter {
|
||||||
plot.setDomainAxis(0, xAxis);
|
plot.setDomainAxis(0, xAxis);
|
||||||
plot.setRangeAxis(0, yAxis);
|
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;
|
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();
|
XYPlot plot = new XYPlot();
|
||||||
plot.setBackgroundPaint(Color.LIGHT_GRAY);
|
plot.setBackgroundPaint(Color.LIGHT_GRAY);
|
||||||
plot.setRangeGridlinePaint(Color.WHITE);
|
plot.setRangeGridlinePaint(Color.WHITE);
|
||||||
|
|
@ -193,7 +263,6 @@ public class Plotter {
|
||||||
problemRenderer.setBaseItemLabelsVisible(true);
|
problemRenderer.setBaseItemLabelsVisible(true);
|
||||||
problemRenderer.setBaseItemLabelPaint(Color.BLACK);
|
problemRenderer.setBaseItemLabelPaint(Color.BLACK);
|
||||||
|
|
||||||
|
|
||||||
NumberAxis xAxis = new NumberAxis();
|
NumberAxis xAxis = new NumberAxis();
|
||||||
xAxis.setRangeWithMargins(problem.getDomainBounds(true));
|
xAxis.setRangeWithMargins(problem.getDomainBounds(true));
|
||||||
|
|
||||||
|
|
@ -204,8 +273,22 @@ public class Plotter {
|
||||||
plot.setRenderer(0, problemRenderer);
|
plot.setRenderer(0, problemRenderer);
|
||||||
plot.setDomainAxis(0, xAxis);
|
plot.setDomainAxis(0, xAxis);
|
||||||
plot.setRangeAxis(0, yAxis);
|
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
|
XYItemRenderer solutionRenderer = new XYLineAndShapeRenderer(true, false); // Lines only
|
||||||
if(showFirstActivity){
|
if(showFirstActivity){
|
||||||
for(int i=0;i<solutionColl.getSeriesCount();i++){
|
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));
|
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.setDataset(2, solutionColl);
|
||||||
plot.setRenderer(1, solutionRenderer);
|
plot.setRenderer(2, solutionRenderer);
|
||||||
plot.setDomainAxis(1, xAxis);
|
// plot.setDomainAxis(2, xAxis);
|
||||||
plot.setRangeAxis(1, yAxis);
|
// plot.setRangeAxis(2, yAxis);
|
||||||
|
|
||||||
return plot;
|
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);
|
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();
|
XYSeriesCollection coll = new XYSeriesCollection();
|
||||||
int counter = 1;
|
int counter = 1;
|
||||||
for(VehicleRoute route : routes){
|
for(VehicleRoute route : routes){
|
||||||
|
|
@ -281,7 +340,34 @@ public class Plotter {
|
||||||
return coll;
|
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();
|
XYSeriesCollection coll = new XYSeriesCollection();
|
||||||
XYSeries vehicleSeries = new XYSeries("depot", false, true);
|
XYSeries vehicleSeries = new XYSeries("depot", false, true);
|
||||||
for(Vehicle v : vehicles){
|
for(Vehicle v : vehicles){
|
||||||
|
|
@ -294,13 +380,24 @@ public class Plotter {
|
||||||
XYSeries serviceSeries = new XYSeries("service", false, true);
|
XYSeries serviceSeries = new XYSeries("service", false, true);
|
||||||
XYSeries pickupSeries = new XYSeries("pickup", false, true);
|
XYSeries pickupSeries = new XYSeries("pickup", false, true);
|
||||||
XYSeries deliverySeries = new XYSeries("delivery", false, true);
|
XYSeries deliverySeries = new XYSeries("delivery", false, true);
|
||||||
for(Job job : services){
|
for(Job job : jobs){
|
||||||
if(job instanceof Pickup){
|
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;
|
Pickup service = (Pickup)job;
|
||||||
Coordinate coord = service.getCoord();
|
Coordinate coord = service.getCoord();
|
||||||
XYDataItem dataItem = new XYDataItem(coord.getX(), coord.getY());
|
XYDataItem dataItem = new XYDataItem(coord.getX(), coord.getY());
|
||||||
pickupSeries.add(dataItem);
|
pickupSeries.add(dataItem);
|
||||||
addLabel(labels, service, dataItem);
|
addLabel(labels, service, dataItem);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(job instanceof Delivery){
|
else if(job instanceof Delivery){
|
||||||
Delivery service = (Delivery)job;
|
Delivery service = (Delivery)job;
|
||||||
|
|
@ -327,25 +424,15 @@ public class Plotter {
|
||||||
return coll;
|
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)){
|
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)){
|
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{
|
private XYSeriesCollection makeVrpSeries(VehicleRoutingProblem vrp, Map<XYDataItem, String> labels) throws NoLocationFoundException{
|
||||||
return makeVrpSeries(vrp.getVehicles(), vrp.getJobs().values(), labels);
|
return makeVrpSeries(vrp.getVehicles(), vrp.getJobs().values(), labels);
|
||||||
}
|
}
|
||||||
|
|
@ -367,6 +454,22 @@ public class Plotter {
|
||||||
if(coord == null) throw new NoLocationFoundException();
|
if(coord == null) throw new NoLocationFoundException();
|
||||||
locs.put(locationId, coord);
|
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{
|
else{
|
||||||
throw new IllegalStateException("job is not a service. this is not supported yet.");
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -14,11 +14,9 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.Color;
|
||||||
import java.awt.geom.Ellipse2D;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -27,31 +25,29 @@ import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
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.apache.log4j.Logger;
|
||||||
import org.jfree.chart.ChartUtilities;
|
import org.jfree.chart.ChartUtilities;
|
||||||
import org.jfree.chart.JFreeChart;
|
import org.jfree.chart.JFreeChart;
|
||||||
import org.jfree.chart.annotations.XYShapeAnnotation;
|
|
||||||
import org.jfree.chart.axis.NumberAxis;
|
import org.jfree.chart.axis.NumberAxis;
|
||||||
import org.jfree.chart.labels.XYItemLabelGenerator;
|
|
||||||
import org.jfree.chart.plot.XYPlot;
|
import org.jfree.chart.plot.XYPlot;
|
||||||
import org.jfree.chart.renderer.xy.XYItemRenderer;
|
import org.jfree.chart.renderer.xy.XYItemRenderer;
|
||||||
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
|
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
|
||||||
import org.jfree.data.xy.XYDataItem;
|
import org.jfree.data.xy.XYDataItem;
|
||||||
import org.jfree.data.xy.XYDataset;
|
|
||||||
import org.jfree.data.xy.XYSeries;
|
import org.jfree.data.xy.XYSeries;
|
||||||
import org.jfree.data.xy.XYSeriesCollection;
|
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
|
* @see VehicleRoutingProblem, VehicleRoutingProblemSolution
|
||||||
*/
|
*/
|
||||||
public static void plotVrpAsPNG(VehicleRoutingProblem vrp, String pngFile, String title){
|
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;
|
XYSeriesCollection problem;
|
||||||
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
|
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
|
||||||
try {
|
try {
|
||||||
|
|
@ -93,7 +91,7 @@ public class SolutionPlotter {
|
||||||
}
|
}
|
||||||
XYPlot plot = createPlot(problem, labels);
|
XYPlot plot = createPlot(problem, labels);
|
||||||
JFreeChart chart = new JFreeChart(title, plot);
|
JFreeChart chart = new JFreeChart(title, plot);
|
||||||
save(chart,pngFile);
|
save(chart,filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -106,7 +104,9 @@ public class SolutionPlotter {
|
||||||
* @see VehicleRoute
|
* @see VehicleRoute
|
||||||
*/
|
*/
|
||||||
public static void plotRoutesAsPNG(Collection<VehicleRoute> routes, Locations locations, String pngFile, String title) {
|
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;
|
XYSeriesCollection problem;
|
||||||
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
|
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
|
||||||
try {
|
try {
|
||||||
|
|
@ -118,7 +118,7 @@ public class SolutionPlotter {
|
||||||
XYSeriesCollection solutionColl = makeSolutionSeries(routes,locations);
|
XYSeriesCollection solutionColl = makeSolutionSeries(routes,locations);
|
||||||
XYPlot plot = createPlot(problem, solutionColl, labels);
|
XYPlot plot = createPlot(problem, solutionColl, labels);
|
||||||
JFreeChart chart = new JFreeChart(title, plot);
|
JFreeChart chart = new JFreeChart(title, plot);
|
||||||
save(chart,pngFile);
|
save(chart,filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -133,7 +133,9 @@ public class SolutionPlotter {
|
||||||
* @see VehicleRoutingProblem, VehicleRoutingProblemSolution
|
* @see VehicleRoutingProblem, VehicleRoutingProblemSolution
|
||||||
*/
|
*/
|
||||||
public static void plotSolutionAsPNG(VehicleRoutingProblem vrp, VehicleRoutingProblemSolution solution, String pngFile, String title){
|
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 problem;
|
||||||
XYSeriesCollection solutionColl;
|
XYSeriesCollection solutionColl;
|
||||||
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
|
Map<XYDataItem,String> labels = new HashMap<XYDataItem, String>();
|
||||||
|
|
@ -146,7 +148,7 @@ public class SolutionPlotter {
|
||||||
}
|
}
|
||||||
XYPlot plot = createPlot(problem, solutionColl, labels);
|
XYPlot plot = createPlot(problem, solutionColl, labels);
|
||||||
JFreeChart chart = new JFreeChart(title, plot);
|
JFreeChart chart = new JFreeChart(title, plot);
|
||||||
save(chart,pngFile);
|
save(chart,filename);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -14,17 +14,18 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package analysis;
|
package jsprit.analysis.toolbox;
|
||||||
|
|
||||||
import java.util.Collection;
|
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 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{
|
public class StopWatch implements AlgorithmStartsListener, AlgorithmEndsListener{
|
||||||
|
|
||||||
|
|
@ -14,10 +14,12 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package util;
|
package jsprit.analysis.util;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import jsprit.core.util.BenchmarkResult;
|
||||||
|
|
||||||
public interface BenchmarkWriter {
|
public interface BenchmarkWriter {
|
||||||
public void write(Collection<BenchmarkResult> results);
|
public void write(Collection<BenchmarkResult> results);
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -22,6 +22,8 @@ import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import jsprit.core.util.BenchmarkResult;
|
||||||
|
|
||||||
import org.jfree.chart.renderer.xy.DeviationRenderer;
|
import org.jfree.chart.renderer.xy.DeviationRenderer;
|
||||||
|
|
||||||
public class HtmlBenchmarkTableWriter implements BenchmarkWriter{
|
public class HtmlBenchmarkTableWriter implements BenchmarkWriter{
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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); }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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]";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
@ -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;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -14,28 +14,28 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package algorithms;
|
package jsprit.core.algorithm;
|
||||||
|
|
||||||
import java.util.Collection;
|
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.Mean;
|
||||||
import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
|
import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
|
||||||
import org.apache.log4j.Logger;
|
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);
|
private static Logger log = Logger.getLogger(NeighborhoodThresholdInitialiser.class);
|
||||||
|
|
||||||
|
|
@ -14,24 +14,22 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
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{
|
public class RemoveEmptyVehicles implements InsertionEndsListener{
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class);
|
|
||||||
|
|
||||||
private VehicleFleetManager fleetManager;
|
private VehicleFleetManager fleetManager;
|
||||||
|
|
||||||
RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
|
public RemoveEmptyVehicles(VehicleFleetManager fleetManager) {
|
||||||
super();
|
super();
|
||||||
this.fleetManager = fleetManager;
|
this.fleetManager = fleetManager;
|
||||||
}
|
}
|
||||||
|
|
@ -14,24 +14,22 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Collection;
|
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{
|
public class ResetAndIniFleetManager implements InsertionStartsListener{
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(ResetAndIniFleetManager.class);
|
|
||||||
|
|
||||||
private VehicleFleetManager vehicleFleetManager;
|
private VehicleFleetManager vehicleFleetManager;
|
||||||
|
|
||||||
ResetAndIniFleetManager(VehicleFleetManager vehicleFleetManager) {
|
public ResetAndIniFleetManager(VehicleFleetManager vehicleFleetManager) {
|
||||||
super();
|
super();
|
||||||
this.vehicleFleetManager = vehicleFleetManager;
|
this.vehicleFleetManager = vehicleFleetManager;
|
||||||
}
|
}
|
||||||
|
|
@ -41,12 +39,7 @@ class ResetAndIniFleetManager implements InsertionStartsListener{
|
||||||
vehicleFleetManager.unlockAll();
|
vehicleFleetManager.unlockAll();
|
||||||
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
|
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
|
||||||
for(VehicleRoute route : routes){
|
for(VehicleRoute route : routes){
|
||||||
// if(route.isEmpty()){
|
|
||||||
// vehicleRoutes.remove(route);
|
|
||||||
// }
|
|
||||||
// else{
|
|
||||||
vehicleFleetManager.lock(route.getVehicle());
|
vehicleFleetManager.lock(route.getVehicle());
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -14,18 +14,21 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
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 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);
|
VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(lastSolution);
|
||||||
lastSolution = newSolution;
|
lastSolution = newSolution;
|
||||||
}
|
}
|
||||||
solutionCostCalculator.calculateCosts(lastSolution);
|
double costs = solutionCostCalculator.getCosts(lastSolution);
|
||||||
|
lastSolution.setCost(costs);
|
||||||
boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution);
|
boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution);
|
||||||
DiscoveredSolution discoveredSolution = new DiscoveredSolution(lastSolution, solutionAccepted, getName());
|
DiscoveredSolution discoveredSolution = new DiscoveredSolution(lastSolution, solutionAccepted, getName());
|
||||||
return discoveredSolution;
|
return discoveredSolution;
|
||||||
|
|
@ -14,14 +14,17 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
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 {
|
public class SearchStrategyManager {
|
||||||
|
|
@ -14,9 +14,10 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 {
|
public interface SearchStrategyModule {
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -14,26 +14,29 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Collection;
|
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 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}.
|
* Algorithm that solves a {@link VehicleRoutingProblem}.
|
||||||
|
|
@ -43,7 +46,36 @@ import basics.algo.VehicleRoutingAlgorithmListeners;
|
||||||
*/
|
*/
|
||||||
public class VehicleRoutingAlgorithm {
|
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;
|
public static final int NOBREAK = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
|
@ -61,7 +93,7 @@ public class VehicleRoutingAlgorithm {
|
||||||
|
|
||||||
private Collection<VehicleRoutingProblemSolution> initialSolutions;
|
private Collection<VehicleRoutingProblemSolution> initialSolutions;
|
||||||
|
|
||||||
private PrematureAlgorithmBreaker prematureAlgorithmBreaker = new PrematureAlgorithmBreaker() {
|
private PrematureAlgorithmTermination prematureAlgorithmTermination = new PrematureAlgorithmTermination() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
|
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
|
* 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.
|
* the assigned number of iterations without solution-acceptance.
|
||||||
*
|
*
|
||||||
*
|
* @deprecated use setPrematureAlgorithmTermination(new IterationWithoutImprovementTermination(int nuIterationsWithoutImprovement));
|
||||||
* @param nuIterationsWithoutImprovement
|
* @param nuIterationsWithoutImprovement
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setPrematureBreak(int nuIterationsWithoutImprovement){
|
public void setPrematureBreak(int nuIterationsWithoutImprovement){
|
||||||
prematureAlgorithmBreaker = new IterationWithoutImprovementBreaker(nuIterationsWithoutImprovement);
|
prematureAlgorithmTermination = new IterationWithoutImprovementTermination(nuIterationsWithoutImprovement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrematureAlgorithmBreaker(PrematureAlgorithmBreaker prematureAlgorithmBreaker){
|
public void setPrematureAlgorithmTermination(PrematureAlgorithmTermination prematureAlgorithmTermination){
|
||||||
this.prematureAlgorithmBreaker = prematureAlgorithmBreaker;
|
this.prematureAlgorithmTermination = prematureAlgorithmTermination;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -146,7 +179,7 @@ public class VehicleRoutingAlgorithm {
|
||||||
SearchStrategy strategy = searchStrategyManager.getRandomStrategy();
|
SearchStrategy strategy = searchStrategyManager.getRandomStrategy();
|
||||||
DiscoveredSolution discoveredSolution = strategy.run(problem, solutions);
|
DiscoveredSolution discoveredSolution = strategy.run(problem, solutions);
|
||||||
selectedStrategy(strategy.getName(),problem, solutions);
|
selectedStrategy(strategy.getName(),problem, solutions);
|
||||||
if(prematureAlgorithmBreaker.isPrematureBreak(discoveredSolution)){
|
if(prematureAlgorithmTermination.isPrematureBreak(discoveredSolution)){
|
||||||
logger.info("premature break at iteration "+ (i+1));
|
logger.info("premature break at iteration "+ (i+1));
|
||||||
nuOfIterationsThisAlgoIsRunning = (i+1);
|
nuOfIterationsThisAlgoIsRunning = (i+1);
|
||||||
break;
|
break;
|
||||||
|
|
@ -194,6 +227,12 @@ public class VehicleRoutingAlgorithm {
|
||||||
return algoListeners;
|
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) {
|
private void iterationEnds(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||||
algoListeners.iterationEnds(i,problem, solutions);
|
algoListeners.iterationEnds(i,problem, solutions);
|
||||||
}
|
}
|
||||||
|
|
@ -14,10 +14,9 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package basics.algo;
|
package jsprit.core.algorithm;
|
||||||
|
|
||||||
import basics.VehicleRoutingAlgorithm;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblem;
|
|
||||||
|
|
||||||
|
|
||||||
public interface VehicleRoutingAlgorithmFactory {
|
public interface VehicleRoutingAlgorithmFactory {
|
||||||
|
|
@ -14,11 +14,12 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class AcceptNewRemoveFirst implements SolutionAcceptor{
|
public class AcceptNewRemoveFirst implements SolutionAcceptor{
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -14,18 +14,19 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 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;
|
private final int solutionMemory;
|
||||||
|
|
||||||
public AcceptNewIfBetterThanWorst(int solutionMemory){
|
public GreedyAcceptance(int solutionMemory){
|
||||||
this.solutionMemory = solutionMemory;
|
this.solutionMemory = solutionMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,6 +48,12 @@ public class AcceptNewIfBetterThanWorst implements SolutionAcceptor{
|
||||||
if (worstSolution == null) worstSolution = s;
|
if (worstSolution == null) worstSolution = s;
|
||||||
else if (s.getCost() > worstSolution.getCost()) 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()){
|
if(newSolution.getCost() < worstSolution.getCost()){
|
||||||
solutions.remove(worstSolution);
|
solutions.remove(worstSolution);
|
||||||
solutions.add(newSolution);
|
solutions.add(newSolution);
|
||||||
|
|
@ -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]";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -14,25 +14,26 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.net.URL;
|
||||||
import java.util.Collection;
|
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.commons.math.stat.descriptive.moment.StandardDeviation;
|
||||||
import org.apache.log4j.Logger;
|
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;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,11 +14,12 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Acceptor that decides whether the newSolution is accepted or not.
|
* Acceptor that decides whether the newSolution is accepted or not.
|
||||||
|
|
@ -14,15 +14,17 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.net.URL;
|
||||||
|
|
||||||
import util.Resource;
|
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||||
import basics.VehicleRoutingAlgorithm;
|
import jsprit.core.algorithm.io.AlgorithmConfig;
|
||||||
import basics.VehicleRoutingProblem;
|
import jsprit.core.algorithm.io.AlgorithmConfigXmlReader;
|
||||||
import basics.io.AlgorithmConfig;
|
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
|
||||||
import basics.io.AlgorithmConfigXmlReader;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
|
import jsprit.core.util.Resource;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -14,15 +14,17 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.net.URL;
|
||||||
|
|
||||||
import util.Resource;
|
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||||
import basics.VehicleRoutingAlgorithm;
|
import jsprit.core.algorithm.io.AlgorithmConfig;
|
||||||
import basics.VehicleRoutingProblem;
|
import jsprit.core.algorithm.io.AlgorithmConfigXmlReader;
|
||||||
import basics.io.AlgorithmConfig;
|
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
|
||||||
import basics.io.AlgorithmConfigXmlReader;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
|
import jsprit.core.util.Resource;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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;
|
import org.apache.commons.configuration.XMLConfiguration;
|
||||||
|
|
||||||
|
|
@ -14,19 +14,20 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
import jsprit.core.util.Resource;
|
||||||
|
|
||||||
import org.apache.commons.configuration.ConfigurationException;
|
import org.apache.commons.configuration.ConfigurationException;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.xml.sax.EntityResolver;
|
import org.xml.sax.EntityResolver;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import util.Resource;
|
|
||||||
|
|
||||||
public class AlgorithmConfigXmlReader {
|
public class AlgorithmConfigXmlReader {
|
||||||
|
|
||||||
|
|
@ -14,28 +14,32 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
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.commons.configuration.HierarchicalConfiguration;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import algorithms.HardConstraints.ConstraintManager;
|
|
||||||
import basics.VehicleRoutingProblem;
|
|
||||||
import basics.algo.InsertionListener;
|
|
||||||
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
|
||||||
|
|
||||||
class InsertionFactory {
|
class InsertionFactory {
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(InsertionFactory.class);
|
private static Logger log = Logger.getLogger(InsertionFactory.class);
|
||||||
|
|
||||||
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
|
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
|
||||||
VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
|
VehicleFleetManager vehicleFleetManager, StateManager routeStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){
|
||||||
boolean concurrentInsertion = false;
|
|
||||||
if(executorService != null) concurrentInsertion = true;
|
|
||||||
if(config.containsKey("[@name]")){
|
if(config.containsKey("[@name]")){
|
||||||
String insertionName = config.getString("[@name]");
|
String insertionName = config.getString("[@name]");
|
||||||
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
|
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
|
||||||
|
|
@ -45,16 +49,17 @@ class InsertionFactory {
|
||||||
List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
|
List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
|
||||||
List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>();
|
List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>();
|
||||||
|
|
||||||
CalculatorBuilder calcBuilder = new CalculatorBuilder(insertionListeners, algorithmListeners);
|
BestInsertionBuilder iBuilder = new BestInsertionBuilder(vrp, vehicleFleetManager, routeStates, constraintManager);
|
||||||
calcBuilder.setStates(routeStates);
|
|
||||||
calcBuilder.setVehicleRoutingProblem(vrp);
|
if(executorService != null){
|
||||||
calcBuilder.setVehicleFleetManager(vehicleFleetManager);
|
iBuilder.setConcurrentMode(executorService, nuOfThreads);
|
||||||
calcBuilder.setConstraintManager(constraintManager);
|
}
|
||||||
|
|
||||||
if(config.containsKey("level")){
|
if(config.containsKey("level")){
|
||||||
String level = config.getString("level");
|
String level = config.getString("level");
|
||||||
if(level.equals("local")){
|
if(level.equals("local")){
|
||||||
calcBuilder.setLocalLevel();
|
iBuilder.setLocalLevel();
|
||||||
|
// calcBuilder.setLocalLevel();
|
||||||
}
|
}
|
||||||
else if(level.equals("route")){
|
else if(level.equals("route")){
|
||||||
int forwardLooking = 0;
|
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");
|
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);
|
if(mem != null) memory = Integer.parseInt(mem);
|
||||||
else log.warn("parameter route[@memory] is missing. by default it is 1");
|
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 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")){
|
if(config.containsKey("considerFixedCosts") || config.containsKey("considerFixedCost")){
|
||||||
String val = config.getString("considerFixedCosts");
|
String val = config.getString("considerFixedCosts");
|
||||||
|
|
@ -80,35 +86,20 @@ class InsertionFactory {
|
||||||
if(weight == null) weight = config.getString("considerFixedCost[@weight]");
|
if(weight == null) weight = config.getString("considerFixedCost[@weight]");
|
||||||
if(weight != null) fixedCostWeight = Double.parseDouble(weight);
|
if(weight != null) fixedCostWeight = Double.parseDouble(weight);
|
||||||
else log.warn("parameter considerFixedCosts[@weight] is missing. by default, it is 0.5.");
|
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 timeSliceString = config.getString("experimental[@timeSlice]");
|
||||||
String neighbors = config.getString("experimental[@neighboringSlices]");
|
String neighbors = config.getString("experimental[@neighboringSlices]");
|
||||||
if(timeSliceString != null && neighbors != null){
|
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")){
|
if(insertionName.equals("bestInsertion")){
|
||||||
insertionStrategy = new BestInsertion(jic);
|
insertionStrategy = iBuilder.build();
|
||||||
}
|
}
|
||||||
// else if(insertionName.equals("regretInsertion")){
|
else throw new IllegalStateException("currently only 'bestInsertion' is supported");
|
||||||
// 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()));
|
|
||||||
for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l);
|
for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l);
|
||||||
// insertionStrategy.addListener(new FindCheaperVehicle(
|
|
||||||
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));
|
|
||||||
|
|
||||||
algorithmListeners.addAll(algoListeners);
|
algorithmListeners.addAll(algoListeners);
|
||||||
|
|
||||||
|
|
@ -14,9 +14,10 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -26,47 +27,68 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
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.HierarchicalConfiguration;
|
||||||
import org.apache.commons.configuration.XMLConfiguration;
|
import org.apache.commons.configuration.XMLConfiguration;
|
||||||
import org.apache.log4j.Logger;
|
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}
|
* @return {@link VehicleRoutingAlgorithm}
|
||||||
*/
|
*/
|
||||||
public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp, final AlgorithmConfig algorithmConfig){
|
public static VehicleRoutingAlgorithm createAlgorithm(final VehicleRoutingProblem vrp, final AlgorithmConfig algorithmConfig){
|
||||||
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),null,0);
|
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(final VehicleRoutingProblem vrp, final XMLConfiguration config){
|
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();
|
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||||
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
|
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
|
||||||
xmlReader.read(configURL);
|
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();
|
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||||
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
|
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
|
||||||
xmlReader.read(configFileName);
|
xmlReader.read(configFileName);
|
||||||
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),null, 0);
|
return createAlgo(vrp,algorithmConfig.getXMLConfiguration(),0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static VehicleRoutingAlgorithm readAndCreateAlgorithm(VehicleRoutingProblem vrp, int nThreads, String configFileName) {
|
||||||
* 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){
|
|
||||||
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
AlgorithmConfig algorithmConfig = new AlgorithmConfig();
|
||||||
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
|
AlgorithmConfigXmlReader xmlReader = new AlgorithmConfigXmlReader(algorithmConfig);
|
||||||
xmlReader.read(configFileName);
|
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
|
// map to store constructed modules
|
||||||
TypedMap definedClasses = new TypedMap();
|
TypedMap definedClasses = new TypedMap();
|
||||||
|
|
@ -433,27 +447,54 @@ public class VehicleRoutingAlgorithms {
|
||||||
// insertion listeners
|
// insertion listeners
|
||||||
List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
|
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
|
//create fleetmanager
|
||||||
final VehicleFleetManager vehicleFleetManager = createFleetManager(vrp);
|
final VehicleFleetManager vehicleFleetManager = createFleetManager(vrp);
|
||||||
|
|
||||||
//create state-manager
|
//create state-manager
|
||||||
final StateManagerImpl stateManager = new StateManagerImpl();
|
final StateManager stateManager = new StateManager(vrp);
|
||||||
|
stateManager.updateLoadStates();
|
||||||
|
stateManager.updateTimeWindowStates();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* define constraints
|
* define constraints
|
||||||
*/
|
*/
|
||||||
//constraint manager
|
//constraint manager
|
||||||
ConstraintManager constraintManager = new ConstraintManager();
|
ConstraintManager constraintManager = new ConstraintManager(vrp,stateManager);
|
||||||
constraintManager.addConstraint(new HardConstraints.HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts()));
|
constraintManager.addTimeWindowConstraint();
|
||||||
|
constraintManager.addLoadConstraint();
|
||||||
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));
|
|
||||||
|
|
||||||
//construct initial solution creator
|
//construct initial solution creator
|
||||||
AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,constraintManager);
|
AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,constraintManager);
|
||||||
|
|
@ -490,32 +531,26 @@ public class VehicleRoutingAlgorithms {
|
||||||
/*
|
/*
|
||||||
* define stateUpdates
|
* 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
|
// stateManager.addActivityVisitor(new UpdateOccuredDeliveries(stateManager));
|
||||||
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new StateUpdates.ResetStateManager(stateManager)));
|
// stateManager.addActivityVisitor(new TimeWindowUpdater(stateManager, vrp.getTransportCosts()));
|
||||||
//update states
|
// stateManager.addActivityVisitor(new UpdateFuturePickups(stateManager));
|
||||||
// metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateStates(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts()));
|
|
||||||
StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged routeChangedListener = new StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged(vrp.getTransportCosts());
|
|
||||||
|
|
||||||
routeChangedListener.addInsertionStartsListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager));
|
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(stateManager);
|
||||||
routeChangedListener.addJobInsertedListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(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 RemoveEmptyVehicles(vehicleFleetManager));
|
||||||
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new ResetAndIniFleetManager(vehicleFleetManager));
|
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new ResetAndIniFleetManager(vehicleFleetManager));
|
||||||
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager));
|
metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager));
|
||||||
|
|
||||||
//define prematureBreak
|
//define prematureBreak
|
||||||
PrematureAlgorithmBreaker prematureAlgoBreaker = getPrematureBreaker(config,algorithmListeners);
|
PrematureAlgorithmTermination prematureAlgoBreaker = getPrematureBreaker(config,algorithmListeners);
|
||||||
metaAlgorithm.setPrematureAlgorithmBreaker(prematureAlgoBreaker);
|
metaAlgorithm.setPrematureAlgorithmTermination(prematureAlgoBreaker);
|
||||||
|
|
||||||
//misc
|
//misc
|
||||||
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
|
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new SolutionVerifier()));
|
||||||
|
|
@ -526,16 +561,16 @@ public class VehicleRoutingAlgorithms {
|
||||||
return metaAlgorithm;
|
return metaAlgorithm;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SolutionCostCalculator getCostCalculator(final StateManagerImpl stateManager) {
|
private static SolutionCostCalculator getCostCalculator(final StateManager stateManager) {
|
||||||
SolutionCostCalculator calc = new SolutionCostCalculator() {
|
SolutionCostCalculator calc = new SolutionCostCalculator() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void calculateCosts(VehicleRoutingProblemSolution solution) {
|
public double getCosts(VehicleRoutingProblemSolution solution) {
|
||||||
double costs = 0.0;
|
double costs = 0.0;
|
||||||
for(VehicleRoute route : solution.getRoutes()){
|
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) {
|
private double getFixedCosts(Vehicle vehicle) {
|
||||||
|
|
@ -549,21 +584,21 @@ public class VehicleRoutingAlgorithms {
|
||||||
|
|
||||||
private static VehicleFleetManager createFleetManager(final VehicleRoutingProblem vrp) {
|
private static VehicleFleetManager createFleetManager(final VehicleRoutingProblem vrp) {
|
||||||
if(vrp.getFleetSize().equals(FleetSize.INFINITE)){
|
if(vrp.getFleetSize().equals(FleetSize.INFINITE)){
|
||||||
return new InfiniteVehicles(vrp.getVehicles());
|
return new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager();
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(vrp.getFleetSize().equals(FleetSize.FINITE)){
|
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. " +
|
throw new IllegalStateException("fleet size can only be infinite or finite. " +
|
||||||
"makes sure your config file contains one of these options");
|
"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]");
|
String basedOn = config.getString("prematureBreak[@basedOn]");
|
||||||
if(basedOn == null){
|
if(basedOn == null){
|
||||||
log.info("set default prematureBreak, i.e. no premature break at all.");
|
log.info("set default prematureBreak, i.e. no premature break at all.");
|
||||||
return new PrematureAlgorithmBreaker() {
|
return new PrematureAlgorithmTermination() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
|
public boolean isPrematureBreak(DiscoveredSolution discoveredSolution) {
|
||||||
|
|
@ -576,14 +611,14 @@ public class VehicleRoutingAlgorithms {
|
||||||
String iter = config.getString("prematureBreak.iterations");
|
String iter = config.getString("prematureBreak.iterations");
|
||||||
if(iter == null) throw new IllegalStateException("prematureBreak.iterations is missing");
|
if(iter == null) throw new IllegalStateException("prematureBreak.iterations is missing");
|
||||||
int iterations = Integer.valueOf(iter);
|
int iterations = Integer.valueOf(iter);
|
||||||
return new IterationWithoutImprovementBreaker(iterations);
|
return new IterationWithoutImprovementTermination(iterations);
|
||||||
}
|
}
|
||||||
if(basedOn.equals("time")){
|
if(basedOn.equals("time")){
|
||||||
log.info("set prematureBreak based on time");
|
log.info("set prematureBreak based on time");
|
||||||
String timeString = config.getString("prematureBreak.time");
|
String timeString = config.getString("prematureBreak.time");
|
||||||
if(timeString == null) throw new IllegalStateException("prematureBreak.time is missing");
|
if(timeString == null) throw new IllegalStateException("prematureBreak.time is missing");
|
||||||
double time = Double.valueOf(timeString);
|
double time = Double.valueOf(timeString);
|
||||||
TimeBreaker timeBreaker = new TimeBreaker(time);
|
TimeTermination timeBreaker = new TimeTermination(time);
|
||||||
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, timeBreaker));
|
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, timeBreaker));
|
||||||
return timeBreaker;
|
return timeBreaker;
|
||||||
}
|
}
|
||||||
|
|
@ -595,7 +630,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
if(iterationsString == null) throw new IllegalStateException("prematureBreak.iterations is missing");
|
if(iterationsString == null) throw new IllegalStateException("prematureBreak.iterations is missing");
|
||||||
double threshold = Double.valueOf(thresholdString);
|
double threshold = Double.valueOf(thresholdString);
|
||||||
int iterations = Integer.valueOf(iterationsString);
|
int iterations = Integer.valueOf(iterationsString);
|
||||||
VariationCoefficientBreaker variationCoefficientBreaker = new VariationCoefficientBreaker(iterations, threshold);
|
VariationCoefficientTermination variationCoefficientBreaker = new VariationCoefficientTermination(iterations, threshold);
|
||||||
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, variationCoefficientBreaker));
|
algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, variationCoefficientBreaker));
|
||||||
return variationCoefficientBreaker;
|
return variationCoefficientBreaker;
|
||||||
}
|
}
|
||||||
|
|
@ -626,7 +661,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners);
|
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");
|
List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
|
||||||
if(modConfigs == null) return null;
|
if(modConfigs == null) return null;
|
||||||
if(modConfigs.isEmpty()) return null;
|
if(modConfigs.isEmpty()) return null;
|
||||||
|
|
@ -651,9 +686,11 @@ public class VehicleRoutingAlgorithms {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||||
CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy, getCostCalculator(routeStates));
|
InsertionInitialSolutionFactory insertionInitialSolutionFactory = new InsertionInitialSolutionFactory(finalInsertionStrategy, getCostCalculator(routeStates));
|
||||||
createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false);
|
// CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy, getCostCalculator(routeStates));
|
||||||
VehicleRoutingProblemSolution vrpSol = createInitialSolution.createInitialSolution(vrp);
|
//
|
||||||
|
// createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false);
|
||||||
|
VehicleRoutingProblemSolution vrpSol = insertionInitialSolutionFactory.createSolution(vrp);
|
||||||
solutions.add(vrpSol);
|
solutions.add(vrpSol);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -698,7 +735,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
SolutionAcceptor definedAcceptor = typedMap.get(acceptorKey);
|
SolutionAcceptor definedAcceptor = typedMap.get(acceptorKey);
|
||||||
if(definedAcceptor != null) return definedAcceptor;
|
if(definedAcceptor != null) return definedAcceptor;
|
||||||
if(acceptorName.equals("acceptNewRemoveWorst")){
|
if(acceptorName.equals("acceptNewRemoveWorst")){
|
||||||
AcceptNewIfBetterThanWorst acceptor = new AcceptNewIfBetterThanWorst(solutionMemory);
|
GreedyAcceptance acceptor = new GreedyAcceptance(solutionMemory);
|
||||||
typedMap.put(acceptorKey, acceptor);
|
typedMap.put(acceptorKey, acceptor);
|
||||||
return acceptor;
|
return acceptor;
|
||||||
}
|
}
|
||||||
|
|
@ -707,6 +744,16 @@ public class VehicleRoutingAlgorithms {
|
||||||
typedMap.put(acceptorKey, acceptor);
|
typedMap.put(acceptorKey, acceptor);
|
||||||
return 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")){
|
if(acceptorName.equals("schrimpfAcceptance")){
|
||||||
int iterOfSchrimpf = strategyConfig.getInt("acceptor.warmup");
|
int iterOfSchrimpf = strategyConfig.getInt("acceptor.warmup");
|
||||||
double alpha = strategyConfig.getDouble("acceptor.alpha");
|
double alpha = strategyConfig.getDouble("acceptor.alpha");
|
||||||
|
|
@ -715,13 +762,21 @@ public class VehicleRoutingAlgorithms {
|
||||||
typedMap.put(acceptorKey, schrimpf);
|
typedMap.put(acceptorKey, schrimpf);
|
||||||
return 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{
|
else{
|
||||||
throw new IllegalStateException("solution acceptor " + acceptorName + " is not known");
|
throw new IllegalStateException("solution acceptor " + acceptorName + " is not known");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager,
|
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]");
|
String moduleName = moduleConfig.getString("[@name]");
|
||||||
if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
|
if(moduleName == null) throw new IllegalStateException("module(-name) is missing.");
|
||||||
String moduleId = moduleConfig.getString("[@id]");
|
String moduleId = moduleConfig.getString("[@id]");
|
||||||
|
|
@ -746,15 +801,15 @@ public class VehicleRoutingAlgorithms {
|
||||||
}
|
}
|
||||||
else if(ruin_name.equals("radialRuin")){
|
else if(ruin_name.equals("radialRuin")){
|
||||||
String ruin_distance = moduleConfig.getString("ruin.distance");
|
String ruin_distance = moduleConfig.getString("ruin.distance");
|
||||||
JobDistance jobDistance;
|
JobDistance jobDistance = new AvgServiceAndShipmentDistance(vrp.getTransportCosts());
|
||||||
if(ruin_distance == null) jobDistance = new JobDistanceAvgCosts(vrp.getTransportCosts());
|
// if(ruin_distance == null) jobDistance
|
||||||
else {
|
// else {
|
||||||
if(ruin_distance.equals("euclidean")){
|
// if(ruin_distance.equals("euclidean")){
|
||||||
jobDistance = new EuclideanServiceDistance();
|
// jobDistance = new EuclideanServiceDistance();
|
||||||
}
|
// }
|
||||||
else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
|
// else throw new IllegalStateException("does not know ruin.distance " + ruin_distance + ". either ommit ruin.distance then the "
|
||||||
+ "default is used or use 'euclidean'");
|
// + "default is used or use 'euclidean'");
|
||||||
}
|
// }
|
||||||
ruin = getRadialRuin(vrp, routeStates, definedClasses, ruinKey, shareToRuin, jobDistance);
|
ruin = getRadialRuin(vrp, routeStates, definedClasses, ruinKey, shareToRuin, jobDistance);
|
||||||
}
|
}
|
||||||
else throw new IllegalStateException("ruin[@name] " + ruin_name + " is not known. Use either randomRuin or radialRuin.");
|
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;
|
return rrModule;
|
||||||
}
|
}
|
||||||
if(moduleName.equals("gendreau")){
|
if(moduleName.equals("gendreau")){
|
||||||
int iterations = moduleConfig.getInt("iterations");
|
throw new UnsupportedOperationException("gendreau is not supported yet");
|
||||||
double share = moduleConfig.getDouble("share");
|
// int iterations = moduleConfig.getInt("iterations");
|
||||||
String ruinName = moduleConfig.getString("ruin[@name]");
|
// double share = moduleConfig.getDouble("share");
|
||||||
if(ruinName == null) throw new IllegalStateException("gendreau.ruin[@name] is missing. set it to \"radialRuin\" or \"randomRuin\"");
|
// String ruinName = moduleConfig.getString("ruin[@name]");
|
||||||
String ruinId = moduleConfig.getString("ruin[@id]");
|
// if(ruinName == null) throw new IllegalStateException("gendreau.ruin[@name] is missing. set it to \"radialRuin\" or \"randomRuin\"");
|
||||||
if(ruinId == null) ruinId = "noId";
|
// String ruinId = moduleConfig.getString("ruin[@id]");
|
||||||
ModKey ruinKey = makeKey(ruinName,ruinId);
|
// if(ruinId == null) ruinId = "noId";
|
||||||
RuinStrategyKey stratKey = new RuinStrategyKey(ruinKey);
|
// ModKey ruinKey = makeKey(ruinName,ruinId);
|
||||||
RuinStrategy ruin = definedClasses.get(stratKey);
|
// RuinStrategyKey stratKey = new RuinStrategyKey(ruinKey);
|
||||||
if(ruin == null){
|
// RuinStrategy ruin = definedClasses.get(stratKey);
|
||||||
ruin = new RuinRadial(vrp, 0.3, new JobDistanceAvgCosts(vrp.getTransportCosts()));
|
// if(ruin == null){
|
||||||
definedClasses.put(stratKey, ruin);
|
// 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 insertionName = moduleConfig.getString("insertion[@name]");
|
||||||
String insertionId = moduleConfig.getString("insertion[@id]");
|
// if(insertionName == null) throw new IllegalStateException("gendreau.insertion[@name] is missing. set it to \"regretInsertion\" or \"bestInsertion\"");
|
||||||
if(insertionId == null) insertionId = "noId";
|
// String insertionId = moduleConfig.getString("insertion[@id]");
|
||||||
ModKey insertionKey = makeKey(insertionName,insertionId);
|
// if(insertionId == null) insertionId = "noId";
|
||||||
InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
|
// ModKey insertionKey = makeKey(insertionName,insertionId);
|
||||||
InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
|
// InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
|
||||||
if(insertion == null){
|
// InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
|
||||||
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
|
// if(insertion == null){
|
||||||
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
|
// List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
|
||||||
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
|
// if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
|
||||||
insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, routeStates, prioListeners, executorService, nuOfThreads, constraintManager);
|
// List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
|
||||||
algorithmListeners.addAll(prioListeners);
|
// 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 gendreau = new Gendreau(vrp, ruin, insertion, vehicleFleetManager);
|
||||||
gendreau.setNuOfIterations(iterations);
|
// gendreau.setShareOfJobsToRuin(share);
|
||||||
gendreau.setFleetManager(vehicleFleetManager);
|
// gendreau.setNuOfIterations(iterations);
|
||||||
definedClasses.put(strategyModuleKey, gendreau);
|
// definedClasses.put(strategyModuleKey, gendreau);
|
||||||
return gendreau;
|
// return gendreau;
|
||||||
}
|
}
|
||||||
throw new NullPointerException("no module found with moduleName=" + moduleName +
|
throw new NullPointerException("no module found with moduleName=" + moduleName +
|
||||||
"\n\tcheck config whether the correct names are used" +
|
"\n\tcheck config whether the correct names are used" +
|
||||||
|
|
@ -823,30 +878,32 @@ public class VehicleRoutingAlgorithms {
|
||||||
"\n\tgendreauPostOpt");
|
"\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);
|
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
|
||||||
RuinStrategy ruin = definedClasses.get(stratKey);
|
RuinStrategy ruin = definedClasses.get(stratKey);
|
||||||
if(ruin == null){
|
if(ruin == null){
|
||||||
ruin = new RuinRadial(vrp, shareToRuin, jobDistance);
|
ruin = new RadialRuinStrategyFactory(shareToRuin, jobDistance).createStrategy(vrp);
|
||||||
definedClasses.put(stratKey, ruin);
|
definedClasses.put(stratKey, ruin);
|
||||||
}
|
}
|
||||||
return 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);
|
RuinStrategyKey stratKey = new RuinStrategyKey(modKey);
|
||||||
RuinStrategy ruin = definedClasses.get(stratKey);
|
RuinStrategy ruin = definedClasses.get(stratKey);
|
||||||
if(ruin == null){
|
if(ruin == null){
|
||||||
ruin = new RuinRandom(vrp, shareToRuin);
|
ruin = new RandomRuinStrategyFactory(shareToRuin).createStrategy(vrp);
|
||||||
definedClasses.put(stratKey, ruin);
|
definedClasses.put(stratKey, ruin);
|
||||||
}
|
}
|
||||||
return 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);
|
InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads, constraintManager);
|
||||||
return insertion;
|
return insertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -14,12 +14,13 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import basics.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,13 +14,14 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import basics.VehicleRoutingAlgorithm;
|
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||||
import basics.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,12 +14,13 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import basics.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,12 +14,13 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import basics.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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{
|
public interface SearchStrategyListener extends VehicleRoutingAlgorithmListener{
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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{
|
public interface SearchStrategyModuleListener extends VehicleRoutingAlgorithmListener{
|
||||||
|
|
||||||
|
|
@ -14,12 +14,13 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import basics.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package basics.algo;
|
package jsprit.core.algorithm.listener;
|
||||||
|
|
||||||
public interface VehicleRoutingAlgorithmListener {
|
public interface VehicleRoutingAlgorithmListener {
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -23,9 +23,10 @@ import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import basics.VehicleRoutingAlgorithm;
|
import jsprit.core.algorithm.VehicleRoutingAlgorithm;
|
||||||
import basics.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
@ -14,18 +14,21 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import algorithms.RuinStrategy.RuinListener;
|
import jsprit.core.algorithm.SearchStrategyModule;
|
||||||
import basics.Job;
|
import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import jsprit.core.algorithm.recreate.InsertionStrategy;
|
||||||
import basics.algo.InsertionListener;
|
import jsprit.core.algorithm.recreate.listener.InsertionListener;
|
||||||
import basics.algo.SearchStrategyModule;
|
import jsprit.core.algorithm.ruin.RuinStrategy;
|
||||||
import basics.algo.SearchStrategyModuleListener;
|
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;
|
private InsertionStrategy insertion;
|
||||||
|
|
||||||
|
|
@ -44,9 +47,8 @@ class RuinAndRecreateModule implements SearchStrategyModule{
|
||||||
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
|
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
|
||||||
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
|
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
|
||||||
insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs);
|
insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs);
|
||||||
// double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
|
|
||||||
// vrpSolution.setCost(totalCost);
|
|
||||||
return vrpSolution;
|
return vrpSolution;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -18,13 +18,14 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Stefan Schroeder - initial API and implementation
|
* 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 additionalCosts;
|
||||||
private double additionalTime;
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -14,16 +14,17 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import basics.costs.VehicleRoutingActivityCosts;
|
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
import basics.route.Driver;
|
import jsprit.core.problem.driver.Driver;
|
||||||
import basics.route.TourActivity;
|
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||||
import basics.route.Vehicle;
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
final class AuxilliaryCostCalculator {
|
final class AuxilliaryCostCalculator {
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
@ -22,15 +22,17 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
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 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{
|
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 static Logger logger = Logger.getLogger(BestInsertion.class);
|
||||||
|
|
||||||
private Random random = RandomNumberGeneration.getRandom();
|
private Random random = RandomNumberGeneration.getRandom();
|
||||||
|
|
@ -56,7 +80,7 @@ final class BestInsertion implements InsertionStrategy{
|
||||||
|
|
||||||
private Inserter inserter;
|
private Inserter inserter;
|
||||||
|
|
||||||
private JobInsertionCalculator bestInsertionCostCalculator;
|
private JobInsertionCostsCalculator bestInsertionCostCalculator;
|
||||||
|
|
||||||
private boolean minVehiclesFirst = false;
|
private boolean minVehiclesFirst = false;
|
||||||
|
|
||||||
|
|
@ -64,7 +88,7 @@ final class BestInsertion implements InsertionStrategy{
|
||||||
this.random = random;
|
this.random = random;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BestInsertion(JobInsertionCalculator jobInsertionCalculator) {
|
public BestInsertion(JobInsertionCostsCalculator jobInsertionCalculator) {
|
||||||
super();
|
super();
|
||||||
this.insertionsListeners = new InsertionListeners();
|
this.insertionsListeners = new InsertionListeners();
|
||||||
inserter = new Inserter(insertionsListeners);
|
inserter = new Inserter(insertionsListeners);
|
||||||
|
|
@ -86,7 +110,7 @@ final class BestInsertion implements InsertionStrategy{
|
||||||
Insertion bestInsertion = null;
|
Insertion bestInsertion = null;
|
||||||
double bestInsertionCost = Double.MAX_VALUE;
|
double bestInsertionCost = Double.MAX_VALUE;
|
||||||
for(VehicleRoute vehicleRoute : vehicleRoutes){
|
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) {
|
if(iData instanceof NoInsertionFound) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +121,7 @@ final class BestInsertion implements InsertionStrategy{
|
||||||
}
|
}
|
||||||
if(!minVehiclesFirst){
|
if(!minVehiclesFirst){
|
||||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
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){
|
if(newIData.getInsertionCost() < bestInsertionCost){
|
||||||
bestInsertion = new Insertion(newRoute,newIData);
|
bestInsertion = new Insertion(newRoute,newIData);
|
||||||
bestInsertionCost = newIData.getInsertionCost();
|
bestInsertionCost = newIData.getInsertionCost();
|
||||||
|
|
@ -106,7 +130,7 @@ final class BestInsertion implements InsertionStrategy{
|
||||||
}
|
}
|
||||||
if(bestInsertion == null){
|
if(bestInsertion == null){
|
||||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
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){
|
if(bestI instanceof InsertionData.NoInsertionFound){
|
||||||
throw new IllegalStateException(getErrorMsg(unassignedJob));
|
throw new IllegalStateException(getErrorMsg(unassignedJob));
|
||||||
}
|
}
|
||||||
|
|
@ -115,9 +139,8 @@ final class BestInsertion implements InsertionStrategy{
|
||||||
vehicleRoutes.add(newRoute);
|
vehicleRoutes.add(newRoute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// logger.info("insert " + unassignedJob + " pickup@" + bestInsertion.getInsertionData().getPickupInsertionIndex() + " delivery@" + bestInsertion.getInsertionData().getDeliveryInsertionIndex());
|
||||||
inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||||
|
|
||||||
}
|
}
|
||||||
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
|
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -14,30 +14,27 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
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 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.
|
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator{
|
||||||
*
|
|
||||||
* @author schroeder
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalculator{
|
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(CalculatesServiceInsertionWithTimeScheduling.class);
|
private static Logger log = Logger.getLogger(CalculatesServiceInsertionWithTimeScheduling.class);
|
||||||
|
|
||||||
private JobInsertionCalculator jic;
|
private JobInsertionCostsCalculator jic;
|
||||||
|
|
||||||
private Random random = new Random();
|
private Random random = new Random();
|
||||||
|
|
||||||
|
|
@ -45,7 +42,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
|
||||||
|
|
||||||
private double timeSlice = 900.0;
|
private double timeSlice = 900.0;
|
||||||
|
|
||||||
public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCalculator jic, double timeSlice, int neighbors) {
|
public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCostsCalculator jic, double timeSlice, int neighbors) {
|
||||||
super();
|
super();
|
||||||
this.jic = jic;
|
this.jic = jic;
|
||||||
this.timeSlice = timeSlice;
|
this.timeSlice = timeSlice;
|
||||||
|
|
@ -59,7 +56,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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>();
|
List<Double> vehicleDepartureTimes = new ArrayList<Double>();
|
||||||
double currentStart;
|
double currentStart;
|
||||||
if(currentRoute.getStart() == null){
|
if(currentRoute.getStart() == null){
|
||||||
|
|
@ -84,7 +81,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul
|
||||||
|
|
||||||
InsertionData bestIData = null;
|
InsertionData bestIData = null;
|
||||||
for(Double departureTime : vehicleDepartureTimes){
|
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;
|
if(bestIData == null) bestIData = iData;
|
||||||
else if(iData.getInsertionCost() < bestIData.getInsertionCost()){
|
else if(iData.getInsertionCost() < bestIData.getInsertionCost()){
|
||||||
iData.setVehicleDepartureTime(departureTime);
|
iData.setVehicleDepartureTime(departureTime);
|
||||||
|
|
@ -14,15 +14,23 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import algorithms.HardConstraints.ConstraintManager;
|
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
||||||
import basics.VehicleRoutingProblem;
|
import jsprit.core.algorithm.recreate.listener.InsertionListener;
|
||||||
import basics.algo.InsertionListener;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
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 static class CalculatorPlusListeners {
|
||||||
|
|
||||||
private JobInsertionCalculator calculator;
|
private JobInsertionCostsCalculator calculator;
|
||||||
|
|
||||||
public JobInsertionCalculator getCalculator() {
|
public JobInsertionCostsCalculator getCalculator() {
|
||||||
return calculator;
|
return calculator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PrioritizedVRAListener> algorithmListener = new ArrayList<PrioritizedVRAListener>();
|
private List<PrioritizedVRAListener> algorithmListener = new ArrayList<PrioritizedVRAListener>();
|
||||||
private List<InsertionListener> insertionListener = new ArrayList<InsertionListener>();
|
private List<InsertionListener> insertionListener = new ArrayList<InsertionListener>();
|
||||||
|
|
||||||
public CalculatorPlusListeners(JobInsertionCalculator calculator) {
|
public CalculatorPlusListeners(JobInsertionCostsCalculator calculator) {
|
||||||
super();
|
super();
|
||||||
this.calculator = calculator;
|
this.calculator = calculator;
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +67,7 @@ class CalculatorBuilder {
|
||||||
|
|
||||||
private VehicleRoutingProblem vrp;
|
private VehicleRoutingProblem vrp;
|
||||||
|
|
||||||
private StateManager states;
|
private RouteAndActivityStateGetter states;
|
||||||
|
|
||||||
private boolean local = true;
|
private boolean local = true;
|
||||||
|
|
||||||
|
|
@ -81,6 +89,8 @@ class CalculatorBuilder {
|
||||||
|
|
||||||
private ConstraintManager constraintManager;
|
private ConstraintManager constraintManager;
|
||||||
|
|
||||||
|
private ActivityInsertionCostsCalculator activityInsertionCostCalculator = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the builder.
|
* Constructs the builder.
|
||||||
*
|
*
|
||||||
|
|
@ -102,7 +112,7 @@ class CalculatorBuilder {
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public CalculatorBuilder setStates(StateManager states){
|
public CalculatorBuilder setStates(RouteAndActivityStateGetter states){
|
||||||
this.states = states;
|
this.states = states;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
@ -138,6 +148,10 @@ class CalculatorBuilder {
|
||||||
local = true;
|
local = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setActivityInsertionCostsCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){
|
||||||
|
this.activityInsertionCostCalculator = activityInsertionCostsCalculator;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a flag to build a calculator that evaluates job insertion on route-level.
|
* Sets a flag to build a calculator that evaluates job insertion on route-level.
|
||||||
*
|
*
|
||||||
|
|
@ -173,16 +187,17 @@ class CalculatorBuilder {
|
||||||
* @return jobInsertionCalculator.
|
* @return jobInsertionCalculator.
|
||||||
* @throws IllegalStateException if vrp == null or activityStates == null or fleetManager == null.
|
* @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(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(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))");
|
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;
|
CalculatorPlusListeners standardLocal = null;
|
||||||
if(local){
|
if(local){
|
||||||
standardLocal = createStandardLocal(vrp, states);
|
standardLocal = createStandardLocal(vrp, states);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
checkServicesOnly();
|
||||||
standardLocal = createStandardRoute(vrp, states,forwardLooking,memory);
|
standardLocal = createStandardRoute(vrp, states,forwardLooking,memory);
|
||||||
}
|
}
|
||||||
baseCalculator = standardLocal.getCalculator();
|
baseCalculator = standardLocal.getCalculator();
|
||||||
|
|
@ -200,6 +215,17 @@ class CalculatorBuilder {
|
||||||
return createFinalInsertion(fleetManager, baseCalculator, states);
|
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) {
|
private void addInsertionListeners(List<InsertionListener> list) {
|
||||||
for(InsertionListener iL : list){
|
for(InsertionListener iL : list){
|
||||||
insertionListeners.add(iL);
|
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");
|
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());
|
ActivityInsertionCostsCalculator actInsertionCalc;
|
||||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion);
|
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;
|
return calcPlusListeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, StateManager activityStates2, double weightOfFixedCosts){
|
private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCostsCalculator baseCalculator, RouteAndActivityStateGetter activityStates2, double weightOfFixedCosts){
|
||||||
final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates2);
|
final JobInsertionConsideringFixCostsCalculator withFixCost = new JobInsertionConsideringFixCostsCalculator(baseCalculator, activityStates2);
|
||||||
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
|
withFixCost.setWeightOfFixCost(weightOfFixedCosts);
|
||||||
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
|
CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost);
|
||||||
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
|
calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost));
|
||||||
return calcPlusListeners;
|
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;
|
int after = forwardLooking;
|
||||||
ActivityInsertionCostsCalculator routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, activityStates2);
|
ActivityInsertionCostsCalculator routeLevelCostEstimator;
|
||||||
JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, routeLevelCostEstimator);
|
if(activityInsertionCostCalculator == null){
|
||||||
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNuOfActsForwardLooking(after);
|
routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityStates2);
|
||||||
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setMemorySize(solutionMemory);
|
}
|
||||||
((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood());
|
else{
|
||||||
((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setStates(activityStates2);
|
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);
|
CalculatorPlusListeners calcPlusListener = new CalculatorPlusListeners(jobInsertionCalculator);
|
||||||
return calcPlusListener;
|
return calcPlusListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JobInsertionCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCalculator baseCalc, StateManager activityStates2){
|
private JobInsertionCostsCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCostsCalculator baseCalc, RouteAndActivityStateGetter activityStates2){
|
||||||
return new CalculatesVehTypeDepServiceInsertion(fleetManager, baseCalc);
|
return new VehicleTypeDependentJobInsertionCalculator(fleetManager, baseCalc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConstraintManager(ConstraintManager constraintManager) {
|
public void setConstraintManager(ConstraintManager constraintManager) {
|
||||||
|
|
@ -14,18 +14,19 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 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 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;
|
VehicleRoutingProblem vrp;
|
||||||
|
|
||||||
CalculatesServiceInsertionConsideringFixCost calcConsideringFix;
|
JobInsertionConsideringFixCostsCalculator calcConsideringFix;
|
||||||
|
|
||||||
private int nuOfJobsToRecreate;
|
private int nuOfJobsToRecreate;
|
||||||
|
|
||||||
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, CalculatesServiceInsertionConsideringFixCost calcConsideringFix) {
|
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, JobInsertionConsideringFixCostsCalculator calcConsideringFix) {
|
||||||
super();
|
super();
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
this.calcConsideringFix = calcConsideringFix;
|
this.calcConsideringFix = calcConsideringFix;
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,14 +14,19 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 jsprit.core.problem.driver.Driver;
|
||||||
import basics.route.Vehicle;
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data object that collects insertion information. It collects insertionCosts, insertionIndeces, vehicle and driver to be employed
|
||||||
class InsertionData {
|
* and departureTime of vehicle at vehicle's start location (e.g. depot).
|
||||||
|
*
|
||||||
|
* @author stefan
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class InsertionData {
|
||||||
|
|
||||||
static class NoInsertionFound extends InsertionData{
|
static class NoInsertionFound extends InsertionData{
|
||||||
|
|
||||||
|
|
@ -33,7 +38,15 @@ class InsertionData {
|
||||||
|
|
||||||
private static InsertionData noInsertion = new NoInsertionFound();
|
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;
|
return noInsertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,22 +93,47 @@ class InsertionData {
|
||||||
return "[iCost="+insertionCost+"][iIndex="+deliveryInsertionIndex+"][depTime="+departureTime+"][vehicle="+selectedVehicle+"][driver="+selectedDriver+"]";
|
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(){
|
public int getDeliveryInsertionIndex(){
|
||||||
return deliveryInsertionIndex;
|
return deliveryInsertionIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns insertionIndex of pickkupActivity. If no insertionPosition is found, it returns NO_INDEX (=-1).
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public int getPickupInsertionIndex(){
|
public int getPickupInsertionIndex(){
|
||||||
return pickupInsertionIndex;
|
return pickupInsertionIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns insertion costs (which might be the additional costs of inserting the corresponding job).
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public double getInsertionCost() {
|
public double getInsertionCost() {
|
||||||
return insertionCost;
|
return insertionCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the vehicle to be employed.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Vehicle getSelectedVehicle() {
|
public Vehicle getSelectedVehicle() {
|
||||||
return selectedVehicle;
|
return selectedVehicle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the vehicle to be employed.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Driver getSelectedDriver(){
|
public Driver getSelectedDriver(){
|
||||||
return selectedDriver;
|
return selectedDriver;
|
||||||
}
|
}
|
||||||
|
|
@ -14,13 +14,14 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import basics.Job;
|
import jsprit.core.algorithm.recreate.listener.InsertionListener;
|
||||||
import basics.algo.InsertionListener;
|
import jsprit.core.problem.job.Job;
|
||||||
import basics.route.VehicleRoute;
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -31,33 +32,7 @@ import basics.route.VehicleRoute;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
interface InsertionStrategy {
|
public 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns the unassigned jobs to service-providers
|
* Assigns the unassigned jobs to service-providers
|
||||||
|
|
@ -14,11 +14,11 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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);
|
public InsertionStrategy createStrategy(VehicleRoutingProblem vrp);
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -14,48 +14,51 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 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 weight_deltaFixCost = 0.5;
|
||||||
|
|
||||||
private double solution_completeness_ratio = 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();
|
super();
|
||||||
this.standardServiceInsertion = standardInsertionCalculator;
|
this.standardServiceInsertion = standardInsertionCalculator;
|
||||||
this.states = activityStates2;
|
this.stateGetter = stateGetter;
|
||||||
logger.info("inialise " + this);
|
logger.info("inialise " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 relFixCost = getDeltaRelativeFixCost(currentRoute, newVehicle, jobToInsert);
|
||||||
double absFixCost = getDeltaAbsoluteFixCost(currentRoute, newVehicle, jobToInsert);
|
double absFixCost = getDeltaAbsoluteFixCost(currentRoute, newVehicle, jobToInsert);
|
||||||
double deltaFixCost = (1-solution_completeness_ratio)*relFixCost + solution_completeness_ratio*absFixCost;
|
double deltaFixCost = (1-solution_completeness_ratio)*relFixCost + solution_completeness_ratio*absFixCost;
|
||||||
double fixcost_contribution = weight_deltaFixCost*solution_completeness_ratio*deltaFixCost;
|
double fixcost_contribution = weight_deltaFixCost*solution_completeness_ratio*deltaFixCost;
|
||||||
if(fixcost_contribution > bestKnownPrice){
|
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){
|
if(iData instanceof NoInsertionFound){
|
||||||
return iData;
|
return iData;
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +83,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
|
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;
|
double currentFix = 0.0;
|
||||||
if(route.getVehicle() != null){
|
if(route.getVehicle() != null){
|
||||||
if(!(route.getVehicle() instanceof NoVehicle)){
|
if(!(route.getVehicle() instanceof NoVehicle)){
|
||||||
|
|
@ -94,7 +97,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
|
private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) {
|
||||||
int currentLoad = getCurrentLoad(route);
|
int currentLoad = getCurrentMaxLoadInRoute(route);
|
||||||
double load = currentLoad + job.getCapacityDemand();
|
double load = currentLoad + job.getCapacityDemand();
|
||||||
double currentRelFix = 0.0;
|
double currentRelFix = 0.0;
|
||||||
if(route.getVehicle() != null){
|
if(route.getVehicle() != null){
|
||||||
|
|
@ -109,8 +112,8 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion
|
||||||
return relativeFixCost;
|
return relativeFixCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getCurrentLoad(VehicleRoute route) {
|
private int getCurrentMaxLoadInRoute(VehicleRoute route) {
|
||||||
return (int) states.getRouteState(route, StateTypes.LOAD).toDouble();
|
return (int) stateGetter.getRouteState(route, StateFactory.MAXLOAD).toDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -14,22 +14,16 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 jsprit.core.problem.driver.Driver;
|
||||||
|
import jsprit.core.problem.job.Job;
|
||||||
import org.junit.Test;
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
import basics.VehicleRoutingProblem;
|
|
||||||
import basics.VehicleRoutingProblemSolution;
|
|
||||||
|
|
||||||
public class ReaderTest {
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
public interface JobInsertionCostsCalculator {
|
||||||
public void testRead_ifReaderIsCalled_itReadsSuccessfully(){
|
|
||||||
new VrpXMLReader(VehicleRoutingProblem.Builder.newInstance(), new ArrayList<VehicleRoutingProblemSolution>()).read("src/test/resources/lui-shen-solution.xml");
|
|
||||||
|
|
||||||
}
|
public InsertionData getInsertionData(VehicleRoute currentRoute, Job newJob, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownCosts);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -18,39 +18,46 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Stefan Schroeder - initial API and implementation
|
* Stefan Schroeder - initial API and implementation
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package algorithms;
|
package jsprit.core.algorithm.recreate;
|
||||||
|
|
||||||
import algorithms.HardConstraints.HardActivityLevelConstraint;
|
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||||
import basics.costs.VehicleRoutingActivityCosts;
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import jsprit.core.problem.misc.JobInsertionContext;
|
||||||
import basics.route.TourActivity;
|
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{
|
class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator{
|
||||||
|
|
||||||
private HardActivityLevelConstraint hardConstraint;
|
|
||||||
|
|
||||||
private VehicleRoutingTransportCosts routingCosts;
|
private VehicleRoutingTransportCosts routingCosts;
|
||||||
|
|
||||||
private VehicleRoutingActivityCosts activityCosts;
|
private VehicleRoutingActivityCosts activityCosts;
|
||||||
|
|
||||||
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint) {
|
|
||||||
|
public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts) {
|
||||||
super();
|
super();
|
||||||
this.routingCosts = routingCosts;
|
this.routingCosts = routingCosts;
|
||||||
this.activityCosts = actCosts;
|
this.activityCosts = actCosts;
|
||||||
this.hardConstraint = hardActivityLevelConstraint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
|
public ActivityInsertionCosts getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
|
||||||
if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
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 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_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());
|
double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||||
|
|
||||||
|
|
@ -66,8 +73,12 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal
|
||||||
double oldCosts;
|
double oldCosts;
|
||||||
double oldTime;
|
double oldTime;
|
||||||
if(iFacts.getRoute().isEmpty()){
|
if(iFacts.getRoute().isEmpty()){
|
||||||
oldCosts = 0.0;
|
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle());
|
||||||
oldTime = 0.0;
|
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{
|
else{
|
||||||
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle());
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
package jsprit.core.algorithm.recreate;
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2013 Stefan Schroeder
|
* Copyright (C) 2013 Stefan Schroeder
|
||||||
*
|
*
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
package jsprit.core.algorithm.recreate;
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (C) 2013 Stefan Schroeder
|
* Copyright (C) 2013 Stefan Schroeder
|
||||||
*
|
*
|
||||||
|
|
@ -18,45 +18,41 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Stefan Schroeder - initial API and implementation
|
* Stefan Schroeder - initial API and implementation
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package algorithms;
|
package jsprit.core.algorithm.recreate;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import algorithms.HardConstraints.HardActivityLevelConstraint;
|
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||||
import basics.costs.VehicleRoutingActivityCosts;
|
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import jsprit.core.problem.misc.JobInsertionContext;
|
||||||
import basics.route.End;
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
import basics.route.Start;
|
import jsprit.core.problem.solution.route.activity.End;
|
||||||
import basics.route.TourActivity;
|
import jsprit.core.problem.solution.route.activity.Start;
|
||||||
import basics.route.VehicleRoute;
|
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{
|
class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCostsCalculator{
|
||||||
|
|
||||||
private HardActivityLevelConstraint hardConstraint;
|
|
||||||
|
|
||||||
private VehicleRoutingActivityCosts activityCosts;
|
private VehicleRoutingActivityCosts activityCosts;
|
||||||
|
|
||||||
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
|
private AuxilliaryCostCalculator auxilliaryPathCostCalculator;
|
||||||
|
|
||||||
private StateManager stateManager;
|
private RouteAndActivityStateGetter stateManager;
|
||||||
|
|
||||||
private int nuOfActivities2LookForward = 0;
|
private int nuOfActivities2LookForward = 0;
|
||||||
|
|
||||||
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint, StateManager stateManager) {
|
public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, RouteAndActivityStateGetter stateManager) {
|
||||||
super();
|
super();
|
||||||
this.activityCosts = actCosts;
|
this.activityCosts = actCosts;
|
||||||
this.hardConstraint = hardActivityLevelConstraint;
|
|
||||||
this.stateManager = stateManager;
|
this.stateManager = stateManager;
|
||||||
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts);
|
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
|
public ActivityInsertionCosts getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) {
|
||||||
if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TourActivity> path = new ArrayList<TourActivity>();
|
List<TourActivity> path = new ArrayList<TourActivity>();
|
||||||
path.add(prevAct); path.add(newAct); path.add(nextAct);
|
path.add(prevAct); path.add(newAct); path.add(nextAct);
|
||||||
int actIndex;
|
int actIndex;
|
||||||
|
|
@ -77,9 +73,9 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost
|
||||||
|
|
||||||
private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) {
|
private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) {
|
||||||
if(act instanceof End){
|
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) {
|
private List<TourActivity> getForwardLookingPath(VehicleRoute route, int actIndex) {
|
||||||
|
|
@ -14,33 +14,40 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 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() {
|
private Neighborhood neighborhood = new Neighborhood() {
|
||||||
|
|
||||||
|
|
@ -61,10 +68,12 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
||||||
logger.info("initialise neighborhood " + neighborhood);
|
logger.info("initialise neighborhood " + neighborhood);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CalculatesServiceInsertion(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint) {
|
|
||||||
|
public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteStateLevelConstraint hardRouteLevelConstraint, HardActivityStateLevelConstraint hardActivityLevelConstraint) {
|
||||||
super();
|
super();
|
||||||
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
|
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||||
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
|
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
|
||||||
|
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
|
||||||
this.transportCosts = routingCosts;
|
this.transportCosts = routingCosts;
|
||||||
activityFactory = new DefaultTourActivityFactory();
|
activityFactory = new DefaultTourActivityFactory();
|
||||||
logger.info("initialise " + this);
|
logger.info("initialise " + this);
|
||||||
|
|
@ -81,13 +90,13 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Override
|
@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(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing.");
|
||||||
if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle 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)){
|
if(!hardRouteLevelConstraint.fulfilled(insertionContext)){
|
||||||
return InsertionData.noInsertionFound();
|
return InsertionData.createEmptyInsertionData();
|
||||||
}
|
}
|
||||||
|
|
||||||
double bestCost = bestKnownCosts;
|
double bestCost = bestKnownCosts;
|
||||||
|
|
@ -99,36 +108,40 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
||||||
|
|
||||||
Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
|
Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
|
||||||
start.setEndTime(newVehicleDepartureTime);
|
start.setEndTime(newVehicleDepartureTime);
|
||||||
|
|
||||||
End end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
|
End end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival());
|
||||||
|
|
||||||
TourActivity prevAct = start;
|
TourActivity prevAct = start;
|
||||||
double prevActStartTime = newVehicleDepartureTime;
|
double prevActStartTime = newVehicleDepartureTime;
|
||||||
int actIndex = 0;
|
int actIndex = 0;
|
||||||
|
boolean loopBroken = false;
|
||||||
for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){
|
for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){
|
||||||
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
|
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);
|
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
|
||||||
if(mc != null){
|
|
||||||
if(mc.getAdditionalCosts() < bestCost){
|
if(mc.getAdditionalCosts() < bestCost){
|
||||||
bestCost = mc.getAdditionalCosts();
|
bestCost = mc.getAdditionalCosts();
|
||||||
bestMarginals = mc;
|
bestMarginals = mc;
|
||||||
insertionIndex = actIndex;
|
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 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;
|
prevActStartTime = nextActEndTime;
|
||||||
|
|
||||||
prevAct = nextAct;
|
prevAct = nextAct;
|
||||||
actIndex++;
|
actIndex++;
|
||||||
}
|
}
|
||||||
End nextAct = end;
|
End nextAct = end;
|
||||||
|
if(!loopBroken){
|
||||||
if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){
|
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);
|
ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
|
||||||
if(mc != null) {
|
|
||||||
if(mc.getAdditionalCosts() < bestCost){
|
if(mc.getAdditionalCosts() < bestCost){
|
||||||
bestCost = mc.getAdditionalCosts();
|
bestCost = mc.getAdditionalCosts();
|
||||||
bestMarginals = mc;
|
bestMarginals = mc;
|
||||||
|
|
@ -136,9 +149,10 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(insertionIndex == InsertionData.NO_INDEX) {
|
if(insertionIndex == InsertionData.NO_INDEX) {
|
||||||
return InsertionData.noInsertionFound();
|
return InsertionData.createEmptyInsertionData();
|
||||||
}
|
}
|
||||||
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
|
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
|
||||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||||
|
|
@ -146,8 +160,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{
|
||||||
return insertionData;
|
return insertionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) {
|
public ActivityInsertionCosts calculate(JobInsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) {
|
||||||
return activityInsertionCostsCalculator.calculate(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
|
return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
@ -23,31 +23,37 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.PriorityQueue;
|
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 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;
|
private final VehicleRoutingTransportCosts transportCosts;
|
||||||
|
|
||||||
|
|
@ -57,9 +63,11 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
|
|
||||||
private TourActivityFactory tourActivityFactory = new DefaultTourActivityFactory();
|
private TourActivityFactory tourActivityFactory = new DefaultTourActivityFactory();
|
||||||
|
|
||||||
private StateManager stateManager;
|
private RouteAndActivityStateGetter stateManager;
|
||||||
|
|
||||||
private HardRouteLevelConstraint hardRouteLevelConstraint;
|
private HardRouteStateLevelConstraint hardRouteLevelConstraint;
|
||||||
|
|
||||||
|
private HardActivityStateLevelConstraint hardActivityLevelConstraint;
|
||||||
|
|
||||||
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
|
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
|
||||||
|
|
||||||
|
|
@ -94,18 +102,19 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
logger.info("set [solutionMemory="+memorySize+"]");
|
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();
|
super();
|
||||||
this.transportCosts = vehicleRoutingCosts;
|
this.transportCosts = vehicleRoutingCosts;
|
||||||
this.activityCosts = costFunc;
|
this.activityCosts = costFunc;
|
||||||
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
|
|
||||||
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
|
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
|
||||||
|
this.hardRouteLevelConstraint = hardRouteLevelConstraint;
|
||||||
|
this.hardActivityLevelConstraint = hardActivityLevelConstraint;
|
||||||
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts);
|
auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts);
|
||||||
logger.info("initialise " + this);
|
logger.info("initialise " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setStates(StateManager stateManager){
|
public void setStates(RouteAndActivityStateGetter stateManager){
|
||||||
this.stateManager = stateManager;
|
this.stateManager = stateManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,13 +137,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Override
|
@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(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!");
|
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)){
|
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;
|
double best_insertion_costs = best_known_insertion_costs;
|
||||||
Service service = (Service)jobToInsert;
|
Service service = (Service)jobToInsert;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* some inis
|
* some inis
|
||||||
*/
|
*/
|
||||||
|
|
@ -164,6 +174,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
double sumOf_prevCosts_newVehicle = 0.0;
|
double sumOf_prevCosts_newVehicle = 0.0;
|
||||||
double prevActDepTime_newVehicle = start.getEndTime();
|
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}
|
* inserting serviceAct2Insert in route r={0,1,...,i-1,i,j,j+1,...,n(r),n(r)+1}
|
||||||
* i=prevAct
|
* i=prevAct
|
||||||
|
|
@ -172,12 +183,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
*/
|
*/
|
||||||
for(TourActivity nextAct : tour.getActivities()){
|
for(TourActivity nextAct : tour.getActivities()){
|
||||||
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
|
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}
|
* 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.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
||||||
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, 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)
|
* 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));
|
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++;
|
actIndex++;
|
||||||
}
|
}
|
||||||
|
if(!loopBroken){
|
||||||
End nextAct = end;
|
End nextAct = end;
|
||||||
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
|
if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){
|
||||||
|
ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle);
|
||||||
InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle);
|
if(status.equals(ConstraintsStatus.FULFILLED)){
|
||||||
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle);
|
||||||
if(actInsertionCosts != null){
|
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)
|
* 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{
|
else{
|
||||||
|
|
||||||
for(int i=0;i<memorySize;i++){
|
for(int i=0;i<memorySize;i++){
|
||||||
InsertionData data = bestInsertionsQueue.poll();
|
InsertionData data = bestInsertionsQueue.poll();
|
||||||
if(data == null){
|
if(data == null){
|
||||||
|
|
@ -271,7 +291,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
/**
|
/**
|
||||||
* compute cost-diff of tour with and without new activity --> insertion_costs
|
* 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
|
* 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();
|
if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.createEmptyInsertionData();
|
||||||
InsertionData insertionData = new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
|
return new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver);
|
||||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
|
||||||
return insertionData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -318,9 +336,9 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul
|
||||||
|
|
||||||
private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) {
|
private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) {
|
||||||
if(act instanceof End){
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,17 +14,19 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 jsprit.core.algorithm.recreate.listener.VehicleSwitchedListener;
|
||||||
import basics.route.VehicleRoute;
|
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;
|
private VehicleFleetManager fleetManager;
|
||||||
|
|
||||||
VehicleSwitched(VehicleFleetManager fleetManager){
|
public VehicleSwitched(VehicleFleetManager fleetManager){
|
||||||
this.fleetManager = fleetManager;
|
this.fleetManager = fleetManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -14,31 +14,33 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Collection;
|
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 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 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.fleetManager = fleetManager;
|
||||||
this.insertionCalculator = jobInsertionCalc;
|
this.insertionCalculator = jobInsertionCalc;
|
||||||
logger.info("inialise " + this);
|
logger.info("inialise " + this);
|
||||||
|
|
@ -49,10 +51,10 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
|
||||||
return "[name=vehicleTypeDependentServiceInsertion]";
|
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();
|
Vehicle selectedVehicle = currentRoute.getVehicle();
|
||||||
Driver selectedDriver = currentRoute.getDriver();
|
Driver selectedDriver = currentRoute.getDriver();
|
||||||
InsertionData bestIData = InsertionData.noInsertionFound();
|
InsertionData bestIData = InsertionData.createEmptyInsertionData();
|
||||||
double bestKnownCost_ = bestKnownCost;
|
double bestKnownCost_ = bestKnownCost;
|
||||||
Collection<Vehicle> relevantVehicles = new ArrayList<Vehicle>();
|
Collection<Vehicle> relevantVehicles = new ArrayList<Vehicle>();
|
||||||
if(!(selectedVehicle instanceof NoVehicle)) {
|
if(!(selectedVehicle instanceof NoVehicle)) {
|
||||||
|
|
@ -65,7 +67,7 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat
|
||||||
|
|
||||||
for(Vehicle v : relevantVehicles){
|
for(Vehicle v : relevantVehicles){
|
||||||
double depTime = v.getEarliestDeparture();
|
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(iData instanceof NoInsertionFound) {
|
||||||
if(bestIData instanceof NoInsertionFound) bestIData = iData;
|
if(bestIData instanceof NoInsertionFound) bestIData = iData;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -14,11 +14,11 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 jsprit.core.algorithm.recreate.InsertionData;
|
||||||
import basics.algo.InsertionListener;
|
import jsprit.core.problem.job.Job;
|
||||||
import basics.route.VehicleRoute;
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
|
||||||
interface BeforeJobInsertionListener extends InsertionListener{
|
interface BeforeJobInsertionListener extends InsertionListener{
|
||||||
|
|
||||||
|
|
@ -14,11 +14,12 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import basics.route.VehicleRoute;
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public interface InsertionEndsListener extends InsertionListener {
|
public interface InsertionEndsListener extends InsertionListener {
|
||||||
|
|
@ -14,7 +14,9 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,20 +14,18 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import basics.Job;
|
import jsprit.core.algorithm.recreate.InsertionData;
|
||||||
import basics.algo.InsertionEndsListener;
|
import jsprit.core.problem.job.Job;
|
||||||
import basics.algo.InsertionListener;
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
import basics.algo.InsertionStartsListener;
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
import basics.algo.JobInsertedListener;
|
|
||||||
import basics.route.Vehicle;
|
|
||||||
import basics.route.VehicleRoute;
|
|
||||||
|
|
||||||
class InsertionListeners {
|
|
||||||
|
public class InsertionListeners {
|
||||||
|
|
||||||
private Collection<InsertionListener> listeners = new ArrayList<InsertionListener>();
|
private Collection<InsertionListener> listeners = new ArrayList<InsertionListener>();
|
||||||
|
|
||||||
|
|
@ -14,15 +14,17 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 java.util.Collection;
|
||||||
|
|
||||||
import basics.Job;
|
import jsprit.core.problem.job.Job;
|
||||||
import basics.route.VehicleRoute;
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public interface InsertionStartsListener extends InsertionListener {
|
public interface InsertionStartsListener extends InsertionListener {
|
||||||
|
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -14,10 +14,10 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 jsprit.core.problem.job.Job;
|
||||||
import basics.route.VehicleRoute;
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -14,13 +14,12 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* 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/>.
|
* 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 jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
import basics.route.Vehicle;
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
import basics.route.VehicleRoute;
|
|
||||||
|
|
||||||
interface VehicleSwitchedListener extends InsertionListener{
|
public interface VehicleSwitchedListener extends InsertionListener{
|
||||||
|
|
||||||
public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle);
|
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
Loading…
Add table
Add a link
Reference in a new issue