The Generating Function of a Weighted Set #
This file formalizes the theory of weighted sets and their weight generating functions, following Section sec.gf.weighted-set of the Algebraic Combinatorics notes.
A weighted set is a set equipped with a weight function to ℕ. When the set is "finite-type" (only finitely many elements of each weight), we can define its weight generating function as a formal power series.
Main Definitions #
WeightedSet: A set with a weight function to ℕWeightedSet.IsFiniteType: Predicate for finite-type weighted setsWeightedSet.weightGenFun: The weight generating function of a finite-type weighted setWeightedSet.Isomorphism: Weight-preserving bijections between weighted setsWeightedSet.disjointUnion: Disjoint union of weighted sets (A + B)WeightedSet.prod: Product of weighted sets (A × B) with additive weightsWeightedSet.pow: Cartesian power of a weighted setWeightedSet.tuples: Infinite disjoint union W^0 + W^1 + W^2 + ... (Kleene star)
Main Results #
WeightedSet.weightGenFun_eq_of_isomorphic: Isomorphic weighted sets have equal generating functionsWeightedSet.weightGenFun_disjointUnion: ḡ(A + B) = ḡ(A) + ḡ(B)WeightedSet.weightGenFun_prod: ḡ(A × B) = ḡ(A) · ḡ(B)WeightedSet.weightGenFun_pow: ḡ(A^k) = ḡ(A)^kDominoTilingsZ.tiling_decomposition_isomorphism: D ≅ F^0 + F^1 + F^2 + ... (Lemma lem.gf.weighted-set.domino.fd)
Applications #
The file includes applications to:
- Counting compositions (recovering the formula for the generating function of compositions)
- Domino tilings of height-2 rectangles (connection to Fibonacci numbers)
Note: Height-3 domino tilings are handled in Details/DominoTilings.lean.
References #
- [Flajolet and Sedgewick, Analytic Combinatorics, Part A][FlaSed09]
- [Fink, Enumerative Combinatorics, §3.3-§3.4][Fink17]
Tags #
weighted set, generating function, combinatorial class, domino tiling
Weighted Sets #
A weighted set is a type equipped with a weight function to ℕ. (Definition \ref{def.gf-ws.weighted-sets}(a))
- weight : α → ℕ
The weight function assigning a natural number to each element
Instances For
A weighted set is finite-type if for each n ∈ ℕ, there are only finitely many elements of weight n. (Definition \ref{def.gf-ws.weighted-sets}(b))
Instances For
The set of elements of a given weight in a weighted set
Instances For
For a finite-type weighted set, the count of elements of weight n
Equations
- W.countOfWeight hft n = ⋯.toFinset.card
Instances For
Weight Generating Function #
The weight generating function of a finite-type weighted set is the FPS ∑_{n ∈ ℕ} (# of elements of weight n) · x^n. (Definition \ref{def.gf-ws.weighted-sets}(c))
Equations
- W.weightGenFun hft = PowerSeries.mk fun (n : ℕ) => ↑(W.countOfWeight hft n)
Instances For
Alternative characterization: weightGenFun = ∑_{a ∈ A} x^{|a|}
Isomorphisms of Weighted Sets #
An isomorphism between weighted sets is a weight-preserving bijection. (Definition \ref{def.gf-ws.weighted-sets}(d))
The underlying bijection
The bijection preserves weights
Instances For
Two weighted sets are isomorphic if there exists an isomorphism between them. (Definition \ref{def.gf-ws.weighted-sets}(e))
Equations
- (W₁ ≅ᵥ W₂) = Nonempty (W₁.Isomorphism W₂)
Instances For
Equations
- WeightedSet.«term_≅ᵥ_» = Lean.ParserDescr.trailingNode `WeightedSet.«term_≅ᵥ_» 1022 0 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ≅ᵥ ") (Lean.ParserDescr.cat `term 0))
Instances For
Isomorphic finite-type weighted sets have equal weight generating functions. (Proposition \ref{prop.gf-ws.iso})
Disjoint Union of Weighted Sets #
The disjoint union of two weighted sets, with weights inherited from each component. (Definition \ref{def.gf-ws.djun})
Instances For
Equations
- WeightedSet.«term_+ᵥ_» = Lean.ParserDescr.trailingNode `WeightedSet.«term_+ᵥ_» 65 65 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " +ᵥ ") (Lean.ParserDescr.cat `term 66))
Instances For
The disjoint union of finite-type weighted sets is finite-type.
The weight generating function of a disjoint union is the sum of the generating functions. (Proposition \ref{prop.gf-ws.djun})
Product of Weighted Sets #
The product of two weighted sets, with weight defined as the sum of component weights. (Definition \ref{def.gf-ws.prod})
Equations
Instances For
Equations
- WeightedSet.«term_×ᵥ_» = Lean.ParserDescr.trailingNode `WeightedSet.«term_×ᵥ_» 70 70 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ×ᵥ ") (Lean.ParserDescr.cat `term 71))
Instances For
The product of finite-type weighted sets is finite-type. (Proof of first part of Proposition \ref{prop.gf-ws.prod})
The weight generating function of a product is the product of the generating functions. (Proposition \ref{prop.gf-ws.prod})
This is the key theorem showing that the weight generating function respects Cartesian products: ḡ(A × B) = ḡ(A) · ḡ(B). The proof partitions the pairs of total weight n by the weight of the first component, showing this equals the convolution sum that defines multiplication of power series.
Cartesian Powers #
The k-th Cartesian power of a weighted set. Weight of (a₁, ..., aₖ) is |a₁| + ... + |aₖ|.
Instances For
The k-th power of a finite-type weighted set is finite-type.
Helper: pow (n+1) is isomorphic to W × pow n
Equations
- W.pow_succ_equiv n = { toEquiv := (Fin.succFunEquiv α n).trans (Equiv.prodComm (Fin n → α) α), weight_eq := ⋯ }
Instances For
The weight generating function of A^k is (ḡ(A))^k. (Proposition \ref{prop.gf-ws.pow})
Infinite Disjoint Union (Tuples) #
The infinite disjoint union W^0 + W^1 + W^2 + ... of all tuples of elements. This is the "Kleene star" construction on weighted sets. An element is a pair (k, f) where k ∈ ℕ and f : Fin k → α is a k-tuple. The weight of (k, f) is the sum of weights of the entries: ∑ᵢ |f(i)|.
Equations
Instances For
A weighted set has positive weights if every element has weight ≥ 1
Equations
- W.HasPositiveWeights = ∀ (a : α), W.weight a ≥ 1
Instances For
The tuples weighted set is finite-type if the original is finite-type and has positive weights.
Note: The hypothesis hpos : W.HasPositiveWeights is necessary. Without it, the theorem is false:
if W has elements of weight 0, then for any weight m, there are infinitely many tuples of weight m
(we can have arbitrarily many weight-0 elements in a tuple). For example, if W = ℕ with weight = id,
then tuples of weight 2 include ⟨1, ![2]⟩, ⟨2, ![0, 2]⟩, ⟨3, ![0, 0, 2]⟩, etc.
The key insight is that with positive weights, a tuple of length n has weight ≥ n, so for weight m, we only need to consider tuples of length ≤ m.
Examples and Applications #
Binary Strings (Example \ref{exa.ws.bin-string1}) #
Binary strings (finite tuples of 0s and 1s) with weight = length
Equations
- WeightedSetExamples.BinaryStrings = { weight := List.length }
Instances For
The binary strings weighted set is finite-type
The generating function of binary strings is 1/(1-2x). Since (mk 1) represents 1 + x + x² + ... = 1/(1-x), we express 1/(1-2x) differently.
Positive Integers #
The positive integers with weight = value
Equations
- WeightedSetExamples.PositiveIntegers = { weight := fun (n : ℕ+) => ↑n }
Instances For
Positive integers form a finite-type weighted set
The generating function of positive integers is x + x² + x³ + ... = x/(1-x)
Compositions #
Compositions of length k are k-tuples of positive integers
Instances For
Compositions form a finite-type weighted set
The generating function of compositions of length k is (x/(1-x))^k
Domino Tilings #
Shapes and Dominos (Definition \ref{def.domino.shapes-and-tilings}) #
A shape is a subset of ℤ² (Definition \ref{def.domino.shapes-and-tilings}(a))
Instances For
Equations
- One or more equations did not get rendered due to their size.
- DominoTilingsZ.instDecidableEqDomino.decEq (DominoTilingsZ.Domino.horizontal i j) (DominoTilingsZ.Domino.vertical i_1 j_1) = isFalse ⋯
- DominoTilingsZ.instDecidableEqDomino.decEq (DominoTilingsZ.Domino.vertical i j) (DominoTilingsZ.Domino.horizontal i_1 j_1) = isFalse ⋯
Instances For
The shape of a domino is nonempty
The shape of a domino is finite
A domino tiling of a shape S is a set partition of S into dominos (Definition \ref{def.domino.shapes-and-tilings}(d))
The set of dominos in the tiling
- pairwise_disjoint : self.dominos.PairwiseDisjoint Domino.toShape
The dominos are pairwise disjoint
The union of dominos equals the shape
Instances For
The empty tiling of an empty shape
Equations
- DominoTilingsZ.Tiling.empty = { dominos := ∅, pairwise_disjoint := DominoTilingsZ.Tiling.empty._proof_1, cover := DominoTilingsZ.Tiling.empty._proof_2 }
Instances For
The number of domino tilings of the n × m rectangle (Definition \ref{def.domino.shapes-and-tilings}(e))
This is defined as the cardinality of the type of all tilings. Note: For this to be meaningful, the set of tilings must be finite, which holds for any finite rectangle.
Equations
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Height-2 Rectangle Tilings #
Domino tilings of height-2 rectangles, with weight = width of rectangle
Equations
- DominoTilingsZ.TilingsHeight2 = { weight := fun (x : (n : ℕ) × DominoTilingsZ.Tiling (DominoTilingsZ.Rectangle n 2)) => match x with | ⟨n, snd⟩ => n }
Instances For
TilingsHeight2 is a finite-type weighted set
A tiling is faultfree if it is nonempty and has no fault
Equations
- DominoTilingsZ.isFaultfree n T = (n > 0 ∧ ∀ (k : ℕ), ¬DominoTilingsZ.hasFault n T k)
Instances For
Faultfree tilings of height-2 rectangles
Equations
- One or more equations did not get rendered due to their size.
Instances For
FaultfreeTilingsHeight2 is finite-type
Helper lemmas for faultfree classification #
The only faultfree tilings of height-2 rectangles have width 1 or 2
The unique tiling of the 1×2 rectangle (one vertical domino)
Equations
- DominoTilingsZ.tiling_1_2 = { dominos := {DominoTilingsZ.Domino.vertical 1 1}, pairwise_disjoint := DominoTilingsZ.tiling_1_2._proof_1, cover := DominoTilingsZ.tiling_1_2._proof_2 }
Instances For
The 1×2 tiling is faultfree
Every tiling of the 1×2 rectangle equals tiling_1_2
The faultfree tiling of the 1×2 rectangle as a Subtype element
Equations
Instances For
Every element of FaultfreeTilingsHeight2 with weight 1 equals faultfreeTiling_1_2
There is exactly one faultfree tiling of width 1 (one vertical domino)
The unique faultfree tiling of width 2: two horizontal dominos
Equations
- One or more equations did not get rendered due to their size.
Instances For
The two horizontal dominos tiling is faultfree
Any faultfree tiling of Rectangle 2 2 equals twoHorizontalDominos
There is exactly one faultfree tiling of width 2 (two horizontal dominos)
For n ≠ 1 and n ≠ 2, there are no faultfree tilings of width n
The generating function of faultfree height-2 tilings is x + x²
Decomposition Lemma (lem.gf.weighted-set.domino.fd) #
Helper definitions for tiling composition/decomposition #
Shift a domino horizontally by an offset
Equations
- (DominoTilingsZ.Domino.horizontal i j).shift offset = DominoTilingsZ.Domino.horizontal (i + offset) j
- (DominoTilingsZ.Domino.vertical i j).shift offset = DominoTilingsZ.Domino.vertical (i + offset) j
Instances For
Shift a set of dominos
Equations
- DominoTilingsZ.shiftDominos ds offset = (fun (d : DominoTilingsZ.Domino) => d.shift offset) '' ds
Instances For
Shifting is injective
Shifting by 0 is the identity
Shift a tiling to a new position
Equations
Instances For
The tiling of the empty rectangle (width 0)
Equations
Instances For
Composition: Concatenating faultfree tilings #
Shifting by natural 0 is the identity
The set of dominos for the i-th component in the composition, shifted appropriately
Equations
- DominoTilingsZ.composeTilings_component_dominos k ts i = (fun (d : DominoTilingsZ.Domino) => d.shiftNat (DominoTilingsZ.partialWidthSum k ts i)) '' (↑(ts i).snd).dominos
Instances For
The union of all shifted dominos for composition
Equations
- DominoTilingsZ.composeTilings_dominos k ts = ⋃ (i : Fin k), DominoTilingsZ.composeTilings_component_dominos k ts i
Instances For
Helper: Dominos from different components have disjoint x-coordinate ranges
The composition function: given a tuple of faultfree tilings, concatenate them horizontally to produce a single tiling.
Each faultfree tiling is shifted by the cumulative width of the previous tilings, and the union of all shifted dominos forms the composed tiling.
This is the inverse of decomposeTiling.
Equations
- DominoTilingsZ.composeTilings k ts = ⟨∑ i : Fin k, (ts i).fst, { dominos := DominoTilingsZ.composeTilings_dominos k ts, pairwise_disjoint := ⋯, cover := ⋯ }⟩
Instances For
For k = 1, the composed dominos equal the original dominos (shifted by 0)
For k = 1, the width of the composed tiling equals the width of the single component
For k = 1, the composed tiling equals the single component (as Tilings)
For k = 1, the composed tiling is faultfree
Helper lemma: The width of composeTilings with a prepended element equals the first width plus the sum of the remaining widths. This is used in proving composeTilings_decomposeTiling.
Helper lemma: When we compose with a prepended element, if the rest composes to a specific width and tiling, then the total width equals first_width + rest_width.
Decomposition: Cutting at faults #
Infrastructure for restricting tilings at faults #
A domino is in the left part (all x-coordinates ≤ k)
Equations
- d.inLeftPart k = ∀ p ∈ d.toShape, p.1 ≤ ↑k
Instances For
A domino is in the right part (all x-coordinates ≥ k+1)
Equations
- d.inRightPart k = ∀ p ∈ d.toShape, p.1 ≥ ↑k + 1
Instances For
Restrict a tiling to the left part at a fault position
Equations
- DominoTilingsZ.restrictTilingLeft n T k hk = { dominos := {d : DominoTilingsZ.Domino | d ∈ T.dominos ∧ d.inLeftPart k}, pairwise_disjoint := ⋯, cover := ⋯ }
Instances For
restrictTilingLeft does not depend on the proof of hasFault
restrictTilingRight does not depend on the proof of hasFault
The left restriction at a fault is faultfree if k is the smallest fault
The original dominos equal the union of left part and shifted right part
The set of fault positions in a tiling
Equations
- DominoTilingsZ.faultPositions n T = {k : ℕ | DominoTilingsZ.hasFault n T k}
Instances For
The fault positions form a finite set (bounded by n)
The minimum fault position in a tiling (when faults exist)
Equations
- DominoTilingsZ.minFault n T hne = ⋯.toFinset.min' ⋯
Instances For
The minimum fault is indeed a fault
The minimum fault is a hasFault
The minimum fault is less than or equal to any other fault
Decidability instance for faultPositions.Nonempty
A faultfree tiling has no faults, so faultPositions is empty
A faultfree tiling has non-nonempty faultPositions
Helper lemmas for k >= 2 case of decomposeTiling_composeTilings #
For k >= 2, the composed tiling has a fault at position (ts 0).1
For k >= 1, there are no faults at positions less than (ts 0).1 in the composed tiling
The minimum fault in a composed tiling with k >= 2 components is at (ts 0).1
Lemmas relating restrictTiling to composeTilings #
The width of composing the tail equals the total width minus the first component width
Dominos from component 0 are in the left part at position (ts 0).1
Dominos from component i >= 1 are in the right part at position (ts 0).1
The left restriction of a composed tiling at the first boundary has the same dominos as the first component
The left restriction of a composed tiling equals the first component's tiling.
This follows from restrictTilingLeft_composeTilings_dominos via Tiling.ext.
Dominos from component i shifted and then unshifted by k gives back the original
The partial width sum for the tail equals the original minus (ts 0).1
The right restriction of a composed tiling at the first boundary has the same dominos as the composition of the tail
The right restriction of a composed tiling has the same dominos as the composition of the tail.
Note: The tilings have different types (different width parameters), so we state this
as a domino equality rather than a tiling equality. Use Tiling.ext with the width
equality composeTilings_tail_width to convert to tiling equality when needed.
The right restriction of a composed tiling equals the composition of the tail.
This combines the width equality composeTilings_tail_width with the domino equality
restrictTilingRight_composeTilings_dominos_eq to give a full tiling equality.
Note: The two tilings have the same type because:
- restrictTilingRight has width (composeTilings k ts).1 - (ts 0).1
- composeTilings (k-1) (tail ts) has width (composeTilings k ts).1 - (ts 0).1 (by composeTilings_tail_width)
The decomposition function: given a tiling of a height-2 rectangle, produce a tuple of faultfree tilings by cutting along all faults.
For example, a tiling with faults at positions k₁ < k₂ < ... < kₘ decomposes into m+1 faultfree tilings of widths k₁, k₂-k₁, ..., n-kₘ.
The empty tiling (n=0) decomposes into the empty tuple (k=0).
Implementation: We recursively find the minimum fault position, cut the tiling there, and decompose the right part. The left part at a minimum fault is always faultfree. If no faults exist, the entire tiling is faultfree and returned as a singleton.
Equations
- One or more equations did not get rendered due to their size.
- DominoTilingsZ.decomposeTiling 0 x_2 = ⟨0, Fin.elim0⟩
Instances For
Decomposing a tiling with faults at the minimum fault position. This characterizes the structure of decomposeTiling when faults exist.
The width of decomposeTiling when faults exist equals m+1 where m is the count from decomposing the right part. This is useful for proving composeTilings_decomposeTiling.
Decomposition followed by composition gives back the original tiling
Decomposing a faultfree tiling returns a singleton tuple containing the original tiling.
This is a key helper for proving decomposeTiling_composeTilings.
Decomposition is invariant under type cast (subst). This is key for handling dependent types in the inverse proofs.
Decomposition depends only on width and dominos. If two tilings have the same width and dominos, their decompositions are equal.
Composition followed by decomposition gives back the original tuple.
This theorem proves that composing faultfree tilings and then decomposing recovers the original tuple of tilings.
The proof handles two cases:
- If k = 0 (empty tuple), the composed tiling is empty (width 0), and decomposeTiling returns the empty tuple by definition.
- If k > 0, the composed tiling has positive width, and we need to show that the faults in the composed tiling occur exactly at the partial width sums, so decomposing at those faults recovers the original pieces.
The sum of widths of the faultfree tilings equals the width of the original. This is the key property that makes the decomposition weight-preserving.
Main decomposition isomorphism (Lemma \ref{lem.gf.weighted-set.domino.fd}):
Any domino tiling of a height-2 rectangle can be decomposed uniquely into a tuple of faultfree tilings of (usually smaller) height-2 rectangles, by cutting it along its faults.
This gives an isomorphism of weighted sets: D ≅ F⁰ + F¹ + F² + F³ + ... where D = TilingsHeight2 and F = FaultfreeTilingsHeight2.
The isomorphism preserves weights: the sum of the widths of the faultfree tilings in the tuple equals the width of the original tiling.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Helper definitions for the Fibonacci recurrence bijection #
Prepend a vertical domino to a tiling of Rectangle m 2, giving a tiling of Rectangle (m+1) 2.
The new tiling has dominos = {vertical 1 1} ∪ (T.dominos shifted right by 1). This is the inverse of restricting at fault 1 when a vertical domino is present.
Equations
- DominoTilingsZ.prependVertical m T = { dominos := {DominoTilingsZ.Domino.vertical 1 1} ∪ (fun (d : DominoTilingsZ.Domino) => d.shiftNat 1) '' T.dominos, pairwise_disjoint := ⋯, cover := ⋯ }
Instances For
The vertical domino is not in the image of shifted dominos from Rectangle m 2.
Prepend a pair of horizontal dominos to a tiling of Rectangle m 2, giving a tiling of Rectangle (m+2) 2.
The new tiling has dominos = {horizontal 1 1, horizontal 1 2} ∪ (T.dominos shifted right by 2). This is the inverse of restricting at fault 2 when horizontal dominos are present.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The horizontal dominos are not in the image of shifted dominos from Rectangle m 2.
The vertical domino at (1,1) is not in the image of dominos shifted by 2.
The Fibonacci recurrence for tiling counts: d_{n+2,2} = d_{n,2} + d_{n+1,2}.
This follows from the bijection: Tiling (Rectangle (n+2) 2) ≃ Tiling (Rectangle n 2) ⊕ Tiling (Rectangle (n+1) 2)
The bijection classifies tilings based on what covers the first column:
- If a vertical domino covers (1,1)-(1,2): removing it and shifting gives a tiling of Rectangle (n+1) 2
- If horizontal dominos cover (1,1)-(2,1) and (1,2)-(2,2): removing them and shifting gives a tiling of Rectangle n 2
This is a classical result in combinatorics.
The count of tilings at weight n equals the number of tilings of R_{n,2}
The generating function of height-2 tilings equals 1/(1-x-x²), which is the Fibonacci generating function
Height-3 Rectangle Tilings #
The set of dominos that fit within a rectangle
Equations
Instances For
The set of dominos in a rectangle is finite
A tiling's dominos are contained in DominosInRectangle
The set of tilings of a rectangle is finite