source: src/main/java/agents/anac/y2019/harddealer/math3/distribution/EnumeratedIntegerDistribution.java

Last change on this file was 204, checked in by Katsuhide Fujita, 5 years ago

Fixed errors of ANAC2019 agents

  • Property svn:executable set to *
File size: 9.7 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package agents.anac.y2019.harddealer.math3.distribution;
18
19import java.util.ArrayList;
20import java.util.HashMap;
21import java.util.List;
22import java.util.Map;
23import java.util.Map.Entry;
24
25import agents.anac.y2019.harddealer.math3.exception.DimensionMismatchException;
26import agents.anac.y2019.harddealer.math3.exception.MathArithmeticException;
27import agents.anac.y2019.harddealer.math3.exception.NotANumberException;
28import agents.anac.y2019.harddealer.math3.exception.NotFiniteNumberException;
29import agents.anac.y2019.harddealer.math3.exception.NotPositiveException;
30import agents.anac.y2019.harddealer.math3.random.RandomGenerator;
31import agents.anac.y2019.harddealer.math3.random.Well19937c;
32import agents.anac.y2019.harddealer.math3.util.Pair;
33
34/**
35 * <p>Implementation of an integer-valued {@link EnumeratedDistribution}.</p>
36 *
37 * <p>Values with zero-probability are allowed but they do not extend the
38 * support.<br/>
39 * Duplicate values are allowed. Probabilities of duplicate values are combined
40 * when computing cumulative probabilities and statistics.</p>
41 *
42 * @since 3.2
43 */
44public class EnumeratedIntegerDistribution extends AbstractIntegerDistribution {
45
46 /** Serializable UID. */
47 private static final long serialVersionUID = 20130308L;
48
49 /**
50 * {@link EnumeratedDistribution} instance (using the {@link Integer} wrapper)
51 * used to generate the pmf.
52 */
53 protected final EnumeratedDistribution<Integer> innerDistribution;
54
55 /**
56 * Create a discrete distribution using the given probability mass function
57 * definition.
58 * <p>
59 * <b>Note:</b> this constructor will implicitly create an instance of
60 * {@link Well19937c} as random generator to be used for sampling only (see
61 * {@link #sample()} and {@link #sample(int)}). In case no sampling is
62 * needed for the created distribution, it is advised to pass {@code null}
63 * as random generator via the appropriate constructors to avoid the
64 * additional initialisation overhead.
65 *
66 * @param singletons array of random variable values.
67 * @param probabilities array of probabilities.
68 * @throws DimensionMismatchException if
69 * {@code singletons.length != probabilities.length}
70 * @throws NotPositiveException if any of the probabilities are negative.
71 * @throws NotFiniteNumberException if any of the probabilities are infinite.
72 * @throws NotANumberException if any of the probabilities are NaN.
73 * @throws MathArithmeticException all of the probabilities are 0.
74 */
75 public EnumeratedIntegerDistribution(final int[] singletons, final double[] probabilities)
76 throws DimensionMismatchException, NotPositiveException, MathArithmeticException,
77 NotFiniteNumberException, NotANumberException{
78 this(new Well19937c(), singletons, probabilities);
79 }
80
81 /**
82 * Create a discrete distribution using the given random number generator
83 * and probability mass function definition.
84 *
85 * @param rng random number generator.
86 * @param singletons array of random variable values.
87 * @param probabilities array of probabilities.
88 * @throws DimensionMismatchException if
89 * {@code singletons.length != probabilities.length}
90 * @throws NotPositiveException if any of the probabilities are negative.
91 * @throws NotFiniteNumberException if any of the probabilities are infinite.
92 * @throws NotANumberException if any of the probabilities are NaN.
93 * @throws MathArithmeticException all of the probabilities are 0.
94 */
95 public EnumeratedIntegerDistribution(final RandomGenerator rng,
96 final int[] singletons, final double[] probabilities)
97 throws DimensionMismatchException, NotPositiveException, MathArithmeticException,
98 NotFiniteNumberException, NotANumberException {
99 super(rng);
100 innerDistribution = new EnumeratedDistribution<Integer>(
101 rng, createDistribution(singletons, probabilities));
102 }
103
104 /**
105 * Create a discrete integer-valued distribution from the input data. Values are assigned
106 * mass based on their frequency.
107 *
108 * @param rng random number generator used for sampling
109 * @param data input dataset
110 * @since 3.6
111 */
112 public EnumeratedIntegerDistribution(final RandomGenerator rng, final int[] data) {
113 super(rng);
114 final Map<Integer, Integer> dataMap = new HashMap<Integer, Integer>();
115 for (int value : data) {
116 Integer count = dataMap.get(value);
117 if (count == null) {
118 count = 0;
119 }
120 dataMap.put(value, ++count);
121 }
122 final int massPoints = dataMap.size();
123 final double denom = data.length;
124 final int[] values = new int[massPoints];
125 final double[] probabilities = new double[massPoints];
126 int index = 0;
127 for (Entry<Integer, Integer> entry : dataMap.entrySet()) {
128 values[index] = entry.getKey();
129 probabilities[index] = entry.getValue().intValue() / denom;
130 index++;
131 }
132 innerDistribution = new EnumeratedDistribution<Integer>(rng, createDistribution(values, probabilities));
133 }
134
135 /**
136 * Create a discrete integer-valued distribution from the input data. Values are assigned
137 * mass based on their frequency. For example, [0,1,1,2] as input creates a distribution
138 * with values 0, 1 and 2 having probability masses 0.25, 0.5 and 0.25 respectively,
139 *
140 * @param data input dataset
141 * @since 3.6
142 */
143 public EnumeratedIntegerDistribution(final int[] data) {
144 this(new Well19937c(), data);
145 }
146
147 /**
148 * Create the list of Pairs representing the distribution from singletons and probabilities.
149 *
150 * @param singletons values
151 * @param probabilities probabilities
152 * @return list of value/probability pairs
153 */
154 private static List<Pair<Integer, Double>> createDistribution(int[] singletons, double[] probabilities) {
155 if (singletons.length != probabilities.length) {
156 throw new DimensionMismatchException(probabilities.length, singletons.length);
157 }
158
159 final List<Pair<Integer, Double>> samples = new ArrayList<Pair<Integer, Double>>(singletons.length);
160
161 for (int i = 0; i < singletons.length; i++) {
162 samples.add(new Pair<Integer, Double>(singletons[i], probabilities[i]));
163 }
164 return samples;
165
166 }
167
168 /**
169 * {@inheritDoc}
170 */
171 public double probability(final int x) {
172 return innerDistribution.probability(x);
173 }
174
175 /**
176 * {@inheritDoc}
177 */
178 public double cumulativeProbability(final int x) {
179 double probability = 0;
180
181 for (final Pair<Integer, Double> sample : innerDistribution.getPmf()) {
182 if (sample.getKey() <= x) {
183 probability += sample.getValue();
184 }
185 }
186
187 return probability;
188 }
189
190 /**
191 * {@inheritDoc}
192 *
193 * @return {@code sum(singletons[i] * probabilities[i])}
194 */
195 public double getNumericalMean() {
196 double mean = 0;
197
198 for (final Pair<Integer, Double> sample : innerDistribution.getPmf()) {
199 mean += sample.getValue() * sample.getKey();
200 }
201
202 return mean;
203 }
204
205 /**
206 * {@inheritDoc}
207 *
208 * @return {@code sum((singletons[i] - mean) ^ 2 * probabilities[i])}
209 */
210 public double getNumericalVariance() {
211 double mean = 0;
212 double meanOfSquares = 0;
213
214 for (final Pair<Integer, Double> sample : innerDistribution.getPmf()) {
215 mean += sample.getValue() * sample.getKey();
216 meanOfSquares += sample.getValue() * sample.getKey() * sample.getKey();
217 }
218
219 return meanOfSquares - mean * mean;
220 }
221
222 /**
223 * {@inheritDoc}
224 *
225 * Returns the lowest value with non-zero probability.
226 *
227 * @return the lowest value with non-zero probability.
228 */
229 public int getSupportLowerBound() {
230 int min = Integer.MAX_VALUE;
231 for (final Pair<Integer, Double> sample : innerDistribution.getPmf()) {
232 if (sample.getKey() < min && sample.getValue() > 0) {
233 min = sample.getKey();
234 }
235 }
236
237 return min;
238 }
239
240 /**
241 * {@inheritDoc}
242 *
243 * Returns the highest value with non-zero probability.
244 *
245 * @return the highest value with non-zero probability.
246 */
247 public int getSupportUpperBound() {
248 int max = Integer.MIN_VALUE;
249 for (final Pair<Integer, Double> sample : innerDistribution.getPmf()) {
250 if (sample.getKey() > max && sample.getValue() > 0) {
251 max = sample.getKey();
252 }
253 }
254
255 return max;
256 }
257
258 /**
259 * {@inheritDoc}
260 *
261 * The support of this distribution is connected.
262 *
263 * @return {@code true}
264 */
265 public boolean isSupportConnected() {
266 return true;
267 }
268
269 /**
270 * {@inheritDoc}
271 */
272 @Override
273 public int sample() {
274 return innerDistribution.sample();
275 }
276}
Note: See TracBrowser for help on using the repository browser.