001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.math3.random; 019 020import java.io.Serializable; 021import java.security.NoSuchAlgorithmException; 022import java.security.NoSuchProviderException; 023import java.util.Collection; 024 025import org.apache.commons.math3.distribution.IntegerDistribution; 026import org.apache.commons.math3.distribution.RealDistribution; 027import org.apache.commons.math3.exception.NotANumberException; 028import org.apache.commons.math3.exception.NotFiniteNumberException; 029import org.apache.commons.math3.exception.NotPositiveException; 030import org.apache.commons.math3.exception.NotStrictlyPositiveException; 031import org.apache.commons.math3.exception.MathIllegalArgumentException; 032import org.apache.commons.math3.exception.NumberIsTooLargeException; 033import org.apache.commons.math3.exception.OutOfRangeException; 034 035/** 036 * Generates random deviates and other random data using a {@link RandomGenerator} 037 * instance to generate non-secure data and a {@link java.security.SecureRandom} 038 * instance to provide data for the <code>nextSecureXxx</code> methods. If no 039 * <code>RandomGenerator</code> is provided in the constructor, the default is 040 * to use a {@link Well19937c} generator. To plug in a different 041 * implementation, either implement <code>RandomGenerator</code> directly or 042 * extend {@link AbstractRandomGenerator}. 043 * <p> 044 * Supports reseeding the underlying pseudo-random number generator (PRNG). The 045 * <code>SecurityProvider</code> and <code>Algorithm</code> used by the 046 * <code>SecureRandom</code> instance can also be reset. 047 * </p> 048 * <p> 049 * For details on the default PRNGs, see {@link java.util.Random} and 050 * {@link java.security.SecureRandom}. 051 * </p> 052 * <p> 053 * <strong>Usage Notes</strong>: 054 * <ul> 055 * <li> 056 * Instance variables are used to maintain <code>RandomGenerator</code> and 057 * <code>SecureRandom</code> instances used in data generation. Therefore, to 058 * generate a random sequence of values or strings, you should use just 059 * <strong>one</strong> <code>RandomDataGenerator</code> instance repeatedly.</li> 060 * <li> 061 * The "secure" methods are *much* slower. These should be used only when a 062 * cryptographically secure random sequence is required. A secure random 063 * sequence is a sequence of pseudo-random values which, in addition to being 064 * well-dispersed (so no subsequence of values is an any more likely than other 065 * subsequence of the the same length), also has the additional property that 066 * knowledge of values generated up to any point in the sequence does not make 067 * it any easier to predict subsequent values.</li> 068 * <li> 069 * When a new <code>RandomDataGenerator</code> is created, the underlying random 070 * number generators are <strong>not</strong> initialized. If you do not 071 * explicitly seed the default non-secure generator, it is seeded with the 072 * current time in milliseconds plus the system identity hash code on first use. 073 * The same holds for the secure generator. If you provide a <code>RandomGenerator</code> 074 * to the constructor, however, this generator is not reseeded by the constructor 075 * nor is it reseeded on first use.</li> 076 * <li> 077 * The <code>reSeed</code> and <code>reSeedSecure</code> methods delegate to the 078 * corresponding methods on the underlying <code>RandomGenerator</code> and 079 * <code>SecureRandom</code> instances. Therefore, <code>reSeed(long)</code> 080 * fully resets the initial state of the non-secure random number generator (so 081 * that reseeding with a specific value always results in the same subsequent 082 * random sequence); whereas reSeedSecure(long) does <strong>not</strong> 083 * reinitialize the secure random number generator (so secure sequences started 084 * with calls to reseedSecure(long) won't be identical).</li> 085 * <li> 086 * This implementation is not synchronized. The underlying <code>RandomGenerator</code> 087 * or <code>SecureRandom</code> instances are not protected by synchronization and 088 * are not guaranteed to be thread-safe. Therefore, if an instance of this class 089 * is concurrently utilized by multiple threads, it is the responsibility of 090 * client code to synchronize access to seeding and data generation methods. 091 * </li> 092 * </ul> 093 * </p> 094 * @deprecated to be removed in 4.0. Use {@link RandomDataGenerator} instead 095 */ 096@Deprecated 097public class RandomDataImpl implements RandomData, Serializable { 098 099 /** Serializable version identifier */ 100 private static final long serialVersionUID = -626730818244969716L; 101 102 /** RandomDataGenerator delegate */ 103 private final RandomDataGenerator delegate; 104 105 /** 106 * Construct a RandomDataImpl, using a default random generator as the source 107 * of randomness. 108 * 109 * <p>The default generator is a {@link Well19937c} seeded 110 * with {@code System.currentTimeMillis() + System.identityHashCode(this))}. 111 * The generator is initialized and seeded on first use.</p> 112 */ 113 public RandomDataImpl() { 114 delegate = new RandomDataGenerator(); 115 } 116 117 /** 118 * Construct a RandomDataImpl using the supplied {@link RandomGenerator} as 119 * the source of (non-secure) random data. 120 * 121 * @param rand the source of (non-secure) random data 122 * (may be null, resulting in the default generator) 123 * @since 1.1 124 */ 125 public RandomDataImpl(RandomGenerator rand) { 126 delegate = new RandomDataGenerator(rand); 127 } 128 129 /** 130 * @return the delegate object. 131 * @deprecated To be removed in 4.0. 132 */ 133 @Deprecated 134 RandomDataGenerator getDelegate() { 135 return delegate; 136 } 137 138 /** 139 * {@inheritDoc} 140 * <p> 141 * <strong>Algorithm Description:</strong> hex strings are generated using a 142 * 2-step process. 143 * <ol> 144 * <li>{@code len / 2 + 1} binary bytes are generated using the underlying 145 * Random</li> 146 * <li>Each binary byte is translated into 2 hex digits</li> 147 * </ol> 148 * </p> 149 * 150 * @param len the desired string length. 151 * @return the random string. 152 * @throws NotStrictlyPositiveException if {@code len <= 0}. 153 */ 154 public String nextHexString(int len) throws NotStrictlyPositiveException { 155 return delegate.nextHexString(len); 156 } 157 158 /** {@inheritDoc} */ 159 public int nextInt(int lower, int upper) throws NumberIsTooLargeException { 160 return delegate.nextInt(lower, upper); 161 } 162 163 /** {@inheritDoc} */ 164 public long nextLong(long lower, long upper) throws NumberIsTooLargeException { 165 return delegate.nextLong(lower, upper); 166 } 167 168 /** 169 * {@inheritDoc} 170 * <p> 171 * <strong>Algorithm Description:</strong> hex strings are generated in 172 * 40-byte segments using a 3-step process. 173 * <ol> 174 * <li> 175 * 20 random bytes are generated using the underlying 176 * <code>SecureRandom</code>.</li> 177 * <li> 178 * SHA-1 hash is applied to yield a 20-byte binary digest.</li> 179 * <li> 180 * Each byte of the binary digest is converted to 2 hex digits.</li> 181 * </ol> 182 * </p> 183 */ 184 public String nextSecureHexString(int len) throws NotStrictlyPositiveException { 185 return delegate.nextSecureHexString(len); 186 } 187 188 /** {@inheritDoc} */ 189 public int nextSecureInt(int lower, int upper) throws NumberIsTooLargeException { 190 return delegate.nextSecureInt(lower, upper); 191 } 192 193 /** {@inheritDoc} */ 194 public long nextSecureLong(long lower, long upper) throws NumberIsTooLargeException { 195 return delegate.nextSecureLong(lower,upper); 196 } 197 198 /** 199 * {@inheritDoc} 200 * <p> 201 * <strong>Algorithm Description</strong>: 202 * <ul><li> For small means, uses simulation of a Poisson process 203 * using Uniform deviates, as described 204 * <a href="http://irmi.epfl.ch/cmos/Pmmi/interactive/rng7.htm"> here.</a> 205 * The Poisson process (and hence value returned) is bounded by 1000 * mean.</li> 206 * 207 * <li> For large means, uses the rejection algorithm described in <br/> 208 * Devroye, Luc. (1981).<i>The Computer Generation of Poisson Random Variables</i> 209 * <strong>Computing</strong> vol. 26 pp. 197-207.</li></ul></p> 210 */ 211 public long nextPoisson(double mean) throws NotStrictlyPositiveException { 212 return delegate.nextPoisson(mean); 213 } 214 215 /** {@inheritDoc} */ 216 public double nextGaussian(double mu, double sigma) throws NotStrictlyPositiveException { 217 return delegate.nextGaussian(mu,sigma); 218 } 219 220 /** 221 * {@inheritDoc} 222 * 223 * <p> 224 * <strong>Algorithm Description</strong>: Uses the Algorithm SA (Ahrens) 225 * from p. 876 in: 226 * [1]: Ahrens, J. H. and Dieter, U. (1972). Computer methods for 227 * sampling from the exponential and normal distributions. 228 * Communications of the ACM, 15, 873-882. 229 * </p> 230 */ 231 public double nextExponential(double mean) throws NotStrictlyPositiveException { 232 return delegate.nextExponential(mean); 233 } 234 235 /** 236 * {@inheritDoc} 237 * 238 * <p> 239 * <strong>Algorithm Description</strong>: scales the output of 240 * Random.nextDouble(), but rejects 0 values (i.e., will generate another 241 * random double if Random.nextDouble() returns 0). This is necessary to 242 * provide a symmetric output interval (both endpoints excluded). 243 * </p> 244 */ 245 public double nextUniform(double lower, double upper) 246 throws NumberIsTooLargeException, NotFiniteNumberException, NotANumberException { 247 return delegate.nextUniform(lower, upper); 248 } 249 250 /** 251 * {@inheritDoc} 252 * 253 * <p> 254 * <strong>Algorithm Description</strong>: if the lower bound is excluded, 255 * scales the output of Random.nextDouble(), but rejects 0 values (i.e., 256 * will generate another random double if Random.nextDouble() returns 0). 257 * This is necessary to provide a symmetric output interval (both 258 * endpoints excluded). 259 * </p> 260 * @since 3.0 261 */ 262 public double nextUniform(double lower, double upper, boolean lowerInclusive) 263 throws NumberIsTooLargeException, NotFiniteNumberException, NotANumberException { 264 return delegate.nextUniform(lower, upper, lowerInclusive); 265 } 266 267 /** 268 * Generates a random value from the {@link org.apache.commons.math3.distribution.BetaDistribution Beta Distribution}. 269 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 270 * to generate random values. 271 * 272 * @param alpha first distribution shape parameter 273 * @param beta second distribution shape parameter 274 * @return random value sampled from the beta(alpha, beta) distribution 275 * @since 2.2 276 */ 277 public double nextBeta(double alpha, double beta) { 278 return delegate.nextBeta(alpha, beta); 279 } 280 281 /** 282 * Generates a random value from the {@link org.apache.commons.math3.distribution.BinomialDistribution Binomial Distribution}. 283 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 284 * to generate random values. 285 * 286 * @param numberOfTrials number of trials of the Binomial distribution 287 * @param probabilityOfSuccess probability of success of the Binomial distribution 288 * @return random value sampled from the Binomial(numberOfTrials, probabilityOfSuccess) distribution 289 * @since 2.2 290 */ 291 public int nextBinomial(int numberOfTrials, double probabilityOfSuccess) { 292 return delegate.nextBinomial(numberOfTrials, probabilityOfSuccess); 293 } 294 295 /** 296 * Generates a random value from the {@link org.apache.commons.math3.distribution.CauchyDistribution Cauchy Distribution}. 297 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 298 * to generate random values. 299 * 300 * @param median the median of the Cauchy distribution 301 * @param scale the scale parameter of the Cauchy distribution 302 * @return random value sampled from the Cauchy(median, scale) distribution 303 * @since 2.2 304 */ 305 public double nextCauchy(double median, double scale) { 306 return delegate.nextCauchy(median, scale); 307 } 308 309 /** 310 * Generates a random value from the {@link org.apache.commons.math3.distribution.ChiSquaredDistribution ChiSquare Distribution}. 311 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 312 * to generate random values. 313 * 314 * @param df the degrees of freedom of the ChiSquare distribution 315 * @return random value sampled from the ChiSquare(df) distribution 316 * @since 2.2 317 */ 318 public double nextChiSquare(double df) { 319 return delegate.nextChiSquare(df); 320 } 321 322 /** 323 * Generates a random value from the {@link org.apache.commons.math3.distribution.FDistribution F Distribution}. 324 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 325 * to generate random values. 326 * 327 * @param numeratorDf the numerator degrees of freedom of the F distribution 328 * @param denominatorDf the denominator degrees of freedom of the F distribution 329 * @return random value sampled from the F(numeratorDf, denominatorDf) distribution 330 * @throws NotStrictlyPositiveException if 331 * {@code numeratorDf <= 0} or {@code denominatorDf <= 0}. 332 * @since 2.2 333 */ 334 public double nextF(double numeratorDf, double denominatorDf) throws NotStrictlyPositiveException { 335 return delegate.nextF(numeratorDf, denominatorDf); 336 } 337 338 /** 339 * <p>Generates a random value from the 340 * {@link org.apache.commons.math3.distribution.GammaDistribution Gamma Distribution}.</p> 341 * 342 * <p>This implementation uses the following algorithms: </p> 343 * 344 * <p>For 0 < shape < 1: <br/> 345 * Ahrens, J. H. and Dieter, U., <i>Computer methods for 346 * sampling from gamma, beta, Poisson and binomial distributions.</i> 347 * Computing, 12, 223-246, 1974.</p> 348 * 349 * <p>For shape >= 1: <br/> 350 * Marsaglia and Tsang, <i>A Simple Method for Generating 351 * Gamma Variables.</i> ACM Transactions on Mathematical Software, 352 * Volume 26 Issue 3, September, 2000.</p> 353 * 354 * @param shape the median of the Gamma distribution 355 * @param scale the scale parameter of the Gamma distribution 356 * @return random value sampled from the Gamma(shape, scale) distribution 357 * @throws NotStrictlyPositiveException if {@code shape <= 0} or 358 * {@code scale <= 0}. 359 * @since 2.2 360 */ 361 public double nextGamma(double shape, double scale) throws NotStrictlyPositiveException { 362 return delegate.nextGamma(shape, scale); 363 } 364 365 /** 366 * Generates a random value from the {@link org.apache.commons.math3.distribution.HypergeometricDistribution Hypergeometric Distribution}. 367 * This implementation uses {@link #nextInversionDeviate(IntegerDistribution) inversion} 368 * to generate random values. 369 * 370 * @param populationSize the population size of the Hypergeometric distribution 371 * @param numberOfSuccesses number of successes in the population of the Hypergeometric distribution 372 * @param sampleSize the sample size of the Hypergeometric distribution 373 * @return random value sampled from the Hypergeometric(numberOfSuccesses, sampleSize) distribution 374 * @throws NumberIsTooLargeException if {@code numberOfSuccesses > populationSize}, 375 * or {@code sampleSize > populationSize}. 376 * @throws NotStrictlyPositiveException if {@code populationSize <= 0}. 377 * @throws NotPositiveException if {@code numberOfSuccesses < 0}. 378 * @since 2.2 379 */ 380 public int nextHypergeometric(int populationSize, int numberOfSuccesses, int sampleSize) 381 throws NotPositiveException, NotStrictlyPositiveException, NumberIsTooLargeException { 382 return delegate.nextHypergeometric(populationSize, numberOfSuccesses, sampleSize); 383 } 384 385 /** 386 * Generates a random value from the {@link org.apache.commons.math3.distribution.PascalDistribution Pascal Distribution}. 387 * This implementation uses {@link #nextInversionDeviate(IntegerDistribution) inversion} 388 * to generate random values. 389 * 390 * @param r the number of successes of the Pascal distribution 391 * @param p the probability of success of the Pascal distribution 392 * @return random value sampled from the Pascal(r, p) distribution 393 * @since 2.2 394 * @throws NotStrictlyPositiveException if the number of successes is not positive 395 * @throws OutOfRangeException if the probability of success is not in the 396 * range {@code [0, 1]}. 397 */ 398 public int nextPascal(int r, double p) 399 throws NotStrictlyPositiveException, OutOfRangeException { 400 return delegate.nextPascal(r, p); 401 } 402 403 /** 404 * Generates a random value from the {@link org.apache.commons.math3.distribution.TDistribution T Distribution}. 405 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 406 * to generate random values. 407 * 408 * @param df the degrees of freedom of the T distribution 409 * @return random value from the T(df) distribution 410 * @since 2.2 411 * @throws NotStrictlyPositiveException if {@code df <= 0} 412 */ 413 public double nextT(double df) throws NotStrictlyPositiveException { 414 return delegate.nextT(df); 415 } 416 417 /** 418 * Generates a random value from the {@link org.apache.commons.math3.distribution.WeibullDistribution Weibull Distribution}. 419 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 420 * to generate random values. 421 * 422 * @param shape the shape parameter of the Weibull distribution 423 * @param scale the scale parameter of the Weibull distribution 424 * @return random value sampled from the Weibull(shape, size) distribution 425 * @since 2.2 426 * @throws NotStrictlyPositiveException if {@code shape <= 0} or 427 * {@code scale <= 0}. 428 */ 429 public double nextWeibull(double shape, double scale) throws NotStrictlyPositiveException { 430 return delegate.nextWeibull(shape, scale); 431 } 432 433 /** 434 * Generates a random value from the {@link org.apache.commons.math3.distribution.ZipfDistribution Zipf Distribution}. 435 * This implementation uses {@link #nextInversionDeviate(IntegerDistribution) inversion} 436 * to generate random values. 437 * 438 * @param numberOfElements the number of elements of the ZipfDistribution 439 * @param exponent the exponent of the ZipfDistribution 440 * @return random value sampled from the Zipf(numberOfElements, exponent) distribution 441 * @since 2.2 442 * @exception NotStrictlyPositiveException if {@code numberOfElements <= 0} 443 * or {@code exponent <= 0}. 444 */ 445 public int nextZipf(int numberOfElements, double exponent) throws NotStrictlyPositiveException { 446 return delegate.nextZipf(numberOfElements, exponent); 447 } 448 449 450 /** 451 * Reseeds the random number generator with the supplied seed. 452 * <p> 453 * Will create and initialize if null. 454 * </p> 455 * 456 * @param seed 457 * the seed value to use 458 */ 459 public void reSeed(long seed) { 460 delegate.reSeed(seed); 461 } 462 463 /** 464 * Reseeds the secure random number generator with the current time in 465 * milliseconds. 466 * <p> 467 * Will create and initialize if null. 468 * </p> 469 */ 470 public void reSeedSecure() { 471 delegate.reSeedSecure(); 472 } 473 474 /** 475 * Reseeds the secure random number generator with the supplied seed. 476 * <p> 477 * Will create and initialize if null. 478 * </p> 479 * 480 * @param seed 481 * the seed value to use 482 */ 483 public void reSeedSecure(long seed) { 484 delegate.reSeedSecure(seed); 485 } 486 487 /** 488 * Reseeds the random number generator with 489 * {@code System.currentTimeMillis() + System.identityHashCode(this))}. 490 */ 491 public void reSeed() { 492 delegate.reSeed(); 493 } 494 495 /** 496 * Sets the PRNG algorithm for the underlying SecureRandom instance using 497 * the Security Provider API. The Security Provider API is defined in <a 498 * href = 499 * "http://java.sun.com/j2se/1.3/docs/guide/security/CryptoSpec.html#AppA"> 500 * Java Cryptography Architecture API Specification & Reference.</a> 501 * <p> 502 * <strong>USAGE NOTE:</strong> This method carries <i>significant</i> 503 * overhead and may take several seconds to execute. 504 * </p> 505 * 506 * @param algorithm 507 * the name of the PRNG algorithm 508 * @param provider 509 * the name of the provider 510 * @throws NoSuchAlgorithmException 511 * if the specified algorithm is not available 512 * @throws NoSuchProviderException 513 * if the specified provider is not installed 514 */ 515 public void setSecureAlgorithm(String algorithm, String provider) 516 throws NoSuchAlgorithmException, NoSuchProviderException { 517 delegate.setSecureAlgorithm(algorithm, provider); 518 } 519 520 /** 521 * {@inheritDoc} 522 * 523 * <p> 524 * Uses a 2-cycle permutation shuffle. The shuffling process is described <a 525 * href="http://www.maths.abdn.ac.uk/~igc/tch/mx4002/notes/node83.html"> 526 * here</a>. 527 * </p> 528 */ 529 public int[] nextPermutation(int n, int k) 530 throws NotStrictlyPositiveException, NumberIsTooLargeException { 531 return delegate.nextPermutation(n, k); 532 } 533 534 /** 535 * {@inheritDoc} 536 * 537 * <p> 538 * <strong>Algorithm Description</strong>: Uses a 2-cycle permutation 539 * shuffle to generate a random permutation of <code>c.size()</code> and 540 * then returns the elements whose indexes correspond to the elements of the 541 * generated permutation. This technique is described, and proven to 542 * generate random samples <a 543 * href="http://www.maths.abdn.ac.uk/~igc/tch/mx4002/notes/node83.html"> 544 * here</a> 545 * </p> 546 */ 547 public Object[] nextSample(Collection<?> c, int k) 548 throws NotStrictlyPositiveException, NumberIsTooLargeException { 549 return delegate.nextSample(c, k); 550 } 551 552 /** 553 * Generate a random deviate from the given distribution using the 554 * <a href="http://en.wikipedia.org/wiki/Inverse_transform_sampling"> inversion method.</a> 555 * 556 * @param distribution Continuous distribution to generate a random value from 557 * @return a random value sampled from the given distribution 558 * @throws MathIllegalArgumentException if the underlynig distribution throws one 559 * @since 2.2 560 * @deprecated use the distribution's sample() method 561 */ 562 @Deprecated 563 public double nextInversionDeviate(RealDistribution distribution) 564 throws MathIllegalArgumentException { 565 return distribution.inverseCumulativeProbability(nextUniform(0, 1)); 566 567 } 568 569 /** 570 * Generate a random deviate from the given distribution using the 571 * <a href="http://en.wikipedia.org/wiki/Inverse_transform_sampling"> inversion method.</a> 572 * 573 * @param distribution Integer distribution to generate a random value from 574 * @return a random value sampled from the given distribution 575 * @throws MathIllegalArgumentException if the underlynig distribution throws one 576 * @since 2.2 577 * @deprecated use the distribution's sample() method 578 */ 579 @Deprecated 580 public int nextInversionDeviate(IntegerDistribution distribution) 581 throws MathIllegalArgumentException { 582 return distribution.inverseCumulativeProbability(nextUniform(0, 1)); 583 } 584 585}