1 /* 2 * Copyright (C) 2013 Alberto Irurueta Carro (alberto@irurueta.com) 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.irurueta.numerical.robust; 17 18 /** 19 * Base class to pick subsets of samples. 20 */ 21 public abstract class SubsetSelector { 22 23 /** 24 * Constant defining minimum amount of allowed samples. 25 */ 26 public static final int MIN_NUM_SAMPLES = 1; 27 28 /** 29 * Defines default subset selector type. 30 */ 31 public static final SubsetSelectorType DEFAULT_SUBSET_SELECTOR_TYPE = 32 SubsetSelectorType.FAST_RANDOM_SUBSET_SELECTOR; 33 34 /** 35 * Total number of samples to pick subsets from. 36 * Subsets need to be always smaller or equal than total number of samples. 37 */ 38 protected int numSamples; 39 40 /** 41 * Constructor. 42 * 43 * @param numSamples number of samples to select subsets from. 44 * @throws IllegalArgumentException if provided number of samples is zero 45 * or negative. 46 */ 47 protected SubsetSelector(final int numSamples) { 48 setNumSamples(numSamples); 49 } 50 51 /** 52 * Returns number of samples to select subsets from. 53 * 54 * @return number of samples to select subsets from. 55 */ 56 public int getNumSamples() { 57 return numSamples; 58 } 59 60 /** 61 * Sets number of samples to select subsets from. 62 * 63 * @param numSamples number of samples to select subsets from. 64 * @throws IllegalArgumentException if provided number of samples is zero or 65 * negative. 66 */ 67 public final void setNumSamples(final int numSamples) { 68 if (numSamples < MIN_NUM_SAMPLES) { 69 throw new IllegalArgumentException(); 70 } 71 this.numSamples = numSamples; 72 } 73 74 /** 75 * Computes a random subset of indices within range of number of samples to 76 * be used on robust estimators. 77 * If subsets need to be computed repeatedly in a small span of time then it 78 * is suggested to use computeRandomSubsets(int, int[]) for better memory 79 * usage. 80 * 81 * @param subsetSize subset size to be computed. This value must be smaller 82 * than total number of samples. 83 * @return array containing indices to be picked. 84 * @throws NotEnoughSamplesException if subset size is greater than the 85 * total number of samples. 86 * @throws InvalidSubsetSizeException if subset size is zero or if result 87 * array does not have at least a length of subsetSize. 88 * @see #computeRandomSubsets(int, int[]) 89 */ 90 public int[] computeRandomSubsets(final int subsetSize) throws NotEnoughSamplesException, 91 InvalidSubsetSizeException { 92 final var result = new int[subsetSize]; 93 computeRandomSubsets(subsetSize, result); 94 return result; 95 } 96 97 /** 98 * Computes a random subset of indices within provided range of positions to 99 * be used on robust estimators. 100 * If subsets need to be computed repeatedly in a small span of time then it 101 * is suggested to use computeRandomSubsets(int, int, int, bool, int[]) for 102 * better memory usage. 103 * 104 * @param minPos minimum position to be picked. This value must be greater 105 * or equal than zero and smaller than the total number of samples and less 106 * than maxPos. 107 * @param maxPos maximum position to be picked. This value must be greater 108 * or equal than zero and smaller than the total number of samples and 109 * greater than minPos. 110 * @param subsetSize subset size to be computed. This value must be smaller 111 * than total number of samples. 112 * @param pickLast true indicates that last sample in range must always be 113 * picked within subset. This is done to obtain faster execution times and 114 * greater stability on some algorithms. 115 * @return array containing indices to be picked. 116 * @throws NotEnoughSamplesException if subset size is greater than the 117 * total number of samples or if maxPos is greater than the total number of 118 * samples. 119 * @throws InvalidSubsetSizeException if subset size is zero, or if subset 120 * size is greater than the allowed range of positions to be picked. 121 * @throws InvalidSubsetRangeException if maximum position is smaller than 122 * minimum position or maximum or minimum position are negative. 123 */ 124 public int[] computeRandomSubsetsInRange( 125 final int minPos, final int maxPos, final int subsetSize, final boolean pickLast) 126 throws NotEnoughSamplesException, InvalidSubsetSizeException, InvalidSubsetRangeException { 127 final var result = new int[subsetSize]; 128 computeRandomSubsetsInRange(minPos, maxPos, subsetSize, pickLast, result); 129 return result; 130 } 131 132 /** 133 * Returns type of this subset selector. 134 * 135 * @return type of this subset selector. 136 */ 137 public abstract SubsetSelectorType getType(); 138 139 /** 140 * Computes a random subset of indices within range of number of samples to 141 * be used on robust estimators. 142 * 143 * @param subsetSize subset size to be computed. This value must be smaller 144 * than total number of samples. 145 * @param result array containing indices to be picked. Provided array must 146 * be at least of length subsetSize. The former subsetSize entries of the 147 * array will be modified by this method. 148 * @throws NotEnoughSamplesException if subset size is greater than the 149 * total number of samples. 150 * @throws InvalidSubsetSizeException if subset size is zero or if result 151 * array does not have at least a length of subsetSize. 152 */ 153 public abstract void computeRandomSubsets(final int subsetSize, final int[] result) 154 throws NotEnoughSamplesException, InvalidSubsetSizeException; 155 156 /** 157 * Computes a random subset of indices within provided range of positions to 158 * be used on robust estimators. 159 * 160 * @param minPos minimum position to be picked. This value must be greater 161 * or equal than zero and smaller than the total number of samples and less 162 * than maxPos. 163 * @param maxPos maximum position to be picked. This value must be greater 164 * or equal than zero and smaller than the total number of samples and 165 * greater than minPos. 166 * @param subsetSize subset size to be computed. This value must be smaller 167 * than total number of samples. 168 * @param pickLast true indicates that last sample in range must always be 169 * picked within subset. This is done to obtain faster execution times and 170 * greater stability on some algorithms. 171 * @param result array containing indices to be picked. Provided array must 172 * be at least of length subsetSize. The former subsetSize entries of the 173 * array will be modified by this method. 174 * @throws NotEnoughSamplesException if subset size is greater than the 175 * total number of samples or if maxPos is greater than the total number of 176 * samples. 177 * @throws InvalidSubsetSizeException if subset size is zero or if result 178 * array does not have at least a length of subsetSize, or if subset size 179 * is greater than the allowed range of positions to be picked. 180 * @throws InvalidSubsetRangeException if maximum position is smaller than 181 * minimum position or maximum or minimum position are negative. 182 */ 183 public abstract void computeRandomSubsetsInRange(final int minPos, final int maxPos, final int subsetSize, 184 final boolean pickLast, final int[] result) throws NotEnoughSamplesException, InvalidSubsetSizeException, 185 InvalidSubsetRangeException; 186 187 /** 188 * Creates a new subset selector instance using provided total number of 189 * samples and default subset selector type. 190 * 191 * @param numSamples number of samples to select subsets from. 192 * @return a subset selector. 193 * @throws IllegalArgumentException if provided number of samples is zero or 194 * negative. 195 */ 196 public static SubsetSelector create(final int numSamples) { 197 return new FastRandomSubsetSelector(numSamples); 198 } 199 }