1
0
Fork 0
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:
oblonski 2014-12-10 20:24:57 +01:00
parent 7ce6a8d68a
commit 593cd5e841
2 changed files with 173 additions and 71 deletions

View file

@ -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;
}
}

View file

@ -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,22 +574,13 @@ 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);
@ -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,31 +612,16 @@ public class VehicleRoutingAlgorithms {
if(termination != null) metaAlgorithm.addTerminationCriterion(termination); if(termination != null) metaAlgorithm.addTerminationCriterion(termination);
} }
} }
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; return metaAlgorithm;
} }
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) { 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,11 +737,7 @@ 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) {