Splittable, serializable pseudorandom number generation in Scala.
The SpRandom package produces random numbers that are reproducible in a multi-threaded context. It also allows the random state to be serialized and deserialized.
SpRandom's Random
class is built on top of the java.util.SplittableRandom
class.
It exposes the following features:
- A
zip
method that facilitates reproducibility in a multi-threaded context - Serializability by persisting the underlying seed (SplittableRandom is not serializable)
- Multiple, convenient ways to instantiate a random state
- A variety of convenience methods to generate pseudorandom outcomes
A Random
object can be instantiated from an integer seed, a long seed, or another Random
object.
import io.citrine.random.Random
val rng = Random(17L)
val rng2 = rng.split() // an independent stream
val uniformRandom = rng.between(1.5, 2.5) // draw from a uniform distribution between 1.5 and 2.5
val normalRandom = rng.nextGaussian(mean = 5.0, stdDev = 0.1) // draw from a normal with mean 5.0 and standard deviation 0.1
val orderedVector = (1 to 10).toVector
val shuffledVector = rng.shuffle(orderedVector) // random permutation of the range (1 to 10)
To get reproducible results in a multi-threaded context, use .zip
.
Imagine that we have some sequence, items
, that we want to process in parallel.
Processing is done by the stochastic, reproducible method heavyStochasticComputation
.
The following call is then reproducible.
rng.zip(items).par.map { case (thisRng, item) => heavyStochasticComputation(item, thisRng) }