The field of rational functions #
This file defines the field ratfunc K
of rational functions over a field K
,
and shows it is the field of fractions of polynomial K
.
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 ofpolynomial K
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] ≃ₐ[polynomial K] 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 apolynomial K →*₀ G₀
to aratfunc K →*₀ G₀
, where[comm_ring K] [comm_group_with_zero G₀]
ratfunc.lift_ring_hom
lifts apolynomial K →+* L
to aratfunc K →+* L
, where[comm_ring K] [field L]
ratfunc.lift_alg_hom
lifts apolynomial K →ₐ[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
liftspolynomial K →* R[X]
when[comm_ring K] [comm_ring R]
ratfunc.map_ring_hom
liftspolynomial K →+* R[X]
when[comm_ring K] [comm_ring R]
ratfunc.map_alg_hom
liftspolynomial K →ₐ[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 K[X]
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 polynomial K
,
especially fraction_ring K[X]
, are given by is_localization.algebra_equiv
.
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 p * q' = p' * q
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 : K[X]) (q : ↥K[X]⁰), 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 K[X] (fraction_ring K[X])) p / ⇑(algebra_map K[X] (fraction_ring K[X])) 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 #
Equations
- ratfunc.has_zero = {zero := ratfunc.zero hring}
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 hring}
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 hring}
Additive inverse of a rational function.
Equations
- {to_fraction_ring := p}.neg = {to_fraction_ring := -p}
Equations
- ratfunc.has_neg = {neg := ratfunc.neg hring}
The multiplicative unit of rational functions.
Equations
- ratfunc.one = {to_fraction_ring := 1}
Equations
- ratfunc.has_one = {one := ratfunc.one hring}
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 hring}
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 hdomain}
Multiplicative inverse of a rational function.
Equations
- {to_fraction_ring := p}.inv = {to_fraction_ring := p⁻¹}
Equations
- ratfunc.has_inv = {inv := ratfunc.inv hdomain}
Scalar multiplication of rational functions.
Equations
- ratfunc.smul r {to_fraction_ring := p} = {to_fraction_ring := r • p}
Equations
- ratfunc.has_scalar = {smul := ratfunc.smul _inst_1}
Equations
- ratfunc.inhabited K = {default := 0}
ratfunc K
is isomorphic to the field of fractions of polynomial K
, 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 hring, inv_fun := ratfunc.of_fraction_ring hring, 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_scalar.smul ratfunc.has_scalar, nsmul_zero' := _, nsmul_succ' := _, neg := has_neg.neg ratfunc.has_neg, sub := has_sub.sub ratfunc.has_sub, sub_eq_add_neg := _, zsmul := has_scalar.smul ratfunc.has_scalar, zsmul_zero' := _, zsmul_succ' := _, zsmul_neg' := _, add_left_neg := _, add_comm := _, mul := has_mul.mul ratfunc.has_mul, mul_assoc := _, one := 1, 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.
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 polynomial R →*₀ 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 polynomial R →+* 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 := _, mul := comm_ring.mul (ratfunc.comm_ring K), mul_assoc := _, one := comm_ring.one (ratfunc.comm_ring K), 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 := _, mul_inv_cancel := _, inv_zero := _}
ratfunc
as field of fractions of polynomial
#
Equations
- ratfunc.algebra R = {to_has_scalar := {smul := has_scalar.smul ratfunc.has_scalar}, to_ring_hom := {to_fun := λ (x : R), ratfunc.mk (⇑(algebra_map R K[X]) x) 1, map_one' := _, map_mul' := _, map_zero' := _, map_add' := _}, commutes' := _, smul_def' := _}
Lift an algebra homomorphism that maps polynomials φ : polynomial K →ₐ[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 polynomial K →ₐ[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 : polynomial K
,
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.
ratfunc.num
is the numerator of a rational function,
normalized such that the denominator is monic.
ratfunc.denom
is the denominator of a rational function,
normalized such that it is monic.
Polynomial structure: C
, X
, eval
#
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.