Repeatable generation of (fake) UUIDs

I need to generate something that would look like a UUID (so that UUID(something) will not error), but depend on some input.

So in the same way this works:

rand(MersenneTwister(0)) == rand(MersenneTwister(0))

I want this to work:

uuid1(MersenneTwister(0)) == uuid1(MersenneTwister(0))

I understand that this behavior defeats the purpose of a UUID, but I need to cheat the system :wink:

Sadly, none of these attempts work:

# I understand why this doesn't work: 
# rand doesn't know which version
# UUID this is supposed to be
rand(MersenneTwister(0), UUID)  

# not sure what the correct format
# for a version 1 UUID is. Apparently
# not this... 
UUID(join([join(rand(['a':'z'; 0:9], n)) for n in ns], '-')) is...

The magic of posting a question here is it always gets answered. Regardless by whom:

function fakeuuid(rng::AbstractRNG)
    ns = [4, 2, 2, 2, 6]
    UUID(join([bytes2hex(rand(rng, UInt8, n)) for n in ns], '-'))
end
fakeuuid(MersenneTwister(0)) == fakeuuid(MersenneTwister(0))
1 Like

You can also use uuid4:

julia> rng = MersenneTwister(0); uuid4(rng)
UUID("bfad144b-f725-4b28-a1be-0e591a3b69ea")

julia> rng = MersenneTwister(0); uuid4(rng)
UUID("bfad144b-f725-4b28-a1be-0e591a3b69ea")
6 Likes

Hmmf, that would be ideal, but it doesn’t work for me?

julia> rng = MersenneTwister(0)
MersenneTwister(UInt32[0x00000000], Random.DSFMT.DSFMT_state(Int32[748398797, 1073523691, -1738140313, 1073664641, -1492392947, 1073490074, -1625281839, 1073254801, 1875112882, 1073717145  …  943540191, 1073626624, 1091647724, 1073372234, -1273625233, -823628301, 835224507, 991807863, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000  …  0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0)

julia> u1 = uuid4(rng) 
UUID("bfad144b-f725-4b28-a1be-0e591a3b69ea")

julia> u2 = uuid4(rng)
UUID("79ed9db9-ec79-46a0-99c5-f638a776ab3c")

julia> u1 == u2
false

Same reason why

julia> rng = MersenneTwister(0);

julia> rand(rng)
0.8236475079774124

julia> rand(rng)
0.9103565379264364

gives you two number. Given the same seed uuid4 produces the same number.

Oh lord. Sorry. Of course … :man_facepalming:

Of course, it is easy to fix some other way:

import Random

struct ConstantRNG{T} <: Random.AbstractRNG
    x::T # it _is_ random. just doesn't change
end

Random.rand(rng::ConstantRNG, ::Type{T}) where T = T(rng.x)

rng = ConstantRNG(1)

then

julia> rand(rng)
1.0

julia> rand(rng)
1.0

:wink: