mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
internal optimization of insertion-issues
This commit is contained in:
parent
e35603ed34
commit
3f7d6b8b01
20 changed files with 315 additions and 282 deletions
|
|
@ -1,95 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* Copyright (C) 2013 Stefan Schroeder
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* This program 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* Contributors:
|
|
||||||
* Stefan Schroeder - initial API and implementation
|
|
||||||
******************************************************************************/
|
|
||||||
package algorithms;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import basics.Job;
|
|
||||||
import basics.algo.InsertionEndsListener;
|
|
||||||
import basics.algo.InsertionListener;
|
|
||||||
import basics.algo.InsertionStartsListener;
|
|
||||||
import basics.algo.JobInsertedListener;
|
|
||||||
import basics.route.VehicleRoute;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
abstract class AbstractInsertionStrategy implements InsertionStrategy{
|
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(AbstractInsertionStrategy.class);
|
|
||||||
|
|
||||||
private Collection<InsertionListener> listener = new ArrayList<InsertionListener>();
|
|
||||||
|
|
||||||
public abstract RouteAlgorithm getRouteAlgorithm();
|
|
||||||
|
|
||||||
public void informJobInserted(int nOfJobs2Recreate, Job insertedJob, VehicleRoute insertedIn){
|
|
||||||
for(InsertionListener l : listener){
|
|
||||||
if(l instanceof JobInsertedListener){
|
|
||||||
((JobInsertedListener)l).informJobInserted(nOfJobs2Recreate, insertedJob, insertedIn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route){
|
|
||||||
for(InsertionListener l : listener){
|
|
||||||
if(l instanceof BeforeJobInsertionListener){
|
|
||||||
((BeforeJobInsertionListener)l).informBeforeJobInsertion(job, data, route);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate){
|
|
||||||
for(InsertionListener l : listener){
|
|
||||||
if(l instanceof InsertionStartsListener){
|
|
||||||
((InsertionStartsListener)l).informInsertionStarts(vehicleRoutes,nOfJobs2Recreate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void informInsertionEndsListeners(Collection<VehicleRoute> vehicleRoutes) {
|
|
||||||
for(InsertionListener l : listener){
|
|
||||||
if(l instanceof InsertionEndsListener){
|
|
||||||
((InsertionEndsListener)l).informInsertionEnds(vehicleRoutes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<InsertionListener> getListener() {
|
|
||||||
return Collections.unmodifiableCollection(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addListener(InsertionListener l){
|
|
||||||
log.info("add insertion-listener " + l);
|
|
||||||
listener.add(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addAllListener(List<InsertionListener> list) {
|
|
||||||
for(InsertionListener l : list) addListener(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -15,9 +15,7 @@ package algorithms;
|
||||||
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 java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
@ -25,6 +23,9 @@ import org.apache.log4j.Logger;
|
||||||
import util.RandomNumberGeneration;
|
import util.RandomNumberGeneration;
|
||||||
import algorithms.InsertionData.NoInsertionFound;
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
|
import basics.algo.InsertionListener;
|
||||||
|
import basics.route.Driver;
|
||||||
|
import basics.route.Vehicle;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,66 +36,53 @@ import basics.route.VehicleRoute;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
final class BestInsertion extends AbstractInsertionStrategy{
|
final class BestInsertion implements InsertionStrategy{
|
||||||
|
|
||||||
public static BestInsertion newInstance(RouteAlgorithm routeAlgorithm){
|
|
||||||
return new BestInsertion(routeAlgorithm);
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
|
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 InsertionListeners insertionsListeners;
|
||||||
|
|
||||||
private RouteAlgorithm routeAlgorithm;
|
private Inserter inserter;
|
||||||
|
|
||||||
public void setExperimentalPreferredRoute(Map<String, VehicleRoute> experimentalPreferredRoute) {
|
private JobInsertionCalculator bestInsertionCostCalculator;
|
||||||
}
|
|
||||||
|
|
||||||
private boolean allowUnassignedJobs = false;
|
|
||||||
|
|
||||||
private boolean fixRouteSet = false;
|
|
||||||
|
|
||||||
private boolean minVehiclesFirst = false;
|
private boolean minVehiclesFirst = false;
|
||||||
|
|
||||||
public void setFixRouteSet(boolean fixRouteSet) {
|
|
||||||
this.fixRouteSet = fixRouteSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRandom(Random random) {
|
public void setRandom(Random random) {
|
||||||
this.random = random;
|
this.random = random;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BestInsertion(RouteAlgorithm routeAlgorithm) {
|
public BestInsertion(JobInsertionCalculator jobInsertionCalculator) {
|
||||||
super();
|
super();
|
||||||
this.routeAlgorithm = routeAlgorithm;
|
|
||||||
this.insertionsListeners = new InsertionListeners();
|
this.insertionsListeners = new InsertionListeners();
|
||||||
|
inserter = new Inserter(insertionsListeners);
|
||||||
|
bestInsertionCostCalculator = jobInsertionCalculator;
|
||||||
logger.info("initialise " + this);
|
logger.info("initialise " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RouteAlgorithm getRouteAlgorithm(){
|
|
||||||
return routeAlgorithm;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[name=bestInsertion]";
|
return "[name=bestInsertion]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs, double result2beat) {
|
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
|
insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs);
|
||||||
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||||
Collections.shuffle(unassignedJobList, random);
|
Collections.shuffle(unassignedJobList, random);
|
||||||
informInsertionStarts(vehicleRoutes,unassignedJobs.size());
|
|
||||||
int inserted = 0;
|
|
||||||
List<String> reasons = new ArrayList<String>();
|
|
||||||
for(Job unassignedJob : unassignedJobList){
|
for(Job unassignedJob : unassignedJobList){
|
||||||
VehicleRoute insertIn = null;
|
|
||||||
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 = routeAlgorithm.calculateBestInsertion(vehicleRoute, unassignedJob, bestInsertionCost);
|
InsertionData iData = bestInsertionCostCalculator.calculate(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;
|
||||||
}
|
}
|
||||||
|
|
@ -105,56 +93,54 @@ final class BestInsertion extends AbstractInsertionStrategy{
|
||||||
}
|
}
|
||||||
if(!minVehiclesFirst){
|
if(!minVehiclesFirst){
|
||||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
||||||
InsertionData newIData = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE);
|
InsertionData newIData = bestInsertionCostCalculator.calculate(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();
|
||||||
vehicleRoutes.add(newRoute);
|
vehicleRoutes.add(newRoute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(bestInsertion != null){
|
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 {
|
|
||||||
if(fixRouteSet){
|
|
||||||
if(allowUnassignedJobs) logger.warn("cannot insert job yet " + unassignedJob);
|
|
||||||
else throw new IllegalStateException("given the vehicles, could not insert job\n");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
||||||
InsertionData bestI = routeAlgorithm.calculateBestInsertion(newRoute, unassignedJob, Double.MAX_VALUE);
|
InsertionData bestI = bestInsertionCostCalculator.calculate(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){
|
||||||
if(allowUnassignedJobs){
|
throw new IllegalStateException(getErrorMsg(unassignedJob));
|
||||||
logger.warn("cannot insert job yet " + unassignedJob);
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
for(String s : reasons){
|
bestInsertion = new Insertion(newRoute,bestI);
|
||||||
System.out.println("reason="+s);
|
vehicleRoutes.add(newRoute);
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("given the vehicles, could not insert job\n" +
|
}
|
||||||
|
|
||||||
|
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 +
|
"\t" + unassignedJob +
|
||||||
"\n\tthis might have the following reasons:\n" +
|
"\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- 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- 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]"
|
"\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);
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
insertIn = newRoute;
|
@Override
|
||||||
informBeforeJobInsertion(unassignedJob,bestI,newRoute);
|
public Collection<InsertionListener> getListeners() {
|
||||||
routeAlgorithm.insertJob(unassignedJob,bestI,newRoute);
|
return Collections.unmodifiableCollection(insertionsListeners.getListeners());
|
||||||
vehicleRoutes.add(newRoute);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
@Override
|
||||||
inserted++;
|
public void addListener(InsertionListener insertionListener) {
|
||||||
informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn);
|
insertionsListeners.addListener(insertionListener);
|
||||||
}
|
|
||||||
informInsertionEndsListeners(vehicleRoutes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import org.apache.log4j.Logger;
|
||||||
import util.RandomNumberGeneration;
|
import util.RandomNumberGeneration;
|
||||||
import algorithms.InsertionData.NoInsertionFound;
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
|
import basics.algo.InsertionListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -40,7 +41,7 @@ import basics.route.VehicleRoute;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
final class BestInsertionConcurrent extends AbstractInsertionStrategy{
|
final class BestInsertionConcurrent implements InsertionStrategy{
|
||||||
|
|
||||||
public static BestInsertionConcurrent newInstance(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads){
|
public static BestInsertionConcurrent newInstance(RouteAlgorithm routeAlgorithm, ExecutorService executor, int nuOfThreads){
|
||||||
return new BestInsertionConcurrent(routeAlgorithm, executor, nuOfThreads);
|
return new BestInsertionConcurrent(routeAlgorithm, executor, nuOfThreads);
|
||||||
|
|
@ -82,10 +83,10 @@ final class BestInsertionConcurrent extends AbstractInsertionStrategy{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs, double result2beat) {
|
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||||
Collections.shuffle(unassignedJobList, random);
|
Collections.shuffle(unassignedJobList, random);
|
||||||
informInsertionStarts(vehicleRoutes,unassignedJobs.size());
|
// informInsertionStarts(vehicleRoutes,unassignedJobs.size());
|
||||||
int inserted = 0;
|
int inserted = 0;
|
||||||
for(final Job unassignedJob : unassignedJobList){
|
for(final Job unassignedJob : unassignedJobList){
|
||||||
VehicleRoute insertIn = null;
|
VehicleRoute insertIn = null;
|
||||||
|
|
@ -127,7 +128,7 @@ final class BestInsertionConcurrent extends AbstractInsertionStrategy{
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bestInsertion != null){
|
if(bestInsertion != null){
|
||||||
informBeforeJobInsertion(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
// informBeforeJobInsertion(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||||
insertIn = bestInsertion.getRoute();
|
insertIn = bestInsertion.getRoute();
|
||||||
// logger.debug("insert job="+unassignedJob+" at index=" + bestInsertion.getInsertionData().getInsertionIndex() + " delta cost=" + bestInsertion.getInsertionData().getInsertionCost());
|
// logger.debug("insert job="+unassignedJob+" at index=" + bestInsertion.getInsertionData().getInsertionIndex() + " delta cost=" + bestInsertion.getInsertionData().getInsertionCost());
|
||||||
routeAlgorithm.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
routeAlgorithm.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||||
|
|
@ -144,9 +145,9 @@ final class BestInsertionConcurrent extends AbstractInsertionStrategy{
|
||||||
// vehicleRoutes.add(newRoute);
|
// vehicleRoutes.add(newRoute);
|
||||||
}
|
}
|
||||||
inserted++;
|
inserted++;
|
||||||
informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn);
|
// informJobInserted((unassignedJobList.size()-inserted), unassignedJob, insertIn);
|
||||||
}
|
}
|
||||||
informInsertionEndsListeners(vehicleRoutes);
|
// informInsertionEndsListeners(vehicleRoutes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
|
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
|
||||||
|
|
@ -191,9 +192,23 @@ final class BestInsertionConcurrent extends AbstractInsertionStrategy{
|
||||||
return batches;
|
return batches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RouteAlgorithm getRouteAlgorithm() {
|
public void removeListener(InsertionListener insertionListener) {
|
||||||
return routeAlgorithm;
|
// 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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn
|
||||||
|
|
||||||
CalculatesServiceInsertionConsideringFixCost calcConsideringFix;
|
CalculatesServiceInsertionConsideringFixCost calcConsideringFix;
|
||||||
|
|
||||||
|
private int nuOfJobsToRecreate;
|
||||||
|
|
||||||
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, CalculatesServiceInsertionConsideringFixCost calcConsideringFix) {
|
public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, CalculatesServiceInsertionConsideringFixCost calcConsideringFix) {
|
||||||
super();
|
super();
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
|
|
@ -55,15 +57,17 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> routes, int nOfJobs2Recreate) {
|
public void informInsertionStarts(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||||
double completenessRatio = (1-((double)nOfJobs2Recreate/(double)vrp.getJobs().values().size()));
|
this.nuOfJobsToRecreate = unassignedJobs.size();
|
||||||
|
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
|
||||||
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
||||||
// log.debug("initialise completenessRatio to " + completenessRatio);
|
// log.debug("initialise completenessRatio to " + completenessRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informJobInserted(int nOfJobsStill2Recreate, Job job2insert, VehicleRoute insertedIn) {
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute) {
|
||||||
double completenessRatio = (1-((double)nOfJobsStill2Recreate/(double)vrp.getJobs().values().size()));
|
nuOfJobsToRecreate--;
|
||||||
|
double completenessRatio = (1-((double)nuOfJobsToRecreate/(double)vrp.getJobs().values().size()));
|
||||||
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
calcConsideringFix.setSolutionCompletenessRatio(completenessRatio);
|
||||||
// log.debug("set completenessRatio to " + completenessRatio);
|
// log.debug("set completenessRatio to " + completenessRatio);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ final class CreateInitialSolution implements InitialSolutionFactory {
|
||||||
vehicleRoutes.add(VehicleRoute.newInstance(TourActivities.emptyTour(), DriverImpl.noDriver(), vehicle));
|
vehicleRoutes.add(VehicleRoute.newInstance(TourActivities.emptyTour(), DriverImpl.noDriver(), vehicle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
insertion.run(vehicleRoutes, getUnassignedJobs(vrp), Double.MAX_VALUE);
|
insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp));
|
||||||
double totalCost = getTotalCost(vehicleRoutes);
|
double totalCost = getTotalCost(vehicleRoutes);
|
||||||
logger.info("creation done");
|
logger.info("creation done");
|
||||||
return new VehicleRoutingProblemSolution(vehicleRoutes, totalCost);
|
return new VehicleRoutingProblemSolution(vehicleRoutes, totalCost);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import basics.Job;
|
||||||
import basics.algo.InsertionStartsListener;
|
import basics.algo.InsertionStartsListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
@ -37,7 +38,7 @@ class FindCheaperVehicle implements InsertionStartsListener{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate) {
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
List<VehicleRoute> newRoutes = new ArrayList<VehicleRoute>();
|
List<VehicleRoute> newRoutes = new ArrayList<VehicleRoute>();
|
||||||
for(VehicleRoute route : vehicleRoutes){
|
for(VehicleRoute route : vehicleRoutes){
|
||||||
if(route.isEmpty()) continue;
|
if(route.isEmpty()) continue;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
@ -30,16 +31,15 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import util.RandomNumberGeneration;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import basics.VehicleRoutingProblemSolution;
|
||||||
import basics.algo.SearchStrategyModule;
|
import basics.algo.SearchStrategyModule;
|
||||||
import basics.algo.SearchStrategyModuleListener;
|
import basics.algo.SearchStrategyModuleListener;
|
||||||
import basics.route.TourActivity;
|
import basics.route.TourActivity;
|
||||||
import basics.route.VehicleRoute;
|
|
||||||
import basics.route.TourActivity.JobActivity;
|
import basics.route.TourActivity.JobActivity;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
import util.RandomNumberGeneration;
|
|
||||||
|
|
||||||
final class Gendreau implements SearchStrategyModule{
|
final class Gendreau implements SearchStrategyModule{
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ final class Gendreau implements SearchStrategyModule{
|
||||||
|
|
||||||
private final InsertionStrategy insertionStrategy;
|
private final InsertionStrategy insertionStrategy;
|
||||||
|
|
||||||
private final RouteAlgorithm routeAlgorithm;
|
private final Inserter inserter;
|
||||||
|
|
||||||
private VehicleFleetManager fleetManager;
|
private VehicleFleetManager fleetManager;
|
||||||
|
|
||||||
|
|
@ -69,7 +69,9 @@ final class Gendreau implements SearchStrategyModule{
|
||||||
|
|
||||||
public Gendreau(VehicleRoutingProblem vrp, RuinStrategy ruin, InsertionStrategy insertionStrategy) {
|
public Gendreau(VehicleRoutingProblem vrp, RuinStrategy ruin, InsertionStrategy insertionStrategy) {
|
||||||
super();
|
super();
|
||||||
this.routeAlgorithm = insertionStrategy.getRouteAlgorithm();
|
InsertionListeners insertionListeners = new InsertionListeners();
|
||||||
|
insertionListeners.addAllListeners(insertionStrategy.getListeners());
|
||||||
|
inserter = new Inserter(insertionListeners);
|
||||||
this.ruin = ruin;
|
this.ruin = ruin;
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
this.insertionStrategy = insertionStrategy;
|
this.insertionStrategy = insertionStrategy;
|
||||||
|
|
@ -119,16 +121,18 @@ final class Gendreau implements SearchStrategyModule{
|
||||||
|
|
||||||
VehicleRoute emptyRoute1 = VehicleRoute.emptyRoute();
|
VehicleRoute emptyRoute1 = VehicleRoute.emptyRoute();
|
||||||
copiedRoutes.add(emptyRoute1);
|
copiedRoutes.add(emptyRoute1);
|
||||||
routeAlgorithm.insertJob(targetJob, routeAlgorithm.calculateBestInsertion(emptyRoute1, targetJob, Double.MAX_VALUE), emptyRoute1);
|
insertionStrategy.insertJobs(Arrays.asList(emptyRoute1), Arrays.asList(targetJob));
|
||||||
|
// routeAlgorithm.insertJob(targetJob, routeAlgorithm.calculateBestInsertion(emptyRoute1, targetJob, Double.MAX_VALUE), emptyRoute1);
|
||||||
unassignedJobs.remove(targetJob);
|
unassignedJobs.remove(targetJob);
|
||||||
|
|
||||||
VehicleRoute emptyRoute2 = VehicleRoute.emptyRoute();
|
VehicleRoute emptyRoute2 = VehicleRoute.emptyRoute();
|
||||||
copiedRoutes.add(emptyRoute2);
|
copiedRoutes.add(emptyRoute2);
|
||||||
Job job2 = jobsInRoute.get(1);
|
Job job2 = jobsInRoute.get(1);
|
||||||
routeAlgorithm.insertJob(job2, routeAlgorithm.calculateBestInsertion(emptyRoute2, job2, Double.MAX_VALUE), emptyRoute2);
|
insertionStrategy.insertJobs(Arrays.asList(emptyRoute2), Arrays.asList(job2));
|
||||||
|
// routeAlgorithm.insertJob(job2, routeAlgorithm.calculateBestInsertion(emptyRoute2, job2, Double.MAX_VALUE), emptyRoute2);
|
||||||
unassignedJobs.remove(job2);
|
unassignedJobs.remove(job2);
|
||||||
|
|
||||||
insertionStrategy.run(copiedRoutes, unassignedJobs, Double.MAX_VALUE);
|
insertionStrategy.insertJobs(copiedRoutes, unassignedJobs);
|
||||||
double cost = getCost(copiedRoutes);
|
double cost = getCost(copiedRoutes);
|
||||||
|
|
||||||
if(cost < bestSolution.getCost()){
|
if(cost < bestSolution.getCost()){
|
||||||
|
|
|
||||||
36
jsprit-core/src/main/java/algorithms/Inserter.java
Normal file
36
jsprit-core/src/main/java/algorithms/Inserter.java
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package algorithms;
|
||||||
|
|
||||||
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
|
import basics.Job;
|
||||||
|
import basics.Service;
|
||||||
|
import basics.route.ServiceActivity;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
class Inserter {
|
||||||
|
|
||||||
|
private InsertionListeners insertionListeners;
|
||||||
|
|
||||||
|
public Inserter(InsertionListeners insertionListeners) {
|
||||||
|
this.insertionListeners = insertionListeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(), ServiceActivity.newInstance((Service)job));
|
||||||
|
vehicleRoute.setDepartureTime(insertionData.getVehicleDepartureTime());
|
||||||
|
}
|
||||||
|
else throw new IllegalStateException("neither service nor shipment. this is not supported.");
|
||||||
|
|
||||||
|
insertionListeners.informJobInserted(job, vehicleRoute);
|
||||||
|
// updateTour(vehicleRoute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -37,7 +37,7 @@ class InsertionFactory {
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(InsertionFactory.class);
|
private static Logger log = Logger.getLogger(InsertionFactory.class);
|
||||||
|
|
||||||
public static AbstractInsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
|
public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config,
|
||||||
VehicleFleetManager vehicleFleetManager, RouteStates activityStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads){
|
VehicleFleetManager vehicleFleetManager, RouteStates activityStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads){
|
||||||
boolean concurrentInsertion = false;
|
boolean concurrentInsertion = false;
|
||||||
if(executorService != null) concurrentInsertion = true;
|
if(executorService != null) concurrentInsertion = true;
|
||||||
|
|
@ -46,7 +46,7 @@ class InsertionFactory {
|
||||||
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
|
if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){
|
||||||
new IllegalStateException(insertionName + " is not supported. use either \"bestInsertion\" or \"regretInsertion\"");
|
new IllegalStateException(insertionName + " is not supported. use either \"bestInsertion\" or \"regretInsertion\"");
|
||||||
}
|
}
|
||||||
AbstractInsertionStrategy insertionStrategy = null;
|
InsertionStrategy insertionStrategy = null;
|
||||||
List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
|
List<InsertionListener> insertionListeners = new ArrayList<InsertionListener>();
|
||||||
List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>();
|
List<PrioritizedVRAListener> algoListeners = new ArrayList<PrioritizedVRAListener>();
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ class InsertionFactory {
|
||||||
JobInsertionCalculator jic = calcBuilder.build();
|
JobInsertionCalculator jic = calcBuilder.build();
|
||||||
TourStateUpdater tourStateCalculator = new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts());
|
TourStateUpdater tourStateCalculator = new TourStateUpdater(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||||
RouteAlgorithm routeAlgorithm = RouteAlgorithmImpl.newInstance(jic, tourStateCalculator);
|
RouteAlgorithm routeAlgorithm = RouteAlgorithmImpl.newInstance(jic, tourStateCalculator);
|
||||||
routeAlgorithm.getListeners().add(new VehicleSwitched(vehicleFleetManager));
|
// routeAlgorithm.getListeners().add(new VehicleSwitched(vehicleFleetManager));
|
||||||
((RouteAlgorithmImpl) routeAlgorithm).setActivityStates(activityStates);
|
((RouteAlgorithmImpl) routeAlgorithm).setActivityStates(activityStates);
|
||||||
|
|
||||||
if(insertionName.equals("bestInsertion")){
|
if(insertionName.equals("bestInsertion")){
|
||||||
|
|
@ -104,24 +104,18 @@ class InsertionFactory {
|
||||||
insertionStrategy = BestInsertionConcurrent.newInstance(routeAlgorithm,executorService,nuOfThreads);
|
insertionStrategy = BestInsertionConcurrent.newInstance(routeAlgorithm,executorService,nuOfThreads);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
insertionStrategy = BestInsertion.newInstance(routeAlgorithm);
|
insertionStrategy = new BestInsertion(jic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(insertionName.equals("regretInsertion")){
|
else if(insertionName.equals("regretInsertion")){
|
||||||
insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
|
insertionStrategy = RegretInsertion.newInstance(routeAlgorithm);
|
||||||
}
|
}
|
||||||
// else if(insertionName.equals("concurrentBestInsertion")){
|
|
||||||
// String processorsString = config.getString("[@processors]");
|
|
||||||
// int processors = 1;
|
|
||||||
// if(processorsString != null) processors = Integer.parseInt(processorsString);
|
|
||||||
//// BestInsertionConcurrent.newInstance(routeAlgorithm,)
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
// insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
|
insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager));
|
||||||
insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager));
|
insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager));
|
||||||
insertionStrategy.addAllListener(insertionListeners);
|
insertionStrategy.addListener(new VehicleSwitched(vehicleFleetManager));
|
||||||
|
insertionStrategy.addListener(new UpdateRoute(activityStates, vrp.getTransportCosts(), vrp.getActivityCosts()));
|
||||||
|
for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l);
|
||||||
// insertionStrategy.addListener(new FindCheaperVehicle(
|
// insertionStrategy.addListener(new FindCheaperVehicle(
|
||||||
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));
|
// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator)));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,29 @@ import basics.algo.InsertionEndsListener;
|
||||||
import basics.algo.InsertionListener;
|
import basics.algo.InsertionListener;
|
||||||
import basics.algo.InsertionStartsListener;
|
import basics.algo.InsertionStartsListener;
|
||||||
import basics.algo.JobInsertedListener;
|
import basics.algo.JobInsertedListener;
|
||||||
|
import basics.route.Vehicle;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
class InsertionListeners {
|
class InsertionListeners {
|
||||||
|
|
||||||
private Collection<InsertionListener> listeners = new ArrayList<InsertionListener>();
|
private Collection<InsertionListener> listeners = new ArrayList<InsertionListener>();
|
||||||
|
|
||||||
public void informJobInserted(int nOfJobs2Recreate, Job insertedJob, VehicleRoute insertedIn){
|
public Collection<InsertionListener> getListeners(){
|
||||||
|
return listeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void informJobInserted(Job insertedJob, VehicleRoute inRoute){
|
||||||
for(InsertionListener l : listeners){
|
for(InsertionListener l : listeners){
|
||||||
if(l instanceof JobInsertedListener){
|
if(l instanceof JobInsertedListener){
|
||||||
((JobInsertedListener)l).informJobInserted(nOfJobs2Recreate, insertedJob, insertedIn);
|
((JobInsertedListener)l).informJobInserted(insertedJob, inRoute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void informVehicleSwitched(VehicleRoute route, Vehicle oldVehicle, Vehicle newVehicle){
|
||||||
|
for(InsertionListener l : listeners){
|
||||||
|
if(l instanceof VehicleSwitchedListener){
|
||||||
|
((VehicleSwitchedListener) l).vehicleSwitched(route, oldVehicle, newVehicle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,10 +43,10 @@ class InsertionListeners {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate){
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs){
|
||||||
for(InsertionListener l : listeners){
|
for(InsertionListener l : listeners){
|
||||||
if(l instanceof InsertionStartsListener){
|
if(l instanceof InsertionStartsListener){
|
||||||
((InsertionStartsListener)l).informInsertionStarts(vehicleRoutes,nOfJobs2Recreate);
|
((InsertionStartsListener)l).informInsertionStarts(vehicleRoutes, unassignedJobs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -54,4 +67,8 @@ class InsertionListeners {
|
||||||
listeners.remove(insertionListener);
|
listeners.remove(insertionListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addAllListeners(Collection<InsertionListener> listeners) {
|
||||||
|
for(InsertionListener l : listeners) addListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,10 +60,13 @@ interface InsertionStrategy {
|
||||||
*
|
*
|
||||||
* @param vehicleRoutes
|
* @param vehicleRoutes
|
||||||
* @param unassignedJobs
|
* @param unassignedJobs
|
||||||
* @param result2beat
|
|
||||||
*/
|
*/
|
||||||
public void run(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs, double result2beat);
|
public void insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
|
||||||
|
|
||||||
public void addListener(InsertionListener insertionListener);
|
public void addListener(InsertionListener insertionListener);
|
||||||
|
|
||||||
|
public void removeListener(InsertionListener insertionListener);
|
||||||
|
|
||||||
|
public Collection<InsertionListener> getListeners();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,14 +76,14 @@ class JobObserver implements JobInsertedListener, BeforeJobInsertionListener, Al
|
||||||
Collection<Info> infos = new ArrayList<Info>();
|
Collection<Info> infos = new ArrayList<Info>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informJobInserted(int nOfJobsStill2Recreate, Job job2insert, VehicleRoute insertedIn) {
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute) {
|
||||||
if(job2insert instanceof Service){
|
if(job2insert instanceof Service){
|
||||||
if(((Service) job2insert).getLocationId().equals(locationId)){
|
if(((Service) job2insert).getLocationId().equals(locationId)){
|
||||||
double actualMC = insertedIn.getCost()-routeCostBefore;
|
double actualMC = inRoute.getCost()-routeCostBefore;
|
||||||
TourActivity act = getAct(job2insert,insertedIn);
|
TourActivity act = getAct(job2insert,inRoute);
|
||||||
double error = (estimatedMC-actualMC);
|
double error = (estimatedMC-actualMC);
|
||||||
int tourSize = insertedIn.getTourActivities().getActivities().size();
|
int tourSize = inRoute.getTourActivities().getActivities().size();
|
||||||
int insertionIndex = getIndexOf(job2insert, insertedIn);
|
int insertionIndex = getIndexOf(job2insert, inRoute);
|
||||||
// infos.add(new Info())
|
// infos.add(new Info())
|
||||||
double depTime = state(act).getEarliestOperationStart()+act.getOperationTime();
|
double depTime = state(act).getEarliestOperationStart()+act.getOperationTime();
|
||||||
infos.add(new Info(depTime,tourSize,insertionIndex,error));
|
infos.add(new Info(depTime,tourSize,insertionIndex,error));
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import org.apache.log4j.Logger;
|
||||||
import algorithms.InsertionData.NoInsertionFound;
|
import algorithms.InsertionData.NoInsertionFound;
|
||||||
import basics.Job;
|
import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
|
import basics.algo.InsertionListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,7 +36,7 @@ import basics.route.VehicleRoute;
|
||||||
* @author stefan schroeder
|
* @author stefan schroeder
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
final class RegretInsertion extends AbstractInsertionStrategy{
|
final class RegretInsertion implements InsertionStrategy{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scorer to include other impacts on score such as time-window length or distance to depot.
|
* Scorer to include other impacts on score such as time-window length or distance to depot.
|
||||||
|
|
@ -127,9 +128,9 @@ final class RegretInsertion extends AbstractInsertionStrategy{
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs, double resultToBeat) {
|
public void insertJobs(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||||
List<Job> jobs = new ArrayList<Job>(unassignedJobs);
|
List<Job> jobs = new ArrayList<Job>(unassignedJobs);
|
||||||
informInsertionStarts(routes,unassignedJobs.size());
|
// informInsertionStarts(routes,unassignedJobs);
|
||||||
int inserted = 0;
|
int inserted = 0;
|
||||||
while(!jobs.isEmpty()){
|
while(!jobs.isEmpty()){
|
||||||
List<Job> unassignedJobList = new ArrayList<Job>(jobs);
|
List<Job> unassignedJobList = new ArrayList<Job>(jobs);
|
||||||
|
|
@ -191,7 +192,7 @@ final class RegretInsertion extends AbstractInsertionStrategy{
|
||||||
jobs.remove(bestScoredJob.getJob());
|
jobs.remove(bestScoredJob.getJob());
|
||||||
}
|
}
|
||||||
inserted++;
|
inserted++;
|
||||||
informJobInserted((unassignedJobList.size()-inserted), assignedJob, insertIn);
|
// informJobInserted(assignedJob, insertIn);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -207,4 +208,22 @@ final class RegretInsertion extends AbstractInsertionStrategy{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,12 @@ import java.util.List;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
import basics.Job;
|
||||||
import basics.algo.InsertionEndsListener;
|
import basics.algo.InsertionEndsListener;
|
||||||
import basics.algo.InsertionStartsListener;
|
import basics.algo.InsertionStartsListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
class RemoveEmptyVehicles implements InsertionStartsListener, InsertionEndsListener{
|
class RemoveEmptyVehicles implements InsertionEndsListener{
|
||||||
|
|
||||||
private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class);
|
private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class);
|
||||||
|
|
||||||
|
|
@ -41,21 +42,6 @@ class RemoveEmptyVehicles implements InsertionStartsListener, InsertionEndsListe
|
||||||
this.fleetManager = fleetManager;
|
this.fleetManager = fleetManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate) {
|
|
||||||
// List<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
|
|
||||||
// for(VehicleRoute route : routes){
|
|
||||||
// if(route.isEmpty()) { vehicleRoutes.remove(route); }
|
|
||||||
// }
|
|
||||||
// List<VehicleRoute> routes = new ArrayList<VehicleRoute>(vehicleRoutes);
|
|
||||||
// for(VehicleRoute route : routes){
|
|
||||||
// if(route.isEmpty()) {
|
|
||||||
// fleetManager.unlock(route.getVehicle());
|
|
||||||
// vehicleRoutes.remove(route);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[name=removeEmptyVehicles]";
|
return "[name=removeEmptyVehicles]";
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import java.util.Collection;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import basics.Job;
|
||||||
import basics.algo.InsertionStartsListener;
|
import basics.algo.InsertionStartsListener;
|
||||||
import basics.route.VehicleRoute;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
@ -40,16 +41,16 @@ class ResetAndIniFleetManager implements InsertionStartsListener{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, int nOfJobs2Recreate) {
|
public void informInsertionStarts(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
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()){
|
// if(route.isEmpty()){
|
||||||
vehicleRoutes.remove(route);
|
// vehicleRoutes.remove(route);
|
||||||
}
|
// }
|
||||||
else{
|
// else{
|
||||||
vehicleFleetManager.lock(route.getVehicle());
|
vehicleFleetManager.lock(route.getVehicle());
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
36
jsprit-core/src/main/java/algorithms/UpdateRoute.java
Normal file
36
jsprit-core/src/main/java/algorithms/UpdateRoute.java
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package algorithms;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import algorithms.RuinStrategy.RuinListener;
|
||||||
|
import basics.Job;
|
||||||
|
import basics.algo.JobInsertedListener;
|
||||||
|
import basics.costs.VehicleRoutingActivityCosts;
|
||||||
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
public class UpdateRoute implements JobInsertedListener, RuinListener{
|
||||||
|
|
||||||
|
private TourStateUpdater routeStateUpdater;
|
||||||
|
|
||||||
|
public UpdateRoute(RouteStates routeStates, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) {
|
||||||
|
routeStateUpdater = new TourStateUpdater(routeStates, routingCosts, activityCosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informJobInserted(Job job2insert, VehicleRoute inRoute) {
|
||||||
|
routeStateUpdater.updateRoute(inRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ruinStarts(Collection<VehicleRoute> routes) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ruinEnds(Collection<VehicleRoute> routes,Collection<Job> unassignedJobs) {
|
||||||
|
for(VehicleRoute route : routes) routeStateUpdater.updateRoute(route);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removed(Job job, VehicleRoute fromRoute) {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -37,7 +37,7 @@ import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import util.RouteUtils;
|
import util.RouteUtils;
|
||||||
import algorithms.RuinStrategy.RuinListener;
|
import algorithms.RuinStrategy.RuinListener;
|
||||||
import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractInsertionKey;
|
import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey;
|
||||||
import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
|
import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey;
|
||||||
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
|
import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey;
|
||||||
import algorithms.VehicleRoutingAlgorithms.TypedMap.RuinStrategyKey;
|
import algorithms.VehicleRoutingAlgorithms.TypedMap.RuinStrategyKey;
|
||||||
|
|
@ -260,11 +260,11 @@ public class VehicleRoutingAlgorithms {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AbstractInsertionKey implements AbstractKey<AbstractInsertionStrategy>{
|
static class InsertionStrategyKey implements AbstractKey<InsertionStrategy>{
|
||||||
|
|
||||||
private ModKey modKey;
|
private ModKey modKey;
|
||||||
|
|
||||||
public AbstractInsertionKey(ModKey modKey) {
|
public InsertionStrategyKey(ModKey modKey) {
|
||||||
super();
|
super();
|
||||||
this.modKey = modKey;
|
this.modKey = modKey;
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +286,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
return false;
|
return false;
|
||||||
if (getClass() != obj.getClass())
|
if (getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
AbstractInsertionKey other = (AbstractInsertionKey) obj;
|
InsertionStrategyKey other = (InsertionStrategyKey) obj;
|
||||||
if (modKey == null) {
|
if (modKey == null) {
|
||||||
if (other.modKey != null)
|
if (other.modKey != null)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -298,8 +298,8 @@ public class VehicleRoutingAlgorithms {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<AbstractInsertionStrategy> getType() {
|
public Class<InsertionStrategy> getType() {
|
||||||
return AbstractInsertionStrategy.class;
|
return InsertionStrategy.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -535,16 +535,14 @@ public class VehicleRoutingAlgorithms {
|
||||||
|
|
||||||
private static void registerInsertionListeners(TypedMap definedClasses, List<InsertionListener> insertionListeners) {
|
private static void registerInsertionListeners(TypedMap definedClasses, List<InsertionListener> insertionListeners) {
|
||||||
for(AbstractKey<?> key : definedClasses.keySet()){
|
for(AbstractKey<?> key : definedClasses.keySet()){
|
||||||
if(key instanceof AbstractInsertionKey){
|
if(key instanceof InsertionStrategyKey){
|
||||||
AbstractInsertionKey insertionKey = (AbstractInsertionKey) key;
|
InsertionStrategyKey insertionKey = (InsertionStrategyKey) key;
|
||||||
AbstractInsertionStrategy insertionStrategy = definedClasses.get(insertionKey);
|
InsertionStrategy insertionStrategy = definedClasses.get(insertionKey);
|
||||||
for(InsertionListener l : insertionListeners){
|
for(InsertionListener l : insertionListeners){
|
||||||
// log.info("add insertionListener " + l + " to " + insertionStrategy);
|
|
||||||
insertionStrategy.addListener(l);
|
insertionStrategy.addListener(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// log.warn("cannot register insertion listeners yet");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getName(HierarchicalConfiguration strategyConfig) {
|
private static String getName(HierarchicalConfiguration strategyConfig) {
|
||||||
|
|
@ -570,15 +568,15 @@ public class VehicleRoutingAlgorithms {
|
||||||
String insertionId = modConfig.getString("[@id]");
|
String insertionId = modConfig.getString("[@id]");
|
||||||
if(insertionId == null) insertionId = "noId";
|
if(insertionId == null) insertionId = "noId";
|
||||||
ModKey modKey = makeKey(insertionName,insertionId);
|
ModKey modKey = makeKey(insertionName,insertionId);
|
||||||
AbstractInsertionKey insertionStrategyKey = new AbstractInsertionKey(modKey);
|
InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(modKey);
|
||||||
AbstractInsertionStrategy insertionStrategy = definedClasses.get(insertionStrategyKey);
|
InsertionStrategy insertionStrategy = definedClasses.get(insertionStrategyKey);
|
||||||
if(insertionStrategy == null){
|
if(insertionStrategy == null){
|
||||||
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
|
List<PrioritizedVRAListener> prioListeners = new ArrayList<PrioritizedVRAListener>();
|
||||||
insertionStrategy = createInsertionStrategy(modConfig, vrp, vehicleFleetManager, activityStates, prioListeners, executorService, nuOfThreads);
|
insertionStrategy = createInsertionStrategy(modConfig, vrp, vehicleFleetManager, activityStates, prioListeners, executorService, nuOfThreads);
|
||||||
algorithmListeners.addAll(prioListeners);
|
algorithmListeners.addAll(prioListeners);
|
||||||
definedClasses.put(insertionStrategyKey,insertionStrategy);
|
definedClasses.put(insertionStrategyKey,insertionStrategy);
|
||||||
}
|
}
|
||||||
final AbstractInsertionStrategy finalInsertionStrategy = insertionStrategy;
|
final InsertionStrategy finalInsertionStrategy = insertionStrategy;
|
||||||
|
|
||||||
return new AlgorithmStartsListener() {
|
return new AlgorithmStartsListener() {
|
||||||
|
|
||||||
|
|
@ -699,8 +697,8 @@ public class VehicleRoutingAlgorithms {
|
||||||
String insertionId = moduleConfig.getString("insertion[@id]");
|
String insertionId = moduleConfig.getString("insertion[@id]");
|
||||||
if(insertionId == null) insertionId = "noId";
|
if(insertionId == null) insertionId = "noId";
|
||||||
ModKey insertionKey = makeKey(insertionName,insertionId);
|
ModKey insertionKey = makeKey(insertionName,insertionId);
|
||||||
AbstractInsertionKey insertionStrategyKey = new AbstractInsertionKey(insertionKey);
|
InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
|
||||||
AbstractInsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
|
InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
|
||||||
if(insertion == null){
|
if(insertion == null){
|
||||||
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
|
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
|
||||||
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
|
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
|
||||||
|
|
@ -708,7 +706,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, activityStates, prioListeners, executorService, nuOfThreads);
|
insertion = createInsertionStrategy(insertionConfigs.get(0), vrp, vehicleFleetManager, activityStates, prioListeners, executorService, nuOfThreads);
|
||||||
algorithmListeners.addAll(prioListeners);
|
algorithmListeners.addAll(prioListeners);
|
||||||
}
|
}
|
||||||
final AbstractInsertionStrategy final_insertion = insertion;
|
final InsertionStrategy final_insertion = insertion;
|
||||||
SearchStrategyModule module = new SearchStrategyModule() {
|
SearchStrategyModule module = new SearchStrategyModule() {
|
||||||
|
|
||||||
private Logger logger = Logger.getLogger(SearchStrategyModule.class);
|
private Logger logger = Logger.getLogger(SearchStrategyModule.class);
|
||||||
|
|
@ -716,7 +714,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
@Override
|
@Override
|
||||||
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
|
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
|
||||||
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
|
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
|
||||||
final_insertion.run(vrpSolution.getRoutes(), ruinedJobs, Double.MAX_VALUE);
|
final_insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs);
|
||||||
double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
|
double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes());
|
||||||
vrpSolution.setCost(totalCost);
|
vrpSolution.setCost(totalCost);
|
||||||
return vrpSolution;
|
return vrpSolution;
|
||||||
|
|
@ -736,7 +734,7 @@ public class VehicleRoutingAlgorithms {
|
||||||
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
|
public void addModuleListener(SearchStrategyModuleListener moduleListener) {
|
||||||
if(moduleListener instanceof InsertionListener){
|
if(moduleListener instanceof InsertionListener){
|
||||||
InsertionListener iListener = (InsertionListener) moduleListener;
|
InsertionListener iListener = (InsertionListener) moduleListener;
|
||||||
if(!final_insertion.getListener().contains(iListener)){
|
if(!final_insertion.getListeners().contains(iListener)){
|
||||||
logger.info("register moduleListener " + moduleListener);
|
logger.info("register moduleListener " + moduleListener);
|
||||||
final_insertion.addListener(iListener);
|
final_insertion.addListener(iListener);
|
||||||
}
|
}
|
||||||
|
|
@ -785,8 +783,8 @@ public class VehicleRoutingAlgorithms {
|
||||||
String insertionId = moduleConfig.getString("insertion[@id]");
|
String insertionId = moduleConfig.getString("insertion[@id]");
|
||||||
if(insertionId == null) insertionId = "noId";
|
if(insertionId == null) insertionId = "noId";
|
||||||
ModKey insertionKey = makeKey(insertionName,insertionId);
|
ModKey insertionKey = makeKey(insertionName,insertionId);
|
||||||
AbstractInsertionKey insertionStrategyKey = new AbstractInsertionKey(insertionKey);
|
InsertionStrategyKey insertionStrategyKey = new InsertionStrategyKey(insertionKey);
|
||||||
AbstractInsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
|
InsertionStrategy insertion = definedClasses.get(insertionStrategyKey);
|
||||||
if(insertion == null){
|
if(insertion == null){
|
||||||
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
|
List<HierarchicalConfiguration> insertionConfigs = moduleConfig.configurationsAt("insertion");
|
||||||
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
|
if(insertionConfigs.size() != 1) throw new IllegalStateException("this should be 1");
|
||||||
|
|
@ -864,8 +862,8 @@ public class VehicleRoutingAlgorithms {
|
||||||
return ruin;
|
return ruin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AbstractInsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, RouteStates activityStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads) {
|
private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, RouteStates activityStates, List<PrioritizedVRAListener> algorithmListeners, ExecutorService executorService, int nuOfThreads) {
|
||||||
AbstractInsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, activityStates, algorithmListeners, executorService, nuOfThreads);
|
InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, activityStates, algorithmListeners, executorService, nuOfThreads);
|
||||||
return insertion;
|
return insertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@
|
||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import basics.route.Vehicle;
|
import basics.route.Vehicle;
|
||||||
import algorithms.RouteAlgorithm.VehicleSwitchedListener;
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
|
||||||
class VehicleSwitched implements VehicleSwitchedListener{
|
class VehicleSwitched implements VehicleSwitchedListener{
|
||||||
|
|
||||||
|
|
@ -32,7 +33,7 @@ class VehicleSwitched implements VehicleSwitchedListener{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void vehicleSwitched(Vehicle oldVehicle, Vehicle newVehicle) {
|
public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle) {
|
||||||
fleetManager.unlock(oldVehicle);
|
fleetManager.unlock(oldVehicle);
|
||||||
fleetManager.lock(newVehicle);
|
fleetManager.lock(newVehicle);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package algorithms;
|
||||||
|
|
||||||
|
import basics.algo.InsertionListener;
|
||||||
|
import basics.route.Vehicle;
|
||||||
|
import basics.route.VehicleRoute;
|
||||||
|
|
||||||
|
interface VehicleSwitchedListener extends InsertionListener{
|
||||||
|
|
||||||
|
public void vehicleSwitched(VehicleRoute vehicleRoute, Vehicle oldVehicle, Vehicle newVehicle);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -37,6 +37,7 @@ import basics.Job;
|
||||||
import basics.Service;
|
import basics.Service;
|
||||||
import basics.VehicleRoutingProblem;
|
import basics.VehicleRoutingProblem;
|
||||||
import basics.VehicleRoutingProblemSolution;
|
import basics.VehicleRoutingProblemSolution;
|
||||||
|
import basics.costs.VehicleRoutingActivityCosts;
|
||||||
import basics.costs.VehicleRoutingTransportCosts;
|
import basics.costs.VehicleRoutingTransportCosts;
|
||||||
import basics.route.Driver;
|
import basics.route.Driver;
|
||||||
import basics.route.DriverImpl;
|
import basics.route.DriverImpl;
|
||||||
|
|
@ -60,6 +61,8 @@ public class GendreauPostOptTest {
|
||||||
|
|
||||||
VehicleRoutingTransportCosts cost;
|
VehicleRoutingTransportCosts cost;
|
||||||
|
|
||||||
|
VehicleRoutingActivityCosts activityCosts;
|
||||||
|
|
||||||
VehicleRoutingProblem vrp;
|
VehicleRoutingProblem vrp;
|
||||||
|
|
||||||
Service job1;
|
Service job1;
|
||||||
|
|
@ -78,6 +81,8 @@ public class GendreauPostOptTest {
|
||||||
|
|
||||||
private RouteAlgorithmImpl routeAlgorithm;
|
private RouteAlgorithmImpl routeAlgorithm;
|
||||||
|
|
||||||
|
private JobInsertionCalculator insertionCalc;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp(){
|
public void setUp(){
|
||||||
|
|
||||||
|
|
@ -148,29 +153,31 @@ public class GendreauPostOptTest {
|
||||||
fleetManager = new VehicleFleetManagerImpl(vehicles);
|
fleetManager = new VehicleFleetManagerImpl(vehicles);
|
||||||
states = new RouteStates();
|
states = new RouteStates();
|
||||||
|
|
||||||
ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction();
|
activityCosts = new ExampleActivityCostFunction();
|
||||||
|
|
||||||
CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, activityCosts);
|
CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, activityCosts);
|
||||||
standardServiceInsertion.setActivityStates(states);
|
standardServiceInsertion.setActivityStates(states);
|
||||||
CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states);
|
CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states);
|
||||||
withFixCost.setWeightOfFixCost(1.2);
|
withFixCost.setWeightOfFixCost(1.2);
|
||||||
|
|
||||||
final JobInsertionCalculator vehicleTypeDepInsertionCost = new CalculatesVehTypeDepServiceInsertion(fleetManager, withFixCost);
|
insertionCalc = new CalculatesVehTypeDepServiceInsertion(fleetManager, withFixCost);
|
||||||
|
|
||||||
updater = new TourStateUpdater(states, cost, activityCosts);
|
updater = new TourStateUpdater(states, cost, activityCosts);
|
||||||
|
|
||||||
|
//
|
||||||
routeAlgorithm = RouteAlgorithmImpl.newInstance(vehicleTypeDepInsertionCost, updater);
|
//
|
||||||
routeAlgorithm.setActivityStates(states);
|
// routeAlgorithm = RouteAlgorithmImpl.newInstance(insertionCalc, updater);
|
||||||
if(fleetManager != null){
|
// routeAlgorithm.setActivityStates(states);
|
||||||
routeAlgorithm.getListeners().add(new RouteAlgorithm.VehicleSwitchedListener() {
|
// if(fleetManager != null){
|
||||||
|
// routeAlgorithm.getListeners().add(new RouteAlgorithm.VehicleSwitchedListener() {
|
||||||
@Override
|
//
|
||||||
public void vehicleSwitched(Vehicle oldVehicle, Vehicle newVehicle) {
|
// @Override
|
||||||
fleetManager.unlock(oldVehicle);
|
// public void vehicleSwitched(Vehicle oldVehicle, Vehicle newVehicle) {
|
||||||
fleetManager.lock(newVehicle);
|
// fleetManager.unlock(oldVehicle);
|
||||||
}
|
// fleetManager.lock(newVehicle);
|
||||||
});
|
// }
|
||||||
}
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -202,10 +209,17 @@ public class GendreauPostOptTest {
|
||||||
|
|
||||||
assertEquals(110.0, sol.getCost(), 0.5);
|
assertEquals(110.0, sol.getCost(), 0.5);
|
||||||
|
|
||||||
|
UpdateRoute stateUpdater = new UpdateRoute(states, vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||||
|
|
||||||
RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()));
|
RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()));
|
||||||
AbstractInsertionStrategy insertionStrategy = new BestInsertion(routeAlgorithm);
|
radialRuin.addListener(stateUpdater);
|
||||||
|
|
||||||
|
InsertionStrategy insertionStrategy = new BestInsertion(insertionCalc);
|
||||||
|
insertionStrategy.addListener(stateUpdater);
|
||||||
|
insertionStrategy.addListener(new VehicleSwitched(fleetManager));
|
||||||
Gendreau postOpt = new Gendreau(vrp, radialRuin, insertionStrategy);
|
Gendreau postOpt = new Gendreau(vrp, radialRuin, insertionStrategy);
|
||||||
postOpt.setFleetManager(fleetManager);
|
postOpt.setFleetManager(fleetManager);
|
||||||
|
|
||||||
VehicleRoutingProblemSolution newSolution = postOpt.runAndGetSolution(sol);
|
VehicleRoutingProblemSolution newSolution = postOpt.runAndGetSolution(sol);
|
||||||
|
|
||||||
assertEquals(2,RouteUtils.getNuOfActiveRoutes(newSolution.getRoutes()));
|
assertEquals(2,RouteUtils.getNuOfActiveRoutes(newSolution.getRoutes()));
|
||||||
|
|
@ -236,15 +250,17 @@ public class GendreauPostOptTest {
|
||||||
|
|
||||||
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
||||||
routes.add(route);
|
routes.add(route);
|
||||||
// routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle()));
|
|
||||||
// routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle()));
|
|
||||||
|
|
||||||
VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(routes, route.getCost());
|
VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(routes, route.getCost());
|
||||||
|
|
||||||
assertEquals(110.0, sol.getCost(), 0.5);
|
assertEquals(110.0, sol.getCost(), 0.5);
|
||||||
|
|
||||||
|
UpdateRoute stateUpdater = new UpdateRoute(states, vrp.getTransportCosts(), vrp.getActivityCosts());
|
||||||
|
|
||||||
RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()));
|
RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts()));
|
||||||
AbstractInsertionStrategy insertionStrategy = new BestInsertion(routeAlgorithm);
|
InsertionStrategy insertionStrategy = new BestInsertion(insertionCalc);
|
||||||
|
insertionStrategy.addListener(stateUpdater);
|
||||||
|
insertionStrategy.addListener(new VehicleSwitched(fleetManager));
|
||||||
Gendreau postOpt = new Gendreau(vrp, radialRuin, insertionStrategy);
|
Gendreau postOpt = new Gendreau(vrp, radialRuin, insertionStrategy);
|
||||||
postOpt.setShareOfJobsToRuin(1.0);
|
postOpt.setShareOfJobsToRuin(1.0);
|
||||||
postOpt.setNuOfIterations(1);
|
postOpt.setNuOfIterations(1);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue