Skip to content

Commit

Permalink
Unified interface for constructors containing variable names (#1360)
Browse files Browse the repository at this point in the history
  • Loading branch information
mgkurtz authored Nov 22, 2023
1 parent c4bf93b commit 562f826
Show file tree
Hide file tree
Showing 15 changed files with 662 additions and 252 deletions.
51 changes: 34 additions & 17 deletions docs/src/constructors.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ For example, to create a parent object for univariate polynomials over the integ
we use the `polynomial_ring` parent object constructor.

```julia
R, x = polynomial_ring(ZZ, "x")
R, x = polynomial_ring(ZZ, :x)
f = x^3 + 3x + 1
g = R(12)
```
Expand All @@ -57,19 +57,36 @@ $12$ to an element of the polynomial ring $\mathbb{Z}[x]$.
For convenience, we provide a list of all the parent object constructors in
AbstractAlgebra.jl and explain what mathematical domains they represent.

| Mathematics | AbstractAlgebra.jl constructor |
|----------------------------------|---------------------------------------------|
| $R = \mathbb{Z}$ | `R = ZZ` |
| $R = \mathbb{Q}$ | `R = QQ` |
| $R = \mathbb{F}_{p}$ | `R = GF(p)` |
| $R = \mathbb{Z}/n\mathbb{Z}$ | `R = residue_ring(ZZ, n)` |
| $S = R[x]$ | `S, x = polynomial_ring(R, "x")` |
| $S = R[x, y]$ | `S, (x, y) = polynomial_ring(R, ["x", "y"])`|
| $S = R[[x]]$ (to precision $n$) | `S, x = power_series_ring(R, n, "x")` |
| $S = R((x))$ (to precision $n$) | `S, x = laurent_series_ring(R, n, "x")` |
| $S = K((x))$ (to precision $n$) | `S, x = laurent_series_field(K, n, "x")` |
| $S = \mathrm{Frac}_R$ | `S = fraction_field(R)` |
| $S = R/(f)$ | `S = residue_ring(R, f)` |
| $S = R/(f)$ (with $(f)$ maximal) | `S = residue_field(R, f)` |
| $S = \mathrm{Mat}_{m\times n}(R)$| `S = matrix_space(R, m, n)` |
| $S = \mathbb{Q}[x]/(f)$ | `S, a = number_field(f, "a")` |
| Mathematics | AbstractAlgebra.jl constructor |
|:-------------------------------------|:------------------------------------------------------|
| $R = \mathbb{Z}$ | `R = ZZ` |
| $R = \mathbb{Q}$ | `R = QQ` |
| $R = \mathbb{F}_{p}$ | `R = GF(p)` |
| $R = \mathbb{Z}/n\mathbb{Z}$ | `R = residue_ring(ZZ, n)` |
| $S = R[x]$ | `S, x = polynomial_ring(R, :x)` |
| $S = R[x, y]$ | `S, (x, y) = polynomial_ring(R, [:x, :y])` |
| $S = R\langle x, y\rangle$ | `S, (x, y) = free_associative_algebra(R, [:x, :y])` |
| $S = K(x)$ | `S, x = rational_function_field(K, :x)` |
| $S = K(x, y)$ | `S, (x, y) = rational_function_field(K, [:x, :y])` |
| $S = R[[x]]$ (to precision $n$) | `S, x = power_series_ring(R, n, :x)` |
| $S = R[[x, y]]$ (to precision $n$) | `S, (x, y) = power_series_ring(R, n, [:x, :y])` |
| $S = R((x))$ (to precision $n$) | `S, x = laurent_series_ring(R, n, :x)` |
| $S = K((x))$ (to precision $n$) | `S, x = laurent_series_field(K, n, :x)` |
| $S = R((x, y))$ (to precision $n$) | `S, (x, y) = laurent_polynomial_ring(R, n, [:x, :y])` |
| Puiseux series ring to precision $n$ | `S, x = PuiseuxSeriesRing(R, n, :x)` |
| $S = K(x)(y)/(f)$ | `S, y = function_field(f, :y)` with $f\in K(x)[t]$ |
| $S = \mathrm{Frac}_R$ | `S = fraction_field(R)` |
| $S = R/(f)$ | `S = residue_ring(R, f)` |
| $S = R/(f)$ (with $(f)$ maximal) | `S = residue_field(R, f)` |
| $S = \mathrm{Mat}_{m\times n}(R)$ | `S = matrix_space(R, m, n)` |
| $S = \mathbb{Q}[x]/(f)$ | `S, a = number_field(f, :a)` |

## Parent objects with variable names

The multivariate parent object constructors (`polynomial_ring`, `power_series_ring`, `free_associative_algebra`, `laurent_polynomial_ring`, and `rational_function_field`) share a common interface for specifying the variable names, which is provided by `@varnames_interface`.

```@docs
AbstractAlgebra.@varnames_interface
AbstractAlgebra.variable_names
AbstractAlgebra.reshape_to_varnames
```
11 changes: 2 additions & 9 deletions docs/src/mpoly_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,10 @@ and floating point types.

To construct a multivariate polynomial ring, there is the following constructor.

```julia
polynomial_ring(R::Ring, s::Vector{<:VarName}; ordering=:lex, cached::Bool=true)
```@docs; canonical=false
polynomial_ring(R::Ring, s::Vector{Symbol})
```

Return a tuple, `S, vars` consisting of a polynomial ring $S$ and an array of
generators (variables) which print according to the strings in the supplied
vector $s$. The ordering can at present be `:lex`, `:deglex` or `:degrevlex`.
By default, the polynomial ring is cached, and creating a polynomial ring with
the same data will return the same ring object $S$. If this caching is not
desired, it can be switched off by setting `cached=false`.

Polynomials in a given ring can be constructed using the generators and basic
polynomial arithmetic. However, this is inefficient and the following build
context is provided for building polynomials term-by-term. It assumes the
Expand Down
8 changes: 5 additions & 3 deletions docs/src/mpolynomial.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ and the polynomial ring types belong to the abstract type `MPolyRing{T}`.
## Polynomial ring constructors

In order to construct multivariate polynomials in AbstractAlgebra.jl, one must first
construct the polynomial ring itself. This is accomplished with one of the following
construct the polynomial ring itself. This is accomplished with the following
constructors.

```@docs
polynomial_ring(R::Ring, S::Vector{VarName}; cached::Bool = true, ordering::Symbol=:lex)
polynomial_ring(R::Ring, n::Int, s::VarName; cached::Bool = false, ordering::Symbol = :lex)
polynomial_ring(::Ring, ::Vector{Symbol})
polynomial_ring(::Ring, ::Vararg)
polynomial_ring(::Ring, ::Int)
@polynomial_ring
```

Like for univariate polynomials, a shorthand constructor is
Expand Down
4 changes: 2 additions & 2 deletions docs/src/polynomial.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ can accept any AbstractAlgebra polynomial type.
In order to construct polynomials in AbstractAlgebra.jl, one must first construct the
polynomial ring itself. This is accomplished with the following constructor.

```@docs
polynomial_ring(R::Ring, s::VarName; cached::Bool = true)
```@docs; canonical=false
polynomial_ring(R::NCRing, s::VarName; cached::Bool = true)
```

A shorthand version of this function is provided: given a base ring `R`, we abbreviate
Expand Down
39 changes: 0 additions & 39 deletions src/AbsMSeries.jl
Original file line number Diff line number Diff line change
Expand Up @@ -214,42 +214,3 @@ when it was created.
function rand(S::MSeriesRing, term_range, v...)
rand(GLOBAL_RNG, S, term_range, v...)
end

###############################################################################
#
# power_series_ring constructor
#
###############################################################################

function power_series_ring(R::Ring, weights::Vector{Int}, prec::Int,
s::Vector{Symbol}; cached::Bool=true, model=:capped_absolute)
return Generic.power_series_ring(R, weights, prec, s; cached=cached, model=model)
end

function power_series_ring(R::Ring, prec::Vector{Int},
s::Vector{Symbol}; cached::Bool=true, model=:capped_absolute)
return Generic.power_series_ring(R, prec, s; cached=cached, model=model)
end

function power_series_ring(R::Ring, prec::Vector{Int},
s::AbstractVector{<:VarName}; cached::Bool=true, model=:capped_absolute)
sym = [Symbol(v) for v in s]
return power_series_ring(R, prec, sym; cached=cached, model=model)
end

function power_series_ring(R::Ring, weights::Vector{Int}, prec::Int,
s::AbstractVector{<:VarName}; cached::Bool=true, model=:capped_absolute)
sym = [Symbol(v) for v in s]
return power_series_ring(R, weights, prec, sym; cached=cached, model=model)
end

function power_series_ring(R::Ring, prec::Int,
s::Vector{Symbol}; cached::Bool=true, model=:capped_absolute)
return Generic.power_series_ring(R, prec, s; cached=cached, model=model)
end

function power_series_ring(R::Ring, prec::Int,
s::AbstractVector{<:VarName}; cached::Bool=true, model=:capped_absolute)
sym = [Symbol(v) for v in s]
return power_series_ring(R, prec, sym; cached=cached, model=model)
end
26 changes: 16 additions & 10 deletions src/AbstractAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -767,8 +767,12 @@ export _checkbounds
export @alias
export @attr
export @attributes
export @free_associative_algebra
export @laurent_polynomial_ring
export @perm_str
export @polynomial_ring
export @power_series_ring
export @rational_function_field
export abs_series
export abs_series_type
export AbsPowerSeriesRing
Expand Down Expand Up @@ -1229,11 +1233,22 @@ export Generic

###############################################################################
#
# Polynomial Ring S, x = R["x"] syntax
# misc
#
###############################################################################

include("misc/ProductIterator.jl")
include("misc/Evaluate.jl")
include("misc/VarNames.jl")

###############################################################################
#
# Polynomial Ring S, x = R[:x] syntax
#
###############################################################################

getindex(R::NCRing, s::VarName) = polynomial_ring(R, s)
# `R[:x, :y]` returns `S, [x, y]` instead of `S, x, y`
getindex(R::NCRing, s::VarName, ss::VarName...) =
polynomial_ring(R, [Symbol(x) for x in (s, ss...)])

Expand Down Expand Up @@ -1264,15 +1279,6 @@ Base.typed_vcat(R::NCRing, args...) = _matrix(R, vcat(args...))
_matrix(R::NCRing, a::AbstractVector) = matrix(R, length(a), isempty(a) ? 0 : 1, a)
_matrix(R::NCRing, a::AbstractMatrix) = matrix(R, a)

###############################################################################
#
# misc
#
###############################################################################

include("misc/ProductIterator.jl")
include("misc/Evaluate.jl")

###############################################################################
#
# Load error objects
Expand Down
44 changes: 0 additions & 44 deletions src/FreeAssAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -255,47 +255,3 @@ end
function rand(S::FreeAssAlgebra, term_range, exp_bound, v...)
rand(GLOBAL_RNG, S, term_range, exp_bound, v...)
end

###############################################################################
#
# free_associative_algebra constructor
#
###############################################################################

function free_associative_algebra(
R::Ring,
s::AbstractVector{<:VarName};
cached::Bool = true)

S = [Symbol(v) for v in s]
return Generic.free_associative_algebra(R, S, cached=cached)
end

function free_associative_algebra(
R::Ring,
s::Vector{Symbol};
cached::Bool = true)

return Generic.free_associative_algebra(R, s, cached=cached)
end

function free_associative_algebra(
R::Ring,
n::Int,
s::VarName;
cached::Bool = false)

S = [Symbol(s, i) for i in 1:n]
return Generic.free_associative_algebra(R, S; cached=cached)
end

function free_associative_algebra(
R::Ring,
n::Int,
s::Symbol=:x;
cached::Bool = false)

S = [Symbol(s, i) for i in 1:n]
return Generic.free_associative_algebra(R, S; cached=cached)
end

32 changes: 13 additions & 19 deletions src/LaurentMPoly.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,24 +143,18 @@ end
###############################################################################

@doc raw"""
laurent_polynomial_ring(R::Ring, s::Vector{T}; cached::Bool = true) where T <: VarName
Given a base ring `R` and an array of strings `s` specifying how the
generators (variables) should be printed, return a tuple `T, (x1, x2, ...)`
representing the new ring $T = R[x1, 1/x1, x2, 1/x2, ...]$ and the generators
$x1, x2, ...$ of the ring. By default the parent object `T` will
depend only on `R` and `x1, x2, ...` and will be cached. Setting the optional
argument `cached` to `false` will prevent the parent object `T` from being
cached.
"""
function laurent_polynomial_ring(R::Ring, s::AbstractVector{<:VarName}; cached::Bool = true)
return Generic.laurent_polynomial_ring(R, [Symbol(v) for v in s], cached=cached)
end
laurent_polynomial_ring(R::Ring, varnames...; cached::Bool = true)
function laurent_polynomial_ring(R::Ring, s::Vector{Symbol}; cached::Bool = true)
return Generic.laurent_polynomial_ring(R, s; cached=cached)
end
Given a base ring `R` and variable names `varnames...`, say `:x, :y, :z`, return
a tuple `S, x, y, z` representing the new ring $S = R[x, 1/x, y, 1/y, z, 1/z]$
and the generators $x, y, z$ of the ring.
function laurent_polynomial_ring(R::Ring, n::Int, s::VarName=:x; cached::Bool = false)
return Generic.laurent_polynomial_ring(R, [Symbol(s, i) for i=1:n]; cached=cached)
end
By default (`cached=true`), the output `S` will be cached, i.e. if
`laurent_polynomial_ring ` is invoked again with the same arguments, the same
(*identical*) ring is returned. Setting `cached` to `false` ensures a distinct
new ring is returned, and will also prevent it from being cached.
For information about the many ways to specify `varnames...` refer to [`polynomial_ring`](@ref) or the
specification in [`AbstractAlgebra.@varnames_interface`](@ref).
"""
laurent_polynomial_ring(R::Ring, s::Vector{Symbol})
Loading

0 comments on commit 562f826

Please sign in to comment.