diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/PrettyAlgorithmBuilder.java b/jsprit-core/src/main/java/jsprit/core/algorithm/PrettyAlgorithmBuilder.java new file mode 100644 index 00000000..7d33fb35 --- /dev/null +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/PrettyAlgorithmBuilder.java @@ -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 . + ******************************************************************************/ + +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 get(VehicleRoute vehicleRoute) { + Collection vehicles = new ArrayList(); + 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 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; + } + +} diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java b/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java index b5a30750..4bedad44 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java @@ -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; @@ -575,24 +573,15 @@ public class VehicleRoutingAlgorithms { final SolutionCostCalculator costCalculator; 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 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 strategyConfigs = config.configurationsAt("strategy.searchStrategies.searchStrategy"); + List 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 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 algorithmListeners) { - metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners); - } - private static InsertionStrategy createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManager routeStates, Set algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, final SolutionCostCalculator solutionCostCalculator, ConstraintManager constraintManager, boolean addDefaultCostCalculators) { List 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 algorithmListeners, TypedMap definedSelectors) { String selectorName = strategyConfig.getString("selector[@name]");