Need to seed a random number generator

I am exploring different metaheuristics, and I need to fix the seed for random number generation.

I used let mut rng = StdRng::seed_from_u64(seed), but my problem is when I pass around this var through different functions, because all of random methods I use need to have a mut reference to rng, thus I need to clone in some steps rng.

And when I clone, the random sequence rng produces it's repeated. I show a toy example:

let seed: u64 = 10;
let iterations = 10;
println!("Seed fixed to {}, printing {} values", seed, iterations);
let mut rng = StdRng::seed_from_u64(seed);

for _ in 0..iterations{
    let rand_value = rng.gen_range(0..1000);
    println!("Random value: {}", rand_value);
}
println!("");



println!("Original generator is cloned");
let mut other_rng = rng.clone();

for _ in 0..iterations{
    let rand_value = other_rng.gen_range(0..1000);
    println!("Random value: {}", rand_value);
}
println!("");

println!("Original generator is cloned (not the second generator)");
let mut yet_another_rng = rng.clone();
for _ in 0..iterations{
    let rand_value = yet_another_rng.gen_range(0..1000);
    println!("Random value: {}", rand_value);
}

Which outputs:
Seed fixed to 10, printing 10 values
Random value: 386
Random value: 130
Random value: 336
Random value: 182
Random value: 624
Random value: 356
Random value: 773
Random value: 110
Random value: 783
Random value: 485

Original generator is cloned
Random value: 693
Random value: 538
Random value: 242
Random value: 121
Random value: 258
Random value: 991
Random value: 633
Random value: 701
Random value: 831
Random value: 90

Original generator is cloned (not the second generator)
Random value: 693
Random value: 538
Random value: 242
Random value: 121
Random value: 258
Random value: 991
Random value: 633
Random value: 701
Random value: 831
Random value: 90

So is clear that second and third random sequence are the same because we are cloning the same original rng. I would like to have a mechanism to "clone" or wathever and change that state, not produce the exact same sequence. Something like we do in C/C++ at the start of main function
Any idea of how can I pass rng through different functions?

Why don't you just pass around a mutable reference to the RNG, then? Why do you think you need to clone it?

1 Like

I would consider rethinking how you are passing it around so you don't clone at all, but if that doesn't work, you can always wrap it in an Arc/Rc with Mutex and clone that instead.

1 Like

Clone is not the right tool for sharing mutable state. You can try any of these options:

  • Arc<Mutex<T>> to share mutable access amongst multiple threads of execution (including multiple frames on a single stack ... but beware of reentrancy).
  • std::sync::mpsc channels to centralize a single worker thread responsible for managing PRNG state and asynchronously responding to messages requesting the next value.

These are just the building blocks for more powerful abstractions like actors. An actor framework may reduce cognitive overhead with the channel implementation.

And what if I need to pass to two functions?

Lets say:
let mut rng = StdRng::seed_from_u64(seed);

some_function(...., &mut rng);
some_other_function(..., &mut rng);

If you don't want to pass the Rng around explicitly, you can put it in a global variable, for example a RefCell<StdRng> in a thread_local!.

This is basically how the rand::thread_rng function is implemented, though it also uses some unsafe code to avoid the overhead of RefCell.

It depends what you do in those functions. If you don't store the mutable reference in the first one, you can still just pass it to the second one as well.

Don't be confused by &mut. The lifetimes in your example are temporary, living only as long as some_function, for instance.

Playground

It is possible to extend the lifetime, which would be problematic. Just don't do that. :wink:

That's perfectly fine as long as those functions are not stuffing the reference into a struct somewhere. If they are, then use one of the other techniques mentioned already.