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 018 package org.apache.commons.math3.random; 019 020 import java.io.Serializable; 021 import java.security.NoSuchAlgorithmException; 022 import java.security.NoSuchProviderException; 023 import java.util.Collection; 024 025 import org.apache.commons.math3.distribution.IntegerDistribution; 026 import org.apache.commons.math3.distribution.RealDistribution; 027 import org.apache.commons.math3.exception.NotANumberException; 028 import org.apache.commons.math3.exception.NotFiniteNumberException; 029 import org.apache.commons.math3.exception.NotPositiveException; 030 import org.apache.commons.math3.exception.NotStrictlyPositiveException; 031 import org.apache.commons.math3.exception.MathIllegalArgumentException; 032 import org.apache.commons.math3.exception.NumberIsTooLargeException; 033 import 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 * @version $Id: RandomDataImpl.java 1421917 2012-12-14 15:05:18Z erans $ 096 */ 097 @Deprecated 098 public class RandomDataImpl implements RandomData, Serializable { 099 100 /** Serializable version identifier */ 101 private static final long serialVersionUID = -626730818244969716L; 102 103 /** RandomDataGenerator delegate */ 104 private final RandomDataGenerator delegate; 105 106 /** 107 * Construct a RandomDataImpl, using a default random generator as the source 108 * of randomness. 109 * 110 * <p>The default generator is a {@link Well19937c} seeded 111 * with {@code System.currentTimeMillis() + System.identityHashCode(this))}. 112 * The generator is initialized and seeded on first use.</p> 113 */ 114 public RandomDataImpl() { 115 delegate = new RandomDataGenerator(); 116 } 117 118 /** 119 * Construct a RandomDataImpl using the supplied {@link RandomGenerator} as 120 * the source of (non-secure) random data. 121 * 122 * @param rand the source of (non-secure) random data 123 * (may be null, resulting in the default generator) 124 * @since 1.1 125 */ 126 public RandomDataImpl(RandomGenerator rand) { 127 delegate = new RandomDataGenerator(rand); 128 } 129 130 /** 131 * @return the delegate object. 132 * @deprecated To be removed in 4.0. 133 */ 134 @Deprecated 135 RandomDataGenerator getDelegate() { 136 return delegate; 137 } 138 139 /** 140 * {@inheritDoc} 141 * <p> 142 * <strong>Algorithm Description:</strong> hex strings are generated using a 143 * 2-step process. 144 * <ol> 145 * <li>{@code len / 2 + 1} binary bytes are generated using the underlying 146 * Random</li> 147 * <li>Each binary byte is translated into 2 hex digits</li> 148 * </ol> 149 * </p> 150 * 151 * @param len the desired string length. 152 * @return the random string. 153 * @throws NotStrictlyPositiveException if {@code len <= 0}. 154 */ 155 public String nextHexString(int len) throws NotStrictlyPositiveException { 156 return delegate.nextHexString(len); 157 } 158 159 /** {@inheritDoc} */ 160 public int nextInt(int lower, int upper) throws NumberIsTooLargeException { 161 return delegate.nextInt(lower, upper); 162 } 163 164 /** {@inheritDoc} */ 165 public long nextLong(long lower, long upper) throws NumberIsTooLargeException { 166 return delegate.nextLong(lower, upper); 167 } 168 169 /** 170 * {@inheritDoc} 171 * <p> 172 * <strong>Algorithm Description:</strong> hex strings are generated in 173 * 40-byte segments using a 3-step process. 174 * <ol> 175 * <li> 176 * 20 random bytes are generated using the underlying 177 * <code>SecureRandom</code>.</li> 178 * <li> 179 * SHA-1 hash is applied to yield a 20-byte binary digest.</li> 180 * <li> 181 * Each byte of the binary digest is converted to 2 hex digits.</li> 182 * </ol> 183 * </p> 184 */ 185 public String nextSecureHexString(int len) throws NotStrictlyPositiveException { 186 return delegate.nextSecureHexString(len); 187 } 188 189 /** {@inheritDoc} */ 190 public int nextSecureInt(int lower, int upper) throws NumberIsTooLargeException { 191 return delegate.nextSecureInt(lower, upper); 192 } 193 194 /** {@inheritDoc} */ 195 public long nextSecureLong(long lower, long upper) throws NumberIsTooLargeException { 196 return delegate.nextSecureLong(lower,upper); 197 } 198 199 /** 200 * {@inheritDoc} 201 * <p> 202 * <strong>Algorithm Description</strong>: 203 * <ul><li> For small means, uses simulation of a Poisson process 204 * using Uniform deviates, as described 205 * <a href="http://irmi.epfl.ch/cmos/Pmmi/interactive/rng7.htm"> here.</a> 206 * The Poisson process (and hence value returned) is bounded by 1000 * mean.</li> 207 * 208 * <li> For large means, uses the rejection algorithm described in <br/> 209 * Devroye, Luc. (1981).<i>The Computer Generation of Poisson Random Variables</i> 210 * <strong>Computing</strong> vol. 26 pp. 197-207.</li></ul></p> 211 */ 212 public long nextPoisson(double mean) throws NotStrictlyPositiveException { 213 return delegate.nextPoisson(mean); 214 } 215 216 /** {@inheritDoc} */ 217 public double nextGaussian(double mu, double sigma) throws NotStrictlyPositiveException { 218 return delegate.nextGaussian(mu,sigma); 219 } 220 221 /** 222 * {@inheritDoc} 223 * 224 * <p> 225 * <strong>Algorithm Description</strong>: Uses the Algorithm SA (Ahrens) 226 * from p. 876 in: 227 * [1]: Ahrens, J. H. and Dieter, U. (1972). Computer methods for 228 * sampling from the exponential and normal distributions. 229 * Communications of the ACM, 15, 873-882. 230 * </p> 231 */ 232 public double nextExponential(double mean) throws NotStrictlyPositiveException { 233 return delegate.nextExponential(mean); 234 } 235 236 /** 237 * {@inheritDoc} 238 * 239 * <p> 240 * <strong>Algorithm Description</strong>: scales the output of 241 * Random.nextDouble(), but rejects 0 values (i.e., will generate another 242 * random double if Random.nextDouble() returns 0). This is necessary to 243 * provide a symmetric output interval (both endpoints excluded). 244 * </p> 245 */ 246 public double nextUniform(double lower, double upper) 247 throws NumberIsTooLargeException, NotFiniteNumberException, NotANumberException { 248 return delegate.nextUniform(lower, upper); 249 } 250 251 /** 252 * {@inheritDoc} 253 * 254 * <p> 255 * <strong>Algorithm Description</strong>: if the lower bound is excluded, 256 * scales the output of Random.nextDouble(), but rejects 0 values (i.e., 257 * will generate another random double if Random.nextDouble() returns 0). 258 * This is necessary to provide a symmetric output interval (both 259 * endpoints excluded). 260 * </p> 261 * @since 3.0 262 */ 263 public double nextUniform(double lower, double upper, boolean lowerInclusive) 264 throws NumberIsTooLargeException, NotFiniteNumberException, NotANumberException { 265 return delegate.nextUniform(lower, upper, lowerInclusive); 266 } 267 268 /** 269 * Generates a random value from the {@link org.apache.commons.math3.distribution.BetaDistribution Beta Distribution}. 270 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 271 * to generate random values. 272 * 273 * @param alpha first distribution shape parameter 274 * @param beta second distribution shape parameter 275 * @return random value sampled from the beta(alpha, beta) distribution 276 * @since 2.2 277 */ 278 public double nextBeta(double alpha, double beta) { 279 return delegate.nextBeta(alpha, beta); 280 } 281 282 /** 283 * Generates a random value from the {@link org.apache.commons.math3.distribution.BinomialDistribution Binomial Distribution}. 284 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 285 * to generate random values. 286 * 287 * @param numberOfTrials number of trials of the Binomial distribution 288 * @param probabilityOfSuccess probability of success of the Binomial distribution 289 * @return random value sampled from the Binomial(numberOfTrials, probabilityOfSuccess) distribution 290 * @since 2.2 291 */ 292 public int nextBinomial(int numberOfTrials, double probabilityOfSuccess) { 293 return delegate.nextBinomial(numberOfTrials, probabilityOfSuccess); 294 } 295 296 /** 297 * Generates a random value from the {@link org.apache.commons.math3.distribution.CauchyDistribution Cauchy Distribution}. 298 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 299 * to generate random values. 300 * 301 * @param median the median of the Cauchy distribution 302 * @param scale the scale parameter of the Cauchy distribution 303 * @return random value sampled from the Cauchy(median, scale) distribution 304 * @since 2.2 305 */ 306 public double nextCauchy(double median, double scale) { 307 return delegate.nextCauchy(median, scale); 308 } 309 310 /** 311 * Generates a random value from the {@link org.apache.commons.math3.distribution.ChiSquaredDistribution ChiSquare Distribution}. 312 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 313 * to generate random values. 314 * 315 * @param df the degrees of freedom of the ChiSquare distribution 316 * @return random value sampled from the ChiSquare(df) distribution 317 * @since 2.2 318 */ 319 public double nextChiSquare(double df) { 320 return delegate.nextChiSquare(df); 321 } 322 323 /** 324 * Generates a random value from the {@link org.apache.commons.math3.distribution.FDistribution F Distribution}. 325 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 326 * to generate random values. 327 * 328 * @param numeratorDf the numerator degrees of freedom of the F distribution 329 * @param denominatorDf the denominator degrees of freedom of the F distribution 330 * @return random value sampled from the F(numeratorDf, denominatorDf) distribution 331 * @throws NotStrictlyPositiveException if 332 * {@code numeratorDf <= 0} or {@code denominatorDf <= 0}. 333 * @since 2.2 334 */ 335 public double nextF(double numeratorDf, double denominatorDf) throws NotStrictlyPositiveException { 336 return delegate.nextF(numeratorDf, denominatorDf); 337 } 338 339 /** 340 * <p>Generates a random value from the 341 * {@link org.apache.commons.math3.distribution.GammaDistribution Gamma Distribution}.</p> 342 * 343 * <p>This implementation uses the following algorithms: </p> 344 * 345 * <p>For 0 < shape < 1: <br/> 346 * Ahrens, J. H. and Dieter, U., <i>Computer methods for 347 * sampling from gamma, beta, Poisson and binomial distributions.</i> 348 * Computing, 12, 223-246, 1974.</p> 349 * 350 * <p>For shape >= 1: <br/> 351 * Marsaglia and Tsang, <i>A Simple Method for Generating 352 * Gamma Variables.</i> ACM Transactions on Mathematical Software, 353 * Volume 26 Issue 3, September, 2000.</p> 354 * 355 * @param shape the median of the Gamma distribution 356 * @param scale the scale parameter of the Gamma distribution 357 * @return random value sampled from the Gamma(shape, scale) distribution 358 * @throws NotStrictlyPositiveException if {@code shape <= 0} or 359 * {@code scale <= 0}. 360 * @since 2.2 361 */ 362 public double nextGamma(double shape, double scale) throws NotStrictlyPositiveException { 363 return delegate.nextGamma(shape, scale); 364 } 365 366 /** 367 * Generates a random value from the {@link org.apache.commons.math3.distribution.HypergeometricDistribution Hypergeometric Distribution}. 368 * This implementation uses {@link #nextInversionDeviate(IntegerDistribution) inversion} 369 * to generate random values. 370 * 371 * @param populationSize the population size of the Hypergeometric distribution 372 * @param numberOfSuccesses number of successes in the population of the Hypergeometric distribution 373 * @param sampleSize the sample size of the Hypergeometric distribution 374 * @return random value sampled from the Hypergeometric(numberOfSuccesses, sampleSize) distribution 375 * @throws NumberIsTooLargeException if {@code numberOfSuccesses > populationSize}, 376 * or {@code sampleSize > populationSize}. 377 * @throws NotStrictlyPositiveException if {@code populationSize <= 0}. 378 * @throws NotPositiveException if {@code numberOfSuccesses < 0}. 379 * @since 2.2 380 */ 381 public int nextHypergeometric(int populationSize, int numberOfSuccesses, int sampleSize) 382 throws NotPositiveException, NotStrictlyPositiveException, NumberIsTooLargeException { 383 return delegate.nextHypergeometric(populationSize, numberOfSuccesses, sampleSize); 384 } 385 386 /** 387 * Generates a random value from the {@link org.apache.commons.math3.distribution.PascalDistribution Pascal Distribution}. 388 * This implementation uses {@link #nextInversionDeviate(IntegerDistribution) inversion} 389 * to generate random values. 390 * 391 * @param r the number of successes of the Pascal distribution 392 * @param p the probability of success of the Pascal distribution 393 * @return random value sampled from the Pascal(r, p) distribution 394 * @since 2.2 395 * @throws NotStrictlyPositiveException if the number of successes is not positive 396 * @throws OutOfRangeException if the probability of success is not in the 397 * range {@code [0, 1]}. 398 */ 399 public int nextPascal(int r, double p) 400 throws NotStrictlyPositiveException, OutOfRangeException { 401 return delegate.nextPascal(r, p); 402 } 403 404 /** 405 * Generates a random value from the {@link org.apache.commons.math3.distribution.TDistribution T Distribution}. 406 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 407 * to generate random values. 408 * 409 * @param df the degrees of freedom of the T distribution 410 * @return random value from the T(df) distribution 411 * @since 2.2 412 * @throws NotStrictlyPositiveException if {@code df <= 0} 413 */ 414 public double nextT(double df) throws NotStrictlyPositiveException { 415 return delegate.nextT(df); 416 } 417 418 /** 419 * Generates a random value from the {@link org.apache.commons.math3.distribution.WeibullDistribution Weibull Distribution}. 420 * This implementation uses {@link #nextInversionDeviate(RealDistribution) inversion} 421 * to generate random values. 422 * 423 * @param shape the shape parameter of the Weibull distribution 424 * @param scale the scale parameter of the Weibull distribution 425 * @return random value sampled from the Weibull(shape, size) distribution 426 * @since 2.2 427 * @throws NotStrictlyPositiveException if {@code shape <= 0} or 428 * {@code scale <= 0}. 429 */ 430 public double nextWeibull(double shape, double scale) throws NotStrictlyPositiveException { 431 return delegate.nextWeibull(shape, scale); 432 } 433 434 /** 435 * Generates a random value from the {@link org.apache.commons.math3.distribution.ZipfDistribution Zipf Distribution}. 436 * This implementation uses {@link #nextInversionDeviate(IntegerDistribution) inversion} 437 * to generate random values. 438 * 439 * @param numberOfElements the number of elements of the ZipfDistribution 440 * @param exponent the exponent of the ZipfDistribution 441 * @return random value sampled from the Zipf(numberOfElements, exponent) distribution 442 * @since 2.2 443 * @exception NotStrictlyPositiveException if {@code numberOfElements <= 0} 444 * or {@code exponent <= 0}. 445 */ 446 public int nextZipf(int numberOfElements, double exponent) throws NotStrictlyPositiveException { 447 return delegate.nextZipf(numberOfElements, exponent); 448 } 449 450 451 /** 452 * Reseeds the random number generator with the supplied seed. 453 * <p> 454 * Will create and initialize if null. 455 * </p> 456 * 457 * @param seed 458 * the seed value to use 459 */ 460 public void reSeed(long seed) { 461 delegate.reSeed(seed); 462 } 463 464 /** 465 * Reseeds the secure random number generator with the current time in 466 * milliseconds. 467 * <p> 468 * Will create and initialize if null. 469 * </p> 470 */ 471 public void reSeedSecure() { 472 delegate.reSeedSecure(); 473 } 474 475 /** 476 * Reseeds the secure random number generator with the supplied seed. 477 * <p> 478 * Will create and initialize if null. 479 * </p> 480 * 481 * @param seed 482 * the seed value to use 483 */ 484 public void reSeedSecure(long seed) { 485 delegate.reSeedSecure(seed); 486 } 487 488 /** 489 * Reseeds the random number generator with 490 * {@code System.currentTimeMillis() + System.identityHashCode(this))}. 491 */ 492 public void reSeed() { 493 delegate.reSeed(); 494 } 495 496 /** 497 * Sets the PRNG algorithm for the underlying SecureRandom instance using 498 * the Security Provider API. The Security Provider API is defined in <a 499 * href = 500 * "http://java.sun.com/j2se/1.3/docs/guide/security/CryptoSpec.html#AppA"> 501 * Java Cryptography Architecture API Specification & Reference.</a> 502 * <p> 503 * <strong>USAGE NOTE:</strong> This method carries <i>significant</i> 504 * overhead and may take several seconds to execute. 505 * </p> 506 * 507 * @param algorithm 508 * the name of the PRNG algorithm 509 * @param provider 510 * the name of the provider 511 * @throws NoSuchAlgorithmException 512 * if the specified algorithm is not available 513 * @throws NoSuchProviderException 514 * if the specified provider is not installed 515 */ 516 public void setSecureAlgorithm(String algorithm, String provider) 517 throws NoSuchAlgorithmException, NoSuchProviderException { 518 delegate.setSecureAlgorithm(algorithm, provider); 519 } 520 521 /** 522 * {@inheritDoc} 523 * 524 * <p> 525 * Uses a 2-cycle permutation shuffle. The shuffling process is described <a 526 * href="http://www.maths.abdn.ac.uk/~igc/tch/mx4002/notes/node83.html"> 527 * here</a>. 528 * </p> 529 */ 530 public int[] nextPermutation(int n, int k) 531 throws NotStrictlyPositiveException, NumberIsTooLargeException { 532 return delegate.nextPermutation(n, k); 533 } 534 535 /** 536 * {@inheritDoc} 537 * 538 * <p> 539 * <strong>Algorithm Description</strong>: Uses a 2-cycle permutation 540 * shuffle to generate a random permutation of <code>c.size()</code> and 541 * then returns the elements whose indexes correspond to the elements of the 542 * generated permutation. This technique is described, and proven to 543 * generate random samples <a 544 * href="http://www.maths.abdn.ac.uk/~igc/tch/mx4002/notes/node83.html"> 545 * here</a> 546 * </p> 547 */ 548 public Object[] nextSample(Collection<?> c, int k) 549 throws NotStrictlyPositiveException, NumberIsTooLargeException { 550 return delegate.nextSample(c, k); 551 } 552 553 /** 554 * Generate a random deviate from the given distribution using the 555 * <a href="http://en.wikipedia.org/wiki/Inverse_transform_sampling"> inversion method.</a> 556 * 557 * @param distribution Continuous distribution to generate a random value from 558 * @return a random value sampled from the given distribution 559 * @throws MathIllegalArgumentException if the underlynig distribution throws one 560 * @since 2.2 561 * @deprecated use the distribution's sample() method 562 */ 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 public int nextInversionDeviate(IntegerDistribution distribution) 580 throws MathIllegalArgumentException { 581 return distribution.inverseCumulativeProbability(nextUniform(0, 1)); 582 } 583 584 }