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 }