version_l.py
2.9 kB · python · 86 lines
1from fractions import Fraction23import mpmath as mp4import numpy as np56TOP = 117MC_TOP = 78MC_SAMPLES = 10**79BATCH = 10**61011def wallis_table(top):12 table = {}13 even = Fraction(16, 3)14 odd = Fraction(3, 8)15 table[2] = ("r/Pi^2", even)16 table[3] = ("rational", odd)17 k = 118 while 2 * k + 2 <= top or 2 * k + 3 <= top:19 even *= Fraction(4 * k * (k + 1), (2 * k + 1) * (2 * k + 3))20 odd *= Fraction((2 * k + 1) * (2 * k + 3), (2 * k + 2) * (2 * k + 4))21 if 2 * k + 2 <= top:22 table[2 * k + 2] = ("r/Pi^2", even)23 if 2 * k + 3 <= top:24 table[2 * k + 3] = ("rational", odd)25 k += 126 return table2728def value(form, rational):29 if form == "r/Pi^2":30 return mp.mpf(rational.numerator) / mp.mpf(rational.denominator) / mp.pi**231 return mp.mpf(rational.numerator) / mp.mpf(rational.denominator)3233def half_ball(rng, count, dim):34 pts = rng.standard_normal((count, dim))35 pts /= np.linalg.norm(pts, axis=1, keepdims=True)36 pts *= rng.random((count, 1)) ** (1.0 / dim)37 pts[:, dim - 1] = np.abs(pts[:, dim - 1])38 return pts3940def flat_face_rate(rng, dim, samples):41 hits = 042 done = 043 while done < samples:44 take = min(BATCH, samples - done)45 p = half_ball(rng, take, dim)46 q = half_ball(rng, take, dim)47 gap = p[:, dim - 1] - q[:, dim - 1]48 good = gap != 0.049 step = np.where(good, p[:, dim - 1] / np.where(good, gap, 1.0), 0.0)50 cross = p[:, : dim - 1] + step[:, None] * (q[:, : dim - 1] - p[:, : dim - 1])51 hits += int(np.count_nonzero(good & (np.linalg.norm(cross, axis=1) <= 1.0)))52 done += take53 return hits / samples5455def main():56 mp.mp.dps = 3057 table = wallis_table(TOP)58 print("VERSION L: two uniform points, the line through them meets the flat face")59 print(" seeds f(2) = 16/(3 Pi^2) and f(3) = 3/8")60 print(" even step f(2k+2)/f(2k) = 4k(k+1)/((2k+1)(2k+3))")61 print(" odd step f(2k+3)/f(2k+1) = (2k+1)(2k+3)/((2k+2)(2k+4))")62 print(f" exact rationals to d = {TOP}")63 for d in sorted(table):64 form, r = table[d]65 v = value(form, r)66 shown = f"({r})/Pi^2" if form == "r/Pi^2" else f"{r}"67 print(f" d = {d:>2} {shown:>26} {form:>9} {mp.nstr(v, 12)}")6869 print(" page decimals")70 for d, digits in ((2, 7), (3, 3), (4, 7), (5, 6), (6, 7), (7, 10)):71 form, r = table[d]72 print(f" d = {d} {mp.nstr(value(form, r), digits)}")7374 rng = np.random.default_rng(20250828)75 print(f" random-point check, {MC_SAMPLES} samples per dimension")76 for d in range(2, MC_TOP + 1):77 form, r = table[d]78 exact = value(form, r)79 est = mp.mpf(flat_face_rate(rng, d, MC_SAMPLES))80 se = mp.sqrt(est * (1 - est) / MC_SAMPLES)81 print(82 f" d = {d} estimate {mp.nstr(est, 8)} exact {mp.nstr(exact, 8)}"83 f" deviation {mp.nstr(est - exact, 3)} one sigma {mp.nstr(se, 3)}"84 )8586main()