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