> On 27 Apr 2019, at 14:49, Gilles Sadowski <[email protected]> wrote:
>
> Hi.
>
> Le sam. 27 avr. 2019 à 15:05, Alex Herbert <[email protected]
> <mailto:[email protected]>> a écrit :
>>
>> I have created RNG-97 and RNG-98 for Jump and LongJump.
>>
>> Please take a look and comment.
>>
>> The documentation highlights the implementation detail that a jump or long
>> jump creates a copy that is far ahead. The original generator is not
>> effected.
>>
>> The use case is thus:
>>
>> rng1 = …;
>> rng2 = rng1.jump();
>> rng3 = rng2.jump();
>> rng4 = rng3.jump();
>>
>> As opposed to:
>>
>> rng1 = …;
>> rng2 = rng1.jump();
>> rng3 = rng1.jump();
>> rng4 = rng1.jump();
>>
>> Where rng1 will be advanced each time leaving behind a copy generator.
>>
>> In either case it will be an overlap problem if any of the children are then
>> used for jumping. So as long as the documentation is clear then this is OK.
>> The helper method to create a jump series (or long jump series) in
>> RandomSource seems the best way to avoid incorrect usage.
>
> +1
>
> I think that the default should be to prevent a "jump" on the returned
> instances.
> An overload could be defined with a parameter (e.g. "allowFurtherJump") but
> I'd
> leave it out until it is requested based on an actual use-case.
I presume you are talking about the helper method in RandomSource.
However it does open the possibility instead of this:
JumpableUniformRandomProvider {
UniformRandomProvider jump();
}
This only works if the state is modified for the current instance to allow
chaining jumps.
Having typed all this up into a summary for the two tickets I feel that they
implement the idea in the wrong way. I think the jump should advance the state
of the current generator. This is the master generator created and used in the
high level code that controls the number of jumps that are required. The
returned copy should be a copy of where the generator was. The copy should not
be used for further jumps. In this way the interface for jump could be made to
return a UniformRandomProvider.
When done like that the jumpable RNG is the only thing you need to hold a
reference to. And you can later decide (perhaps dynamically) if you need to do
some more jumps to get another series. Each call to jump moves the master along
and leaves behind a RNG that can be used for a set number of cycles (the jump
length). So you can do:
JumpableUniformRandomProvider rng = …;
UniformRandomProvider[] series1 = RandomSource.createJumpSeries(rng);
// Do work with series1 and then maybe
UniformRandomProvider[] series2 = RandomSource.createJumpSeries(rng);
// Do work with series2, etc
UniformRandomProvider[] series3 = RandomSource.createJumpSeries(rng);
Or
JumpableUniformRandomProvider masterRng = …;
ExecutorService executor = Executors.newCachedThreadPool();
ArrayList<Future<Result>> futures = new ArrayList<>();
for (Input input : inputs) {
final UniformRandomProvider rng = masterRng.jump();
futures.add(executor.submit(new Callable<Result>() {
// Do something random with rng, then
return new Result(...);
}));
}
The later example uses ‘inputs’ as something where perhaps the size is not
known such as an Iterable or likewise in Java 8 it could be written to consume
a Stream.
Similarly the LongJumpableUniformRandomProvider interface can return a
JumpableUniformRandomProvider so preventing the result from being used for
another long jump but it can be used for (short) jumps.
Have a think on use cases but my feeling is that the interface is more powerful
if you do advance the state and leave copies behind, rather than creating
future copies which must be chained together to create a series.
Alex
>
> Best,
> Gilles
>
>>
>> Alex
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> <mailto:[email protected]>
> For additional commands, e-mail: [email protected]
> <mailto:[email protected]>