Last active
March 30, 2020 09:13
-
-
Save SebastienEske/1f6a280caa2b348a25210a0de303d8f2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
class CMWC(random.Random): | |
# code from here https://code.activestate.com/recipes/576707/ | |
'Long period random number generator: Complementary Multiply with Carry' | |
# http://en.wikipedia.org/wiki/Multiply-with-carry | |
a = 3636507990 | |
logb = 32 | |
b = 2 ** logb | |
r = 1359 | |
def _gen_word(self): | |
i = self.i | |
xc, self.c = divmod(self.a * self.Q[i] + self.c, self.b) | |
x = self.Q[i] = self.b - 1 - xc | |
self.i = 0 if i + 1 == self.r else i + 1 | |
return x | |
def getrandbits(self, k): | |
while self.bits < k: | |
self.f = (self.f << self.logb) | self._gen_word() | |
self.bits += self.logb | |
x = self.f & ((1 << k) - 1) | |
self.f >>= k | |
self.bits -= k | |
return x | |
def random(self, RECIP_BPF=random.RECIP_BPF, BPF=random.BPF): | |
return self.getrandbits(BPF) * RECIP_BPF | |
def seed(self, seed=None): | |
seeder = random.Random(seed) | |
Q = [seeder.randrange(0x100000000) for i in range(self.r)] | |
c = seeder.randrange(0x100000000) | |
self.setstate(0, 0, 0, c, Q) | |
def getstate(self): | |
return self.f, self.bits, self.i, self.c, tuple(self.Q) | |
def setstate(self, f, bits, i, c, Q): | |
self.f, self.bits, self.i, self.c, self.Q = f, bits, i, c, list(Q) | |
class myrandomtransform(): | |
def __init__(self, seed=None): | |
self.rng = CMWC() | |
if seed is not None: | |
self.rng.seed(seed) | |
def run(self): | |
return self.rng.random() | |
a = myrandomtransform(2) | |
b = myrandomtransform(2) | |
avalues = [] | |
bvalues = [] | |
for i in range(10): | |
if random.random() > 0.5: | |
avalues.append(a.run()) | |
else: | |
bvalues.append(b.run()) | |
print(avalues) | |
print(bvalues) |
Hello,
Yes and no. :-) The point here is to control the random number generator (RNG) to prevent:
- non deterministic behavior due to low level routines, other implementation hidden issues
- change of behavior between different RNG versions
I was intending to use it to comment on this issue but somehow I did not (can't remember why): pytorch/vision#1234
So it is not trying to be super random, just enough for testing purposes (as long as the testing does not require high quality randomness) while guaranteeing reproducibility of the randomness which is paramount for testing.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Why so complicated?
should do the same thing, no?