RandomSample with specified random number generator

Jonathan M Davis jmdavisProg at gmx.com
Thu Jun 14 16:32:30 PDT 2012


On Friday, June 15, 2012 01:04:15 Joseph Rushton Wakeling wrote:
> On Thursday, 14 June 2012 at 22:17:44 UTC, Jonathan M Davis wrote:
> > On Thursday, June 14, 2012 23:37:05 jerro wrote:
> >> Issues with copying rngs are not unique to randomSample -
> >> anyone
> >> who uses random number generators will run into them
> >> sooner or later. So the problem is not that randomSample takes
> >> a rng as a parameter - it's that rngs are value types. The
> >> proper solution would be to make them reference types.
> > 
> > Exactly. This has been discussed before (IIRC, there's a bug
> > report which
> > discusses it). The most straightforward solution is to change
> > the random
> > number generator ranges to classes, but that _will_ break code,
> > because
> > they're constructed completely differently.
> 
> I don't think the solution is to pass the RNGs as refs.

I'm not talking about passing them as refs. I'm talking about making them 
reference types. It arguably makes no sense for random number generators to be 
passed around by value. It makes it ludicrously easy to get the same value 
multiple times simply because you passed it around. If you want to guarantee 
that you get the same value multiple times, then you should have to use save.

> I'm not
> familiar with the precise bug report you mention, but the
> reasoning is clear:it's because if you do something like,
> 
> auto getRandomSample(size_t N, size_t n)
> {
> auto rng = Random(unpredictableSeed);
> auto sample = randomSample(iota(0, N), n, rng);
> }
> 
> void main()
> {
> writeln(getRandomSample(100, 5));
> }
> 
> ... then if the RNG were stored in RandomSample by ref rather
> than value, this will fail, because the variable rng will no
> longer exist when the sample is evaluated in main().

I don't believe that the bug report had anything to do with randomSample. It 
had to do with using random number generator ranges in general. The problem is 
that if do something like

auto func(R)(R r)
{
 r.popFront();
 auto value = r.front;
 ///...
}

func(generator);
generator.popFront();
auto value = generator.front;

then both of those values will be the same, because the generator was passed 
by value. You don't have that problem if the generator is a reference type. 
And if you really want the same value twice, then you can use save.

> As far as I can see the only _safe_ option is that randomSample
> must always be passed a uniquely seeded RNG. And if you take
> that line then it's a small step to conclude that you can
> dispense with passing an RNG at all and just pass the seed, with
> the RNG type passed as a template parameter.

You need to be able to pass a random number generator range, because 
otherwise, you can't use any number generator other than the default. But you 
could just reseed the thing at the beginning of randomSample as long as 
isSeedable!R is true if you really want to ensure that it's seeded right 
before randomSample does its thing.

- Jonathan M Davis


More information about the Digitalmars-d mailing list