1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math.random;
18
19 import java.io.Serializable;
20 import java.io.BufferedReader;
21 import java.io.FileReader;
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.InputStreamReader;
25 import java.net.URL;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import org.apache.commons.math.stat.descriptive.SummaryStatistics;
30 import org.apache.commons.math.stat.descriptive.StatisticalSummary;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class EmpiricalDistributionImpl implements Serializable, EmpiricalDistribution {
60
61
62 private static final long serialVersionUID = -6773236347582113490L;
63
64
65 private ArrayList binStats = null;
66
67
68 private SummaryStatistics sampleStats = null;
69
70
71 private int binCount = 1000;
72
73
74 private boolean loaded = false;
75
76
77 private double[] upperBounds = null;
78
79
80 private RandomData randomData = new RandomDataImpl();
81
82
83
84
85 public EmpiricalDistributionImpl() {
86 binStats = new ArrayList();
87 }
88
89
90
91
92
93
94 public EmpiricalDistributionImpl(int binCount) {
95 this.binCount = binCount;
96 binStats = new ArrayList();
97 }
98
99
100
101
102
103
104
105 public void load(double[] in) {
106 DataAdapter da = new ArrayDataAdapter(in);
107 try {
108 da.computeStats();
109 fillBinStats(in);
110 } catch (Exception e) {
111 throw new RuntimeException(e.getMessage());
112 }
113 loaded = true;
114
115 }
116
117
118
119
120
121
122
123 public void load(URL url) throws IOException {
124 BufferedReader in =
125 new BufferedReader(new InputStreamReader(url.openStream()));
126 try {
127 DataAdapter da = new StreamDataAdapter(in);
128 try {
129 da.computeStats();
130 } catch (Exception e) {
131 throw new IOException(e.getMessage());
132 }
133 in = new BufferedReader(new InputStreamReader(url.openStream()));
134 fillBinStats(in);
135 loaded = true;
136 } finally {
137 if (in != null) {
138 try {
139 in.close();
140 } catch (Exception ex) {
141
142 }
143 }
144 }
145 }
146
147
148
149
150
151
152
153 public void load(File file) throws IOException {
154 BufferedReader in = new BufferedReader(new FileReader(file));
155 try {
156 DataAdapter da = new StreamDataAdapter(in);
157 try {
158 da.computeStats();
159 } catch (Exception e) {
160 throw new IOException(e.getMessage());
161 }
162 in = new BufferedReader(new FileReader(file));
163 fillBinStats(in);
164 loaded = true;
165 } finally {
166 if (in != null) {
167 try {
168 in.close();
169 } catch (Exception ex) {
170
171 }
172 }
173 }
174 }
175
176
177
178
179
180 private abstract class DataAdapter{
181
182
183
184
185
186
187
188 public abstract void computeBinStats(double min, double delta)
189 throws Exception;
190
191
192
193
194
195 public abstract void computeStats() throws Exception;
196 }
197
198
199
200
201
202 private class DataAdapterFactory{
203
204
205
206
207
208
209 public DataAdapter getAdapter(Object in) {
210 if (in instanceof BufferedReader) {
211 BufferedReader inputStream = (BufferedReader) in;
212 return new StreamDataAdapter(inputStream);
213 } else if (in instanceof double[]) {
214 double[] inputArray = (double[]) in;
215 return new ArrayDataAdapter(inputArray);
216 } else {
217 throw new IllegalArgumentException(
218 "Input data comes from the" + " unsupported source");
219 }
220 }
221 }
222
223
224
225 private class StreamDataAdapter extends DataAdapter{
226
227
228 private BufferedReader inputStream;
229
230
231
232
233
234
235 public StreamDataAdapter(BufferedReader in){
236 super();
237 inputStream = in;
238 }
239
240
241
242
243
244
245
246 public void computeBinStats(double min, double delta)
247 throws IOException {
248 String str = null;
249 double val = 0.0d;
250 while ((str = inputStream.readLine()) != null) {
251 val = Double.parseDouble(str);
252 SummaryStatistics stats =
253 (SummaryStatistics) binStats.get(findBin(min, val, delta));
254 stats.addValue(val);
255 }
256
257 inputStream.close();
258 inputStream = null;
259 }
260
261
262
263
264
265 public void computeStats() throws IOException {
266 String str = null;
267 double val = 0.0;
268 sampleStats = SummaryStatistics.newInstance();
269 while ((str = inputStream.readLine()) != null) {
270 val = new Double(str).doubleValue();
271 sampleStats.addValue(val);
272 }
273 inputStream.close();
274 inputStream = null;
275 }
276 }
277
278
279
280
281 private class ArrayDataAdapter extends DataAdapter{
282
283
284 private double[] inputArray;
285
286
287
288
289
290
291 public ArrayDataAdapter(double[] in){
292 super();
293 inputArray = in;
294 }
295
296
297
298
299
300 public void computeStats() throws IOException {
301 sampleStats = SummaryStatistics.newInstance();
302 for (int i = 0; i < inputArray.length; i++) {
303 sampleStats.addValue(inputArray[i]);
304 }
305 }
306
307
308
309
310
311
312
313 public void computeBinStats(double min, double delta)
314 throws IOException {
315 for (int i = 0; i < inputArray.length; i++) {
316 SummaryStatistics stats =
317 (SummaryStatistics) binStats.get(
318 findBin(min, inputArray[i], delta));
319 stats.addValue(inputArray[i]);
320 }
321 }
322 }
323
324
325
326
327
328
329
330 private void fillBinStats(Object in) throws IOException {
331
332 double min = sampleStats.getMin();
333 double max = sampleStats.getMax();
334 double delta = (max - min)/(new Double(binCount)).doubleValue();
335 double[] binUpperBounds = new double[binCount];
336 binUpperBounds[0] = min + delta;
337 for (int i = 1; i< binCount - 1; i++) {
338 binUpperBounds[i] = binUpperBounds[i-1] + delta;
339 }
340 binUpperBounds[binCount -1] = max;
341
342
343 if (!binStats.isEmpty()) {
344 binStats.clear();
345 }
346 for (int i = 0; i < binCount; i++) {
347 SummaryStatistics stats = SummaryStatistics.newInstance();
348 binStats.add(i,stats);
349 }
350
351
352 DataAdapterFactory aFactory = new DataAdapterFactory();
353 DataAdapter da = aFactory.getAdapter(in);
354 try {
355 da.computeBinStats(min, delta);
356 } catch (Exception e) {
357 if(e instanceof RuntimeException){
358 throw new RuntimeException(e.getMessage());
359 }else{
360 throw new IOException(e.getMessage());
361 }
362 }
363
364
365 upperBounds = new double[binCount];
366 upperBounds[0] =
367 ((double)((SummaryStatistics)binStats.get(0)).getN())/
368 (double)sampleStats.getN();
369 for (int i = 1; i < binCount-1; i++) {
370 upperBounds[i] = upperBounds[i-1] +
371 ((double)((SummaryStatistics)binStats.get(i)).getN())/
372 (double)sampleStats.getN();
373 }
374 upperBounds[binCount-1] = 1.0d;
375 }
376
377
378
379
380
381
382
383
384
385 private int findBin(double min, double value, double delta) {
386 return Math.min(
387 Math.max((int) Math.ceil((value- min) / delta) - 1, 0),
388 binCount - 1);
389 }
390
391
392
393
394
395
396
397 public double getNextValue() throws IllegalStateException {
398
399 if (!loaded) {
400 throw new IllegalStateException("distribution not loaded");
401 }
402
403
404 double x = Math.random();
405
406
407 for (int i = 0; i < binCount; i++) {
408 if (x <= upperBounds[i]) {
409 SummaryStatistics stats = (SummaryStatistics)binStats.get(i);
410 if (stats.getN() > 0) {
411 if (stats.getStandardDeviation() > 0) {
412 return randomData.nextGaussian
413 (stats.getMean(),stats.getStandardDeviation());
414 } else {
415 return stats.getMean();
416 }
417 }
418 }
419 }
420 throw new RuntimeException("No bin selected");
421 }
422
423
424
425
426
427
428
429
430
431 public StatisticalSummary getSampleStats() {
432 return sampleStats;
433 }
434
435
436
437
438
439
440 public int getBinCount() {
441 return binCount;
442 }
443
444
445
446
447
448
449
450
451 public List getBinStats() {
452 return binStats;
453 }
454
455
456
457
458
459
460
461
462
463 public double[] getUpperBounds() {
464 int len = upperBounds.length;
465 double[] out = new double[len];
466 System.arraycopy(upperBounds, 0, out, 0, len);
467 return out;
468 }
469
470
471
472
473
474
475 public boolean isLoaded() {
476 return loaded;
477 }
478 }