commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Gilles <gil...@harfang.homelinux.org>
Subject [Math] Setting the state of RNGs (a.k.a. seeding)
Date Mon, 11 Jan 2016 02:09:58 GMT
Hi.

This post is related to:
   https://issues.apache.org/jira/browse/MATH-1314

Problem:
Different RNGs have different ways to manage their internal state
(which is updated at each call to the "next()" function).
Some use one, or two, "int" (or "long") values, or arrays (of
varying sizes).

This leads to many signatures for setting that state:
  setSeed(int)
  setSeed(long)
  setSeed(int[])
  setSeed(long[])

Some families of RNGs could even allow to switch to another member
of that family by resetting yet other data that make up the state.

So this adds up in such a way that it is either incorrect or misleading
to assume that the API advertised by a single interface can represent
all the situations.
A trivial example is an RNG that must implement "setSeed(int[])" (since
it is part of the "RandomGenerator" interface), but only uses a single
"int" to set its state; it will thus probably simply discard all array
elements except the first.
At the opposite, an RNG that has a complex state (say, an array of N
"long" values) will need to provide a procedure to create this array
from the single value that is passed when calling e.g. "setSeed(int)".

I think that it would be more appropriate to advertise the seeding
procedure(s) in separate interfaces, e.g.:

public interface LongSeedable {
   void setSeed(long seed);
}

public interface IntArraySeedable {
   void setSeed(int[] seed)
}

Hence RNGs that can indeed initialize, in a "complete" way, their
state from various input types would implement each of the
corresponding interfaces.

Apart from that, we could provide wrappers that allow to call a
non-"natively" implemented "setSeed" method (where the transformation
from, say, "long" to "int[]" is performed by an external procedure):

public interface Long2IntArrayTransformer {
   int[] toIntArray(long seed);
}

public class SeedableFactory {
   public LongSeedable makeLongSeedable(final IntArraySeedable rng,
                                        final Long2IntArrayTransformer 
c) {
     return new LongSeedable() {
       public void setSeed(long seed) {
         rng.setSeed(c.toIntArray(seed));
       }
     };
   }

   // And similarly for other conversions.
}

In user code:

// Constructor initializes "native" state.
Well1024a rng = new Well1024a(new int[] { 11, 29 });

// Call nextDouble(), nextInt(), etc.

// Reseed "natively".
rng.setSeed(new int[] { 17, 43 });

// Call nextDouble(), nextInt(), etc.

// Reseed using non-"native" method "setSeed(long)" (assuming that 
"Well1024a"
// implements "IntArraySeedable" but not "LongSeedable").
// Assuming that "WellSeedTransformer" implements 
"Long2IntArrayTransformer".
SeedableFactory.makeLongSeedable(rng, new 
WellSeedTransformer()).setSeed(1234567810111213L);

// Call nextDouble(), nextInt(), etc.

In summary, the "SeedableFactory" methods could create uniform
"views" of dissimilar RNGs, and would allow users to select
a state initialization algorithm independently of the RNG
algorithm.

Gilles


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message