KrimsN

randvar

May 29th, 2020
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.15 KB | None | 0 0
  1. import scipy.optimize as opt
  2. from math import erf, pi, sqrt, exp, log
  3. from randtest import sample, expval, disp
  4. import random
  5. from hist import build_hist
  6. import matplotlib.pyplot as plt
  7. import numpy as np
  8.  
  9. random.seed()
  10.  
  11.  
  12. def distrf(x):
  13.     k = x**2/8
  14.     return k * sqrt(2/pi) * exp(-k)
  15.    
  16.  
  17. class MaxwellDistribution:
  18.     def __init__(self):
  19.         pass
  20.  
  21.     def __call__(self, x):
  22.         if x > 0:
  23.             a = 2*sqrt(2)
  24.             # интеграл от плотности
  25.             # при a = 2sqrt(2)      
  26.             # (условие нормировки)
  27.             return erf(x/a) - x*exp(-x**2/8)/sqrt(2*pi)
  28.         else:
  29.             return 0.0
  30.  
  31.  
  32. def dist_random(dist):
  33.     a = random.random()
  34.     # предполагаем, что вероятность выпадения чисел,
  35.     # больших 20, равна нулю
  36.     # но на самом деле из 100 тыс испытаний
  37.     # самое большое, что я получил --
  38.     # это 11 с копейками
  39.     return opt.bisect(lambda x: dist(x) - a,
  40.                       0.0, 20.0)
  41.  
  42.            
  43. if __name__ == "__main__":
  44.     D = MaxwellDistribution()
  45.     N = 10**4
  46.    
  47.     S = sample(lambda: dist_random(D), N)
  48.     bars = 45
  49.     k = 10 / bars
  50.     # bars = 1 + int(log(N)/log(2))
  51.     G = build_hist(S, bars, 0.0, 10.0)
  52.     M = expval(S)
  53.     V = disp(S, M)
  54.    
  55.     a = 2 * sqrt(2)
  56.    
  57.     # Real M,D
  58.     real_M = 4 * sqrt(2/pi)
  59.     real_V = 12 - 32/pi
  60.    
  61.     print(f' M: {M}, M_отклонение: {abs(real_M-M)/real_M} ')
  62.     print(f' D: {V}, D_отклонение: {abs(real_V-V)/real_V} ')
  63.    
  64.  
  65.     plt.style.use('seaborn-dark')
  66.     fig, ax = plt.subplots()
  67.    
  68.     x = np.fromiter([10*i/bars for i in range(bars)], dtype=float)
  69.     # f = np.vectorize(distrf)
  70.     f = np.vectorize(lambda x: distrf(x)*k)
  71.     f2 = np.vectorize(lambda x: D(x+k)-D(x))
  72.     fs = f(x)
  73.     fr = f2(x)
  74.    
  75.     x_axis = [f'{X:.1f}' for X in x]
  76.     width = 0.17
  77.     rects1 = ax.bar(x, G, width, label=f'Гистограмма (k={k})')
  78.     plot = ax.plot(x, fs, 'b-', label='kf(x)')
  79.     plot2 = ax.plot(x, fr, 'g-', label='F(x+k)-F(x)')
  80.     ax.set_title('Гистограмма распределения Максвелла')
  81.     ax.set_xticks(x)
  82.    
  83.     ax.set_ylabel('P')
  84.     ax.set_xticklabels(x_axis)
  85.     plt.xticks(rotation=45)
  86.     ax.legend()
  87.     plt.show()
Add Comment
Please, Sign In to add comment