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.fieldprovides a field structureratfunc.Cis the constant polynomialratfunc.Xis the indeterminateratfunc.evalevaluates a rational function given a value for the indeterminate You can useis_fraction_ringAPI to treatratfuncas the field of fractions of polynomials:
algebra_map K[X] (ratfunc K)maps polynomials to rational functionsis_fraction_ring.alg_equivmaps other fields of fractions ofpolynomial Ktoratfunc 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_scalarsto change thefraction_ring K[X] ≃ₐ[polynomial K] ratfunc Ktofraction_ring K[X] ≃ₐ[K] ratfunc K.
Working with rational functions as fractions:
ratfunc.numandratfunc.denomgive the numerator and denominator. These values are chosen to be coprime and such thatratfunc.denomis 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_homlifts apolynomial K →*₀ G₀to aratfunc K →*₀ G₀, where[comm_ring K] [comm_group_with_zero G₀]ratfunc.lift_ring_homlifts apolynomial K →+* Lto aratfunc K →+* L, where[comm_ring K] [field L]ratfunc.lift_alg_homlifts apolynomial K →ₐ[S] Lto 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.mapliftspolynomial K →* R[X]when[comm_ring K] [comm_ring R]ratfunc.map_ring_homliftspolynomial K →+* R[X]when[comm_ring K] [comm_ring R]ratfunc.map_alg_homliftspolynomial 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/qtof p q, iffis 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/qtof p q, iffis well-defined in the sense thatf (a * p) (a * q) = f p' q'.ratfunc.induction_on: ifPholds onp / qfor all polynomialsp q, thenPholds on all rational functions
We define the degree of a rational function, with values in ℤ:
int_degreeis the degree of a rational function, defined as the difference between thenat_degreeof its numerator and thenat_degreeof 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] defs
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 simped 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.