Documentation

Mathlib.Data.Polynomial.Laurent

Laurent polynomials #

We introduce Laurent polynomials over a semiring R. Mathematically, they are expressions of the form $$\sum_{i \in \mathbb{Z}} a_i T ^ i$$ where the sum extends over a finite subset of ℤ. Thus, negative exponents are allowed. The coefficients come from the semiring R and the variable T commutes with everything.

Since we are going to convert back and forth between polynomials and Laurent polynomials, we decided to maintain some distinction by using the symbol T, rather than X, as the variable for Laurent polynomials.

Notation #

The symbol R[T;T⁻¹] stands for LaurentPolynomial R. We also define

• C : R →+* R[T;T⁻¹] the inclusion of constant polynomials, analogous to the one for R[X];
• T : ℤ → R[T;T⁻¹] the sequence of powers of the variable T.

Implementation notes #

We define Laurent polynomials as AddMonoidAlgebra R ℤ. Thus, they are essentially Finsupps ℤ →₀ R. This choice differs from the current irreducible design of Polynomial, that instead shields away the implementation via Finsupps. It is closer to the original definition of polynomials.

As a consequence, LaurentPolynomial plays well with polynomials, but there is a little roughness in establishing the API, since the Finsupp implementation of R[X] is well-shielded.

Unlike the case of polynomials, I felt that the exponent notation was not too easy to use, as only natural exponents would be allowed. Moreover, in the end, it seems likely that we should aim to perform computations on exponents in ℤ anyway and separating this via the symbol T seems convenient.

I made a heavy use of simp lemmas, aiming to bring Laurent polynomials to the form C a * T n. Any comments or suggestions for improvements is greatly appreciated!

Future work #

Lots is missing! -- (Riccardo) add inclusion into Laurent series. -- (Riccardo) giving a morphism (as R-alg, so in the commutative case) from R[T,T⁻¹] to S is the same as choosing a unit of S. -- A "better" definition of trunc would be as an R-linear map. This works: -- -- def trunc : R[T;T⁻¹] →[R] R[X] := -- begin -- refine (_ : R[ℕ] →[R] R[X]).comp _, -- { exact ⟨(toFinsuppIso R).symm, by simp⟩ }, -- { refine ⟨λ r, comapDomain _ r (Set.injOn_of_injective (λ a b ab, Int.ofNat.inj ab) _), _⟩, -- exact λ r f, comapDomain_smul _ _ _ } -- end --  -- but it would make sense to bundle the maps better, for a smoother user experience. -- I (DT) did not have the strength to embark on this (possibly short!) journey, after getting to -- this stage of the Laurent process! -- This would likely involve adding a comapDomain analogue of -- AddMonoidAlgebra.mapDomainAlgHom and an R-linear version of -- Polynomial.toFinsuppIso. -- Add degree, int_degree, int_trailing_degree, leading_coeff, trailing_coeff,....

@[inline, reducible]
abbrev LaurentPolynomial (R : Type u_2) [] :
Type u_2

The semiring of Laurent polynomials with coefficients in the semiring R. We denote it by R[T;T⁻¹]. The ring homomorphism C : R →+* R[T;T⁻¹] includes R as the constant polynomials.

Instances For
Instances For
theorem LaurentPolynomial.ext {R : Type u_1} [] {p : } {q : } (h : ∀ (a : ), p a = q a) :
p = q
def Polynomial.toLaurent {R : Type u_1} [] :

The ring homomorphism, taking a polynomial with coefficients in R to a Laurent polynomial with coefficients in R.

Instances For
theorem Polynomial.toLaurent_apply {R : Type u_1} [] (p : ) :
Polynomial.toLaurent p = AddMonoidAlgebra.mapDomain Nat.cast p.toFinsupp

This is not a simp lemma, as it is usually preferable to use the lemmas about C and X instead.

def Polynomial.toLaurentAlg {R : Type u_1} [] :

The R-algebra map, taking a polynomial with coefficients in R to a Laurent polynomial with coefficients in R.

Instances For
@[simp]
theorem Polynomial.coe_toLaurentAlg {R : Type u_1} [] :
Polynomial.toLaurentAlg = Polynomial.toLaurent
theorem Polynomial.toLaurentAlg_apply {R : Type u_1} [] (f : ) :
Polynomial.toLaurentAlg f = Polynomial.toLaurent f
theorem LaurentPolynomial.single_zero_one_eq_one {R : Type u_1} [] :
(fun₀ | 0 => 1) = 1

The functions C and T. #

def LaurentPolynomial.C {R : Type u_1} [] :

The ring homomorphism C, including R into the ring of Laurent polynomials over R as the constant Laurent polynomials.

Instances For
theorem LaurentPolynomial.algebraMap_apply {R : Type u_2} {A : Type u_3} [] [] [Algebra R A] (r : R) :
↑() r = LaurentPolynomial.C (↑() r)
theorem LaurentPolynomial.C_eq_algebraMap {R : Type u_2} [] (r : R) :
LaurentPolynomial.C r = ↑() r

When we have [CommSemiring R], the function C is the same as algebraMap R R[T;T⁻¹]. (But note that C is defined when R is not necessarily commutative, in which case algebraMap is not available.)

theorem LaurentPolynomial.single_eq_C {R : Type u_1} [] (r : R) :
(fun₀ | 0 => r) = LaurentPolynomial.C r
@[simp]
theorem LaurentPolynomial.C_apply {R : Type u_1} [] (t : R) (n : ) :
↑(LaurentPolynomial.C t) n = if n = 0 then t else 0
def LaurentPolynomial.T {R : Type u_1} [] (n : ) :

The function n ↦ T ^ n, implemented as a sequence ℤ → R[T;T⁻¹].

Using directly T ^ n does not work, since we want the exponents to be of Type ℤ and there is no ℤ-power defined on R[T;T⁻¹]. Using that T is a unit introduces extra coercions. For these reasons, the definition of T is as a sequence.

Instances For
@[simp]
theorem LaurentPolynomial.T_apply {R : Type u_1} [] (m : ) (n : ) :
↑() m = if n = m then 1 else 0
@[simp]
theorem LaurentPolynomial.T_zero {R : Type u_1} [] :
theorem LaurentPolynomial.T_add {R : Type u_1} [] (m : ) (n : ) :
theorem LaurentPolynomial.T_sub {R : Type u_1} [] (m : ) (n : ) :
@[simp]
theorem LaurentPolynomial.T_pow {R : Type u_1} [] (m : ) (n : ) :
@[simp]
theorem LaurentPolynomial.mul_T_assoc {R : Type u_1} [] (f : ) (m : ) (n : ) :

The simp version of mul_assoc, in the presence of T's.

@[simp]
theorem LaurentPolynomial.single_eq_C_mul_T {R : Type u_1} [] (r : R) (n : ) :
(fun₀ | n => r) = LaurentPolynomial.C r *
@[simp]
theorem Polynomial.toLaurent_C_mul_T {R : Type u_1} [] (n : ) (r : R) :
Polynomial.toLaurent (↑() r) = LaurentPolynomial.C r *
@[simp]
theorem Polynomial.toLaurent_C {R : Type u_1} [] (r : R) :
Polynomial.toLaurent (Polynomial.C r) = LaurentPolynomial.C r
@[simp]
theorem Polynomial.toLaurent_comp_C {R : Type u_1} [] :
Polynomial.toLaurent Polynomial.C = LaurentPolynomial.C
@[simp]
theorem Polynomial.toLaurent_X {R : Type u_1} [] :
Polynomial.toLaurent Polynomial.X =
theorem Polynomial.toLaurent_one {R : Type u_1} [] :
Polynomial.toLaurent 1 = 1
theorem Polynomial.toLaurent_C_mul_eq {R : Type u_1} [] (r : R) (f : ) :
Polynomial.toLaurent (Polynomial.C r * f) = LaurentPolynomial.C r * Polynomial.toLaurent f
theorem Polynomial.toLaurent_X_pow {R : Type u_1} [] (n : ) :
Polynomial.toLaurent (Polynomial.X ^ n) =
theorem Polynomial.toLaurent_C_mul_X_pow {R : Type u_1} [] (n : ) (r : R) :
Polynomial.toLaurent (Polynomial.C r * Polynomial.X ^ n) = LaurentPolynomial.C r *
instance LaurentPolynomial.invertibleT {R : Type u_1} [] (n : ) :
@[simp]
theorem LaurentPolynomial.invOf_T {R : Type u_1} [] (n : ) :
theorem LaurentPolynomial.isUnit_T {R : Type u_1} [] (n : ) :
theorem LaurentPolynomial.induction_on {R : Type u_1} [] {M : } (p : ) (h_C : (a : R) → M (LaurentPolynomial.C a)) (h_add : {p q : } → M pM qM (p + q)) (h_C_mul_T : (n : ) → (a : R) → M (LaurentPolynomial.C a * )M (LaurentPolynomial.C a * LaurentPolynomial.T (n + 1))) (h_C_mul_T_Z : (n : ) → (a : R) → M (LaurentPolynomial.C a * )M (LaurentPolynomial.C a * LaurentPolynomial.T (-n - 1))) :
M p
theorem LaurentPolynomial.induction_on' {R : Type u_1} [] {M : } (p : ) (h_add : (p q : ) → M pM qM (p + q)) (h_C_mul_T : (n : ) → (a : R) → M (LaurentPolynomial.C a * )) :
M p

To prove something about Laurent polynomials, it suffices to show that

• the condition is closed under taking sums, and
• it holds for monomials.
theorem LaurentPolynomial.commute_T {R : Type u_1} [] (n : ) (f : ) :
@[simp]
theorem LaurentPolynomial.T_mul {R : Type u_1} [] (n : ) (f : ) :
def LaurentPolynomial.trunc {R : Type u_1} [] :

trunc : R[T;T⁻¹] →+ R[X] maps a Laurent polynomial f to the polynomial whose terms of nonnegative degree coincide with the ones of f. The terms of negative degree of f "vanish". trunc is a left-inverse to Polynomial.toLaurent.

Instances For
@[simp]
theorem LaurentPolynomial.trunc_C_mul_T {R : Type u_1} [] (n : ) (r : R) :
LaurentPolynomial.trunc (LaurentPolynomial.C r * ) = if 0 n then ↑() r else 0
@[simp]
theorem LaurentPolynomial.leftInverse_trunc_toLaurent {R : Type u_1} [] :
Function.LeftInverse LaurentPolynomial.trunc Polynomial.toLaurent
@[simp]
theorem Polynomial.trunc_toLaurent {R : Type u_1} [] (f : ) :
LaurentPolynomial.trunc (Polynomial.toLaurent f) = f
theorem Polynomial.toLaurent_injective {R : Type u_1} [] :
Function.Injective Polynomial.toLaurent
@[simp]
theorem Polynomial.toLaurent_inj {R : Type u_1} [] (f : ) (g : ) :
Polynomial.toLaurent f = Polynomial.toLaurent g f = g
theorem Polynomial.toLaurent_ne_zero {R : Type u_1} [] {f : } :
f 0 Polynomial.toLaurent f 0
theorem LaurentPolynomial.exists_T_pow {R : Type u_1} [] (f : ) :
n f', Polynomial.toLaurent f' =
theorem LaurentPolynomial.induction_on_mul_T {R : Type u_1} [] {Q : } (f : ) (Qf : {f : } → {n : } → Q (Polynomial.toLaurent f * )) :
Q f

This is a version of exists_T_pow stated as an induction principle.

theorem LaurentPolynomial.reduce_to_polynomial_of_mul_T {R : Type u_1} [] (f : ) {Q : } (Qf : (f : ) → Q (Polynomial.toLaurent f)) (QT : (f : ) → Q ()Q f) :
Q f

Suppose that Q is a statement about Laurent polynomials such that

• Q is true on ordinary polynomials;
• Q (f * T) implies Q f; it follow that Q is true on all Laurent polynomials.
theorem LaurentPolynomial.support_C_mul_T {R : Type u_1} [] (a : R) (n : ) :
(LaurentPolynomial.C a * ).support {n}
theorem LaurentPolynomial.support_C_mul_T_of_ne_zero {R : Type u_1} [] {a : R} (a0 : a 0) (n : ) :
(LaurentPolynomial.C a * ).support = {n}
theorem LaurentPolynomial.toLaurent_support {R : Type u_1} [] (f : ) :
(Polynomial.toLaurent f).support = Finset.map Nat.castEmbedding ()

The support of a polynomial f is a finset in ℕ. The lemma toLaurent_support f shows that the support of f.toLaurent is the same finset, but viewed in ℤ under the natural inclusion ℕ ↪ ℤ.

def LaurentPolynomial.degree {R : Type u_1} [] (f : ) :

The degree of a Laurent polynomial takes values in WithBot ℤ. If f : R[T;T⁻¹] is a Laurent polynomial, then f.degree is the maximum of its support of f, or ⊥, if f = 0.

Instances For
@[simp]
theorem LaurentPolynomial.degree_zero {R : Type u_1} [] :
@[simp]
theorem LaurentPolynomial.degree_eq_bot_iff {R : Type u_1} [] {f : } :
f = 0
@[simp]
theorem LaurentPolynomial.degree_C_mul_T {R : Type u_1} [] (n : ) (a : R) (a0 : a 0) :
LaurentPolynomial.degree (LaurentPolynomial.C a * ) = n
theorem LaurentPolynomial.degree_C_mul_T_ite {R : Type u_1} [] (n : ) (a : R) :
LaurentPolynomial.degree (LaurentPolynomial.C a * ) = if a = 0 then else n
@[simp]
theorem LaurentPolynomial.degree_T {R : Type u_1} [] [] (n : ) :
theorem LaurentPolynomial.degree_C {R : Type u_1} [] {a : R} (a0 : a 0) :
LaurentPolynomial.degree (LaurentPolynomial.C a) = 0
theorem LaurentPolynomial.degree_C_ite {R : Type u_1} [] (a : R) :
LaurentPolynomial.degree (LaurentPolynomial.C a) = if a = 0 then else 0
theorem LaurentPolynomial.degree_C_mul_T_le {R : Type u_1} [] (n : ) (a : R) :
LaurentPolynomial.degree (LaurentPolynomial.C a * ) n
theorem LaurentPolynomial.degree_T_le {R : Type u_1} [] (n : ) :
theorem LaurentPolynomial.degree_C_le {R : Type u_1} [] (a : R) :
LaurentPolynomial.degree (LaurentPolynomial.C a) 0
theorem LaurentPolynomial.algebraMap_X_pow {R : Type u_1} [] (n : ) :
↑() (Polynomial.X ^ n) =
@[simp]
theorem LaurentPolynomial.algebraMap_eq_toLaurent {R : Type u_1} [] (f : ) :
↑() f = Polynomial.toLaurent f
def LaurentPolynomial.invert {R : Type u_2} [] :

The map which substitutes T ↦ T⁻¹ into a Laurent polynomial.

Instances For
@[simp]
theorem LaurentPolynomial.invert_T {R : Type u_2} [] (n : ) :
LaurentPolynomial.invert () =
@[simp]
theorem LaurentPolynomial.invert_apply {R : Type u_2} [] (f : ) (n : ) :
↑(LaurentPolynomial.invert f) n = f (-n)
@[simp]
theorem LaurentPolynomial.invert_comp_C {R : Type u_2} [] :
LaurentPolynomial.invert LaurentPolynomial.C = LaurentPolynomial.C
@[simp]
theorem LaurentPolynomial.invert_C {R : Type u_2} [] (t : R) :
LaurentPolynomial.invert (LaurentPolynomial.C t) = LaurentPolynomial.C t
theorem LaurentPolynomial.involutive_invert {R : Type u_2} [] :
Function.Involutive LaurentPolynomial.invert
@[simp]
theorem LaurentPolynomial.invert_symm {R : Type u_2} [] :
AlgEquiv.symm LaurentPolynomial.invert = LaurentPolynomial.invert
theorem LaurentPolynomial.toLaurent_reverse {R : Type u_2} [] (p : ) :
Polynomial.toLaurent () = LaurentPolynomial.invert (Polynomial.toLaurent p) *