4.8. Solutions: Lecture 4#
4.8.1. Exercise 4.1#
ex_4.1.py
#!/usr/bin/python
'''
Si scriva una funzione che implementi il generatore lineare congruenziale di numeri pseudo-casuali,
utilizzando questi parametri:
M = 2147483647
A = 214013
C = 2531011
python3 es_4.1.py 10
'''
import sys
def main () :
'''
Funzione che implementa il programma principale
'''
if len(sys.argv) < 2 :
print ('usage: ', sys.argv[0], 'numero')
exit ()
# fixed parameters
A = 214013
C = 2531011
M = 2147483647
# first number, i.e. the seed of the generation
num = 10
randlist = []
for i in range (int (sys.argv[1])):
num = (A * num + C) % M
randlist.append (num)
print (i, randlist[-1])
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
4.8.2. Exercise 4.2#
ex_4.2.py
#!/usr/bin/python
'''
Si scriva una funzione che implementi il generatore lineare congruenziale di numeri pseudo-casuali,
utilizzando questi parametri:
M = 2147483647
A = 214013
C = 2531011
python3 es_4.2.py 10
'''
import sys
class LCG :
'''Linear congruential generator'''
# fixed parameters
A = 214013
C = 2531011
M = 2147483647
# current sequence value
def __init__ (self, value = 12345):
self.num = value
def seed (self, value) :
self.num = value
def random (self) :
self.num = (self.A * self.num + self.C) % self.M
return self.num
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def main () :
'''
Funzione che implementa il programma principale
'''
if len(sys.argv) < 2 :
print ('usage: ', sys.argv[0], 'numero')
exit ()
seed = 10
my_LCG = LCG (seed)
randlist = []
for i in range (int (sys.argv[1])):
randlist.append (my_LCG.random ())
print (i, randlist[-1])
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
4.8.3. Exercise 4.3#
ex_4.3.py
#!/usr/bin/python
'''
Si mostri che inizializzare il seed di un generatore di numeri pseudo-casuali interi
equivale ad inserirsi in una sequenza di numeri pseudo-casuali ad un qualunque punto.
python3 es_4.3.py 10
nb: `random.seed` does not restart the sequence from the given value,
rather it uses the given value to calculate a random *state* that is then used to generate the random numbers.
'''
import sys
import random
def main () :
'''
Funzione che implementa il programma principale
'''
if len(sys.argv) < 2 :
print ('usage: ', sys.argv[0], 'numero')
exit ()
randlist = []
randstates = []
for i in range (int (sys.argv[1])):
# Return the next random floating point number in the range 0.0 <= X < 1.0
randlist.append (random.randint (0, 100))
randstates.append (random.getstate ())
print (i, randlist[-1])
random.setstate (randstates[4])
print (random.randint (0, 100), randlist[5])
random.seed( randlist[4] )
print (random.randint (0, 100), randlist[5])
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
4.8.4. Exercise 4.4#
ex_4.4.py
#!/usr/bin/python
'''
Si implementi un generatore di numeri pseudo-casuali secondo una distribuzione uniforme
fra due estremi arbitrari.
* Si utilizzi la libreria MatPlotLib per visualizzare la distribuzione dei numeri generati.
python3 es_4.4.py 2.2 4.3 2000 2.4
'''
import sys
import random
import matplotlib.pyplot as plt
import numpy as np
from math import floor
from myrand import generate_range
def main () :
'''
Funzione che implementa il programma principale
'''
if len(sys.argv) < 5 :
print ('usage: ', sys.argv[0], 'xMin xMax numero seed')
exit ()
xMin = float (sys.argv[1]) # minimum of the histogram drawing range
xMax = float (sys.argv[2]) # maximum of the histogram drawing range
seed = float (sys.argv[4])
N = int (sys.argv[3])
print (' -------- ')
print (' minimum : ', xMin)
print (' maximum : ', xMax)
print (' seed : ', seed)
print (' N : ', N)
print (' -------- ')
randlist = generate_range (xMin, xMax, N, seed)
# plotting of the generated list of numbers in a histogram
nBins = floor (len (randlist) / 20.) + 1 # number of bins of the hitogram
bin_edges = np.linspace (xMin, xMax, nBins) # edges o the histogram bins
# disegno della funzione
fig, ax = plt.subplots ()
ax.set_title ('Histogram of random numbers', size=14)
ax.set_xlabel ('random value')
ax.set_ylabel ('events in bin')
ax.hist (randlist, # list of numbers
bins = bin_edges,
color = 'orange',
# normed = True,
)
plt.savefig ('es_4.4.png')
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
myrand.py
#!/usr/bin/python
import random
from math import sqrt
def generate_uniform (N, seed = 0.) :
'''
generazione di N numeri pseudo-casuali distribuiti fra 0 ed 1
a partire da un determinato seed
'''
if seed != 0. : random.seed (float (seed))
randlist = []
for i in range (N):
# Return the next random floating point number in the range 0.0 <= X < 1.0
randlist.append (random.random ())
return randlist
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def rand_range (xMin, xMax) :
'''
generazione di un numero pseudo-casuale distribuito fra xMin ed xMax
'''
return xMin + random.random () * (xMax - xMin)
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def generate_range (xMin, xMax, N, seed = 0.) :
'''
generazione di N numeri pseudo-casuali distribuiti fra xMin ed xMax
a partire da un determinato seed
'''
if seed != 0. : random.seed (float (seed))
randlist = []
for i in range (N):
# Return the next random floating point number in the range 0.0 <= X < 1.0
randlist.append (rand_range (xMin, xMax))
return randlist
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def rand_TAC (f, xMin, xMax, yMax) :
'''
generazione di un numero pseudo-casuale
con il metodo try and catch
'''
x = rand_range (xMin, xMax)
y = rand_range (0, yMax)
while (y > f (x)) :
x = rand_range (xMin, xMax)
y = rand_range (0, yMax)
return x
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def generate_TAC (f, xMin, xMax, yMax, N, seed = 0.) :
'''
generazione di N numeri pseudo-casuali
con il metodo try and catch, in un certo intervallo,
a partire da un determinato seed
'''
if seed != 0. : random.seed (float (seed))
randlist = []
for i in range (N):
# Return the next random floating point number in the range 0.0 <= X < 1.0
randlist.append (rand_TAC (f, xMin, xMax, yMax))
return randlist
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def rand_TCL (xMin, xMax, N_sum = 10) :
'''
generazione di un numero pseudo-casuale
con il metodo del teorema centrale del limite
su un intervallo fissato
'''
y = 0.
for i in range (N_sum) :
y = y + rand_range (xMin, xMax)
y /= N_sum ;
return y ;
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def generate_TCL (xMin, xMax, N, N_sum = 10, seed = 0.) :
'''
generazione di N numeri pseudo-casuali
con il metodo del teorema centrale del limite, in un certo intervallo,
a partire da un determinato seed
'''
if seed != 0. : random.seed (float (seed))
randlist = []
for i in range (N):
# Return the next random floating point number in the range 0.0 <= X < 1.0
randlist.append (rand_TCL (xMin, xMax, N_sum))
return randlist
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def rand_TCL_ms (mean, sigma, N_sum = 10) :
'''
generazione di un numero pseudo-casuale
con il metodo del teorema centrale del limite
note media e sigma della gaussiana
'''
y = 0.
delta = sqrt (3 * N_sum) * sigma
xMin = mean - delta
xMax = mean + delta
for i in range (N_sum) :
y = y + rand_range (xMin, xMax)
y /= N_sum ;
return y ;
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def generate_TCL_ms (mean, sigma, N, N_sum = 10, seed = 0.) :
'''
generazione di N numeri pseudo-casuali
con il metodo del teorema centrale del limite, note media e sigma della gaussiana,
a partire da un determinato seed
'''
if seed != 0. : random.seed (float (seed))
randlist = []
delta = sqrt (3 * N_sum) * sigma
xMin = mean - delta
xMax = mean + delta
for i in range (N):
# Return the next random floating point number in the range 0.0 <= X < 1.0
randlist.append (rand_TCL (xMin, xMax, N_sum))
return randlist
4.8.5. Exercise 4.5#
ex_4.4.py
#!/usr/bin/python
'''
Si implementi un generatore di numeri pseudo-casuali secondo una distribuzione uniforme
fra due estremi arbitrari.
* Si utilizzi la libreria MatPlotLib per visualizzare la distribuzione dei numeri generati.
python3 es_4.4.py 2.2 4.3 2000 2.4
'''
import sys
import random
import matplotlib.pyplot as plt
import numpy as np
from math import floor
from myrand import generate_range
def main () :
'''
Funzione che implementa il programma principale
'''
if len(sys.argv) < 5 :
print ('usage: ', sys.argv[0], 'xMin xMax numero seed')
exit ()
xMin = float (sys.argv[1]) # minimum of the histogram drawing range
xMax = float (sys.argv[2]) # maximum of the histogram drawing range
seed = float (sys.argv[4])
N = int (sys.argv[3])
print (' -------- ')
print (' minimum : ', xMin)
print (' maximum : ', xMax)
print (' seed : ', seed)
print (' N : ', N)
print (' -------- ')
randlist = generate_range (xMin, xMax, N, seed)
# plotting of the generated list of numbers in a histogram
nBins = floor (len (randlist) / 20.) + 1 # number of bins of the hitogram
bin_edges = np.linspace (xMin, xMax, nBins) # edges o the histogram bins
# disegno della funzione
fig, ax = plt.subplots ()
ax.set_title ('Histogram of random numbers', size=14)
ax.set_xlabel ('random value')
ax.set_ylabel ('events in bin')
ax.hist (randlist, # list of numbers
bins = bin_edges,
color = 'orange',
# normed = True,
)
plt.savefig ('es_4.4.png')
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
4.8.6. Exercise 4.6#
ex_4.6.py
#!/usr/bin/python
'''
Si implementi un generatore di numeri pseduo-casuali che utilizzi il metodo della funzione inversa
per generare eventi distribuiti secondo distribuzione di probabilita' esponenziale.
* Si utilizzi la libreria MatPlotLib per visualizzare la distribuzione dei numeri generati.
python3 es_4.6.py 100 2.4
'''
import sys
import random
import matplotlib.pyplot as plt
import numpy as np
from math import floor
from myrand import generate_TAC
def inv_exp (y, lamb = 1) :
'''
Inverse of the primitive of the exponential PDF.
pdf(x) = lambda * exp(-lambda x) x >= 0, 0 otherwise.
F(x) = int_{0}^{x} pdf(x)dx = 1 - exp(-lambda * x) for x >= 0, 0 otherwise.
F^{-1}(y) = - (ln(1-y)) / lambda
'''
return -1 * np.log (1-y) / lamb
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def main () :
'''
Funzione che implementa il programma principale
'''
if len(sys.argv) < 3 :
print ('usage: ', sys.argv[0], 'N tau [seed=10]')
exit ()
tau = float (sys.argv[2])
if tau <= 0 :
print ('The tau parameter has to be positive')
exit ()
lamb = 1./tau ;
N = int (sys.argv[1])
seed = 10
if len(sys.argv) >= 4 :
seed = float (sys.argv[3])
random.seed (seed)
randlist = []
for i in range (N):
randlist.append (inv_exp (random.random (), lamb))
# plotting of the generated list of numbers in a histogram
nBins = floor (len (randlist) / 100.) # number of bins of the hitogram
bin_edges = np.linspace (0., 3., nBins + 1) # edges o the histogram bins
# disegno della funzione
fig, ax = plt.subplots ()
ax.set_title ('Histogram of random numbers', size=14)
ax.set_xlabel ('random value')
ax.set_ylabel ('events in bin')
ax.hist (randlist, # list of numbers
bins = bin_edges,
color = 'orange',
# normed = True,
)
plt.savefig ('es_4.6.png')
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()
4.8.7. Exercise 4.7#
stats.py
#!/usr/bin/python
from math import sqrt
class stats :
'''calculator for statistics of a list of numbers'''
summ = 0.
sumSq = 0.
N = 0
sample = []
def __init__ (self, sample):
'''
reads as input the collection of events,
which needs to be a list of numbers
'''
self.sample = sample
self.summ = sum (self.sample)
self.sumSq = sum ([x*x for x in self.sample])
self.N = len (self.sample)
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def mean (self) :
'''
calculates the mean of the sample present in the object
'''
return self.summ / self.N
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def variance (self, bessel = True) :
'''
calculates the variance of the sample present in the object
'''
var = self.sumSq / self.N - self.mean () * self.mean ()
if bessel : var = self.N * var / (self.N - 1)
return var
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def sigma (self, bessel = True) :
'''
calculates the sigma of the sample present in the object
'''
return sqrt (self.variance (bessel))
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def sigma_mean (self, bessel = True) :
'''
calculates the sigma of the sample present in the object
'''
return sqrt (self.variance (bessel) / self.N)
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
def append (self, x):
'''
add an element to the sample
'''
self.sample.append (x)
self.summ = self.summ + x
self.sumSq = self.sumSq + x * x
self.N = self.N + 1
4.8.8. Exercise 4.8#
ex_4.8.py
#!/usr/bin/python
'''
Partendo dal lavoro svolto durante la Lezione 3,
si implementi un oggetto chiamato ```stats```,
che calcola le statistiche associate ad un campione di numeri
salvato in una lista di Python.
* quali diverse opzioni di progettazione sono possibili per questo oggetto?
* che variabili è necessario aggiungere alla classe per garantirne la funzionalità?
* che valore devono avere queste variabili in fase di inizilizzazione?
Si collaudi l'oggetto ```stats``` con ciascuono degli agoritmi di generazione implementati.
In particolare, poi:
* si verifichi che il valore della varianza della distribuzione uniforme corrisponde alle attese
(quale è l'incertezza associata al numero ottenuto?)
* si verifichi che il valore della varianza ottenuta con la tecnica del teorema centrale del limite
corrisponda a quello atteso
python3 es_4.8.py 0. 3. 20000 2.4 10
'''
import sys
import random
import matplotlib.pyplot as plt
import numpy as np
from math import floor
from myrand import generate_TCL_ms
from stats import stats
def main () :
'''
Funzione che implementa il programma principale
'''
if len(sys.argv) < 6:
print ('usage: ', sys.argv[0], 'mean sigma numero seed numero_somme')
exit ()
mean = float (sys.argv[1]) # minimum of the histogram drawing range
sigma = float (sys.argv[2]) # maximum of the histogram drawing range
seed = float (sys.argv[4])
N = int (sys.argv[3])
N_sum = int (sys.argv[5])
print (' -------- ')
print (' mean : ', mean)
print (' sigma : ', sigma)
print (' seed : ', seed)
print (' N : ', N)
print (' N_sum : ', N_sum)
print (' -------- ')
randlist = generate_TCL_ms (mean, sigma, N, N_sum, seed)
my_stats = stats (randlist)
my_mean = my_stats.mean ()
my_sigma = my_stats.sigma ()
print ('media: ', my_mean) ;
print ('varianza: ', my_stats.variance ()) ;
print ('sigma: ', my_sigma) ;
# plotting of the generated list of numbers in a histogram
nBins = floor (len (randlist) / 400.) # number of bins of the hitogram
bin_edges = np.linspace (mean - 3 * sigma, mean + 3 * sigma, nBins + 1) # edges o the histogram bins
# disegno della funzione
fig, ax = plt.subplots ()
ax.set_title ('Histogram of random numbers', size=14)
ax.set_xlabel ('random value')
ax.set_ylabel ('events in bin')
ax.hist (randlist, # list of numbers
bins = bin_edges,
color = 'orange',
# normed = True,
)
yrange = plt.ylim ()
ax.plot ([my_mean, my_mean], yrange, color = 'red')
ax.plot ([my_mean - my_sigma, my_mean - my_sigma], yrange, linestyle='dashed', color = 'red')
ax.plot ([my_mean + my_sigma, my_mean + my_sigma], yrange, linestyle='dashed', color = 'red')
plt.savefig ('es_4.8.png')
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
if __name__ == "__main__":
main ()