Skip to content

feat(ch34): NP-Completeness — theorem layer complete (composition, P⊆NP, ≤_P transitivity, complement, union, intersection) - #156

Closed
TankTechnology wants to merge 36 commits into
mainfrom
feat/ch34-framework
Closed

feat(ch34): NP-Completeness — theorem layer complete (composition, P⊆NP, ≤_P transitivity, complement, union, intersection)#156
TankTechnology wants to merge 36 commits into
mainfrom
feat/ch34-framework

Conversation

@TankTechnology

@TankTechnology TankTechnology commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Green-field Chapter 34 (NP-Completeness), building on Mathlib's
Turing.TM2ComputableInPolyTime (machine-level polynomial-time computability
with Polynomial ℕ time bounds). The theorem layer of Sections 34.1–34.3 is
now complete and kernel-clean.

Section 34.1 — Polynomial Time (framework + closure properties)

  • CLRS.Chapter34.Language / PolyTimeComputable / PolyTimeDecidable /
    ClassP / mem_ClassP.
  • PolyTimeComputable.comp — polytime composition closure, closing Mathlib's
    proof_wanted TM2ComputableInPolyTime.comp via the shared-stack two-phase
    TM2 machine Turing.TM2Comp.compMachine (Composition.lean).
  • PolyTimeDecidable.compl / ClassP_complP closed under complement
    (via the Bool.not machine Turing.TM2Comp.notMachine).
  • PolyTimeDecidable.union / ClassP_union and PolyTimeDecidable.inter /
    ClassP_interP closed under union and intersection, via the AND/OR
    machine Turing.TM2AndOr.andOrMachine (AndOr.lean): a four-phase TM2 that
    duplicates the input onto both deciders' stacks, runs M₁ then M₂
    sequentially, and combines the two Bool results with AND/OR.

Section 34.2 — Polynomial-Time Verification

  • PolyTimeVerifiable / ClassNP / mem_ClassNP.
  • PolyTimeVerifiable.of_decidable and ClassP_subset_ClassNPP ⊆ NP
    (Theorem 34.2), via the pair-projection machine Turing.Prj.prjMachine
    (PairProjection.lean).

Section 34.3 — NP-Completeness and Reducibility

  • PolyTimeReducible / NPHard / NPComplete / ClassNPC.
  • PolyTimeReducible.trans — transitivity of ≤_P via the composition
    closure.

Remaining chapter scope (documented, not sorry)

  • Sections 34.4–34.5 specific reductions (CIRCUIT-SAT, SAT, 3-CNF-SAT,
    CLIQUE, VERTEX-COVER, HAM-CYCLE, SUBSET-SUM) are not yet represented.
  • The empty/universal languages in P as concrete machine constructions.
  • Open problems (P vs NP) are intentionally out of scope.

Verification

  • lake build CLRSLean passes (no sorry/admit; the headline theorems
    depend only on propext/Classical.choice/Quot.sound).
  • check_repository.py and check_progress_csv.py --write-dashboard pass.
  • literate.toml / docs / README / Progress.lean / progress CSV synced.

🤖 Generated with Claude Code

TankTechnology and others added 30 commits August 5, 2026 20:32
- 31.5 chinese_remainder_general: the full k-modulus Chinese remainder
  theorem via Nat.chineseRemainderOfList (existence + uniqueness mod the
  product).
- 31.4 linear_congruence_solutions: the solutions of a·x ≡ b (mod n) are
  exactly the residue class x0 mod (n/gcd(a,n)) (Thm 31.10).
- 31.4 linear_congruence_distinct: the d = gcd(a,n) values k·(n/d) for
  k < d are pairwise incongruent, so there are exactly d distinct solutions.

Co-Authored-By: Claude <noreply@anthropic.com>
- rsa_pow_cong: for prime p and e*d ≡ 1 (mod p-1), m^(e*d) ≡ m (mod p) —
  covering both p|m and p∤m via ZMod.pow_card_sub_one.
- rsa_correct_general: for distinct primes p q and
  e*d ≡ 1 (mod (p-1)(q-1)), m^(e*d) ≡ m (mod p*q) for every m, via the
  per-prime congruences and the Chinese remainder theorem.
- prime_coprime: distinct primes are coprime.

Co-Authored-By: Claude <noreply@anthropic.com>
…work

Drop the 31.5 general-CRT and 31.7 RSA general-message items from the
chapter guide deferred list and raise the tracked-theorem count to 19,
matching the proofs landed in eda498d (Thm 31.10, 31.27) and 81ac64e
(Thm 31.36 general case).

Co-Authored-By: Claude <noreply@anthropic.com>
Add the Fibonacci running-time analysis of the Euclidean algorithm,
closing the last 31.2 deferred item:

- euclidDivisions counts the recursive calls of CLRS EUCLID.
- fib_le_of_euclidDivisions (CLRS Lemma 31.10): k calls with a > b >= 1
  force b >= F_{k+1} and a >= F_{k+2}, by strong induction on b.
- euclidDivisions_lt (CLRS Theorem 31.11, Lamé's theorem): b < F_{k+1}
  implies fewer than k calls.
- euclidDivisions_le_two_log (CLRS Corollary 31.12): at most 2*log2 b + 2
  calls, i.e. O(log b), via new exponential growth lemmas
  fib_two_step_ge_pow_two / pow_two_le_fib (2^(n/2) <= F_{n+2}).

All theorems kernel-checked with clean axioms; progress CSV bumped to
22/22 tracked theorems and docs/proof-map.md updated.

Co-Authored-By: Claude <noreply@anthropic.com>
Add the Carmichael-number half of the 31.8 deferred work:

- isCarmichael n: composite and a^(n-1) ≡ 1 (mod n) for every a coprime
  to n, with the projection lemmas and
  carmichael_fermatPseudoprime (a Carmichael number is a Fermat
  pseudoprime to every coprime base).
- isCarmichael_561: the smallest Carmichael number is 561, shown via
  fermat_test for the prime factors 3, 11, 17 and the new helper
  modeq_of_coprime_mul (combining congruences under coprime moduli).
  This concretely shows PSEUDOPRIME cannot certify primality.

Kernel-clean axioms; progress CSV bumped to 24/24 and docs updated.

Co-Authored-By: Claude <noreply@anthropic.com>
Define the Miller-Rabin machinery (correctness/error bound deferred):

- strongTestParams: write n-1 = 2^s * d with d odd via Nat.factorization.
- strongPseudoprime (STRONG-PSEUDOPRIME): a^d ≡ 1 or a^(2^i * d) ≡ -1
  for some i < s (i ranging over Fin s for decidability).
- Witness: a base that refutes strong pseudoprimality.
- millerRabin: the executable single-base decision procedure.
- instDecidableStrongPseudoprime for the Fin-bounded search.

Computational sanity checks: millerRabin 5 2 = true, 9 2 = false, and
561 2 = false - although 561 is a Carmichael number, base 2 witnesses
that it is composite, illustrating why Miller-Rabin beats PSEUDOPRIME.

Kernel-clean; docs and proof map updated; correctness/error bound
remain deferred.

Co-Authored-By: Claude <noreply@anthropic.com>
Prove the prime direction of Miller-Rabin correctness in 31.8:

- strongTestParams_spec: the 2^s·d decomposition of n-1 (via
  Nat.Prime.pow_dvd_iff_le_factorization and Nat.mul_div_cancel').
- modeq_neg_one_of_sq_eq_one: for a prime p, x^2 ≡ 1 and x ≢ 1
  (mod p) imply x ≡ -1 — the roots-of-unity fact via Nat.sq_sub_sq
  and Nat.Prime.dvd_mul.
- strongPseudoprime_of_prime: for prime n and a coprime to n, the
  sequence a^d, a^(2d), ..., a^(2^s·d) reaches 1 (Fermat); at the
  first such index the previous value is a square root of 1 that is
  not 1, hence -1.  Uses Nat.find for the minimal index.
- not_witness_of_prime (a prime has no witness) and
  witness_not_prime (a witness certifies compositeness).

Kernel-clean axioms; progress CSV bumped to 26/26; only the
Miller-Rabin error bound and Pollard's-rho analysis remain deferred.

Co-Authored-By: Claude <noreply@anthropic.com>
Complete the deterministic part of the 31.9 deferred work:

- rho_collision_factor_dist: the |y-x| (Nat.dist) version of the
  collision-factor lemma, matching GCD(|y-x|, n) in POLLARD-RHO.
- RhoState (tortoise-and-hare state: step count, current value,
  power-of-two snapshot, next boundary), pollardStep (one iteration),
  pollardRhoLoop (over a step budget), and pollardRho (the full CLRS
  algorithm).
- pollardRho_sound: whenever the returned value differs from n it is a
  nontrivial divisor of n (the only exit producing a value is the
  1 < d < n check on the gcd, and the gcd always divides n).
- pollardStep_collision_factor: a mod-p collision at a step makes that
  step's candidate a multiple of p, so the loop returns a factor.

Kernel-clean (pollardRho_sound needs only propext and Quot.sound);
progress CSV bumped to 27/27. The birthday-paradox expected-O(sqrt p)
running-time analysis remains deferred as a CLRS heuristic.

Co-Authored-By: Claude <noreply@anthropic.com>
Start the error-bound proof with the clean foundational lemmas:

- modeq_pow_two_sub_one: (n-1)^2 ≡ 1 (mod n), via
  (n-1)^2 - 1 = n*(n-2).
- strongPseudoprime_pow: a strong probable prime to base a satisfies
  a^(n-1) ≡ 1 (mod n).  With n-1 = 2^s·d, either a^d ≡ 1, or
  a^(2^i·d) ≡ -1 and a^(n-1) = (a^(2^i·d))^(2^(s-i)) ≡ (-1)^even = 1.
  Every strong liar therefore lies in the kernel of a ↦ a^(n-1), the
  first step toward showing the liars form a subgroup of the units.

Kernel-clean axioms.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Write docs/ch31-error-bound-handoff.md capturing the verified roadmap for
the last remaining ch31 theorem (Rabin-Monier: at most phi(n)/4 strong
liars for odd composite n).  Key content:

- Correct structure: embed liars into the subgroup S(n) = {x :
  x^(2^(nu(n)-1)*t) ≡ ±1 mod n}, then bound |S| ≤ phi(n)/4 via the
  three-case analysis (>=3 prime factors, n=pq, n=p^2).
- Verified negative result: strong liars are NOT a subgroup for
  multi-prime n (brute-force counterexamples 65/85/145/185), so the naive
  subgroup approach is wrong; prime powers are cyclic.
- Mathlib gap: cyclicity of (Z/p^e)^* / exists_primitive_root is missing;
  build it first (Milestone 0).
- Concrete Milestone 0-4 attack order and reusable API/lemma inventory.

Co-Authored-By: Claude <noreply@anthropic.com>
Add the verified Mathlib findings from the attack's first step:
- Cyclicity of (Z/p)^* for prime p is a free instance (finite-field
  unit-group theorem), with IsCyclic.exists_generator as the generator.
- (Z/p^e)^* cyclicity for e >= 2 is NOT in Mathlib; suggest either
  proving primitive roots mod odd prime powers or a Hensel-lifting
  reduction to (Z/p)^*.
- Nat.card (ZMod n)^* = totient n is not a named lemma but the pieces
  exist (Nat.card_units, totient_eq_card_coprime).
- Revised Milestone 0-4 order.

Co-Authored-By: Claude <noreply@anthropic.com>
…ib gaps

Verified corrections to the Miller-Rabin error-bound handoff:

- Target ≤ (n−1)/4, NOT ≤ φ(n)/4: the φ-bound is false for n = 9
  (liars(9) = {1,8}, 2 > φ(9)/4 = 1; (n−1)/4 gives equality).
- |S(n)| = 2^(k(ν−1)+1)·∏gcd(t,d_i) and exact liar count
  |L| = G·(2^(kν)−1)/(2^k−1) re-derived and checked on n = 9,15,25,65,561.
- Both former "gaps" are now in Mathlib: ZMod.isCyclic_units_of_prime_pow
  ((Z/p^e)ˣ cyclic for odd p, no Hensel needed) and
  ZMod.card_units_eq_totient (the φ-bridge).  Only remaining primitive to
  write: #{x : α // x^n = 1} = gcd(n, |α|) for cyclic α.

Co-Authored-By: Claude <noreply@anthropic.com>
…rs ⊆ S

Milestone 1-2 of the Rabin-Monier error bound.  Kernel-clean (only
propext/Classical.choice/Quot.sound).

- units of ZMod n: Nat.card (ZMod n)ˣ = φ(n), prime case p−1.
- nu(n) = min over prime factors p of v₂(p−1), with 2^ν | p−1 and ν ≥ 1
  for odd n.
- S(n) = {x ∈ (ZMod n)ˣ : x^(2^(ν−1)·t) ∈ {±1}} as a Subgroup (preimage of
  {1,−1} under the power map), avoiding ZMod-coercion pain.
- Parity lemma: orderOf (a^(2^i·d)) = 2 with d odd ⟹ 2^(i+1) | orderOf a.
- liar_mem_goodSet: every strong liar lies in S(n), via reduction mod each
  prime divisor (ZMod.castHom) + the parity lemma forcing 2^(i+1) | p−1.

Co-Authored-By: Claude <noreply@anthropic.com>
Milestone 3 foundation: the counting kernel for |S(n)|.

- card_multiples_dvd: #{i < N : d | i} = N/d for d | N.
- card_fin_dvd_mul: #{i < N : N | i·n} = gcd(N, n), via the gcd-reduction
  (N/g | i) and coprimality of quotients.
- card_pow_eq_one_cyclic: in a finite cyclic group of order N, the number of
  elements with x^n = 1 is gcd(n, N) — via the generator parametrization
  (IsCyclic.image_range_card) and the i ↦ g^i bijection.

All kernel-clean (only propext/Classical.choice/Quot.sound).

Co-Authored-By: Claude <noreply@anthropic.com>
Milestone 3a: the per-prime-power counting primitive.

- card_pow_eq_one_prime_pow: #{x : (ZMod (p^e))ˣ // x^m = 1} = gcd(m, φ(p^e))
  via cyclicity of (Z/p^e)ˣ (ZMod.isCyclic_units_of_prime_pow) + the cyclic
  torsion count.
- card_pow_eq_c_of_exists: in a finite commutative group, the fiber of x↦x^m
  over any element in its image has the same size as the m-torsion (coset of
  the kernel).
- card_pow_le_card_pow_eq_one: so any fiber has size ≤ the m-torsion — this
  bounds the "≡ −1" part by the "≡ 1" part without needing −1 in the image.

Kernel-clean (only propext/Classical.choice/Quot.sound).

Co-Authored-By: Claude <noreply@anthropic.com>
Milestone 3b: card_pow_eq_one_crt shows the number of units x modulo n with
x^m = 1 equals the product over prime factors p of the number of units modulo
p^e_p with x^m = 1.

Uses ZMod.equivPi (the CRT as a ring isomorphism on ZMod n), Units.mapEquiv +
MulEquiv.piUnits to lift to unit groups, and Equiv.subtypePiEquivPi to turn
the pointwise-torsion subtype into a Pi of per-prime-power torsion subtypes.

Kernel-clean (only propext/Classical.choice/Quot.sound).

Co-Authored-By: Claude <noreply@anthropic.com>
…1)/2

Milestone 3c (partial): the key per-prime-factor bound for |S(n)|.

- odd_dvd_of_dvd_mul_two / odd_of_dvd_odd: odd-divisor helpers.
- gcd_pow_mul_le_half: for m = 2^(ν−1)·t with t odd and 2^ν | p−1, the gcd
  of m and p−1 is at most (p−1)/2 (2-adic valuation ≤ ν−1, odd part ≤ d).

Kernel-clean (only propext/Classical.choice/Quot.sound).

Co-Authored-By: Claude <noreply@anthropic.com>
Milestone 3 assembly: the structural bound for the error bound.

- card_subtype_filter, card_or_le: counting a disjunction of predicates.
- goodSet_card_le: |S(n)| = |{x : x^m ∈ {±1}}| ≤ 2·|{x : x^m = 1}| — the
  "≡ −1" part is a fiber of the power map, no larger than the m-torsion.
- mTorsion_eq_prod: the m-torsion of (ZMod n)ˣ is the product over prime
  factors p of gcd(m, φ(p^e_p)) (via card_pow_eq_one_crt + the per-prime-power
  count).

Together: |S(n)| ≤ 2·∏ gcd(m, φ(p^e)) ≤ 2^(1−k)·∏(p−1).  Kernel-clean.

Co-Authored-By: Claude <noreply@anthropic.com>
Completes the structural bound for the error bound:
|S(n)| ≤ 2·|S₁| ≤ 2·∏(p−1)/2 = 2^(1−k)·∏(p−1).

- nu_le_v2_nat_sub_one: ν(n) ≤ v₂(n−1), since every prime factor is
  ≡ 1 mod 2^ν and n = ∏p^e (Nat.ModEq.prod_one).
- mExp_dvd: m = 2^(ν−1)·t divides n−1.
- mExp_coprime_prime: m is coprime to every prime factor p of n.
- gcd_eq_gcd_of_coprime / gcd_totient_eq_gcd_prime:
  gcd(m, φ(p^e)) = gcd(m, p−1).
- mTorsion_le_prod_half: |S₁| ≤ ∏ (p−1)/2, via the per-factor gcd bound
  gcd_pow_mul_le_half.

Kernel-clean (only propext/Classical.choice/Quot.sound).  The remaining work
is the three-case arithmetic (|S| ≤ 2^(1−k)·∏(p−1) ≤ (n−1)/4 for k ≥ 3,
k = 1, k = 2).

Co-Authored-By: Claude <noreply@anthropic.com>
Milestones 1-3 (ν, S(n), liars ⊆ S, |S| ≤ 2^(1−k)·∏(p−1)) are committed.
The handoff now documents the only remaining work — Milestone 4, the
three-case bound |S| ≤ (n−1)/4 — with the k=2 analysis worked out:

- sub-case s < r is easy via pq−1 ≥ 2^(2ν+1)d_p·d_q (no d/gcd needed);
- sub-case s = r needs "d_p | t ∧ d_q | t ⟹ d_p = d_q ⟹ p = q" to get a
  factor-3 saving.

Co-Authored-By: Claude <noreply@anthropic.com>
Milestone 4 of the Rabin–Monier error-bound proof: the three-case
arithmetic bound on the good subgroup S(n).

- k=1 (prime power): |S| ≤ p−1 ≤ (p^e−1)/4 via the CRT m-torsion count
  and 4(p−1) ≤ p²−1.
- k=2 (semiprime n = p^a q^b): squarefree n=pq uses the refined bound
  8·gcd(m,p−1)·gcd(m,q−1) ≤ pq−1, split into s<r (2^(2s+1) ≤ 2^(s+r))
  and s=r (key lemma: d_p|t ∧ d_q|t forces p=q, giving a factor-3 saving);
  non-squarefree uses the crude 2(p−1)(q−1) ≤ n−1.
- k≥3: 2^(1−k)·∏(p−1) ≤ (n−1)/4 via ∏(p−1) ≤ n−1.

Key lemmas: nu_semiprime (ν(pq) = min v₂(p−1) v₂(q−1)),
gcd_pow_mul_oddPart (gcd decomposition), semiprime_key_lemma,
semiprime_gcd_bound, crude_bound, prod_primeFactors_pair,
goodUnits_card_le_semiprime.

Assembles to goodUnits_card_le (|S(n)| ≤ (n−1)/4) and the headline
strongLiars_card_le: at most (n−1)/4 of the bases are strong liars for
odd composite n (Theorem 31.38).  Kernel-clean: only
propext/Classical.choice/Quot.sound, no sorryAx.

Docs: chapter guide, progress CSV (29/29 tracked), proof map, and the
module header all updated; the error bound is no longer deferred.
The project base is now the CLRS 4th edition, which renumbered several
results in Chapter 31.  Verified against the 4th-edition text:

- Miller-Rabin error bound: Theorem 31.38 -> Theorem 31.39 (the
  witnesses >= (n-1)/2 theorem; (n-1)/4 is its Rabin-Monier sharpening).
- Fermat's little theorem: Theorem 31.30 -> Theorem 31.31; Euler's
  theorem is Theorem 31.30.
- Modular-linear solvability: Theorem 31.11 -> Corollary 31.21; the
  distinct-solutions count is Corollary 31.22.
- Euclid recursion: Lemma 31.2 -> Theorem 31.9 (GCD recursion theorem).
- Fixed the handoff doc title typo ("Theorem 31.8" -> 31.39).
- Noted that the 4th edition removed Section 31.9 (integer
  factorization); the POLLARD-RHO file is retained pending the repo-wide
  migration.

The §31.1-31.3 references (mod_add, exists_mul_inverse_mod,
mul_left_cancel_mod, gcd_is_linear_combination) remain on their legacy
numbers pending the repo-wide 4th-edition migration.

Co-Authored-By: Claude <noreply@anthropic.com>
Bring origin/main (37 commits: 4th-edition facade, edition maps, Ch30,
literate shard infrastructure, scripts) into feat/ch31-refinements.

The ch31 section files merged cleanly, keeping the full Miller-Rabin
error-bound work (strongLiars_card_le).  Conflicts resolved only in
CLRSLean/Progress.lean and docs/clrs-proof-progress.csv, taking the
remote's new fourth-edition schema.

Verification: lake build CLRSLean (8958 jobs) passes; check_repository.py
and check_progress_csv.py (1326/1326) pass.

Co-Authored-By: Claude <noreply@anthropic.com>
Add goodUnits_card_le and strongLiars_card_le to the chapter 31 row of the
fourth-edition progress ledger (tracked/proved 15 -> 17), since the merged
error-bound work is now in the source.  Regenerate Progress.lean and the
README progress table; update the snapshot test's expected total
(1,326 -> 1,328).

Co-Authored-By: Claude <noreply@anthropic.com>
Green-field start of Chapter 34 on Mathlib's Turing.TM2ComputableInPolyTime
(machine-level polynomial-time computability with Polynomial ℕ bounds).

Section 34.1 defines the framework:
- Language: a set of strings over an alphabet.
- PolyTimeComputable: a function computed by a TM2 machine in polynomial
  time.
- PolyTimeDecidable / ClassP: the class of polynomial-time decidable
  languages; mem_ClassP (kernel-clean, only propext/Quot.sound).

Wiring: Chapter_34.lean guide, literate.toml, CLRSLean.lean import,
FourthEdition guide now imports the source (status partial), interface
test, edition-map (34.1 native), progress CSV (34 partial 1/1), proof map.

Deferred (documented in the guide, not sorry): concrete machine
constructions (empty/universal in P), Turing.TM2ComputableInPolyTime.comp
(Mathlib proof_wanted), ClassP closure, then 34.2 NP and 34.3 reducibility.
Open problems (P vs NP) and specific reductions (34.4-34.5) are out of
scope per the session plan.

Verification: lake build CLRSLean passes; check_repository.py passes;
test_check_progress_csv.py updated (1,328 -> 1,329; not-started 5 -> 4).

Co-Authored-By: Claude <noreply@anthropic.com>
Extends the green-field NP-completeness formalization with the rest of the
conceptual framework:

- 34.2 Polynomial-Time Verification: pairEncoding (certificate/input
  encoding with a separator), PolyTimeVerifiable, ClassNP, mem_ClassNP.
- 34.3 NP-Completeness and Reducibility: PolyTimeReducible (L₁ ≤_P L₂),
  NPHard, NPComplete, ClassNPC.

Wiring: chapter guide lists all three sections; literate.toml, index.md,
edition map (34.2, 34.3 native), progress CSV (34 partial 3/3, 34.1-34.3
represented), interface test, README/progress dashboard regenerated.

The theorem layer remains the documented next milestone:
Turing.TM2ComputableInPolyTime.comp (polytime-composition closure; Mathlib
leaves this proof_wanted — a combined-machine construction is partially
developed), P ⊆ NP, transitivity of PolyTimeReducible, and the
NP-completeness characterization.  Open problems (P vs NP) and the
specific reductions (34.4-34.5) remain out of scope.

Verification: lake build CLRSLean passes; check_repository.py passes;
tests updated (1,329 -> 1,331).

Co-Authored-By: Claude <noreply@anthropic.com>
Shared-stack composition construction for `TM2ComputableInPolyTime.comp`
(scratch): the combined machine has stacks `Sum K₁ K₂`; phase 1 runs `h1`'s
program reindexed `k ↦ inl k` (`halt` jumps into `h2`'s main); phase 2 runs
`h2`'s program with its input stack implemented by `h1`'s output stack
(`convIn`/`convOut` through the alphabet equivalence).

`stepAux_mapStmt₁`/`stepAux_mapStmt₂` and `step₁_sim`/`step₂_sim` show every
combined step mirrors the underlying machine's step.

Co-Authored-By: Claude <noreply@anthropic.com>
`evalsTo_lift`/`evalsToInTime_lift` transport an evaluation through a step
simulation; `stepAux_stk_len_pushCount` + `maxPushCount₁` bound any stack's
growth per step, giving `evalsTo_out_len_le` (output length ≤ input length +
linear in steps) — the input to phase 2's time bound.  `compTime` combines
`h1.time` with `h2.time.comp (X + h1.time)`.

Co-Authored-By: Claude <noreply@anthropic.com>
`mapCfg₁_init`, `mapCfg₁_halt_eq`, and `mapCfg₂_halt_eq` connect the embedded
configurations.  The final piece, `mapCfg₂_halt_eq`, needed the composite
`compOutputAlphabet` — an `Equiv.cast` recast when `h2` reuses its input stack
as output — to reduce element-wise.  Making `compMachine` an `abbrev`
(reducible) lets `rw` see `(compMachine h1 h2).Γ (compMachine h1 h2).k₁` as
`CompΓ h1 h2 (compk₁ h1 h2)`; the `⋯ ▸` cast round-trip closes via the new
`cast_symm_cancel` (proof irrelevance).  Axiom-clean (`propext`/
`Classical.choice`/`Quot.sound` only).

Co-Authored-By: Claude <noreply@anthropic.com>
TankTechnology and others added 6 commits August 7, 2026 00:30
Closes Mathlib's `proof_wanted TM2ComputableInPolyTime.comp`.

`comp_outputsFun` runs the combined machine in two phases: phase 1 lifted
through `mapCfg₁`, meeting `mapCfg₁_halt_eq`, phase 2 through `mapCfg₂`,
closing with `mapCfg₂_halt_eq`, chained by `EvalsToInTime.trans`.  The total
time `m₂ + m₁` is bounded by `compTime` using the new
`Polynomial.eval_mono_nat` (`eval` on `Polynomial ℕ` is monotone — nonnegative
coefficients at a nonnegative argument) and the phase-1 output-length bound
`evalsTo_out_len_le`.

`comp_scratch` proves `Nonempty (TM2ComputableInPolyTime eα eγ (g ∘ f))`,
axiom-clean (`propext`/`Classical.choice`/`Quot.sound` only).

Co-Authored-By: Claude <noreply@anthropic.com>
…o 34.3

Move the composition construction from the scratch into
`Section_34_1_Polynomial_Time/Composition.lean` (module
`...Composition`, namespace `Turing.TM2Comp`): the combined two-phase machine,
step simulations, configuration bridges, time bound, and
`comp_scratch` (Mathlib's `proof_wanted TM2ComputableInPolyTime.comp`).

Section 34.1 now proves `PolyTimeComputable.comp` (composition closure, CLRS
§34.1); section 34.3 proves `PolyTimeReducible.trans` (transitivity of `≤_P`,
CLRS §34.3).  The root `Scratch_comp.lean` is removed.

Co-Authored-By: Claude <noreply@anthropic.com>
`Section_34_2_Polynomial_Time_Verification/PairProjection.lean` builds the
pair-projection machine `prjMachine` (three stacks, phases
scan/copy₁/copy₂/fin; the LIFO double pass through `temp` outputs `y` in
order) and proves `prjComputableInPolyTime` (`pairEncoding x y ↦ y` is
polytime).  The phase lemmas (`scan_phase`, `copy1_phase`, `copy2_phase`,
`fin_step`) run the machine's `(flip bind Sstep)^[n]` iteration.

Section 34.2 proves `PolyTimeVerifiable.of_decidable` (a decider is a verifier
that ignores the certificate, composed with the projection machine) and
`ClassP_subset_ClassNP` (`P ⊆ NP`, CLRS Theorem 34.2).

`pairEncoding` moves from 34.2 to 34.1 so both 34.2 and the projection module
can import it without a cycle.  Axiom-clean.

Co-Authored-By: Claude <noreply@anthropic.com>
`Turing.TM2Comp.boolEncoding`/`notMachine`/`notComputableInPolyTime` (in the
Composition module) compute `Bool.not` on the one-symbol encoding in one step.
Section 34.1 proves `PolyTimeDecidable.compl` (negate the decider, composed
with the NOT machine) and `ClassP_compl` (closure of `P` under complement,
CLRS §34.1).  `boolEncoding` becomes an alias to the shared `Turing.TM2Comp`
def.

Co-Authored-By: Claude <noreply@anthropic.com>
Chapter 34's theorem layer (polytime composition, P ⊆ NP, transitivity of
`≤_P`, P closed under complement) is complete.  Sync the ledger and site
configuration:

- `docs/clrs-proof-progress.csv`: 6 tracked / 6 proved; theorem-layer note;
  remaining gap = Sections 34.4-34.5 + P closed under union/intersection.
- Regenerated `CLRSLean/Progress.lean` and the README progress table
  (total 1334 theorem entries; `test_check_progress_csv.py` count updated).
- `literate.toml`: register the `Composition` and `PairProjection` modules.
- `docs/index.md`, `docs/proof-map.md`, `CLRSLean/Chapter_34.lean`
  (aggregator imports the sub-modules), and the fourth-edition guide:
  coverage boundary updated.

Co-Authored-By: Claude <noreply@anthropic.com>
Closes the last theorem-layer gap of Chapter 34: P is closed under union
and intersection.  The construction is Turing.TM2AndOr, a four-phase TM2
machine that duplicates the input onto both deciders' input stacks
(dupScan/dupRestore via a scratch stack), runs M₁ then M₂ sequentially on
their own stack halves, and combines the two Bool results with AND/OR.

- Section_34_1_Polynomial_Time/AndOr.lean (856 lines, kernel-clean):
  andOrMachine, mapStmt₁/mapStmt₂ reindexings, dup phase lemmas
  (dup_copyout_phase/dup_restore_phase/dup_phase), combine_step,
  mapCfg₁to₂ bridge, andOrTime, andOr_outputsFun, and
  andOrComputableInPolyTime (x ↦ [op (f₁ x) (f₂ x)] polytime).
- Section_34_1: PolyTimeDecidable.union/inter and ClassP_union/inter.
- Docs/literate.toml/index/README/proof-map/progress CSV synced; repo
  checker passes; headline theorems depend only on propext/Classical.choice/Quot.sound.

Co-Authored-By: Claude <noreply@anthropic.com>
@TankTechnology TankTechnology changed the title feat(ch34): NP-Completeness — chapter skeleton + 34.1 framework (class P) feat(ch34): NP-Completeness — theorem layer complete (composition, P⊆NP, ≤_P transitivity, complement, union, intersection) Aug 7, 2026
@TankTechnology

Copy link
Copy Markdown
Owner Author

Superseded by #157 (clean branch feat/ch34-complete based on current main, no ch31 deltas). This branch kept ch31 refinements from the PR #155 integration; the ch34 work is identical.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant