Hello. Le lun. 29 avr. 2019 à 19:09, Alex Herbert <alex.d.herb...@gmail.com> a écrit : > > On 28/04/2019 19:11, Gilles Sadowski wrote: > > Le dim. 28 avr. 2019 à 17:02, Alex Herbert <alex.d.herb...@gmail.com> a > > écrit : > >> > >> > >>> On 28 Apr 2019, at 00:59, Bernd Eckenfels <e...@zusammenkunft.net> wrote: > >>> > >>> Hello, > >>> > >>> Just a question, I am unclear on the terminology, is „jump“ (did I miss > >>> the discussion leading toot?) something invented here? It sounds to me > >>> like this is a generator where the state can be cloned and it is > >>> „seekable“. It probably makes sense to have those two dimensions > >>> separated anyway. > >> Hi Bernd, thanks for the input. > >> > >> This thread started with the definition: > >> Jump: > >> > >> To create a new instance of the generator that is deterministically based > >> on the state of the current instance but advanced a set number of > >> iterations. > >> > >> > >> However it is not required to create a new instance at the same time as > >> jumping. You are correct in that this is two functionalities: > >> > >> 1. Jump forward in the sequence > >> 2. Copy > >> > >> However the two are coupled. Having jump on its own is useless (why move > >> forward in the sequence without using it?). So a copy needs to be created > >> somewhere before/after the jump. > >> > >> The idea of a jump is to create a series of the generator at different > >> points in the state. The generators can be used for parallel computations > >> and will be ensured to not overlap in their output sequence for number of > >> outputs skipped by the jump length. > >> > >> FYI. The generators that support this have jump sizes of 2^64, 96, 128, > >> 192, 256 and 512. So this is a lot of output sequence to jump. > >> > >> Copy on its own works but for what purpose? If you want a second generator > >> at the moment you just create a new one (with a different seed). Duplicate > >> copies of generators is prone to potential pitfalls where simulations are > >> not as random as you intend. For a special use case where you wish to run > >> multiple simulations with the same generator you can use the Restorable > >> interface to save the state of one and re-create it in other instances. > >> > >> The current thread came to the choice of: > >> > >>>>> So the options are (in all cases returning the copy): > >>>>> > >>>>> 1. createAndJumpCopy > >>>>> 2. copyAndJumpParent > >>>>> 3. jumpParentAndCopy > >>>>> 4. jump and copy separately > >> Jump and copy separately was ruled out to discourage misuse of copy. > >> > >> The current suggestion is 1. Create a copy and jump that ahead. The > >> current instance is not affected. > >> > >> I now consider this to be weaker for a variety of use cases than 2. This > >> copies the current state for use and then jumps the parent ahead. So this > >> alters the state of the parent generator. > >> > >> Note that all other methods of a generator alter its state. So having jump > >> alter its state is reasonable. > >> > >> The most flexible API is to separate jump and copy into two methods. We > >> can still support helper functions that take in a Jumpable generator and > >> create a jump series of generators for parallel work. Separating jump and > >> copy allows the functionality to be used in a larger number of ways than > >> any other interface that attempts to combine jump and copy. > >> > >> I am fine with having separate jump and copy. If so the copy method, being > >> part of the Jumpable interface, will be functionally coupled with the jump > >> method and should be described in Javadoc with the intended purpose to use > >> it to copy the parent state either before or after a jump into a child > >> generator. > >> > >> As a precursor this API is very flexible: > >> > >> JumpableUniformRandomProvider extends UniformRandomProvider { > >> /** Jump and return same instance. */ > >> JumpableUniformRandomProvider jump(); > >> /** Copy the instance. */ > >> JumpableUniformRandomProvider copy(); > >> } > >> > >> Returning the same instance in jump() allows method chaining such as > >> either: > >> > >> rng.jump().copy(); > >> rng.copy().jump(); > >> > >> This potential pitfall is that a user may do this: > >> > >> UniformRandomProvider rng1 = rng.copy().jump(); > >> UniformRandomProvider rng2 = rng.copy().jump(); > >> > >> Where rng1 and 2 will be the same, 1 jump ahead of the parent state. Or: > >> > >> UniformRandomProvider rng1 = rng.jump(); > >> UniformRandomProvider rng2 = rng.jump(); > >> > >> Where rng, rng1 and rng2 are the same instance all 2 jumps ahead of the > >> start point. > >> > >> I think our purpose is to provide an API for the generators that can jump > >> and that is not too restrictive given the use cases we have so far thought > >> up. There may be other ideas of use cases that cannot be done with the > >> coupled functionality of: > >> > >> JumpableUniformRandomProvider extends UniformRandomProvider { > >> /** Copy the instance, then jump ahead. Return the copy of the > >> previous state. */ > >> JumpableUniformRandomProvider jump(); > >> } > >> > >> JumpableUniformRandomProvider extends UniformRandomProvider { > >> /** Copy the instance, then jump the copy ahead. Return the copy. The > >> current instance is not affected. */ > >> JumpableUniformRandomProvider jump(); > >> } > >> > >> So the split functions without allowing method chaining: > >> > >> JumpableUniformRandomProvider extends UniformRandomProvider { > >> /** Jump the current instance ahead. */ > >> void jump(); > >> /** Copy the instance. This is intended to be used either before or > >> after a call to jump() > >> * to create a series of generators. */ > >> JumpableUniformRandomProvider copy(); > >> } > > As you indicated above, there is no advantage in having separate > > "jump()" and "copy()", > > as counter-intuitive it may look at first sight. > > So is the favoured approach now to make the jump method return a copy of > the current state and then increment the state of the current instance > with a jump, as in: > > JumpableUniformRandomProvider extends UniformRandomProvider { > /** Copy the instance, then jump ahead. Return the copy of the previous > state. */ > JumpableUniformRandomProvider jump(); > } > > This would appear to solve more use cases than returning a copy that is > further ahead. For example the dynamic generation of a jump sequence of > an unknown size: > > List<UniformRandomProvider> rngs = ...; > JumpableUniformRandomProvider rng; > for (Data data : Iterable<Data>) { > rngs.add(rng.jump()); > } > // Do something with all the Data and rngs
I confirm agreement. ;-) > I note that if this is the functionality then the jump() method can be > written to return a UniformRandomProvider: > > JumpableUniformRandomProvider extends UniformRandomProvider { > /** Copy the instance, then jump ahead. Return the copy of the previous > state. */ > UniformRandomProvider jump(); > } > > It would not have to be enforced to remove jump functionality from the > copy but should make it clear that the returned object is not to be > jumped again. Yes, but a cast could work around the artificial limitation of the return type, while "restrict" prevents misuse. Gilles > > Alex > > > Regards, > > Gilles > > > >> WDYT? > >> > >> Alex --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org