From 64b5d77267fd579a992090509c50c99f1f04c0b1 Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Sat, 22 Nov 2014 12:37:22 +0100 Subject: [PATCH] add infrastructure towards adaptive/dynamic search strategies --- .../jsprit/core/algorithm/SearchStrategy.java | 43 +++++---- .../core/algorithm/SearchStrategyManager.java | 87 +++++++++++-------- .../algorithm/VehicleRoutingAlgorithm.java | 13 +-- 3 files changed, 79 insertions(+), 64 deletions(-) diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategy.java b/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategy.java index 6a13beab..e93ca090 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategy.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategy.java @@ -1,16 +1,16 @@ /******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * + * 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 + * 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 . ******************************************************************************/ @@ -61,25 +61,32 @@ public class SearchStrategy { private static Logger logger = LogManager.getLogger(SearchStrategy.class); - private Collection searchStrategyModules = new ArrayList(); + private final Collection searchStrategyModules = new ArrayList(); - private SolutionSelector solutionSelector; + private final SolutionSelector solutionSelector; - private SolutionCostCalculator solutionCostCalculator; + private final SolutionCostCalculator solutionCostCalculator; - private SolutionAcceptor solutionAcceptor; + private final SolutionAcceptor solutionAcceptor; + + private final String id; private String name; - - public SearchStrategy(SolutionSelector solutionSelector, SolutionAcceptor solutionAcceptor, SolutionCostCalculator solutionCostCalculator) { - super(); - this.solutionSelector = solutionSelector; - this.solutionAcceptor = solutionAcceptor; - this.solutionCostCalculator = solutionCostCalculator; - logger.info("initialise " + this); - } - public String getName() { + public SearchStrategy(String id, SolutionSelector solutionSelector, SolutionAcceptor solutionAcceptor, SolutionCostCalculator solutionCostCalculator) { + if(id == null) throw new IllegalStateException("strategy id cannot be null"); + this.solutionSelector = solutionSelector; + this.solutionAcceptor = solutionAcceptor; + this.solutionCostCalculator = solutionCostCalculator; + this.id = id; + logger.info("initialise " + this); + } + + public String getId() { + return id; + } + + public String getName() { return name; } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategyManager.java b/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategyManager.java index fb38c740..4ddfd6ba 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategyManager.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategyManager.java @@ -1,16 +1,16 @@ /******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * + * 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 + * 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 . ******************************************************************************/ @@ -20,11 +20,7 @@ import jsprit.core.algorithm.listener.SearchStrategyListener; import jsprit.core.algorithm.listener.SearchStrategyModuleListener; import jsprit.core.util.RandomNumberGeneration; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Random; - +import java.util.*; public class SearchStrategyManager { @@ -33,11 +29,15 @@ public class SearchStrategyManager { private List strategies = new ArrayList(); - private List probabilities = new ArrayList(); + private List weights = new ArrayList(); + + private Map id2index = new HashMap(); private Random random = RandomNumberGeneration.getRandom(); - private double sumOfProbabilities = 0; + private double sumWeights = 0; + + private int strategyIndex = 0; public void setRandom(Random random) { this.random = random; @@ -49,34 +49,53 @@ public class SearchStrategyManager { } + /** + * Returns the probabilities. + * [schroeder (2014.11.21): Now they are actually no propabilities anymore but weights. The resulting probabilities + * are calculated here with the sum of weights] + * @return list of probabilities + */ public List getProbabilities() { - return Collections.unmodifiableList(probabilities); + return Collections.unmodifiableList(weights); } /** - * adds a new search strategy. the probability must be within [0,1]. + * adds a new search strategy with a certain weight. * @param strategy strategy to be added - * @param probability probability of corresponding strategy to be added - * @throws java.lang.IllegalStateException if strategy is null OR prob > 1. OR prob < 0. + * @param weight of corresponding strategy to be added + * @throws java.lang.IllegalStateException if strategy is null OR weight < 0 */ - public void addStrategy(SearchStrategy strategy, double probability){ - if(strategy == null){ - throw new IllegalStateException("strategy is null. make sure adding a valid strategy."); - } - if(probability > 1.0){ - throw new IllegalStateException("probability is higher than one, but it must be within [0,1]."); - } - if(probability < 0.0){ - throw new IllegalStateException("probability is lower than zero, but it must be within [0,1]."); + public void addStrategy(SearchStrategy strategy, double weight){ + if(strategy == null){ + throw new IllegalStateException("strategy is null. make sure adding a valid strategy."); + } + if(id2index.keySet().contains(strategy.getId())){ + throw new IllegalStateException("strategyId " + strategy.getId() + " already in use"); + } + if(weight < 0.0){ + throw new IllegalStateException("weight is lower than zero."); } + id2index.put(strategy.getId(),strategyIndex); + strategyIndex++; strategies.add(strategy); - probabilities.add(probability); - sumOfProbabilities += probability; - if(sumOfProbabilities > 1.0){ - throw new IllegalStateException("total probability of all strategies is higher than one, but it must be within [0,1]."); - } + weights.add(weight); + sumWeights += weight; } + public void informStrategyWeightChanged(String strategyId, double weight){ + int strategyIndex = id2index.get(strategyId); + weights.set(strategyIndex, weight); + updateSumWeights(); + } + + private void updateSumWeights() { + double sum = 0.; + for(double w : weights){ + sum += w; + } + sumWeights = sum; + } + /** * Returns search strategy that has been randomly selected. * @@ -86,10 +105,10 @@ public class SearchStrategyManager { public SearchStrategy getRandomStrategy() { if(random == null) throw new IllegalStateException("randomizer is null. make sure you set random object correctly"); double randomFig = random.nextDouble(); - double sumWeight = 0.0; - for (int i = 0; i < probabilities.size(); i++) { - sumWeight += probabilities.get(i); - if (randomFig < sumWeight) { + double sumProbabilities = 0.0; + for (int i = 0; i < weights.size(); i++) { + sumProbabilities += weights.get(i) / sumWeights; + if (randomFig < sumProbabilities) { return strategies.get(i); } } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/VehicleRoutingAlgorithm.java b/jsprit-core/src/main/java/jsprit/core/algorithm/VehicleRoutingAlgorithm.java index 7367815b..9fbaa97a 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/VehicleRoutingAlgorithm.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/VehicleRoutingAlgorithm.java @@ -193,7 +193,6 @@ public class VehicleRoutingAlgorithm { logger.info("------------------------------------------------"); logger.info("algorithm starts"); double now = System.currentTimeMillis(); - verify(); int noIterationsThisAlgoIsRunning = maxIterations; counter.reset(); Collection solutions = new ArrayList(initialSolutions); @@ -248,17 +247,7 @@ public class VehicleRoutingAlgorithm { public int getNuOfIterations(){ return maxIterations; } - - /** - * Asserts that the sum of probabilities of the searchStrategies is equal to 1.0. - */ - private void verify() { - double sum = 0.0; - for(Double prob : searchStrategyManager.getProbabilities()){ - sum += prob; - } - if(sum < 1.0*0.99 || sum > 1.0*1.01) throw new IllegalStateException("sum of probabilities is not 1.0, but is "+ sum + ". make sure that the sum of the probability of each searchStrategy is 1.0"); - } + private void algorithmEnds(VehicleRoutingProblem problem, Collection solutions) { algoListeners.algorithmEnds(problem, solutions);