Documentation

CompPoly.Univariate.Basic

Computable Univariate Polynomials #

This file defines CPolynomial R, the type of canonical univariate polynomials. Canonicality is tracked semantically by requiring the last stored coefficient, when present, to be nonzero.

This provides a unique representation for each polynomial, enabling stronger extensionality properties compared to the raw CPolynomial.Raw type.

def CompPoly.CPolynomial (R : Type u_2) [Zero R] :
Type u_2

Computable univariate polynomials are represented canonically with no trailing zeros.

A polynomial p : CPolynomial.Raw R is canonical if its last stored coefficient is nonzero whenever the underlying array is nonempty. This gives an instance-stable carrier while keeping the raw normalization algorithms available separately.

TODO optimizations may be had by trimming only at the end of iterative operations

Equations
Instances For
    theorem CompPoly.CPolynomial.ext {R : Type u_1} [Zero R] {p q : CPolynomial R} (h : p = q) :
    p = q

    Extensionality for canonical polynomials.

    theorem CompPoly.CPolynomial.ext_iff {R : Type u_1} [Zero R] {p q : CPolynomial R} :
    p = q p = q

    Canonical polynomials coerce to raw polynomials.

    Equations

    The zero polynomial is canonical without any normalization assumptions.

    Equations

    The zero polynomial provides the inhabited instance.

    Equations
    instance CompPoly.CPolynomial.instBEq (R : Type u_2) [Zero R] [BEq R] :

    CPolynomial R has BEq when R does, comparing the underlying coefficient arrays.

    Equations

    CPolynomial R has LawfulBEq when R does: p == q iff p = q.

    @[simp]
    theorem CompPoly.CPolynomial.trim_eq {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] (p : CPolynomial R) :
    (↑p).trim = p

    Canonical computable polynomials are trim-stable.

    Addition of canonical polynomials (result is canonical).

    Equations
    theorem CompPoly.CPolynomial.add_comm {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p q : CPolynomial R) :
    p + q = q + p
    theorem CompPoly.CPolynomial.add_assoc {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p q r : CPolynomial R) :
    p + q + r = p + (q + r)
    theorem CompPoly.CPolynomial.zero_add {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p : CPolynomial R) :
    0 + p = p
    theorem CompPoly.CPolynomial.add_zero {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p : CPolynomial R) :
    p + 0 = p
    def CompPoly.CPolynomial.nsmul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (n : ) (p : CPolynomial R) :

    Scalar multiplication by a natural number (result is canonical).

    Equations
    Instances For
      theorem CompPoly.CPolynomial.nsmul_zero {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p : CPolynomial R) :
      nsmul 0 p = 0
      theorem CompPoly.CPolynomial.nsmul_succ {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (n : ) (p : CPolynomial R) :
      nsmul (n + 1) p = nsmul n p + p

      Multiplication of canonical polynomials.

      The product of two canonical polynomials is canonical because multiplication preserves the "no trailing zeros" property.

      Equations

      The constant polynomial 1 is canonical, and is the Unit for multiplication.

      This is #[1], which has no trailing zeros.

      This proof does not work without the assumption that R is non-trivial.

      Equations
      @[reducible]
      def CompPoly.CPolynomial.coeff {R : Type u_1} [Zero R] (p : CPolynomial R) (i : ) :
      R

      The coefficient of X^i in the polynomial. Returns 0 if i is out of bounds.

      Equations
      Instances For
        def CompPoly.CPolynomial.C {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] (r : R) :

        The constant polynomial C r.

        Equations
        Instances For
          def CompPoly.CPolynomial.monomial {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [DecidableEq R] (n : ) (c : R) :

          Construct a canonical monomial c * X^n as a CPolynomial R.

          The result is canonical (no trailing zeros) when c ≠ 0. For example, monomial 2 3 represents 3 * X^2.

          Note: If c = 0, this returns 0 (the zero polynomial).

          Equations
          Instances For

            Return the degree of a CPolynomial.

            Equations
            Instances For

              Natural number degree of a canonical polynomial.

              Returns the degree as a natural number. For the zero polynomial, returns 0. This matches Mathlib's Polynomial.natDegree API.

              Equations
              Instances For

                Return the leading coefficient of a CPolynomial as the last coefficient of the trimmed array, or 0 if the trimmed array is empty.

                Equations
                Instances For
                  def CompPoly.CPolynomial.eval {R : Type u_1} [Semiring R] (x : R) (p : CPolynomial R) :
                  R

                  Evaluate a polynomial at a point.

                  Equations
                  Instances For
                    def CompPoly.CPolynomial.eval₂ {R : Type u_1} {S : Type u_2} [Semiring R] [Semiring S] (f : R →+* S) (x : S) (p : CPolynomial R) :
                    S

                    Evaluate at x : S via a ring hom f : R →+* S; eval₂ f x p = f(a₀) + f(a₁)*x + f(a₂)*x² + ....

                    Equations
                    Instances For

                      The support of a polynomial: indices with nonzero coefficients.

                      Equations
                      Instances For

                        Number of coefficients (length of the underlying array).

                        Equations
                        Instances For

                          Upper bound on degree: size - 1 if non-empty, if empty.

                          Equations
                          Instances For

                            Convert degreeBound to a natural number by sending to 0.

                            Equations
                            Instances For
                              def CompPoly.CPolynomial.monic {R : Type u_1} [Zero R] [One R] [BEq R] (p : CPolynomial R) :

                              Check if a CPolynomial is monic, i.e. its leading coefficient is 1.

                              Equations
                              Instances For

                                The polynomial with the constant term removed; coeff (divX p) i = coeff p (i + 1).

                                Equations
                                Instances For
                                  theorem CompPoly.CPolynomial.coeff_C {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] (r : R) (i : ) :
                                  (C r).coeff i = if i = 0 then r else 0

                                  Coefficient of the constant polynomial C r.

                                  theorem CompPoly.CPolynomial.coeff_X {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] (i : ) :
                                  X.coeff i = if i = 1 then 1 else 0

                                  Coefficient of the variable X.

                                  @[simp]
                                  theorem CompPoly.CPolynomial.coeff_zero {R : Type u_1} [Zero R] (i : ) :
                                  coeff 0 i = 0

                                  Coefficient of the zero polynomial.

                                  theorem CompPoly.CPolynomial.coeff_one {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] (i : ) :
                                  coeff 1 i = if i = 0 then 1 else 0

                                  Coefficient of the constant polynomial 1.

                                  theorem CompPoly.CPolynomial.coeff_add {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p q : CPolynomial R) (i : ) :
                                  (p + q).coeff i = p.coeff i + q.coeff i

                                  Coefficient of a sum.

                                  theorem CompPoly.CPolynomial.coeff_monomial {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [DecidableEq R] (n i : ) (c : R) :
                                  (monomial n c).coeff i = if i = n then c else 0

                                  Coefficient of a monomial.

                                  theorem CompPoly.CPolynomial.coeff_mul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p q : CPolynomial R) (k : ) :
                                  (p * q).coeff k = iFinset.range (k + 1), p.coeff i * q.coeff (k - i)

                                  Coefficient of a product (convolution sum).

                                  theorem CompPoly.CPolynomial.eq_iff_coeff {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] {p q : CPolynomial R} :
                                  p = q ∀ (i : ), p.coeff i = q.coeff i

                                  Two polynomials are equal iff they have the same coefficients.

                                  theorem CompPoly.CPolynomial.monomial_add {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [DecidableEq R] (n : ) (a b : R) :
                                  monomial n (a + b) = monomial n a + monomial n b

                                  Monomials are additive in their coefficient.

                                  theorem CompPoly.CPolynomial.eq_zero_iff_coeff_zero {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] {p : CPolynomial R} :
                                  p = 0 ∀ (i : ), p.coeff i = 0

                                  Zero characterization: p = 0 iff all coefficients are zero.

                                  theorem CompPoly.CPolynomial.mem_support_iff {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] (p : CPolynomial R) (i : ) :
                                  i p.support p.coeff i 0

                                  An index is in the support iff the coefficient there is nonzero.

                                  The support is empty iff the polynomial is zero.

                                  theorem CompPoly.CPolynomial.eval_eq_sum_support {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p : CPolynomial R) (x : R) :
                                  eval x p = ip.support, p.coeff i * x ^ i

                                  Evaluation equals the sum over support of coefficients times powers.

                                  theorem CompPoly.CPolynomial.eval₂_eq_sum_support {R : Type u_1} {S : Type u_2} [Semiring R] [BEq R] [LawfulBEq R] [Semiring S] (f : R →+* S) (p : CPolynomial R) (x : S) :
                                  eval₂ f x p = ip.support, f (p.coeff i) * x ^ i

                                  Evaluation via a ring hom equals the sum over support of mapped coefficients times powers.

                                  theorem CompPoly.CPolynomial.coeff_C_mul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] (p : CPolynomial R) (c : R) (i : ) :
                                  (C c * p).coeff i = c * p.coeff i
                                  theorem CompPoly.CPolynomial.coeff_X_mul_succ {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] (p : CPolynomial R) (n : ) :
                                  (X * p).coeff (n + 1) = p.coeff n

                                  Lemmas on coefficients and multiplication by X.

                                  theorem CompPoly.CPolynomial.coeff_mul_X_succ {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] (p : CPolynomial R) (n : ) :
                                  (p * X).coeff (n + 1) = p.coeff n
                                  theorem CompPoly.CPolynomial.coeff_extract_succ {R : Type u_1} [Zero R] (a : Raw R) (i : ) :
                                  Raw.coeff (Array.extract a 1) i = a.coeff (i + 1)
                                  theorem CompPoly.CPolynomial.coeff_divX {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] (p : CPolynomial R) (i : ) :
                                  p.divX.coeff i = p.coeff (i + 1)
                                  theorem CompPoly.CPolynomial.divX_size_lt {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] (p : CPolynomial R) (hp : Array.size p > 0) :
                                  theorem CompPoly.CPolynomial.induction_on {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] {P : CPolynomial RProp} (p : CPolynomial R) (h0 : P 0) (hC : ∀ (a : R), P (C a)) (hadd : ∀ (p q : CPolynomial R), P pP qP (p + q)) (hX : ∀ (p : CPolynomial R), P pP (X * p)) :
                                  P p

                                  Induction principle for polynomials (mirrors mathlib's Polynomial.induction_on).

                                  theorem CompPoly.CPolynomial.degree_eq_support_max_aux_degree {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] (p : CPolynomial R) {k : Fin (Array.size p)} (hk : (↑p).lastNonzero = some k) :
                                  p.degree = k

                                  Lemma for degree_eq_support_max: degree in terms of lastNonzero.

                                  theorem CompPoly.CPolynomial.degree_eq_support_max_aux_lastNonzero {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] (p : CPolynomial R) (hp : p 0) :
                                  ∃ (k : Fin (Array.size p)), (↑p).lastNonzero = some k
                                  theorem CompPoly.CPolynomial.degree_eq_support_max {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] (p : CPolynomial R) (hp : p 0) :
                                  np.support, p.degree = n

                                  Degree equals the maximum of the support when the polynomial is non-zero. Here p.degree = some n where n is the maximum index in p.support.

                                  theorem CompPoly.CPolynomial.degree_eq_natDegree {R : Type u_1} [Zero R] (p : CPolynomial R) (hp : p 0) :

                                  When p ≠ 0, degree p equals natDegree p (as WithBot).

                                  Lemma for computing the degree of 0 in proofs.

                                  theorem CompPoly.CPolynomial.natDegree_eq_support_sup {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] (p : CPolynomial R) :
                                  p.natDegree = p.support.sup fun (n : ) => n

                                  The natural degree is the maximum element of the support.

                                  Quotient of p by a monic polynomial q. Matches Mathlib's Polynomial.divByMonic.

                                  Equations
                                  Instances For

                                    Remainder of p modulo a monic polynomial q. Matches Mathlib's Polynomial.modByMonic.

                                    Equations
                                    Instances For
                                      def CompPoly.CPolynomial.div {R : Type u_1} [Field R] [BEq R] [LawfulBEq R] (p q : CPolynomial R) :

                                      Quotient of p by q (when R is a field).

                                      Equations
                                      Instances For
                                        def CompPoly.CPolynomial.mod {R : Type u_1} [Field R] [BEq R] [LawfulBEq R] (p q : CPolynomial R) :

                                        Remainder of p modulo q (when R is a field).

                                        Equations
                                        Instances For
                                          theorem CompPoly.CPolynomial.one_mul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] (p : CPolynomial R) :
                                          1 * p = p
                                          theorem CompPoly.CPolynomial.mul_one {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] (p : CPolynomial R) :
                                          p * 1 = p
                                          theorem CompPoly.CPolynomial.mul_assoc {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p q r : CPolynomial R) :
                                          p * q * r = p * (q * r)
                                          theorem CompPoly.CPolynomial.zero_mul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p : CPolynomial R) :
                                          0 * p = 0
                                          theorem CompPoly.CPolynomial.mul_zero {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p : CPolynomial R) :
                                          p * 0 = 0
                                          theorem CompPoly.CPolynomial.mul_add {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p q r : CPolynomial R) :
                                          p * (q + r) = p * q + p * r
                                          theorem CompPoly.CPolynomial.add_mul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p q r : CPolynomial R) :
                                          (p + q) * r = p * r + q * r
                                          theorem CompPoly.CPolynomial.pow_is_trimmed {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] (p : Raw R) (n : ) :
                                          (p ^ n).trim = p ^ n
                                          theorem CompPoly.CPolynomial.pow_succ_right {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] (p : Raw R) (n : ) :
                                          p ^ (n + 1) = p ^ n * p

                                          CPolynomial R forms a commutative monoid when R is a semiring.

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

                                          CPolynomial R forms a semiring when R is a semiring.

                                          The semiring structure extends the AddCommGroup structure with multiplication. All operations preserve the canonical property (no trailing zeros).

                                          Equations
                                          • One or more equations did not get rendered due to their size.
                                          theorem CompPoly.CPolynomial.val_pow {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [Nontrivial R] (p : CPolynomial R) (n : ) :
                                          ↑(p ^ n) = p ^ n

                                          The underlying Raw value of p ^ n equals p.val ^ n (using the Raw Pow instance). This bridges the optimized powBySq used in the Semiring instance with the spec pow.

                                          theorem CompPoly.CPolynomial.C_mul_X_pow_eq_monomial {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] [DecidableEq R] [Nontrivial R] (r : R) (n : ) :
                                          C r * X ^ n = monomial n r

                                          C r * X^n = monomial n r as canonical polynomials.

                                          theorem CompPoly.CPolynomial.mul_comm {R : Type u_1} [CommSemiring R] [BEq R] [LawfulBEq R] (p q : CPolynomial R) :
                                          p * q = q * p

                                          CPolynomial R forms a commutative semiring when R is a commutative semiring.

                                          Commutativity follows from the commutativity of multiplication in the base ring.

                                          Equations
                                          theorem CompPoly.CPolynomial.erase_canonical {R : Type u_1} [Ring R] [BEq R] [LawfulBEq R] [DecidableEq R] (n : ) (p : CPolynomial R) :
                                          have e := p - Raw.monomial n ((↑p).coeff n); e.trim = e
                                          def CompPoly.CPolynomial.erase {R : Type u_1} [Ring R] [BEq R] [LawfulBEq R] [DecidableEq R] (n : ) (p : CPolynomial R) :

                                          Erase the coefficient at index n (same as p except coeff n = 0, then trimmed).

                                          Equations
                                          Instances For
                                            theorem CompPoly.CPolynomial.coeff_erase {R : Type u_1} [Ring R] [BEq R] [LawfulBEq R] [DecidableEq R] (n i : ) (p : CPolynomial R) :
                                            (erase n p).coeff i = if i = n then 0 else p.coeff i

                                            Coefficient of erase n p: zero at n, otherwise coeff p i.

                                            Leading coefficient equals the coefficient at natDegree.

                                            A polynomial equals its leading monomial plus the rest (erase at natDegree).

                                            theorem CompPoly.CPolynomial.coeff_neg {R : Type u_1} [Ring R] [BEq R] [LawfulBEq R] (p : CPolynomial R) (i : ) :
                                            (-p).coeff i = -p.coeff i
                                            theorem CompPoly.CPolynomial.coeff_sub {R : Type u_1} [Ring R] [BEq R] [LawfulBEq R] (p q : CPolynomial R) (i : ) :
                                            (p - q).coeff i = p.coeff i - q.coeff i
                                            theorem CompPoly.CPolynomial.neg_add_cancel {R : Type u_1} [Ring R] [BEq R] [LawfulBEq R] (p : CPolynomial R) :
                                            -p + p = 0
                                            Equations
                                            • One or more equations did not get rendered due to their size.

                                            CPolynomial R forms a ring when R is a ring.

                                            The ring structure extends the semiring structure with negation and subtraction. Most of the structure is already provided by the Semiring instance.

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

                                            CPolynomial R forms a commutative ring when R is a commutative ring.

                                            This combines the CommSemiring and Ring structures.

                                            Equations
                                            instance CompPoly.CPolynomial.smul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] :

                                            Scalar multiplication for canonical polynomials: multiply each coefficient by r, then trim to restore canonicity.

                                            Equations
                                            theorem CompPoly.CPolynomial.coeff_smul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (r : R) (p : CPolynomial R) (i : ) :
                                            (r p).coeff i = r * p.coeff i

                                            Coefficient of a scalar multiple.

                                            theorem CompPoly.CPolynomial.smul_zero {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (r : R) :
                                            r 0 = 0

                                            Scalar multiplication on 0 gives 0.

                                            theorem CompPoly.CPolynomial.smul_eq_of_coeff_eq {R : Type u_1} [Zero R] [BEq R] [LawfulBEq R] {p q : CPolynomial R} (h : Raw.Trim.equiv p q) :
                                            p = q

                                            Helper lemma: Two CPolynomials are equal if the underlying Raw CPolynomials are trim equivalent.

                                            theorem CompPoly.CPolynomial.smul_add {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (r : R) (p q : CPolynomial R) :
                                            r (p + q) = r p + r q

                                            Scalar multiplication distributes.

                                            theorem CompPoly.CPolynomial.add_smul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (r s : R) (p : CPolynomial R) :
                                            (r + s) p = r p + s p

                                            Scalar multiplication distributes across scalar addition.

                                            theorem CompPoly.CPolynomial.zero_smul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p : CPolynomial R) :
                                            0 p = 0

                                            Scalar multiplication by 0 gives 0.

                                            theorem CompPoly.CPolynomial.one_smul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (p : CPolynomial R) :
                                            1 p = p

                                            Scalar multiplication on p by 1 gives p.

                                            theorem CompPoly.CPolynomial.mul_smul {R : Type u_1} [Semiring R] [BEq R] [LawfulBEq R] (r s : R) (p : CPolynomial R) :
                                            (r * s) p = r s p

                                            Scalar multiplication is associative.

                                            CPolynomial forms a module when R is a semiring.

                                            Equations