The is_poly
predicate #
THIS FILE IS SYNCHRONIZED WITH MATHLIB4. Any changes to this file require a corresponding PR to mathlib4.
witt_vector.is_poly
is a (type-valued) predicate on functions f : Π R, 𝕎 R → 𝕎 R
.
It asserts that there is a family of polynomials φ : ℕ → mv_polynomial ℕ ℤ
,
such that the n
th coefficient of f x
is equal to φ n
evaluated on the coefficients of x
.
Many operations on Witt vectors satisfy this predicate (or an analogue for higher arity functions).
We say that such a function f
is a polynomial function.
The power of satisfying this predicate comes from is_poly.ext
.
It shows that if φ
and ψ
witness that f
and g
are polynomial functions,
then f = g
not merely when φ = ψ
, but in fact it suffices to prove
∀ n, bind₁ φ (witt_polynomial p _ n) = bind₁ ψ (witt_polynomial p _ n)
(in other words, when evaluating the Witt polynomials on φ
and ψ
, we get the same values)
which will then imply φ = ψ
and hence f = g
.
Even though this sufficient condition looks somewhat intimidating,
it is rather pleasant to check in practice;
more so than direct checking of φ = ψ
.
In practice, we apply this technique to show that the composition of witt_vector.frobenius
and witt_vector.verschiebung
is equal to multiplication by p
.
Main declarations #
witt_vector.is_poly
,witt_vector.is_poly₂
: two predicates that assert that a unary/binary function on Witt vectors is polynomial in the coefficients of the input values.witt_vector.is_poly.ext
,witt_vector.is_poly₂.ext
: two polynomial functions are equal if their families of polynomials are equal after evaluating the Witt polynomials on them.witt_vector.is_poly.comp
(+ many variants) show that unary/binary compositions of polynomial functions are polynomial.witt_vector.id_is_poly
,witt_vector.neg_is_poly
,witt_vector.add_is_poly₂
,witt_vector.mul_is_poly₂
: several well-known operations are polynomial functions (for Verschiebung, Frobenius, and multiplication byp
, see their respective files).
On higher arity analogues #
Ideally, there should be a predicate is_polyₙ
for functions of higher arity,
together with is_polyₙ.comp
that shows how such functions compose.
Since mathlib does not have a library on composition of higher arity functions,
we have only implemented the unary and binary variants so far.
Nullary functions (a.k.a. constants) are treated
as constant functions and fall under the unary case.
Tactics #
There are important metaprograms defined in this file:
the tactics ghost_simp
and ghost_calc
and the attributes @[is_poly]
and @[ghost_simps]
.
These are used in combination to discharge proofs of identities between polynomial functions.
Any atomic proof of is_poly
or is_poly₂
(i.e. not taking additional is_poly
arguments)
should be tagged as @[is_poly]
.
Any lemma doing "ring equation rewriting" with polynomial functions should be tagged
@[ghost_simps]
, e.g.
@[ghost_simps]
lemma bind₁_frobenius_poly_witt_polynomial (n : ℕ) :
bind₁ (frobenius_poly p) (witt_polynomial p ℤ n) = (witt_polynomial p ℤ (n+1))
Proofs of identities between polynomial functions will often follow the pattern
begin
ghost_calc _,
<minor preprocessing>,
ghost_simp
end
References #
- poly : ∃ (φ : ℕ → mv_polynomial ℕ ℤ), ∀ ⦃R : Type ?⦄ [_inst_3 : comm_ring R] (x : witt_vector p R), (f x).coeff = λ (n : ℕ), ⇑(mv_polynomial.aeval x.coeff) (φ n)
A function f : Π R, 𝕎 R → 𝕎 R
that maps Witt vectors to Witt vectors over arbitrary base rings
is said to be polynomial if there is a family of polynomials φₙ
over ℤ
such that the n
th
coefficient of f x
is given by evaluating φₙ
at the coefficients of x
.
See also witt_vector.is_poly₂
for the binary variant.
The ghost_calc
tactic treats is_poly
as a type class,
and the @[is_poly]
attribute derives certain specialized composition instances
for declarations of type is_poly f
.
For the most part, users are not expected to treat is_poly
as a class.
Instances of this typeclass
- witt_vector.id_is_poly
- witt_vector.id_is_poly_i'
- witt_vector.neg_is_poly.comp_i
- witt_vector.zero_is_poly
- witt_vector.one_is_poly
- witt_vector.add_is_poly₂.comp_diag
- witt_vector.mul_is_poly₂.comp_diag
- witt_vector.frobenius_fun_is_poly.comp_i
- witt_vector.frobenius_is_poly.comp_i
- witt_vector.verschiebung_fun_is_poly.comp_i
- witt_vector.verschiebung_is_poly.comp_i
- witt_vector.mul_n_is_poly.comp_i
- witt_vector.select_is_poly.comp_i
Instances of other typeclasses for witt_vector.is_poly
The identity function on Witt vectors is a polynomial function.
Equations
- witt_vector.is_poly.inhabited p = {default := _}
The composition of polynomial functions is polynomial.
- poly : ∃ (φ : ℕ → mv_polynomial (fin 2 × ℕ) ℤ), ∀ ⦃R : Type ?⦄ [_inst_3 : comm_ring R] (x y : witt_vector p R), (f x y).coeff = λ (n : ℕ), witt_vector.peval (φ n) ![x.coeff, y.coeff]
A binary function f : Π R, 𝕎 R → 𝕎 R → 𝕎 R
on Witt vectors
is said to be polynomial if there is a family of polynomials φₙ
over ℤ
such that the n
th
coefficient of f x y
is given by evaluating φₙ
at the coefficients of x
and y
.
See also witt_vector.is_poly
for the unary variant.
The ghost_calc
tactic treats is_poly₂
as a type class,
and the @[is_poly]
attribute derives certain specialized composition instances
for declarations of type is_poly₂ f
.
For the most part, users are not expected to treat is_poly₂
as a class.
Instances of this typeclass
- witt_vector.neg_is_poly.comp₂_i
- witt_vector.add_is_poly₂.comp₂_i
- witt_vector.mul_is_poly₂.comp₂_i
- witt_vector.frobenius_fun_is_poly.comp₂_i
- witt_vector.frobenius_is_poly.comp₂_i
- witt_vector.verschiebung_fun_is_poly.comp₂_i
- witt_vector.verschiebung_is_poly.comp₂_i
- witt_vector.mul_n_is_poly.comp₂_i
- witt_vector.select_is_poly.comp₂_i
Instances of other typeclasses for witt_vector.is_poly₂
The composition of polynomial functions is polynomial.
The composition of a polynomial function with a binary polynomial function is polynomial.
The diagonal λ x, f x x
of a polynomial function f
is polynomial.
The @[is_poly]
attribute #
This attribute is used to derive specialized composition instances
for is_poly
and is_poly₂
declarations.
is_poly
instances #
These are not declared as instances at the top level,
but the @[is_poly]
attribute adds instances based on each one.
Users are expected to use the non-instance versions manually.
The additive negation is a polynomial function on Witt vectors.
The function that is constantly zero on Witt vectors is a polynomial function.
The coefficients of 1 : 𝕎 R
as polynomials.
Equations
- witt_vector.one_poly n = ite (n = 0) 1 0
The function that is constantly one on Witt vectors is a polynomial function.
Addition of Witt vectors is a polynomial function.
Multiplication of Witt vectors is a polynomial function.
Equations
The composition of a binary polynomial function with a unary polynomial function in the first argument is polynomial.
The composition of a binary polynomial function with a unary polynomial function in the second argument is polynomial.