diff --git a/Random/.generators.py.swp b/Random/.generators.py.swp deleted file mode 100644 index af74f0d2fd905306d364547cccd8084cc04b07d5..0000000000000000000000000000000000000000 Binary files a/Random/.generators.py.swp and /dev/null differ diff --git a/Random/__pycache__/generators.cpython-36.pyc b/Random/__pycache__/generators.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..12d1299222c60aedbec5e87efed307976b0ef7b8 Binary files /dev/null and b/Random/__pycache__/generators.cpython-36.pyc differ diff --git a/Random/generators.py b/Random/generators.py index 3534eadbe9fd6930a256f9f985dbf1d23dd440d0..2d8a444ca88107b4134734a5fee61a5a36971de1 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Random/main.py b/Random/main.py index 3ab482e7064ff823357fbfbfda633d5fd4f8ba31..3fc897886114252e251d8fca901cb800eb85a8e3 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')