The Lindström-Gessel-Viennot Lemma: Weighted and Generalized Versions #
This file formalizes the weighted version of the LGV lemma and related results, following Section "The weighted version ... The nonpermutable case" (sec.det.comb.lgv) of the Algebraic Combinatorics notes.
Main definitions #
LGV.SimpleDigraph: A digraph structure with no self-loops (irreflexive adjacency)LGV.SimpleDigraph.toDigraph: Conversion to Mathlib'sDigraphtypeLGV.ArcWeight: A weight function on arcs of a digraphLGV.pathWeight: The weight of a path (product of arc weights)LGV.pathTupleWeight: The weight of a path tuple (product of path weights)LGV.pathWeightMatrix: The matrix of sums of path weights between source/target verticesLGV.catalanHankelMatrix: The Hankel matrix of Catalan numbers
Main results #
LGV.lgv_weighted_lattice: LGV lemma, lattice weight version (Theorem thm.lgv.kpaths.wt)LGV.lgv_weighted_digraph: LGV lemma, digraph weight version (Theorem thm.lgv.kpaths.wt-dg)LGV.lgv_nonpermutable: LGV lemma, nonpermutable lattice weight version (Corollary cor.lgv.kpaths.wt-np)LGV.binom_det_nonneg: Determinant of binomial coefficient matrix is nonnegative (Corollary cor.lgv.binom-det-nonneg)LGV.catalan_hankel_det: Hankel determinant of Catalan numbers equals 1 (Corollary cor.lgv.catalan-hankel-det-0)LGV.catalan_hankel_det_zerothroughLGV.catalan_hankel_det_seven: Base cases proved by computation
References #
- Source: AlgebraicCombinatorics/tex/Determinants/LGV2.tex
- [Lindström, On the vector representations of induced matroids][Lindstrom73]
- [Gessel-Viennot, Binomial determinants, paths, and hook length formulae][GesVie85]
Implementation notes #
We formalize the LGV lemma for general path-finite acyclic digraphs, with the integer lattice ℤ² as a special case. The key construction is a sign-reversing involution on intersecting path tuples that exchanges tails at the first intersection point.
The nonpermutable case applies when the source and target vertices are "sorted" in a way that prevents non-identity permutations from having non-intersecting path tuples.
For the Catalan Hankel determinant, we use Mathlib's catalan function and prove
the base cases (k = 0, 1, ..., 7) by direct computation using native_decide.
The general theorem uses the LGV lemma with Dyck paths.
Relationship with LGV1.lean #
This file (LGV2.lean) and LGV1.lean both work with the integer lattice digraph, but use different representations:
- LGV1.lean: Uses Mathlib's
Digraphtype andLatticePath(list of steps: east/north) - LGV2.lean: Uses
LGV.SimpleDigraph(custom structure with irreflexivity) andSimpleDigraph.Path(list of vertices)
The integer lattice definitions have equivalent adjacency relations, proven by
integerLattice_arc_iff and integerLattice_toDigraph_adj_iff. The conversion
SimpleDigraph.toDigraph allows transferring results between the two representations.
This file contains the complete weighted LGV lemma proof. LGV1.lean contains the counting case infrastructure with lattice-specific path counting results.
Digraph Definitions #
We work with simple digraphs that are path-finite and acyclic.
A simple digraph with vertex set V. Convention conv.lgv.digraph(d): A simple digraph has arcs as pairs of distinct vertices.
Instances For
A path in a digraph is a list of vertices where consecutive vertices are connected by arcs. A path may contain 0 arcs (in which case start and end are identical).
- vertices : List V
The vertices of the path, in order
The path is nonempty
- arcs_valid (i : ℕ) (hi : i + 1 < self.vertices.length) : D.arc (self.vertices.get ⟨i, ⋯⟩) (self.vertices.get ⟨i + 1, hi⟩)
Consecutive vertices are connected by arcs
Instances For
The starting vertex of a path
Instances For
The ending vertex of a path
Instances For
A digraph is path-finite if there are only finitely many paths between any two vertices. Convention conv.lgv.digraph(b)
Instances For
Extract a subpath from index i to index j (inclusive).
The resulting path has j - i + 1 vertices.
Equations
Instances For
In an acyclic digraph, all vertices on a path are distinct. This follows from the fact that if a vertex appears twice, we could extract a cycle (a path from that vertex back to itself).
Conversion to Mathlib's Digraph #
LGV.SimpleDigraph is a specialized digraph structure that enforces irreflexivity
(no self-loops). Mathlib's Digraph is more general and allows self-loops.
We provide a conversion that forgets the irreflexivity proof, allowing use of Mathlib's digraph infrastructure when needed.
Convert a SimpleDigraph to Mathlib's Digraph.
This forgets the irreflexivity proof but preserves the adjacency relation.
Note: LGV1.lean uses Mathlib's Digraph directly, while LGV2.lean uses this
SimpleDigraph structure. This conversion enables interoperability.
Instances For
The adjacency relation is preserved by toDigraph.
The Integer Lattice ℤ² #
Definition def.lgv.lattice: The integer lattice has vertex set ℤ² with arcs (i,j) → (i+1,j) (east-steps) and (i,j) → (i,j+1) (north-steps).
Relationship with LGV1.lean #
LGV1.lean defines LGV.integerLattice : Digraph LatticePoint using Mathlib's Digraph.
This file defines LGV.integerLattice : SimpleDigraph (ℤ × ℤ) using our custom structure.
The two definitions have semantically identical adjacency relations:
- LGV1:
IntegerLatticeAdj p q ↔ q = (p.1 + 1, p.2) ∨ q = (p.1, p.2 + 1) - LGV2:
integerLattice.arc u v ↔ (v.1 = u.1 + 1 ∧ v.2 = u.2) ∨ (v.1 = u.1 ∧ v.2 = u.2 + 1)
The lemma integerLattice_arc_iff proves these are equivalent, enabling
results from either file to be transferred to the other.
The integer lattice digraph ℤ².
This is the same lattice as in LGV1.lean, but using SimpleDigraph instead of
Mathlib's Digraph. See integerLattice_arc_iff for the characterization
and integerLattice_toDigraph_adj_iff for the equivalence with LGV1's definition.
Equations
Instances For
The integer lattice adjacency relation in LGV2 matches the one in LGV1.
This bridges the two definitions:
- LGV1.lean:
integerLattice.Adj p qwhereintegerLattice : Digraph LatticePoint - LGV2.lean:
integerLattice.arc u vwhereintegerLattice : SimpleDigraph (ℤ × ℤ)
Both are equivalent to: v = (u.1 + 1, u.2) ∨ v = (u.1, u.2 + 1)
Vertices of a lattice path are bounded by start and finish coordinates
The integer lattice is path-finite
Path Weights #
For each arc, we assign a weight from a commutative ring K. The weight of a path is the product of its arc weights.
An arc weight function assigns a ring element to each arc. Definition in Theorem thm.lgv.kpaths.wt
Equations
- LGV.ArcWeight D K = ((u v : V) → D.arc u v → K)
Instances For
Helper function to compute the product of arc weights along a vertex list. Uses recursion on the structure of the list.
- For an empty list or single vertex, the weight is 1 (no arcs).
- For a list [v₀, v₁, ...], the weight is w(v₀, v₁) * (weight of [v₁, ...]).
Equations
- LGV.pathWeightAux w [] arcs_valid_2 = 1
- LGV.pathWeightAux w [head] arcs_valid_2 = 1
- LGV.pathWeightAux w (v₀ :: v₁ :: rest) arcs_valid_2 = w v₀ v₁ ⋯ * LGV.pathWeightAux w (v₁ :: rest) ⋯
Instances For
The weight of a path is the product of weights of its arcs. w(p) := ∏_{a is an arc of p} w(a)
Equations
- LGV.pathWeight w p = LGV.pathWeightAux w p.vertices ⋯
Instances For
pathWeightAux is independent of the proof of arcs_valid (proof irrelevance).
pathWeightAux equality when lists are equal (combines substitution with proof irrelevance).
pathWeightAux of a cons-cons list factors into an arc weight times the tail.
pathWeightAux is multiplicative over list append when the lists share a common vertex. If l1 = [..., v] and l2 = [v, ...], then pathWeightAux (l1 ++ l2.tail) = pathWeightAux l1 * pathWeightAux l2.
The weight of a path tuple is the product of weights of its component paths. w(𝐩) := w(p₁) w(p₂) ⋯ w(pₖ)
Equations
- LGV.pathTupleWeight w ps = ∏ i : Fin k, LGV.pathWeight w (ps i)
Instances For
k-Vertices and Path Tuples #
Definition def.lgv.path-tups: A k-vertex is a k-tuple of vertices. A path tuple from 𝐀 to 𝐁 is a k-tuple of paths where pᵢ goes from Aᵢ to Bᵢ.
A k-vertex is a k-tuple of vertices of D. Definition def.lgv.path-tups(a)
Equations
- LGV.kVertex V k = (Fin k → V)
Instances For
Permute a k-vertex by a permutation σ: σ(𝐀) = (A_{σ(1)}, A_{σ(2)}, ..., A_{σ(k)}). Definition def.lgv.path-tups(b)
Equations
- LGV.permuteKVertex σ A i = A (σ i)
Instances For
A path tuple from 𝐀 to 𝐁 is a k-tuple (p₁, ..., pₖ) where pᵢ is a path from Aᵢ to Bᵢ. Definition def.lgv.path-tups(c)
The paths in the tuple
Each path starts at the corresponding source vertex
Each path ends at the corresponding target vertex
Instances For
Two paths have a vertex in common
Equations
- LGV.pathsIntersect p q = ∃ v ∈ p.vertices, v ∈ q.vertices
Instances For
A path tuple is non-intersecting (nipat) if no two paths share a vertex. Definition def.lgv.path-tups(d)
Equations
- pt.isNonIntersecting = ∀ (i j : Fin k), i ≠ j → ¬LGV.pathsIntersect (pt.paths i) (pt.paths j)
Instances For
A path tuple is intersecting (ipat) if some two paths share a vertex. Definition def.lgv.path-tups(e)
Equations
Instances For
The Path Weight Matrix #
The matrix M where M_{i,j} = ∑_{p : Aᵢ → Bⱼ} w(p).
The set of paths from u to v in a path-finite digraph
Equations
- LGV.pathsFromTo D hpf u v = ⋯.toFinset
Instances For
The sum of weights of all paths from u to v. ∑_{p : u → v} w(p)
Equations
- LGV.pathWeightSum hpf w u v = ∑ p ∈ LGV.pathsFromTo D hpf u v, LGV.pathWeight w p
Instances For
The path weight matrix M_{i,j} = ∑_{p : Aᵢ → Bⱼ} w(p)
Equations
- LGV.pathWeightMatrix hpf w A B = Matrix.of fun (i j : Fin k) => LGV.pathWeightSum hpf w (A i) (B j)
Instances For
LGV Lemma: Weighted Lattice Version #
Theorem thm.lgv.kpaths.wt: For the integer lattice with arc weights w, det(M) = ∑{σ ∈ Sₖ} (-1)^σ ∑{𝐩 nipat from 𝐀 to σ(𝐁)} w(𝐩)
The set of non-intersecting path tuples from 𝐀 to 𝐁
Equations
- LGV.nipatSet A B = {pt : LGV.PathTuple D k A B | pt.isNonIntersecting}
Instances For
The set of nipats is finite (follows from path-finiteness)
Equations
- ⋯ = ⋯
Instances For
Convert nipatSet to Finset using the finiteness proof
Equations
- LGV.nipatFinset hpf A B = ⋯.toFinset
Instances For
When nipatSet is empty, nipatFinset is empty
Sum of weights over all nipats from 𝐀 to 𝐁 Note: σ is not used in this definition since the permutation is already encoded in B (which should be permuteKVertex σ B' for some B')
Equations
- LGV.nipatWeightSum hpf w A B _σ = ∑ pt ∈ LGV.nipatFinset hpf A B, LGV.pathTupleWeight w pt.paths
Instances For
Path Tuple Infrastructure for LGV #
The key step in the LGV proof is to express the product of sums as a sum over path tuples: ∏j (∑{p : A_j → B_j} w(p)) = ∑_{pt : PathTuple} pathTupleWeight w pt.paths
This uses Finset.prod_univ_sum and a bijection between PathTuple and the piFinset.
Bijection between PathTuple and the piFinset of pathsFromTo. This is the key to converting the product of sums to a sum over path tuples.
Equations
- One or more equations did not get rendered due to their size.
Instances For
LGV Lemma: General Digraph Version #
Theorem thm.lgv.kpaths.wt-dg: The same result holds for any path-finite acyclic digraph.
The proof uses a sign-reversing involution on intersecting path tuples. The key steps are:
- Express det(M) using the Leibniz formula as ∑_σ (-1)^σ ∏i M{i,σ(i)}
- Expand each product as a sum over path tuples from 𝐀 to σ(𝐁)
- Define a sign-reversing involution f on intersecting path tuples:
- Find the first crowded point (vertex in multiple paths)
- Pick the smallest index i whose path contains a crowded point
- Pick the first crowded point v on path p_i
- Pick the largest index j such that v is on path p_j
- Exchange the tails of p_i and p_j at v
- This maps (σ, 𝐩) to (σ ∘ t_{i,j}, 𝐩'), where t_{i,j} is the transposition
- The involution preserves weight but flips sign, so intersecting tuples cancel
- Only non-intersecting path tuples (nipats) contribute to the sum
A crowded point in a path tuple is a vertex that appears in at least two paths
Equations
Instances For
An intersecting path tuple has at least one crowded point
The set of path tuples from 𝐀 to σ(𝐁) paired with the permutation σ
Equations
- LGV.pathTupleWithPerm A B = ((σ : Equiv.Perm (Fin k)) × LGV.PathTuple D k A (LGV.permuteKVertex σ B))
Instances For
The sign of a path tuple with permutation is (-1)^σ
Equations
Instances For
The weight of a path tuple with permutation
Equations
Instances For
The index of the first occurrence of a vertex in a path's vertex list
Equations
- LGV.firstIndexIn p v = List.findIdx (fun (x : V) => decide (x = v)) p.vertices
Instances For
In an acyclic digraph, the first intersection of two paths (if they intersect) is well-defined: it's the same whether we look from path p or path q. This is because if they were different, we could form a cycle.
Split a path at a vertex v, returning (head ending at v, tail starting at v). The head includes v, the tail starts at v.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The head of splitAt ends at v
The tail of splitAt starts at v
Concatenate two paths where the first path ends at v and the second starts at v. The resulting path goes from the start of the first to the end of the second. The vertex v appears once in the result (not duplicated).
Equations
Instances For
pathWeight is multiplicative over path concatenation.
pathWeight factors over splitAt: the weight of a path is the product of the weights of its head and tail after splitting at any vertex.
The head of splitAt starts at the original path's start
The tail of splitAt ends at the original path's finish
Exchange the tails of two paths at a common vertex. If p goes A → v → B and q goes A' → v → B', then after exchange: p' goes A → v → B' and q' goes A' → v → B
Equations
Instances For
The first path from exchangeTails starts at the original first path's start
The first path from exchangeTails ends at the original second path's finish
The second path from exchangeTails starts at the original second path's start
The second path from exchangeTails ends at the original first path's finish
The crowded point v is in the first exchanged path's vertices. Since head_p ends at v, and concat uses head_p.vertices ++ tail_q.vertices.tail, v is in the first path.
The crowded point v is in the second exchanged path's vertices. Since head_q ends at v, and concat uses head_q.vertices ++ tail_p.vertices.tail, v is in the second path.
The head of path p (vertices before v) is preserved after exchangeTails. This is the key lemma for proving that the canonical selection is invariant.
Exchanging tails preserves the total weight.
Proof outline: The key insight is that pathWeight is multiplicative over path
concatenation: if p = p₁ ++ p₂ (concatenation at a shared vertex), then
w(p) = w(p₁) * w(p₂).
When we exchange tails at vertex v:
- p has weight w(p_head) * w(p_tail) where p_head ends at v and p_tail starts at v
- q has weight w(q_head) * w(q_tail) where q_head ends at v and q_tail starts at v
- p' = p_head ++ q_tail has weight w(p_head) * w(q_tail)
- q' = q_head ++ p_tail has weight w(q_head) * w(p_tail)
Thus: w(p) * w(q) = w(p_head) * w(p_tail) * w(q_head) * w(q_tail) = w(p_head) * w(q_tail) * w(q_head) * w(p_tail) (by commutativity) = w(p') * w(q')
Status: Now that exchangeTails is defined, the proof follows from
multiplicativity of pathWeight and commutativity of multiplication in K.
The proof requires showing pathWeight is multiplicative over path concatenation.
Deterministic Intersection Data Selection #
The sign-reversing involution requires selecting intersection data (i, j, v) deterministically so that applying the involution twice returns the original path tuple. The algorithm from the LaTeX source is:
- Pick the smallest i such that path i contains a crowded point
- Pick the first crowded point v on path i (by position in the path)
- Pick the largest j such that v is on path j
This selection is preserved under the involution because:
- The heads of paths i and j (before v) are unchanged
- So v is still the first crowded point on path i
- And j is still the largest index containing v
The set of path indices that have a crowded vertex (shared with another path)
Equations
Instances For
The set of crowded vertices on a specific path
Equations
Instances For
The set of path indices that contain a given vertex
Instances For
The index of the first crowded vertex on a path (by position)
Equations
- pt.firstCrowdedIndexOnPath i = List.findIdx (fun (v : V) => decide (v ∈ pt.crowdedVerticesOnPath i)) (pt.paths i).vertices
Instances For
An intersecting path tuple has nonempty crowdedPathIndices
Key lemma: if i is the smallest crowded path index and v is a crowded vertex on path i, then all other paths containing v have index > i
Canonical Intersection Data Selection #
The sign-reversing involution requires selecting intersection data (i, j, v) canonically so that applying the involution twice returns the original path tuple. The algorithm is:
- i = the smallest path index that contains a crowded point
- v = the first crowded point on path i (by position in the vertex list)
- j = the largest path index that contains v
This selection is preserved under the involution because:
- The heads of paths i and j (before v) are unchanged by exchangeTails
- So v is still the first crowded point on path i
- And j is still the largest index containing v
Get the smallest crowded path index.
Equations
- pt.minCrowdedPathIndex hip = pt.crowdedPathIndices.min' ⋯
Instances For
The minimum crowded path index is in crowdedPathIndices
The minimum crowded path index is minimal
The crowded vertices on the minimum path are nonempty
Get the first crowded vertex on the minimum crowded path. This uses List.find? to get the first vertex in the path that is crowded.
Equations
- pt.firstCrowdedVertex hip = (List.find? (fun (v : V) => decide (v ∈ pt.crowdedVerticesOnPath (pt.minCrowdedPathIndex hip))) (pt.paths (pt.minCrowdedPathIndex hip)).vertices).get ⋯
Instances For
The first crowded vertex is in the minimum crowded path
The first crowded vertex is in the crowdedVerticesOnPath set
The first crowded vertex is crowded (shared with another path)
The set of path indices containing the first crowded vertex (excluding the minimum)
Equations
- pt.otherPathsContainingFirstCrowded hip = {j ∈ pt.pathIndicesContaining (pt.firstCrowdedVertex hip) | j ≠ pt.minCrowdedPathIndex hip}
Instances For
The set of other paths containing the first crowded vertex is nonempty
Get the largest path index containing the first crowded vertex (other than the minimum)
Equations
- pt.maxOtherPathIndex hip = (pt.otherPathsContainingFirstCrowded hip).max' ⋯
Instances For
The max other path index is different from the min crowded path index
The first crowded vertex is in the max other path
Helper function to extract intersection indices from an intersecting path tuple. Returns a pair (i, j) with i ≠ j such that paths i and j intersect.
Equations
- LGV.getIntersectionIndices pt hip = Classical.choice ⋯
Instances For
Helper function to extract full intersection data from an intersecting path tuple. Returns (i, j, v, hvi, hvj) where i ≠ j and v is on both paths i and j.
Equations
- LGV.getIntersectionData pt hip = Classical.choice ⋯
Instances For
Canonical (Deterministic) Intersection Data Selection #
To prove that signReversing is an involution, we need to select intersection data (i, j, v) deterministically so that the same selection is made before and after applying the involution.
The canonical selection algorithm:
- i = smallest index in crowdedPathIndices (using Finset.min')
- v = first crowded vertex on path i (by position in the path)
- j = largest index in pathIndicesContaining v, excluding i (using Finset.max')
This selection is preserved under exchangeTails because:
- The head of path i (vertices before v) is unchanged
- So v is still the first crowded vertex on path i
- And j is still the largest index containing v
A crowded path index has at least 2 paths containing some crowded vertex
If i is a crowded path index, the set of other path indices containing a crowded vertex on i is nonempty
A crowded path index has nonempty crowdedVerticesOnPath
The first crowded vertex on path i (when i is a crowded path index) exists in the path
The vertex at firstCrowdedIndexOnPath is in crowdedVerticesOnPath
Canonical intersection data: deterministically selects (i, j, v) for an intersecting path tuple.
- i = smallest crowded path index
- v = first crowded vertex on path i
- j = largest path index containing v (other than i)
Equations
- One or more equations did not get rendered due to their size.
Instances For
The sign-reversing involution on intersecting path tuples. For an ipat (σ, 𝐩), we:
- Find the smallest i such that p_i contains a crowded point
- Find the first crowded point v on p_i
- Find the largest j such that v is on p_j
- Exchange tails of p_i and p_j at v
- Compose σ with the transposition t_{i,j} This gives (σ ∘ t_{i,j}, 𝐩') which is still an ipat.
Implementation note: The permutation component is sp.1 * Equiv.swap i j where
i and j are the intersection indices. The path tuple component uses exchangeTails
to swap the tails of paths i and j at the crowded vertex v.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The signReversing map preserves the intersecting property. The crowded point v at indices i and j is preserved in the exchanged paths.
Key invariance lemma: The canonical selection returns the same (i, j, v) for sp' as for sp. This is the heart of the involutive proof.
The permutation of signReversing is the original permutation composed with a transposition. This captures the essential structural property of the sign-reversing involution: when we exchange tails at indices i and j, we compose σ with the transposition (i j).
The paths of signReversing are obtained by exchanging tails at indices i and j. This captures the essential structural property of the sign-reversing involution for the paths: paths at indices i and j have their tails exchanged at the crowded point v, while all other paths remain unchanged.
The sign-reversing map flips the sign
The sign-reversing map preserves weight
The sign-reversing map has no fixed points (since it always flips the sign)
Infrastructure for LGV Proof #
The following definitions and lemmas provide the infrastructure needed to complete the LGV theorem proof. The key steps are:
- Define the finset of all path tuples
- Define the finset of intersecting path tuples (ipats)
- Prove that the signed sum over ipats is 0 using the sign-reversing involution
The set of all path tuples from A to B
Equations
Instances For
The set of all path tuples is finite (follows from path-finiteness)
Equations
- ⋯ = ⋯
Instances For
Convert allPathTupleSet to Finset
Equations
- LGV.allPathTupleFinset hpf A B = ⋯.toFinset
Instances For
Every path tuple is in allPathTupleFinset
The set of intersecting path tuples (ipats)
Equations
- LGV.ipatSet A B = {pt : LGV.PathTuple D k A B | pt.isIntersecting}
Instances For
The set of ipats is finite
Equations
- ⋯ = ⋯
Instances For
Convert ipatSet to Finset
Equations
- LGV.ipatFinset hpf A B = ⋯.toFinset
Instances For
Membership in ipatFinset
Membership in nipatFinset
nipats and ipats are disjoint
nipats ∪ ipats = all path tuples (set-level equality)
The product of path weights equals the sum over path tuples
The set of all intersecting path tuples with permutation. This is the domain of the sign-reversing involution.
Equations
- LGV.ipatWithPermSet A B = {sp : LGV.pathTupleWithPerm A B | sp.snd.isIntersecting}
Instances For
PathTuple is finite when the digraph is path-finite.
pathTupleWithPerm is finite when the digraph is path-finite.
The set of intersecting path tuples with permutation is finite.
Equations
- ⋯ = ⋯
Instances For
Convert ipatWithPermSet to Finset
Equations
- LGV.ipatWithPermFinset hpf A B = ⋯.toFinset
Instances For
Membership in ipatWithPermFinset
The signed sum over ALL intersecting path tuples (with permutation) is zero.
This is the correct formulation of the cancellation lemma. The sign-reversing
involution signReversing maps (σ, pt) to (σ * swap i j, pt'), where:
- sign(σ * swap i j) = -sign(σ) (sign flips)
- weight(pt') = weight(pt) (weight preserved)
So each pair {sp, signReversing(sp)} contributes: sign(σ) * w(pt) + sign(σ * swap i j) * w(pt') = sign(σ) * w(pt) + (-sign(σ)) * w(pt) = 0
The total sum is therefore 0.
Note: This works in any CommRing K, including characteristic 2, because we're summing pairs that each contribute 0, not just showing 2x = 0.
The set of all path tuples with permutation
Equations
Instances For
The set of all path tuples with permutation is finite
Equations
- ⋯ = ⋯
Instances For
Convert allPathTupleWithPermSet to Finset
Equations
- LGV.allPathTupleWithPermFinset hpf A B = ⋯.toFinset
Instances For
Every path tuple with permutation is in allPathTupleWithPermFinset
The set of non-intersecting path tuples with permutation
Equations
- LGV.nipatWithPermSet A B = {sp : LGV.pathTupleWithPerm A B | sp.snd.isNonIntersecting}
Instances For
The set of non-intersecting path tuples with permutation is finite
Equations
- ⋯ = ⋯
Instances For
Convert nipatWithPermSet to Finset
Equations
- LGV.nipatWithPermFinset hpf A B = ⋯.toFinset
Instances For
Membership in nipatWithPermFinset
nipats and ipats with permutation are disjoint
nipats ∪ ipats with permutation = all path tuples with permutation (as a sum equality)
The sum over all path tuples with permutation splits into nipats and ipats
The sum over nipats with permutation equals the sum over permutations of nipatWeightSum
The determinant can be written as a sum over all path tuples with permutation
LGV lemma, digraph weight version (Theorem thm.lgv.kpaths.wt-dg) Label: thm.lgv.kpaths.wt-dg
For any path-finite acyclic digraph D with arc weights w ∈ K: det((∑{p : Aᵢ → Bⱼ} w(p)){i,j}) = ∑{σ ∈ Sₖ} (-1)^σ ∑{𝐩 nipat from 𝐀 to σ(𝐁)} w(𝐩)
This generalizes the lattice version - we only use that D is path-finite and acyclic.
Proof outline:
- By Leibniz formula: det(M) = ∑_σ (-1)^σ ∏i M{i,σ(i)}
- Each M_{i,σ(i)} = ∑{p : A_i → B{σ(i)}} w(p), so the product expands to ∑_{𝐩 : path tuple from 𝐀 to σ(𝐁)} w(𝐩)
- Thus det(M) = ∑σ (-1)^σ ∑{𝐩 : 𝐀 → σ(𝐁)} w(𝐩)
- Split the inner sum into nipats and ipats
- The sign-reversing involution on ipats shows ∑_{ipats} (-1)^σ w(𝐩) = 0
- Only nipats remain: det(M) = ∑σ (-1)^σ ∑{𝐩 nipat from 𝐀 to σ(𝐁)} w(𝐩)
LGV lemma, lattice weight version (Theorem thm.lgv.kpaths.wt) Label: thm.lgv.kpaths.wt
For the integer lattice ℤ² with arc weights w ∈ K: det((∑{p : Aᵢ → Bⱼ} w(p)){i,j}) = ∑{σ ∈ Sₖ} (-1)^σ ∑{𝐩 nipat from 𝐀 to σ(𝐁)} w(𝐩)
The proof uses a sign-reversing involution on intersecting path tuples: when two paths intersect, exchange their tails at the first intersection point. This changes the sign (via the permutation) but preserves the weight.
This is a special case of lgv_weighted_digraph for the integer lattice.
The Nonpermutable Case #
Corollary cor.lgv.kpaths.wt-np: When the source and target vertices are "sorted" (x-coordinates decreasing, y-coordinates increasing), only the identity permutation contributes to the sum.
The x-coordinate of a lattice point
Equations
Instances For
The y-coordinate of a lattice point
Equations
Instances For
A k-vertex has weakly decreasing x-coordinates
Equations
- LGV.xDecreasing A = ∀ (i j : Fin k), i ≤ j → LGV.xCoord (A j) ≤ LGV.xCoord (A i)
Instances For
A k-vertex has weakly increasing y-coordinates
Equations
- LGV.yIncreasing A = ∀ (i j : Fin k), i ≤ j → LGV.yCoord (A i) ≤ LGV.yCoord (A j)
Instances For
Discrete intermediate value theorem for integers. If f : ℤ → ℤ satisfies |f(n+1) - f(n)| ≤ 1 for all n in [a, b), and f(a) ≥ 0 and f(b) ≤ 0, then there exists c in [a, b] with f(c) = 0.
Baby Jordan curve theorem (Proposition prop.lgv.jordan-2) Label: prop.lgv.jordan-2
If A' is weakly northwest of A, and B' is weakly northwest of B, then any path from A to B' and any path from A' to B must intersect.
This is used to show that non-identity permutations have no nipats.
Proof sketch: Both paths visit vertices with consecutive sum values (x + y). The sum ranges [A.1+A.2, B'.1+B'.2] for p and [A'.1+A'.2, B.1+B.2] for p' overlap. At each sum s in the overlap, path p has x-coordinate x_p(s) and p' has x_p'(s). At s_lo = max(A.1+A.2, A'.1+A'.2): x_p ≥ x_p' (because A.1 ≥ A'.1 and A.2 ≤ A'.2). At s_hi = min(B'.1+B'.2, B.1+B.2): x_p ≤ x_p' (because B'.1 ≤ B.1 and B'.2 ≥ B.2). By discrete IVT, there exists s where x_p(s) = x_p'(s), so the vertices coincide.
A monotone bijection on Fin k is the identity. This is used to show that if σ ≠ id, then σ is not monotone.
When σ ≠ id, there are no nipats from 𝐀 to σ(𝐁) under the sorting conditions
When the nipatSet is empty, the nipatWeightSum is zero
Permuting a k-vertex by the identity permutation gives the same k-vertex
LGV lemma, nonpermutable lattice weight version (Corollary cor.lgv.kpaths.wt-np) Label: cor.lgv.kpaths.wt-np
Under the sorting conditions:
- x(A₁) ≥ x(A₂) ≥ ⋯ ≥ x(Aₖ)
- y(A₁) ≤ y(A₂) ≤ ⋯ ≤ y(Aₖ)
- x(B₁) ≥ x(B₂) ≥ ⋯ ≥ x(Bₖ)
- y(B₁) ≤ y(B₂) ≤ ⋯ ≤ y(Bₖ)
The LGV formula simplifies to: det((∑{p : Aᵢ → Bⱼ} w(p)){i,j}) = ∑_{𝐩 nipat from 𝐀 to 𝐁} w(𝐩)
Applications #
Binomial Coefficient Determinants (Corollary cor.lgv.binom-det-nonneg) #
When the matrix entries are binomial coefficients, the determinant is nonnegative.
The FKG Inequality for Binomial Coefficients #
The key combinatorial inequality underlying the binomial determinant nonnegativity. This is the 2×2 case of the LGV lemma, which can be proved directly by induction.
The FKG inequality for binomial coefficients: C(a,c) * C(b,d) ≥ C(a,d) * C(b,c) when a ≥ b and c ≥ d.
This handles all cases including when some choose values are zero.
Base cases for binomial determinant nonnegativity #
Lattice point setup for binomial determinants #
The key construction: set Aᵢ = (0, -aᵢ) and Bᵢ = (bᵢ, -bᵢ). These satisfy the sorting conditions for lgv_nonpermutable.
The source lattice points have constant x-coordinate 0, so xDecreasing holds trivially.
Helper definitions for the path-subset bijection #
The bijection between paths from (0, -a) to (b, -b) and b-element subsets of Fin a is constructed using the following helpers:
eastStepCount a S i: count of elements j ∈ S with j < ivertexAtPos a S i: the vertex at position i in the path determined by SpathVerticesList a S: the list of vertices for the path determined by S
Bijection between paths from (0, -a) to (b, -b) and b-element subsets of Fin a.
This encapsulates the key combinatorial bijection from Proposition prop.lgv.1-paths.ct:
- A path from (0, -a) to (b, -b) has exactly a steps (coordinate sum goes from -a to 0)
- A path has exactly b east-steps (x-coordinate goes from 0 to b)
- A path is uniquely determined by which of its a steps are east-steps
- This gives a bijection to b-element subsets of Fin a
Equations
- One or more equations did not get rendered due to their size.
Instances For
The number of paths from (0, -a) to (b, -b) in the integer lattice equals C(a, b). This follows from Proposition prop.lgv.1-paths.ct.
Unit weight infrastructure for binomial determinant proof #
The unit weight function assigns weight 1 to every arc. With this weight:
- pathWeight p = 1 for any path p
- pathTupleWeight ps = 1 for any path tuple ps
- pathWeightSum = cardinality of paths
- nipatWeightSum = cardinality of nipats ≥ 0
The unit arc weight function assigns 1 to every arc
Equations
- LGV.unitArcWeight x✝² x✝¹ x✝ = 1
Instances For
With unit weight, pathWeight is always 1
With unit weight, pathTupleWeight is always 1
With unit weight, pathWeightSum equals cardinality of paths
The binomial matrix equals pathWeightMatrix with unit weight
With unit weight, nipatWeightSum equals cardinality of nipats
nipatWeightSum with unit weight is nonnegative
The ipatWithPermFinset can be decomposed as a sigma type over permutations. This is the ipat analogue of the decomposition used for nipats.
The sum over ipatWithPermFinset equals the sum over permutations of ipat counts. With unit weight, pathTupleWeight = 1, so this becomes a signed count.
The signed sum of ipat counts over all permutations is zero.
This is the counting version of sum_ipatWithPerm_signed_weight_eq_zero.
The proof uses the sign-reversing involution on intersecting path tuples: for each ipat (σ, pt), swap tails at the first intersection point to get (σ * swap i j, pt'), which has opposite sign but the same weight (= 1).
This lemma is the key step needed to complete LGV1.lean's lgv_involution_cancellation.
Catalan Hankel Determinant (Corollary cor.lgv.catalan-hankel-det-0) #
The Hankel determinant of Catalan numbers equals 1.
We use Mathlib's catalan function from Mathlib.Combinatorics.Enumerative.Catalan.
The Catalan numbers are defined by cₙ = C(2n,n)/(n+1), and the Hankel matrix
has entry (i,j) equal to c_{i+j}. This is a famous result that can be proven
using the LGV lemma with Dyck paths.
The Catalan Hankel matrix is symmetric (since c_{i+j} = c_{j+i}).
The (0,0) entry of the Catalan Hankel matrix is 1 (= c₀).
Entry (i,j) of the Catalan Hankel matrix is catalan(i+j).
Catalan Hankel determinant for k=0: empty matrix has determinant 1.
Catalan Hankel determinant for k=1: 1×1 matrix [c₀] = [1], det = 1.
Catalan Hankel determinant for k=2: 2×2 matrix [[c₀, c₁], [c₁, c₂]] = [[1, 1], [1, 2]]. det = 1·2 - 1·1 = 1.
Catalan Hankel determinant for k=3.
Catalan Hankel determinant for k=4.
Catalan Hankel determinant for k=5.
Catalan Hankel determinant for k=6.
Catalan Hankel determinant for k=7.
The Dyck path digraph: vertices are ℤ × ℕ, arcs go (i,j) → (i+1, j+1) and (i,j) → (i+1, j-1). Used for counting Catalan numbers via Dyck paths.
A Dyck path from (0,0) to (2n,0) corresponds to a balanced sequence of n up-steps and n down-steps that never goes below the x-axis. A Dyck path is a lattice path that stays on or above the x-axis, where each step goes either up-right or down-right.
Equations
Instances For
Every arc in the Dyck digraph increases the first coordinate by 1
The Dyck digraph is path-finite.
Proof: We show that paths from u to v are finite by:
- If v.1 < u.1, no paths exist (x-coordinate strictly increases along arcs)
- Otherwise, paths have fixed length n = v.1 - u.1 + 1
- The y-coordinate is bounded: 0 ≤ y ≤ u.2 + n at each vertex
- Each path is determined by its vertex sequence, which is a function Fin n → box
- Since box is finite and n is finite, there are finitely many such functions
- The map from paths to vertex sequences is injective, so paths are finite
Unit Arc Weight for Dyck Digraph #
Infrastructure for connecting the Catalan Hankel matrix to the LGV lemma.
Path weight with unit weight is 1
Path tuple weight with unit weight is 1
With unit weight, pathWeightSum equals cardinality of paths
With unit weight, nipatWeightSum equals cardinality of nipats
Convert a Dyck path to a list of DyckSteps. Each arc (x,y) → (x+1,y+1) becomes U, each arc (x,y) → (x+1,y-1) becomes D.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The step list has length = vertices.length - 1 = number of arcs.
Convert a Dyck path to a DyckWord. Each arc (x,y) → (x+1,y+1) becomes U, each arc (x,y) → (x+1,y-1) becomes D.
Note: This definition requires substantial infrastructure to prove well-formedness. The key properties are:
- count_U_eq_count_D: follows from start.2 = 0 = finish.2
- count_D_le_count_U: follows from y ≥ 0 throughout the path (Dyck condition)
Equations
- LGV.dyckPathToWord p hstart hfinish = { toList := LGV.dyckPathToSteps p, count_U_eq_count_D := ⋯, count_D_le_count_U := ⋯ }
Instances For
The semilength of dyckPathToWord equals the count of U steps.
Helper function to compute the y-coordinate at position i in a DyckWord path
Equations
- LGV.dyckWordY w i = List.count DyckStep.U (List.take i ↑w) - List.count DyckStep.D (List.take i ↑w)
Instances For
Convert a DyckWord to a Dyck path from (0, 0) to (2n, 0) where n = semilength.
Note: The vertices are constructed as (i, y_i) where y_i = #U - #D in the first i steps. The Dyck word conditions ensure y_i ≥ 0 and the path stays in the valid region.
Equations
- LGV.dyckWordToPath w = { vertices := LGV.dyckWordToVertices w, nonempty := ⋯, arcs_valid := ⋯ }
Instances For
The start of dyckWordToPath is (0, 0)
The finish of dyckWordToPath is (2 * semilength, 0)
The number of Dyck paths from (0, 0) to (2n, 0) equals the n-th Catalan number. This is a classical result connecting Dyck paths to Catalan numbers.
Proof strategy: We construct a bijection between Dyck paths and DyckWords of semilength n.
- Each arc (x,y) → (x+1,y+1) corresponds to U
- Each arc (x,y) → (x+1,y-1) corresponds to D
- The Dyck condition (y ≥ 0) ensures the prefix condition for DyckWords
- Equal start and end y-coordinates ensures equal counts of U and D
Then we use Mathlib's DyckWord.card_dyckWord_semilength_eq_catalan.
Key lemmas needed:
- dyckPathToWord is well-defined (DyckWord conditions satisfied) ✓
- dyckWordToPath is well-defined (arc validity) ✓
- The maps are inverses (bijection) ✓
- dyckPathToWord maps paths from (0,0) to (2n,0) to words of semilength n ✓
Create translated path by shifting x-coordinates
Equations
- LGV.translatePath d p = { vertices := List.map (LGV.translateVertex✝ d) p.vertices, nonempty := ⋯, arcs_valid := ⋯ }
Instances For
The number of Dyck paths from (-2i, 0) to (2j, 0) equals catalan(i+j).
This follows from translation invariance: shifting by 2i gives a bijection
with paths from (0, 0) to (2(i+j), 0), which equal catalan(i+j) by dyck_paths_eq_catalan.
The Catalan Hankel matrix equals the path weight matrix for the Dyck digraph. Entry (i,j) = catalan(i+j) = number of Dyck paths from (-2i, 0) to (2j, 0).
General case of Catalan Hankel determinant for k ≥ 8. The proof uses the LGV lemma with Dyck paths. Source: The TeX source says "The details are LTTR" (Left To The Reader).
The full proof requires:
- catalan_unique_nipat: There is exactly one non-intersecting path tuple
- dyck_no_nipat_for_nonidentity: Non-identity permutations have no nipats These lemmas are defined later in this file but the proof structure requires them to be available here.
Catalan Hankel determinant equals 1 (Corollary cor.lgv.catalan-hankel-det-0) Label: cor.lgv.catalan-hankel-det-0
det((c_{i+j})_{0 ≤ i,j < k}) = 1
where cₙ is the n-th Catalan number.
Note: The TeX source uses 1-indexed notation det((c_{i+j-2}){1 ≤ i,j ≤ k}), which is equivalent to our 0-indexed det((c{i+j})_{0 ≤ i,j < k}).
Proof sketch (via LGV lemma): Use the Dyck path digraph with Aᵢ = (-2i, 0) and Bᵢ = (2i, 0).
- The (i,j) entry of the path matrix counts paths from Aᵢ to Bⱼ, which equals c_{i+j} (Catalan number).
- There is exactly one non-intersecting path tuple from 𝐀 to 𝐁 (the nested Dyck paths).
- For non-identity permutations σ, there are no nipats from 𝐀 to σ(𝐁).
- By LGV, det = 1 · 1 = 1.
In the Dyck digraph, x-coordinate increases by 1 on each arc
A path from (x, y) to (x, y') must have length 1 (i.e., be trivial)
Nested Dyck Paths for the Catalan Hankel Determinant #
The nested Dyck path from (-2n, 0) to (2n, 0) goes: (-2n, 0) → (-2n+1, 1) → ... → (0, 2n) → (1, 2n-1) → ... → (2n, 0)
At step i (0 ≤ i ≤ 4n), the vertex is (i - 2n, min(i, 4n - i)).
The nested Dyck path from (-2n, 0) to (2n, 0)
Equations
- LGV.nestedDyckPath n = { vertices := LGV.nestedDyckVertices n, nonempty := ⋯, arcs_valid := ⋯ }
Instances For
Different nested Dyck paths don't share any vertices
There is exactly one nipat in the Catalan Hankel setup.
The proof constructs the canonical nipat where path_i is the "nested" Dyck path from (-2i, 0) to (2i, 0) that goes up to height 2i and back down: (-2i, 0) → (-2i+1, 1) → ... → (0, 2i) → (1, 2i-1) → ... → (2i, 0)
Existence: The canonical paths form a valid PathTuple because:
- Each path is a valid Dyck path (arcs go up-right or down-right)
- Start/finish conditions are satisfied by construction
Non-intersection: The canonical paths don't intersect because:
- Path_i visits vertices (x, y) with y ≤ 2i
- At height y, path_i is at x = -2i + y (going up) or x = y (going down)
- Path_j (j > i) at height y ≤ 2i is at x = -2j + y or x = y
- These x-coordinates differ when j ≠ i
Uniqueness: Any nipat must equal the canonical one because:
- In the Dyck digraph, paths from (-2i, 0) to (2i, 0) must have length 4i
- For non-intersection with outer paths, inner paths must stay "inside"
- The only way to do this is the nested structure
Bridge Between LGV1 and LGV2 Path Representations #
This section documents the connection between the path representations used in LGV1.lean (list of steps) and LGV2.lean (list of vertices), and provides key infrastructure for bridging them.
Key Insight #
A LatticePath (list of east/north steps) starting at point A can be converted to
a SimpleDigraph.Path by computing the list of vertices visited:
[east, north, east]starting at(0,0)→[(0,0), (1,0), (1,1), (2,1)]
The conversion is bijective for paths between fixed endpoints.
Status #
The key theorem sum_signed_ipatFinset_card_eq_zero proves that the signed sum of
ipat counts is zero. To use this in LGV1.lean's lgv_involution_cancellation, we need:
numIpatsK A B σ = (ipatFinset integerLattice_pathFinite A (permuteKVertex σ B)).card
This requires showing that ipatsFromTo (LGV1) and ipatFinset (LGV2) have the same
cardinality, which follows from a bijection between the path tuple representations.
Approach #
The bijection works as follows:
- Given a
LatticePath(list of steps) starting atA, compute the vertex list - This vertex list forms a valid
SimpleDigraph.PathinintegerLattice - The map is injective because different step sequences give different vertex lists
- The map is surjective because every
SimpleDigraph.PathinintegerLatticecorresponds to a unique step sequence (each arc is either east or north)
The intersection property is preserved because both representations check if any vertex appears in multiple paths of the tuple.
A lattice step on the integer lattice: either east (+1,0) or north (0,+1).
This is the canonical definition for lattice steps. LGV1.lean defines an equivalent
type LGV1.LatticeStep with an explicit equivalence LGV1.latticeStepEquiv.
The two types are isomorphic via:
LGV1.latticeStepEquiv : LGV1.LatticeStep ≃ LGV.LatticeStep'LGV1.latticePathToLatticePath' : LGV1.LatticePath → LGV.LatticePath'LGV1.latticePath'ToLatticePath : LGV.LatticePath' → LGV1.LatticePath
Note: The duplication exists because LGV1 imports LGV2, so LGV2 cannot reference LGV1's definitions. Both definitions are intentionally kept compatible.
- east : LatticeStep'
- north : LatticeStep'
Instances For
Equations
- LGV.instReprLatticeStep' = { reprPrec := LGV.instReprLatticeStep'.repr }
Equations
- LGV.instReprLatticeStep'.repr LGV.LatticeStep'.east prec✝ = Repr.addAppParen (Std.Format.nest (if prec✝ ≥ 1024 then 1 else 2) (Std.Format.text "LGV.LatticeStep'.east")).group prec✝
- LGV.instReprLatticeStep'.repr LGV.LatticeStep'.north prec✝ = Repr.addAppParen (Std.Format.nest (if prec✝ ≥ 1024 then 1 else 2) (Std.Format.text "LGV.LatticeStep'.north")).group prec✝
Instances For
A lattice path as a list of steps (matching LGV1.lean's definition)
Equations
Instances For
Compute the endpoint of a lattice path starting from a given point
Equations
- path.endpoint start = List.foldl (fun (p : ℤ × ℤ) (s : LGV.LatticeStep') => s.apply p) start path
Instances For
Compute all vertices visited by a lattice path, including start. For path = [s₁, s₂, ..., sₙ], this returns [start, s₁(start), s₂(s₁(start)), ...]
Equations
- LGV.LatticePath'.toVertices [] start = [start]
- LGV.LatticePath'.toVertices (s :: rest) start = start :: LGV.LatticePath'.toVertices rest (s.apply start)
Instances For
The vertices list is nonempty
Each step creates a valid arc in the integer lattice
Consecutive vertices in toVertices are connected by arcs
Convert a lattice path to a SimpleDigraph.Path
Equations
- path.toPath start = { vertices := path.toVertices start, nonempty := ⋯, arcs_valid := ⋯ }
Instances For
The first vertex is the start point
The start of the converted path is the original start point
The last vertex is the endpoint
The finish of the converted path is the endpoint
Key bridge lemma: A lattice path going from A to B converts to a SimpleDigraph.Path from A to B. This is the foundation for showing the path representations are equivalent.
The length of the vertex list equals the number of steps plus one
Bridge Bijection Lemmas #
The following lemmas establish that LatticePath'.toPath is a bijection between
step-based lattice paths and vertex-based digraph paths.
These lemmas provide the foundation for connecting LGV1.lean's counting results with LGV2.lean's weighted results.
The vertices of a converted path match the original vertex list
Two paths with the same vertices are equal
toPath is injective: different step sequences give different paths.
Proof sketch:
- If toPath p1 start = toPath p2 start, then their vertex lists are equal
- The vertex list uniquely determines the step sequence because:
- Each arc in the integer lattice is uniquely determined by source and target
- Given consecutive vertices u, v, the step is east iff v.1 = u.1 + 1
- By induction on the path length, equal vertex lists imply equal step sequences
This is a key lemma for the bridge between LGV1 and LGV2 path representations.
Surjectivity of toPath #
To complete the bridge between path representations, we need to show that every
SimpleDigraph.Path in the integer lattice comes from a LatticePath'.
The key insight is that each arc in the integer lattice uniquely determines a step:
- If v.1 = u.1 + 1 (and v.2 = u.2), the step is east
- If v.2 = u.2 + 1 (and v.1 = u.1), the step is north
Convert an arc in the integer lattice to a step. This is the inverse operation to LatticeStep'.apply.
Equations
- LGV.arcToStep' u v _h = if v.1 = u.1 + 1 then LGV.LatticeStep'.east else LGV.LatticeStep'.north
Instances For
arcToStep' produces the correct step
Convert a vertex list to a step list (partial inverse of toVertices)
Equations
- LGV.verticesToSteps' [] x_2 = []
- LGV.verticesToSteps' [head] x_2 = []
- LGV.verticesToSteps' (u :: v :: rest) harcs = LGV.arcToStep' u v ⋯ :: LGV.verticesToSteps' (v :: rest) ⋯
Instances For
Convert a SimpleDigraph.Path to a LatticePath'
Equations
Instances For
toPath is surjective: every SimpleDigraph.Path comes from a LatticePath'.
This completes the bijection between step-based and vertex-based path representations.
Together with toPath_injective, this shows that the two representations are equivalent.
The bijection between LatticePath' and SimpleDigraph.Path starting at a fixed point.
This establishes that the two path representations are equivalent, which is the key step needed to bridge LGV1.lean's counting results with LGV2.lean's weighted results.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Path Tuple Bridge #
This section provides the bridge between LGV1-style path tuples (using LatticePath = List LatticeStep) and LGV2-style path tuples (using SimpleDigraph.Path).
The key results are:
latticePath'TupleEquiv- bijection between path tupleslatticePath'Tuple_isIntersecting_iff- intersection property is preserved
These results allow us to transfer the counting result sum_signed_ipatFinset_card_eq_zero
from LGV2 types to LGV1 types.
A path tuple in the LGV1 style: k paths from A to B where each path is a list of steps.
- paths : Fin k → LatticePath'
The paths in the tuple
Each path goes from A_i to B_i
Instances For
A LatticePath'Tuple is non-intersecting if no two paths share a vertex
Equations
- pt.isNonIntersecting = ∀ (i j : Fin k), i ≠ j → Disjoint (pt.verticesOf i) (pt.verticesOf j)
Instances For
A LatticePath'Tuple is intersecting if it is not non-intersecting
Equations
Instances For
Convert a LatticePath'Tuple to a PathTuple
Equations
Instances For
Convert a PathTuple to a LatticePath'Tuple
Equations
- LGV.pathTupleToLatticePath'Tuple pt = { paths := fun (i : Fin k) => LGV.pathToLatticePath' (pt.paths i), valid := ⋯ }
Instances For
The bijection between LatticePath'Tuple and PathTuple
Equations
- LGV.latticePath'TupleEquiv A B = { toFun := LGV.latticePath'TupleToPathTuple, invFun := LGV.pathTupleToLatticePath'Tuple, left_inv := ⋯, right_inv := ⋯ }
Instances For
The vertices of a converted path match the original vertices
The intersection property is preserved by the bijection