Documentation

AlgebraicCombinatorics.FPS.IntegerCompositions

Integer Compositions #

This file formalizes integer compositions and weak compositions, following Section sec.fps.intcomps of the source text.

Main definitions #

Main results #

Implementation notes #

This file defines Composition as List ℕ+, which is an alternative representation to Mathlib's Mathlib.Combinatorics.Enumerative.Composition which uses Composition n as a structure with blocks : List and proofs of positivity and sum. Both representations are equivalent; we use List ℕ+ here to follow the source text's presentation more directly.

References #

See the source LaTeX file AlgebraicCombinatorics/tex/FPS/IntegerCompositions.tex

Integer Compositions #

An integer composition is a finite tuple of positive integers. We represent it as a list of positive integers.

(Definition def.fps.comps, part (a))

Equations
Instances For

    The size of a composition is the sum of its entries.

    (Definition def.fps.comps, part (b))

    Equations
    Instances For

      The length of a composition is the number of parts. (We use len to avoid conflict with List.length.)

      (Definition def.fps.comps, part (c))

      Equations
      Instances For

        Basic @[simp] lemmas for size and len #

        @[simp]

        The size of the empty composition is 0.

        @[simp]

        The length of the empty composition is 0.

        @[simp]

        The size of a cons composition is the head value plus the tail size.

        @[simp]

        The length of a cons composition is the tail length plus 1.

        The size of a composition is at least its length, since each part is positive.

        Singleton constructor #

        @[simp]

        The size of a singleton composition is the value of its single part.

        @[simp]

        The length of a singleton composition is 1.

        Append operation #

        Concatenation of two compositions.

        Equations
        Instances For
          @[simp]

          The size of the concatenation of two compositions equals the sum of their sizes.

          @[simp]

          The length of the concatenation of two compositions equals the sum of their lengths.

          A composition of n is a composition whose size is n.

          (Definition def.fps.comps, part (d))

          Equations
          Instances For

            A composition of n into k parts is a composition with size n and length k.

            (Definition def.fps.comps, part (e))

            Equations
            Instances For

              Equivalence with Mathlib's Composition type #

              Convert a composition (List ℕ+) to a blocks list (List ℕ)

              Equations
              Instances For
                def AlgebraicCombinatorics.Composition.ofBlocks (blocks : List ) (hpos : ∀ {i : }, i blocks0 < i) :

                Convert a blocks list with positivity proof to a composition (List ℕ+)

                Equations
                Instances For
                  theorem AlgebraicCombinatorics.Composition.toBlocks_ofBlocks (blocks : List ) (hpos : ∀ {i : }, i blocks0 < i) :
                  (ofBlocks blocks ).toBlocks = blocks

                  Equivalence between our Composition.ofSize n and Mathlib's Composition n. This allows us to use Mathlib's composition_card theorem.

                  Equations
                  • One or more equations did not get rendered due to their size.
                  Instances For

                    Equivalence between Composition.ofSizeIntoParts n k and the filtered set of Mathlib compositions of n with length k.

                    Equations
                    • One or more equations did not get rendered due to their size.
                    Instances For

                      The empty list is the only composition of size 0.

                      Counting Compositions via Mathlib #

                      We prove the main counting theorem using Mathlib's Composition n type, which has a well-developed API including an equivalence with subsets of Fin (n-1).

                      The key insight is that compositions of n into k parts correspond bijectively to (k-1)-element subsets of {1, ..., n-1}, giving the count C(n-1, k-1).

                      Key lemma: for n > 0, the cardinality of the finset associated to a composition equals the length minus 1.

                      This follows from the structure of the compositionAsSetEquiv: it extracts the "interior" boundary points of a composition (those between 0 and n), and a composition of length k has exactly k-1 such interior points.

                      The cardinality of the associated finset plus 1 equals the composition length.

                      theorem AlgebraicCombinatorics.MathlibComposition.card_compositions_of_length (n k : ) (hn : 0 < n) (hk : 0 < k) :
                      {c : _root_.Composition n | c.length = k}.card = (n - 1).choose (k - 1)

                      Theorem thm.fps.comps.num-comps-n-k (using Mathlib's Composition): For n > 0 and k > 0, the number of compositions of n into k parts is C(n-1, k-1).

                      The proof establishes a bijection between compositions of length k and (k-1)-subsets of Fin (n-1), then uses the formula for counting subsets of a given size.

                      Theorem thm.fps.comps.num-comps-n-k: For n > 0 and k > 0, the number of compositions of n into k parts is Nat.choose (n-1) (k-1).

                      Note: The source text states this as C(n-1, n-k) = C(n-1, k-1) for n > 0, but C(n-1, n-k) uses integer binomial coefficients where C(-1, -k) = 0 for k > 0. In Lean's Nat.choose with truncating subtraction, Nat.choose (0-1) (0-k) = Nat.choose 0 0 = 1, which is incorrect for the case n = 0, k > 0. Additionally, when n > 0 and k = 0, the formula Nat.choose (n-1) (k-1) = Nat.choose (n-1) 0 = 1, but there are no compositions of n > 0 into 0 parts (the count should be 0).

                      Therefore, we require both n > 0 and k > 0, and handle edge cases separately.

                      For n > 0 and k = 0, there are no compositions (since compositions have positive parts, and the sum of zero positive integers is 0, not n).

                      For n = 0, the only composition is the empty one (into 0 parts). There are no compositions of 0 into k > 0 parts (since all parts must be positive).

                      Theorem thm.fps.comps.num-comps-n: The number of compositions of n is 2^(n-1) when n > 0, and 1 when n = 0.

                      This is proved by establishing an equivalence with Mathlib's Composition n and using composition_card from Mathlib.

                      For n > 0, the number of compositions of n is 2^(n-1).

                      Weak Compositions #

                      A weak composition is a finite tuple of nonnegative integers.

                      (Definition def.fps.wcomps, part (a))

                      Equations
                      Instances For

                        The size of a weak composition is the sum of its entries.

                        (Definition def.fps.wcomps, part (b))

                        Equations
                        Instances For

                          The length of a weak composition is the number of parts. (We use len to avoid conflict with List.length.)

                          (Definition def.fps.wcomps, part (c))

                          Equations
                          Instances For

                            Basic @[simp] lemmas for size and len #

                            @[simp]

                            The size of the empty weak composition is 0.

                            @[simp]

                            The length of the empty weak composition is 0.

                            @[simp]

                            The size of a cons weak composition is the head value plus the tail size.

                            @[simp]

                            The length of a cons weak composition is the tail length plus 1.

                            A weak composition of n is a weak composition whose size is n.

                            (Definition def.fps.wcomps, part (d))

                            Equations
                            Instances For

                              A weak composition of n into k parts is a tuple of k nonnegative integers summing to n.

                              (Definition def.fps.wcomps, part (e))

                              Equations
                              Instances For

                                Function representation of weak compositions #

                                Alternative representation of weak compositions as functions Fin k → ℕ. This is equivalent to ofSizeIntoParts n k but easier to work with for cardinality proofs.

                                Equations
                                Instances For

                                  Key lemma: sum of counts over a finite type equals cardinality.

                                  Equivalence between ofSizeIntoParts' n k and Sym (Fin k) n.

                                  Equations
                                  • One or more equations did not get rendered due to their size.
                                  Instances For

                                    Theorem thm.fps.comps.num-wcomps-n-k: The number of weak compositions of n into k parts is Nat.choose (n+k-1) n.

                                    The proof uses the "stars and bars" technique: weak compositions of n into k parts are in bijection with multisets of size n from an alphabet of size k (i.e., Sym (Fin k) n), which are counted by Nat.choose (n+k-1) n.

                                    Equivalence between list and function representations #

                                    Convert a list-based weak composition to a function-based one.

                                    Equations
                                    Instances For
                                      theorem AlgebraicCombinatorics.WeakComposition.ofFun_get {k : } (f : Fin k) (i : Fin k) :
                                      List.get (ofFun f) (Fin.cast i) = f i

                                      The sum of a list equals the Finset sum over its indices.

                                      The two representations (list-based and function-based) are equivalent. The forward direction converts a list [a₀, a₁, ..., aₖ₋₁] to the function i ↦ aᵢ. The backward direction converts a function f : Fin k → ℕ to the list [f(0), f(1), ..., f(k-1)].

                                      Equations
                                      • One or more equations did not get rendered due to their size.
                                      Instances For

                                        The set of all weak compositions of n into k parts is finite.

                                        Equations
                                        • One or more equations did not get rendered due to their size.

                                        Theorem thm.fps.comps.num-wcomps-n-k (first form): The number of weak compositions of n into k parts is Nat.choose (n+k-1) n.

                                        Alternative form: for k > 0, the number of weak compositions of n into k parts is Nat.choose (n+k-1) (k-1).

                                        For k = 0, the only weak composition is the empty one (which has size 0).

                                        Bijection between weak compositions of n into k parts and compositions of n+k into k parts. Adding 1 to each entry of a weak composition gives a composition.

                                        This is the key bijection used in the proof of Theorem thm.fps.comps.num-wcomps-n-k.

                                        Equations
                                        • One or more equations did not get rendered due to their size.
                                        Instances For

                                          Bounded Weak Compositions #

                                          A weak composition of n into k parts with entries bounded by p (i.e., each entry is in {0, 1, ..., p-1}).

                                          This is used in Theorem thm.fps.comps.num-wpcomps-n-k.

                                          Equations
                                          Instances For

                                            The set of bounded weak compositions is finite.

                                            Equations

                                            Generating Function Approach #

                                            The proof of Theorem thm.fps.comps.num-wpcomps-n-k uses generating functions. The generating function for bounded weak compositions is W_{k,p} = (∑_{i=0}^{p-1} x^i)^k, which equals ((1-x^p)/(1-x))^k = (1-x^p)^k * (1-x)^{-k}.

                                            Using binomial expansions:

                                            Convolving these gives the formula.

                                            The generating function for bounded weak compositions.

                                            Equations
                                            Instances For

                                              The geometric series identity: (∑_{i=0}^{p-1} x^i) * (1 - x) = 1 - x^p.

                                              Power of invOneSubPow: (invOneSubPow ℤ 1)^k = invOneSubPow ℤ k.

                                              The geometric series equals (1 - X^p) * (1 - X)^{-1}.

                                              The generating function equals (1-X^p)^k * (1-X)^{-k}.

                                              The coefficient of x^n in (1-x)^{-k} for k > 0.

                                              Key lemma: the coefficient of x^n in the generating function equals the count.

                                              This is the standard fact that [x^n](∑_{i<p} x^i)^k counts k-tuples in {0,...,p-1}^k summing to n. The proof uses the product rule for power series coefficients.

                                              theorem AlgebraicCombinatorics.BoundedWeakComposition.coeff_genFun_formula (n k p : ) :
                                              (PowerSeries.coeff n) (genFun k p) = jFinset.range (k + 1) with p * j n, (-1) ^ j * (k.choose j) * ((n - p * j + k - 1).choose (n - p * j))
                                              theorem AlgebraicCombinatorics.BoundedWeakComposition.card (n k p : ) :
                                              (Fintype.card (BoundedWeakComposition n k p)) = jFinset.range (k + 1) with p * j n, (-1) ^ j * (k.choose j) * ((n - p * j + k - 1).choose (n - p * j))

                                              Theorem thm.fps.comps.num-wpcomps-n-k: The number of k-tuples (α₁, α₂, ..., αₖ) ∈ {0, 1, ..., p-1}^k satisfying α₁ + α₂ + ... + αₖ = n is ∑_{j : p*j ≤ n} (-1)^j * C(k,j) * C(n - p*j + k - 1, n - p*j).

                                              Note: The sum is restricted to j with p * j ≤ n because when p * j > n, the mathematical binomial coefficient C(n - p*j + k - 1, n - p*j) should be 0 (as there are no compositions with negative sum), but Nat.choose with truncating subtraction would give a non-zero value.

                                              Proof Strategy #

                                              The proof uses generating functions. The generating function for bounded weak compositions is W_{k,p} = (∑_{i=0}^{p-1} x^i)^k, which equals ((1-x^p)/(1-x))^k = (1-x^p)^k * (1-x)^{-k}.

                                              Using binomial expansions:

                                              • (1-x^p)^k = ∑_{j=0}^k (-1)^j C(k,j) x^{pj}
                                              • (1-x)^{-k} = ∑_{m≥0} C(m+k-1, m) x^m

                                              Convolving these gives the formula.

                                              Binary Strings Identity #

                                              The cardinality of BoundedWeakComposition n k 2 (binary k-strings with n ones) is C(k, n). This is because choosing a binary string with n ones is equivalent to choosing which n of the k positions will be 1.

                                              theorem AlgebraicCombinatorics.binom_sum_identity (n k : ) :
                                              (k.choose n) = jFinset.range (k + 1) with 2 * j n, (-1) ^ j * (k.choose j) * ((n - 2 * j + k - 1).choose (n - 2 * j))

                                              Proposition prop.fps.comps.num-w2comps-n-k-id: For n, k ∈ ℕ, we have C(k, n) = ∑_{j : 2*j ≤ n} (-1)^j * C(k,j) * C(n - 2j + k - 1, n - 2j).

                                              This identity arises from the special case p = 2 of Theorem thm.fps.comps.num-wpcomps-n-k, where we count binary strings (k-tuples of 0s and 1s) with exactly n ones.

                                              Proof Strategy #

                                              The proof uses generating functions:

                                              1. Binary k-strings with n ones are counted by C(k, n) (choosing which n positions are 1s)
                                              2. By Theorem thm.fps.comps.num-wpcomps-n-k with p = 2, the count also equals the sum formula
                                              3. The generating function identity (1+X)^k = (1-X²)^k / (1-X)^k underlies this:
                                                • (1-X²) = (1-X)(1+X), so (1-X²)^k / (1-X)^k = (1+X)^k
                                                • Coefficient of X^n in (1+X)^k is C(k, n)
                                                • Coefficient of X^n in (1-X²)^k * (1-X)^{-k} gives the sum formula via convolution

                                              Note: The sum is restricted to j with 2 * j ≤ n because when 2j > n, the term contributes 0 (no valid compositions exist with negative sum).