org.jamesframework.core.search.algo.exh.SubsetSolutionIterator Maven / Gradle / Ivy
Show all versions of james-core Show documentation
// Copyright 2014 Herman De Beukelaer // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package org.jamesframework.core.search.algo.exh; import java.util.NoSuchElementException; import java.util.Set; import org.jamesframework.core.problems.solutions.SubsetSolution; /** * A subset solution iterator generates all possible subsets within a given size range, given a * set of IDs from which to select. It can be plugged into an exhaustive search algorithm * to generate and evaluate all possible subset solutions. *
is* The implemented generation algorithm is the revolving door algorithm from * "Combinatorial Algorithms: Generation, Enumeration and Search", Donald Kreher * and Douglas Stinson, CRC Press, 1999 (chapter 2, p. 43-52). This algorithm generates * k-subsets in a specific minimal change ordering called the revolving door ordering. * * @author Herman De Beukelaer */ public class SubsetSolutionIterator implements SolutionIterator
{ // maximum subset size private final int maxSubsetSize; // collection of IDs to select from private final Set IDs; // array representation (arbitrary order) private final Integer[] IDsArray; // indices (in IDs array) of IDs selected in next generated subset solution // NOTE: last element of t is a dummy element set to |IDs| private int[] t; /** * Create a subset solution iterator that generates all subsets within the given size range, * sampled from the given set of IDs. * * @param IDs set of IDs to select from * @param minSubsetSize minimum subset size * @param maxSubsetSize maximum subset size * @throws NullPointerException if IDs
isnull
* @throws IllegalArgumentException ifIDs
is empty, *minSubsetSize ≤ 0
, *minSubsetSize > |IDs|
, * orminSubsetSize > maxSubsetSize
*/ public SubsetSolutionIterator(SetIDs, int minSubsetSize, int maxSubsetSize){ // check collection of IDs if(IDs.isEmpty()){ throw new IllegalArgumentException("Error while creating subset solution iterator: collection of IDs to select from " + "can not be empty."); } // store set of IDs this.IDs = IDs; // convert set of IDs to array (impose arbitrary order) this.IDsArray = IDs.toArray(new Integer[0]); // check minimum/maximum size if(minSubsetSize <= 0){ throw new IllegalArgumentException("Error while creating subset solution iterator: minimum subset size should be " + "strictly positive."); } if(minSubsetSize > IDs.size()){ throw new IllegalArgumentException("Error while creating subset solution iterator: minimum subset size can not be " + "larger than number of IDs to select from."); } if(minSubsetSize > maxSubsetSize){ throw new IllegalArgumentException("Error while creating subset solution iterator: minimum subset size can not be " + "larger than maximum subset size."); } // set indices of selected IDs in first generated solution (t = {0,1,...,k-1}, with k = minimum subset size) t = new int[minSubsetSize+1]; for(int i=0; i IDs null
* @throws IllegalArgumentException ifIDs
is empty, *fixedSubsetSize ≤ 0
, * orfixedSubsetSize > |IDs|
*/ public SubsetSolutionIterator(SetIDs, int fixedSubsetSize){ this(IDs, fixedSubsetSize, fixedSubsetSize); } /** * Checks whether more subset solutions are to be generated. * * @return true
if not all possible subsets of all valid size have already been generated */ @Override public boolean hasNext() { return t != null; } /** * Generate the next subset solution. The returned subset will either have the same size as the previously generated solution, * if any, or it will be a larger subset. * * @return next subset solution within the size bounds * @throws NoSuchElementException if there is no next solution to be generated */ @Override public SubsetSolution next() { // check if there is a next solution to generate if(!hasNext()){ throw new NoSuchElementException("No more subset solutions to be generated."); } // create subset solution based on currently selected indices (returned at the end of the method) SubsetSolution sol = new SubsetSolution(IDs); for(int i=0; i= 0){ t[j-2] = j-1; } } } else { if(t[j+1] != t[j]+1){ if(j-1 >= 0){ t[j-1] = t[j]; } t[j] = t[j] + 1; } else { t[j+1] = t[j]; t[j] = j; } } } // return current solution return sol; } }