/** * */ package vroom.common.heuristics.alns; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import umontreal.iro.lecuyer.rng.RandomStream; import vroom.common.utilities.Utilities; import vroom.common.utilities.Utilities.Random; import vroom.common.utilities.optimization.IInstance; import vroom.common.utilities.optimization.IParameters; import vroom.common.utilities.optimization.ISolution; import vroom.common.utilities.optimization.OptimizationSense; import vroom.common.utilities.optimization.SolutionComparator; /** * <code>SimpleSolutionPool</code> is an implementation of {@link IPALNSSolutionPool} that maintain a fixed size set of * solutions ordered according to their objective value. * <p> * Creation date: Nov 17, 2011 - 4:10:47 PM * * @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a * href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a * href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a> * @version 1.0 */ public class SimpleSolutionPool<S extends ISolution> implements IPALNSSolutionPool<S> { private final SortedSet<S> mSolutions; private final Set<S> mSolutionsView; private final OptimizationSense mSense; private final int mMaxSize; /** * Creates a new <code>SimpleSolutionPool</code> based on a {@link TreeSet} and {@link SolutionComparator} * * @param sense * the optimization sense * @param maxSize * the maximum number of solutions to keep in this pool */ public SimpleSolutionPool(OptimizationSense sense, ALNSGlobalParameters params) { this(sense, params.get(ALNSGlobalParameters.PALNS_POOL_SIZE), new TreeSet<S>( new SolutionComparator<S>(sense))); } /** * Creates a new <code>SimpleSolutionPool</code> * * @param sense * the optimization sense * @param maxSize * the maximum number of solutions to keep in this pool * @param solutions * an initial collection of solutions for this pool */ public SimpleSolutionPool(OptimizationSense sense, Integer maxSize, SortedSet<S> solutions) { mSolutions = solutions; mSense = sense; mMaxSize = maxSize; mSolutionsView = Collections.unmodifiableSet(mSolutions); } @Override public void initialize(IInstance instance, S solution, IParameters params) { }; @Override public boolean add(S solution, boolean mainIteration) { if (size() == mMaxSize) { // The pool is full S worst = getSolutionsInternal().first(); if (mSense.isBetter(worst.getObjectiveValue(), solution.getObjectiveValue(), false)) { // The solution is better than the worst solution from the pool, add it boolean added = getSolutionsInternal().add(solution); if (added) // The solution was not present, remove the worst to maintain the pool size getSolutionsInternal().remove(worst); return added; } else { // The solution is worst than the worst solution from the pool, reject it return false; } } else { // Pool is not full, add the solution to it return getSolutionsInternal().add(solution); } } @Override public void addAll(Collection<S> solutions, boolean mainIteration) { for (S s : solutions) add(s, mainIteration); } @Override public Collection<S> subset(int size, RandomStream rndStream) { return Random.sample(getSolutions(), size, rndStream); } @Override public final Iterator<S> iterator() { return getSolutions().iterator(); } @Override public final Set<S> getSolutions() { return mSolutionsView; } /** * Return the actual set containing the solutions (not the view returned by {@link #getSolutions()}) * * @return the set containing the solutions * @see #getSolutions() */ protected SortedSet<S> getSolutionsInternal() { return mSolutions; } @Override public S getBest() { return mSolutions.last(); } @Override public final int size() { return mSolutions.size(); } /** * Returns the maximum size of this solution pool * * @return the maximum size of this solution pool */ public final int getMaxSize() { return mMaxSize; } /** * Returns the optimization sense * * @return the optimization sense */ public final OptimizationSense getSense() { return mSense; } @Override public final boolean isFull() { return size() >= getMaxSize(); } @Override public void clear() { mSolutions.clear(); } @Override public String toString() { StringBuilder b = new StringBuilder(size() * 10); b.append("["); for (S sol : getSolutions()) { b.append(Utilities.format(sol.getObjective())); b.append(","); } if (b.length() > 1) b.setCharAt(b.length() - 1, ']'); else b.append(']'); return String.format("size:%s/%s %s", size(), mMaxSize, b); } }