mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
add PrettyAlgorithmBuilder to make testing and applying new strategies and algorithms easier
This commit is contained in:
parent
7ce6a8d68a
commit
593cd5e841
2 changed files with 173 additions and 71 deletions
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (C) 2014 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 jsprit.core.algorithm.acceptor.SchrimpfAcceptance;
|
||||||
|
import jsprit.core.algorithm.acceptor.SolutionAcceptor;
|
||||||
|
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
|
||||||
|
import jsprit.core.algorithm.recreate.InsertionStrategy;
|
||||||
|
import jsprit.core.algorithm.recreate.VehicleSwitched;
|
||||||
|
import jsprit.core.algorithm.state.*;
|
||||||
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
|
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.vehicle.Vehicle;
|
||||||
|
import jsprit.core.problem.vehicle.VehicleFleetManager;
|
||||||
|
import jsprit.core.util.ActivityTimeTracker;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by schroeder on 10.12.14.
|
||||||
|
*/
|
||||||
|
public class PrettyAlgorithmBuilder {
|
||||||
|
|
||||||
|
private final VehicleRoutingProblem vrp;
|
||||||
|
|
||||||
|
private final VehicleFleetManager fleetManager;
|
||||||
|
|
||||||
|
private final StateManager stateManager;
|
||||||
|
|
||||||
|
private final ConstraintManager constraintManager;
|
||||||
|
|
||||||
|
private SearchStrategyManager searchStrategyManager;
|
||||||
|
|
||||||
|
private InsertionStrategy iniInsertionStrategy;
|
||||||
|
|
||||||
|
private SolutionCostCalculator iniObjFunction;
|
||||||
|
|
||||||
|
private boolean coreStuff = false;
|
||||||
|
|
||||||
|
public static PrettyAlgorithmBuilder newInstance(VehicleRoutingProblem vrp, VehicleFleetManager fleetManager, StateManager stateManager, ConstraintManager constraintManager){
|
||||||
|
return new PrettyAlgorithmBuilder(vrp,fleetManager,stateManager,constraintManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrettyAlgorithmBuilder(VehicleRoutingProblem vrp, VehicleFleetManager fleetManager, StateManager stateManager, ConstraintManager constraintManager){
|
||||||
|
this.vrp = vrp;
|
||||||
|
this.fleetManager = fleetManager;
|
||||||
|
this.stateManager = stateManager;
|
||||||
|
this.constraintManager = constraintManager;
|
||||||
|
this.searchStrategyManager = new SearchStrategyManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrettyAlgorithmBuilder withStrategy(SearchStrategy strategy, double weight){
|
||||||
|
searchStrategyManager.addStrategy(strategy,weight);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrettyAlgorithmBuilder constructInitialSolutionWith(InsertionStrategy insertionStrategy, SolutionCostCalculator objFunction){
|
||||||
|
this.iniInsertionStrategy = insertionStrategy;
|
||||||
|
this.iniObjFunction = objFunction;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VehicleRoutingAlgorithm build(){
|
||||||
|
if(coreStuff){
|
||||||
|
constraintManager.addTimeWindowConstraint();
|
||||||
|
constraintManager.addLoadConstraint();
|
||||||
|
constraintManager.addSkillsConstraint();
|
||||||
|
stateManager.updateLoadStates();
|
||||||
|
stateManager.updateTimeWindowStates();
|
||||||
|
UpdateVehicleDependentPracticalTimeWindows tw_updater = new UpdateVehicleDependentPracticalTimeWindows(stateManager, vrp.getTransportCosts());
|
||||||
|
tw_updater.setVehiclesToUpdate(new UpdateVehicleDependentPracticalTimeWindows.VehiclesToUpdate() {
|
||||||
|
@Override
|
||||||
|
public Collection<Vehicle> get(VehicleRoute vehicleRoute) {
|
||||||
|
Collection<Vehicle> vehicles = new ArrayList<Vehicle>();
|
||||||
|
vehicles.add(vehicleRoute.getVehicle());
|
||||||
|
vehicles.addAll(fleetManager.getAvailableVehicles(vehicleRoute.getVehicle()));
|
||||||
|
return vehicles;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
stateManager.addStateUpdater(tw_updater);
|
||||||
|
stateManager.updateSkillStates();
|
||||||
|
stateManager.addStateUpdater(new UpdateEndLocationIfRouteIsOpen());
|
||||||
|
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS));
|
||||||
|
stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
|
||||||
|
}
|
||||||
|
VehicleRoutingAlgorithm vra = new VehicleRoutingAlgorithm(vrp,searchStrategyManager);
|
||||||
|
vra.addListener(stateManager);
|
||||||
|
RemoveEmptyVehicles removeEmptyVehicles = new RemoveEmptyVehicles(fleetManager);
|
||||||
|
ResetAndIniFleetManager resetAndIniFleetManager = new ResetAndIniFleetManager(fleetManager);
|
||||||
|
VehicleSwitched vehicleSwitched = new VehicleSwitched(fleetManager);
|
||||||
|
vra.addListener(removeEmptyVehicles);
|
||||||
|
vra.addListener(resetAndIniFleetManager);
|
||||||
|
vra.addListener(vehicleSwitched);
|
||||||
|
if(iniInsertionStrategy != null) {
|
||||||
|
if (!iniInsertionStrategy.getListeners().contains(removeEmptyVehicles))
|
||||||
|
iniInsertionStrategy.addListener(removeEmptyVehicles);
|
||||||
|
if (!iniInsertionStrategy.getListeners().contains(resetAndIniFleetManager))
|
||||||
|
iniInsertionStrategy.addListener(resetAndIniFleetManager);
|
||||||
|
if (!iniInsertionStrategy.getListeners().contains(vehicleSwitched))
|
||||||
|
iniInsertionStrategy.addListener(vehicleSwitched);
|
||||||
|
if (!iniInsertionStrategy.getListeners().contains(stateManager))
|
||||||
|
iniInsertionStrategy.addListener(stateManager);
|
||||||
|
vra.addListener(new AlgorithmStartsListener() {
|
||||||
|
@Override
|
||||||
|
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||||
|
solutions.add(new InsertionInitialSolutionFactory(iniInsertionStrategy, iniObjFunction).createSolution(vrp));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
addArbitraryListener(vra);
|
||||||
|
return vra;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addArbitraryListener(VehicleRoutingAlgorithm vra) {
|
||||||
|
searchSchrimpfAndRegister(vra);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void searchSchrimpfAndRegister(VehicleRoutingAlgorithm vra) {
|
||||||
|
for(SearchStrategy strategy : vra.getSearchStrategyManager().getStrategies()){
|
||||||
|
SolutionAcceptor acceptor = strategy.getSolutionAcceptor();
|
||||||
|
if(acceptor instanceof SchrimpfAcceptance){
|
||||||
|
vra.addListener((SchrimpfAcceptance)acceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrettyAlgorithmBuilder addCoreStateAndConstraintStuff() {
|
||||||
|
this.coreStuff = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -21,12 +21,10 @@ import jsprit.core.algorithm.*;
|
||||||
import jsprit.core.algorithm.acceptor.*;
|
import jsprit.core.algorithm.acceptor.*;
|
||||||
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.*;
|
import jsprit.core.algorithm.io.VehicleRoutingAlgorithms.TypedMap.*;
|
||||||
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
|
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.PrioritizedVRAListener;
|
||||||
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.Priority;
|
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.Priority;
|
||||||
import jsprit.core.algorithm.module.RuinAndRecreateModule;
|
import jsprit.core.algorithm.module.RuinAndRecreateModule;
|
||||||
import jsprit.core.algorithm.recreate.InsertionStrategy;
|
import jsprit.core.algorithm.recreate.InsertionStrategy;
|
||||||
import jsprit.core.algorithm.recreate.VehicleSwitched;
|
|
||||||
import jsprit.core.algorithm.recreate.listener.InsertionListener;
|
import jsprit.core.algorithm.recreate.listener.InsertionListener;
|
||||||
import jsprit.core.algorithm.ruin.RadialRuinStrategyFactory;
|
import jsprit.core.algorithm.ruin.RadialRuinStrategyFactory;
|
||||||
import jsprit.core.algorithm.ruin.RandomRuinStrategyFactory;
|
import jsprit.core.algorithm.ruin.RandomRuinStrategyFactory;
|
||||||
|
|
@ -576,23 +574,14 @@ public class VehicleRoutingAlgorithms {
|
||||||
if(solutionCostCalculator==null) costCalculator = getDefaultCostCalculator(stateManager);
|
if(solutionCostCalculator==null) costCalculator = getDefaultCostCalculator(stateManager);
|
||||||
else costCalculator = solutionCostCalculator;
|
else costCalculator = solutionCostCalculator;
|
||||||
|
|
||||||
|
PrettyAlgorithmBuilder prettyAlgorithmBuilder = PrettyAlgorithmBuilder.newInstance(vrp,vehicleFleetManager,stateManager,constraintManager);
|
||||||
//construct initial solution creator
|
//construct initial solution creator
|
||||||
final InsertionStrategy initialInsertionStrategy = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,costCalculator, constraintManager, addDefaultCostCalculators);
|
final InsertionStrategy initialInsertionStrategy = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,costCalculator, constraintManager, addDefaultCostCalculators);
|
||||||
if(initialInsertionStrategy != null) algorithmListeners.add(new PrioritizedVRAListener(Priority.MEDIUM, new AlgorithmStartsListener() {
|
if(initialInsertionStrategy != null) prettyAlgorithmBuilder.constructInitialSolutionWith(initialInsertionStrategy,costCalculator);
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection<VehicleRoutingProblemSolution> solutions) {
|
|
||||||
InsertionInitialSolutionFactory insertionInitialSolutionFactory = new InsertionInitialSolutionFactory(initialInsertionStrategy, costCalculator);
|
|
||||||
VehicleRoutingProblemSolution vrpSol = insertionInitialSolutionFactory.createSolution(vrp);
|
|
||||||
solutions.add(vrpSol);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
//construct algorithm, i.e. search-strategies and its modules
|
//construct algorithm, i.e. search-strategies and its modules
|
||||||
int solutionMemory = config.getInt("strategy.memory");
|
int solutionMemory = config.getInt("strategy.memory");
|
||||||
SearchStrategyManager searchStratManager = new SearchStrategyManager();
|
List<HierarchicalConfiguration> strategyConfigs = config.configurationsAt("strategy.searchStrategies.searchStrategy");
|
||||||
List<HierarchicalConfiguration> strategyConfigs = config.configurationsAt("strategy.searchStrategies.searchStrategy");
|
|
||||||
for(HierarchicalConfiguration strategyConfig : strategyConfigs){
|
for(HierarchicalConfiguration strategyConfig : strategyConfigs){
|
||||||
String name = getName(strategyConfig);
|
String name = getName(strategyConfig);
|
||||||
SolutionAcceptor acceptor = getAcceptor(strategyConfig,vrp,algorithmListeners,definedClasses,solutionMemory);
|
SolutionAcceptor acceptor = getAcceptor(strategyConfig,vrp,algorithmListeners,definedClasses,solutionMemory);
|
||||||
|
|
@ -605,14 +594,13 @@ public class VehicleRoutingAlgorithms {
|
||||||
SearchStrategyModule module = buildModule(moduleConfig,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads, constraintManager, addDefaultCostCalculators);
|
SearchStrategyModule module = buildModule(moduleConfig,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads, constraintManager, addDefaultCostCalculators);
|
||||||
strategy.addModule(module);
|
strategy.addModule(module);
|
||||||
}
|
}
|
||||||
searchStratManager.addStrategy(strategy, strategyConfig.getDouble("probability"));
|
prettyAlgorithmBuilder.withStrategy(strategy,strategyConfig.getDouble("probability"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//construct algorithm
|
//construct algorithm
|
||||||
VehicleRoutingAlgorithm metaAlgorithm = new VehicleRoutingAlgorithm(vrp, searchStratManager);
|
VehicleRoutingAlgorithm metaAlgorithm = prettyAlgorithmBuilder.build();
|
||||||
String maxIterationsString = config.getString("iterations");
|
int maxIterations = getMaxIterations(config);
|
||||||
if(maxIterationsString == null) maxIterationsString = config.getString("maxIterations");
|
if(maxIterations > -1) metaAlgorithm.setMaxIterations(maxIterations);
|
||||||
if(maxIterationsString != null) metaAlgorithm.setMaxIterations(Integer.parseInt(maxIterationsString));
|
|
||||||
|
|
||||||
//define prematureBreak
|
//define prematureBreak
|
||||||
PrematureAlgorithmTermination prematureAlgorithmTermination = getPrematureTermination(config, algorithmListeners);
|
PrematureAlgorithmTermination prematureAlgorithmTermination = getPrematureTermination(config, algorithmListeners);
|
||||||
|
|
@ -624,32 +612,17 @@ public class VehicleRoutingAlgorithms {
|
||||||
if(termination != null) metaAlgorithm.addTerminationCriterion(termination);
|
if(termination != null) metaAlgorithm.addTerminationCriterion(termination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return metaAlgorithm;
|
||||||
RemoveEmptyVehicles removeEmptyVehicles = new RemoveEmptyVehicles(vehicleFleetManager);
|
|
||||||
ResetAndIniFleetManager resetAndIniFleetManager = new ResetAndIniFleetManager(vehicleFleetManager);
|
|
||||||
VehicleSwitched vehicleSwitched = new VehicleSwitched(vehicleFleetManager);
|
|
||||||
|
|
||||||
metaAlgorithm.addListener(stateManager);
|
|
||||||
metaAlgorithm.addListener(removeEmptyVehicles);
|
|
||||||
metaAlgorithm.addListener(resetAndIniFleetManager);
|
|
||||||
metaAlgorithm.addListener(vehicleSwitched);
|
|
||||||
|
|
||||||
if(initialInsertionStrategy != null) {
|
|
||||||
if(initialInsertionStrategy.getListeners() != null){
|
|
||||||
if(!initialInsertionStrategy.getListeners().contains(stateManager)) initialInsertionStrategy.addListener(stateManager);
|
|
||||||
if(!initialInsertionStrategy.getListeners().contains(removeEmptyVehicles)) initialInsertionStrategy.addListener(removeEmptyVehicles);
|
|
||||||
if(!initialInsertionStrategy.getListeners().contains(resetAndIniFleetManager)) initialInsertionStrategy.addListener(resetAndIniFleetManager);
|
|
||||||
if(!initialInsertionStrategy.getListeners().contains(vehicleSwitched)) initialInsertionStrategy.addListener(vehicleSwitched);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//register listeners
|
|
||||||
registerListeners(metaAlgorithm, algorithmListeners);
|
|
||||||
registerInsertionListeners(definedClasses,insertionListeners);
|
|
||||||
return metaAlgorithm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SolutionCostCalculator getDefaultCostCalculator(final StateManager stateManager) {
|
private static int getMaxIterations(XMLConfiguration config) {
|
||||||
|
String maxIterationsString = config.getString("iterations");
|
||||||
|
if(maxIterationsString == null) maxIterationsString = config.getString("maxIterations");
|
||||||
|
if(maxIterationsString != null) return (Integer.parseInt(maxIterationsString));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SolutionCostCalculator getDefaultCostCalculator(final StateManager stateManager) {
|
||||||
return new VariablePlusFixedSolutionCostCalculatorFactory(stateManager).createCalculator();
|
return new VariablePlusFixedSolutionCostCalculatorFactory(stateManager).createCalculator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -739,30 +712,12 @@ public class VehicleRoutingAlgorithms {
|
||||||
throw new IllegalStateException("prematureBreak basedOn " + basedOn + " is not defined");
|
throw new IllegalStateException("prematureBreak basedOn " + basedOn + " is not defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerInsertionListeners(TypedMap definedClasses, List<InsertionListener> insertionListeners) {
|
private static String getName(HierarchicalConfiguration strategyConfig) { if(strategyConfig.containsKey("[@name]")){
|
||||||
for(AbstractKey<?> key : definedClasses.keySet()){
|
|
||||||
if(key instanceof InsertionStrategyKey){
|
|
||||||
InsertionStrategyKey insertionKey = (InsertionStrategyKey) key;
|
|
||||||
InsertionStrategy insertionStrategy = definedClasses.get(insertionKey);
|
|
||||||
for(InsertionListener l : insertionListeners){
|
|
||||||
insertionStrategy.addListener(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getName(HierarchicalConfiguration strategyConfig) {
|
|
||||||
if(strategyConfig.containsKey("[@name]")){
|
|
||||||
return strategyConfig.getString("[@name]");
|
return strategyConfig.getString("[@name]");
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void registerListeners(VehicleRoutingAlgorithm metaAlgorithm, Set<PrioritizedVRAListener> algorithmListeners) {
|
|
||||||
metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static InsertionStrategy createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManager routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, final SolutionCostCalculator solutionCostCalculator, ConstraintManager constraintManager, boolean addDefaultCostCalculators) {
|
private static InsertionStrategy createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManager routeStates, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, final SolutionCostCalculator solutionCostCalculator, ConstraintManager constraintManager, boolean addDefaultCostCalculators) {
|
||||||
List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
|
List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
|
||||||
if(modConfigs == null) return null;
|
if(modConfigs == null) return null;
|
||||||
|
|
@ -782,12 +737,8 @@ public class VehicleRoutingAlgorithms {
|
||||||
algorithmListeners.addAll(prioListeners);
|
algorithmListeners.addAll(prioListeners);
|
||||||
definedClasses.put(insertionStrategyKey,insertionStrategy);
|
definedClasses.put(insertionStrategyKey,insertionStrategy);
|
||||||
}
|
}
|
||||||
final InsertionStrategy finalInsertionStrategy = insertionStrategy;
|
return insertionStrategy;
|
||||||
|
}
|
||||||
return finalInsertionStrategy;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SolutionSelector getSelector(HierarchicalConfiguration strategyConfig, VehicleRoutingProblem vrp, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedSelectors) {
|
private static SolutionSelector getSelector(HierarchicalConfiguration strategyConfig, VehicleRoutingProblem vrp, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedSelectors) {
|
||||||
String selectorName = strategyConfig.getString("selector[@name]");
|
String selectorName = strategyConfig.getString("selector[@name]");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue