The field of rational functions #
THIS FILE IS SYNCHRONIZED WITH MATHLIB4. Any changes to this file require a corresponding PR to mathlib4.
This file defines the field ratfunc K
of rational functions over a field K
,
and shows it is the field of fractions of K[X]
.
Main definitions #
Working with rational functions as polynomials:
ratfunc.field
provides a field structureratfunc.C
is the constant polynomialratfunc.X
is the indeterminateratfunc.eval
evaluates a rational function given a value for the indeterminate You can useis_fraction_ring
API to treatratfunc
as the field of fractions of polynomials:
algebra_map K[X] (ratfunc K)
maps polynomials to rational functionsis_fraction_ring.alg_equiv
maps other fields of fractions ofK[X]
toratfunc K
, in particular:fraction_ring.alg_equiv K[X] (ratfunc K)
maps the generic field of fraction construction toratfunc K
. Combine this withalg_equiv.restrict_scalars
to change thefraction_ring K[X] ≃ₐ[K[X]] ratfunc K
tofraction_ring K[X] ≃ₐ[K] ratfunc K
.
Working with rational functions as fractions:
ratfunc.num
andratfunc.denom
give the numerator and denominator. These values are chosen to be coprime and such thatratfunc.denom
is monic.
Embedding of rational functions into Laurent series, provided as a coercion, utilizing
the underlying ratfunc.coe_alg_hom
.
Lifting homomorphisms of polynomials to other types, by mapping and dividing, as long as the homomorphism retains the non-zero-divisor property:
ratfunc.lift_monoid_with_zero_hom
lifts aK[X] →*₀ G₀
to aratfunc K →*₀ G₀
, where[comm_ring K] [comm_group_with_zero G₀]
ratfunc.lift_ring_hom
lifts aK[X] →+* L
to aratfunc K →+* L
, where[comm_ring K] [field L]
ratfunc.lift_alg_hom
lifts aK[X] →ₐ[S] L
to aratfunc K →ₐ[S] L
, where[comm_ring K] [field L] [comm_semiring S] [algebra S K[X]] [algebra S L]
This is satisfied by injective homs. We also have lifting homomorphisms of polynomials to other polynomials, with the same condition on retaining the non-zero-divisor property across the map:ratfunc.map
liftsK[X] →* R[X]
when[comm_ring K] [comm_ring R]
ratfunc.map_ring_hom
liftsK[X] →+* R[X]
when[comm_ring K] [comm_ring R]
ratfunc.map_alg_hom
liftsK[X] →ₐ[S] R[X]
when[comm_ring K] [is_domain K] [comm_ring R] [is_domain R]
We also have a set of recursion and induction principles:
ratfunc.lift_on
: define a function by mapping a fraction of polynomialsp/q
tof p q
, iff
is well-defined in the sense thatp/q = p'/q' → f p q = f p' q'
.ratfunc.lift_on'
: define a function by mapping a fraction of polynomialsp/q
tof p q
, iff
is well-defined in the sense thatf (a * p) (a * q) = f p' q'
.ratfunc.induction_on
: ifP
holds onp / q
for all polynomialsp q
, thenP
holds on all rational functions
We define the degree of a rational function, with values in ℤ
:
int_degree
is the degree of a rational function, defined as the difference between thenat_degree
of its numerator and thenat_degree
of its denominator. In particular,int_degree 0 = 0
.
Implementation notes #
To provide good API encapsulation and speed up unification problems,
ratfunc
is defined as a structure, and all operations are @[irreducible] def
s
We need a couple of maps to set up the field
and is_fraction_ring
structure,
namely ratfunc.of_fraction_ring
, ratfunc.to_fraction_ring
, ratfunc.mk
and
ratfunc.to_fraction_ring_ring_equiv
.
All these maps get simp
ed to bundled morphisms like algebra_map K[X] (ratfunc K)
and is_localization.alg_equiv
.
There are separate lifts and maps of homomorphisms, to provide routes of lifting even when the codomain is not a field or even an integral domain.
References #
- to_fraction_ring : fraction_ring (polynomial K)
ratfunc K
is K(x)
, the field of rational functions over K
.
The inclusion of polynomials into ratfunc
is algebra_map K[X] (ratfunc K)
,
the maps between ratfunc K
and another field of fractions of K[X]
,
especially fraction_ring K[X]
, are given by is_localization.algebra_equiv
.
Instances for ratfunc
- ratfunc.has_sizeof_inst
- ratfunc.has_zero
- ratfunc.has_add
- ratfunc.has_sub
- ratfunc.has_neg
- ratfunc.has_one
- ratfunc.has_mul
- ratfunc.has_div
- ratfunc.has_inv
- ratfunc.has_smul
- ratfunc.is_scalar_tower
- ratfunc.subsingleton
- ratfunc.inhabited
- ratfunc.nontrivial
- ratfunc.comm_ring
- ratfunc.field
- ratfunc.algebra
- ratfunc.is_fraction_ring
- ratfunc.coe_to_laurent_series
- ratfunc.laurent_series.algebra
- ratfunc.laurent_series.is_scalar_tower
Non-dependent recursion principle for ratfunc K
:
To construct a term of P : Sort*
out of x : ratfunc K
,
it suffices to provide a constructor f : Π (p q : K[X]), P
and a proof that f p q = f p' q'
for all p q p' q'
such that q' * p = q * p'
where
both q
and q'
are not zero divisors, stated as q ∉ K[X]⁰
, q' ∉ K[X]⁰
.
If considering K
as an integral domain, this is the same as saying that
we construct a value of P
for such elements of ratfunc K
by setting
lift_on (p / q) f _ = f p q
.
When [is_domain K]
, one can use ratfunc.lift_on'
, which has the stronger requirement
of ∀ {p q a : K[X]} (hq : q ≠ 0) (ha : a ≠ 0), f (a * p) (a * q) = f p q)
.
Equations
- x.lift_on f H = localization.lift_on x.to_fraction_ring (λ (p : polynomial K) (q : ↥(non_zero_divisors (polynomial K))), f p ↑q) _
ratfunc.mk (p q : K[X])
is p / q
as a rational function.
If q = 0
, then mk
returns 0.
This is an auxiliary definition used to define an algebra
structure on ratfunc
;
the simp
normal form of mk p q
is algebra_map _ _ p / algebra_map _ _ q
.
Equations
- ratfunc.mk p q = {to_fraction_ring := ⇑(algebra_map (polynomial K) (fraction_ring (polynomial K))) p / ⇑(algebra_map (polynomial K) (fraction_ring (polynomial K))) q}
Non-dependent recursion principle for ratfunc K
: if f p q : P
for all p q
,
such that f (a * p) (a * q) = f p q
, then we can find a value of P
for all elements of ratfunc K
by setting lift_on' (p / q) f _ = f p q
.
The value of f p 0
for any p
is never used and in principle this may be anything,
although many usages of lift_on'
assume f p 0 = f 0 1
.
Induction principle for ratfunc K
: if f p q : P (ratfunc.mk p q)
for all p q
,
then P
holds on all elements of ratfunc K
.
See also induction_on
, which is a recursion principle defined in terms of algebra_map
.
Defining the field structure #
The zero rational function.
Equations
- ratfunc.zero = {to_fraction_ring := 0}
Equations
- ratfunc.has_zero = {zero := ratfunc.zero _inst_1}
Addition of rational functions.
Equations
- {to_fraction_ring := p}.add {to_fraction_ring := q} = {to_fraction_ring := p + q}
Equations
- ratfunc.has_add = {add := ratfunc.add _inst_1}
Subtraction of rational functions.
Equations
- {to_fraction_ring := p}.sub {to_fraction_ring := q} = {to_fraction_ring := p - q}
Equations
- ratfunc.has_sub = {sub := ratfunc.sub _inst_1}
Additive inverse of a rational function.
Equations
- {to_fraction_ring := p}.neg = {to_fraction_ring := -p}
Equations
- ratfunc.has_neg = {neg := ratfunc.neg _inst_1}
The multiplicative unit of rational functions.
Equations
- ratfunc.one = {to_fraction_ring := 1}
Equations
- ratfunc.has_one = {one := ratfunc.one _inst_1}
Multiplication of rational functions.
Equations
- {to_fraction_ring := p}.mul {to_fraction_ring := q} = {to_fraction_ring := p * q}
Equations
- ratfunc.has_mul = {mul := ratfunc.mul _inst_1}
Division of rational functions.
Equations
- {to_fraction_ring := p}.div {to_fraction_ring := q} = {to_fraction_ring := p / q}
Equations
- ratfunc.has_div = {div := ratfunc.div _inst_2}
Multiplicative inverse of a rational function.
Equations
- {to_fraction_ring := p}.inv = {to_fraction_ring := p⁻¹}
Equations
- ratfunc.has_inv = {inv := ratfunc.inv _inst_2}
Scalar multiplication of rational functions.
Equations
- ratfunc.smul r {to_fraction_ring := p} = {to_fraction_ring := r • p}
Equations
- ratfunc.has_smul = {smul := ratfunc.smul _inst_2}
Equations
- ratfunc.inhabited K = {default := 0}
ratfunc K
is isomorphic to the field of fractions of K[X]
, as rings.
This is an auxiliary definition; simp
-normal form is is_localization.alg_equiv
.
Equations
- ratfunc.to_fraction_ring_ring_equiv K = {to_fun := ratfunc.to_fraction_ring _inst_1, inv_fun := ratfunc.of_fraction_ring _inst_1, left_inv := _, right_inv := _, map_mul' := _, map_add' := _}
Equations
- ratfunc.comm_ring K = {add := has_add.add ratfunc.has_add, add_assoc := _, zero := 0, zero_add := _, add_zero := _, nsmul := has_smul.smul ratfunc.has_smul, nsmul_zero' := _, nsmul_succ' := _, neg := has_neg.neg ratfunc.has_neg, sub := has_sub.sub ratfunc.has_sub, sub_eq_add_neg := _, zsmul := has_smul.smul ratfunc.has_smul, zsmul_zero' := _, zsmul_succ' := _, zsmul_neg' := _, add_left_neg := _, add_comm := _, int_cast := ring.int_cast._default (ring.nat_cast._default 1 has_add.add _ 0 _ _ has_smul.smul _ _) has_add.add _ 0 _ _ has_smul.smul _ _ 1 _ _ has_neg.neg has_sub.sub _ has_smul.smul _ _ _ _, nat_cast := ring.nat_cast._default 1 has_add.add _ 0 _ _ has_smul.smul _ _, one := 1, nat_cast_zero := _, nat_cast_succ := _, int_cast_of_nat := _, int_cast_neg_succ_of_nat := _, mul := has_mul.mul ratfunc.has_mul, mul_assoc := _, one_mul := _, mul_one := _, npow := npow_rec ratfunc.has_mul, npow_zero' := _, npow_succ' := _, left_distrib := _, right_distrib := _, mul_comm := _}
Lift a monoid homomorphism that maps polynomials φ : R[X] →* S[X]
to a ratfunc R →* ratfunc S
,
on the condition that φ
maps non zero divisors to non zero divisors,
by mapping both the numerator and denominator and quotienting them.
Equations
- ratfunc.map φ hφ = {to_fun := λ (f : ratfunc R), f.lift_on (λ (n d : polynomial R), dite (⇑φ d ∈ non_zero_divisors (polynomial S)) (λ (h : ⇑φ d ∈ non_zero_divisors (polynomial S)), {to_fraction_ring := localization.mk (⇑φ n) ⟨⇑φ d, h⟩}) (λ (h : ⇑φ d ∉ non_zero_divisors (polynomial S)), 0)) _, map_one' := _, map_mul' := _}
Lift a ring homomorphism that maps polynomials φ : R[X] →+* S[X]
to a ratfunc R →+* ratfunc S
,
on the condition that φ
maps non zero divisors to non zero divisors,
by mapping both the numerator and denominator and quotienting them.
Equations
- ratfunc.map_ring_hom φ hφ = {to_fun := (ratfunc.map φ hφ).to_fun, map_one' := _, map_mul' := _, map_zero' := _, map_add' := _}
Lift an monoid with zero homomorphism R[X] →*₀ G₀
to a ratfunc R →*₀ G₀
on the condition that φ
maps non zero divisors to non zero divisors,
by mapping both the numerator and denominator and quotienting them.
Lift an injective ring homomorphism R[X] →+* L
to a ratfunc R →+* L
by mapping both the numerator and denominator and quotienting them.
Equations
- ratfunc.lift_ring_hom φ hφ = {to_fun := (ratfunc.lift_monoid_with_zero_hom φ.to_monoid_with_zero_hom hφ).to_fun, map_one' := _, map_mul' := _, map_zero' := _, map_add' := _}
Equations
- ratfunc.field K = {add := comm_ring.add (ratfunc.comm_ring K), add_assoc := _, zero := comm_ring.zero (ratfunc.comm_ring K), zero_add := _, add_zero := _, nsmul := comm_ring.nsmul (ratfunc.comm_ring K), nsmul_zero' := _, nsmul_succ' := _, neg := comm_ring.neg (ratfunc.comm_ring K), sub := comm_ring.sub (ratfunc.comm_ring K), sub_eq_add_neg := _, zsmul := comm_ring.zsmul (ratfunc.comm_ring K), zsmul_zero' := _, zsmul_succ' := _, zsmul_neg' := _, add_left_neg := _, add_comm := _, int_cast := comm_ring.int_cast (ratfunc.comm_ring K), nat_cast := comm_ring.nat_cast (ratfunc.comm_ring K), one := comm_ring.one (ratfunc.comm_ring K), nat_cast_zero := _, nat_cast_succ := _, int_cast_of_nat := _, int_cast_neg_succ_of_nat := _, mul := comm_ring.mul (ratfunc.comm_ring K), mul_assoc := _, one_mul := _, mul_one := _, npow := comm_ring.npow (ratfunc.comm_ring K), npow_zero' := _, npow_succ' := _, left_distrib := _, right_distrib := _, mul_comm := _, inv := has_inv.inv ratfunc.has_inv, div := has_div.div ratfunc.has_div, div_eq_mul_inv := _, zpow := zpow_rec ratfunc.has_inv, zpow_zero' := _, zpow_succ' := _, zpow_neg' := _, exists_pair_ne := _, rat_cast := division_ring.rat_cast._default comm_ring.add _ comm_ring.zero _ _ comm_ring.nsmul _ _ comm_ring.neg comm_ring.sub _ comm_ring.zsmul _ _ _ _ _ comm_ring.int_cast comm_ring.nat_cast comm_ring.one _ _ _ _ comm_ring.mul _ _ _ comm_ring.npow _ _ _ _ has_inv.inv has_div.div _ zpow_rec _ _ _, mul_inv_cancel := _, inv_zero := _, rat_cast_mk := _, qsmul := division_ring.qsmul._default (… … _ _ _ _ comm_ring.int_cast comm_ring.nat_cast comm_ring.one _ _ _ _ comm_ring.mul _ _ _ comm_ring.npow _ _ _ _ has_inv.inv has_div.div _ zpow_rec _ _ _) comm_ring.add _ comm_ring.zero _ _ comm_ring.nsmul _ _ comm_ring.neg comm_ring.sub _ comm_ring.zsmul _ _ _ _ _ comm_ring.int_cast comm_ring.nat_cast comm_ring.one _ _ _ _ comm_ring.mul _ _ _ comm_ring.npow _ _ _ _, qsmul_eq_mul' := _}
ratfunc
as field of fractions of polynomial
#
Equations
- ratfunc.algebra K R = {to_has_smul := {smul := has_smul.smul ratfunc.has_smul}, to_ring_hom := {to_fun := λ (x : R), ratfunc.mk (⇑(algebra_map R (polynomial K)) x) 1, map_one' := _, map_mul' := _, map_zero' := _, map_add' := _}, commutes' := _, smul_def' := _}
Lift an algebra homomorphism that maps polynomials φ : K[X] →ₐ[S] R[X]
to a ratfunc K →ₐ[S] ratfunc R
,
on the condition that φ
maps non zero divisors to non zero divisors,
by mapping both the numerator and denominator and quotienting them.
Lift an injective algebra homomorphism K[X] →ₐ[S] L
to a ratfunc K →ₐ[S] L
by mapping both the numerator and denominator and quotienting them.
Equations
- ratfunc.lift_alg_hom φ hφ = {to_fun := (ratfunc.lift_ring_hom φ.to_ring_hom hφ).to_fun, map_one' := _, map_mul' := _, map_zero' := _, map_add' := _, commutes' := _}
ratfunc K
is the field of fractions of the polynomials over K
.
Induction principle for ratfunc K
: if f p q : P (p / q)
for all p q : K[X]
,
then P
holds on all elements of ratfunc K
.
See also induction_on'
, which is a recursion principle defined in terms of ratfunc.mk
.
Numerator and denominator #
ratfunc.num_denom
are numerator and denominator of a rational function over a field,
normalized such that the denominator is monic.
Equations
- x.num_denom = x.lift_on' (λ (p q : polynomial K), ite (q = 0) (0, 1) (let r : polynomial K := gcd_monoid.gcd p q in (⇑polynomial.C ((q / r).leading_coeff)⁻¹ * (p / r), ⇑polynomial.C ((q / r).leading_coeff)⁻¹ * (q / r)))) ratfunc.num_denom._proof_2
ratfunc.num
is the numerator of a rational function,
normalized such that the denominator is monic.
A version of num_div_dvd
with the LHS in simp normal form
ratfunc.denom
is the denominator of a rational function,
normalized such that it is monic.
Polynomial structure: C
, X
, eval
#
ratfunc.X
is the polynomial variable (aka indeterminate).
Equations
- ratfunc.X = ⇑(algebra_map (polynomial K) (ratfunc K)) polynomial.X
Evaluate a rational function p
given a ring hom f
from the scalar field
to the target and a value x
for the variable in the target.
Fractions are reduced by clearing common denominators before evaluating:
eval id 1 ((X^2 - 1) / (X - 1)) = eval id 1 (X + 1) = 2
, not 0 / 0 = 0
.
Equations
- ratfunc.eval f a p = polynomial.eval₂ f a p.num / polynomial.eval₂ f a p.denom
eval
is an additive homomorphism except when a denominator evaluates to 0
.
Counterexample: eval _ 1 (X / (X-1)) + eval _ 1 (-1 / (X-1)) = 0
... ≠ 1 = eval _ 1 ((X-1) / (X-1))
.
See also ratfunc.eval₂_denom_ne_zero
to make the hypotheses simpler but less general.
eval
is a multiplicative homomorphism except when a denominator evaluates to 0
.
Counterexample: eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)
.
See also ratfunc.eval₂_denom_ne_zero
to make the hypotheses simpler but less general.
int_degree x
is the degree of the rational function x
, defined as the difference between
the nat_degree
of its numerator and the nat_degree
of its denominator. In particular,
int_degree 0 = 0
.
Equations
- x.int_degree = ↑(x.num.nat_degree) - ↑(x.denom.nat_degree)
The coercion ratfunc F → laurent_series F
as bundled alg hom.