View Javadoc
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 }