Multivariate Puiseux polynomials
A Puiseux polynomial over a field $K$ is a finite sum of terms $c x_1^{e_1} \cdots x_n^{e_n}$ with $c \in K$ and rational exponents $e_i$, which may be negative. Puiseux polynomials form a ring containing the Laurent polynomial ring $K[x_1^{\pm 1}, \dots, x_n^{\pm 1}]$.
Generic Puiseux polynomial types
AbstractAlgebra.jl provides a generic implementation of multivariate Puiseux polynomials in the file src/generic/PuiseuxMPoly.jl, built on top of the generic multivariate Laurent polynomials.
The element type is PuiseuxMPolyRingElem{T} <: RingElem and the parent type is PuiseuxMPolyRing{T} <: Ring, parameterized on the coefficient type T.
A Puiseux polynomial $f$ is stored as a pair $(g, d)$ of a Laurent polynomial $g$ and a positive integer $d$, its scale, with
\[f(x_1, \dots, x_n) = g(x_1^{1/d}, \dots, x_n^{1/d}).\]
The representation is normalized: $d$ is coprime to the greatest common divisor of all exponents of $g$, so $d$ is the least common denominator of the exponents of $f$. Every Puiseux polynomial has a unique normalized representation, which makes comparing elements cheap. Arithmetic rescales both operands to a common scale, operates on the underlying Laurent polynomials and normalizes the result.
Constructor
AbstractAlgebra.puiseux_polynomial_ring — Method
puiseux_polynomial_ring(K::Field, variableSymbols::Vector{Symbol}; cached::Bool = true)Return a tuple (R, x) consisting of the ring R of Puiseux polynomials over K in the given variables and the vector x of its generators.
The elements of R are finite sums of terms $c x_1^{e_1} \cdots x_n^{e_n}$ with $c \in K$ and rational, possibly negative, exponents $e_i$. If cached is false, the underlying Laurent polynomial ring is not cached, so the result is distinct from all other Puiseux polynomial rings.
Examples
julia> R, (x, y) = puiseux_polynomial_ring(QQ, ["x", "y"]);
julia> R
Puiseux polynomial ring in 2 variables x, y
over rationals
julia> f = x^(1//2) + 2*y^(-1//3)
x^(1//2) + 2*y^(-1//3)
julia> f^2
x + 4*x^(1//2)*y^(-1//3) + 4*y^(-2//3)Elements can be created from the generators by the usual arithmetic operations, and constants can be coerced into the ring by calling it:
julia> R, (x, y) = puiseux_polynomial_ring(QQ, ["x", "y"]);
julia> R(3)
3
julia> 3*x^(1//2)*y^(-2//3) - 1
3*x^(1//2)*y^(-2//3) - 1Basic functionality
Puiseux polynomial rings implement the Ring interface. In addition, the following functions are available.
base_ring(R::PuiseuxMPolyRing)
coefficient_ring(R::PuiseuxMPolyRing)
symbols(R::PuiseuxMPolyRing)
number_of_variables(R::PuiseuxMPolyRing)
gens(R::PuiseuxMPolyRing)
is_univariate(R::PuiseuxMPolyRing)Here base_ring returns the underlying Laurent polynomial ring, and coefficient_ring returns the field $K$.
length(f::PuiseuxMPolyRingElem)
coefficients(f::PuiseuxMPolyRingElem)
monomials(f::PuiseuxMPolyRingElem)
exponent_vectors(f::PuiseuxMPolyRingElem)
leading_coefficient(f::PuiseuxMPolyRingElem)
is_gen(f::PuiseuxMPolyRingElem)
is_monomial(f::PuiseuxMPolyRingElem)
is_term(f::PuiseuxMPolyRingElem)
is_unit(f::PuiseuxMPolyRingElem)
canonical_unit(f::PuiseuxMPolyRingElem)The exponent vectors have entries of type Rational{Int}. The units are the nonzero terms, i.e. the nonzero constant multiples of monomials. As for Laurent polynomials, the canonical unit of f is the canonical unit of its leading coefficient times $x_1^{m_1} \cdots x_n^{m_n}$, where $m_i$ is the smallest exponent of $x_i$ in f.
julia> R, (x, y) = puiseux_polynomial_ring(QQ, ["x", "y"]);
julia> f = x^(1//2) + 2*y^(1//3);
julia> collect(coefficients(f))
2-element Vector{Rational{BigInt}}:
1
2
julia> exponent_vectors(f)
2-element Vector{Vector{Rational{Int64}}}:
[1//2, 0]
[0, 1//3]
julia> is_unit(f), is_unit(2*x^(1//2))
(false, true)
julia> canonical_unit(3*x*y + 2*x^(1//2))
3*x^(1//2)The normalized representation can be inspected with the following functions.
AbstractAlgebra.Generic.poly — Method
poly(f::PuiseuxMPolyRingElem)Return the Laurent polynomial $g$ in base_ring(parent(f)) with $f(x_1, \dots, x_n) = g(x_1^{1/d}, \dots, x_n^{1/d})$, where $d$ is scale(f).
Examples
julia> R, (x, y) = puiseux_polynomial_ring(QQ, ["x", "y"]);
julia> poly(x^(1//2) + 2*y^(1//3))
x^3 + 2*y^2AbstractAlgebra.Generic.scale — Method
scale(f::PuiseuxMPolyRingElem)Return the least common denominator $d > 0$ of the exponents of f, so that f is the Laurent polynomial poly(f) evaluated at $x_1^{1/d}, \dots, x_n^{1/d}$.
Examples
julia> R, (x, y) = puiseux_polynomial_ring(QQ, ["x", "y"]);
julia> scale(x^(1//2) + 2*y^(1//3))
6Powering
^(f::PuiseuxMPolyRingElem, n::Integer)
^(f::PuiseuxMPolyRingElem, q::Rational)Any Puiseux polynomial can be raised to a nonnegative integer power. A negative integer power requires f to be a monomial times a constant, and a non-integer rational power requires f to be a monomial with coefficient one.
julia> R, (x, y) = puiseux_polynomial_ring(QQ, ["x", "y"]);
julia> (x^(1//2) + y)^2
x + 2*x^(1//2)*y + y^2
julia> (x*y^2)^(1//3)
x^(1//3)*y^(2//3)
julia> (x + y)^(1//2)
ERROR: ArgumentError: only monomials can be exponentiated to non-integer powers
[...]Divisibility
divexact(f::PuiseuxMPolyRingElem, g::PuiseuxMPolyRingElem; check::Bool = true)
divexact(f::PuiseuxMPolyRingElem, a::RingElement; check::Bool = true)
divides(f::PuiseuxMPolyRingElem, g::PuiseuxMPolyRingElem)
gcd(f::PuiseuxMPolyRingElem, g::PuiseuxMPolyRingElem)divexact returns the quotient of f by a nonzero Puiseux polynomial or constant g, provided the division is exact. divides(f, g) returns a tuple (flag, q) where flag is true if $f = qg$ for some Puiseux polynomial $q$; otherwise q is zero. gcd(f, g) returns a greatest common divisor of f and g; with it, fraction_field(R) gives the field of Puiseux fractions.
julia> R, (x, y) = puiseux_polynomial_ring(QQ, ["x", "y"]);
julia> f = x^(1//2) + 2*y^(1//3);
julia> divexact(f^2, f)
x^(1//2) + 2*y^(1//3)
julia> divexact(f, x^(1//6))
x^(1//3) + 2*x^(-1//6)*y^(1//3)
julia> divides(f^2, f)
(true, x^(1//2) + 2*y^(1//3))
julia> divides(x, f)
(false, 0)
julia> gcd(1 - x, 1 - x^(1//2))
x^(1//2) - 1
julia> K = fraction_field(R);
julia> (1 - K(x)) // (1 - K(x^(1//2)))
x^(1//2) + 1Ordering
Base.isless — Method
isless(f::PuiseuxMPolyRingElem, g::PuiseuxMPolyRingElem)Return whether $f < g$ in the ordering of univariate Puiseux polynomials over an ordered field in which the variable is positive and smaller than every positive element of the field: $f < g$ if and only if the lowest-order term of $g - f$ has a positive coefficient. The ordering extends to the fraction field of the Puiseux polynomial ring; see Joswig et al..
Comparisons with integers, rationals and elements of the coefficient field are also supported.
Examples
julia> R, (t,) = puiseux_polynomial_ring(QQ, [:t]);
julia> 0 < t^2 < t < t^(1//2) < 1//1000
true
julia> K = fraction_field(R);
julia> 1000 < K(1) // K(t)
trueChanging the coefficient ring
change_base_ring(K::Ring, f::PuiseuxMPolyRingElem; cached::Bool = true, parent::PuiseuxMPolyRing)
map_coefficients(g, f::PuiseuxMPolyRingElem; cached::Bool = true, parent::PuiseuxMPolyRing)Return the Puiseux polynomial obtained from f by coercing each coefficient into K, respectively by applying g to each coefficient. Unless parent is given, the result lies in the Puiseux polynomial ring over K, respectively over the parent of the images of g, in the same variables as parent(f).
julia> R, (x, y) = puiseux_polynomial_ring(QQ, ["x", "y"]);
julia> map_coefficients(c -> 2*c, x^(1//2) + 3*y^(1//3))
2*x^(1//2) + 6*y^(1//3)Valuation
AbstractAlgebra.valuation — Method
valuation(f::PuiseuxMPolyRingElem)Return the smallest exponent occurring in the univariate Puiseux polynomial f, or PosInf() if f is zero.
Examples
julia> R, (t,) = puiseux_polynomial_ring(QQ, ["t"]);
julia> valuation(t^(-2//3) + t^(1//2))
-2//3