source: src/main/java/agents/anac/y2015/agentBuyogV2/flanagan/math/PsRandom.java

Last change on this file was 127, checked in by Wouter Pasman, 6 years ago

#41 ROLL BACK of rev.126 . So this version is equal to rev. 125

File size: 75.2 KB
Line 
1/* Program PsRandom
2*
3* Class for obtaining a single decimal or binary pseudorandom number
4* or a sequence of decimal or binary pseudorandom numbers
5* Supplements the Java random class with the generation of
6* of lorentzian, poissonian, logistic, student's t, pareto,
7* exponential, gumbel, weibull, frechet, rayleigh,
8* beta distribution, gamma distribution, erlang distribution,
9* chi-square distribution, F-distribution, uniform,
10* gaussian (normal) and correlated gaussian pseudo-random deviates
11* and pseudorandom binary numbers (bits).
12* Also offers a choice of Knuth or Park-Miller generation methods.
13*
14* Binary pseudorandom number calculations are adapted from
15* the Numerical Recipes methods written in the C language
16* based on the "primitive polynomials modulo 2" method:
17* Numerical Recipes in C, The Art of Scientific Computing,
18* W.H. Press, S.A. Teukolsky, W.T. Vetterling & B.P. Flannery,
19* Cambridge University Press, 2nd Edition (1992) pp 296 - 300.
20* (http://www.nr.com/).
21*
22* AUTHOR: Dr Michael Thomas Flanagan
23* DATE: 22 April 2004
24* UPDATE: 21 November 2006, 31 December 2006, 14 April 2007, 19 October 2007, 16-29 March 2008,
25* 3 July 2008, 19 September 2008, 28 September 2008, 13 and 18 October 2009, 12-24 July 2010
26*
27* DOCUMENTATION:
28* See Michael Thomas Flanagan's Java library on-line web page:
29* http://www.ee.ucl.ac.uk/~mflanaga/java/PsRandom.html
30* http://www.ee.ucl.ac.uk/~mflanaga/java/
31*
32* Copyright (c) 2004 - 2009 Michael Thomas Flanagan
33*
34* PERMISSION TO COPY:
35*
36* Permission to use, copy and modify this software and its documentation for NON-COMMERCIAL purposes is granted, without fee,
37* provided that an acknowledgement to the author, Dr Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all copies
38* and associated documentation or publications.
39*
40* Redistributions of the source code of this source code, or parts of the source codes, must retain the above copyright notice, this list of conditions
41* and the following disclaimer and requires written permission from the Michael Thomas Flanagan:
42*
43* Redistribution in binary form of all or parts of this class must reproduce the above copyright notice, this list of conditions and
44* the following disclaimer in the documentation and/or other materials provided with the distribution and requires written permission from the Michael Thomas Flanagan:
45*
46* Dr Michael Thomas Flanagan makes no representations about the suitability or fitness of the software for any or for a particular purpose.
47* Dr Michael Thomas Flanagan shall not be liable for any damages suffered as a result of using, modifying or distributing this software
48* or its derivatives.
49*
50***************************************************************************************/
51
52package agents.anac.y2015.agentBuyogV2.flanagan.math;
53
54import java.io.Serializable;
55import java.util.Random;
56
57import agents.anac.y2015.agentBuyogV2.flanagan.analysis.Stat;
58import agents.anac.y2015.agentBuyogV2.flanagan.roots.RealRoot;
59import agents.anac.y2015.agentBuyogV2.flanagan.roots.RealRootFunction;
60
61public class PsRandom implements Serializable{
62
63 private static final long serialVersionUID = 1L; // serial version unique identifier
64
65 private long seed; // current seed value - updated after each generation of a pseudorandom bit
66 // initial seed supplied as either:
67 // i. as the current clock time (in milliseconds since 1970)
68 // (no argument given to the constructor)
69 // ii. by the user as the constructor argument
70 // method are available for resetting the value of the seed
71
72 private long initialSeed; // initial seed value
73
74 private int methodOptionDecimal = 1; // Method for calculating pseudorandom decimal numbers
75 // = 1 Method - Knuth - this class calls the Java Random class which
76 // implements this method
77 // See Numerical Recipes in C - W.H. Press et al. (Cambridge)
78 // 1st edition 1988 p. 212, 2nd edition 1992 p283 for details
79 // This is the default option used in all methods in this class,
80 // Pseudorandom, generating a decimal random number, i.e. all but
81 // the methods to generate pseudorandom binary numbers.
82 // = 2 Method - Park and Miller random number generator with Bays-Durham shuffle
83 // after ran1 (Numerical Recipes in C - W.H. Press et al. (Cambridge)
84 // 2nd edition 1992 p280.
85
86 private int methodOptionInteger = 1; // Method for calculating pseudorandom integer numbers
87 // = 1 Method - java Random nextInt(int(n)
88 // = 2 Method - next double scaled with rounding
89 // = 3 Method - next doubled scaled with flooring
90
91 private Random rr = null; // instance of java.util.Random if Knuth method (default method) used
92
93 private int methodOptionBinary = 1; // Method for calculating pseudorandom binary numbers
94 // = 1 Method - Primitive polynomials modulo 2 method - version 1
95 // This method is the more cumbersome one in terms of coding (see method 2 below)
96 // but more readily lends itself to a shift register hardware implementation
97 // = 2 Method - Primitive polynomials modulo 2 method - version 2
98 // This method is the more suited to software implementation (compare with method 1 above)
99 // but lends itself less readily to a shift register hardware implementation
100 // Method 1 is the default option
101
102 // Park and Miller constants and variables
103 private long ia = 16807L;
104 private long im = 2147483647L;
105 private double am = 1.0D/im;
106 private long iq = 127773L;
107 private long ir = 2836L;
108 private int ntab = 32;
109 private long ndiv = (1L + (im - 1L)/ntab);
110 private double eps = 1.2e-7;
111 private double rnmx = 1.0D - eps;
112 private long iy = 0L;
113 private long[] iv = new long[ntab];
114
115 // Box-Muller variables
116 private int iset = 0;
117 private double gset = 0.0D;
118
119 // Polynomial powers of 2 (used in calculation of psedorandom binary numbers)
120 // See header reference (Numerical Recipes) above for polynomials other than (18, 5, 2, 1, 0)
121 private long powTwo1 = 1;
122 private long powTwo2 = 2;
123 private long powTwo5 = 16;
124 private long powTwo18 = 131072;
125 private long mask = powTwo1 + powTwo2 + powTwo5;
126
127 // CONSTRUCTORS
128
129 // Seed taken from the clock
130 public PsRandom(){
131 this.seed = System.currentTimeMillis();
132 this.initialSeed = this.seed;
133 this.rr = new Random(this.seed);
134 }
135
136 // Seed supplied by user
137 public PsRandom(long seed){
138 this.seed = seed;
139 this.initialSeed = seed;
140 this.rr = new Random(this.seed);
141 }
142
143 // METHODS
144
145 // Resets the value of the seed
146 public void setSeed(long seed){
147 this.seed = seed;
148 if(this.methodOptionDecimal==1) {
149 rr = new Random(this.seed);
150 }
151 }
152
153 // Returns the initial value of the seed
154 public long getInitialSeed(){
155 return this.initialSeed;
156 }
157
158 // Returns the current value of the seed
159 public long getSeed(){
160 return this.seed;
161 }
162
163 // Resets the method of calculation of a pseudorandom decimal number
164 // argument = 1 -> Knuth; argument = 2 -> Parker-Miller
165 // Default option = 1
166 public void setMethodDecimal(int methodOpt){
167 if(methodOpt<1 || methodOpt>2)throw new IllegalArgumentException("Argument to PsRandom.setMethodDecimal must 1 or 2\nValue transferred was"+methodOpt);
168 this.methodOptionDecimal = methodOpt;
169 if(methodOpt==1) {
170 rr = new Random(this.seed);
171 }
172 }
173
174 // Return the pseudorandom decimal number method option; 1 = Method 1 (Knuth), 2= Method 2 (Parker-Miller)
175 public int getMethodDecimal(){
176 return this.methodOptionDecimal;
177 }
178
179 // Resets the method of calculation of a pseudorandom integer number
180 // argument = 1 -> Diego Moreira alternative 1; argument = 2 -> Diego Moreira alternative 2; 3 -> Java Random class method nextInt
181 // Default option = 1
182 public void setMethodInteger(int methodOpt){
183 if(methodOpt<1 || methodOpt>3)throw new IllegalArgumentException("Argument to PsRandom.setMethodInteger must 1, 2 or 3\nValue transferred was"+methodOpt);
184 this.methodOptionInteger = methodOpt;
185 }
186
187 // Return the pseudorandom integer number method option; 1 = Method 1 (Diego Moreira alternative 1), 2= Method 2 (Diego Moreira alternative 2), 2 = ; 3 -> Java Random class method nextInt
188 public int getMethodInteger(){
189 return this.methodOptionInteger;
190 }
191
192 // Resets the method of calculation of a pseudorandom binary number
193 // argument = 1 -> method 1; argument = 2 -> Method 2
194 // See above and Numerical Recipes reference (in program header) for method descriptions
195 // Default option = 1
196 public void setMethodBinary(int methodOpt){
197 if(methodOpt<1 || methodOpt>2)throw new IllegalArgumentException("Argument to PsRandom.setMethodBinary must 1 or 2\nValue transferred was"+methodOpt);
198 this.methodOptionBinary = methodOpt;
199 if(methodOpt==1) {
200 rr = new Random(this.seed);
201 }
202 }
203
204 // Return the binary pseudorandom number method option; 1 = Method 1, 2= Method 2
205 public int getMethodBinary(){
206 return this.methodOptionBinary;
207 }
208
209 // Returns a pseudorandom double between 0.0 and 1.0
210 public double nextDouble(){
211 if(this.methodOptionDecimal==1)
212 return this.rr.nextDouble();
213 else
214 return this.parkMiller();
215 }
216
217 // Returns a pseudorandom double between 0.0 and top
218 public double nextDouble(double top){
219 return top*this.nextDouble();
220 }
221
222 // Returns a pseudorandom double between bottom and top
223 public double nextDouble(double bottom, double top){
224 return (top - bottom)*this.nextDouble() + bottom;
225 }
226
227 // Returns an array, of length arrayLength, of pseudorandom doubles between 0.0 and 1.0
228 public double[] doubleArray(int arrayLength){
229 double[] array = new double[arrayLength];
230 for(int i=0; i<arrayLength; i++){
231 array[i] = this.nextDouble();
232 }
233 return array;
234 }
235
236 // Returns an array, of length arrayLength, of pseudorandom doubles between 0.0 and top
237 public double[] doubleArray(int arrayLength, double top){
238 double[] array = new double[arrayLength];
239 for(int i=0; i<arrayLength; i++){
240 array[i] = top*this.nextDouble();
241 }
242 return array;
243 }
244
245 // Returns an array, of length arrayLength, of pseudorandom doubles between bottom and top
246 public double[] doubleArray(int arrayLength, double bottom, double top){
247 double[] array = new double[arrayLength];
248 for(int i=0; i<arrayLength; i++){
249 array[i] = (top - bottom)*this.nextDouble() + bottom;
250 }
251 return array;
252 }
253
254
255 // Park and Miller random number generator with Bays-Durham shuffle
256 // after ran1 Numerical Recipes in C - W.H. Press et al. (Cambridge)
257 // 2nd edition 1992 p280.
258 // return a pseudorandom number between 0.0 and 1.0
259 public double parkMiller(){
260 int jj = 0;
261 long kk = 0L;
262 double temp = 0.0D;
263 this.iy = 0L;
264
265 if(this.seed <= 0L || iy!=0){
266 if(-this.seed < 1){
267 this.seed = 1;
268 }
269 else{
270 this.seed = -this.seed;
271 }
272 for(int j=ntab+7; j>=0; j--){
273 kk = this.seed/iq;
274 this.seed = ia*( this.seed - kk*iq)- ir*kk;
275 if(this.seed < 0L) {
276 this.seed += im;
277 }
278 if (j < ntab) {
279 iv[j] = this.seed;
280 }
281 }
282 iy = iv[0];
283 }
284 kk = this.seed/iq;
285 this.seed = ia*(this.seed - kk*iq)-ir*kk;
286 if(this.seed < 0) {
287 this.seed += im;
288 }
289 jj = (int)(iy/ndiv);
290 iy = iv[jj];
291 iv[jj] = this.seed;
292 if((temp = am*iy) > rnmx)
293 return rnmx;
294 else
295 return temp;
296 }
297
298 // Returns a pseudorandom bit
299 public int nextBit(){
300 if(this.methodOptionBinary==1)
301 return nextBitM1();
302 else
303 return nextBitM2();
304 }
305
306 // Returns an array, of length arrayLength, of pseudorandom bits
307 public int[] bitArray(int arrayLength){
308 int[] bitarray = new int[arrayLength];
309 for(int i=0; i<arrayLength; i++){
310 bitarray[i]=nextBit();
311 }
312 return bitarray;
313 }
314
315 // Returns a pseudorandom bit - Method 1
316 // This method is the more cumbersome one in terms of coding (see method 2 below)
317 // but more readily lends itself to a shift register hardware implementation
318 public int nextBitM1(){
319 long newBit;
320
321 newBit = ((this.seed & this.powTwo18) >> 17L) ^ ((this.seed & this.powTwo5) >> 4L) ^ ((this.seed & this.powTwo2) >> 1L) ^ (this.seed & this.powTwo1);
322 this.seed=(this.seed << 1L) | newBit;
323 return (int) newBit;
324 }
325
326 // Returns a pseudorandom bit - Method 2
327 // This method is the more suited to software implementation (compare with method 1 above)
328 // but lends itself less readily to a shift register hardware implementation
329 public int nextBitM2(){
330 int randomBit = 0;
331 if((this.seed & this.powTwo18)<=0L){
332 this.seed = ((this.seed ^ this.mask) << 1L) | this.powTwo1;
333 randomBit = 1;
334 }
335 else{
336 this.seed <<= 1L;
337 randomBit = 0;
338 }
339
340 return randomBit;
341 }
342
343 // Returns a Gaussian (normal) random deviate
344 // mean = the mean, sd = standard deviation
345 public double nextGaussian(double mean, double sd){
346 double ran = 0.0D;
347 if(this.methodOptionDecimal==1){
348 ran=this.rr.nextGaussian();
349 }
350 else{
351 ran=this.boxMullerParkMiller();
352 }
353 ran = ran*sd+mean;
354 return ran;
355 }
356
357 // Returns a Gaussian (normal) random deviate
358 // mean = 0.0, sd = 1.0
359 public double nextGaussian(){
360 double ran = 0.0D;
361 if(this.methodOptionDecimal==1){
362 ran=this.rr.nextGaussian();
363 }
364 else{
365 ran=this.boxMullerParkMiller();
366 }
367 return ran;
368 }
369
370 public double nextNormal(double mean, double sd){
371 return nextGaussian(mean, sd);
372 }
373
374 public double nextNormal(){
375 return nextGaussian();
376 }
377
378
379 // Returns an array of Gaussian (normal) random deviates
380 // mean = the mean, sd = standard deviation, n = length of array
381 public double[] gaussianArray(double mean, double sd, int n){
382 double[] ran = new double[n];
383 for(int i=0; i<n; i++){
384 ran[i]=this.nextGaussian();
385 }
386 ran = Stat.standardize(ran);
387 for(int i=0; i<n; i++){
388 ran[i] = ran[i]*sd+mean;
389 }
390 return ran;
391 }
392
393 public double[] normalArray(double mean, double sd, int n){
394 return gaussianArray(mean, sd, n);
395 }
396
397
398 // Returns two arrays, both of length n, of correlated Gaussian (normal) random deviates
399 // of means, mean1 and mean2, and standard deviations, sd1 and sd2,
400 // and a correlation coefficient, rho
401 public double[][] correlatedGaussianArrays(double mean1, double mean2, double sd1, double sd2, double rho, int n){
402 if(Math.abs(rho)>1.0D)throw new IllegalArgumentException("The correlation coefficient, " + rho + ", must lie between -1 and 1");
403 double[][] ran = new double[2][n];
404 double[] ran1 = this.gaussianArray(0.0, 1.0, n);
405 double[] ran2 = this.gaussianArray(0.0, 1.0, n);
406
407 double ranh = 0.0D;
408 double rhot = Math.sqrt(1.0D - rho*rho);
409
410 for(int i=0; i<n; i++){
411 ran[0][i] = ran1[i]*sd1 + mean1;
412 ran[1][i] = (rho*ran1[i] + rhot*ran2[i])*sd2 + mean2;
413 }
414 return ran;
415 }
416
417 public double[][] correlatedNormalArrays(double mean1, double mean2, double sd1, double sd2, double rho, int n){
418 return correlatedGaussianArrays(mean1, mean2, sd1, sd2, rho, n);
419 }
420
421
422 // Box-Muller normal deviate generator
423 // after gasdev (Numerical Recipes in C - W.H. Press et al. (Cambridge)
424 // 2nd edition 1992 p289
425 // Uses Park and Miller method for generating pseudorandom numbers
426 double boxMullerParkMiller(){
427 double fac = 0.0D, rsq = 0.0D, v1 = 0.0D, v2 = 0.0D;
428
429 if (iset==0){
430 do {
431 v1=2.0*parkMiller()-1.0D;
432 v2=2.0*parkMiller()-1.0D;
433 rsq=v1*v1+v2*v2;
434 }while (rsq >= 1.0D || rsq == 0.0D);
435 fac=Math.sqrt(-2.0D*Math.log(rsq)/rsq);
436 gset=v1*fac;
437 iset=1;
438 return v2*fac;
439 }else{
440 iset=0;
441 return gset;
442 }
443 }
444
445
446
447 // returns a two parameter log-normal random deviate
448 public double nextLogNormal(double mu, double sigma){
449 double ran = 0.0D;
450
451 // Create instance of the class holding the two parameter log normal cfd function
452 LogNormalTwoParFunct logNorm2 = new LogNormalTwoParFunct();
453
454 // set function variables
455 logNorm2.mu = mu;
456 logNorm2.sigma = sigma;
457
458 // required tolerance
459 double tolerance = 1e-10;
460
461 // lower bound
462 double lowerBound = 0.0D;
463 double sigma2 = sigma*sigma;
464
465 // upper bound
466 double upperBound = 5.0D*Math.sqrt((Math.exp(sigma2) - 1.0D)*Math.exp(2.0D*mu + sigma2));
467
468 // Create instance of RealRoot
469 RealRoot realR = new RealRoot();
470
471 // Set extension limits
472 realR.noLowerBoundExtension();
473
474 // Set tolerance
475 realR.setTolerance(tolerance);
476
477 // Supress error messages and arrange for NaN to be returned as root if root not found
478 realR.resetNaNexceptionToTrue();
479 realR.supressLimitReachedMessage();
480 realR.supressNaNmessage();
481
482 // Loop to reject failed attempts at calculating the deviate
483 boolean test=true;
484 int ii=0;
485 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
486 while(test){
487
488 // set function cfd variable
489 logNorm2.cfd = this.nextDouble();
490
491 // call root searching method
492 ran = realR.falsePosition(logNorm2, lowerBound, upperBound);
493
494 if(!Double.isNaN(ran)){
495 test=false;
496 }
497 else{
498 if(ii>imax){
499 System.out.println("class: PsRandom, method: nextLogNormal");
500 System.out.println(imax + " successive attempts at calculating a random log-normal deviate failed for values of mu = " + mu + ", sigma = " + sigma);
501 System.out.println("NaN returned");
502 ran = Double.NaN;
503 test = false;
504 }
505 else{
506 ii++;
507 }
508 }
509 }
510 return ran;
511 }
512
513 public double nextLogNormalTwoPar(double mu, double sigma){
514 return nextLogNormal(mu, sigma);
515 }
516
517 // returns an array of two parameter log-normal pseudo-random deviates
518 public double[] logNormalArray(double mu, double sigma, int n){
519 double[] ran = new double[n];
520
521 // Create instance of the class holding the two parameter log normal cfd function
522 LogNormalTwoParFunct logNorm2 = new LogNormalTwoParFunct();
523
524 // set function variables
525 logNorm2.mu = mu;
526 logNorm2.sigma = sigma;
527
528 // required tolerance
529 double tolerance = 1e-10;
530
531 // lower bound
532 double lowerBound = 0.0D;
533
534 // upper bound
535 double sigma2 = sigma*sigma;
536 double upperBound = 5.0D*Math.sqrt((Math.exp(sigma2) - 1.0D)*Math.exp(2.0D*mu + sigma2));
537
538 for(int i=0; i<n; i++){
539
540 // Create instance of RealRoot
541 RealRoot realR = new RealRoot();
542
543 // Set extension limits
544 realR.noLowerBoundExtension();
545
546 // Set tolerance
547 realR.setTolerance(tolerance);
548
549 // Supress error messages and arrange for NaN to be returned as root if root not found
550 realR.resetNaNexceptionToTrue();
551 realR.supressLimitReachedMessage();
552 realR.supressNaNmessage();
553
554 // Loop to reject failed attempts at calculating the deviate
555 boolean test=true;
556 int ii=0;
557 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
558 while(test){
559
560 // set function cfd variable
561 logNorm2.cfd = this.nextDouble();
562
563 // call root searching method
564 double rangd = realR.bisect(logNorm2, lowerBound, upperBound);
565
566 if(!Double.isNaN(rangd)){
567 test=false;
568 ran[i] = rangd;
569 }
570 else{
571 if(ii>imax){
572 System.out.println("class: PsRandom, method: logNormalArray");
573 System.out.println(imax + " successive attempts at calculating a random gamma deviate failed for values of mu = " + mu + ", sigma = " + sigma);
574 System.out.println("NaN returned");
575 ran[i] = Double.NaN;
576 test = false;
577 }
578 else{
579 ii++;
580 }
581 }
582 }
583 }
584 return ran;
585 }
586
587 public double[] logNormalTwoParArray(double mu, double sigma, int n){
588 return logNormalArray(mu, sigma, n);
589 }
590
591
592 // returns a three parameter log-normal random deviate
593 public double nextLogNormalThreePar(double alpha, double beta, double gamma){
594 double ran = Double.NaN;
595
596 // Create instance of the class holding the Three Parameter LogNormal cfd function
597 LogNormalThreeParFunct logNorm3 = new LogNormalThreeParFunct();
598
599 // set function variables
600 logNorm3.alpha = alpha;
601 logNorm3.beta = beta;
602 logNorm3.gamma = gamma;
603
604 // required tolerance
605 double tolerance = 1e-10;
606
607 // lower bound
608 double lowerBound = alpha;
609 double beta2 = beta*beta;
610 double upperBound = 5.0D*Math.sqrt((Math.exp(beta2) - 1.0D)*Math.exp(2.0D*Math.log(gamma) + beta2));
611
612 // Create instance of RealRoot
613 RealRoot realR = new RealRoot();
614
615 // Set extension limits
616 realR.noLowerBoundExtension();
617
618 // Set tolerance
619 realR.setTolerance(tolerance);
620
621 // Supress error messages and arrange for NaN to be returned as root if root not found
622 realR.resetNaNexceptionToTrue();
623 realR.supressLimitReachedMessage();
624 realR.supressNaNmessage();
625
626 // Loop to reject failed attempts at calculating the deviate
627 boolean test=true;
628 int ii=0;
629 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
630 while(test){
631
632 // set function cfd variable
633 logNorm3.cfd = this.nextDouble();
634
635 // call root searching method
636 ran = realR.falsePosition(logNorm3, lowerBound, upperBound);
637
638 if(!Double.isNaN(ran)){
639 test=false;
640 }
641 else{
642 if(ii>imax){
643 System.out.println("class: PsRandom, method: nextLogNormalThreePar");
644 System.out.println(imax + " successive attempts at calculating a random log-normal deviate failed for values of alpha = " + alpha + ", beta = " + beta + ", gamma = " + gamma);
645 System.out.println("NaN returned");
646 ran = Double.NaN;
647 test = false;
648 }
649 else{
650 ii++;
651 }
652 }
653 }
654 return ran;
655 }
656
657
658 // returns an array of three parameter log-normal random deviates
659 public double[] logNormalThreeParArray(double alpha, double beta, double gamma, int n){
660 double[] ran = new double[n];
661
662 // Create instance of the class holding the Three Parameter log normal cfd function
663 LogNormalThreeParFunct logNorm3 = new LogNormalThreeParFunct();
664
665 // set function variables
666 logNorm3.alpha = alpha;
667 logNorm3.beta = beta;
668 logNorm3.gamma = gamma;
669
670 // required tolerance
671 double tolerance = 1e-10;
672
673 // lower bound
674 double lowerBound = alpha;
675
676 // upper bound
677 double beta2 = beta*beta;
678 double upperBound = 5.0D*Math.sqrt((Math.exp(beta2) - 1.0D)*Math.exp(2.0D*Math.log(gamma) + beta2));
679
680 for(int i=0; i<n; i++){
681
682 // Create instance of RealRoot
683 RealRoot realR = new RealRoot();
684
685 // Set extension limits
686 realR.noLowerBoundExtension();
687
688 // Set tolerance
689 realR.setTolerance(tolerance);
690
691 // Supress error messages and arrange for NaN to be returned as root if root not found
692 realR.resetNaNexceptionToTrue();
693 realR.supressLimitReachedMessage();
694 realR.supressNaNmessage();
695
696 // Loop to reject failed attempts at calculating the deviate
697 boolean test=true;
698 int ii=0;
699 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
700 while(test){
701
702 // set function cfd variable
703 logNorm3.cfd = this.nextDouble();
704
705 // call root searching method, bisectNewtonRaphson
706 double rangd = realR.falsePosition(logNorm3, lowerBound, upperBound);
707
708 if(!Double.isNaN(rangd)){
709 test=false;
710 ran[i] = rangd;
711 }
712 else{
713 if(ii>imax){
714 System.out.println("class: PsRandom, method: logNormalThreeParArray");
715 System.out.println(imax + " successive attempts at calculating a log-normal gamma deviate failed for values of alpha = " + alpha + ", beta = " + beta + ", gamma = " + gamma);
716 System.out.println("NaN returned");
717 ran[i] = Double.NaN;
718 test = false;
719 }
720 else{
721 ii++;
722 }
723 }
724 }
725 }
726 return ran;
727 }
728
729
730
731 // Returns a Lorentzian pseudorandom deviate
732 // mu = the mean, gamma = half-height widthy
733 public double nextLorentzian (double mu, double gamma){
734 double ran = Math.tan((this.nextDouble()-0.5)*Math.PI);
735 ran = ran*gamma/2.0D+mu;
736
737 return ran;
738 }
739
740
741 // Returns an array of Lorentzian pseudorandom deviates
742 // mu = the mean, gamma = half-height width, n = length of array
743 public double[] lorentzianArray (double mu, double gamma, int n){
744 double[] ran = new double[n];
745 for(int i=0; i<n; i++){
746 ran[i]=Math.tan((this.nextDouble()-0.5)*Math.PI);
747 ran[i] = ran[i]*gamma/2.0D+mu;
748 }
749 return ran;
750 }
751
752 // Returns a Poissonian pseudorandom deviate
753 // follows the approach of Numerical Recipes, 2nd Edition, p 294
754 public double nextPoissonian(double mean){
755 double ran = 0.0D;
756 double oldm = -1.0D;
757 double expt = 0.0D;
758 double em = 0.0D;
759 double term = 0.0D;
760 double sq = 0.0D;
761 double lnMean = 0.0D;
762 double yDev = 0.0D;
763
764 if(mean < 12.0D){
765 if(mean != oldm){
766 oldm = mean;
767 expt = Math.exp(-mean);
768 }
769 em = -1.0D;
770 term = 1.0D;
771 do{
772 ++em;
773 term *= this.nextDouble();
774 }while(term>expt);
775 ran = em;
776 }
777 else{
778 if(mean != oldm){
779 oldm = mean;
780 sq = Math.sqrt(2.0D*mean);
781 lnMean = Math.log(mean);
782 expt = lnMean - Stat.logGamma(mean+1.0D);
783 }
784 do{
785 do{
786 yDev = Math.tan(Math.PI*this.nextDouble());
787 em = sq*yDev+mean;
788 }while(em<0.0D);
789 em = Math.floor(em);
790 term = 0.9D*(1.0D+yDev*yDev)*Math.exp(em*lnMean - Stat.logGamma(em+1.0D)-expt);
791 }while(this.nextDouble()>term);
792 ran = em;
793 }
794 return ran;
795 }
796
797 // Returns an array of Poisson random deviates
798 // follows the approach of Numerical Recipes, 2nd Edition, p 294
799 public double[] poissonianArray(double mean, int n){
800 double[] ran = new double[n];
801 double oldm = -1.0D;
802 double expt = 0.0D;
803 double em = 0.0D;
804 double term = 0.0D;
805 double sq = 0.0D;
806 double lnMean = 0.0D;
807 double yDev = 0.0D;
808
809 if(mean < 12.0D){
810 for(int i=0; i<n; i++){
811 if(mean != oldm){
812 oldm = mean;
813 expt = Math.exp(-mean);
814 }
815 em = -1.0D;
816 term = 1.0D;
817 do{
818 ++em;
819 term *= this.nextDouble();
820 }while(term>expt);
821 ran[i] = em;
822 }
823 }
824 else{
825 for(int i=0; i<n; i++){
826 if(mean != oldm){
827 oldm = mean;
828 sq = Math.sqrt(2.0D*mean);
829 lnMean = Math.log(mean);
830 expt = lnMean - Stat.logGamma(mean+1.0D);
831 }
832 do{
833 do{
834 yDev = Math.tan(Math.PI*this.nextDouble());
835 em = sq*yDev+mean;
836 }while(em<0.0D);
837 em = Math.floor(em);
838 term = 0.9D*(1.0D+yDev*yDev)*Math.exp(em*lnMean - Stat.logGamma(em+1.0D)-expt);
839 }while(this.nextDouble()>term);
840 ran[i] = em;
841 }
842 }
843 return ran;
844 }
845
846 // Returns a Binomial pseudorandom deviate from a binomial
847 // distribution of nTrial trials each of probablity, prob,
848 // after bndlev Numerical Recipes in C - W.H. Press et al. (Cambridge)
849 // 2nd edition 1992 p295.
850 public double nextBinomial(double prob, int nTrials){
851
852 if(prob<0.0D || prob>1.0D)throw new IllegalArgumentException("The probablity provided, " + prob + ", must lie between 0 and 1)");
853
854 double binomialDeviate = 0.0D; // the binomial deviate to be returned
855 double deviateMean = 0.0D; // mean of deviate to be produced
856 double testDeviate = 0.0D; // test deviate
857 double workingProb = 0.0; // working value of the probability
858 double logProb = 0.0; // working value of the probability
859 double probOld = -1.0D; // previous value of the working probability
860 double probC = -1.0D; // complementary value of the working probability
861 double logProbC = -1.0D; // log of the complementary value of the working probability
862 int nOld= -1; // previous value of trials counter
863 double enTrials = 0.0D; // (double) trials counter
864 double oldGamma = 0.0D; // a previous log Gamma function value
865 double tanW = 0.0D; // a working tangent
866 double hold0 = 0.0D; // a working holding variable
867 int jj; // counter
868
869 workingProb=(prob <= 0.5D ? prob : 1.0-prob); // distribution invariant on swapping prob for 1 - prob
870 deviateMean = nTrials*workingProb;
871
872 if(nTrials < 25) {
873 // if number of trials greater than 25 use direct method
874 binomialDeviate=0.0D;
875 for (jj=1;jj<=nTrials;jj++)if (this.nextDouble() < workingProb) {
876 ++binomialDeviate;
877 }
878 }
879 else if(deviateMean < 1.0D) {
880 // if fewer than 1 out of 25 events - Poisson approximation is accurate
881 double expOfMean=Math.exp(-deviateMean);
882 testDeviate=1.0D;
883 for(jj=0;jj<=nTrials;jj++) {
884 testDeviate *= this.nextDouble();
885 if (testDeviate < expOfMean) {
886 break;
887 }
888 }
889 binomialDeviate=(jj <= nTrials ? jj : nTrials);
890
891 }
892 else{
893 // use rejection method
894 if(nTrials != nOld) {
895 // if nTrials has changed compute useful quantities
896 enTrials = nTrials;
897 oldGamma = Stat.logGamma(enTrials + 1.0D);
898 nOld = nTrials;
899 }
900 if(workingProb != probOld) {
901 // if workingProb has changed compute useful quantities
902 probC = 1.0 - workingProb;
903 logProb = Math.log(workingProb);
904 logProbC = Math.log(probC);
905 probOld = workingProb;
906 }
907
908 double sq = Math.sqrt(2.0*deviateMean*probC);
909 do{
910 do{
911 double angle = Math.PI*this.nextDouble();
912 tanW = Math.tan(angle);
913 hold0 = sq*tanW + deviateMean;
914 }while(hold0 < 0.0D || hold0 >= (enTrials + 1.0D)); // rejection test
915 hold0 = Math.floor(hold0); // integer value distribution
916 testDeviate = 1.2D*sq*(1.0D + tanW*tanW)*Math.exp(oldGamma - Stat.logGamma(hold0 + 1.0D) - Stat.logGamma(enTrials - hold0 + 1.0D) + hold0*logProb + (enTrials - hold0)*logProbC);
917 }while(this.nextDouble() > testDeviate); // rejection test
918 binomialDeviate=hold0;
919 }
920
921 if(workingProb != prob)
922 {
923 binomialDeviate = nTrials - binomialDeviate; // symmetry transformation
924 }
925
926 return binomialDeviate;
927 }
928
929 // Returns an array of n Binomial pseudorandom deviates from a binomial
930 // distribution of nTrial trials each of probablity, prob,
931 // after bndlev Numerical Recipes in C - W.H. Press et al. (Cambridge)
932 // 2nd edition 1992 p295.
933 public double[] binomialArray(double prob, int nTrials, int n){
934
935 if(nTrials<n)throw new IllegalArgumentException("Number of deviates requested, " + n + ", must be less than the number of trials, " + nTrials);
936 if(prob<0.0D || prob>1.0D)throw new IllegalArgumentException("The probablity provided, " + prob + ", must lie between 0 and 1)");
937
938 double[] ran = new double[n]; // array of deviates to be returned
939
940 double binomialDeviate = 0.0D; // the binomial deviate to be returned
941 double deviateMean = 0.0D; // mean of deviate to be produced
942 double testDeviate = 0.0D; // test deviate
943 double workingProb = 0.0; // working value of the probability
944 double logProb = 0.0; // working value of the probability
945 double probOld = -1.0D; // previous value of the working probability
946 double probC = -1.0D; // complementary value of the working probability
947 double logProbC = -1.0D; // log of the complementary value of the working probability
948 int nOld= -1; // previous value of trials counter
949 double enTrials = 0.0D; // (double) trials counter
950 double oldGamma = 0.0D; // a previous log Gamma function value
951 double tanW = 0.0D; // a working tangent
952 double hold0 = 0.0D; // a working holding variable
953 int jj; // counter
954
955 double probOriginalValue = prob;
956 for(int i=0; i<n; i++){
957 prob = probOriginalValue;
958 workingProb=(prob <= 0.5D ? prob : 1.0-prob); // distribution invariant on swapping prob for 1 - prob
959 deviateMean = nTrials*workingProb;
960
961 if(nTrials < 25) {
962 // if number of trials greater than 25 use direct method
963 binomialDeviate=0.0D;
964 for(jj=1;jj<=nTrials;jj++)if (this.nextDouble() < workingProb) {
965 ++binomialDeviate;
966 }
967 }
968 else if(deviateMean < 1.0D) {
969 // if fewer than 1 out of 25 events - Poisson approximation is accurate
970 double expOfMean=Math.exp(-deviateMean);
971 testDeviate=1.0D;
972 for (jj=0;jj<=nTrials;jj++) {
973 testDeviate *= this.nextDouble();
974 if (testDeviate < expOfMean) {
975 break;
976 }
977 }
978 binomialDeviate=(jj <= nTrials ? jj : nTrials);
979
980 }
981 else{
982 // use rejection method
983 if(nTrials != nOld) {
984 // if nTrials has changed compute useful quantities
985 enTrials = nTrials;
986 oldGamma = Stat.logGamma(enTrials + 1.0D);
987 nOld = nTrials;
988 }
989 if(workingProb != probOld) {
990 // if workingProb has changed compute useful quantities
991 probC = 1.0 - workingProb;
992 logProb = Math.log(workingProb);
993 logProbC = Math.log(probC);
994 probOld = workingProb;
995 }
996
997 double sq = Math.sqrt(2.0*deviateMean*probC);
998 do{
999 do{
1000 double angle = Math.PI*this.nextDouble();
1001 tanW = Math.tan(angle);
1002 hold0 = sq*tanW + deviateMean;
1003 }while(hold0 < 0.0D || hold0 >= (enTrials + 1.0D)); // rejection test
1004 hold0 = Math.floor(hold0); // integer value distribution
1005 testDeviate = 1.2D*sq*(1.0D + tanW*tanW)*Math.exp(oldGamma - Stat.logGamma(hold0 + 1.0D) - Stat.logGamma(enTrials - hold0 + 1.0D) + hold0*logProb + (enTrials - hold0)*logProbC);
1006 }while(this.nextDouble() > testDeviate); // rejection test
1007 binomialDeviate=hold0;
1008 }
1009
1010 if(workingProb != prob)
1011 {
1012 binomialDeviate = nTrials - binomialDeviate; // symmetry transformation
1013 }
1014
1015 ran[i] = binomialDeviate;
1016 }
1017
1018 return ran;
1019 }
1020
1021
1022 // Returns a Pareto pseudorandom deviate
1023 public double nextPareto(double alpha, double beta){
1024 return Math.pow(1.0D-this.nextDouble(), -1.0D/alpha)*beta;
1025 }
1026
1027 // Returns an array, of Pareto pseudorandom deviates, of length n
1028 public double[] paretoArray (double alpha, double beta, int n){
1029 double[] ran = new double[n];
1030 for(int i=0; i<n; i++){
1031 ran[i] = Math.pow(1.0D-this.nextDouble(), -1.0D/alpha)*beta;
1032 }
1033 return ran;
1034 }
1035
1036 // Returns an exponential pseudorandom deviate
1037 public double nextExponential(double mu, double sigma){
1038 return mu - Math.log(1.0D-this.nextDouble())*sigma;
1039 }
1040
1041 // Returns an array, of exponential pseudorandom deviates, of length n
1042 public double[] exponentialArray (double mu, double sigma, int n){
1043 double[] ran = new double[n];
1044 for(int i=0; i<n; i++){
1045 ran[i] = mu - Math.log(1.0D-this.nextDouble())*sigma;
1046 }
1047 return ran;
1048 }
1049
1050 // Returns a Rayleigh pseudorandom deviate
1051 public double nextRayleigh(double sigma){
1052 return Math.sqrt(-2.0D*Math.log(1.0D-this.nextDouble()))*sigma;
1053 }
1054
1055 // Returns an array, of Rayleigh pseudorandom deviates, of length n
1056 public double[] rayleighArray (double sigma, int n){
1057 double[] ran = new double[n];
1058 for(int i=0; i<n; i++){
1059 ran[i] = Math.sqrt(-2.0D*Math.log(1.0D-this.nextDouble()))*sigma;
1060 }
1061 return ran;
1062 }
1063
1064 // Returns a minimal Gumbel (Type I EVD) random deviate
1065 // mu = location parameter, sigma = scale parameter
1066 public double nextMinimalGumbel(double mu, double sigma){
1067 return Math.log(Math.log(1.0D/(1.0D-this.nextDouble())))*sigma+mu;
1068 }
1069
1070 // Returns an array of minimal Gumbel (Type I EVD) random deviates
1071 // mu = location parameter, sigma = scale parameter, n = length of array
1072 public double[] minimalGumbelArray(double mu, double sigma, int n){
1073 double[] ran = new double[n];
1074 for(int i=0; i<n; i++){
1075 ran[i] = Math.log(Math.log(1.0D/(1.0D-this.nextDouble())))*sigma+mu;
1076 }
1077 return ran;
1078 }
1079
1080 // Returns a maximal Gumbel (Type I EVD) random deviate
1081 // mu = location parameter, sigma = scale parameter
1082 public double nextMaximalGumbel(double mu, double sigma){
1083 return mu-Math.log(Math.log(1.0D/(1.0D-this.nextDouble())))*sigma;
1084 }
1085
1086 // Returns an array of maximal Gumbel (Type I EVD) random deviates
1087 // mu = location parameter, sigma = scale parameter, n = length of array
1088 public double[] maximalGumbelArray(double mu, double sigma, int n){
1089 double[] ran = new double[n];
1090 for(int i=0; i<n; i++){
1091 ran[i] = mu-Math.log(Math.log(1.0D/(1.0D-this.nextDouble())))*sigma;
1092 }
1093 return ran;
1094 }
1095
1096 // Returns a Frechet (Type II EVD) random deviate
1097 // mu = location parameter, sigma = scale parameter, gamma = shape parameter
1098 public double nextFrechet(double mu, double sigma, double gamma){
1099 return Math.pow((1.0D/(Math.log(1.0D/this.nextDouble()))),1.0D/gamma)*sigma + mu;
1100 }
1101
1102 // Returns an array of Frechet (Type II EVD) random deviates
1103 // mu = location parameter, sigma = scale parameter, gamma = shape parameter, n = length of array
1104 public double[] frechetArray(double mu, double sigma, double gamma, int n){
1105 double[] ran = new double[n];
1106 for(int i=0; i<n; i++){
1107 ran[i] = Math.pow((1.0D/(Math.log(1.0D/this.nextDouble()))),1.0D/gamma)*sigma + mu;
1108 }
1109 return ran;
1110 }
1111
1112 // Returns a Weibull (Type III EVD) random deviate
1113 // mu = location parameter, sigma = scale parameter, gamma = shape parameter
1114 public double nextWeibull(double mu, double sigma, double gamma){
1115 return Math.pow(-Math.log(1.0D-this.nextDouble()),1.0D/gamma)*sigma + mu;
1116 }
1117
1118 // Returns an array of Weibull (Type III EVD) random deviates
1119 // mu = location parameter, sigma = scale parameter, gamma = shape parameter, n = length of array
1120 public double[] weibullArray(double mu, double sigma, double gamma, int n){
1121 double[] ran = new double[n];
1122 for(int i=0; i<n; i++){
1123 ran[i] = Math.pow(-Math.log(1.0D-this.nextDouble()),1.0D/gamma)*sigma + mu;
1124 }
1125 return ran;
1126 }
1127
1128 // Returns an array of Logistic distribution random deviates
1129 // mu = location parameter, scale = scale parameter
1130 public double nextLogistic(double mu, double scale){
1131 return 2.0D*scale*Fmath.atanh(2.0D*this.nextDouble() - 1.0D) + mu;
1132 }
1133
1134 // Returns an array of Logistic distribution random deviate
1135 // mu = location parameter, scale = scale parameter, n is the length of the returned array
1136 public double[] logisticArray(double mu, double scale, int n){
1137 double[] ran = new double[n];
1138 for(int i=0; i<n; i++) {
1139 ran[i] = 2.0D*scale*Fmath.atanh(2.0D*this.nextDouble() - 1.0D) + mu;
1140 }
1141 return ran;
1142 }
1143
1144
1145 // Returns a Student t random deviate
1146 // nu = the degrees of freedom
1147 public double nextStudentT(int nu){
1148
1149 double ran = 0.0D;
1150
1151 // Create instance of the class holding the Student's t cfd function
1152 StudentTfunct strt = new StudentTfunct();
1153
1154 // change set function variables
1155 strt.nu = nu;
1156
1157 // Set initial range for search
1158 double centre = 0.0D;
1159 double range = 100.0D;
1160 if(nu>2) {
1161 range = nu/(nu-2);
1162 }
1163
1164 // lower bound
1165 double lowerBound = centre - 5.0D*range;
1166
1167 // upper bound
1168 double upperBound = centre + 5.0D*range;
1169
1170 // required tolerance
1171 double tolerance = 1e-10;
1172
1173 // Create instance of RealRoot
1174 RealRoot realR = new RealRoot();
1175
1176 // Set tolerance
1177 realR.setTolerance(tolerance);
1178
1179 // Supress error messages and arrange for NaN to be returned as root if root not found
1180 realR.resetNaNexceptionToTrue();
1181 realR.supressLimitReachedMessage();
1182 realR.supressNaNmessage();
1183
1184 // Loop to reject failed attempts at calculating the deviate
1185 boolean test=true;
1186 int ii=0;
1187 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
1188 while(test){
1189
1190 // set function cfd varaible
1191 strt.cfd = this.nextDouble();
1192
1193 // call root searching method
1194 ran = realR.falsePosition(strt, lowerBound, upperBound);
1195
1196 if(!Double.isNaN(ran)){
1197 test=false;
1198 }
1199 else{
1200 if(ii>imax){
1201 System.out.println("class: PsRandom, method: studentT");
1202 System.out.println(imax + " successive attempts at calculating a random Student's T deviate failed for values of nu = " + nu);
1203 System.out.println("NaN returned");
1204 ran = Double.NaN;
1205 test = false;
1206 }
1207 else{
1208 ii++;
1209 }
1210 }
1211 }
1212 return ran;
1213
1214 }
1215
1216 // Returns an array of Student's t random deviates
1217 // nu = the degrees of freedom
1218 public double[] studentTarray(int nu, int n){
1219
1220 double[] ran = new double[n];
1221
1222 // Create instance of the class holding the Student's t cfd function
1223 StudentTfunct strt = new StudentTfunct();
1224
1225 // set function variables
1226 strt.nu = nu;
1227
1228 // Set initial range for search
1229 double centre = 0.0D;
1230 double range = 100.0D;
1231 if(nu>2) {
1232 range = nu/(nu-2);
1233 }
1234
1235 // required tolerance
1236 double tolerance = 1e-10;
1237
1238 // lower bound
1239 double lowerBound = centre - 5.0D*range;
1240
1241 // upper bound
1242 double upperBound = centre + 5.0D*range;
1243
1244 for(int i=0; i<n; i++){
1245
1246 // Create instance of RealRoot
1247 RealRoot realR = new RealRoot();
1248
1249 // Set tolerance
1250 realR.setTolerance(tolerance);
1251
1252 // Supress error messages and arrange for NaN to be returned as root if root not found
1253 realR.resetNaNexceptionToTrue();
1254 realR.supressLimitReachedMessage();
1255 realR.supressNaNmessage();
1256
1257 // Loop to reject failed attempts at calculating the deviate
1258 boolean test=true;
1259 int ii=0;
1260 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
1261 while(test){
1262
1263 // set function cfd variable
1264 strt.cfd = this.nextDouble();
1265
1266 // call root searching method, bisectNewtonRaphson
1267 double rangd = realR.falsePosition(strt, lowerBound, upperBound);
1268
1269 if(!Double.isNaN(rangd)){
1270 test=false;
1271 ran[i] = rangd;
1272 }
1273 else{
1274 if(ii>imax){
1275 System.out.println("class: PsRandom, method: studentTarray");
1276 System.out.println(imax + " successive attempts at calculating a random gamma deviate failed for values of nu = " + nu);
1277 System.out.println("NaN returned");
1278 ran[i] = Double.NaN;
1279 test = false;
1280 }
1281 else{
1282 ii++;
1283 }
1284 }
1285 }
1286 }
1287 return ran;
1288 }
1289
1290 // method for generating a Beta random deviate
1291 public double nextBeta(double alpha, double beta){
1292 return nextBeta(0.0D, 1.0D, alpha, beta);
1293 }
1294
1295
1296 // method for generating a Beta random deviate
1297 public double nextBeta(double min, double max, double alpha, double beta){
1298
1299 double ran = 0.0D;
1300
1301 // Create instance of the class holding the Beta cfd function
1302 BetaFunct bart = new BetaFunct();
1303
1304 // set function variables
1305 bart.alpha = alpha;
1306 bart.beta = beta;
1307 bart.min = min;
1308 bart.max = max;
1309
1310 // required tolerance
1311 double tolerance = 1e-10;
1312
1313 // lower bound
1314 double lowerBound = min;
1315 // upper bound
1316 double upperBound = max;
1317
1318 // Create instance of RealRoot
1319 RealRoot realR = new RealRoot();
1320
1321 // Set extension limits
1322 realR.noLowerBoundExtension();
1323 realR.noUpperBoundExtension();
1324
1325 // Set tolerance
1326 realR.setTolerance(tolerance);
1327
1328 // Supress error messages and arrange for NaN to be returned as root if root not found
1329 realR.resetNaNexceptionToTrue();
1330 realR.supressLimitReachedMessage();
1331 realR.supressNaNmessage();
1332
1333 // Loop to reject failed attempts at calculating the deviate
1334 boolean test=true;
1335 int ii=0;
1336 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
1337 while(test){
1338
1339 // set function cfd variable
1340 bart.cfd = this.nextDouble();
1341
1342 // call root searching method, false position
1343 ran = realR.falsePosition(bart, lowerBound, upperBound);
1344
1345 if(!Double.isNaN(ran)){
1346 test=false;
1347 }
1348 else{
1349 if(ii>imax){
1350 System.out.println("class: PsRandom, method: nextBeta");
1351 System.out.println(imax + " successive attempts at calculating a random beta deviate failed for values of min = " + min + ", max = " + max + ", alpha = " + alpha + ", beta = " + beta);
1352 System.out.println("NaN returned");
1353 ran = Double.NaN;
1354 test = false;
1355 }
1356 else{
1357 ii++;
1358 }
1359 }
1360 }
1361
1362 return ran;
1363
1364 }
1365
1366 // method for generating an array of Beta random deviates
1367 public double[] betaArray(double alpha, double beta, int n){
1368 return betaArray(0.0D, 1.0D, alpha, beta, n);
1369 }
1370
1371 // method for generating an array of Beta random deviates
1372 public double[] betaArray(double min, double max, double alpha, double beta, int n){
1373
1374 double[] ran = new double[n];
1375
1376 // Create instance of the class holding the Beta cfd function
1377 BetaFunct bart = new BetaFunct();
1378
1379 // set function variables
1380 bart.alpha = alpha;
1381 bart.beta = beta;
1382 bart.min = min;
1383 bart.max = max;
1384
1385 // required tolerance
1386 double tolerance = 1e-10;
1387
1388 // lower bound
1389 double lowerBound = min;
1390
1391 // upper bound
1392 double upperBound = max;
1393
1394 for(int i=0; i<n; i++){
1395
1396 // Create instance of RealRoot
1397 RealRoot realR = new RealRoot();
1398
1399 // Set extension limits
1400 realR.noLowerBoundExtension();
1401 realR.noUpperBoundExtension();
1402
1403 // Set tolerance
1404 realR.setTolerance(tolerance);
1405
1406 // Supress error messages and arrange for NaN to be returned as root if root not found
1407 realR.resetNaNexceptionToTrue();
1408 realR.supressLimitReachedMessage();
1409 realR.supressNaNmessage();
1410
1411 // Loop to reject failed attempts at calculating the deviate
1412 boolean test=true;
1413 int ii=0;
1414 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
1415 while(test){
1416
1417 // set function cfd variable
1418 bart.cfd = this.nextDouble();
1419
1420 // call root searching method
1421 double rangd = realR.bisect(bart, lowerBound, upperBound);
1422
1423 if(!Double.isNaN(rangd)){
1424 test=false;
1425 ran[i] = rangd;
1426 }
1427 else{
1428 if(ii>imax){
1429 System.out.println("class: PsRandom, method: betaArray");
1430 System.out.println(imax + " successive attempts at calculating a random beta deviate failed for values of min = " + min + ", max = " + max + ", alpha = " + alpha + ", beta = " + beta);
1431 System.out.println("NaN returned");
1432 ran[i] = Double.NaN;
1433 test = false;
1434 }
1435 else{
1436 ii++;
1437 }
1438 }
1439 }
1440 }
1441
1442 return ran;
1443 }
1444
1445
1446 // method for generating a Gamma random deviate
1447 public double nextGamma(double mu, double beta, double gamma){
1448
1449 double ran = 0.0D; // variable to hold the random deviate
1450
1451 // Create instance of the class holding the Gamma cfd function
1452 GammaFunct gart = new GammaFunct();
1453
1454 // set function variables
1455 gart.mu = mu;
1456 gart.beta = beta;
1457 gart.gamma = gamma;
1458
1459 // Set initial range for search
1460 double range = Math.sqrt(gamma)*beta;
1461
1462 // required tolerance
1463 double tolerance = 1e-10;
1464
1465 // lower bound
1466 double lowerBound = mu;
1467
1468 // upper bound
1469 double upperBound = mu + 5.0D*range;
1470 if(upperBound<=lowerBound) {
1471 upperBound += range;
1472 }
1473
1474 // Create instance of RealRoot
1475 RealRoot realR = new RealRoot();
1476
1477 // Set extension limits
1478 realR.noLowerBoundExtension();
1479
1480 // Set tolerance
1481 realR.setTolerance(tolerance);
1482
1483 // Supress error messages and arrange for NaN to be returned as root if root not found
1484 realR.resetNaNexceptionToTrue();
1485 realR.supressLimitReachedMessage();
1486 realR.supressNaNmessage();
1487
1488 // Loop to reject failed attempts at calculating the deviate
1489 boolean test=true;
1490 int ii=0;
1491 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
1492 while(test){
1493
1494 // set function cfd variable
1495 gart.cfd = this.nextDouble();
1496
1497 // call root searching method, bisect
1498 ran = realR.bisect(gart, lowerBound, upperBound);
1499
1500 if(!Double.isNaN(ran)){
1501 test=false;
1502 }
1503 else{
1504 if(ii>imax){
1505 System.out.println("class: PsRandom, method: nextGamma");
1506 System.out.println(imax + " successive attempts at calculating a random gamma deviate failed for values of mu = " + mu + ", beta = " + beta + ", gamma = " + gamma);
1507 System.out.println("NaN returned");
1508 ran = Double.NaN;
1509 test = false;
1510 }
1511 else{
1512 ii++;
1513 }
1514 }
1515 }
1516
1517 return ran;
1518
1519 }
1520
1521 // method for generating an array of Gamma random deviates
1522 public double[] gammaArray(double mu, double beta, double gamma, int n){
1523
1524 double[] ran = new double[n];
1525
1526 // Create instance of the class holding the gamma cfd function
1527 GammaFunct gart = new GammaFunct();
1528
1529 // set function variables
1530 gart.mu = mu;
1531 gart.beta = beta;
1532 gart.gamma = gamma;
1533
1534 // Set initial range for search
1535 double range = Math.sqrt(gamma)*beta;
1536
1537 // required tolerance
1538 double tolerance = 1e-10;
1539
1540 // lower bound
1541 double lowerBound = mu;
1542
1543 // upper bound
1544 double upperBound = mu + 5.0D*range;
1545 if(upperBound<=lowerBound) {
1546 upperBound += range;
1547 }
1548
1549 for(int i=0; i<n; i++){
1550
1551 // Create instance of RealRoot
1552 RealRoot realR = new RealRoot();
1553
1554 // Set extension limits
1555 realR.noLowerBoundExtension();
1556
1557 // Set tolerance
1558 realR.setTolerance(tolerance);
1559
1560 // Supress error messages and arrange for NaN to be returned as root if root not found
1561 realR.resetNaNexceptionToTrue();
1562 realR.supressLimitReachedMessage();
1563 realR.supressNaNmessage();
1564
1565 // Loop to reject failed attempts at calculating the deviate
1566 boolean test=true;
1567 int ii=0;
1568 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
1569 while(test){
1570
1571 // set function cfd variable
1572 gart.cfd = this.nextDouble();
1573
1574 // call root searching method, bisectNewtonRaphson
1575 double rangd = realR.bisect(gart, lowerBound, upperBound);
1576
1577 if(!Double.isNaN(rangd)){
1578 test=false;
1579 ran[i] = rangd;
1580 }
1581 else{
1582 if(ii>imax){
1583 System.out.println("class: PsRandom, method: gammaArray");
1584 System.out.println(imax + " successive attempts at calculating a random gamma deviate failed for values of mu = " + mu + ", beta = " + beta + ", gamma = " + gamma);
1585 System.out.println("NaN returned");
1586 ran[i] = Double.NaN;
1587 test = false;
1588 }
1589 else{
1590 ii++;
1591 }
1592 }
1593 }
1594 }
1595
1596 return ran;
1597
1598 }
1599
1600 // method for generating an Erlang random deviate
1601 public double nextErlang(double lambda, int kay){
1602 return nextGamma(0.0D, 1.0D/lambda, kay);
1603 }
1604
1605
1606 // method for generating an array of Erlang random deviates
1607 public double[] erlangArray(double lambda, int kay, int n){
1608 return gammaArray(0.0D, 1.0D/lambda, kay, n);
1609 }
1610
1611 // CHI-SQUARE
1612 // method for generating an array of Chi-Square random deviates
1613 public double[] chiSquareArray(int nu, int n){
1614 if(nu<=0)throw new IllegalArgumentException("The degrees of freedom [nu], " + nu + ", must be greater than zero");
1615
1616 double[] ran = new double[n];
1617
1618 // Create instance of the class holding the chiSquare cfd function
1619 ChiSquareFunct csrt = new ChiSquareFunct();
1620
1621 // set function variables
1622 csrt.nu = nu;
1623
1624 // required tolerance
1625 double tolerance = 1e-10;
1626
1627 // lower bound
1628 double lowerBound = 0.0D;
1629
1630 // upper bound
1631 double upperBound = 5.0D*Math.sqrt(2*nu);
1632
1633 for(int i=0; i<n; i++){
1634
1635 // Create instance of RealRoot
1636 RealRoot realR = new RealRoot();
1637
1638 // Set extension limits
1639 realR.noLowerBoundExtension();
1640
1641 // Set tolerance
1642 realR.setTolerance(tolerance);
1643
1644 // Supress error messages and arrange for NaN to be returned as root if root not found
1645 realR.resetNaNexceptionToTrue();
1646 realR.supressLimitReachedMessage();
1647 realR.supressNaNmessage();
1648
1649 // Loop to reject failed attempts at calculating the deviate
1650 boolean test=true;
1651 int ii=0;
1652 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
1653 while(test){
1654
1655 // set function cfd variable
1656 csrt.cfd = this.nextDouble();
1657
1658 // call root searching method
1659 double rangd = realR.falsePosition(csrt, lowerBound, upperBound);
1660
1661 if(!Double.isNaN(rangd)){
1662 test=false;
1663 ran[i] = rangd;
1664 }
1665 else{
1666 if(ii>imax){
1667 System.out.println("class: PsRandom, method: chiSquareArray");
1668 System.out.println(imax + " successive attempts at calculating a random chi square deviate failed for values of nu = " + nu);
1669 System.out.println("NaN returned");
1670 ran[i] = Double.NaN;
1671 test = false;
1672 }
1673 else{
1674 ii++;
1675 }
1676 }
1677 }
1678 }
1679 return ran;
1680 }
1681
1682 // method for generating a Chi-Square random deviate
1683 public double nextChiSquare(int nu){
1684 if(nu<=0)throw new IllegalArgumentException("The degrees of freedom [nu], " + nu + ", must be greater than zero");
1685
1686 double ran = 0.0D;
1687
1688 // Create instance of the class holding the chiSquare cfd function
1689 ChiSquareFunct csrt = new ChiSquareFunct();
1690
1691 // set function variables
1692 csrt.nu = nu;
1693
1694 // required tolerance
1695 double tolerance = 1e-10;
1696
1697 // lower bound
1698 double lowerBound = 0.0D;
1699 // upper bound
1700 double upperBound = 5.0D*Math.sqrt(2*nu);
1701
1702 // Create instance of RealRoot
1703 RealRoot realR = new RealRoot();
1704
1705 // Set extension limits
1706 realR.noLowerBoundExtension();
1707
1708 // Set tolerance
1709 realR.setTolerance(tolerance);
1710
1711 // Supress error messages and arrange for NaN to be returned as root if root not found
1712 realR.resetNaNexceptionToTrue();
1713 realR.supressLimitReachedMessage();
1714 realR.supressNaNmessage();
1715
1716 // Loop to reject failed attempts at calculating the deviate
1717 boolean test=true;
1718 int ii=0;
1719 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
1720 while(test){
1721
1722 // set function cfd variable
1723 csrt.cfd = this.nextDouble();
1724
1725 // call root searching method
1726 ran = realR.falsePosition(csrt, lowerBound, upperBound);
1727
1728 if(!Double.isNaN(ran)){
1729 test=false;
1730 }
1731 else{
1732 if(ii>imax){
1733 System.out.println("class: PsRandom, method: nextChiSqauare");
1734 System.out.println(imax + " successive attempts at calculating a random Chi Square deviate failed for values of nu = " + nu);
1735 System.out.println("NaN returned");
1736 ran = Double.NaN;
1737 test = false;
1738 }
1739 else{
1740 ii++;
1741 }
1742 }
1743 }
1744 return ran;
1745 }
1746
1747 // F-DISTRIBUTION
1748 // method for generating an F-distribution random deviate
1749 public double nextF(int nu1, int nu2){
1750 double ran = Double.NaN;
1751
1752 // Create instance of the class holding the F-distribution cfd function
1753 Ffunct frt = new Ffunct();
1754
1755 // set function variables
1756 frt.nu1 = nu1;
1757 frt.nu2 = nu2;
1758 // required tolerance
1759 double tolerance = 1e-10;
1760
1761 // lower bound
1762 double lowerBound = 0.0D;
1763
1764 // upper bound
1765 double upperBound = 10.0D;
1766 if(nu2>4) {
1767 upperBound = 5.0D*Math.sqrt(2*nu2*nu2*(nu1+nu2-2)/(nu1*(nu2-2)*(nu2-2)*(nu2-4)));
1768 }
1769
1770
1771 // Create instance of RealRoot
1772 RealRoot realR = new RealRoot();
1773
1774 // Set extension limits
1775 realR.noLowerBoundExtension();
1776
1777 // Set tolerance
1778 realR.setTolerance(tolerance);
1779
1780 // Supress error messages and arrange for NaN to be returned as root if root not found
1781 realR.resetNaNexceptionToTrue();
1782 realR.supressLimitReachedMessage();
1783 realR.supressNaNmessage();
1784
1785 // Loop to reject failed attempts at calculating the deviate
1786 boolean test=true;
1787 int ii=0;
1788 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
1789 while(test){
1790
1791 // set function cfd variable
1792 frt.cfd = this.nextDouble();
1793
1794 // call root searching method
1795 ran = realR.falsePosition(frt, lowerBound, upperBound);
1796
1797 if(!Double.isNaN(ran)){
1798 test=false;
1799 }
1800 else{
1801 if(ii>imax){
1802 System.out.println("class: PsRandom, method: nextF");
1803 System.out.println(imax + " successive attempts at calculating a random F-distribution deviate failed for values of nu1 = " + nu1 + ", nu2 = " + nu2);
1804 System.out.println("NaN returned");
1805 ran = Double.NaN;
1806 test = false;
1807 }
1808 else{
1809 ii++;
1810 }
1811 }
1812 }
1813 return ran;
1814 }
1815
1816
1817 // method for generating an array of F-distribution random deviates
1818 public double[] fArray(int nu1, int nu2, int n){
1819 double[] ran = new double[n];
1820
1821 // Create instance of the class holding the F-distribution cfd function
1822 Ffunct frt = new Ffunct();
1823
1824 // set function variables
1825 frt.nu1 = nu1;
1826 frt.nu2 = nu2;
1827
1828 // required tolerance
1829 double tolerance = 1e-10;
1830
1831 // lower bound
1832 double lowerBound = 0.0D;
1833
1834 // upper bound
1835 double upperBound = 10.0D;
1836 double nu1d = nu1;
1837 double nu2d = nu2;
1838 if(nu2>4) {
1839 upperBound = 5.0D*Math.sqrt(2*nu2d*nu2d*(nu1d+nu2d-2)/(nu1d*(nu2d-2)*(nu2d-2)*(nu2d-4)));
1840 }
1841
1842 for(int i=0; i<n; i++){
1843
1844 // Create instance of RealRoot
1845 RealRoot realR = new RealRoot();
1846
1847 // Set extension limits
1848 realR.noLowerBoundExtension();
1849
1850 // Set tolerance
1851 realR.setTolerance(tolerance);
1852
1853 // Supress error messages and arrange for NaN to be returned as root if root not found
1854 realR.resetNaNexceptionToTrue();
1855 realR.supressLimitReachedMessage();
1856 realR.supressNaNmessage();
1857
1858 // Loop to reject failed attempts at calculating the deviate
1859 boolean test=true;
1860 int ii=0;
1861 int imax = 10; // maximum number of successive attempts at calculating deviate allowed
1862 while(test){
1863
1864 // set function cfd variable
1865 frt.cfd = this.nextDouble();
1866
1867 // call root searching method
1868 double rangd = realR.falsePosition(frt, lowerBound, upperBound);
1869 if(!Double.isNaN(rangd)){
1870 test=false;
1871 ran[i] = rangd;
1872 }
1873 else{
1874 if(ii>imax){
1875 System.out.println("class: PsRandom, method: fArray");
1876 System.out.println(imax + " successive attempts at calculating a random f-distribution deviate failed for values of nu1 = " + nu1 + ", nu2 = " + nu2);
1877 System.out.println("NaN returned");
1878 ran[i] = Double.NaN;
1879 test = false;
1880 }
1881 else{
1882 ii++;
1883 }
1884 }
1885 }
1886 }
1887 return ran;
1888 }
1889
1890 // PSEUDORANDOM INTEGERS
1891 // Returns a pseudorandom int integer between 0.0 and top
1892 public int nextInteger(int bottom, int top){
1893 int randint = 0;
1894 switch(this.methodOptionInteger){
1895 case 1: // Java Random class nextInt()
1896 randint = this.rr.nextInt(++top - bottom) + bottom;
1897 break;
1898 case 2: randint = (int)Math.round(this.nextDouble()*(top - bottom)) + bottom;
1899 break;
1900 case 3: randint = (int)Math.floor(this.nextDouble()*(++top - bottom)) + bottom;
1901 break;
1902 default: throw new IllegalArgumentException("methodOptionInteger, " + this.methodOptionInteger + " is not recognised");
1903 }
1904
1905 return randint;
1906 }
1907
1908 // Returns a pseudorandom int integer between bottom (inclusive) and top (inclusive)
1909 public int nextInteger(int top){
1910 return this.nextInteger(0, top);
1911 }
1912
1913 // Returns an array, of length arraylength, of pseudorandom int integers between 0.0 (inclusive) and top (inclusive)
1914 public int[] integerArray(int arrayLength, int top){
1915 int[] array = new int[arrayLength];
1916 for(int i=0; i<arrayLength; i++){
1917 array[i] = this.nextInteger(top);
1918 }
1919 return array;
1920 }
1921
1922 // Returns an array, of length arraylength, of pseudorandom int integers between bottom and top
1923 public int[] integerArray(int arrayLength, int bottom, int top){
1924 int[] array = new int[arrayLength];
1925 for(int i=0; i<arrayLength; i++){
1926 array[i] = this.nextInteger(bottom - top) + bottom;
1927 }
1928 return array;
1929 }
1930
1931 // Returns an array, of length top+1, of unique pseudorandom integers between bottom and top
1932 // i.e. no integer is repeated and all integers between bottom and top inclusive are present
1933 public int[] uniqueIntegerArray(int bottom, int top){
1934 int range = top - bottom;
1935 int[] array = uniqueIntegerArray(range);
1936 for(int i=0; i<range+1; i++) {
1937 array[i] += bottom;
1938 }
1939 return array;
1940 }
1941
1942
1943 // Returns an array, of length top+1, of unique pseudorandom integers between 0 and top
1944 // i.e. no integer is repeated and all integers between 0 and top inclusive are present
1945 public int[] uniqueIntegerArray(int top){
1946 int numberOfIntegers = top + 1; // number of unique pseudorandom integers returned
1947 int[] array = new int[numberOfIntegers]; // array to contain returned unique pseudorandom integers
1948 boolean allFound = false; // will equal true when all required integers found
1949 int nFound = 0; // number of required pseudorandom integers found
1950 boolean[] found = new boolean[numberOfIntegers]; // = true when integer corresponding to its index is found
1951 for(int i=0; i<numberOfIntegers; i++) {
1952 found[i] = false;
1953 }
1954
1955 while(!allFound){
1956 int ii = this.nextInteger(top);
1957 if(!found[ii]){
1958 array[nFound] = ii;
1959 found[ii] = true;
1960 nFound++;
1961 if(nFound==numberOfIntegers) {
1962 allFound = true;
1963 }
1964 }
1965 }
1966 return array;
1967 }
1968
1969
1970
1971 // Return the serial version unique identifier
1972 public static long getSerialVersionUID(){
1973 return PsRandom.serialVersionUID;
1974 }
1975}
1976
1977
1978// Class to evaluate the Student's t-function
1979class StudentTfunct implements RealRootFunction{
1980 public int nu = 0;
1981 public double cfd = 0.0D;
1982
1983 public double function(double x){
1984
1985 double y = cfd - Stat.studentTcdf(x, nu);
1986
1987 return y;
1988 }
1989}
1990
1991// Class to evaluate the Gamma distribution function
1992class GammaFunct implements RealRootFunction{
1993 public double mu = 0.0D;
1994 public double beta = 0.0D;
1995 public double gamma = 0.0D;
1996 public double cfd = 0.0D;
1997
1998 public double function(double x){
1999
2000 double y = cfd - Stat.gammaCDF(mu, beta, gamma, x);
2001
2002 return y;
2003 }
2004}
2005
2006
2007// Class to evaluate the Beta distribution function
2008class BetaFunct implements RealRootFunction{
2009 public double alpha = 0.0D;
2010 public double beta = 0.0D;
2011 public double min = 0.0D;
2012 public double max = 0.0D;
2013 public double cfd = 0.0D;
2014
2015 public double function(double x){
2016 double y = cfd - Stat.betaCDF(min, max, alpha, beta, x);
2017
2018 return y;
2019 }
2020}
2021
2022// Class to evaluate the chi-square distribution function
2023class ChiSquareFunct implements RealRootFunction{
2024
2025 public double cfd = 0.0D;
2026 public int nu = 0;
2027
2028 public double function(double x){
2029
2030 double y = cfd - Stat.chiSquareCDF(x, nu);
2031
2032 return y;
2033 }
2034}
2035
2036// Class to evaluate the F-distribution function
2037class Ffunct implements RealRootFunction{
2038
2039 public double cfd = 0.0D;
2040 public int nu1 = 0;
2041 public int nu2 = 0;
2042
2043 public double function(double x){
2044
2045 double y = cfd - (1.0D - Stat.fCompCDF(x, nu1, nu2));
2046
2047 return y;
2048 }
2049}
2050
2051
2052// Class to evaluate the two parameter log-normal distribution function
2053class LogNormalTwoParFunct implements RealRootFunction{
2054
2055 public double cfd = 0.0D;
2056 public double mu = 0.0D;
2057 public double sigma = 0.0D;
2058
2059 public double function(double x){
2060
2061 double y = cfd - Stat.logNormalCDF(mu, sigma, x);
2062
2063 return y;
2064 }
2065}
2066
Note: See TracBrowser for help on using the repository browser.