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.io.VehicleRoutingAlgorithms.TypedMap.*;
|
||||
import jsprit.core.algorithm.listener.AlgorithmEndsListener;
|
||||
import jsprit.core.algorithm.listener.AlgorithmStartsListener;
|
||||
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
|
||||
import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.Priority;
|
||||
import jsprit.core.algorithm.module.RuinAndRecreateModule;
|
||||
import jsprit.core.algorithm.recreate.InsertionStrategy;
|
||||
import jsprit.core.algorithm.recreate.VehicleSwitched;
|
||||
import jsprit.core.algorithm.recreate.listener.InsertionListener;
|
||||
import jsprit.core.algorithm.ruin.RadialRuinStrategyFactory;
|
||||
import jsprit.core.algorithm.ruin.RandomRuinStrategyFactory;
|
||||
|
|
@ -576,23 +574,14 @@ public class VehicleRoutingAlgorithms {
|
|||
if(solutionCostCalculator==null) costCalculator = getDefaultCostCalculator(stateManager);
|
||||
else costCalculator = solutionCostCalculator;
|
||||
|
||||
PrettyAlgorithmBuilder prettyAlgorithmBuilder = PrettyAlgorithmBuilder.newInstance(vrp,vehicleFleetManager,stateManager,constraintManager);
|
||||
//construct initial solution creator
|
||||
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() {
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
}));
|
||||
if(initialInsertionStrategy != null) prettyAlgorithmBuilder.constructInitialSolutionWith(initialInsertionStrategy,costCalculator);
|
||||
|
||||
//construct algorithm, i.e. search-strategies and its modules
|
||||
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){
|
||||
String name = getName(strategyConfig);
|
||||
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);
|
||||
strategy.addModule(module);
|
||||
}
|
||||
searchStratManager.addStrategy(strategy, strategyConfig.getDouble("probability"));
|
||||
}
|
||||
prettyAlgorithmBuilder.withStrategy(strategy,strategyConfig.getDouble("probability"));
|
||||
}
|
||||
|
||||
//construct algorithm
|
||||
VehicleRoutingAlgorithm metaAlgorithm = new VehicleRoutingAlgorithm(vrp, searchStratManager);
|
||||
String maxIterationsString = config.getString("iterations");
|
||||
if(maxIterationsString == null) maxIterationsString = config.getString("maxIterations");
|
||||
if(maxIterationsString != null) metaAlgorithm.setMaxIterations(Integer.parseInt(maxIterationsString));
|
||||
VehicleRoutingAlgorithm metaAlgorithm = prettyAlgorithmBuilder.build();
|
||||
int maxIterations = getMaxIterations(config);
|
||||
if(maxIterations > -1) metaAlgorithm.setMaxIterations(maxIterations);
|
||||
|
||||
//define prematureBreak
|
||||
PrematureAlgorithmTermination prematureAlgorithmTermination = getPrematureTermination(config, algorithmListeners);
|
||||
|
|
@ -624,32 +612,17 @@ public class VehicleRoutingAlgorithms {
|
|||
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 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();
|
||||
}
|
||||
|
||||
|
|
@ -739,30 +712,12 @@ public class VehicleRoutingAlgorithms {
|
|||
throw new IllegalStateException("prematureBreak basedOn " + basedOn + " is not defined");
|
||||
}
|
||||
|
||||
private static void registerInsertionListeners(TypedMap definedClasses, List<InsertionListener> insertionListeners) {
|
||||
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]")){
|
||||
private static String getName(HierarchicalConfiguration strategyConfig) { if(strategyConfig.containsKey("[@name]")){
|
||||
return strategyConfig.getString("[@name]");
|
||||
}
|
||||
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) {
|
||||
List<HierarchicalConfiguration> modConfigs = config.configurationsAt("construction.insertion");
|
||||
if(modConfigs == null) return null;
|
||||
|
|
@ -782,12 +737,8 @@ public class VehicleRoutingAlgorithms {
|
|||
algorithmListeners.addAll(prioListeners);
|
||||
definedClasses.put(insertionStrategyKey,insertionStrategy);
|
||||
}
|
||||
final InsertionStrategy finalInsertionStrategy = insertionStrategy;
|
||||
|
||||
return finalInsertionStrategy;
|
||||
|
||||
|
||||
}
|
||||
return insertionStrategy;
|
||||
}
|
||||
|
||||
private static SolutionSelector getSelector(HierarchicalConfiguration strategyConfig, VehicleRoutingProblem vrp, Set<PrioritizedVRAListener> algorithmListeners, TypedMap definedSelectors) {
|
||||
String selectorName = strategyConfig.getString("selector[@name]");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue