smith_cascade.py

7.9 kB · python · 196 lines

1import sys2import time3from fractions import Fraction4from math import comb56PREC = 2567TOP = 51189def jacobsthal(k):10    return (2 ** k - (-1) ** k) // 31112def polymul(a, b):13    out = [0] * (len(a) + len(b) - 1)14    for i, x in enumerate(a):15        if x:16            for j, y in enumerate(b):17                out[i + j] += x * y18    return out1920def digit_poly(D):21    base = [0] * (2 * D - 1)22    for k in range(D):23        base[2 * k] = comb(D - 1, k)24    return polymul(base, [1, D, 1])2526def m_even(D):27    P = digit_poly(D)28    R = (D - 1) // 229    n = R + 13031    def coefficient(x):32        return P[x] if 0 <= x < len(P) else 03334    M = [[0] * n for _ in range(n)]35    for cp in range(n):36        for c in range(n):37            v = coefficient(c + D - 3 * cp)38            if c:39                v += coefficient(-c + D - 3 * cp)40            M[cp][c] = v41    return M4243def fill(D):44    return 2 ** (D - 1) * (D + 2)4546def bareiss_det(A):47    n = len(A)48    M = [row[:] for row in A]49    sign = 150    prev = 151    for k in range(n - 1):52        if M[k][k] == 0:53            p = next((r for r in range(k + 1, n) if M[r][k]), None)54            if p is None:55                return 056            M[k], M[p] = M[p], M[k]57            sign = -sign58        for i in range(k + 1, n):59            for j in range(k + 1, n):60                M[i][j] = (M[i][j] * M[k][k] - M[i][k] * M[k][j]) // prev61        prev = M[k][k]62    return sign * M[n - 1][n - 1]6364def v_2(x):65    return (x & -x).bit_length() - 16667def smith_valuations(A, prec=PREC):68    n = len(A)69    cur = prec70    M = [[x % (1 << cur) for x in row] for row in A]71    out = []72    for k in range(n):73        bv = None74        best = None75        for i in range(k, n):76            for j in range(k, n):77                x = M[i][j]78                if x:79                    v = v_2(x)80                    if bv is None or v < bv:81                        bv, best = v, (i, j)82            if bv == 0:83                break84        if best is None:85            raise ValueError("singular modulo 2^%d at step %d" % (cur, k))86        if bv > cur - 64:87            raise ValueError("precision exhausted")88        i0, j0 = best89        M[k], M[i0] = M[i0], M[k]90        if j0 != k:91            for row in M:92                row[k], row[j0] = row[j0], row[k]93        out.append(bv)94        cur -= bv95        m2 = 1 << cur96        u = (M[k][k] >> bv) % m297        inv = pow(u, -1, m2)98        prow = M[k][k:]99        for i in range(k + 1, n):100            Mi = M[i]101            a = Mi[k] >> bv102            if a % m2:103                f = (a * inv) % m2104                M[i] = Mi[:k] + [(x - f * y) % m2 for x, y in zip(Mi[k:], prow)]105            elif bv:106                M[i] = [x % m2 for x in Mi]107            M[i][k] = 0108    return out109110TROUGHS = sorted({2 * jacobsthal(k) + s for k in range(2, 20) for s in (1, 3)})111112def tent(D):113    return min(abs(D - t) // 2 + 1 for t in TROUGHS)114115def layer(a, j):116    return sum(1 for x in a if x >= j)117118def profile(D, prec=PREC):119    a = smith_valuations(m_even(D), prec)120    n = len(a)121    return dict(D=D, n=n, a=a, v_2=sum(a), L1=layer(a, 1), L2=layer(a, 2), L3=layer(a, 3), L4=layer(a, 4), L5=layer(a, 5), amax=max(a), X=sum(a) - layer(a, 1), tent=tent(D))122123def octave(D):124    return D.bit_length() - 1125126def cone_checks(rows, key):127    seq = [r[key] for r in rows]128    lipschitz = sum(1 for i in range(len(seq) - 1) if abs(seq[i + 1] - seq[i]) > 1)129    minima = [rows[i]["D"] for i in range(1, len(seq) - 1) if seq[i] <= seq[i - 1] and seq[i] <= seq[i + 1] and (seq[i] < seq[i - 1] or seq[i] < seq[i + 1]) and seq[i] != 1]130    plateaus = [rows[i]["D"] for i in range(1, len(seq) - 1) if seq[i - 1] == seq[i] == seq[i + 1] and seq[i] != 1]131    return lipschitz, minima, plateaus132133def argmax(rows, key):134    m = max(r[key] for r in rows)135    return m, [r["D"] for r in rows if r[key] == m]136137def main():138    t0 = time.time()139    rows = [profile(D) for D in range(3, TOP + 1, 2)]140    print("odd D = 3..%d, rows %d, seconds %.0f" % (TOP, len(rows), time.time() - t0))141    print("tent law nullity = tent(D): %d/%d, misses %s" % (sum(r["L1"] == r["tent"] for r in rows), len(rows), [r["D"] for r in rows if r["L1"] != r["tent"]]))142    rows = [r for r in rows if r["D"] >= 5]143    print("rows at odd D = 5..%d: %d" % (TOP, len(rows)))144    for D in (5, 7):145        r = next(r for r in rows if r["D"] == D)146        print("D = %d profile %s v_2 = %d n = %d" % (D, r["a"], r["v_2"], r["n"]))147    print()148    print("octave  D range   maxL2 J(k-2)  maxL3 J(k-4)  maxL4  maxL5  max_amax k+4  maxX  max(v_2-ceil(n/3))  at D")149    for k in range(2, 9):150        W = [r for r in rows if octave(r["D"]) == k]151        l2, _ = argmax(W, "L2")152        l3, _ = argmax(W, "L3")153        l4, _ = argmax(W, "L4")154        l5, _ = argmax(W, "L5")155        am, _ = argmax(W, "amax")156        x, _ = argmax(W, "X")157        for r in W:158            r["slack"] = r["v_2"] - (-(-r["n"] // 3))159        sl, at = argmax(W, "slack")160        print("%-7d %3d..%-4d %5d %6d  %5d %6d  %5d  %5d  %8d %3d  %4d  %17d  %s" % (k, W[0]["D"], W[-1]["D"], l2, jacobsthal(k - 2), l3, jacobsthal(k - 4) if k >= 4 else 0, l4, l5, am, k + 4, x, sl, at))161    print()162    for j, key in ((1, "L1"), (2, "L2"), (3, "L3")):163        lip, mins, plat = cone_checks(rows, key)164        print("layer %d cones: Lipschitz breaks %d, interior local minima off 1 %s, plateaus off 1 %s" % (j, lip, mins, plat))165    print()166    print("v_2 <= ceil(n/3) + 9 at every row: %s, max slack %d at D = %s" % (all(r["slack"] <= 9 for r in rows), *argmax(rows, "slack")))167    print("v_2 > n at D = %s" % [r["D"] for r in rows if r["v_2"] > r["n"]])168    print("v_2 = n at D = %s" % [r["D"] for r in rows if r["v_2"] == r["n"]])169    cls = [r for r in rows if r["D"] % 6 == 1 and r["D"] >= 13]170    ratio = max(Fraction(r["v_2"], r["D"] - 1) for r in cls)171    print("class D = 1 mod 6, rows %d (%d..%d): max(v_2 - n) = %d, all v_2 < D - 1: %s, max v_2/(D-1) = %s at D = %s" % (len(cls), cls[0]["D"], cls[-1]["D"], max(r["v_2"] - r["n"] for r in cls), all(r["v_2"] < r["D"] - 1 for r in cls), ratio, [r["D"] for r in cls if Fraction(r["v_2"], r["D"] - 1) == ratio]))172    last = rows[-1]173    print("D = %d: v_2 = %d, ceil(n/3) + 13 = %d, ceil(n/3) + 9 = %d" % (last["D"], last["v_2"], -(-last["n"] // 3) + 13, -(-last["n"] // 3) + 9))174    print("max v_2/n over odd D >= 17: %.3f" % max(r["v_2"] / r["n"] for r in rows if r["D"] >= 17))175    print()176    print("first amax > 9 at D = %d, max amax %d at D = %s" % (next(r["D"] for r in rows if r["amax"] > 9), *argmax(rows, "amax")))177    print("first L3 != 1 at D = %d, max L3 %d at D = %s" % (next(r["D"] for r in rows if r["L3"] != 1), *argmax(rows, "L3")))178    print("first L2 > 5 at D = %d, max L2 %d at D = %s" % (next(r["D"] for r in rows if r["L2"] > 5), *argmax(rows, "L2")))179    print("max X %d at D = %s" % argmax(rows, "X"))180    print("X = v_2 - nullity at D = 255, 257: %s" % [r["X"] for r in rows if r["D"] in (255, 257)])181    print("second largest divisor valuation, max over rows %d; rows with L5 = 0: %s" % (max(sorted(r["a"])[-2] for r in rows), [r["D"] for r in rows if r["L5"] == 0]))182    print("v_2/(D-1) at D = 13, 19: %s" % [str(Fraction(r["v_2"], r["D"] - 1)) for r in rows if r["D"] in (13, 19)])183    print()184    bad = [D for D in range(5, 62, 2) if v_2(bareiss_det(m_even(D))) != sum(smith_valuations(m_even(D)))]185    print("exact determinant against Smith sum, odd D = 5..61: mismatches %s" % bad)186    t1 = time.time()187    stable = all(smith_valuations(m_even(D), 1024) == next(r["a"] for r in rows if r["D"] == D) for D in (255, 257, 511))188    print("profiles at D = 255, 257, 511 unchanged at precision 1024: %s, seconds %.0f" % (stable, time.time() - t1))189    E = m_even(7)190    pencil = [[fill(7) * (i == j) - 3 * E[i][j] for j in range(4)] for i in range(4)]191    d7 = bareiss_det(pencil)192    print("D = 7: det(fill I - 3 M_even) = %d, v_2 = %d, fill = %d" % (d7, v_2(d7), fill(7)))193    print("total seconds %.0f" % (time.time() - t0))194195if __name__ == "__main__":196    main()