1
0
Fork 0
mirror of https://github.com/graphhopper/jsprit.git synced 2020-01-24 07:45:05 +01:00

add infrastructure towards adaptive/dynamic search strategies

This commit is contained in:
oblonski 2014-11-22 12:37:22 +01:00
parent a32a750bed
commit 64b5d77267
3 changed files with 79 additions and 64 deletions

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder * Copyright (C) 2014 Stefan Schroeder
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -61,24 +61,31 @@ public class SearchStrategy {
private static Logger logger = LogManager.getLogger(SearchStrategy.class); private static Logger logger = LogManager.getLogger(SearchStrategy.class);
private Collection<SearchStrategyModule> searchStrategyModules = new ArrayList<SearchStrategyModule>(); private final Collection<SearchStrategyModule> searchStrategyModules = new ArrayList<SearchStrategyModule>();
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; private String name;
public SearchStrategy(SolutionSelector solutionSelector, SolutionAcceptor solutionAcceptor, SolutionCostCalculator solutionCostCalculator) { public SearchStrategy(String id, SolutionSelector solutionSelector, SolutionAcceptor solutionAcceptor, SolutionCostCalculator solutionCostCalculator) {
super(); if(id == null) throw new IllegalStateException("strategy id cannot be null");
this.solutionSelector = solutionSelector; this.solutionSelector = solutionSelector;
this.solutionAcceptor = solutionAcceptor; this.solutionAcceptor = solutionAcceptor;
this.solutionCostCalculator = solutionCostCalculator; this.solutionCostCalculator = solutionCostCalculator;
this.id = id;
logger.info("initialise " + this); logger.info("initialise " + this);
} }
public String getId() {
return id;
}
public String getName() { public String getName() {
return name; return name;
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (C) 2013 Stefan Schroeder * Copyright (C) 2014 Stefan Schroeder
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -20,11 +20,7 @@ import jsprit.core.algorithm.listener.SearchStrategyListener;
import jsprit.core.algorithm.listener.SearchStrategyModuleListener; import jsprit.core.algorithm.listener.SearchStrategyModuleListener;
import jsprit.core.util.RandomNumberGeneration; import jsprit.core.util.RandomNumberGeneration;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class SearchStrategyManager { public class SearchStrategyManager {
@ -33,11 +29,15 @@ public class SearchStrategyManager {
private List<SearchStrategy> strategies = new ArrayList<SearchStrategy>(); private List<SearchStrategy> strategies = new ArrayList<SearchStrategy>();
private List<Double> probabilities = new ArrayList<Double>(); private List<Double> weights = new ArrayList<Double>();
private Map<String, Integer> id2index = new HashMap<String,Integer>();
private Random random = RandomNumberGeneration.getRandom(); private Random random = RandomNumberGeneration.getRandom();
private double sumOfProbabilities = 0; private double sumWeights = 0;
private int strategyIndex = 0;
public void setRandom(Random random) { public void setRandom(Random random) {
this.random = random; this.random = random;
@ -49,32 +49,51 @@ 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<Double> getProbabilities() { public List<Double> 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 strategy strategy to be added
* @param probability probability of corresponding strategy to be added * @param weight of corresponding strategy to be added
* @throws java.lang.IllegalStateException if strategy is null OR prob > 1. OR prob < 0. * @throws java.lang.IllegalStateException if strategy is null OR weight < 0
*/ */
public void addStrategy(SearchStrategy strategy, double probability){ public void addStrategy(SearchStrategy strategy, double weight){
if(strategy == null){ if(strategy == null){
throw new IllegalStateException("strategy is null. make sure adding a valid strategy."); throw new IllegalStateException("strategy is null. make sure adding a valid strategy.");
} }
if(probability > 1.0){ if(id2index.keySet().contains(strategy.getId())){
throw new IllegalStateException("probability is higher than one, but it must be within [0,1]."); throw new IllegalStateException("strategyId " + strategy.getId() + " already in use");
} }
if(probability < 0.0){ if(weight < 0.0){
throw new IllegalStateException("probability is lower than zero, but it must be within [0,1]."); throw new IllegalStateException("weight is lower than zero.");
} }
id2index.put(strategy.getId(),strategyIndex);
strategyIndex++;
strategies.add(strategy); strategies.add(strategy);
probabilities.add(probability); weights.add(weight);
sumOfProbabilities += probability; sumWeights += weight;
if(sumOfProbabilities > 1.0){
throw new IllegalStateException("total probability of all strategies is higher than one, but it must be within [0,1].");
} }
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;
} }
/** /**
@ -86,10 +105,10 @@ public class SearchStrategyManager {
public SearchStrategy getRandomStrategy() { public SearchStrategy getRandomStrategy() {
if(random == null) throw new IllegalStateException("randomizer is null. make sure you set random object correctly"); if(random == null) throw new IllegalStateException("randomizer is null. make sure you set random object correctly");
double randomFig = random.nextDouble(); double randomFig = random.nextDouble();
double sumWeight = 0.0; double sumProbabilities = 0.0;
for (int i = 0; i < probabilities.size(); i++) { for (int i = 0; i < weights.size(); i++) {
sumWeight += probabilities.get(i); sumProbabilities += weights.get(i) / sumWeights;
if (randomFig < sumWeight) { if (randomFig < sumProbabilities) {
return strategies.get(i); return strategies.get(i);
} }
} }

View file

@ -193,7 +193,6 @@ public class VehicleRoutingAlgorithm {
logger.info("------------------------------------------------"); logger.info("------------------------------------------------");
logger.info("algorithm starts"); logger.info("algorithm starts");
double now = System.currentTimeMillis(); double now = System.currentTimeMillis();
verify();
int noIterationsThisAlgoIsRunning = maxIterations; int noIterationsThisAlgoIsRunning = maxIterations;
counter.reset(); counter.reset();
Collection<VehicleRoutingProblemSolution> solutions = new ArrayList<VehicleRoutingProblemSolution>(initialSolutions); Collection<VehicleRoutingProblemSolution> solutions = new ArrayList<VehicleRoutingProblemSolution>(initialSolutions);
@ -249,16 +248,6 @@ public class VehicleRoutingAlgorithm {
return maxIterations; 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<VehicleRoutingProblemSolution> solutions) { private void algorithmEnds(VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
algoListeners.algorithmEnds(problem, solutions); algoListeners.algorithmEnds(problem, solutions);