Random Object Generation

Pseudo-random quantities are used in several Magma algorithms, and may also be generated explicitly by some intrinsics. Throughout the Handbook, the word `random' is used for `pseudo-random'.

Since V2.7 (June 2000), Magma contains an implementation of the Monster random number generator of G. Marsaglia [Mar00]. The period of this generator is 229430 - 227382 (approximately 108859), and passes all of the stringent tests in Marsaglia's Diehard test suite [Mar95]. Since V2.13 (July 2006), this generator is combined with the MD5 hash function to produce a higher-quality result.

Because the generator uses an internal array of machine integers, one `seed' variable does not express the whole state, so the method for setting or getting the generator state is by way of a pair of values: (1) the seed for initializing the array, and (2) the number of steps performed since the initialization.

SetSeed(s, c) : RngIntElt, RngIntElt ->
SetSeed(s) : RngIntElt ->
(Procedure.) Reset the random number generator to have initial seed s (0 ≤s < 232), and advance to step c (0 ≤c < 264). If c is not given, it is taken to be 0. Passing -Sn to Magma at startup is equivalent to typing SetSeed(n); after startup.

GetSeed() : -> RngIntElt, RngIntElt
Return the initial seed s used to initialize the random-number generator and also the current step c. This is the complement to the SetSeed function.
Random(S) : Str -> Elt
Given a finite set or structure S, return a random element of S.
Random(a, b) : RngIntElt, RngIntElt -> RngIntElt
Return a random integer lying in the interval [a, b], where a≤b.

Random(b) : RngIntElt -> RngIntElt
Return a random integer lying in the interval [0, b], where b is a non-negative integer. Because of the good properties of the underlying Monster generator, calling Random(1) is a good safe way to produce a sequence of random bits.

Example State_IsIntrinsic (H1E23)

We demonstrate how one can return to a previous random state by the use of GetSeed and SetSeed. We begin with initial seed 1 at step 0 and create a multi-set of 100,000 random integers in the range [1..4].
> SetSeed(1);
> GetSeed();
1 0
> time S := {* Random(1, 4): i in [1..100000] *};
Time: 0.490
> S;
{* 1^^24911, 2^^24893, 3^^25139, 4^^25057 *}
We note the current state by GetSeed, and then print 10 random integers in the range [1..100].
> GetSeed();
1 100000
> [Random(1, 100): i in [1 .. 10]];
[ 85, 41, 43, 69, 66, 61, 63, 31, 84, 11 ]
> GetSeed();
1 100014
We now restart with a different initial seed 23 (again at step 0), and do the same as before, noting the different random integers produced.
> SetSeed(23);
> GetSeed();
23 0
> time S := {* Random(1, 4): i in [1..100000] *};
Time: 0.500
> S;
{* 1^^24962, 2^^24923, 3^^24948, 4^^25167 *}
> GetSeed();
23 100000
> [Random(1, 100): i in [1 .. 10]];
[ 3, 93, 11, 62, 6, 73, 46, 52, 100, 30 ]
> GetSeed();
23 100013
Finally, we restore the random generator state to what it was after the creation of the multi-set for the first seed. We then print the 10 random integers in the range [1..100], and note that they are the same as before.
> SetSeed(1, 100000);
> [Random(1, 100): i in [1 .. 10]];
[ 85, 41, 43, 69, 66, 61, 63, 31, 84, 11 ]
> GetSeed();
1 100014
V2.28, 13 July 2023