Userguide (web site). Update following modularization and addition of sampling utilities.
Project: http://git-wip-us.apache.org/repos/asf/commons-rng/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-rng/commit/1af0ab09 Tree: http://git-wip-us.apache.org/repos/asf/commons-rng/tree/1af0ab09 Diff: http://git-wip-us.apache.org/repos/asf/commons-rng/diff/1af0ab09 Branch: refs/heads/master Commit: 1af0ab09d562509a3ab54ffcca1205f7786beaf5 Parents: 4d40f20 Author: Gilles <er...@apache.org> Authored: Sun Nov 20 02:06:29 2016 +0100 Committer: Gilles <er...@apache.org> Committed: Sun Nov 20 02:06:29 2016 +0100 ---------------------------------------------------------------------- src/site/apt/userguide/rng.apt | 201 ++++++++++++++------ src/site/apt/userguide/why_not_java_random.apt | 86 +++++++++ src/site/xdoc/userguide/index.xml | 14 +- 3 files changed, 242 insertions(+), 59 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-rng/blob/1af0ab09/src/site/apt/userguide/rng.apt ---------------------------------------------------------------------- diff --git a/src/site/apt/userguide/rng.apt b/src/site/apt/userguide/rng.apt index 9681b78..eb88e05 100644 --- a/src/site/apt/userguide/rng.apt +++ b/src/site/apt/userguide/rng.apt @@ -19,26 +19,54 @@ The Apache Commons RNG User Guide ----------------------------- -1. Usage overview +1. Purpose - <<<Commons RNG>>> provides generators of random sequences of numbers. - Please refer to the {{{../apidocs/index.html}Javadoc}} for details on - the API illustrated by the following examples. + <<<Commons RNG>>> provides generators of "pseudo-randomness", i.e. the + generators produces deterministic sequences of bytes, currently in chunks + of 32 (a.k.a. <<<int>>) or 64 bits (a.k.a. <<<long>>>), depending on the + implementation. + The goal was to provide an API that is simple and unencumbered with old + design decisions. - * The public API is defined in package <<<org.apache.commons.rng>>>. + The design is clean and its rationale is explained extensively in the code + and Javadoc. + The code evolved during several months in order to accommodate the + requirements gathered from the design issues identified in the + <<<org.apache.commons.math3.random>>> package and the explicit design + goal of {{{./why_not_java_random.html}severing ties}} to <<<java.util.Random>>>. -+--------------------------+ -import org.apache.commons.rng.UniformRandomProvider; -import org.apache.commons.rng.RandomSource; -+--------------------------+ + The library is divided into modules: + + * {{{../commons-rng-client-api/apidocs/org/apache/commons/rng/package-summary.html}Client API}} + + * {{{../commons-rng-core/apidocs/org/apache/commons/rng/core/package-summary.html}Core}} + + * {{{../commons-rng-simple/apidocs/org/apache/commons/rng/simple/package-summary.html}Simple}} + + * {{{../commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/package-summary.html}Sampling}} + + * {{{../commons-rng-jmh/apidocs/org/apache/commons/rng/jmh/package-summary.html}Benchmark}} + + * {{{../commons-rng-examples/apidocs/org/apache/commons/rng/examples/package-summary.html}Examples}} + + [] + + +2. Usage overview + + Please refer to the generated documentation (of the appropriate module) + for details on the API illustrated by the following examples. * Random number generator objects are instantiated through factory methods defined in <<<RandomSource>>>, an <<<enum>>> that declares - {{{../apidocs/org/apache/commons/rng/RandomSource.html#enum.constant.detail}all the available implementations}}. + {{{../commons-rng-simple/apidocs/org/apache/commons/rng/simple/RandomSource.html#enum.constant.detail}all the available implementations}}. +--------------------------+ +import org.apache.commons.rng.UniformRandomProvider; +import org.apache.commons.rng.simple.RandomSource; + UniformRandomProvider rng = RandomSource.create(RandomSource.MT); +--------------------------+ @@ -155,7 +183,7 @@ if (!RandomSource.TWO_CMRES.isNativeSeed(seed)) { +--------------------------+ For each available implementation, the native seed type is specified in the - {{{../apidocs/org/apache/commons/rng/RandomSource.html#enum.constant.detail}Javadoc}}. + {{{../commons-rng-simple/apidocs/org/apache/commons/rng/simple/RandomSource.html#enum.constant.detail}Javadoc}}. * Whenever a random source implementation is parameterized, the custom arguments @@ -172,9 +200,9 @@ UniformRandomProvider rng = RandomSource.create(RandomSource.TWO_CMRES_SELECT, s * The current state of a generator can be - {{{../apidocs/org/apache/commons/rng/RestorableUniformRandomProvider.html#saveState}saved}} + {{{../commons-rng-client-api/apidocs/org/apache/commons/rng/RestorableUniformRandomProvider.html#saveState--}saved}} and - {{{../apidocs/org/apache/commons/rng/RestorableUniformRandomProvider.html#restoreState-org.apache.commons.rng.RandomProviderState-}restored}} + {{{../commons-rng-client-api/apidocs/org/apache/commons/rng/RestorableUniformRandomProvider.html#restoreState-org.apache.commons.rng.RandomProviderState-}restored}} later on. +--------------------------+ @@ -198,6 +226,10 @@ double y = rng.nextDouble(); // x == y. such that the sequence will continue from where it left off. +--------------------------+ +import org.apache.commons.rng.RestorableUniformRandomProvider; +import org.apache.commons.rng.simple.RandomSource; +import org.apache.commons.rng.core.RandomProviderDefaultState; + RandomSource source = RandomSource.MT_64; // Known source identifier. RestorableUniformRandomProvider rngOrig = RandomSource.create(source); // Original RNG instance. @@ -206,12 +238,12 @@ RestorableUniformRandomProvider rngOrig = RandomSource.create(source); // Origin RandomProviderState stateOrig = rngOrig.saveState(rngOrig); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); -oos.writeObject(((RandomSource.State) stateOrig).getState()); +oos.writeObject(((RandomProviderDefaultState) stateOrig).getState()); // Deserialize state. ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); -RandomProviderState stateNew = new RandomSource.State((byte[]) ois.readObject()); +RandomProviderState stateNew = new RandomProviderDefaultState((byte[]) ois.readObject()); RestorableUniformRandomProvider rngNew = RandomSource.create(source); // New RNG instance from the same "source". @@ -220,62 +252,121 @@ rngNew.restoreState(stateNew); +--------------------------+ + * Generation of random deviates for various distributions. + ++--------------------------+ +import org.apache.commons.rng.sampling.distribution.ContinuousSampler; +import org.apache.commons.rng.sampling.distribution.BoxMullerGaussianSampler; + +ContinuousSampler sampler = new BoxMullerGaussianSampler(RandomSource.create(RandomSource.MT_64), + 45.6, 2.3); +double random = sampler.sample(); ++--------------------------+ + ++--------------------------+ +import org.apache.commons.rng.sampling.distribution.DiscreteSampler; +import org.apache.commons.rng.sampling.distribution.RejectionInversionZipfSampler; + +DiscreteSampler sampler = new RejectionInversionZipfSampler(RandomSource.create(RandomSource.ISAAC), + 5, 1.2); +int random = sampler.sample(); ++--------------------------+ + + * Permutation, sampling from a <<<Collection>>> and shuffling utilities. + ++--------------------------+ +import org.apache.commons.rng.sampling.PermutationSampler; + +PermutationSampler sampler = new PermutationSampler(RandomSource.create(RandomSource.KISS), + 6, 3); + +// 3 elements from a shuffling of the (0, 1, 2, 3, 4, 5) tuplet. +int[] random = sampler.sample(); ++--------------------------+ + ++--------------------------+ +import java.util.ArrayList; +import org.apache.commons.rng.sampling.CollectionSampler; + +ArrayList<String> list = new ArrayList<>(); +list.add("Apache") +list.add("Commons"); +list.add("RNG"); + +CollectionSampler sampler = new CollectionSampler(RandomSource.create(RandomSource.MWC_256), + list, 1); +String word = sampler.sample().get(0); ++--------------------------+ + [] -2. Library layout +3. Library layout - The library's public API consists of classes and interfaces defined in package - <<<org.apache.commons.rng>>>. + The API for client code consists of classes and interfaces defined in package + {{{../commons-rng-client-api/apidocs/org/apache/commons/rng/package-summary.html}org.apache.commons.rng}}. * Interface <<<UniformRandomProvider>>> provides access to a sequence of random values uniformly distributed within some range. - * Enum <<<RandomSource>>> determines which algorithm to use for generating the - sequence of random values. - * Interfaces <<<RestorableUniformRandomProvider>>> and <<<RandomProviderState>>> provide the "save/restore" API. - * Class <<<RandomSource.State>>> implements the <<<RandomProviderState>>> - interface to enable "save/restore" for all <<<RestorableUniformRandomProvider>>> - instances created through the <<<RandomSource>>> factory methods. - [] - The <<<org.apache.commons.rng.internal>>> package and packages below it - contain classes for supporting the above API. - None of those classes should be used directly in applications. - The rest of this section briefly describes the internal classes. - More information is available in the {{{../apidocs/index.html}Javadoc}}. + The API for instantiating generators is defined in package + {{{../commons-rng-simple/apidocs/org/apache/commons/rng/simple/package-summary.html}org.apache.commons.rng.simple}}. + + * Enum <<<RandomSource>>> determines which algorithm to use for generating the + sequence of random values. + + [] + + The <<<org.apache.commons.rng.simple.internal>>> package contain classes + for supporting initialization (a.k.a. "seeding") of the generators. + They must not be used directly in applications, as all the necessary utilities + are accessible through methods defined in <<<RandomSource>>>. * <<<ProviderBuilder>>>: contains methods for instantiating the concrete RNG implementations based on the source identifier; it also takes care of calling the appropriate classes for seed type conversion. + * <<<SeedFactory>>>: contains factory methods for generating random seeds. + + * <<<SeedConverter>>>: interface for classes that transform between + supported seed types. + + * Various classes that implement <<<SeedConverter>>> in order to transform + from caller's seed to "native" seed. + + [] + + + The {{{../commons-rng-core/apidocs/org/apache/commons/rng/core/package-summary.html}org.apache.commons.rng.core}}. + package contain the implementation of the algorithms for the generation of + pseudo-random sequences. + Applications should not directly import or use classes defined in this package: + all generators can be instantiated through the <<<RandomSource>>> factory. + + * Class <<<RandomProviderDefaultState>>> implements the <<<RandomProviderState>>> + interface to enable "save/restore" for all <<<RestorableUniformRandomProvider>>> + instances created through the <<<RandomSource>>> factory methods. + * <<<BaseProvider>>>: base class for all concrete RNG implementations; it contains higher-level algorithms <<<nextInt(int n)>>> and <<<nextLong(long n)>>> common to all implementations. - * <<<org.apache.commons.rng.internal.util>>> + * <<<org.apache.commons.rng.core.util>>> ** <<<NumberFactory>>>: contains utilities for interpreting and combining the output (<<<int>>> or <<<long>>>) of the underlying source of randomness into the requested output, i.e. one of the Java primitive types supported by <<<UniformRandomProvider>>>. - ** <<<SeedFactory>>>: contains factory methods for generating random seeds. - - ** <<<SeedConverter>>>: interface for classes that transform between - supported seed types. - - ** Various classes that implement <<<SeedConverter>>> in order to transform - from caller's seed to "native" seed. - [] - * <<<org.apache.commons.rng.internal.source32>>> + * <<<org.apache.commons.rng.core.source32>>> ** <<<RandomIntSource>>>: describes an algorithm that generates randomness in 32-bits chunks (a.k.a Java <<<int>>>). @@ -286,7 +377,7 @@ rngNew.restoreState(stateNew); [] - * <<<org.apache.commons.rng.internal.source64>>> + * <<<org.apache.commons.rng.core.source64>>> ** <<<RandomLongSource>>>: describes an algorithm that generates randomness in 64-bits chunks (a.k.a Java <<<long>>>). @@ -300,9 +391,12 @@ rngNew.restoreState(stateNew); [] -3. Performance +4. Performance + + This section reports + {{{../commons-rng-jmh/apidocs/org/apache/commons/rng/jmh/package-summary.html}performance benchmarks}} + of the RNG implementations. - This section reports benchmarks of the RNG implementations. All runs were performed on a platform with the following characteristics: * CPU: Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz @@ -324,12 +418,9 @@ rngNew.restoreState(stateNew); [] - The benchmark code is available in the "src/test" part of the source - code repository (in class <<<GenerationTestPerformance>>>). - The first column is the RNG identifier (see {{{../apidocs/org/apache/commons/rng/RandomSource.html}RandomSource}}); - the performance value is the ratio of the (JMH) score with respect - to the score of <<<RandomSource.JDK>>>. + The first column is the RNG identifier (see {{{../commons-rng-simple/apidocs/org/apache/commons/rng/simple/RandomSource.html}RandomSource}}); + the performance value is the ratio of the (JMH) score with respect to the score of <<<RandomSource.JDK>>>. In these tables, <lower> is <better>. @@ -446,10 +537,12 @@ rngNew.restoreState(stateNew); -4. Quality +5. Quality - This section reports results of performing "stress tests" that aim at detecting failures - of an implementation to produce sequences of numbers that follow a uniform distribution. + This section reports results of + {{{../commons-rng-examples/apidocs/org/apache/commons/rng/examples/stress/package-summary.html}performing "stress tests"}} + that aim at detecting failures of an implementation to produce sequences of numbers + that follow a uniform distribution. Two different test suites were used: @@ -459,7 +552,7 @@ rngNew.restoreState(stateNew); [] - The first column is the RNG identifier (see {{{../apidocs/org/apache/commons/rng/RandomSource.html}RandomSource}}). + The first column is the RNG identifier (see {{{../commons-rng-simple/apidocs/org/apache/commons/rng/simple/RandomSource.html}RandomSource}}). The second and third columns contain the number of tests which <Dieharder> and <TestU01> respectively reported as below the accepted threshold for considering the sequence as uniformly random; hence, in this table, <lower> is <better>. @@ -479,7 +572,7 @@ rngNew.restoreState(stateNew); *---------------------------------*----------------*----------------* | WELL_512_A | {{{../txt/userguide/stress/dh/run_1/dh_3}0}}, {{{../txt/userguide/stress/dh/run_2/dh_3}0}}, {{{../txt/userguide/stress/dh/run_3/dh_3}0}} | {{{../txt/userguide/stress/tu/run_1/tu_3}6}}, {{{../txt/userguide/stress/tu/run_2/tu_3}6}}, {{{../txt/userguide/stress/tu/run_3/tu_3}6}} | *---------------------------------*----------------*----------------* -| WELL_1024_A | {{{../txt/userguide/stress/dh/run_1/dh_4}0}}, {{{../txt/userguide/stress/dh/run_2/dh_4}0}} , {{{../txt/userguide/stress/dh/run_3/dh_4}1}}| {{{../txt/userguide/stress/tu/run_1/tu_4}4}}, {{{../txt/userguide/stress/tu/run_2/tu_4}6}}, {{{../txt/userguide/stress/tu/run_3/tu_4}5}} | +| WELL_1024_A | {{{../txt/userguide/stress/dh/run_1/dh_4}0}}, {{{../txt/userguide/stress/dh/run_2/dh_4}0}}, {{{../txt/userguide/stress/dh/run_3/dh_4}1}}| {{{../txt/userguide/stress/tu/run_1/tu_4}4}}, {{{../txt/userguide/stress/tu/run_2/tu_4}6}}, {{{../txt/userguide/stress/tu/run_3/tu_4}5}} | *---------------------------------*----------------*----------------* | WELL_19937_A | {{{../txt/userguide/stress/dh/run_1/dh_5}0}}, {{{../txt/userguide/stress/dh/run_2/dh_5}0}}, {{{../txt/userguide/stress/dh/run_3/dh_5}0}} | {{{../txt/userguide/stress/tu/run_1/tu_5}2}}, {{{../txt/userguide/stress/tu/run_2/tu_5}3}}, {{{../txt/userguide/stress/tu/run_3/tu_5}4}} | *---------------------------------*----------------*----------------* @@ -505,6 +598,6 @@ rngNew.restoreState(stateNew); *---------------------------------*----------------*----------------* -5. Dependencies +6. Dependencies Apache Commons RNG requires JDK 1.6+ and has no runtime dependencies. http://git-wip-us.apache.org/repos/asf/commons-rng/blob/1af0ab09/src/site/apt/userguide/why_not_java_random.apt ---------------------------------------------------------------------- diff --git a/src/site/apt/userguide/why_not_java_random.apt b/src/site/apt/userguide/why_not_java_random.apt new file mode 100644 index 0000000..5f2b190 --- /dev/null +++ b/src/site/apt/userguide/why_not_java_random.apt @@ -0,0 +1,86 @@ +~~ +~~ Licensed to the Apache Software Foundation (ASF) under one or more +~~ contributor license agreements. See the NOTICE file distributed with +~~ this work for additional information regarding copyright ownership. +~~ The ASF licenses this file to You under the Apache License, Version 2.0 +~~ (the "License"); you may not use this file except in compliance with +~~ the License. You may obtain a copy of the License at +~~ +~~ http://www.apache.org/licenses/LICENSE-2.0 +~~ +~~ Unless required by applicable law or agreed to in writing, software +~~ distributed under the License is distributed on an "AS IS" BASIS, +~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +~~ See the License for the specific language governing permissions and +~~ limitations under the License. +~~ + + ----------------------------- + Why not <<<java.util.Random>>> ? + ----------------------------- + +The "Apache Commons RNG" project started off from code originally in the +"Apache Commons Math" project; there, the code in package +{{{http://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/random/package-summary.html}org.apache.commons.math3.random}} +had its design prominently based on the JDK's +{{{https://docs.oracle.com/javase/7/docs/api/java/util/Random.html}Random}} +class. + +Although it is often a good idea to rely on the language's standard library, +sometimes it is not. +And, in this case, there are numerous reasons for avoiding <<<java.util.Random>>>. + +1. The {{{https://en.wikipedia.org/wiki/Linear_congruential_generator}LCG}} + algorithm used by <<<java.util.Random>>> + + * has a serious {{{http://www.ics.uci.edu/~fowlkes/class/cs177/marsaglia.pdf}defect}}, and + + * is not as efficient as some of the alternatives that do not suffer from this problem. + + [] + + +2. Although the {{{https://docs.oracle.com/javase/7/docs/api/java/util/Random.html#next(int)}next}} + method seems to imply that it is designed for inheritance, it is not quite so: + + * {{{https://docs.oracle.com/javase/7/docs/api/java/util/Random.html#setSeed(long)}setSeed}} + is tied to the assumption that the state of the generator is entirely + defined by a single <<<long>>> value. + + * {{{https://docs.oracle.com/javase/7/docs/api/java/util/Random.html#next(int)}next}} + implies that an implementation must produce a 32-bits value. + + * <<<Random>>> is {{{http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html}Serializable}} + and thus imposes it on subclasses even though the issue of persistent + storage is application-dependent. + + [] + + + As a side note, the newer + {{{https://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html}SplittableRandom}} + + * is <<<final>>> (hence, there is no temptation to mistake it as an interface), and + + * does not inherit from <<<Random>>> (which is a clear hint that the + JDK's developers themselves do not consider <<<Random>>> as the + best option for new code). + + [] + + +3. Thus, <<<java.util.Random>>> _should_ have been an implementation of a + more general interface (without a <<<setSeed>>> method that is bound to + be implementation-specific, or a {{{https://docs.oracle.com/javase/7/docs/api/java/util/Random.html#nextGaussian()}nextGaussian}} + that singles out just one of many types of random deviates). + + +4. As a concrete class, <<<java.util.Random>>> contains code tied to + "implementation details"; it is hard to modify it without changing + long-established behaviour, even if it would be to fix a + {{{https://bugs.openjdk.java.net/browse/JDK-8154225}bug}}. + + +5. Methods are <<<synchronized>>>, incurring an unnecessary performance + impact for single-threaded applications, while multi-threaded ones will + be subject to contention. http://git-wip-us.apache.org/repos/asf/commons-rng/blob/1af0ab09/src/site/xdoc/userguide/index.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/userguide/index.xml b/src/site/xdoc/userguide/index.xml index fce9a60..027abbb 100644 --- a/src/site/xdoc/userguide/index.xml +++ b/src/site/xdoc/userguide/index.xml @@ -29,23 +29,27 @@ <ul> <li> - <a href="rng.html#a1._Usage_overview"> + <a href="rng.html#a1._Purpose"> 1. Usage overview (for users)</a> </li> <li> - <a href="rng.html#a2._Library_layout"> + <a href="rng.html#a2._Usage_overview"> + 1. Usage overview (for users)</a> + </li> + <li> + <a href="rng.html#a3._Library_layout"> 2. Library layout (for developers)</a> </li> <li> - <a href="rng.html#a3._Performance"> + <a href="rng.html#a4._Performance"> 3. Performance</a> </li> <li> - <a href="rng.html#a4._Quality"> + <a href="rng.html#a5._Quality"> 4. Quality</a> </li> <li> - <a href="rng.html#a5._Dependencies"> + <a href="rng.html#a6._Dependencies"> 5. Dependencies</a> </li> </ul>