diff --git a/Random/MPI.py b/Random/MPI.py new file mode 100644 index 0000000000000000000000000000000000000000..fc9b368bdc9fde2598c637eff2cd2186f8d4064e --- /dev/null +++ b/Random/MPI.py @@ -0,0 +1,40 @@ +#Uses MPI to dispatch random number generation on multiple nodes. +#files are saved into .npy files which can be loaded later with numpy +from mpi4py import MPI +from generators import * +from datetime import datetime + +comm = MPI.COMM_WORLD +size = comm.Get_size() # we suppose > 1 +rank = comm.Get_rank() + +#Wrapper for outside call +def MPIBatchRandomNormalized(generator,elmPerNode): + name = type(generator).__name__ + N = elmPerNode + + if rank == 0: + print("processing "+name+"...") + + #set seed with rank offset + generator.seed(rank + datetime.now().timestamp()) + randomNumbers = generator.batchRandomNormalized(N) + + #receives all the results. + gathered = comm.gather(data, root=0) + if rank==0: + data = np.array() + for l in gathered: + data += np.array(l) + print("Saving to "+name+".npz ...") + with open(name+".npy", "wb") as f: + np.save(f, data) + +if __name__ == "__main__": + N = 1000000 + generators = [ParkMiller(), KnuthLewis(), Marsaglia() + , LavauxJenssens(), Haynes(), MitchelMoore() + , MersenneTwister(), BlumBlumShub()] + + for e in generators + MPIBatchRandomNormalized(e,N) diff --git a/Random/generators.py b/Random/generators.py index f820e484ff99debe51f8e0e423d2c1152e93dd14..bbd6b193f75ef276e23277792d55a055ab724714 100644 --- a/Random/generators.py +++ b/Random/generators.py @@ -4,6 +4,7 @@ import random class RandomNumberGenerator: def __init__(self): + self.max = 0 #for normalization return NotImplementedError def random(self): @@ -28,7 +29,7 @@ class RandomNumberGenerator: """ return n normalized values """ - return [self.randomNorm() for i in range(n)] + return [self.random() for i in range(n)] / self.max class LCG(RandomNumberGenerator): @@ -42,6 +43,7 @@ class LCG(RandomNumberGenerator): self.c = c self.a = a self.x = 0 # default seed + self.max = self.m + 1 def random(self): self.x = (self.a * self.x + self.c) % self.m @@ -51,7 +53,7 @@ class LCG(RandomNumberGenerator): self.x = seed def randomNorm(self): - return self.random() / (self.m + 1) + return self.random() / self.max class ParkMiller(LCG): @@ -110,6 +112,7 @@ class LaggedFibonnaci(RandomNumberGenerator): self.m = m self.ParkMiller = ParkMiller() self.values = [] + self.max = self.m + 1 def seed(self, seed): self.ParkMiller.seed(seed) @@ -124,7 +127,7 @@ class LaggedFibonnaci(RandomNumberGenerator): return self.values[-1] def randomNorm(self): - return self.random() / (self.m + 1) + return self.random() / self.max class MitchelMoore(LaggedFibonnaci): @@ -164,6 +167,7 @@ class CNS(RandomNumberGenerator): super().__init__() self.M = M self.x = x0 # must verify pgcd(M,x0) = 1 + self.max = M + 1 def seed(self, seed): self.x = seed @@ -173,7 +177,7 @@ class CNS(RandomNumberGenerator): return self.x def randomNorm(self): - return self.random() / (self.M + 1) + return self.random() / self.max class BlumBlumShub(CNS): diff --git a/Random/main.py b/Random/main.py old mode 100644 new mode 100755 index 364597cf17d257b33d422cd87d19c8cfed054fe9..4473b35ba3d99f953f0c9d6a996dc321db4289c1 --- a/Random/main.py +++ b/Random/main.py @@ -2,30 +2,43 @@ from generators import * from datetime import datetime import matplotlib.pyplot as plt import numpy as np - +import seaborn as sns if __name__=="__main__": + ##INIT PARAMS## + N = 1000000 + RESOLUTION = 100 + #set seaborn params + sns.set_theme(style="darkgrid") + + #bandwidth for smooth density + #https://en.wikipedia.org/wiki/Kernel_density_estimation#Bandwidth_selection + BW = 0.337 + + #init generators generators = [ParkMiller(), KnuthLewis(), Marsaglia() , LavauxJenssens(), Haynes(), MitchelMoore() , MersenneTwister(), BlumBlumShub()] + #init seed on timesystem seed = datetime.now().timestamp() - N = 1000000 - RESOLUTION = 100 - + + #generate each diagrams for each random func for e in generators: name = type(e).__name__ + print("processing "+name+"...") e.seed(seed) res = e.batchRandomNormalized(N) + results.append(results) + print("building histograms..") - #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) + sns.displot(res, kde=True) ax.set_xlabel('Value') ax.set_ylabel('Probability density') ax.set_title(type(e).__name__) - #plt.show() plt.savefig(type(e).__name__+'.png') + + #generate diagrams with all randoms