-
Notifications
You must be signed in to change notification settings - Fork 0
/
build_rnc.py
65 lines (54 loc) · 1.98 KB
/
build_rnc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
## simple numerical random number converter from inv(CDF)
## Barry Y. Li and Tim Duong (2024)
import sys
import numpy as np
def generate_random_numbers(filename):
# 1. parameters
lower = 0 # sampling range lower bound
upper = 16 # sampling range upper bound
n = int(1e7) # number of random numbers to draw
randy = np.random.rand(n)
x = np.arange(lower, upper + 1e-4, 1e-4)
# 2. define PDF
def f(x):
return np.exp(-((x-5) / 2)**2)
# 3. trapezoidal integral function
def numint(x, f, i):
return np.trapz(f[:i+1], x[:i+1])
# 4. compute cdf numerically
intf = np.zeros(len(x) - 1)
for i in range(len(x) - 1):
intf[i] = 0.5 * (f(x[i+1]) + f(x[i])) * (x[i+1] - x[i])
cdf_f = np.cumsum(intf)
# 5. normalize the cdf
f = f(x) / cdf_f[-1]
intf = np.zeros(len(x) - 1)
for i in range(len(x) - 1):
intf[i] = 0.5 * (f[i+1] + f[i]) * (x[i+1] - x[i])
cdf_f = np.cumsum(intf)
# 6. convert random numbers based on the cdf
def closest_value(y, x):
findind = 0
endind = len(y) - 1
while endind - findind > 1:
midind = (endind + findind) // 2
if y[midind] >= x:
endind = midind
else:
findind = midind
if endind - findind == 1 and abs(y[endind] - x) < abs(y[findind] - x):
findind = endind
return findind
new_vec = np.zeros(n)
for i in range(n):
c = closest_value(cdf_f, randy[i])
new_vec[i] = x[c]
# 7. Write new_vec to a .log file
np.savetxt(filename, new_vec)
print(f"Random numbers saved to {filename}.")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python3 rng.py <filename>")
else:
filename = sys.argv[1]
generate_random_numbers(filename)