From c3cd051095e25822f2859aeb663e995d1bfc9c7f Mon Sep 17 00:00:00 2001 From: Enzo De Carvalho Bittencourt <enzo.decarvalhobittencourt@ensiie.eu> Date: Fri, 22 Sep 2023 17:23:56 +0200 Subject: [PATCH] added RNG + creating plots --- Random/.generators.py.swp | Bin 12288 -> 0 bytes Random/__pycache__/generators.cpython-36.pyc | Bin 0 -> 7548 bytes Random/generators.py | 165 ++++++++++++++++++- Random/graph.py | 0 Random/main.py | 29 +++- 5 files changed, 183 insertions(+), 11 deletions(-) delete mode 100644 Random/.generators.py.swp create mode 100644 Random/__pycache__/generators.cpython-36.pyc create mode 100644 Random/graph.py diff --git a/Random/.generators.py.swp b/Random/.generators.py.swp deleted file mode 100644 index af74f0d2fd905306d364547cccd8084cc04b07d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2KW`H;7>6BZLJ=@Bn4Bsl(EI@g3Q}335S>&qw4!Tpb545b&KKEtDrJBH!OGIH zAjAMde2Ox$u&^S*H(=odz|X$isXz;&Tcp?0le6Em{l0!K9je@BXT!hEueUl3?KES1 z&#Lm>r)9SLim`h_HH9*Xz4f;iMoCi%H5JWmu`Q0C`LNiq-5ad?ey_dm_x<*oP(c#6 zCsIi*(nOoqbm!<j=nfem1II9srQ_yum0i7Z+5M?|wF~_0nLEeWh?bB6GC&5%02v?y zWPl8i0WvVJ2GVJTJwov(W(QcDT`Rv`XG6M>0Wv@a$N(8217v^<kO4A42FL&zAOmw~ zKm?3EKFL_SisJG6fARnS*9FGDfPL^5JOxjH0Ta*#*T6Zj0Dhce>^t}f_Q4DA9PEJy zK!aQ0CRhRIK?Qt6-p}9zcmrO8T_C_+Fa$l|>YGEqR5BSL17v^<kO4A42FL&zAOmx2 zfX|wd(YSS=uW%z}z-%y(V>hVVTT8CnxPf!pd$t`|fu(|9EFzck&WJDOotW9_c029f zjIP^lY{<59mk#$ZMPyNm*sO$df<R${*`aN2%?P0pbK@cuBa|nzVUtazt~Xl4VW`4% zIIK6A4cj`(P=2&{iI0}JD9WnUYHsFgsHD)mo2ZG-q)I~(@$#i^E}}`I!*nZ8XxEG) zVGLjG_Uri@;DapQl)7KM2L6jYEz?XZK1fnOo<=gp_A=;cooJWZ7Fv{H`$ncb-IC4> zPsXlamcr}|+lm$ClS4`ycOSO%pILW883kN$<qpEfI*DE8wL!n!@?g$G9`8Rg{_!wS dajx-Dh4|ih9^Vi;OftjsDZCVH-oNxb_7htp0!RP= diff --git a/Random/__pycache__/generators.cpython-36.pyc b/Random/__pycache__/generators.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..12d1299222c60aedbec5e87efed307976b0ef7b8 GIT binary patch literal 7548 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 F{tNKC9yI^} literal 0 HcmV?d00001 diff --git a/Random/generators.py b/Random/generators.py index 3534ead..2d8a444 100644 --- a/Random/generators.py +++ b/Random/generators.py @@ -1,37 +1,188 @@ ## Various Random Generators ## +import random + class RandomNumberGenerator: def __init__(self): return NotImplementedError - def random(): + def random(self): """ yield a number from the RNG """ return NotImplementedError - - def seed(): + + def seed(self): """ set the seed of the generator """ return NotImplementedError + def randomNorm(self): + """ + return random between 0 and 1 + """ + return NotImplementedError + + def batchRandomNormalized(self, n): + """ + return n normalized values + """ + return [self.randomNorm() for i in range(n)] + class LCG(RandomNumberGenerator): """ Linear Congruential generator algorithm """ - def __init__(self, m, c, a): + def __init__(self, a, c, m): super().__init__() self.m = m self.c = c self.a = a - self.x = 0 #default seed + self.x = 0 # default seed + + def random(self): + self.x = (self.a * self.x + self.c) % self.m + return self.x + + def seed(self, seed): + self.x = seed + + def randomNorm(self): + return self.random() / (self.m + 1) - def random(): - self.x = self.a * self.x + self.c % self.m + +class ParkMiller(LCG): + """ + Park and Miller's LCG + """ + + def __init__(self): + super().__init__(16807, 0, 2147483647) + + +class KnuthLewis(LCG): + """ + Knuth and Lewis' LCG + """ + + def __init__(self): + super().__init__(1664525, 1013904223, 4294967296) + + +class Marsaglia(LCG): + """ + Marsaglia's LCG + """ + + def __init__(self): + super().__init__(69069, 0, 4294967296) + + +class LavauxJenssens(LCG): + """ + Lavaux And Jenssens' LCG + """ + + def __init__(self): + super().__init__(31167285, 1, 281474976710656) + + +class Haynes(LCG): + """ + Haynes' LCG + """ + + def __init__(self): + super().__init__(6364136223846793005, 1, 18446744073709552000) +class LaggedFibonnaci(RandomNumberGenerator): + """ + Lagged Fibonnaci generator algorithm + """ + + def __init__(self, l, k, m): + self.l = l + self.k = k + self.m = m + self.ParkMiller = ParkMiller() + self.values = [] + + def seed(self, seed): + self.ParkMiller.seed(seed) + self.values = [self.ParkMiller.random() for i in range(max(self.l, self.k))] + + def random(self): + # init values if non-existents + if not (self.values): + self.values = [self.ParkMiller.random() for i in range(max(self.l, self.k))] + val = (self.values[-self.l] + self.values[-self.k]) % self.m + self.values.append(val) + return self.values[-1] + + def randomNorm(self): + return random() / (self.m + 1) + + +class MitchelMoore(LaggedFibonnaci): + """ + Mitchel and Moore's Lagged Fibonnaci + we use m = 2^32 + """ + + def __init__(self): + super().__init__(24, 55, 4294967296) + + +class MersenneTwister(RandomNumberGenerator): + """ + MersenneTwister algorithm (native random.random()) + """ + + def __init__(self): + super().__init__() + + def seed(self, seed): + random.seed(seed) + + def randomNorm(self): + return random.random() + + def random(self): + return self.randomNorm() + + +class CNS(RandomNumberGenerator): + """ + Cryptography Network Security + """ + + def __init__(self, x0, M): + super().__init__() + self.M = M + self.x = x0 # must verify pgcd(M,x0) = 1 + def seed(self, seed): self.x = seed + + def random(self): + self.x = pow(self.x, 2) % self.M + return self.x + + def randomNorm(self): + return self.random() / (self.M + 1) + + +class BlumBlumShub(CNS): + """ + Blum Blum Shub + """ + + def __init__(self): + super().__init__(7817, 56923661) + + def seed(self, seed): + return # do nothing diff --git a/Random/graph.py b/Random/graph.py new file mode 100644 index 0000000..e69de29 diff --git a/Random/main.py b/Random/main.py index 3ab482e..3fc8978 100644 --- a/Random/main.py +++ b/Random/main.py @@ -1,7 +1,28 @@ -import generators +from generators import * +from datetime import datetime +import matplotlib.pyplot as plt +import numpy as np + if __name__=="__main__": - LCG = generators.LCG(5, 1, 1) - LCG.seed(0) - print(LCG.random()) + generators = [ParkMiller(), KnuthLewis(), Marsaglia() + , LavauxJenssens(), Haynes(), MitchelMoore() + , MersenneTwister(), BlumBlumShub()] + + seed = datetime.now().timestamp() + N = 1000 + RESOLUTION = 100 + + for e in generators: + e.seed(seed) + res = e.batchRandomNormalized(N) + + #matplotlib prep + #see https://matplotlib.org/stable/gallery/statistics/histogram_features.html#sphx-glr-gallery-statistics-histogram-features-py + fig, ax = plt.subplots() + n, bins, patches = ax.hist(res, RESOLUTION, density=True) + ax.set_xlabel('Value') + ax.set_ylabel('Probability density') + ax.set_title(type(e).__name__) + plt.savefig(type(e).__name__+'.png') -- GitLab