shifted_sums.py
6.5 kB · python · 184 lines
1import subprocess2import sys3import time4from concurrent.futures import ThreadPoolExecutor56TOP = 267LOW = 168WORKERS = 89SHOW = 4010CONTROL_TOP = 1611CHECK = 1812PAGE_T = [0, -1, -3, -4, 0, -6, -5, -27, -21, -25, -51, -118, -168, -178, -257, -169]13PAGE_ENDPOINT = [0, -1, -1, -1, 3, -6, 0, -22, 6, -4, -27, -67, -49, -10, -78, 88, 82, 209, 543, 858, 335, -407, 3030]14LOWS = f"L=vector(2^{LOW},r,6*fromdigits(binary(r-1),3));"1516# PARI171819def gp(script):20 out = subprocess.run(["gp", "-q"], input=script + "\n", capture_output=True, text=True, check=True).stdout21 return [[int(x) for x in line.split()] for line in out.split("\n") if line.strip()]222324def fan(scripts):25 with ThreadPoolExecutor(len(scripts)) as pool:26 return [row for part in pool.map(gp, scripts) for row in part]272829def head(j):30 return f"h=6*fromdigits(binary({j}),3)*3^{LOW}+1;"313233def sums_script(js):34 body = [LOWS]35 for j in js:36 body.append(37 f"{head(j)} p=0; mn=0; mx=0; "38 f"for(r=1,2^{LOW}, p+=moebius(h+L[r]); if(p<mn,mn=p); if(p>mx,mx=p)); "39 f'print({j}," ",p," ",mn," ",mx);'40 )41 return "\n".join(body)424344def cross_script(jobs):45 body = [LOWS]46 for j, start, ls in jobs:47 body.append(48 f"{head(j)} p={start}; ls={ls}; "49 f'for(r=1,2^{LOW}, p+=moebius(h+L[r]); if(p!=0&&sign(p)!=ls, if(ls!=0, print({j}," ",r," ",sign(p)," ",h+L[r])); ls=sign(p)));'50 f'print({j}," ",0," ",ls," ",p);'51 )52 return "\n".join(body)535455def low_levels():56 return gp(LOWS + f" p=0; s=0; for(r=1,2^{LOW}, p+=moebius(1+L[r]); if(r==2^s, print(s,\" \",p); s++));")575859def sequential(top):60 return gp(f"p=0; ls=0; k=0; at=0; for(i=0,2^{top}-1, p+=moebius(6*fromdigits(binary(i),3)+1); if(p!=0&&sign(p)!=ls, if(ls!=0, k++; at=i+1); ls=sign(p))); print(p,\" \",k,\" \",at);")[0]616263def spread(items):64 return [items[k::WORKERS] for k in range(WORKERS) if items[k::WORKERS]]6566# THE WALK676869def chunk_sums():70 got = fan([sums_script(js) for js in spread(list(range(2 ** (TOP - LOW))))])71 return {j: (p, mn, mx) for j, p, mn, mx in got}727374def candidates(sums):75 todo, starts, ls, start = [], {}, 0, 076 for j in range(len(sums)):77 p, mn, mx = sums[j]78 starts[j] = (start, ls)79 if ls == 0 or (ls > 0 and start + mn < 0) or (ls < 0 and start + mx > 0):80 todo.append(j)81 end = start + p82 if end != 0:83 ls = 1 if end > 0 else -184 else:85 ls = gp(cross_script([(j, start, ls)]))[-1][2]86 start += p87 return todo, starts888990def crossings(sums):91 todo, starts = candidates(sums)92 got = fan([cross_script([(j, *starts[j]) for j in js]) for js in spread(todo)])93 flips = sorted((j * 2**LOW + r, sg, n) for j, r, sg, n in got if r > 0)94 return flips, len(todo)959697def positive_share(flips, n):98 pos, sign, at = 0, 1, 199 for m, sg, _ in flips:100 if m > n:101 break102 if sign > 0:103 pos += m - at104 sign, at = sg, m105 if sign > 0:106 pos += n + 1 - at107 return pos / n108109110def verb_walk():111 t0 = time.time()112 low = dict(low_levels())113 sums = chunk_sums()114 t1 = time.time()115 flips, todo = crossings(sums)116 t2 = time.time()117 level = dict(low)118 run = 0119 for j in range(len(sums)):120 run += sums[j][0]121 if (j + 1) & j == 0:122 level[LOW + (j + 1).bit_length() - 1] = run123 assert [level[s] for s in range(1, 17)] == PAGE_T124 mu = dict(gp("\n".join(f'print({t}," ",moebius(3^{t}+1));' for t in range(2, TOP + 2))))125 ends = [level[t - 1] - level[t - 2] + mu[t] for t in range(2, 25)]126 assert ends == PAGE_ENDPOINT127 early = [m for m, _, _ in flips if m <= 2**CHECK]128 assert sequential(CHECK) == [level[CHECK], len(early), early[-1]]129 print(f"T_s = sum_(w in B_s) mu(6w + 1), B_s the 2^s base 3 {{0,1}}-strings of length s, walked in ascending w to s = {TOP}")130 print(f"checks: T_1..T_16 equal the page's list; T_(t-1) - T_(t-2) + mu(3^t + 1) equals the page's M_F(x_t; R_t) at t = 2..24; a sequential walk to 2^{CHECK} repeats T_{CHECK}, the flip count and the last flip")131 print(" s | 2^s | top element | T_s | T_s/2^(s/2) | flips n <= 2^s | share of n <= 2^s with last nonzero sign +")132 for s in range(TOP + 1):133 n = 2**s134 k = sum(1 for m, _, _ in flips if m <= n)135 print(f"{s:3d} | {n:10d} | {3 ** (s + 1) - 2:17d} | {level[s]:9d} | {level[s] / 2 ** (s / 2):11.4f} | {k:14d} | {positive_share(flips, n):.4f}")136 neg = [s for s in range(1, TOP + 1) if level[s] < 0]137 pos = [s for s in range(1, TOP + 1) if level[s] > 0]138 print(f"T_s < 0 at s = {neg}")139 print(f"T_s > 0 at s = {pos}")140 print(f"T_s = 0 at s = {[s for s in range(1, TOP + 1) if level[s] == 0]}")141 print(f"cut: n = 2^{TOP} = {2**TOP} terms, largest element 3^{TOP + 1} - 2 = {3 ** (TOP + 1) - 2}, P = {level[TOP]}")142 print(f"sign changes of the prefix walk P_n (last nonzero sign flips): {len(flips)} in all, {todo} chunks of 2^{LOW} rewalked")143 print(f"the last {min(SHOW, len(flips))}: n, new sign, element 6w + 1")144 for m, sg, n in flips[-SHOW:]:145 print(f" n = {m:10d} {'+' if sg > 0 else '-'} 6w + 1 = {n}")146 print(f"walk {t1 - t0:.1f} s, rewalk {t2 - t1:.1f} s, {WORKERS} gp processes")147148# THE CONTROL149150151def smooth23(x):152 count, a = 0, 1153 while a <= x:154 b = a155 while b <= x:156 count, b = count + 1, 3 * b157 a *= 2158 return count159160161def verb_control():162 t0 = time.time()163 got = gp(164 "p=0; ls=0; ch=0; ps=0; c=0; s=0; nx=1; "165 f"forstep(n=1,3^{CONTROL_TOP}-2,6, p+=moebius(n); c++; if(p!=0&&sign(p)!=ls, if(ls!=0,ch++); ls=sign(p)); if(ls>0,ps++); "166 'if(n==nx, print(s," ",p," ",ch," ",ps," ",c); s++; nx=3^(s+1)-2));'167 )168 print("control: the whole class, M(x; 6, 1) = sum_(n <= x, n = 1 mod 6) mu(n), at x = 3^(s+1) - 2")169 print("drift = 3/4 - Psi_(2,3)(x), the s = 0 residue of M(x; 6, 1) with M's constant -2 and 1/(L(0, chi_-3)(1 + 2^0)) = 3/2")170 print(" s | x | M(x; 6, 1) | drift | M/sqrt(x/6) | flips to x | share with last nonzero sign +")171 for s, p, ch, ps, c in got:172 x = 3 ** (s + 1) - 2173 print(f"{s:3d} | {x:16d} | {p:10d} | {0.75 - smooth23(x):7.2f} | {p / (x / 6) ** 0.5:11.4f} | {ch:10d} | {ps / c:.4f}")174 print(f"control {time.time() - t0:.1f} s")175176177def main():178 verbs = {"walk": verb_walk, "control": verb_control}179 for v in sys.argv[1:] or list(verbs):180 verbs[v]()181182183if __name__ == "__main__":184 main()