The ledger file frc/ledgers/p29_finitism.py of The Undeclared Posit of Potential Infinity, rendered with an anchor per line: the marked lines (# 29:C2 (p29010): a predicate and its accession key) are the checks that decide the predicates of the paper's predicate ledger — 13 of 13 checks passing; the predicates' theorems are the declarations of Finitism in the core. ▶ run the predicates on Google Colab.
1"""p29_finitism — the ledger file of 29-finitism (9 October 2026).23"The Undeclared Posit of Potential Infinity" (Akhtman, preprint pp202607.0670.v1). The paper's predicate ledger (Appendix A)4is docs/29-finitism/29-finitism-ledger.json. This file binds its predicates to the framework: the table of keys5(generated from the ledger by ci/make_ledgers.py), the test data, and the thirteen checks of four blocks, which call the6logic theme (frc/logic.py, frc/formation.py). Each check names the predicate(s) it witnesses (LEDGER) under a7`# 29:XN (<key>)` marker on the check that decides it (PREDICATES). The paper has no earlier validation package: this8file is its first witness, written with the ledger. The Lean side is the certificate9lean/FrcCore/Ledgers/P29Finitism.lean over the logic and foundation themes' keys.1011 python3 -m frc.ledgers.p29_finitism every block, the census; exit 1 if a check fails (≈ 30 s)12 python3 -m frc.ledgers.p29_finitism C one block (A, B, C or D)13 from frc.ledgers.p29_finitism import R; R.predicate("29:C2") one predicate: its blocks run once per session1415Blocks: A the exhibits: the finite frame, Q, induction EXACT (29:B4–B6)16 B empirical idleness: records, the minimal realization, padding EXACT (29:C1–C4)17 C the boundary and the buffer frame EXACT (29:C6–C8, C10)18 D bounded actualism: conservativity and determinacy EXACT (29:E2, E4; X1, X2)1920The notebook frc/ledgers/p29_finitism.ipynb runs one predicate per cell, the cell's id its key (gate G13).21"""22import random, sys23from itertools import product2425from frc.registry import Registry26from frc.logic import fval, table, random_formula, random_structure, successor_counterexample27from frc.formation import (passes, minimal, pad, double, swap, is_automorphism, count_invariant, swap_invariant, buffer,28 chain, reachable, least_below, finite_induction_holds, records, record, random_universe,29 random_passed_trace, sval2, sval2_table, so_arities, random_sformula, closed,30 d0_eval, d0_eval_frame, d0_bound, random_d0)3132# ---- generated by ci/make_ledgers.py from docs/29-finitism/29-finitism-ledger.json; edit the ledger, not this table ----33PAPER = "29-finitism"34KEYS = {"A1": "p29001", "A2": "p29002", "B1": "p29003", "B2": "p29004", "B3": "p29005", "B4": "p29006", "B5": "p25010", "B6": "p29007", "B7": "p29008", "C1": "p29009", "C2": "p29010", "C3": "p29011", "C4": "p29012", "C5": "p29013", "C6": "p29014", "C7": "p29015", "C8": "p29016", "C9": "p29017", "C10": "p05013", "D1": "p29018", "D2": "p29019", "D3": "p29020", "E1": "p29021", "E2": "p29022", "E3": "p29023", "E4": "p29024", "E5": "p29025", "X1": "p29026", "X2": "p29027"} # every row of the ledger: its label and its accession key35LEAN = {"B4": "core", "B5": "core", "B6": "core", "C2": "core", "C3": "core", "C4": "core", "C6": "core", "C7": "core", "C8": "core", "C10": "core", "E2": "core", "E4": "core", "X1": "core", "X2": "core"} # the rows with a Lean declaration: the libraries whose key files prove them36# ---- end of the generated table ----3738LEAN_ONLY = () # the predicates with a Lean declaration and no python check (gate G12): none3940# The paper's predicate ledger (Appendix A, predicates cited as 29:XN): the predicate(s) each check witnesses.41LEDGER = {42 "A1": "29:B4", "A2": "29:B5", "A3": "29:B6",43 "B1": "29:C1", "B2": "29:C2", "B3": "29:C3", "B4": "29:C4",44 "C1": "29:C6", "C2": "29:C7", "C3": "29:C8, 29:X1", "C4": "29:C10",45 "D1": "29:E2, 29:X2", "D2": "29:E4",46}4748BLOCK = {"A": "the exhibits: the finite frame, Q, induction", # check-id prefix -> the block (the function block_<letter> below)49 "B": "empirical idleness: records, the minimal realization, padding",50 "C": "the boundary and the buffer frame",51 "D": "bounded actualism: conservativity and determinacy"}5253# the deciding check of each witnessed predicate (the other checks that touch it are corroboration)54PREDICATES = {55 "29:B4": "A1", "29:B5": "A2", "29:B6": "A3",56 "29:C1": "B1", "29:C2": "B2", "29:C3": "B3", "29:C4": "B4",57 "29:C6": "C1", "29:C7": "C2", "29:C8": "C3", "29:X1": "C3", "29:C10": "C4",58 "29:E2": "D1", "29:X2": "D1", "29:E4": "D2",59}6061R = Registry("29", "finitism", LEDGER, PREDICATES, sources=[__file__])6263SEED = 2964ALPHABETS = (2, 3, 5, 32) # s, the letters of an agent's alphabet65CAPACITIES = range(0, 12) # K, the record length6667# ------------------------------------------------------------------------------------------------------------68# block A: the exhibits (29:B4, B5, B6)69# Section 2 of the paper: a finite initial segment of arithmetic (truncated successor, sum and product as graphs) has a70# complete and decidable theory and carries no injective successor missing 0; the cyclic variant's successor act is total71# and makes nothing new; Robinson's Q has no finite model; on every finite frame the least-number principle and the72# induction schema hold for all subsets.73@R.block("A", BLOCK["A"])74def block_A():75 """Block A — the exhibits (EXACT): A1–A3."""76 rng = random.Random(SEED)77 # A1 the finite segment [0, m) with the graphs of the truncated successor, sum and product: every sentence or its78 # negation holds (decided by exhaustive evaluation, frc.logic.fval, and by the table method); no map of [0, m) into79 # itself is injective and misses 0; the cycle: x -> x+1 mod m is a bijection, one m-cycle, every object an image (29:B4)80 ok = True; det = []81 for m in range(1, 5):82 def rel(r, args, m=m):83 if r == 0: return len(args) == 2 and args[0] < m and args[1] == args[0] + 1 # successor's graph, overflow fails84 if r == 1: return len(args) == 3 and args[0] + args[1] == args[2] # sum's graph85 if r == 2: return len(args) == 3 and args[0] * args[1] == args[2] # product's graph86 return False87 M = (m, rel)88 for _ in range(40):89 phi = random_formula(rng, 3, 1)90 sent = ("all", phi)91 v = fval(M, (), sent)92 ok &= (v != fval(M, (), ("neg", sent))) # complete and consistent93 ok &= v == (() in table(M, sent, 0)) # decided a second way94 ok &= successor_counterexample(m) is None95 cyc = [(x + 1) % m for x in range(m)]96 ok &= sorted(cyc) == list(range(m)) # a bijection: nothing new97 x, seen = 0, []98 while x not in seen: seen.append(x); x = cyc[x]99 ok &= len(seen) == m and x == 0 # one m-cycle, back to the start100 det.append(f"m={m}: 40 sentences decided two ways, no injective successor missing 0, one {m}-cycle")101 # 29:B4 (p29006)102 R.check("A1", "the finite segment: complete and decidable theory (two evaluators agree on 160 sentences), no injective successor missing 0; the cycle: total, bijective, one m-cycle", ok, "; ".join(det))103104 # A2 no finite structure interprets Q: on n <= 7 no injective map of [0, n) into itself misses an element (all n^n maps);105 # on n <= 3 no (domain D, zero Z, successor relation Sg) satisfies totality on D, Q2 injectivity and Q1 (Sg never reaches106 # a zero) — all 2^n domains, 2^n zero sets and 2^(n^2) relations (29:B5)107 ok = all(successor_counterexample(n) is None for n in range(1, 8))108 found = 0109 for n in range(1, 4):110 for D in product([False, True], repeat=n):111 if not any(D): continue112 for Z in product([False, True], repeat=n):113 if not any(D[z] and Z[z] for z in range(n)): continue114 for Sg in product([False, True], repeat=n * n):115 S = lambda x, y: Sg[x * n + y]116 tot = all(any(D[y] and S(x, y) for y in range(n)) for x in range(n) if D[x])117 inj = all(x == x2 for x in range(n) for x2 in range(n) for y in range(n)118 if D[x] and D[x2] and S(x, y) and S(x2, y))119 q1 = all(not Z[y] for x in range(n) for y in range(n) if D[x] and D[y] and S(x, y))120 if tot and inj and q1: found += 1121 ok &= found == 0122 # 29:B5 (p25010)123 R.check("A2", "no finite structure interprets Q: no injective successor missing 0 on n <= 7 (all n^n maps); no relational interpretation (D, Z, Sg) with totality, Q2 and Q1 on n <= 3", ok,124 f"relational interpretations found: {found}")125126 # A3 induction is a theorem of every finite frame: every nonempty subset of [0, n) has a least element, and the induction127 # schema holds for 500 random properties (the least counterexample refutes a closed-under-successor failure) (29:B6)128 ok = True129 for _ in range(500):130 n = rng.randrange(0, 16); P = [rng.randrange(2) == 0 for _ in range(n)]131 ok &= finite_induction_holds(P)132 fails = [x for x in range(n) if not P[x]]133 ok &= least_below([not p for p in P], n) == (fails[0] if fails else None)134 ok &= all(least_below(P, n) is None or (P[least_below(P, n)] and not any(P[y] for y in range(least_below(P, n)))) for _ in (0,))135 # 29:B6 (p29007)136 R.check("A3", "on [0, n), n < 16: every nonempty subset has a least element (500 random subsets), and a property true at 0 and closed under successor below n holds below n", ok)137138# ------------------------------------------------------------------------------------------------------------139# block B: empirical idleness (29:C1, C2, C3, C4)140# Section 4: an agent of capacity K over s letters holds fewer than s^(K+1) records; a check that passes in any universe141# passes in the minimal realization of its own trace (t objects, closed); the check is decided by exhaustive evaluation142# of its t^2 atoms and the trace is a record of t^2 symbols; padding by any number of fresh formations keeps it passing.143@R.block("B", BLOCK["B"])144def block_B():145 """Block B — empirical idleness (EXACT): B1–B4."""146 rng = random.Random(SEED + 1)147 # B1 the record count: sum_{i<=K} s^i < s^(K+1), also by the closed form of the geometric sum (29:C1)148 ok = all(records(s, K) < s ** (K + 1) and records(s, K) == (s ** (K + 1) - 1) // (s - 1) for s in ALPHABETS for K in CAPACITIES)149 # 29:C1 (p29009)150 R.check("B1", "fewer than s^(K+1) records of at most K symbols over s letters, s in {2, 3, 5, 32}, K < 12 (48 pairs)", ok)151152 # B2 the minimal realization: 300 random universes of at most 8 objects, a trace that passes in each; the minimal153 # realization has exactly t objects, is closed, and the check passes in it under the identity; on t <= 3 it is among154 # all universes on t objects that realize the trace (29:C2)155 ok = True; n_traces = 0; searched = 0156 for _ in range(300):157 U = random_universe(rng, rng.randrange(2, 9))158 T, e = random_passed_trace(rng, U); t = T[0]159 assert passes(T, U, e)160 M = minimal(T)161 ok &= M[0] == t and closed(M) and passes(T, M, list(range(t)))162 if t <= 3:163 found = [list(f) for f in product([None] + list(range(t)), repeat=t) if passes(T, (t, list(f)), list(range(t)))]164 ok &= M[1] in found; searched += 1165 n_traces += 1166 # 29:C2 (p29010)167 R.check("B2", "a passed check passes in the finite universe of its own trace, t(r) objects, closed, read by the identity: 300 random traces; on t <= 3 the minimal realization found by exhaustive search", ok,168 f"{n_traces} traces, {searched} searched exhaustively")169170 # B3 the asymmetry: the check reads t^2 atoms and terminates (its evaluation is a finite conjunction, counted), and the171 # trace's atom table is a record of t^2 symbols; retained when t^2 <= K (29:C3)172 ok = True; cnt = 0173 for _ in range(200):174 U = random_universe(rng, rng.randrange(1, 8))175 T, e = random_passed_trace(rng, U); t = T[0]176 rec = record(T)177 ok &= len(rec) == t * t178 reads = sum(1 for i in range(t) for j in range(t)) # the atoms the check reads179 ok &= reads == t * t and passes(T, U, e)180 ok &= (t * t <= 8) == (len(rec) <= 8) # retained by an agent of capacity 8 iff t^2 <= 8181 cnt += 1182 # 29:C3 (p29011)183 R.check("B3", "the check of a trace evaluates its t^2 atoms and terminates; the trace is itself a record of t^2 symbols, retained by an agent of capacity K iff t^2 <= K (200 traces)", ok, f"{cnt} traces")184185 # B4 padding: a passed check passes after any number of fresh formations, so for every B a realizing universe of more186 # than B objects exists; the padded universe stays closed (29:C4)187 ok = True188 for _ in range(300):189 U = random_universe(rng, rng.randrange(1, 8))190 T, e = random_passed_trace(rng, U); t = T[0]191 M = minimal(T)192 for B in (0, 1, 5, 40):193 P = pad(M, B + 1)194 ok &= passes(T, P, list(range(t))) and P[0] > B and closed(P)195 ok &= passes(T, pad(U, B + 1), e)196 # 29:C4 (p29012)197 R.check("B4", "a passed check passes unchanged after padding by B + 1 fresh formations, B in {0, 1, 5, 40}, from the minimal realization and from the original universe (300 traces): no bound is entailed", ok)198199# ------------------------------------------------------------------------------------------------------------200# block C: the boundary and the buffer frame (29:C6, C7, C8, C10)201# Lemma boundary: the disjoint double carries the swap, an automorphism without fixed points; a swap-invariant condition202# has an even number of satisfiers; the minimal realization holds only trace objects and a datum never formed has no203# preimage. Proposition illusion: the buffer frame of sigma seeds and D rounds. O3: the pigeonhole on records.204@R.block("C", BLOCK["C"])205def block_C():206 """Block C — the boundary and the buffer frame (EXACT): C1–C4."""207 rng = random.Random(SEED + 2)208 # C1 the double and its swap: an automorphism, fixed-point-free, of order two; the check passes in the double read in the209 # first copy; 1,500 swap-invariant conditions have an even number of satisfiers, never one (29:C6)210 ok = True; conds = 0211 for _ in range(300):212 U = random_universe(rng, rng.randrange(1, 8)); n = U[0]213 W = double(U)214 sigma = [swap(U, x) for x in range(2 * n)]215 ok &= is_automorphism(W, sigma) and all(sigma[x] != x and sigma[sigma[x]] == x for x in range(2 * n))216 T, e = random_passed_trace(rng, U)217 ok &= passes(T, W, e)218 for _ in range(5):219 D0 = [rng.randrange(2) == 0 for _ in range(n)]; D = D0 + D0220 ok &= swap_invariant(W, D)221 c = count_invariant(W, D)222 ok &= c == 2 * sum(D0) and c != 1; conds += 1223 # 29:C6 (p29014)224 R.check("C1", "the double of a universe carries the swap: an automorphism, no fixed point, order two; the check passes in the double; a swap-invariant condition has an even number of satisfiers, never exactly one", ok,225 f"300 doubles, {conds} invariant conditions")226227 # C2 the minimal realization confines: it has exactly the trace's t objects; a datum x the trace never forms has no228 # preimage in it (29:C7)229 ok = True; cases = 0230 for _ in range(300):231 U = random_universe(rng, rng.randrange(1, 8))232 T, e = random_passed_trace(rng, U); t, atom = T233 M = minimal(T)234 ok &= M[0] == t235 for x in range(t):236 if not any(atom[i][x] for i in range(t)):237 ok &= all(M[1][y] != x for y in range(t)); cases += 1238 # 29:C7 (p29015)239 R.check("C2", "the minimal realization has the trace's objects and nothing else; a datum the trace never forms has no preimage there", ok, f"{cases} unformed data checked")240241 # C3 the buffer frame: sigma seeds and D rounds, sigma(D+1) formations; every object below level D has a fresh image242 # one level up; k acts from a seed reach level k; the objects reachable in r acts are sigma(r+1); the instance243 # (sigma, D) = (2, 17): M = 36 > 2 * 2^4 and D > 2^4 (29:C8); hence "one can always continue" below the horizon (29:X1)244 ok = True; frames = 0245 for sigma in (1, 2, 3):246 for D in (1, 2, 5, 17):247 M, form = buffer(sigma, D)248 ok &= M == sigma * (D + 1)249 seeds = [s * (D + 1) for s in range(sigma)]250 for r in range(D + 1):251 ok &= len(reachable((M, form), seeds, r)) == sigma * (r + 1)252 for s in range(sigma):253 for k in range(D + 1):254 x = chain(sigma, D, s, k)255 ok &= x == s * (D + 1) + k256 if k < D: ok &= form[x] == x + 1 and x + 1 < M and (x + 1) % (D + 1) == x % (D + 1) + 1257 ok &= form[chain(sigma, D, s, D)] is None258 frames += 1259 ok &= 2 * 2 ** 4 < buffer(2, 17)[0] and 2 ** 4 < 17260 # 29:C8 (p29016), 29:X1 (p29026)261 R.check("C3", "the buffer frame (sigma seeds, D rounds): sigma(D+1) formations, every object below level D formed one level up, k acts reach level k, sigma(r+1) objects reachable in r acts; (2, 17): M = 36 > 32, 17 > 16", ok,262 f"{frames} frames")263264 # C4 the pigeonhole: an agent of capacity K over s letters holds fewer than s^(K+1) records; in a frame of M > s^(K+1)265 # formations no reading of the frame into the records is injective — every map [0, M) -> [0, R) with R < M collides,266 # checked on all R^M maps for M <= 5 and at (s, K, M) = (2, 3, 36) by counting (29:C10)267 ok = all(any(f[i] == f[j] for i in range(M) for j in range(i)) for M in range(2, 6) for Rn in range(1, M) for f in product(range(Rn), repeat=M))268 s, K, M = 2, 3, 36269 ok &= records(s, K) < s ** (K + 1) < M and records(s, K) == 15270 # 29:C10 (p05013)271 R.check("C4", "every map of M objects into R < M records collides (all R^M maps, M <= 5); at (s, K, M) = (2, 3, 36) the agent holds 15 < 16 < 36 records, so no injective reading of the frame exists", ok)272273# ------------------------------------------------------------------------------------------------------------274# block D: bounded actualism (29:E2, E4; X2)275# Section 7: certificate conservativity — a Delta_0 sentence takes its standard value in every frame beyond its bound276# (5:B6), every schema instance below the bound is decided by evaluation, induction transfers instance-wise (B6);277# effective determinacy on a finite frame — the full second-order theory decided by exhaustive evaluation.278@R.block("D", BLOCK["D"])279def block_D():280 """Block D — bounded actualism (EXACT): D1–D2."""281 rng = random.Random(SEED + 3)282 # D1 conservativity: 400 random Delta_0 sentences take their standard value in the frames W_N for N = t+1, t+2, t+10283 # above their bound t; 100 first-order sentences over random structures decided two ways; the induction schema on284 # 200 random properties (29:E2); hence no proof practice below the bound is lost (29:X2)285 ok = True; n_d0 = 0286 for _ in range(400):287 phi = random_d0(rng, 3, 0); b = d0_bound((), phi); v = d0_eval((), phi)288 ok &= all(d0_eval_frame(N, (), phi) == v for N in (b + 1, b + 2, b + 10)); n_d0 += 1289 for _ in range(100):290 M = random_structure(rng, rng.randrange(1, 4)); phi = ("all", random_formula(rng, 3, 1))291 ok &= fval(M, (), phi) == (() in table(M, phi, 0))292 for _ in range(200):293 P = [rng.randrange(2) == 0 for _ in range(rng.randrange(0, 12))]294 ok &= finite_induction_holds(P)295 # 29:E2 (p29022), 29:X2 (p29027)296 R.check("D1", "400 Delta_0 sentences keep their standard value in every frame beyond their bound (N = t+1, t+2, t+10); 100 schema instances decided two ways; the induction schema on 200 properties", ok, f"{n_d0} sentences")297298 # D2 effective determinacy on a finite frame: 60 random second-order sentences (set and relation quantifiers of arity299 # 1 and 2) over structures of m <= 3 elements, decided by exhaustive evaluation over the 2^m subsets and the 2^(m^a)300 # relations, and a second way by tables of satisfying assignments; each sentence or its negation holds (29:E4)301 ok = True; n_so = 0302 for _ in range(60):303 m = rng.randrange(1, 4); M = random_structure(rng, m)304 phi = random_sformula(rng, 3, 0, 0, 0)305 ok &= so_arities(phi) == (0, 0, 0)306 v = sval2(M, (), (), (), phi)307 ok &= v == (((), (), ()) in sval2_table(M, phi, 0, 0, 0, 2))308 ok &= sval2(M, (), (), (), ("neg", phi)) != v; n_so += 1309 # 29:E4 (p29024)310 R.check("D2", "the full second-order theory of a finite structure (m <= 3) decided by exhaustive evaluation over its 2^m subsets and 2^(m^a) relations: 60 sentences agree with the table method, each or its negation holds", ok,311 f"{n_so} sentences")312313if __name__ == "__main__":314 want = [a.upper() for a in sys.argv[1:]] or sorted(BLOCK)315 bad = [b for b in want if b not in BLOCK]316 if bad: sys.exit(f"no block {', '.join(bad)}: the blocks are {', '.join(sorted(BLOCK))}")317 for b in want: R.run_block(b)318 sys.exit(0 if R.summary(write=False, expect=list(LEDGER) if want == sorted(BLOCK) else None) else 1)319