large.py

20.8 kB · python · 451 lines

1import math2import sys3import time4from fractions import Fraction5from functools import lru_cache6from itertools import combinations78import mpmath as mp9import sympy as sp1011CODE = (1, 3, 0, 0)12R = sp.Rational13N = sp.symbols("n")14B = sp.symbols("b", positive=True)15FIVE = {"g": (0, 0), "g+b": (0, -1), "g+1": (1, 0), "g+b-1": (-1, -1), "g+b+1": (1, -1)}1617# DIGIT POLYNOMIALS1819def weights(code):20    w = [0, 0, 0, 0]21    for p in range(8):22        if code >> p & 1:23            w[bin(p).count("1")] += 124    return tuple(w)2526def convolve(p, q):27    out = [0] * (len(p) + len(q) - 1)28    for i, x in enumerate(p):29        if x:30            for j, y in enumerate(q):31                if y:32                    out[i + j] += x * y33    return out3435BASIS = {}3637def digit_polynomial(b, w):38    if b not in BASIS:39        e = [1 - k % 2 for k in range(b)]40        o = [k % 2 for k in range(b)]41        ee, eo, oo = convolve(e, e), convolve(e, o), convolve(o, o)42        BASIS[b] = [convolve(ee, e), convolve(ee, o), convolve(eo, o), convolve(oo, o)]43    return [sum(w[k] * BASIS[b][k][s] for k in range(4)) for s in range(3 * b - 2)]4445def at(p, s):46    return p[s] if 0 <= s < len(p) else 04748def automaton(b, w=CODE):49    p, g = digit_polynomial(b, w), 3 * (b - 1) // 250    return [[at(p, c + g - b * d) for d in (-1, 0, 1)] for c in (-1, 0, 1)]5152def block(b, w=CODE):53    p, g = digit_polynomial(b, w), 3 * (b - 1) // 254    return [[at(p, g), at(p, g + b)], [2 * at(p, g + 1), at(p, g + b - 1) + at(p, g + b + 1)]]5556def fill(b, w):57    n = (b + 1) // 258    return sum(w[k] * n ** (3 - k) * (n - 1) ** k for k in range(4))5960def spectra_block(b):61    if b % 4 == 3:62        return [[3 * (b + 1) * (3 * b - 1) // 16, (b + 1) * (b + 5) // 32], [3 * (b + 1) ** 2 // 8, 3 * (b + 1) ** 2 // 16]]63    return [[(3 * b * b + 6 * b + 7) // 16, 3 * (b - 1) * (b + 3) // 32], [3 * (b - 1) * (3 * b + 5) // 8, (b + 3) ** 2 // 16]]6465def matmul(a, c):66    return [[sum(a[i][k] * c[k][j] for k in range(len(c))) for j in range(len(c[0]))] for i in range(len(a))]6768def word_count(word, letter, centre):69    m = None70    for b in reversed(word):71        x = letter(b)72        m = x if m is None else matmul(m, x)73    return m[centre][centre]7475def brute(word, code):76    side = math.prod(word)77    target = 3 * (side - 1) // 278    keep = [code >> p & 1 for p in range(8)]7980    def ok(x, y, z):81        for b in reversed(word):82            if not keep[(x % b & 1) | (y % b & 1) << 1 | (z % b & 1) << 2]:83                return False84            x, y, z = x // b, y // b, z // b85        return True8687    return sum(ok(x, y, target - x - y) for x in range(side) for y in range(max(0, target - x - side + 1), min(side, target - x + 1)))8889# THE WORDS9091def verb_words():92    print("WORDS: brute-force slice counts against the carry product, finest letter on the left")93    expect = {(3, 5): 60, (5, 3): 72, (3, 5, 7): 2412, (7, 5, 3): 2688, (5, 7): 300}94    bad = []95    for word in [(3, 5), (5, 3), (3, 5, 7), (7, 5, 3), (5, 7), (7, 5), (3, 3, 5), (5, 3, 3), (3, 7, 5), (5, 7, 9), (9, 7, 5), (3, 3, 3)]:96        x = brute(word, 23)97        y = word_count(word, automaton, 1)98        z = word_count(word, block, 0)99        if not x == y == z or expect.get(word, x) != x:100            bad.append(word)101        print("word=%s brute=%d automaton=%d block=%d" % (word, x, y, z))102    for code in (105, 150, 126, 127, 7, 129, 255):103        for word in [(3, 5), (5, 3), (3, 5, 7), (7, 5, 3)]:104            x, y = brute(word, code), word_count(word, lambda b: automaton(b, weights(code)), 1)105            if x != y:106                bad.append((code, word))107        print("code=%d words (3,5) (5,3) (3,5,7) (7,5,3): %s" % (code, [brute(wd, code) for wd in [(3, 5), (5, 3), (3, 5, 7), (7, 5, 3)]]))108    leak = [b for b in range(3, 42, 2) if any(at(digit_polynomial(b, (1, 3, 3, 1)), c + 3 * (b - 1) // 2 - b * d) for c in (-1, 0, 1) for d in (-2, 2))]109    print("no carry leaves abs(c) <= 1 for the full cube at odd b = 3..41: %s" % (not leak))110    print("mismatches=%s" % bad)111112# THE LETTER, SYMBOLIC113114@lru_cache(maxsize=None)115def symbolic_coefficient(k, c, d, parity):116    if (c + d + parity + 1 - k) % 2:117        return sp.Integer(0), 2118    t = (c + 3 * (N - 1) - (2 * N - 1) * d - k) / 2119    total, start = sp.Integer(0), 2120    for size in range(4):121        for sub in combinations(range(3), size):122            x = sp.expand(t - sum(N - (1 if i < k else 0) for i in sub))123            poly = sp.Poly(x, N)124            alpha, beta = poly.coeff_monomial(N), poly.coeff_monomial(1)125            if alpha > 0:126                total += (-1) ** size * (x + 2) * (x + 1) / 2127                start = max(start, int(sp.ceiling(-beta / alpha)))128            else:129                start = max(start, int(sp.floor(-beta / alpha)) + 1)130    return sp.expand(total), start131132def symbolic_block(w, parity):133    coef, start = {}, 2134    for name, (c, d) in FIVE.items():135        total = sp.Integer(0)136        for k in range(4):137            if w[k]:138                x, s0 = symbolic_coefficient(k, c, d, parity)139                total += w[k] * x140                start = max(start, s0)141        coef[name] = sp.expand(total)142    s = sp.Matrix([[coef["g"], coef["g+b"]], [2 * coef["g+1"], coef["g+b-1"] + coef["g+b+1"]]])143    return s, start144145def symbolic_fill(w):146    return sp.expand(sum(w[k] * N ** (3 - k) * (N - 1) ** k for k in range(4)))147148def in_b(expr):149    return sp.expand(expr.subs(N, (B + 1) / 2))150151def parity_masses(w, parity):152    even, odd = R(w[0] + w[2], 4), R(w[1] + w[3], 4)153    return (odd, even) if parity == 0 else (even, odd)154155def limit_letter(u, v):156    return sp.Matrix([[3 * u / 4, v / 8], [3 * v / 2, u / 4]])157158def perron(m):159    lam = max(m.eigenvals(), key=lambda e: sp.N(e))160    right = (m - lam * sp.eye(2)).nullspace()[0]161    left = (m.T - lam * sp.eye(2)).nullspace()[0]162    return sp.radsimp(lam), right, left163164def first_order(a, r):165    lam, right, left = perron(a)166    return sp.radsimp(sp.simplify((left.T * r * right)[0] / (lam * (left.T * right)[0]))), lam167168CLASS = {0: "b = 3 mod 4", 1: "b = 1 mod 4"}169170def expansion(parity):171    s, start = symbolic_block(CODE, parity)172    a = s.applyfunc(lambda e: sp.Poly(in_b(e), B).coeff_monomial(B**2))173    first = s.applyfunc(lambda e: sp.Poly(in_b(e), B).coeff_monomial(B))174    second = s.applyfunc(lambda e: sp.Poly(in_b(e), B).coeff_monomial(1))175    return s, start, a, first, second176177def verb_letter():178    print("LETTER: the carry block of one letter over b^2 as an exact quadratic in t = 1/b, and its limit")179    for parity in (0, 1):180        s, start, a, first, second = expansion(parity)181        bad = []182        for b in range(3, 102, 2):183            n = (b + 1) // 2184            if n % 2 != parity:185                continue186            if n >= start and sp.Matrix(s.subs(N, n)) != sp.Matrix(block(b)):187                bad.append(b)188            if sp.Matrix(spectra_block(b)) != sp.Matrix(block(b)):189                bad.append(("spectra", b))190        print("%s: S_b/b^2 = A + B t + B_2 t^2 = %s + t %s + t^2 %s, extraction stable from b >= %d, mismatches at odd b = 3..101: %s" % (CLASS[parity], a.tolist(), first.tolist(), second.tolist(), 2 * start - 1, bad))191        u, w = parity_masses(CODE, parity)192        q = {0: R(1, 4), 1: R(3, 4)}193        f = {-1: R(1, 8), 0: R(3, 4), 1: R(1, 8)}194        three = all(sp.Poly(in_b(sum(CODE[k] * symbolic_coefficient(k, c, d, parity)[0] for k in range(4))), B).coeff_monomial(B**2) == f[d] * q[(c + d + 1 - parity) % 2] for c in (-1, 0, 1) for d in (-1, 0, 1))195        fb = sp.Poly(in_b(symbolic_fill(CODE)), B)196        print("  M_b[c, c']/b^2 -> f(c') q(c + c' + g) on all nine carries, f = 1/8, 3/4, 1/8, q = 1/4 even, 3/4 odd: %s; fill/b^3 = %s (1 + (%s)/b + O(b^-2))" % (three, fb.coeff_monomial(B**3), fb.coeff_monomial(B**2) / fb.coeff_monomial(B**3)))197        lam, _, _ = perron(a)198        print("  limit = [[3u/4, v/8], [3v/2, u/4]] with u = %s, v = %s: %s; trace %s, det %s, lambda = %s = %.6f" % (u, w, a == limit_letter(u, w), a.trace(), a.det(), lam, float(lam)))199        t = in_b(s.trace())200        dt = in_b(s.det())201        root = sp.factor(t / 2) + sp.sqrt(sp.factor(t**2 / 4 - dt))202        print("  exact root rho_b = %s, disc/16 = %s" % (sp.simplify(root).subs(sp.Abs(B - 1), B - 1), sp.factor(t**2 - 4 * dt) / 16))203        mu, _ = first_order(a, first)204        print("  rho_b/b^2 = lambda (1 + mu/b + O(b^-2)), mu = %s" % mu)205        print("  (log b)(log_b rho_b - log_b fill + 1) = log(2 lambda) + (mu - 3/2)/b + O(b^-2) = %.6f + (%s)/b, sign %s" % (math.log(2 * float(lam)), sp.radsimp(mu - R(3, 2)), "+" if 2 * lam > 1 else "-"))206    a3, a1 = expansion(0)[2], expansion(1)[2]207    lam, _, _ = perron(a1 * a3)208    print("pair: lambda(A_1 A_3) = %s, per letter sqrt = %.6f; [A_3, A_1] = %s" % (lam, math.sqrt(float(lam)), (a3 * a1 - a1 * a3).tolist()))209210# THE DRIFT211212def ink_logs(sides, marks, rows):213    v, scale, side2, out = [1.0, 0.0], 0.0, 0.0, {}214    for i, b in enumerate(sides, 1):215        s = spectra_block(b)216        x = [[s[0][0] / b**2, s[0][1] / b**2], [s[1][0] / b**2, s[1][1] / b**2]]217        if rows:218            v = [v[0] * x[0][0] + v[1] * x[1][0], v[0] * x[0][1] + v[1] * x[1][1]]219        else:220            v = [x[0][0] * v[0] + x[0][1] * v[1], x[1][0] * v[0] + x[1][1] * v[1]]221        top = max(v)222        v = [y / top for y in v]223        scale += math.log(top)224        side2 += 2 * math.log(b)225        if i in marks:226            out[i] = scale + math.log(v[0]) - math.log(0.75 + 0.25 * math.exp(-side2))227    return out228229WORDS = {230    "sides 3, 7, 11, .. coarsest first": (lambda k: 4 * k - 1, False),231    "sides 5, 9, 13, .. coarsest first": (lambda k: 4 * k + 1, False),232    "sides 3, 5, 7, .. coarsest first": (lambda k: 2 * k + 1, False),233    "sides 3, 5, 7, .. finest first": (lambda k: 2 * k + 1, True),234}235236def exponents():237    a3, b3 = expansion(0)[2:4]238    a1, b1 = expansion(1)[2:4]239    mu3, l3 = first_order(a3, b3)240    mu1, l1 = first_order(a1, b1)241    nu, lp = first_order(a1 * a3, b1 * a3 + a1 * b3)242    nu2, _ = first_order(a3 * a1, b3 * a1 + a3 * b1)243    return {"3": (l3, mu3 / 4), "1": (l1, mu1 / 4), "pair": (sp.sqrt(lp), nu / 4), "pair reversed": (sp.sqrt(lp), nu2 / 4)}, (a3, a1, b3, b1)244245def verb_drift():246    print("DRIFT: first-order perturbation of the limiting letter, then local fits at two lengths")247    ex, (a3, a1, b3, b1) = exponents()248    print("first-order term identical in both classes: %s = (3/8) [[1, 1/2], [2, 1]]: %s" % (b3.tolist(), b3 == b1 == R(3, 8) * sp.Matrix([[1, R(1, 2)], [2, 1]])))249    for key, (lam, gamma) in ex.items():250        print("%s: lambda = %s, gamma = %s = %.9f" % (key, sp.nsimplify(lam), sp.radsimp(gamma), float(gamma)))251    marks = [4000, 8000, 16000, 32000]252    keys = ["3", "1", "pair", "pair"]253    for (name, (side, rows)), key in zip(WORDS.items(), keys):254        lam, gamma = map(float, ex[key])255        out = ink_logs([side(k) for k in range(1, marks[-1] + 1)], set(marks), rows)256        est = [(out[2 * m] - out[m] - m * math.log(lam)) / math.log(2) for m in marks[:-1]]257        rich = [2 * y - x for x, y in zip(est, est[1:])]258        print("%s: derived gamma %.6f, local fits L -> 2L at L = 4000, 8000, 16000: %s; Richardson at 8000, 16000: %s" % (name, gamma, ", ".join("%.6f" % e for e in est), ", ".join("%.6f" % e for e in rich)))259260# THE CONSTANTS261262def neville(xs, ys):263    p = list(ys)264    for k in range(1, len(xs)):265        for i in range(len(xs) - 1, k - 1, -1):266            p[i] = (p[i] * xs[i - k] - p[i - 1] * xs[i]) / (xs[i - k] - xs[i])267    return p[-1]268269def constants_along(side, rows, marks, lam, gamma):270    v, scale, side2, out = [mp.mpf(1), mp.mpf(0)], mp.mpf(0), mp.mpf(0), {}271    for i in range(1, max(marks) + 1):272        b = side(i)273        s = spectra_block(b)274        bb = mp.mpf(b) ** 2275        x = [[s[0][0] / bb, s[0][1] / bb], [s[1][0] / bb, s[1][1] / bb]]276        if rows:277            v = [v[0] * x[0][0] + v[1] * x[1][0], v[0] * x[0][1] + v[1] * x[1][1]]278        else:279            v = [x[0][0] * v[0] + x[0][1] * v[1], x[1][0] * v[0] + x[1][1] * v[1]]280        top = max(v)281        v = [y / top for y in v]282        scale += mp.log(top)283        side2 += 2 * mp.log(b)284        if i in marks:285            out[i] = mp.exp(scale + mp.log(v[0]) - mp.log(mp.mpf(3) / 4 + mp.exp(-side2) / 4) - i * mp.log(lam) - gamma * mp.log(i))286    return out287288def blink(a3, a1):289    lam, right, _ = perron(a1 * a3)290    coarse = sp.radsimp((a3 * right)[0] / (sp.sqrt(lam) * right[0]))291    lam, _, left = perron(a3 * a1)292    fine = sp.radsimp((left.T * a3)[0] / (sp.sqrt(lam) * left[0]))293    return coarse, fine294295def verb_constants():296    print("CONSTANTS: ink / (lambda^L L^gamma) at L = 2^j, Neville-extrapolated in 1/L to two depths")297    mp.mp.dps = 40298    ex, (a3, a1, _, _) = exponents()299    keys = ["3", "1", "pair", "pair"]300    found = {}301    for (name, (side, rows)), key in zip(WORDS.items(), keys):302        lam, gamma = (mp.mpf(sp.N(x, 50)) for x in ex[key])303        lengths = [256 * 2**j for j in range(7)]304        for shift, tag in ((0, "even L"), (1, "odd L")):305            if key != "pair" and shift:306                continue307            marks = [m + shift for m in lengths]308            out = constants_along(side, rows, set(marks), lam, gamma)309            xs = [mp.mpf(1) / m for m in marks]310            ys = [out[m] for m in marks]311            deep, shallow = neville(xs, ys), neville(xs[:-1], ys[:-1])312            digits = int(-mp.log10(abs(deep - shallow) / deep)) if deep != shallow else 40313            found[name, tag] = deep314            print("%s, %s: C(L=%d) = %s; extrapolated %s and %s, agreeing to %d digits" % (name, tag, marks[-1], mp.nstr(ys[-1], 12), mp.nstr(deep, 18), mp.nstr(shallow, 18), digits))315    coarse, fine = blink(a3, a1)316    for name, exact in (("sides 3, 5, 7, .. coarsest first", coarse), ("sides 3, 5, 7, .. finest first", fine)):317        ratio = found[name, "odd L"] / found[name, "even L"]318        print("%s: blink C_odd/C_even = %s, derived %s = %s" % (name, mp.nstr(ratio, 15), sp.nsimplify(exact), mp.nstr(mp.mpf(sp.N(exact, 50)), 15)))319    print("row word, finest-first over coarsest-first: even L %s, odd L %s" % (mp.nstr(found["sides 3, 5, 7, .. finest first", "even L"] / found["sides 3, 5, 7, .. coarsest first", "even L"], 15), mp.nstr(found["sides 3, 5, 7, .. finest first", "odd L"] / found["sides 3, 5, 7, .. coarsest first", "odd L"], 15)))320321# THE DESIGNS322323def exact_sign(s, q):324    if s[0][1] * s[1][0] == 0:325        if s[0][0] == 0:326            return None327        return (s[0][0] > q) - (s[0][0] < q)328    t = s[0][0] + s[1][1]329    chi = q * q - t * q + s[0][0] * s[1][1] - s[0][1] * s[1][0]330    if 2 * q < t or chi < 0:331        return 1332    return 0 if chi == 0 else -1333334def last_root(p):335    p = sp.Poly(sp.expand(p), N)336    if p.is_zero or p.degree() == 0:337        return 0338    ends = [hi for (lo, hi), _ in p.intervals()]339    return int(math.ceil(max(ends))) + 1 if ends else 0340341def eventual(w, parity):342    s, start = symbolic_block(w, parity)343    f = symbolic_fill(w)344    if s[0, 1] == 0:345        polys, guard = [(2 * N - 1) * s[0, 0] - f], s[0, 0]346    else:347        t, d = s.trace(), s.det()348        polys, guard = [t * (2 * N - 1) - 2 * f, f**2 - t * f * (2 * N - 1) + d * (2 * N - 1) ** 2], s[0, 1] * s[1, 0]349    roots = max(last_root(p) for p in polys + [guard])350    zeros = [r for r in sp.Poly(sp.expand(guard), N).real_roots()]351    top = max(start, roots)352    n = top + 2 + (top + parity) % 2353    b = 2 * n - 1354    return exact_sign([[int(x) for x in row] for row in s.subs(N, n).tolist()], Fraction(int(f.subs(N, n)), b)), b, start, roots, max(zeros) if zeros else None355356def verb_designs():357    print("DESIGNS: all 256 dim 3 parity designs at infinite side, and the sign of the census exponent against solid dimension minus 1 at every odd base")358    classes = {}359    for code in range(1, 256):360        classes.setdefault(weights(code), []).append(code)361    tally, mism, late, law, reach, flat, guards, blind = {}, [], [], 0, [0, 0, 0], [], {}, set()362    for w, codes in sorted(classes.items()):363        e, o = w[0] + w[2], w[1] + w[3]364        row = []365        for parity in (0, 1):366            u, v = parity_masses(w, parity)367            lam = (2 * u + sp.sqrt(u**2 + 3 * v**2)) / 4368            s, start = symbolic_block(w, parity)369            for b in range(2 * start - 1, 62, 2):370                if ((b + 1) // 2) % 2 == parity and [[int(x) for x in r] for r in s.subs(N, (b + 1) // 2).tolist()] != block(b, w):371                    mism.append((w, b, "form"))372            if s.applyfunc(lambda x: sp.Poly(in_b(x), B).coeff_monomial(B**2)) != limit_letter(u, v):373                mism.append((w, parity, "limit"))374            sign, b_star, start, roots, zero = eventual(w, parity)375            if zero is not None:376                guards[w, parity] = zero377            if s[0, 0] == 0 and s[1, 1] == 0:378                blind.update(codes)379            reach = [max(reach[0], start), max(reach[1], b_star), max(reach[2], roots)]380            predicted = int(sp.sign(u - v))381            if sign != predicted or predicted != int(sp.sign(o - e)) * (1 - 2 * parity):382                mism.append((w, parity, "sign"))383            for b in range(3, b_star + 1, 2):384                if ((b + 1) // 2) % 2 == parity:385                    x = exact_sign(block(b, w), Fraction(fill(b, w), b))386                    if x != sign:387                        late.append((w, b, x, sign))388                    if x != sign and not (x is None and sign == -1):389                        law += len(codes)390            row.append((sign, lam))391        if e == o:392            for b in range(3, 42, 2):393                m = automaton(b, w)394                if any(sum(r) * b != fill(b, w) for r in m):395                    flat.append((w, b))396        key = (row[0][0], row[1][0])397        tally[key] = tally.get(key, 0) + len(codes)398        print("weights=%s e=%d o=%d designs=%d: 8 lambda/(e + o) = %.6f at 3 mod 4, %.6f at 1 mod 4, sign %s" % (w, e, o, len(codes), float(8 * row[0][1] / (e + o)), float(8 * row[1][1] / (e + o)), key))399    print("tally of signs (3 mod 4, 1 mod 4) over codes 1..255: %s" % dict(sorted(tally.items())))400    print("symbolic forms stable from b >= %d; every real root of every sign polynomial below n = %d, b = %d; every odd base up to b = %d checked exactly" % (2 * reach[0] - 1, reach[2], 2 * reach[2] - 1, reach[1]))401    print("largest real root of the case guard, s00 on a triangular class and s01 s10 otherwise: %s at %s" % ((max(guards.values()), max(guards, key=guards.get)) if guards else "none"))402    print("codes whose block has a zero diagonal on a class, count zero at every odd level there: %d" % len(blind))403    print("odd bases where the exact sign differs from the large-side sign: %s (None is an empty slice)" % late)404    print("designs violating sign = sgn(o - e) at 3 mod 4 and sgn(e - o) at 1 mod 4, an empty slice counted below: %d" % law)405    print("e = o designs with an automaton row sum other than fill/b at odd b = 3..41: %s" % flat)406    print("mismatches=%s" % mism)407408# THE CLOSED FORM AT SIDES 3 MOD 4409410def verb_closed():411    print("CLOSED: sides 3, 7, 11, .. coarsest first, the generating function and the constant")412    k, z = sp.symbols("k z")413    a = sp.Matrix([[18, 1], [12, 6]])414    c = sp.Matrix([[-6, 1], [0, 0]])415    b = 4 * k - 1416    letter = sp.Matrix([[3 * (b + 1) * (3 * b - 1) / 16, (b + 1) * (b + 5) / 32], [3 * (b + 1) ** 2 / 8, 3 * (b + 1) ** 2 / 16]])417    print("S_(4k-1) = (k/2)(k K_1 + K_0) with K_1 = %s, K_0 = %s: %s" % (a.tolist(), c.tolist(), sp.expand(letter - k / 2 * (k * a + c)) == sp.zeros(2)))418    d = 1 - 24 * z + 96 * z**2419    p = sp.Matrix([1 - 6 * z, 12 * z])420    lhs = (sp.eye(2) - z * a) * (d * p.diff(z) - R(3, 4) * d.diff(z) * p)421    rhs = d * (a + c) * p422    print("W = (1 - 24z + 96z^2)^(-3/4) (1 - 6z, 12z) solves (1 - z K_1) W' = (K_1 + K_0) W, W(0) = e_0: %s" % (sp.expand(lhs - rhs) == sp.zeros(2, 1)))423    y = [Fraction(1), Fraction(18)]424    for m in range(1, 60):425        y.append(((24 * m + 18) * y[m] - (96 * m + 48) * y[m - 1]) / (m + 1))426    v, bad = [1, 0], []427    for L in range(1, 61):428        s = spectra_block(4 * L - 1)429        v = [s[0][0] * v[0] + s[0][1] * v[1], s[1][0] * v[0] + s[1][1] * v[1]]430        series = y[L] - 6 * y[L - 1]431        if Fraction(math.factorial(L) ** 2, 2**L) * series != v[0]:432            bad.append(L)433        if L <= 4:434            print("L=%d count=%d" % (L, v[0]))435    print("count_L = (L!)^2 2^(-L) [z^L] (1 - 6z)(1 - 24z + 96z^2)^(-3/4) at L = 1..60: mismatches=%s" % bad)436    mp.mp.dps = 40437    exact = mp.gamma(mp.mpf(3) / 4) * (1 + mp.sqrt(3)) / (3 * (mp.sqrt(3) - 1) ** (mp.mpf(3) / 4))438    lam = (3 + mp.sqrt(3)) / 8439    marks = [256 * 2**j for j in range(7)]440    out = constants_along(lambda i: 4 * i - 1, False, set(marks), lam, mp.mpf(1) / 4)441    print("C_3 = Gamma(3/4)(1 + sqrt(3))/(3 (sqrt(3) - 1)^(3/4)) = %s; extrapolated %s" % (mp.nstr(exact, 25), mp.nstr(neville([mp.mpf(1) / m for m in marks], [out[m] for m in marks]), 20)))442443# RUN444445VERBS = {"words": verb_words, "letter": verb_letter, "drift": verb_drift, "constants": verb_constants, "closed": verb_closed, "designs": verb_designs}446447if __name__ == "__main__":448    for name in sys.argv[1:] or list(VERBS):449        start = time.time()450        VERBS[name]()451        print("%s: %.1fs" % (name, time.time() - start))