From 86df96819733d8c3ea5914708512566559948524 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Tue, 12 Nov 2024 18:45:21 +0000 Subject: [PATCH] build based on 286b6b4 --- dev/.documenter-siteinfo.json | 2 +- dev/assertions/index.html | 22 +++---- dev/constructors/index.html | 6 +- dev/direct_sum/index.html | 6 +- dev/euclidean_interface/index.html | 2 +- dev/extending_abstractalgebra/index.html | 20 +++---- dev/field/index.html | 2 +- dev/field_interface/index.html | 2 +- dev/field_introduction/index.html | 2 +- dev/finfield/index.html | 6 +- dev/fraction/index.html | 8 +-- dev/fraction_interface/index.html | 2 +- dev/free_associative_algebra/index.html | 10 ++-- dev/free_module/index.html | 4 +- dev/function_field/index.html | 16 ++--- dev/functional_map/index.html | 2 +- dev/ideal/index.html | 8 +-- dev/index.html | 2 +- dev/integer/index.html | 8 +-- dev/interface_introduction/index.html | 2 +- dev/laurent_mpolynomial/index.html | 2 +- dev/laurent_polynomial/index.html | 4 +- dev/linear_solving/index.html | 12 ++-- dev/map_cache/index.html | 2 +- dev/map_interface/index.html | 6 +- dev/map_introduction/index.html | 2 +- dev/map_with_inverse/index.html | 2 +- dev/matrix/index.html | 76 ++++++++++++------------ dev/matrix_algebras/index.html | 6 +- dev/matrix_interface/index.html | 2 +- dev/matrix_introduction/index.html | 2 +- dev/misc/index.html | 34 +++++------ dev/module/index.html | 10 ++-- dev/module_homomorphism/index.html | 14 ++--- dev/module_interface/index.html | 2 +- dev/module_introduction/index.html | 2 +- dev/mpoly_interface/index.html | 4 +- dev/mpolynomial/index.html | 34 +++++------ dev/mseries/index.html | 2 +- dev/ncpolynomial/index.html | 16 ++--- dev/ncring_interface/index.html | 2 +- dev/perm/index.html | 34 +++++------ dev/poly_interface/index.html | 2 +- dev/polynomial/index.html | 42 ++++++------- dev/puiseux/index.html | 14 ++--- dev/quotient_module/index.html | 6 +- dev/rand/index.html | 2 +- dev/rational/index.html | 2 +- dev/real/index.html | 2 +- dev/residue/index.html | 12 ++-- dev/residue_interface/index.html | 2 +- dev/ring/index.html | 30 +++++----- dev/ring_interface/index.html | 2 +- dev/ring_introduction/index.html | 2 +- dev/series/index.html | 18 +++--- dev/series_interface/index.html | 2 +- dev/submodule/index.html | 8 +-- dev/total_fraction/index.html | 2 +- dev/types/index.html | 2 +- dev/univpolynomial/index.html | 4 +- dev/visualizing_types/index.html | 2 +- dev/ytabs/index.html | 40 ++++++------- 62 files changed, 299 insertions(+), 299 deletions(-) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index f845c118c..65b6901e1 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.6","generation_timestamp":"2024-11-12T11:52:36","documenter_version":"1.7.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.6","generation_timestamp":"2024-11-12T18:45:06","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/dev/assertions/index.html b/dev/assertions/index.html index 09e1ef058..58aa39cd0 100644 --- a/dev/assertions/index.html +++ b/dev/assertions/index.html @@ -1,12 +1,12 @@ Assertion and Verbosity Macros · AbstractAlgebra.jl

Assertion and Verbosity Macros

We describe here various macros provided by AbstractAlgebra.

Verbosity macros

There is a list of symbols called verbosity scopes which represent keywords used to trigger some particular macros within the codes. Each of these verbosity scopes is associated with a verbosity level, being set to $0$ by default. A verbosity macro is joined to a verbosity scope S and a value k (set to $1$ by default) such that, if the current verbosity level l of S is bigger than or equal to k, then the macro triggers a given action.

AbstractAlgebra.add_verbosity_scopeMethod
AbstractAlgebra.add_verbosity_scope(s::Symbol) -> Nothing

Add the symbol s to the list of (global) verbosity scopes.

Examples

julia> AbstractAlgebra.add_verbosity_scope(:MyScope)
-
source
AbstractAlgebra.set_verbosity_levelMethod
AbstractAlgebra.set_verbosity_level(s::Symbol, l::Int) -> Int

If s represents a known verbosity scope, set the current verbosity level of s to l.

One can access the current verbosity level of s by calling the function get_verbosity_level.

If s is not yet known as a verbosity scope, the function raises an ErrorException showing the error message "Not a valid symbol". One can add s to the list of verbosity scopes by calling the function add_verbosity_scope.

Examples

julia> AbstractAlgebra.add_verbosity_scope(:MyScope)
+
source
AbstractAlgebra.set_verbosity_levelMethod
AbstractAlgebra.set_verbosity_level(s::Symbol, l::Int) -> Int

If s represents a known verbosity scope, set the current verbosity level of s to l.

One can access the current verbosity level of s by calling the function get_verbosity_level.

If s is not yet known as a verbosity scope, the function raises an ErrorException showing the error message "Not a valid symbol". One can add s to the list of verbosity scopes by calling the function add_verbosity_scope.

Examples

julia> AbstractAlgebra.add_verbosity_scope(:MyScope)
 
 julia> AbstractAlgebra.set_verbosity_level(:MyScope, 4)
 4
 
 julia> AbstractAlgebra.set_verbosity_level(:MyScope, 0)
-0
source
AbstractAlgebra.get_verbosity_levelMethod
AbstractAlgebra.get_verbosity_level(s::Symbol) -> Int

If s represents a known verbosity scope, return the current verbosity level of s.

One can modify the current verbosity level of s by calling the function set_verbosity_level.

If s is not yet known as a verbosity scope, the function raises an ErrorException showing the error message "Not a valid symbol". One can add s to the list of verbosity scopes by calling the function add_verbosity_scope.

Examples

julia> AbstractAlgebra.add_verbosity_scope(:MyScope)
+0
source
AbstractAlgebra.get_verbosity_levelMethod
AbstractAlgebra.get_verbosity_level(s::Symbol) -> Int

If s represents a known verbosity scope, return the current verbosity level of s.

One can modify the current verbosity level of s by calling the function set_verbosity_level.

If s is not yet known as a verbosity scope, the function raises an ErrorException showing the error message "Not a valid symbol". One can add s to the list of verbosity scopes by calling the function add_verbosity_scope.

Examples

julia> AbstractAlgebra.add_verbosity_scope(:MyScope)
 
 julia> AbstractAlgebra.get_verbosity_level(:MyScope)
 0
@@ -21,7 +21,7 @@
 0
 
 julia> AbstractAlgebra.get_verbosity_level(:MyScope)
-0
source

Printings

Printings

AbstractAlgebra.@vprintlnMacro
@vprintln(S::Symbol, k::Int, msg::String)
 @vprintln S k msg
 
 @vprintln(S::Symbol, msg::String)
@@ -45,11 +45,11 @@
 
 julia> vprint_example()
 Triggered
-Triggered

If one does not setup in advance a verbosity scope, the macro will raise an ExceptionError showing the error message "Not a valid symbol".

source
AbstractAlgebra.@vprintMacro
@vprint(S::Symbol, k::Int, msg::String)
+Triggered

If one does not setup in advance a verbosity scope, the macro will raise an ExceptionError showing the error message "Not a valid symbol".

source
AbstractAlgebra.@vprintMacro
@vprint(S::Symbol, k::Int, msg::String)
 @vprint S k msg
 
 @vprint(S::Symbol, msg::String)
-@vprint S msg

The same as @vprintln, but without the final newline.

source

Actions

Actions

AbstractAlgebra.@v_doMacro
@v_do(S::Symbol, k::Int, act::Expr)
 @v_do S k act
 
 @v_do(S::Symbol, act::Expr)
@@ -73,14 +73,14 @@
 v_do_example (generic function with 1 method)
 
 julia> v_do_example(1,1,1,1)
-(2, 3, 1, 1)

If one does not setup in advance a verbosity scope, the macro will raise an ExceptionError showing the error message "Not a valid symbol".

source

Assertion macros

There is a list of symbols called assertion scopes which represent keywords used to trigger some particular macros within the codes. Each of these assertion scopes is associated with an assertion level, being set to $0$ by default. An assertion macro is joined to an assertion scope S and a value k (set to $1$ by default) such that, if the current assertion level l of S is bigger than or equal to k, then the macro triggers an action on the given assertion

AbstractAlgebra.add_assertion_scopeMethod
AbstractAlgebra.add_assertion_scope(s::Symbol) -> Nothing

Add the symbol s to the list of (global) assertion scopes.

Examples

julia> AbstractAlgebra.add_assertion_scope(:MyScope)
-
source
AbstractAlgebra.set_assertion_levelMethod
AbstractAlgebra.set_assertion_level(s::Symbol, l::Int) -> Int

If s represents a known assertion scope, set the current assertion level of s to l.

One can access the current assertion level of s by calling the function get_assertion_level.

If s is not yet known as an assertion scope, the function raises an ErrorException showing the error message "Not a valid symbol". One can add s to the list of assertion scopes by calling the function add_assertion_scope.

Examples

julia> AbstractAlgebra.add_assertion_scope(:MyScope)
+(2, 3, 1, 1)

If one does not setup in advance a verbosity scope, the macro will raise an ExceptionError showing the error message "Not a valid symbol".

source

Assertion macros

There is a list of symbols called assertion scopes which represent keywords used to trigger some particular macros within the codes. Each of these assertion scopes is associated with an assertion level, being set to $0$ by default. An assertion macro is joined to an assertion scope S and a value k (set to $1$ by default) such that, if the current assertion level l of S is bigger than or equal to k, then the macro triggers an action on the given assertion

AbstractAlgebra.add_assertion_scopeMethod
AbstractAlgebra.add_assertion_scope(s::Symbol) -> Nothing

Add the symbol s to the list of (global) assertion scopes.

Examples

julia> AbstractAlgebra.add_assertion_scope(:MyScope)
+
source
AbstractAlgebra.set_assertion_levelMethod
AbstractAlgebra.set_assertion_level(s::Symbol, l::Int) -> Int

If s represents a known assertion scope, set the current assertion level of s to l.

One can access the current assertion level of s by calling the function get_assertion_level.

If s is not yet known as an assertion scope, the function raises an ErrorException showing the error message "Not a valid symbol". One can add s to the list of assertion scopes by calling the function add_assertion_scope.

Examples

julia> AbstractAlgebra.add_assertion_scope(:MyScope)
 
 julia> AbstractAlgebra.set_assertion_level(:MyScope, 4)
 4
 
 julia> AbstractAlgebra.set_assertion_level(:MyScope, 0)
-0
source
AbstractAlgebra.get_assertion_levelMethod
AbstractAlgebra.get_assertion_level(s::Symbol) -> Int

If s represents a symbol of a known assertion scope, return the current assertion level of s.

One can modify the current assertion level of s by calling the function set_assertion_level.

If s is not yet known as an assertion scope, the function raises an ErrorException showing the error message "Not a valid symbol". One can add s to the list of assertion scopes by calling the function add_assertion_scope.

Examples

julia> AbstractAlgebra.add_assertion_scope(:MyScope)
+0
source
AbstractAlgebra.get_assertion_levelMethod
AbstractAlgebra.get_assertion_level(s::Symbol) -> Int

If s represents a symbol of a known assertion scope, return the current assertion level of s.

One can modify the current assertion level of s by calling the function set_assertion_level.

If s is not yet known as an assertion scope, the function raises an ErrorException showing the error message "Not a valid symbol". One can add s to the list of assertion scopes by calling the function add_assertion_scope.

Examples

julia> AbstractAlgebra.add_assertion_scope(:MyScope)
 
 julia> AbstractAlgebra.get_assertion_level(:MyScope)
 0
@@ -95,7 +95,7 @@
 0
 
 julia> AbstractAlgebra.get_assertion_level(:MyScope)
-0
source

Check

Check

AbstractAlgebra.@hassertMacro
@hassert(S::Symbol, k::Int, assert::Expr)
 @hassert S k assert
 
 @hassert(S::Symbol, assert::Expr)
@@ -124,7 +124,7 @@
 1
 
 julia> AbstractAlgebra.set_assertion_level(:MyScope, 0)
-0

If one does not setup in advance an assertion scope, the macro will raise an ExceptionError showing the error message "Not a valid symbol".

source

Miscellaneous

AbstractAlgebra.@reqMacro
@req(assert, msg)
+0

If one does not setup in advance an assertion scope, the macro will raise an ExceptionError showing the error message "Not a valid symbol".

source

Miscellaneous

AbstractAlgebra.@reqMacro
@req(assert, msg)
 @req assert msg

Check whether the assertion assert is true. If not, throw an ArgumentError with error message msg.

The macro @req takes two arguments: the first one is an assertion assert (an expression which returns a boolean) and a string msg corresponding to the desired error message to be returned whenever assert is false.

If the number of arguments is not 2, an AssertionError is raised.

Examples

julia> function req_test(x::Int)
        @req iseven(x) "x must be even"
        return div(x,2)
@@ -140,4 +140,4 @@
        catch e e
        end
 1
-
source
+source diff --git a/dev/constructors/index.html b/dev/constructors/index.html index dd1b7be93..e225d35a2 100644 --- a/dev/constructors/index.html +++ b/dev/constructors/index.html @@ -43,7 +43,7 @@ @g (macro with 1 method) julia> @g("parameters", [:x, :y], a=1, b=2; c=3) -("parameters", :c => 3, :a => 1, :b => 2)source
AbstractAlgebra.variable_namesFunction
variable_names(a...) -> Vector{Symbol}
+("parameters", :c => 3, :a => 1, :b => 2)
source
AbstractAlgebra.variable_namesFunction
variable_names(a...) -> Vector{Symbol}
 variable_names(a::Tuple) -> Vector{Symbol}

Create a vector of variable names from a variable name specification.

Each argument can be either an Array of VarNames, or of the form s::VarName => iter, or of the form s::VarName => (iter...). Here iter is supposed to be any iterable, typically a range like 1:5. The :s => iter specification is shorthand for ["s[$i]" for i in iter]. Similarly :s => (iter1, iter2) is shorthand for ["s[$i,$j]" for i in iter1, j in iter2], and likewise for three and more iterables.

As an alternative "s#" => iter is shorthand for ["s$i" for i in iter]. This also works for multiple iterators in that"s#" => (iter1, iter2) is shorthand for ["s$i$j" for i in iter1, j in iter2].

Examples

julia> AbstractAlgebra.variable_names([:x, :y])
 2-element Vector{Symbol}:
  :x
@@ -81,7 +81,7 @@
  :a
  :b
  :c
- :z
source
AbstractAlgebra.reshape_to_varnamesFunction
reshape_to_varnames(vec::Vector{T}, varnames...) :: Tuple{Array{<:Any, T}}
+ :z
source
AbstractAlgebra.reshape_to_varnamesFunction
reshape_to_varnames(vec::Vector{T}, varnames...) :: Tuple{Array{<:Any, T}}
 reshape_to_varnames(vec::Vector{T}, varnames::Tuple) :: Tuple{Array{<:Any, T}}

Turn vec into the shape of varnames. Reverse flattening from variable_names.

Examples

julia> s = ([:a, :b], "x#" => (1:1, 1:2), "y#" => 1:2, [:z]);
 
 julia> AbstractAlgebra.reshape_to_varnames(AbstractAlgebra.variable_names(s...), s...)
@@ -94,4 +94,4 @@
 (AbstractAlgebra.Generic.MPoly{BigInt}[a, b], AbstractAlgebra.Generic.MPoly{BigInt}[x11 x12], AbstractAlgebra.Generic.MPoly{BigInt}[y1, y2], AbstractAlgebra.Generic.MPoly{BigInt}[z])
 
 julia> R, (a, b), x, y, z = polynomial_ring(ZZ, s...)
-(Multivariate polynomial ring in 7 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[a, b], AbstractAlgebra.Generic.MPoly{BigInt}[x11 x12], AbstractAlgebra.Generic.MPoly{BigInt}[y1, y2], AbstractAlgebra.Generic.MPoly{BigInt}[z])
source
+(Multivariate polynomial ring in 7 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[a, b], AbstractAlgebra.Generic.MPoly{BigInt}[x11 x12], AbstractAlgebra.Generic.MPoly{BigInt}[y1, y2], AbstractAlgebra.Generic.MPoly{BigInt}[z])source diff --git a/dev/direct_sum/index.html b/dev/direct_sum/index.html index 852bd528c..fec05814f 100644 --- a/dev/direct_sum/index.html +++ b/dev/direct_sum/index.html @@ -1,6 +1,6 @@ Direct Sums · AbstractAlgebra.jl

Direct Sums

AbstractAlgebra allows the construction of the external direct sum of any nonempty vector of finitely presented modules.

Note that external direct sums are considered equal iff they are the same object.

Generic direct sum type

AbstractAlgebra provides a generic direct sum type Generic.DirectSumModule{T} where T is the element type of the base ring. The implementation is in src/generic/DirectSum.jl

Elements of direct sum modules have type Generic.DirectSumModuleElem{T}.

Abstract types

Direct sum module types belong to the abstract type FPModule{T} and their elements to FPModuleElem{T}.

Constructors

AbstractAlgebra.direct_sumFunction
direct_sum(m::Vector{<:FPModule{T}}) where T <: RingElement
-direct_sum(vals::FPModule{T}...) where T <: RingElement

Return a tuple $M, f, g$ consisting of $M$ the direct sum of the modules m (supplied as a vector of modules), a vector $f$ of the injections of the $m[i]$ into $M$ and a vector $g$ of the projections from $M$ onto the $m[i]$.

source

Examples

julia> F = free_module(ZZ, 5)
+direct_sum(vals::FPModule{T}...) where T <: RingElement

Return a tuple $M, f, g$ consisting of $M$ the direct sum of the modules m (supplied as a vector of modules), a vector $f$ of the injections of the $m[i]$ into $M$ and a vector $g$ of the projections from $M$ onto the $m[i]$.

source

Examples

julia> F = free_module(ZZ, 5)
 Free module of rank 5 over integers
 
 julia> m1 = F(BigInt[4, 7, 8, 2, 6])
@@ -31,7 +31,7 @@
 (Submodule over integers with 2 generators and no relations, Hom: S3 -> F)
 
 julia> D, f = direct_sum(S1, S2, S3)
-(DirectSumModule over integers, AbstractAlgebra.Generic.ModuleHomomorphism{BigInt}[Hom: S1 -> D, Hom: S2 -> D, Hom: S3 -> D], AbstractAlgebra.Generic.ModuleHomomorphism{BigInt}[Hom: D -> S1, Hom: D -> S2, Hom: D -> S3])

Functionality for direct sums

In addition to the Module interface, AbstractAlgebra direct sums implement the following functionality.

Basic manipulation

Examples

julia> F = free_module(ZZ, 5)
+(DirectSumModule over integers, AbstractAlgebra.Generic.ModuleHomomorphism{BigInt}[Hom: S1 -> D, Hom: S2 -> D, Hom: S3 -> D], AbstractAlgebra.Generic.ModuleHomomorphism{BigInt}[Hom: D -> S1, Hom: D -> S2, Hom: D -> S3])

Functionality for direct sums

In addition to the Module interface, AbstractAlgebra direct sums implement the following functionality.

Basic manipulation

Examples

julia> F = free_module(ZZ, 5)
 Free module of rank 5 over integers
 
 julia> m1 = F(BigInt[4, 7, 8, 2, 6])
@@ -96,4 +96,4 @@
 julia> psi = ModuleHomomorphism(D, D, [r, r])
 Module homomorphism
   from DirectSumModule over rationals
-  to DirectSumModule over rationals
+ to DirectSumModule over rationals diff --git a/dev/euclidean_interface/index.html b/dev/euclidean_interface/index.html index bb0a80659..a2173f0a7 100644 --- a/dev/euclidean_interface/index.html +++ b/dev/euclidean_interface/index.html @@ -1,2 +1,2 @@ -Euclidean Ring Interface · AbstractAlgebra.jl

Euclidean Ring Interface

If a ring provides a meaningful Euclidean structure such that a useful Euclidean remainder can be computed practically, various additional functionality is provided by AbstractAlgebra.jl for those rings. This functionality depends on the following functions existing. An implementation must provide divrem, and the remaining are optional as generic fallbacks exist.

Base.divremMethod
divrem(f::T, g::T) where T <: RingElem

Return a pair q, r consisting of the Euclidean quotient and remainder of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

source
Base.modMethod
mod(f::T, g::T) where T <: RingElem

Return the Euclidean remainder of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

Note

For best compatibility with the internal assumptions made by AbstractAlgebra, the Euclidean remainder function should provide unique representatives for the residue classes; the mod function should satisfy

  1. mod(a_1, b) = mod(a_2, b) if and only if $b$ divides $a_1 - a_2$, and
  2. mod(0, b) = 0.
source
Base.divMethod
div(f::T, g::T) where T <: RingElem

Return the Euclidean quotient of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

source
AbstractAlgebra.mulmodMethod
mulmod(f::T, g::T, m::T) where T <: RingElem

Return mod(f*g, m) but possibly computed more efficiently.

source
Base.powermodMethod
powermod(f::T, e::Int, m::T) where T <: RingElem

Return mod(f^e, m) but possibly computed more efficiently.

source
Base.invmodMethod
invmod(f::T, m::T) where T <: RingElem

Return an inverse of $f$ modulo $m$, meaning that isone(mod(invmod(f,m)*f,m)) returns true.

If such an inverse doesn't exist, a NotInvertibleError should be thrown.

source
AbstractAlgebra.dividesMethod
divides(f::T, g::T) where T <: RingElem

Return a pair, flag, q, where flag is set to true if $g$ divides $f$, in which case q is set to the quotient, or flag is set to false and q is set to zero(f).

source
AbstractAlgebra.removeMethod
remove(f::T, p::T) where T <: RingElem

Return a pair v, q where $p^v$ is the highest power of $p$ dividing $f$ and $q$ is the cofactor after $f$ is divided by this power.

See also valuation, which only returns the valuation.

source
Base.gcdMethod
gcd(a::T, b::T) where T <: RingElem

Return a greatest common divisor of $a$ and $b$, i.e., an element $g$ which is a common divisor of $a$ and $b$, and with the property that any other common divisor of $a$ and $b$ divides $g$.

Note

For best compatibility with the internal assumptions made by AbstractAlgebra, the return is expected to be unit-normalized in such a way that if the return is a unit, that unit should be one.

source
Base.gcdMethod
gcd(f::T, g::T, hs::T...) where T <: RingElem

Return a greatest common divisor of $f$, $g$ and the elements in hs.

source
Base.gcdMethod
gcd(fs::AbstractArray{<:T}) where T <: RingElem

Return a greatest common divisor of the elements in fs. Requires that fs is not empty.

source
Base.lcmMethod
lcm(f::T, g::T) where T <: RingElem

Return a least common multiple of $f$ and $g$, i.e., an element $d$ which is a common multiple of $f$ and $g$, and with the property that any other common multiple of $f$ and $g$ is a multiple of $d$.

source
Base.lcmMethod
lcm(f::T, g::T, hs::T...) where T <: RingElem

Return a least common multiple of $f$, $g$ and the elements in hs.

source
Base.lcmMethod
lcm(fs::AbstractArray{<:T}) where T <: RingElem

Return a least common multiple of the elements in fs. Requires that fs is not empty.

source
Base.gcdxMethod
gcdx(f::T, g::T) where T <: RingElem

Return a triple d, s, t such that $d = gcd(f, g)$ and $d = sf + tg$, with $s$ loosely reduced modulo $g/d$ and $t$ loosely reduced modulo $f/d$.

source
AbstractAlgebra.gcdinvMethod
gcdinv(f::T, g::T) where T <: RingElem

Return a tuple d, s such that $d = gcd(f, g)$ and $s = (f/d)^{-1} \pmod{g/d}$. Note that $d = 1$ iff $f$ is invertible modulo $g$, in which case $s = f^{-1} \pmod{g}$.

source
AbstractAlgebra.crtMethod
crt(r1::T, m1::T, r2::T, m2::T; check::Bool=true) where T <: RingElement

Return an element congruent to $r_1$ modulo $m_1$ and $r_2$ modulo $m_2$. If check = true and no solution exists, an error is thrown.

If T is a fixed precision integer type (like Int), the result will be correct if abs(ri) <= abs(mi) and abs(m1 * m2) < typemax(T).

source
AbstractAlgebra.crtMethod
crt(r::Vector{T}, m::Vector{T}; check::Bool=true) where T <: RingElement

Return an element congruent to $r_i$ modulo $m_i$ for each $i$.

source
AbstractAlgebra.crt_with_lcmMethod
crt_with_lcm(r1::T, m1::T, r2::T, m2::T; check::Bool=true) where T <: RingElement

Return a tuple consisting of an element congruent to $r_1$ modulo $m_1$ and $r_2$ modulo $m_2$ and the least common multiple of $m_1$ and $m_2$. If check = true and no solution exists, an error is thrown.

source
AbstractAlgebra.crt_with_lcmMethod
crt_with_lcm(r::Vector{T}, m::Vector{T}; check::Bool=true) where T <: RingElement

Return a tuple consisting of an element congruent to $r_i$ modulo $m_i$ for each $i$ and the least common multiple of the $m_i$.

source
AbstractAlgebra.coprime_baseFunction
coprime_base(S::Vector{RingElement}) -> Vector{RingElement}

Returns a coprime base for $S$, i.e. the resulting array contains pairwise coprime objects that multiplicatively generate the same set as the input array.

source
AbstractAlgebra.coprime_base_push!Function
coprime_base_push!(S::Vector{RingElem}, a::RingElem) -> Vector{RingElem}

Given an array $S$ of coprime elements, insert a new element, that is, find a coprime base for push(S, a).

source
+Euclidean Ring Interface · AbstractAlgebra.jl

Euclidean Ring Interface

If a ring provides a meaningful Euclidean structure such that a useful Euclidean remainder can be computed practically, various additional functionality is provided by AbstractAlgebra.jl for those rings. This functionality depends on the following functions existing. An implementation must provide divrem, and the remaining are optional as generic fallbacks exist.

Base.divremMethod
divrem(f::T, g::T) where T <: RingElem

Return a pair q, r consisting of the Euclidean quotient and remainder of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

source
Base.modMethod
mod(f::T, g::T) where T <: RingElem

Return the Euclidean remainder of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

Note

For best compatibility with the internal assumptions made by AbstractAlgebra, the Euclidean remainder function should provide unique representatives for the residue classes; the mod function should satisfy

  1. mod(a_1, b) = mod(a_2, b) if and only if $b$ divides $a_1 - a_2$, and
  2. mod(0, b) = 0.
source
Base.divMethod
div(f::T, g::T) where T <: RingElem

Return the Euclidean quotient of $f$ by $g$. A DivideError should be thrown if $g$ is zero.

source
AbstractAlgebra.mulmodMethod
mulmod(f::T, g::T, m::T) where T <: RingElem

Return mod(f*g, m) but possibly computed more efficiently.

source
Base.powermodMethod
powermod(f::T, e::Int, m::T) where T <: RingElem

Return mod(f^e, m) but possibly computed more efficiently.

source
Base.invmodMethod
invmod(f::T, m::T) where T <: RingElem

Return an inverse of $f$ modulo $m$, meaning that isone(mod(invmod(f,m)*f,m)) returns true.

If such an inverse doesn't exist, a NotInvertibleError should be thrown.

source
AbstractAlgebra.dividesMethod
divides(f::T, g::T) where T <: RingElem

Return a pair, flag, q, where flag is set to true if $g$ divides $f$, in which case q is set to the quotient, or flag is set to false and q is set to zero(f).

source
AbstractAlgebra.removeMethod
remove(f::T, p::T) where T <: RingElem

Return a pair v, q where $p^v$ is the highest power of $p$ dividing $f$ and $q$ is the cofactor after $f$ is divided by this power.

See also valuation, which only returns the valuation.

source
Base.gcdMethod
gcd(a::T, b::T) where T <: RingElem

Return a greatest common divisor of $a$ and $b$, i.e., an element $g$ which is a common divisor of $a$ and $b$, and with the property that any other common divisor of $a$ and $b$ divides $g$.

Note

For best compatibility with the internal assumptions made by AbstractAlgebra, the return is expected to be unit-normalized in such a way that if the return is a unit, that unit should be one.

source
Base.gcdMethod
gcd(f::T, g::T, hs::T...) where T <: RingElem

Return a greatest common divisor of $f$, $g$ and the elements in hs.

source
Base.gcdMethod
gcd(fs::AbstractArray{<:T}) where T <: RingElem

Return a greatest common divisor of the elements in fs. Requires that fs is not empty.

source
Base.lcmMethod
lcm(f::T, g::T) where T <: RingElem

Return a least common multiple of $f$ and $g$, i.e., an element $d$ which is a common multiple of $f$ and $g$, and with the property that any other common multiple of $f$ and $g$ is a multiple of $d$.

source
Base.lcmMethod
lcm(f::T, g::T, hs::T...) where T <: RingElem

Return a least common multiple of $f$, $g$ and the elements in hs.

source
Base.lcmMethod
lcm(fs::AbstractArray{<:T}) where T <: RingElem

Return a least common multiple of the elements in fs. Requires that fs is not empty.

source
Base.gcdxMethod
gcdx(f::T, g::T) where T <: RingElem

Return a triple d, s, t such that $d = gcd(f, g)$ and $d = sf + tg$, with $s$ loosely reduced modulo $g/d$ and $t$ loosely reduced modulo $f/d$.

source
AbstractAlgebra.gcdinvMethod
gcdinv(f::T, g::T) where T <: RingElem

Return a tuple d, s such that $d = gcd(f, g)$ and $s = (f/d)^{-1} \pmod{g/d}$. Note that $d = 1$ iff $f$ is invertible modulo $g$, in which case $s = f^{-1} \pmod{g}$.

source
AbstractAlgebra.crtMethod
crt(r1::T, m1::T, r2::T, m2::T; check::Bool=true) where T <: RingElement

Return an element congruent to $r_1$ modulo $m_1$ and $r_2$ modulo $m_2$. If check = true and no solution exists, an error is thrown.

If T is a fixed precision integer type (like Int), the result will be correct if abs(ri) <= abs(mi) and abs(m1 * m2) < typemax(T).

source
AbstractAlgebra.crtMethod
crt(r::Vector{T}, m::Vector{T}; check::Bool=true) where T <: RingElement

Return an element congruent to $r_i$ modulo $m_i$ for each $i$.

source
AbstractAlgebra.crt_with_lcmMethod
crt_with_lcm(r1::T, m1::T, r2::T, m2::T; check::Bool=true) where T <: RingElement

Return a tuple consisting of an element congruent to $r_1$ modulo $m_1$ and $r_2$ modulo $m_2$ and the least common multiple of $m_1$ and $m_2$. If check = true and no solution exists, an error is thrown.

source
AbstractAlgebra.crt_with_lcmMethod
crt_with_lcm(r::Vector{T}, m::Vector{T}; check::Bool=true) where T <: RingElement

Return a tuple consisting of an element congruent to $r_i$ modulo $m_i$ for each $i$ and the least common multiple of the $m_i$.

source
AbstractAlgebra.coprime_baseFunction
coprime_base(S::Vector{RingElement}) -> Vector{RingElement}

Returns a coprime base for $S$, i.e. the resulting array contains pairwise coprime objects that multiplicatively generate the same set as the input array.

source
AbstractAlgebra.coprime_base_push!Function
coprime_base_push!(S::Vector{RingElem}, a::RingElem) -> Vector{RingElem}

Given an array $S$ of coprime elements, insert a new element, that is, find a coprime base for push(S, a).

source
diff --git a/dev/extending_abstractalgebra/index.html b/dev/extending_abstractalgebra/index.html index 8a25d4615..9e6451348 100644 --- a/dev/extending_abstractalgebra/index.html +++ b/dev/extending_abstractalgebra/index.html @@ -9,12 +9,12 @@ (Laurent series ring in x over integers, x + O(x^4)) julia> parent(x) == S -truesource
AbstractAlgebra.elem_typeFunction
elem_type(parent)
+true
source
AbstractAlgebra.elem_typeFunction
elem_type(parent)
 elem_type(parent_type)

Given a parent object (or its type), return the type of its elements.

Examples

julia> S, x = power_series_ring(QQ, 2, :x)
 (Univariate power series ring over rationals, x + O(x^3))
 
 julia> elem_type(S) == typeof(x)
-true
source
AbstractAlgebra.parent_typeFunction
parent_type(element)
+true
source
AbstractAlgebra.parent_typeFunction
parent_type(element)
 parent_type(element_type)

Given an element (or its type), return the type of its parent object.

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
@@ -25,7 +25,7 @@
 julia> a = rand(S, 0:1, 0:1);
 
 julia> parent_type(a) == typeof(S)
-true
source

Acquiring associated elements and parents

Further, if one has a base ring, like polynomials over the integers $\mathbb{Z}[x]$, then one should implement

AbstractAlgebra.base_ringFunction
base_ring(a)

Return base ring $R$ of given element or parent $a$.

Examples

julia> S, x = polynomial_ring(QQ, :x)
+true
source

Acquiring associated elements and parents

Further, if one has a base ring, like polynomials over the integers $\mathbb{Z}[x]$, then one should implement

AbstractAlgebra.base_ringFunction
base_ring(a)

Return base ring $R$ of given element or parent $a$.

Examples

julia> S, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> base_ring(S) == QQ
@@ -35,7 +35,7 @@
 Finite field F_7
 
 julia> base_ring(R)
-Union{}
source
AbstractAlgebra.base_ring_typeFunction
base_ring_type(a)

Return the type of the base ring of the given element, element type, parent or parent type $a$.

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+Union{}
source
AbstractAlgebra.base_ring_typeFunction
base_ring_type(a)

Return the type of the base ring of the given element, element type, parent or parent type $a$.

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> base_ring_type(R) == typeof(base_ring(R))
@@ -48,7 +48,7 @@
 true
 
 julia> base_ring_type(typeof(zero(R))) == typeof(base_ring(zero(R)))
-true
source

Special elements

For rings, one has to extend the following methods:

Base.oneFunction
one(a)

Return the multiplicative identity in the algebraic structure of $a$, which can be either an element or parent.

Examples

julia> S = matrix_space(ZZ, 2, 2)
+true
source

Special elements

For rings, one has to extend the following methods:

Base.oneFunction
one(a)

Return the multiplicative identity in the algebraic structure of $a$, which can be either an element or parent.

Examples

julia> S = matrix_space(ZZ, 2, 2)
 Matrix space of 2 rows and 2 columns
   over integers
 
@@ -66,7 +66,7 @@
 Finite field F_5
 
 julia> one(G)
-1
source
Base.zeroFunction
zero(a)

Return the additive identity in the algebraic structure of $a$, which can be either an element or parent.

Examples

julia> S = matrix_ring(QQ, 2)
+1
source
Base.zeroFunction
zero(a)

Return the additive identity in the algebraic structure of $a$, which can be either an element or parent.

Examples

julia> S = matrix_ring(QQ, 2)
 Matrix ring of degree 2
   over rationals
 
@@ -78,7 +78,7 @@
 (Univariate polynomial ring in x over integers, x)
 
 julia> zero(x^3 + 2)
-0
source

Groups should only extend at least one of these. The one that is required depends on if the group is additive (commutative) or multiplicative.

Basic manipulation

If one would like to implement a ring, these are the basic manipulation methods that all rings should extend:

Base.isoneFunction
isone(a)

Return true if $a$ is the multiplicative identity, else return false.

Examples

julia> S = matrix_space(ZZ, 2, 2); T = matrix_space(ZZ, 2, 3); U = matrix_space(ZZ, 3, 2);
+0
source

Groups should only extend at least one of these. The one that is required depends on if the group is additive (commutative) or multiplicative.

Basic manipulation

If one would like to implement a ring, these are the basic manipulation methods that all rings should extend:

Base.isoneFunction
isone(a)

Return true if $a$ is the multiplicative identity, else return false.

Examples

julia> S = matrix_space(ZZ, 2, 2); T = matrix_space(ZZ, 2, 3); U = matrix_space(ZZ, 3, 2);
 
 julia> isone(S([1 0; 0 1]))
 true
@@ -93,18 +93,18 @@
 (Puiseux series field in x over rationals, x + O(x^11))
 
 julia> isone(x), isone(T(1))
-(false, true)
source
Base.iszeroFunction
iszero(a)

Return true if $a$ is the additative identity, else return false.

Examples

julia> T, x = puiseux_series_field(QQ, 10, :x)
+(false, true)
source
Base.iszeroFunction
iszero(a)

Return true if $a$ is the additative identity, else return false.

Examples

julia> T, x = puiseux_series_field(QQ, 10, :x)
 (Puiseux series field in x over rationals, x + O(x^11))
 
 julia> a = T(0)
 O(x^10)
 
 julia> iszero(a)
-true
source
AbstractAlgebra.is_unitFunction
is_unit(a::T) where {T <: NCRingElem}

Return true if $a$ is invertible, else return false.

Examples

julia> S, x = polynomial_ring(QQ, :x)
+true
source
AbstractAlgebra.is_unitFunction
is_unit(a::T) where {T <: NCRingElem}

Return true if $a$ is invertible, else return false.

Examples

julia> S, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> is_unit(x), is_unit(S(1)), is_unit(S(4))
 (false, true, true)
 
 julia> is_unit(ZZ(-1)), is_unit(ZZ(4))
-(true, false)
source

With the same logic as earlier, groups only need to extend one of the methods isone and iszero.

+(true, false)source

With the same logic as earlier, groups only need to extend one of the methods isone and iszero.

diff --git a/dev/field/index.html b/dev/field/index.html index 3cd23709b..703e06123 100644 --- a/dev/field/index.html +++ b/dev/field/index.html @@ -1,4 +1,4 @@ Field functionality · AbstractAlgebra.jl

Field functionality

Abstract types for rings

All field types in AbstractAlgebra belong to the Field abstract type and field elements belong to the FieldElem abstract type.

As Julia types cannot belong to our FieldElem type hierarchy, we also provide the union type FieldElement which includes FieldElem in union with the Julia types Rational and AbstractFloat.

Note that

Field <: Ring
 FieldElem <: RingElem
-FieldElement <: RingElement

Of course all Ring functionality is available for AbstractAlgebra fields and their elements.

Functions for types and parents of fields

characteristic(R::MyParent)

Return the characteristic of the field. If the characteristic is not known, an exception is raised.

Basic functions

is_unit(f::MyElem)

Return true if the given element is invertible, i.e. nonzero in the field.

+FieldElement <: RingElement

Of course all Ring functionality is available for AbstractAlgebra fields and their elements.

Functions for types and parents of fields

characteristic(R::MyParent)

Return the characteristic of the field. If the characteristic is not known, an exception is raised.

Basic functions

is_unit(f::MyElem)

Return true if the given element is invertible, i.e. nonzero in the field.

diff --git a/dev/field_interface/index.html b/dev/field_interface/index.html index b4e268e97..612fc85d4 100644 --- a/dev/field_interface/index.html +++ b/dev/field_interface/index.html @@ -1,2 +1,2 @@ -Field Interface · AbstractAlgebra.jl

Field Interface

AbstractAlgebra.jl generic code makes use of a standardised set of functions which it expects to be implemented for all fields. Here we document this interface. All libraries which want to make use of the generic capabilities of AbstractAlgebra.jl must supply all of the required functionality for their fields.

Types

Most fields must supply two types:

  • a type for the parent object (representing the field itself)
  • a type for elements of that field

For example, the generic fraction field type in AbstractAlgebra.jl provides two types in generic/GenericTypes.jl:

  • Generic.FracField{T} for the parent objects
  • Generic.FracFieldElem{T} for the actual fractions

The parent type must belong to Field and the element type must belong to FieldElem. Of course, the types may belong to these abstract types transitively.

For parameterised fields, we advise that the types of both the parent objects and element objects to be parameterised by the types of the elements of the base ring.

There can be variations on this theme: e.g. in some areas of mathematics there is a notion of a coefficient domain, in which case it may make sense to parameterise all types by the type of elements of this coefficient domain. But note that this may have implications for the ad hoc operators one might like to explicitly implement.

FieldElement type union

Because of its lack of multiple inheritance, Julia does not allow Julia Base types to belong to FieldElem. To allow us to work equally with AbstractAlgebra and Julia types that represent elements of fields we define a union type FieldElement in src/julia/JuliaTypes.

So far, in addition to FieldElem the union type FieldElement includes the Julia types Rational and AbstractFloat.

Most of the generic code in AbstractAlgebra makes use of the union type FieldElement instead of FieldElem so that the generic functions also accept the Julia Base field types.

Note

One must be careful when defining ad hoc binary operations for field element types. It is often necessary to define separate versions of the functions for FieldElem then for each of the Julia types separately in order to avoid ambiguity warnings.

Note that even though FieldElement is a union type we still have the following inclusion

FieldElement <: RingElement

Parent object caches

In many cases, it is desirable to have only one object in the system to represent each field. This means that if the same field is constructed twice, elements of the two fields will be compatible as far as arithmetic is concerned.

In order to facilitate this, global caches of fields are stored in AbstractAlgebra.jl, usually implemented using dictionaries. For example, the Generic.FracField parent objects are looked up in a dictionary FracDict to see if they have been previously defined.

Whether these global caches are provided or not, depends on both mathematical and algorithmic considerations. E.g. in the case of number fields, it isn't desirable to identify all number fields with the same defining polynomial, as they may be considered with distinct embeddings into one another. In other cases, identifying whether two fields are the same may be prohibitively expensive. Generally, it may only make sense algorithmically to identify two fields if they were constructed from identical data.

If a global cache is provided, it must be optionally possible to construct the parent objects without caching. This is done by passing a boolean value cached to the inner constructor of the parent object. See generic/GenericTypes.jl for examples of how to construct and handle such caches.

Required functions for all fields

In the following, we list all the functions that are required to be provided for fields in AbstractAlgebra.jl or by external libraries wanting to use AbstractAlgebra.jl.

We give this interface for fictitious types MyParent for the type of the field parent object R and MyElem for the type of the elements of the field.

Note

Generic functions in AbstractAlgebra.jl may not rely on the existence of functions that are not documented here. If they do, those functions will only be available for fields that implement that additional functionality, and should be documented as such.

In the first place, all fields are rings and therefore any field type must implement all of the Ring interface. The functionality below is in addition to this basic functionality.

Data type and parent object methods

characteristic(R::MyParent)

Return the characteristic of the field. If the characteristic is not known, an exception is raised.

Basic manipulation of rings and elements

is_unit(f::MyElem)

Return true if the given element is invertible, i.e. nonzero in the field.

+Field Interface · AbstractAlgebra.jl

Field Interface

AbstractAlgebra.jl generic code makes use of a standardised set of functions which it expects to be implemented for all fields. Here we document this interface. All libraries which want to make use of the generic capabilities of AbstractAlgebra.jl must supply all of the required functionality for their fields.

Types

Most fields must supply two types:

  • a type for the parent object (representing the field itself)
  • a type for elements of that field

For example, the generic fraction field type in AbstractAlgebra.jl provides two types in generic/GenericTypes.jl:

  • Generic.FracField{T} for the parent objects
  • Generic.FracFieldElem{T} for the actual fractions

The parent type must belong to Field and the element type must belong to FieldElem. Of course, the types may belong to these abstract types transitively.

For parameterised fields, we advise that the types of both the parent objects and element objects to be parameterised by the types of the elements of the base ring.

There can be variations on this theme: e.g. in some areas of mathematics there is a notion of a coefficient domain, in which case it may make sense to parameterise all types by the type of elements of this coefficient domain. But note that this may have implications for the ad hoc operators one might like to explicitly implement.

FieldElement type union

Because of its lack of multiple inheritance, Julia does not allow Julia Base types to belong to FieldElem. To allow us to work equally with AbstractAlgebra and Julia types that represent elements of fields we define a union type FieldElement in src/julia/JuliaTypes.

So far, in addition to FieldElem the union type FieldElement includes the Julia types Rational and AbstractFloat.

Most of the generic code in AbstractAlgebra makes use of the union type FieldElement instead of FieldElem so that the generic functions also accept the Julia Base field types.

Note

One must be careful when defining ad hoc binary operations for field element types. It is often necessary to define separate versions of the functions for FieldElem then for each of the Julia types separately in order to avoid ambiguity warnings.

Note that even though FieldElement is a union type we still have the following inclusion

FieldElement <: RingElement

Parent object caches

In many cases, it is desirable to have only one object in the system to represent each field. This means that if the same field is constructed twice, elements of the two fields will be compatible as far as arithmetic is concerned.

In order to facilitate this, global caches of fields are stored in AbstractAlgebra.jl, usually implemented using dictionaries. For example, the Generic.FracField parent objects are looked up in a dictionary FracDict to see if they have been previously defined.

Whether these global caches are provided or not, depends on both mathematical and algorithmic considerations. E.g. in the case of number fields, it isn't desirable to identify all number fields with the same defining polynomial, as they may be considered with distinct embeddings into one another. In other cases, identifying whether two fields are the same may be prohibitively expensive. Generally, it may only make sense algorithmically to identify two fields if they were constructed from identical data.

If a global cache is provided, it must be optionally possible to construct the parent objects without caching. This is done by passing a boolean value cached to the inner constructor of the parent object. See generic/GenericTypes.jl for examples of how to construct and handle such caches.

Required functions for all fields

In the following, we list all the functions that are required to be provided for fields in AbstractAlgebra.jl or by external libraries wanting to use AbstractAlgebra.jl.

We give this interface for fictitious types MyParent for the type of the field parent object R and MyElem for the type of the elements of the field.

Note

Generic functions in AbstractAlgebra.jl may not rely on the existence of functions that are not documented here. If they do, those functions will only be available for fields that implement that additional functionality, and should be documented as such.

In the first place, all fields are rings and therefore any field type must implement all of the Ring interface. The functionality below is in addition to this basic functionality.

Data type and parent object methods

characteristic(R::MyParent)

Return the characteristic of the field. If the characteristic is not known, an exception is raised.

Basic manipulation of rings and elements

is_unit(f::MyElem)

Return true if the given element is invertible, i.e. nonzero in the field.

diff --git a/dev/field_introduction/index.html b/dev/field_introduction/index.html index a056b8d3b..8f1f38718 100644 --- a/dev/field_introduction/index.html +++ b/dev/field_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

A number of basic fields are provided, such as the rationals, finite fields, the real field, etc.

Various generic field constructions can then be made recursively on top of these basic fields. For example, fraction fields, residue fields, function fields, etc.

From the point of view of the system, all fields are rings and whether an object is a ring/field or an element thereof can be determined at the type level. There are abstract types for all field and for all field element types.

The field hierarchy can be extended by implementing new fields to follow one or more field interfaces, including the interface that all fields must follow. Once an interface is satisfied, all the corresponding generic functionality will work over the new field.

Implementations of new fields can either be generic or can be specialised implementations provided by, for example, a C library.

+Introduction · AbstractAlgebra.jl

Introduction

A number of basic fields are provided, such as the rationals, finite fields, the real field, etc.

Various generic field constructions can then be made recursively on top of these basic fields. For example, fraction fields, residue fields, function fields, etc.

From the point of view of the system, all fields are rings and whether an object is a ring/field or an element thereof can be determined at the type level. There are abstract types for all field and for all field element types.

The field hierarchy can be extended by implementing new fields to follow one or more field interfaces, including the interface that all fields must follow. Once an interface is satisfied, all the corresponding generic functionality will work over the new field.

Implementations of new fields can either be generic or can be specialised implementations provided by, for example, a C library.

diff --git a/dev/finfield/index.html b/dev/finfield/index.html index f7bf2f617..efe5ecde6 100644 --- a/dev/finfield/index.html +++ b/dev/finfield/index.html @@ -1,5 +1,5 @@ -Finite fields · AbstractAlgebra.jl

Finite fields

AbstractAlgebra.jl provides a module, implemented in src/julia/GF.jl for finite fields. The module is a naive implementation that supports only fields of degree $1$ (prime fields). They are modelled as $\mathbb{Z}/p\mathbb{Z}$ for $p$ a prime.

Types and parent objects

Finite fields have type GFField{T} where T is either Int or BigInt.

Elements of such a finite field have type GFElem{T}.

Finite field constructors

In order to construct finite fields in AbstractAlgebra.jl, one must first construct the field itself. This is accomplished with the following constructors.

AbstractAlgebra.GFMethod
GF(p::T; check::Bool=true) where T <: Integer

Return the finite field $\mathbb{F}_p$, where $p$ is a prime. By default, the integer $p$ is checked with a probabilistic algorithm for primality. When check == false, no check is made, but the behaviour of the resulting object is undefined if $p$ is composite.

source

Here are some examples of creating a finite field and making use of the resulting parent object to coerce various elements into the field.

Examples

julia> F = GF(13)
+Finite fields · AbstractAlgebra.jl

Finite fields

AbstractAlgebra.jl provides a module, implemented in src/julia/GF.jl for finite fields. The module is a naive implementation that supports only fields of degree $1$ (prime fields). They are modelled as $\mathbb{Z}/p\mathbb{Z}$ for $p$ a prime.

Types and parent objects

Finite fields have type GFField{T} where T is either Int or BigInt.

Elements of such a finite field have type GFElem{T}.

Finite field constructors

In order to construct finite fields in AbstractAlgebra.jl, one must first construct the field itself. This is accomplished with the following constructors.

AbstractAlgebra.GFMethod
GF(p::T; check::Bool=true) where T <: Integer

Return the finite field $\mathbb{F}_p$, where $p$ is a prime. By default, the integer $p$ is checked with a probabilistic algorithm for primality. When check == false, no check is made, but the behaviour of the resulting object is undefined if $p$ is composite.

source

Here are some examples of creating a finite field and making use of the resulting parent object to coerce various elements into the field.

Examples

julia> F = GF(13)
 Finite field F_13
 
 julia> g = F(3)
@@ -41,7 +41,7 @@
 
 julia> m = inv(k)
 1
-

Basic manipulation of fields and elements

AbstractAlgebra.dataMethod
data(R::GFElem)

Return the internal data used to represent the finite field element. This coincides with lift except where the internal data ids a machine integer.

source
AbstractAlgebra.liftMethod
lift(R::GFElem)

Lift the finite field element to the integers. The result will be a multiprecision integer regardless of how the field element is represented internally.

source
AbstractAlgebra.genMethod
gen(R::GFField{T}) where T <: Integer

Return a generator of the field. Currently this returns 1.

source

Examples

julia> F = GF(13)
+

Basic manipulation of fields and elements

AbstractAlgebra.dataMethod
data(R::GFElem)

Return the internal data used to represent the finite field element. This coincides with lift except where the internal data ids a machine integer.

source
AbstractAlgebra.liftMethod
lift(R::GFElem)

Lift the finite field element to the integers. The result will be a multiprecision integer regardless of how the field element is represented internally.

source
AbstractAlgebra.genMethod
gen(R::GFField{T}) where T <: Integer

Return a generator of the field. Currently this returns 1.

source

Examples

julia> F = GF(13)
 Finite field F_13
 
 julia> d = degree(F)
@@ -52,4 +52,4 @@
 
 julia> g = gen(F)
 1
-
+
diff --git a/dev/fraction/index.html b/dev/fraction/index.html index 0ae34e193..767a68777 100644 --- a/dev/fraction/index.html +++ b/dev/fraction/index.html @@ -113,7 +113,7 @@ x^2 + x + 1 julia> d = denominator(g) -x^3 + 3*x + 1

Greatest common divisor

Base.gcdMethod
gcd(a::FracElem{T}, b::FracElem{T}) where {T <: RingElem}

Return a greatest common divisor of $a$ and $b$ if one exists. N.B: we define the GCD of $a/b$ and $c/d$ to be gcd$(ad, bc)/bd$, reduced to lowest terms. This requires the existence of a greatest common divisor function for the base ring.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
+x^3 + 3*x + 1

Greatest common divisor

Base.gcdMethod
gcd(a::FracElem{T}, b::FracElem{T}) where {T <: RingElem}

Return a greatest common divisor of $a$ and $b$ if one exists. N.B: we define the GCD of $a/b$ and $c/d$ to be gcd$(ad, bc)/bd$, reduced to lowest terms. This requires the existence of a greatest common divisor function for the base ring.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> f = (x + 1)//(x^3 + 3x + 1)
@@ -124,7 +124,7 @@
 
 julia> h = gcd(f, g)
 (x + 1)//(x^5 + x^4 + 4*x^3 + 4*x^2 + 4*x + 1)
-

Square root

AbstractAlgebra.is_squareMethod
is_square(a::FracElem{T}) where T <: RingElem

Return true if $a$ is a square.

source
Base.sqrtMethod
Base.sqrt(a::FracElem{T}; check::Bool=true) where T <: RingElem

Return the square root of $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
+

Square root

AbstractAlgebra.is_squareMethod
is_square(a::FracElem{T}) where T <: RingElem

Return true if $a$ is a square.

source
Base.sqrtMethod
Base.sqrt(a::FracElem{T}; check::Bool=true) where T <: RingElem

Return the square root of $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> S = fraction_field(R)
@@ -138,7 +138,7 @@
 (21//4*x^6 - 15*x^5 + 27//14*x^4 + 9//20*x^3 + 3//7*x + 9//10)//(x + 3)
 
 julia> is_square(a^2)
-true

Remove and valuation

When working over a Euclidean domain, it is convenient to extend valuations to the fraction field. To facilitate this, we define the following functions.

AbstractAlgebra.removeMethod
remove(z::FracElem{T}, p::T) where {T <: RingElem}

Return the tuple $n, x$ such that $z = p^nx$ where $x$ has valuation $0$ at $p$.

source
AbstractAlgebra.valuationMethod
valuation(z::FracElem{T}, p::T) where {T <: RingElem}

Return the valuation of $z$ at $p$.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+true

Remove and valuation

When working over a Euclidean domain, it is convenient to extend valuations to the fraction field. To facilitate this, we define the following functions.

AbstractAlgebra.removeMethod
remove(z::FracElem{T}, p::T) where {T <: RingElem}

Return the tuple $n, x$ such that $z = p^nx$ where $x$ has valuation $0$ at $p$.

source
AbstractAlgebra.valuationMethod
valuation(z::FracElem{T}, p::T) where {T <: RingElem}

Return the valuation of $z$ at $p$.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> f = (x + 1)//(x^3 + 3x + 1)
@@ -187,4 +187,4 @@
 julia> collect(f)
 2-element Vector{Tuple{BigInt, Int64}}:
  (10, 10)
- (42, -8)
+ (42, -8) diff --git a/dev/fraction_interface/index.html b/dev/fraction_interface/index.html index 48dcf06fd..e12184ac3 100644 --- a/dev/fraction_interface/index.html +++ b/dev/fraction_interface/index.html @@ -1,2 +1,2 @@ -Fraction Field Interface · AbstractAlgebra.jl

Fraction Field Interface

Fraction fields are supported in AbstractAlgebra.jl, at least for gcd domains. In addition to the standard Ring interface, some additional functions are required to be present for fraction fields.

Types and parents

AbstractAlgebra provides two abstract types for fraction fields and their elements:

  • FracField{T} is the abstract type for fraction field parent types
  • FracElem{T} is the abstract type for types of fractions

We have that FracField{T} <: Field and FracElem{T} <: FieldElem.

Note that both abstract types are parameterised. The type T should usually be the type of elements of the base ring of the fraction field.

Fraction fields should be made unique on the system by caching parent objects (unless an optional cache parameter is set to false). Fraction fields should at least be distinguished based on their base ring.

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Required functionality for fraction fields

In addition to the required functionality for the Field interface the Fraction Field interface has the following required functions.

We suppose that R is a fictitious base ring, and that S is the fraction field with parent object S of type MyFracField{T}. We also assume the fractions in the field have type MyFrac{T}, where T is the type of elements of the base ring.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElem.

Constructors

The following constructors create fractions. Note that these constructors don't require construction of the parent object first. This is easier to achieve if the fraction element type doesn't contain a reference to the parent object, but merely contains a reference to the base ring. The parent object can then be constructed on demand.

//(x::T, y::T) where T <: RingElem

Return the fraction $x/y$.

//(x::T, y::FracElem{T}) where T <: RingElem

Return $x/y$ where $x$ is in the base ring of $y$.

//(x::FracElem{T}, y::T) where T <: RingElem

Return $x/y$ where $y$ is in the base ring of $x$.

Basic manipulation of fields and elements

numerator(d::MyFrac{T}) where T <: RingElem

Given a fraction $d = a/b$ return $a$, where $a/b$ is in lowest terms with respect to the canonical_unit and gcd functions on the base ring.

denominator(d::MyFrac{T}) where T <: RingElem

Given a fraction $d = a/b$ return $b$, where $a/b$ is in lowest terms with respect to the canonical_unit and gcd functions on the base ring.

+Fraction Field Interface · AbstractAlgebra.jl

Fraction Field Interface

Fraction fields are supported in AbstractAlgebra.jl, at least for gcd domains. In addition to the standard Ring interface, some additional functions are required to be present for fraction fields.

Types and parents

AbstractAlgebra provides two abstract types for fraction fields and their elements:

  • FracField{T} is the abstract type for fraction field parent types
  • FracElem{T} is the abstract type for types of fractions

We have that FracField{T} <: Field and FracElem{T} <: FieldElem.

Note that both abstract types are parameterised. The type T should usually be the type of elements of the base ring of the fraction field.

Fraction fields should be made unique on the system by caching parent objects (unless an optional cache parameter is set to false). Fraction fields should at least be distinguished based on their base ring.

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Required functionality for fraction fields

In addition to the required functionality for the Field interface the Fraction Field interface has the following required functions.

We suppose that R is a fictitious base ring, and that S is the fraction field with parent object S of type MyFracField{T}. We also assume the fractions in the field have type MyFrac{T}, where T is the type of elements of the base ring.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElem.

Constructors

The following constructors create fractions. Note that these constructors don't require construction of the parent object first. This is easier to achieve if the fraction element type doesn't contain a reference to the parent object, but merely contains a reference to the base ring. The parent object can then be constructed on demand.

//(x::T, y::T) where T <: RingElem

Return the fraction $x/y$.

//(x::T, y::FracElem{T}) where T <: RingElem

Return $x/y$ where $x$ is in the base ring of $y$.

//(x::FracElem{T}, y::T) where T <: RingElem

Return $x/y$ where $y$ is in the base ring of $x$.

Basic manipulation of fields and elements

numerator(d::MyFrac{T}) where T <: RingElem

Given a fraction $d = a/b$ return $a$, where $a/b$ is in lowest terms with respect to the canonical_unit and gcd functions on the base ring.

denominator(d::MyFrac{T}) where T <: RingElem

Given a fraction $d = a/b$ return $b$, where $a/b$ is in lowest terms with respect to the canonical_unit and gcd functions on the base ring.

diff --git a/dev/free_associative_algebra/index.html b/dev/free_associative_algebra/index.html index 5195c2bab..a424a09b9 100644 --- a/dev/free_associative_algebra/index.html +++ b/dev/free_associative_algebra/index.html @@ -37,7 +37,7 @@ leading_term(a::FreeAssociativeAlgebraElem) leading_exponent_word(a::FreeAssociativeAlgebraElem)

For types that allow constant time access to coefficients, the following are also available, allowing access to the given coefficient, monomial or term. Terms are numbered from the most significant first.

coeff(f::FreeAssociativeAlgebraElem, n::Int)
 monomial(f::FreeAssociativeAlgebraElem, n::Int)
-term(f::FreeAssociativeAlgebraElem, n::Int)

In contrast with the interface for multivariable polynomials, the function exponent_vector is replaced by exponent_word

AbstractAlgebra.Generic.exponent_wordMethod
exponent_word(a::FreeAssociativeAlgebraElem{T}, i::Int) where T <: RingElement

Return a vector of variable indices corresponding to the monomial of the $i$-th term of $a$. Term numbering begins at $1$, and the variable indices are given in the order of the variables for the ring.

source

Examples

julia> R, (x, y, z) = free_associative_algebra(ZZ, [:x, :y, :z])
+term(f::FreeAssociativeAlgebraElem, n::Int)

In contrast with the interface for multivariable polynomials, the function exponent_vector is replaced by exponent_word

AbstractAlgebra.Generic.exponent_wordMethod
exponent_word(a::FreeAssociativeAlgebraElem{T}, i::Int) where T <: RingElement

Return a vector of variable indices corresponding to the monomial of the $i$-th term of $a$. Term numbering begins at $1$, and the variable indices are given in the order of the variables for the ring.

source

Examples

julia> R, (x, y, z) = free_associative_algebra(ZZ, [:x, :y, :z])
 (Free associative algebra on 3 indeterminates over integers, AbstractAlgebra.Generic.FreeAssociativeAlgebraElem{BigInt}[x, y, z])
 
 julia> map(total_degree, (R(0), R(1), -x^2*y^2*z^2*x + z*y))
@@ -83,9 +83,9 @@
 true
 
 julia> m1*m2 - m2*m1 == f(m1, m2)
-true
source

Iterators

The following iterators are provided for elements of a free associative algebra, with exponent_words providing the analogous functionality that exponent_vectors provides for multivariate polynomials.

terms(p::FreeAssociativeAlgebraElem)
+true
source

Iterators

The following iterators are provided for elements of a free associative algebra, with exponent_words providing the analogous functionality that exponent_vectors provides for multivariate polynomials.

terms(p::FreeAssociativeAlgebraElem)
 coefficients(p::FreeAssociativeAlgebraElem)
-monomials(p::FreeAssociativeAlgebraElem)
AbstractAlgebra.exponent_wordsMethod
exponent_words(a::FreeAssociativeAlgebraElem{T}) where T <: RingElement

Return an iterator for the exponent words of the given polynomial. To retrieve an array of the exponent words, use collect(exponent_words(a)).

source

Examples

julia> R, (a, b, c) = free_associative_algebra(ZZ, [:a, :b, :c])
+monomials(p::FreeAssociativeAlgebraElem)
AbstractAlgebra.exponent_wordsMethod
exponent_words(a::FreeAssociativeAlgebraElem{T}) where T <: RingElement

Return an iterator for the exponent words of the given polynomial. To retrieve an array of the exponent words, use collect(exponent_words(a)).

source

Examples

julia> R, (a, b, c) = free_associative_algebra(ZZ, [:a, :b, :c])
 (Free associative algebra on 3 indeterminates over integers, AbstractAlgebra.Generic.FreeAssociativeAlgebraElem{BigInt}[a, b, c])
 
 julia> collect(terms(3*b*a*c - b + c + 2))
@@ -114,7 +114,7 @@
  [2, 1, 3]
  [2]
  [3]
- []

Groebner bases

The function groebner_basis provides the computation of a Groebner basis of an ideal, given a set of generators of that ideal. Since such a Groebner basis is not necessarily finite, one can additionally pass a reduction_bound to the function, to only compute a partial Groebner basis.

AbstractAlgebra.Generic.groebner_basisMethod
groebner_basis(g::Vector{FreeAssociativeAlgebraElem{T}}, reduction_bound::Int = typemax(Int), remove_redundancies::Bool = false)

Compute a Groebner basis for the ideal generated by g. Stop when reduction_bound many non-zero entries have been added to the Groebner basis. If the computation stops due to the bound being exceeded, the result is in general not an actual Groebner basis, just a subset of one. However, whenever the normal form with respect to this incomplete Groebner basis is 0, it will also be 0 with respect to the full Groebner basis.

If remove_redundancies is set to true, some redundant obstructions will be removed during the computation, which might save time, however in practice it seems to inflate the running time regularly.

source
AbstractAlgebra.Generic.normal_formMethod
normal_form(f::FreeAssociativeAlgebraElem{T}, g::Vector{FreeAssociativeAlgebraElem{T}}, aut::AhoCorasickAutomaton)

Assuming g is a Groebner basis and aut an Aho-Corasick automaton for the elements of g, compute the normal form of f with respect to g

source
AbstractAlgebra.Generic.interreduce!Method
interreduce!(g::Vector{FreeAssociativeAlgebraElem{T}}) where T

Interreduce a given Groebner basis with itself, i.e. compute the normal form of each element of g with respect to the rest of the elements and discard elements with normal form $0$ and duplicates.

source

The implementation uses a non-commutative version of the Buchberger algorithm as described in

Xingqiang Xiu, Non-commutative Gröbner Bases and Applications, PhD thesis, 2012.

Examples

julia> R = @free_associative_algebra(GF(2), [:x, :y, :u, :v, :t, :s])
+ []

Groebner bases

The function groebner_basis provides the computation of a Groebner basis of an ideal, given a set of generators of that ideal. Since such a Groebner basis is not necessarily finite, one can additionally pass a reduction_bound to the function, to only compute a partial Groebner basis.

AbstractAlgebra.Generic.groebner_basisMethod
groebner_basis(g::Vector{FreeAssociativeAlgebraElem{T}}, reduction_bound::Int = typemax(Int), remove_redundancies::Bool = false)

Compute a Groebner basis for the ideal generated by g. Stop when reduction_bound many non-zero entries have been added to the Groebner basis. If the computation stops due to the bound being exceeded, the result is in general not an actual Groebner basis, just a subset of one. However, whenever the normal form with respect to this incomplete Groebner basis is 0, it will also be 0 with respect to the full Groebner basis.

If remove_redundancies is set to true, some redundant obstructions will be removed during the computation, which might save time, however in practice it seems to inflate the running time regularly.

source
AbstractAlgebra.Generic.normal_formMethod
normal_form(f::FreeAssociativeAlgebraElem{T}, g::Vector{FreeAssociativeAlgebraElem{T}}, aut::AhoCorasickAutomaton)

Assuming g is a Groebner basis and aut an Aho-Corasick automaton for the elements of g, compute the normal form of f with respect to g

source
AbstractAlgebra.Generic.interreduce!Method
interreduce!(g::Vector{FreeAssociativeAlgebraElem{T}}) where T

Interreduce a given Groebner basis with itself, i.e. compute the normal form of each element of g with respect to the rest of the elements and discard elements with normal form $0$ and duplicates.

source

The implementation uses a non-commutative version of the Buchberger algorithm as described in

Xingqiang Xiu, Non-commutative Gröbner Bases and Applications, PhD thesis, 2012.

Examples

julia> R = @free_associative_algebra(GF(2), [:x, :y, :u, :v, :t, :s])
 Free associative algebra on 6 indeterminates x, y, u, v, ..., s
   over finite field F_2
 
@@ -129,4 +129,4 @@
 julia> g = Generic.groebner_basis([u*(x*y)^3 + u*(x*y)^2 + u + v, (y*x)^3*t + (y*x)^2*t + t + s]);
 
 julia> normal_form(u*(x*y)^3*s*t + u*(x*y)^2*s*t +u*s*t + v*s*t, g)
-0
+0 diff --git a/dev/free_module/index.html b/dev/free_module/index.html index 224fe48b7..fc52a9916 100644 --- a/dev/free_module/index.html +++ b/dev/free_module/index.html @@ -1,5 +1,5 @@ -Free Modules and Vector Spaces · AbstractAlgebra.jl

Free Modules and Vector Spaces

AbstractAlgebra allows the construction of free modules of any rank over any Euclidean ring and the vector space of any dimension over a field. By default the system considers the free module of a given rank over a given ring or vector space of given dimension over a field to be unique.

Generic free module and vector space types

AbstractAlgebra provides generic types for free modules and vector spaces, via the type FreeModule{T} for free modules, where T is the type of the elements of the ring $R$ over which the module is built.

Elements of a free module have type FreeModuleElem{T}.

Vector spaces are simply free modules over a field.

The implementation of generic free modules can be found in src/generic/FreeModule.jl.

The free module of a given rank over a given ring is made unique on the system by caching them (unless an optional cache parameter is set to false).

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Abstract types

The type FreeModule{T} belongs to FPModule{T} and FreeModuleElem{T} to FPModuleElem{T}. Here the FP prefix stands for finitely presented.

Functionality for free modules

As well as implementing the entire module interface, free modules provide the following functionality.

Constructors

Construct the free module/vector space of given rank/dimension.

Examples

julia> M = free_module(ZZ, 3)
+Free Modules and Vector Spaces · AbstractAlgebra.jl

Free Modules and Vector Spaces

AbstractAlgebra allows the construction of free modules of any rank over any Euclidean ring and the vector space of any dimension over a field. By default the system considers the free module of a given rank over a given ring or vector space of given dimension over a field to be unique.

Generic free module and vector space types

AbstractAlgebra provides generic types for free modules and vector spaces, via the type FreeModule{T} for free modules, where T is the type of the elements of the ring $R$ over which the module is built.

Elements of a free module have type FreeModuleElem{T}.

Vector spaces are simply free modules over a field.

The implementation of generic free modules can be found in src/generic/FreeModule.jl.

The free module of a given rank over a given ring is made unique on the system by caching them (unless an optional cache parameter is set to false).

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Abstract types

The type FreeModule{T} belongs to FPModule{T} and FreeModuleElem{T} to FPModuleElem{T}. Here the FP prefix stands for finitely presented.

Functionality for free modules

As well as implementing the entire module interface, free modules provide the following functionality.

Constructors

Construct the free module/vector space of given rank/dimension.

Examples

julia> M = free_module(ZZ, 3)
 Free module of rank 3 over integers
 
 julia> V = vector_space(QQ, 2)
@@ -21,4 +21,4 @@
 julia> basis(V)
 2-element Vector{AbstractAlgebra.Generic.FreeModuleElem{Rational{BigInt}}}:
  (1//1, 0//1)
- (0//1, 1//1)
+ (0//1, 1//1)
diff --git a/dev/function_field/index.html b/dev/function_field/index.html index c7b890021..7203edcad 100644 --- a/dev/function_field/index.html +++ b/dev/function_field/index.html @@ -64,7 +64,7 @@ julia> d = denominator(g) x^3 + 3*x + 1 -

Note that numerator and denominator are returned as elements of a polynomial ring whose variable is printed the same way as that of the generator of the rational function field.

Rational function field functionality provided by AbstractAlgebra.jl

The following functionality is provided for rational function fields.

Greatest common divisor

Base.gcdMethod
gcd(a::RationalFunctionFieldElem{T, U}, b::RationalFunctionFieldElem{T, U}) where {T <: FieldElement, U <: Union{PolyRingElem, MPolyRingElem}}

Return a greatest common divisor of $a$ and $b$ if one exists. N.B: we define the GCD of $a/b$ and $c/d$ to be gcd$(ad, bc)/bd$, reduced to lowest terms.

source

Examples

julia> R, x = rational_function_field(QQ, :x)
+

Note that numerator and denominator are returned as elements of a polynomial ring whose variable is printed the same way as that of the generator of the rational function field.

Rational function field functionality provided by AbstractAlgebra.jl

The following functionality is provided for rational function fields.

Greatest common divisor

Base.gcdMethod
gcd(a::RationalFunctionFieldElem{T, U}, b::RationalFunctionFieldElem{T, U}) where {T <: FieldElement, U <: Union{PolyRingElem, MPolyRingElem}}

Return a greatest common divisor of $a$ and $b$ if one exists. N.B: we define the GCD of $a/b$ and $c/d$ to be gcd$(ad, bc)/bd$, reduced to lowest terms.

source

Examples

julia> R, x = rational_function_field(QQ, :x)
 (Rational function field over rationals, x)
 
 julia> f = (x + 1)//(x^3 + 3x + 1)
@@ -75,7 +75,7 @@
 
 julia> h = gcd(f, g)
 (x + 1)//(x^5 + x^4 + 4*x^3 + 4*x^2 + 4*x + 1)
-

Square root

AbstractAlgebra.is_squareMethod
is_square(f::PolyRingElem{T}) where T <: RingElement

Return true if $f$ is a perfect square.

source
is_square(a::FracElem{T}) where T <: RingElem

Return true if $a$ is a square.

source
Base.sqrtMethod
Base.sqrt(f::PolyRingElem{T}; check::Bool=true) where T <: RingElement

Return the square root of $f$. By default the function checks the input is square and raises an exception if not. If check=false this check is omitted.

source
Base.sqrt(a::FracElem{T}; check::Bool=true) where T <: RingElem

Return the square root of $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source
sqrt(a::Generic.PuiseuxSeriesElem{T}; check::Bool=true) where T <: RingElement

Return the square root of the given Puiseux series $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source

Examples

julia> R, x = rational_function_field(QQ, :x)
+

Square root

AbstractAlgebra.is_squareMethod
is_square(f::PolyRingElem{T}) where T <: RingElement

Return true if $f$ is a perfect square.

source
is_square(a::FracElem{T}) where T <: RingElem

Return true if $a$ is a square.

source
Base.sqrtMethod
Base.sqrt(f::PolyRingElem{T}; check::Bool=true) where T <: RingElement

Return the square root of $f$. By default the function checks the input is square and raises an exception if not. If check=false this check is omitted.

source
Base.sqrt(a::FracElem{T}; check::Bool=true) where T <: RingElem

Return the square root of $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source
sqrt(a::Generic.PuiseuxSeriesElem{T}; check::Bool=true) where T <: RingElement

Return the square root of the given Puiseux series $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source

Examples

julia> R, x = rational_function_field(QQ, :x)
 (Rational function field over rationals, x)
 
 julia> a = (21//4*x^6 - 15*x^5 + 27//14*x^4 + 9//20*x^3 + 3//7*x + 9//10)//(x + 3)
@@ -145,10 +145,10 @@
 (20*x^2 + 19*x + 22)*y + 22*x^2 + 21*x
 
 julia> f*inv(f)
-1

Function field functionality provided by AbstractAlgebra.jl

The following functionality is provided for function fields.

Basic manipulation

AbstractAlgebra.Generic.base_fieldMethod
base_field(R::FunctionField)

Return the rational function field that the field R is an extension of. Synonymous with base_ring.

source
AbstractAlgebra.varMethod
var(R::FunctionField)

Return the variable name of the generator of the function field R as a symbol.

source
AbstractAlgebra.characteristicMethod
characteristic(R::FunctionField)

Return the characteristic of the underlying rational function field.

source
AbstractAlgebra.Generic.defining_polynomialMethod
defining_polynomial(R::FunctionField)
-modulus(R::FunctionField)

Return the original polynomial that was used to define the function field R.

source
Base.numeratorMethod
Base.numerator(R::FunctionField{T}, canonicalise::Bool=true) where T <: FieldElement
-Base.denominator(R::FunctionField{T}, canonicalise::Bool=true) where T <: FieldElement

Thinking of elements of the rational function field as fractions, put the defining polynomial of the function field over a common denominator and return the numerator/denominator respectively. Note that the resulting polynomials belong to a different ring than the original defining polynomial. The canonicalise is ignored, but exists for compatibility with the Generic interface.

source
Base.numeratorMethod
Base.numerator(a::FunctionFieldElem{T}, canonicalise::Bool=true) where T <: FieldElement
-Base.denominator(a::FunctionFieldElem{T}, canonicalise::Bool=true) where T <: FieldElement

Return the numerator and denominator of the function field element a. Note that elements are stored in fraction free form so that the denominator is a common denominator for the coefficients of the element a. If canonicalise is set to true the fraction is first canonicalised.

source
AbstractAlgebra.degreeMethod
degree(S::FunctionField)

Return the degree of the defining polynomial of the function field, i.e. the degree of the extension that the function field makes of the underlying rational function field.

source
AbstractAlgebra.genMethod
gen(S::FunctionField{T}) where T <: FieldElement

Return the generator of the function field returned by the function field constructor.

source
AbstractAlgebra.is_genMethod
is_gen(a::FunctionFieldElem)

Return true if a is the generator of the function field returned by the function field constructor.

source
AbstractAlgebra.coeffMethod
coeff(a::FunctionFieldElem, n::Int)

Return the degree n coefficient of the element a in its polynomial representation in terms of the generator of the function field. The coefficient is returned as an element of the underlying rational function field.

source
AbstractAlgebra.Generic.num_coeffMethod
num_coeff(a::FunctionFieldElem, n::Int)

Return the degree n coefficient of the numerator of the element a (in its polynomial representation in terms of the generator of the function field, rationalised as per numerator/denominator described above). The coefficient will be an polynomial over the base_ring of the underlying rational function field.

source

Examples

julia> R, x = rational_function_field(QQ, :x)
+1

Function field functionality provided by AbstractAlgebra.jl

The following functionality is provided for function fields.

Basic manipulation

AbstractAlgebra.Generic.base_fieldMethod
base_field(R::FunctionField)

Return the rational function field that the field R is an extension of. Synonymous with base_ring.

source
AbstractAlgebra.varMethod
var(R::FunctionField)

Return the variable name of the generator of the function field R as a symbol.

source
AbstractAlgebra.characteristicMethod
characteristic(R::FunctionField)

Return the characteristic of the underlying rational function field.

source
AbstractAlgebra.Generic.defining_polynomialMethod
defining_polynomial(R::FunctionField)
+modulus(R::FunctionField)

Return the original polynomial that was used to define the function field R.

source
Base.numeratorMethod
Base.numerator(R::FunctionField{T}, canonicalise::Bool=true) where T <: FieldElement
+Base.denominator(R::FunctionField{T}, canonicalise::Bool=true) where T <: FieldElement

Thinking of elements of the rational function field as fractions, put the defining polynomial of the function field over a common denominator and return the numerator/denominator respectively. Note that the resulting polynomials belong to a different ring than the original defining polynomial. The canonicalise is ignored, but exists for compatibility with the Generic interface.

source
Base.numeratorMethod
Base.numerator(a::FunctionFieldElem{T}, canonicalise::Bool=true) where T <: FieldElement
+Base.denominator(a::FunctionFieldElem{T}, canonicalise::Bool=true) where T <: FieldElement

Return the numerator and denominator of the function field element a. Note that elements are stored in fraction free form so that the denominator is a common denominator for the coefficients of the element a. If canonicalise is set to true the fraction is first canonicalised.

source
AbstractAlgebra.degreeMethod
degree(S::FunctionField)

Return the degree of the defining polynomial of the function field, i.e. the degree of the extension that the function field makes of the underlying rational function field.

source
AbstractAlgebra.genMethod
gen(S::FunctionField{T}) where T <: FieldElement

Return the generator of the function field returned by the function field constructor.

source
AbstractAlgebra.is_genMethod
is_gen(a::FunctionFieldElem)

Return true if a is the generator of the function field returned by the function field constructor.

source
AbstractAlgebra.coeffMethod
coeff(a::FunctionFieldElem, n::Int)

Return the degree n coefficient of the element a in its polynomial representation in terms of the generator of the function field. The coefficient is returned as an element of the underlying rational function field.

source
AbstractAlgebra.Generic.num_coeffMethod
num_coeff(a::FunctionFieldElem, n::Int)

Return the degree n coefficient of the numerator of the element a (in its polynomial representation in terms of the generator of the function field, rationalised as per numerator/denominator described above). The coefficient will be an polynomial over the base_ring of the underlying rational function field.

source

Examples

julia> R, x = rational_function_field(QQ, :x)
 (Rational function field over rationals, x)
 
 julia> U, z = R[:z]
@@ -201,7 +201,7 @@
 (x + 1)//(x^2 + 1)
 
 julia> num_coeff(a, 1)
-x + 1

Trace and norm

LinearAlgebra.normMethod
norm(a::FunctionFieldElem)

Return the absolute norm of a as an element of the underlying rational function field.

source
julia> R, x = rational_function_field(QQ, :x)
+x + 1

Trace and norm

LinearAlgebra.normMethod
norm(a::FunctionFieldElem)

Return the absolute norm of a as an element of the underlying rational function field.

source
julia> R, x = rational_function_field(QQ, :x)
 (Rational function field over rationals, x)
 
 julia> U, z = R[:z]
@@ -220,4 +220,4 @@
 (x^7 + 20//9*x^6 + 766//81*x^5 + 2027//81*x^4 + 110//3*x^3 + 682//9*x^2 + 1060//9*x + 725//9)//(x^3 - 2*x^2 - 4*x + 8)
 
 julia> tr(f)
-(2*x^4 + 38//9*x^3 + 85//9*x^2 + 24*x + 25)//(x^2 - 4)
+(2*x^4 + 38//9*x^3 + 85//9*x^2 + 24*x + 25)//(x^2 - 4) diff --git a/dev/functional_map/index.html b/dev/functional_map/index.html index 719d81d2a..4b7e4ee4c 100644 --- a/dev/functional_map/index.html +++ b/dev/functional_map/index.html @@ -8,4 +8,4 @@ to integers julia> f(ZZ(2)) -3source +3source diff --git a/dev/ideal/index.html b/dev/ideal/index.html index ac6b0adbf..6d24baa98 100644 --- a/dev/ideal/index.html +++ b/dev/ideal/index.html @@ -17,7 +17,7 @@ 7 julia> J = Generic.Ideal(ZZ, W) -AbstractAlgebra.Generic.Ideal{BigInt}(Integers, BigInt[1])

Ideal functions

Basic functionality

AbstractAlgebra.gensMethod
gens(I::Ideal{T}) where T <: RingElement

Return a list of generators of the ideal I in reduced form and canonicalised.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+AbstractAlgebra.Generic.Ideal{BigInt}(Integers, BigInt[1])

Ideal functions

Basic functionality

AbstractAlgebra.gensMethod
gens(I::Ideal{T}) where T <: RingElement

Return a list of generators of the ideal I in reduced form and canonicalised.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> V = [1 + 2x^2 + 3x^3, 5x^4 + 1, 2x - 1]
@@ -32,7 +32,7 @@
 julia> gens(I)
 2-element Vector{AbstractAlgebra.Generic.Poly{BigInt}}:
  3
- x + 1

Arithmetic of Ideals

Ideals support addition, multiplication, scalar multiplication and equality testing of ideals.

Containment

Base.containsMethod
Base.contains(I::Ideal{T}, J::Ideal{T}) where T <: RingElement

Return true if the ideal J is contained in the ideal I.

source
Base.intersectMethod
intersect(I::Ideal{T}, J::Ideal{T}) where T <: RingElement

Return the intersection of the ideals I and J.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+ x + 1

Arithmetic of Ideals

Ideals support addition, multiplication, scalar multiplication and equality testing of ideals.

Containment

Base.containsMethod
Base.contains(I::Ideal{T}, J::Ideal{T}) where T <: RingElement

Return true if the ideal J is contained in the ideal I.

source
Base.intersectMethod
intersect(I::Ideal{T}, J::Ideal{T}) where T <: RingElement

Return the intersection of the ideals I and J.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> V = [1 + 2x^2 + 3x^3, 5x^4 + 1, 2x - 1]
@@ -59,7 +59,7 @@
 true
 
 julia> intersect(I, J) == J
-true

Normal form

For ideal of polynomial rings it is possible to return the normal form of a polynomial with respect to an ideal.

AbstractAlgebra.Generic.normal_formMethod
normal_form(p::U, I::Ideal{U}) where {T <: RingElement, U <: Union{AbstractAlgebra.PolyRingElem{T}, AbstractAlgebra.MPolyRingElem{T}}}

Return the normal form of the polynomial p with respect to the ideal I.

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y]; internal_ordering=:degrevlex)
+true

Normal form

For ideal of polynomial rings it is possible to return the normal form of a polynomial with respect to an ideal.

AbstractAlgebra.Generic.normal_formMethod
normal_form(p::U, I::Ideal{U}) where {T <: RingElement, U <: Union{AbstractAlgebra.PolyRingElem{T}, AbstractAlgebra.MPolyRingElem{T}}}

Return the normal form of the polynomial p with respect to the ideal I.

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y]; internal_ordering=:degrevlex)
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
 
 julia> V = [3*x^2*y - 3*y^2, 9*x^2*y + 7*x*y]
@@ -72,4 +72,4 @@
 
 
 julia> normal_form(30x^5*y + 2x + 1, I)
-135*y^4 + 138*y^3 - 147*y^2 + 2*x + 1
+135*y^4 + 138*y^3 - 147*y^2 + 2*x + 1 diff --git a/dev/index.html b/dev/index.html index afb17dac2..8bd880867 100644 --- a/dev/index.html +++ b/dev/index.html @@ -41,4 +41,4 @@ u = t + O(t^100) -@time divexact((u*exp(x*u)), (exp(u)-1)); +@time divexact((u*exp(x*u)), (exp(u)-1)); diff --git a/dev/integer/index.html b/dev/integer/index.html index a53ffe240..f8ce9c481 100644 --- a/dev/integer/index.html +++ b/dev/integer/index.html @@ -41,20 +41,20 @@ julia> is_unit(r) true -

Divisibility testing

AbstractAlgebra.is_divisible_byMethod
is_divisible_by(a::Integer, b::Integer)

Return true if $a$ is divisible by $b$, i.e. if there exists $c$ such that $a = bc$.

source
AbstractAlgebra.is_associatedMethod
is_associated(a::Integer, b::Integer)

Return true if $a$ and $b$ are associated, i.e. if there exists a unit $c$ such that $a = bc$. For integers, this reduces to checking if $a$ and $b$ differ by a factor of $1$ or $-1$.

source

Examples

julia> r = ZZ(6)
+

Divisibility testing

AbstractAlgebra.is_divisible_byMethod
is_divisible_by(a::Integer, b::Integer)

Return true if $a$ is divisible by $b$, i.e. if there exists $c$ such that $a = bc$.

source
AbstractAlgebra.is_associatedMethod
is_associated(a::Integer, b::Integer)

Return true if $a$ and $b$ are associated, i.e. if there exists a unit $c$ such that $a = bc$. For integers, this reduces to checking if $a$ and $b$ differ by a factor of $1$ or $-1$.

source

Examples

julia> r = ZZ(6)
 6
 
 julia> s = ZZ(3)
 3
 
 julia> is_divisible_by(r, s)
-true

Square root

AbstractAlgebra.sqrtMethod
sqrt(a::T; check::Bool=true) where T <: Integer

Return the square root of $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source
AbstractAlgebra.is_squareMethod
is_square(f::PolyRingElem{T}) where T <: RingElement

Return true if $f$ is a perfect square.

source
is_square(a::ResFieldElem{T}) where T <: Integer

Return true if $a$ is a square.

source
is_square(a::T) where T <: Integer

Return true if $a$ is a square.

source
AbstractAlgebra.is_square_with_sqrtMethod
is_square_with_sqrt(a::T) where T <: Integer

Return (true, s) if $a$ is a perfect square, where $s^2 = a$. Otherwise return (false, 0).

source
AbstractAlgebra.rootMethod
root(a::T, n::Int; check::Bool=true) where T <: Integer

Return the $n$-th root of $a$. If check=true the function will test if the input was a perfect $n$-th power, otherwise an exception will be raised. We require $n > 0$.

source
AbstractAlgebra.irootMethod
iroot(a::T, n::Int) where T <: Integer

Return the truncated integer part of the $n$-th root of $a$ (round towards zero). We require $n > 0$ and also $a \geq 0$ if $n$ is even.

source
AbstractAlgebra.is_powerMethod
is_power(a::T, n::Int) where T <: Integer

Return true, q if $a$ is a perfect $n$-th power with $a = q^n$. Otherwise return false, 0. We require $n > 0$.

source
AbstractAlgebra.expMethod
exp(a::T) where T <: Integer

Return $1$ if $a = 0$, otherwise throw an exception. This function is not generally of use to the user, but is used internally in AbstractAlgebra.jl.

source
exp(a::Rational{T}) where T <: Integer

Return $1$ if $a = 0$, otherwise throw an exception.

source

Examples

julia> d = AbstractAlgebra.sqrt(ZZ(36))
+true

Square root

AbstractAlgebra.sqrtMethod
sqrt(a::T; check::Bool=true) where T <: Integer

Return the square root of $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source
AbstractAlgebra.is_squareMethod
is_square(f::PolyRingElem{T}) where T <: RingElement

Return true if $f$ is a perfect square.

source
is_square(a::ResFieldElem{T}) where T <: Integer

Return true if $a$ is a square.

source
is_square(a::T) where T <: Integer

Return true if $a$ is a square.

source
AbstractAlgebra.is_square_with_sqrtMethod
is_square_with_sqrt(a::T) where T <: Integer

Return (true, s) if $a$ is a perfect square, where $s^2 = a$. Otherwise return (false, 0).

source
AbstractAlgebra.rootMethod
root(a::T, n::Int; check::Bool=true) where T <: Integer

Return the $n$-th root of $a$. If check=true the function will test if the input was a perfect $n$-th power, otherwise an exception will be raised. We require $n > 0$.

source
AbstractAlgebra.irootMethod
iroot(a::T, n::Int) where T <: Integer

Return the truncated integer part of the $n$-th root of $a$ (round towards zero). We require $n > 0$ and also $a \geq 0$ if $n$ is even.

source
AbstractAlgebra.is_powerMethod
is_power(a::T, n::Int) where T <: Integer

Return true, q if $a$ is a perfect $n$-th power with $a = q^n$. Otherwise return false, 0. We require $n > 0$.

source
AbstractAlgebra.expMethod
exp(a::T) where T <: Integer

Return $1$ if $a = 0$, otherwise throw an exception. This function is not generally of use to the user, but is used internally in AbstractAlgebra.jl.

source
exp(a::Rational{T}) where T <: Integer

Return $1$ if $a = 0$, otherwise throw an exception.

source

Examples

julia> d = AbstractAlgebra.sqrt(ZZ(36))
 6
 
 julia> is_square(ZZ(9))
 true
 
 julia> m = AbstractAlgebra.exp(ZZ(0))
-1

Coprime bases

AbstractAlgebra.ppioMethod
ppio(a::T, b::T)

Return a pair $(c,d)$ such that $a=c*d$ and $c = gcd(a, b^\infty)$ if $a\neq 0$, and $c=b$, $d=0$ if $a=0$.

source

Examples

julia> c, n = ppio(ZZ(12), ZZ(26))
+1

Coprime bases

AbstractAlgebra.ppioMethod
ppio(a::T, b::T)

Return a pair $(c,d)$ such that $a=c*d$ and $c = gcd(a, b^\infty)$ if $a\neq 0$, and $c=b$, $d=0$ if $a=0$.

source

Examples

julia> c, n = ppio(ZZ(12), ZZ(26))
 (4, 3)
-
+ diff --git a/dev/interface_introduction/index.html b/dev/interface_introduction/index.html index fa8311127..8b98a3269 100644 --- a/dev/interface_introduction/index.html +++ b/dev/interface_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

AbstractAlgebra defines a series of interfaces that can be extended with new types that implement those interfaces. For example, if one were implementing a new polynomial ring type, one would implement all of the required functionality described in this chapter for the relevant AbstractAlgebra interfaces. This would include the Ring Interface and the Univariate Polynomial Ring Interface.

Once a new type implements all the required functionality, all the corresponding generic functionality would then function automatically for the new type.

One may then go on to implement some of the optional functionality for performance if the provided generic functionality is insufficient.

AbstractAlgebra tries to provide all generic constructions recursively so that one can have towers of generic constructions. This means that new interfaces should generally only be added if they cooperate with all the existing interfaces, at least so far as the theory exists to do so.

+Introduction · AbstractAlgebra.jl

Introduction

AbstractAlgebra defines a series of interfaces that can be extended with new types that implement those interfaces. For example, if one were implementing a new polynomial ring type, one would implement all of the required functionality described in this chapter for the relevant AbstractAlgebra interfaces. This would include the Ring Interface and the Univariate Polynomial Ring Interface.

Once a new type implements all the required functionality, all the corresponding generic functionality would then function automatically for the new type.

One may then go on to implement some of the optional functionality for performance if the provided generic functionality is insufficient.

AbstractAlgebra tries to provide all generic constructions recursively so that one can have towers of generic constructions. This means that new interfaces should generally only be added if they cooperate with all the existing interfaces, at least so far as the theory exists to do so.

diff --git a/dev/laurent_mpolynomial/index.html b/dev/laurent_mpolynomial/index.html index 2a17b38da..ef0637e46 100644 --- a/dev/laurent_mpolynomial/index.html +++ b/dev/laurent_mpolynomial/index.html @@ -24,4 +24,4 @@ -x^-5*y^-4 julia> gcd(x^-3 - y^3, x^-2 - y^2) -x*y - 1 +x*y - 1 diff --git a/dev/laurent_polynomial/index.html b/dev/laurent_polynomial/index.html index 3062b7272..0729c367c 100644 --- a/dev/laurent_polynomial/index.html +++ b/dev/laurent_polynomial/index.html @@ -6,7 +6,7 @@ x^2 + 2*x^-3 julia> rand(R, -3:3, -9:9) --3*x^2 - 8*x + 4 + 3*x^-1 - 6*x^-2 + 9*x^-3source
laurent_polynomial_ring(R::Ring, varnames...; cached::Bool = true)

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.

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 or the specification in AbstractAlgebra.@varnames_interface.

source

Basic functionality

Laurent polynomials implement the ring interface, and some methods from the polynomial interface, for example:

julia> R, x = laurent_polynomial_ring(ZZ, :x)
+-3*x^2 - 8*x + 4 + 3*x^-1 - 6*x^-2 + 9*x^-3
source
laurent_polynomial_ring(R::Ring, varnames...; cached::Bool = true)

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.

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 or the specification in AbstractAlgebra.@varnames_interface.

source

Basic functionality

Laurent polynomials implement the ring interface, and some methods from the polynomial interface, for example:

julia> R, x = laurent_polynomial_ring(ZZ, :x)
 (Univariate Laurent polynomial ring in x over integers, x)
 
 julia> var(R)
@@ -46,4 +46,4 @@
 5.0*x^3 + 2.0*x + x^-2
 
 julia> leading_coefficient(f), trailing_coefficient(f)
-(5, 1)
+(5, 1) diff --git a/dev/linear_solving/index.html b/dev/linear_solving/index.html index 3be027665..f7d9bdfe6 100644 --- a/dev/linear_solving/index.html +++ b/dev/linear_solving/index.html @@ -17,17 +17,17 @@ 3-element Vector{Rational{BigInt}}: 1//5 1//3 - 2//45source

Now the functions solve, can_solve, etc. can be used with C in place of $A$. This way the time-consuming part of the solving (i.e. computing a reduced form of $A$) is only done once and the result cached in C to be reused.

Detailed documentation

AbstractAlgebra.Solve.solveFunction
solve(A::MatElem{T}, b::Vector{T}; side::Symbol = :left) where T
+ 2//45
source

Now the functions solve, can_solve, etc. can be used with C in place of $A$. This way the time-consuming part of the solving (i.e. computing a reduced form of $A$) is only done once and the result cached in C to be reused.

Detailed documentation

AbstractAlgebra.Solve.solveFunction
solve(A::MatElem{T}, b::Vector{T}; side::Symbol = :left) where T
 solve(A::MatElem{T}, b::MatElem{T}; side::Symbol = :left) where T
 solve(C::SolveCtx{T}, b::Vector{T}; side::Symbol = :left) where T
-solve(C::SolveCtx{T}, b::MatElem{T}; side::Symbol = :left) where T

Return $x$ of same type as $b$ solving the linear system $xA = b$, if side == :left (default), or $Ax = b$, if side == :right.

If no solution exists, an error is raised.

If a context object C is supplied, then the above applies for A = matrix(C).

See also can_solve_with_solution.

source
AbstractAlgebra.Solve.can_solveFunction
can_solve(A::MatElem{T}, b::Vector{T}; side::Symbol = :left) where T
+solve(C::SolveCtx{T}, b::MatElem{T}; side::Symbol = :left) where T

Return $x$ of same type as $b$ solving the linear system $xA = b$, if side == :left (default), or $Ax = b$, if side == :right.

If no solution exists, an error is raised.

If a context object C is supplied, then the above applies for A = matrix(C).

See also can_solve_with_solution.

source
AbstractAlgebra.Solve.can_solveFunction
can_solve(A::MatElem{T}, b::Vector{T}; side::Symbol = :left) where T
 can_solve(A::MatElem{T}, b::MatElem{T}; side::Symbol = :left) where T
 can_solve(C::SolveCtx{T}, b::Vector{T}; side::Symbol = :left) where T
-can_solve(C::SolveCtx{T}, b::MatElem{T}; side::Symbol = :left) where T

Return true if the linear system $xA = b$ or $Ax = b$ with side == :left (default) or side == :right, respectively, has a solution and false otherwise.

If a context object C is supplied, then the above applies for A = matrix(C).

See also can_solve_with_solution.

source
AbstractAlgebra.Solve.can_solve_with_solutionFunction
can_solve_with_solution(A::MatElem{T}, b::Vector{T}; side::Symbol = :left) where T
+can_solve(C::SolveCtx{T}, b::MatElem{T}; side::Symbol = :left) where T

Return true if the linear system $xA = b$ or $Ax = b$ with side == :left (default) or side == :right, respectively, has a solution and false otherwise.

If a context object C is supplied, then the above applies for A = matrix(C).

See also can_solve_with_solution.

source
AbstractAlgebra.Solve.can_solve_with_solutionFunction
can_solve_with_solution(A::MatElem{T}, b::Vector{T}; side::Symbol = :left) where T
 can_solve_with_solution(A::MatElem{T}, b::MatElem{T}; side::Symbol = :left) where T
 can_solve_with_solution(C::SolveCtx{T}, b::Vector{T}; side::Symbol = :left) where T
-can_solve_with_solution(C::SolveCtx{T}, b::MatElem{T}; side::Symbol = :left) where T

Return true and $x$ of same type as $b$ solving the linear system $xA = b$, if such a solution exists. Return false and an empty vector or matrix, if the system has no solution.

If side == :right, the system $Ax = b$ is solved.

If a context object C is supplied, then the above applies for A = matrix(C).

See also solve.

source
AbstractAlgebra.Solve.can_solve_with_solution_and_kernelFunction
can_solve_with_solution_and_kernel(A::MatElem{T}, b::Vector{T}; side::Symbol = :left) where T
+can_solve_with_solution(C::SolveCtx{T}, b::MatElem{T}; side::Symbol = :left) where T

Return true and $x$ of same type as $b$ solving the linear system $xA = b$, if such a solution exists. Return false and an empty vector or matrix, if the system has no solution.

If side == :right, the system $Ax = b$ is solved.

If a context object C is supplied, then the above applies for A = matrix(C).

See also solve.

source
AbstractAlgebra.Solve.can_solve_with_solution_and_kernelFunction
can_solve_with_solution_and_kernel(A::MatElem{T}, b::Vector{T}; side::Symbol = :left) where T
 can_solve_with_solution_and_kernel(A::MatElem{T}, b::MatElem{T}; side::Symbol = :left) where T
 can_solve_with_solution_and_kernel(C::SolveCtx{T}, b::Vector{T}; side::Symbol = :left) where T
-can_solve_with_solution_and_kernel(C::SolveCtx{T}, b::MatElem{T}; side::Symbol = :left) where T

Return true, $x$ of same type as $b$ solving the linear system $xA = b$, together with a matrix $K$ giving the kernel of $A$ (i.e. $KA = 0$), if such a solution exists. Return false, an empty vector or matrix and an empty matrix, if the system has no solution.

If side == :right, the system $Ax = b$ is solved.

If a context object C is supplied, then the above applies for A = matrix(C).

See also solve and kernel.

source
AbstractAlgebra.kernelFunction
kernel(f::ModuleHomomorphism{T}) where T <: RingElement

Return a pair K, g consisting of the kernel object $K$ of the given module homomorphism $f$ (as a submodule of its domain) and the canonical injection from the kernel into the domain of $f$.

source
kernel(A::MatElem; side::Symbol = :left)
-kernel(C::SolveCtx; side::Symbol = :left)

Return a matrix $K$ whose rows generate the left kernel of $A$, that is, $KA$ is the zero matrix.

If side == :right, the columns of $K$ generate the right kernel of $A$, that is, $AK$ is the zero matrix.

If the base ring is a principal ideal domain, the rows or columns respectively of $K$ are a basis of the respective kernel.

If a context object C is supplied, then the above applies for A = matrix(C).

source
+can_solve_with_solution_and_kernel(C::SolveCtx{T}, b::MatElem{T}; side::Symbol = :left) where T

Return true, $x$ of same type as $b$ solving the linear system $xA = b$, together with a matrix $K$ giving the kernel of $A$ (i.e. $KA = 0$), if such a solution exists. Return false, an empty vector or matrix and an empty matrix, if the system has no solution.

If side == :right, the system $Ax = b$ is solved.

If a context object C is supplied, then the above applies for A = matrix(C).

See also solve and kernel.

source
AbstractAlgebra.kernelFunction
kernel(f::ModuleHomomorphism{T}) where T <: RingElement

Return a pair K, g consisting of the kernel object $K$ of the given module homomorphism $f$ (as a submodule of its domain) and the canonical injection from the kernel into the domain of $f$.

source
kernel(A::MatElem; side::Symbol = :left)
+kernel(C::SolveCtx; side::Symbol = :left)

Return a matrix $K$ whose rows generate the left kernel of $A$, that is, $KA$ is the zero matrix.

If side == :right, the columns of $K$ generate the right kernel of $A$, that is, $AK$ is the zero matrix.

If the base ring is a principal ideal domain, the rows or columns respectively of $K$ are a basis of the respective kernel.

If a context object C is supplied, then the above applies for A = matrix(C).

source
diff --git a/dev/map_cache/index.html b/dev/map_cache/index.html index d554f0989..23b3bf841 100644 --- a/dev/map_cache/index.html +++ b/dev/map_cache/index.html @@ -27,4 +27,4 @@ 200 julia> d = f(ZZ(1)) -2 +2 diff --git a/dev/map_interface/index.html b/dev/map_interface/index.html index 96c8e39b4..ff0c795fe 100644 --- a/dev/map_interface/index.html +++ b/dev/map_interface/index.html @@ -12,7 +12,7 @@ of univariate polynomial ring in t over integers julia> f(t) -tsource

Return an identity map on the domain $R$.

Of course there is nothing stopping a map type or class from implementing its own identity map type, and defining composition of maps of the same kind with such an identity map. In such a case, the class of such an identity map type must belong to IdentityMap so that composition with other map types still works.

Composition of maps

Any two compatible maps in AbstractAlgebra can be composed and any composition can be applied.

In order to facilitate this, the Generic module provides a type Generic.CompositeMap{D, C}, which contains two maps map1 and map2, corresponding to the two maps to be applied in a composition, in the order they should be applied.

To construct a composition map from two existing maps, we have the following function:

AbstractAlgebra.composeMethod
compose(f::Map, g::Map)

Compose the two maps $f$ and $g$, i.e. return the map $h$ such that $h(x) = g(f(x))$.

Examples

julia> f = map_from_func(x -> x + 1, ZZ, ZZ);
+t
source

Return an identity map on the domain $R$.

Of course there is nothing stopping a map type or class from implementing its own identity map type, and defining composition of maps of the same kind with such an identity map. In such a case, the class of such an identity map type must belong to IdentityMap so that composition with other map types still works.

Composition of maps

Any two compatible maps in AbstractAlgebra can be composed and any composition can be applied.

In order to facilitate this, the Generic module provides a type Generic.CompositeMap{D, C}, which contains two maps map1 and map2, corresponding to the two maps to be applied in a composition, in the order they should be applied.

To construct a composition map from two existing maps, we have the following function:

AbstractAlgebra.composeMethod
compose(f::Map, g::Map)

Compose the two maps $f$ and $g$, i.e. return the map $h$ such that $h(x) = g(f(x))$.

Examples

julia> f = map_from_func(x -> x + 1, ZZ, ZZ);
 
 julia> g = map_from_func(x -> QQ(x), ZZ, QQ);
 
@@ -22,5 +22,5 @@
   to rationals
 which is the composite of
   Map: integers -> integers
-  Map: integers -> rationals
source

As a shortcut for this function we have the following operator:

*(f::Map{D, U}, g::Map{U, C}) where {D, U, C} = compose(f, g)

Note the order of composition. If we have maps $f : X \to Y$, $g : Y \to Z$ the correct order of the maps in this operator is f*g, so that (f*g)(x) = g(f(x)).

This is chosen so that for left $R$-module morphisms represented by a matrix, the order of matrix multiplication will match the order of composition of the corresponding morphisms.

Of course, a custom map type or class of maps can implement its own composition type and compose function.

This is the case with the FunctionalMap class for example, which caches the Julia function/closure corresponding to the composition of two functional maps. As this cached function needs to be stored inside the composition, a special type is necessary for the composition of two functional maps.

By default, compose will check that the two maps are composable, i.e. the codomain of the first map matches the domain of the second map. This is implemented by the following function:

check_composable(f::Map{D, U}, g::Map{U, C})

Raise an exception if the codomain of $f$ doesn't match the domain of $g$.

Note that composite maps should keep track of the two maps they were constructed from. To access these maps, the following functions are provided:

map1(f::CompositeMap)
-map2(f::CompositeMap)

Any custom composite map type must also provide these functions for that map type, even if there exist fields with those names. This is because there is no common map class for all composite map types. Therefore the Generic system cannot provide fallbacks for all such composite map types.

+ Map: integers -> rationalssource

As a shortcut for this function we have the following operator:

*(f::Map{D, U}, g::Map{U, C}) where {D, U, C} = compose(f, g)

Note the order of composition. If we have maps $f : X \to Y$, $g : Y \to Z$ the correct order of the maps in this operator is f*g, so that (f*g)(x) = g(f(x)).

This is chosen so that for left $R$-module morphisms represented by a matrix, the order of matrix multiplication will match the order of composition of the corresponding morphisms.

Of course, a custom map type or class of maps can implement its own composition type and compose function.

This is the case with the FunctionalMap class for example, which caches the Julia function/closure corresponding to the composition of two functional maps. As this cached function needs to be stored inside the composition, a special type is necessary for the composition of two functional maps.

By default, compose will check that the two maps are composable, i.e. the codomain of the first map matches the domain of the second map. This is implemented by the following function:

check_composable(f::Map{D, U}, g::Map{U, C})

Raise an exception if the codomain of $f$ doesn't match the domain of $g$.

Note that composite maps should keep track of the two maps they were constructed from. To access these maps, the following functions are provided:

map1(f::CompositeMap)
+map2(f::CompositeMap)

Any custom composite map type must also provide these functions for that map type, even if there exist fields with those names. This is because there is no common map class for all composite map types. Therefore the Generic system cannot provide fallbacks for all such composite map types.

diff --git a/dev/map_introduction/index.html b/dev/map_introduction/index.html index 4338273bc..04245c058 100644 --- a/dev/map_introduction/index.html +++ b/dev/map_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

Maps in AbstractAlgebra model maps on sets $f : D \to C$ for some domain $D$ and codomain $C$, which have no real limitations except that elements of the codomain and domain be represented by element objects in the system.

Maps $f : D \to C$ in AbstractAlgebra are modeled by Julia objects that are able to be called on a single element $d \in D$ of the domain to yield an element $f(d) \in C$ of the codomain. We say that the map is being applied.

Maps can be constructed from Julia functions, or they can be represented by some other kind of data, e.g. a matrix, or built up from other maps.

Maps in AbstractAlgebra have a domain and codomain, can be applied, composed with other maps. Various special kinds of map provide more functionality.

For details please refer to the Map Interface documentation.

For example, there are functional maps which wrap a Julia function, cached maps which cache values so they do not have to be recomputed each time they are applied to the same inputs and various kinds of maps with inverses, e.g. maps with sections, retractions and full inverses.

The map system uses a complex four parameter Map type, however various helper functions are provided to make it easier to work with.

+Introduction · AbstractAlgebra.jl

Introduction

Maps in AbstractAlgebra model maps on sets $f : D \to C$ for some domain $D$ and codomain $C$, which have no real limitations except that elements of the codomain and domain be represented by element objects in the system.

Maps $f : D \to C$ in AbstractAlgebra are modeled by Julia objects that are able to be called on a single element $d \in D$ of the domain to yield an element $f(d) \in C$ of the codomain. We say that the map is being applied.

Maps can be constructed from Julia functions, or they can be represented by some other kind of data, e.g. a matrix, or built up from other maps.

Maps in AbstractAlgebra have a domain and codomain, can be applied, composed with other maps. Various special kinds of map provide more functionality.

For details please refer to the Map Interface documentation.

For example, there are functional maps which wrap a Julia function, cached maps which cache values so they do not have to be recomputed each time they are applied to the same inputs and various kinds of maps with inverses, e.g. maps with sections, retractions and full inverses.

The map system uses a complex four parameter Map type, however various helper functions are provided to make it easier to work with.

diff --git a/dev/map_with_inverse/index.html b/dev/map_with_inverse/index.html index b632441b2..7ab170bb5 100644 --- a/dev/map_with_inverse/index.html +++ b/dev/map_with_inverse/index.html @@ -31,4 +31,4 @@ julia> a = h(ZZ(1)) 1 - + diff --git a/dev/matrix/index.html b/dev/matrix/index.html index a8c419caf..0d3e56329 100644 --- a/dev/matrix/index.html +++ b/dev/matrix/index.html @@ -91,7 +91,7 @@ julia> M = R() [0 0] -[0 0]

Block diagonal matrix constructors

It is also possible to create block diagonal matrices from a vector of existing matrices. It is also possible to construct them from Julia matrices if one supplies the base ring.

Note that if the input matrices are not square, the output matrix may not be square.

AbstractAlgebra.block_diagonal_matrixMethod
block_diagonal_matrix(V::Vector{<:MatElem{T}}) where T <: NCRingElement

Create the block diagonal matrix whose blocks are given by the matrices in V. There must be at least one matrix in V.

source
AbstractAlgebra.block_diagonal_matrixMethod
block_diagonal_matrix(R::NCRing, V::Vector{<:Matrix{T}}) where T <: NCRingElement

Create the block diagonal matrix over the ring R whose blocks are given by the matrices in V. Entries are coerced into R upon creation.

source

Examples

julia> block_diagonal_matrix(ZZ, [[1 2; 3 4], [4 5 6; 7 8 9]])
+[0   0]

Block diagonal matrix constructors

It is also possible to create block diagonal matrices from a vector of existing matrices. It is also possible to construct them from Julia matrices if one supplies the base ring.

Note that if the input matrices are not square, the output matrix may not be square.

AbstractAlgebra.block_diagonal_matrixMethod
block_diagonal_matrix(V::Vector{<:MatElem{T}}) where T <: NCRingElement

Create the block diagonal matrix whose blocks are given by the matrices in V. There must be at least one matrix in V.

source
AbstractAlgebra.block_diagonal_matrixMethod
block_diagonal_matrix(R::NCRing, V::Vector{<:Matrix{T}}) where T <: NCRingElement

Create the block diagonal matrix over the ring R whose blocks are given by the matrices in V. Entries are coerced into R upon creation.

source

Examples

julia> block_diagonal_matrix(ZZ, [[1 2; 3 4], [4 5 6; 7 8 9]])
 [1   2   0   0   0]
 [3   4   0   0   0]
 [0   0   4   5   6]
@@ -122,14 +122,14 @@
 julia> Matrix{Int}(A)
 2×3 Matrix{Int64}:
  1  2  3
- 4  5  6
source
Core.ArrayMethod
Array(A::MatrixElem{T}) where T <: NCRingElement

Convert A to a Julia Matrix of the same dimensions with the same elements.

Examples

julia> R, x = ZZ[:x]; A = R[x^0 x^1; x^2 x^3]
+ 4  5  6
source
Core.ArrayMethod
Array(A::MatrixElem{T}) where T <: NCRingElement

Convert A to a Julia Matrix of the same dimensions with the same elements.

Examples

julia> R, x = ZZ[:x]; A = R[x^0 x^1; x^2 x^3]
 [  1     x]
 [x^2   x^3]
 
 julia> Array(A)
 2×2 Matrix{AbstractAlgebra.Generic.Poly{BigInt}}:
  1    x
- x^2  x^3
source

Matrices also support iteration, and therefore functions accepting an iterator can be called on them, e.g.:

julia> M = matrix_space(ZZ, 2, 3); x = M(1:6)
+ x^2  x^3
source

Matrices also support iteration, and therefore functions accepting an iterator can be called on them, e.g.:

julia> M = matrix_space(ZZ, 2, 3); x = M(1:6)
 [1   2   3]
 [4   5   6]
 
@@ -180,27 +180,27 @@
 [20   29]

Matrix functionality provided by AbstractAlgebra.jl

Most of the following generic functionality is available for both matrix spaces and matrix algebras. Exceptions include functions that do not return or accept square matrices or which cannot specify a parent. Such functions include solve, kernel, and nullspace which can't be provided for matrix algebras.

For details on functionality that is provided for matrix algebras only, see the dedicated section of the documentation.

Basic matrix functionality

As well as the Ring and Matrix interfaces, the following functions are provided to manipulate matrices and to set and retrieve entries and other basic data associated with the matrices.

AbstractAlgebra.Generic.dense_matrix_typeMethod
dense_matrix_type(::Type{T}) where T<:NCRingElement
 dense_matrix_type(::T) where T<:NCRingElement
 dense_matrix_type(::Type{S}) where S<:NCRing
-dense_matrix_type(::S) where S<:NCRing

Return the type of matrices with coefficients of type T respectively elem_type(S).

source
AbstractAlgebra.number_of_rowsMethod
number_of_rows(a::MatSpace)

Return the number of rows of the given matrix space.

source
AbstractAlgebra.number_of_columnsMethod
number_of_columns(a::MatSpace)

Return the number of columns of the given matrix space.

source
AbstractAlgebra.number_of_rowsMethod
number_of_rows(a::MatrixElem{T}) where T <: NCRingElement

Return the number of rows of the given matrix.

source
AbstractAlgebra.number_of_columnsMethod
number_of_columns(a::MatrixElem{T}) where T <: NCRingElement

Return the number of columns of the given matrix.

source
Base.lengthMethod
length(a::MatrixElem{T}) where T <: NCRingElement

Return the number of entries in the given matrix.

source
Base.isemptyMethod
isempty(a::MatrixElem{T}) where T <: NCRingElement

Return true if a does not contain any entry (i.e. length(a) == 0), and false otherwise.

source
AbstractAlgebra.identity_matrixMethod
identity_matrix(R::NCRing, n::Int)

Return the $n \times n$ identity matrix over $R$.

source
AbstractAlgebra.identity_matrixMethod
identity_matrix(M::MatElem{T}) where T <: NCRingElement

Construct the identity matrix in the same matrix space as M, i.e. with ones down the diagonal and zeroes elsewhere. M must be square. This is an alias for one(M).

source
AbstractAlgebra.ones_matrixMethod
ones_matrix(R::Ring, r::Int, c::Int)

Return the $r \times c$ ones matrix over $R$.

source
AbstractAlgebra.scalar_matrixMethod
scalar_matrix(R::NCRing, n::Int, a::NCRingElement)
-scalar_matrix(n::Int, a::NCRingElement)

Return the $n \times n$ matrix over R with a along the main diagonal and zeroes elsewhere. If R is not specified, it defaults to parent(a).

source
AbstractAlgebra.diagonal_matrixMethod
diagonal_matrix(x::NCRingElement, m::Int, [n::Int])

Return the $m \times n$ matrix over $R$ with x along the main diagonal and zeroes elsewhere. If n is not specified, it defaults to m.

Examples

julia> diagonal_matrix(ZZ(2), 2, 3)
+dense_matrix_type(::S) where S<:NCRing

Return the type of matrices with coefficients of type T respectively elem_type(S).

source
AbstractAlgebra.number_of_rowsMethod
number_of_rows(a::MatSpace)

Return the number of rows of the given matrix space.

source
AbstractAlgebra.number_of_columnsMethod
number_of_columns(a::MatSpace)

Return the number of columns of the given matrix space.

source
AbstractAlgebra.number_of_rowsMethod
number_of_rows(a::MatrixElem{T}) where T <: NCRingElement

Return the number of rows of the given matrix.

source
AbstractAlgebra.number_of_columnsMethod
number_of_columns(a::MatrixElem{T}) where T <: NCRingElement

Return the number of columns of the given matrix.

source
Base.lengthMethod
length(a::MatrixElem{T}) where T <: NCRingElement

Return the number of entries in the given matrix.

source
Base.isemptyMethod
isempty(a::MatrixElem{T}) where T <: NCRingElement

Return true if a does not contain any entry (i.e. length(a) == 0), and false otherwise.

source
AbstractAlgebra.identity_matrixMethod
identity_matrix(R::NCRing, n::Int)

Return the $n \times n$ identity matrix over $R$.

source
AbstractAlgebra.identity_matrixMethod
identity_matrix(M::MatElem{T}) where T <: NCRingElement

Construct the identity matrix in the same matrix space as M, i.e. with ones down the diagonal and zeroes elsewhere. M must be square. This is an alias for one(M).

source
AbstractAlgebra.ones_matrixMethod
ones_matrix(R::Ring, r::Int, c::Int)

Return the $r \times c$ ones matrix over $R$.

source
AbstractAlgebra.scalar_matrixMethod
scalar_matrix(R::NCRing, n::Int, a::NCRingElement)
+scalar_matrix(n::Int, a::NCRingElement)

Return the $n \times n$ matrix over R with a along the main diagonal and zeroes elsewhere. If R is not specified, it defaults to parent(a).

source
AbstractAlgebra.diagonal_matrixMethod
diagonal_matrix(x::NCRingElement, m::Int, [n::Int])

Return the $m \times n$ matrix over $R$ with x along the main diagonal and zeroes elsewhere. If n is not specified, it defaults to m.

Examples

julia> diagonal_matrix(ZZ(2), 2, 3)
 [2   0   0]
 [0   2   0]
 
 julia> diagonal_matrix(QQ(-1), 3)
 [-1//1    0//1    0//1]
 [ 0//1   -1//1    0//1]
-[ 0//1    0//1   -1//1]
source
Base.zeroMethod
zero(a::MatSpace)

Return the zero matrix in the given matrix space.

source
Base.zeroMethod
zero(x::MatrixElem{T}, R::NCRing, r::Int, c::Int) where T <: NCRingElement
+[ 0//1    0//1   -1//1]
source
Base.zeroMethod
zero(a::MatSpace)

Return the zero matrix in the given matrix space.

source
Base.zeroMethod
zero(x::MatrixElem{T}, R::NCRing, r::Int, c::Int) where T <: NCRingElement
 zero(x::MatrixElem{T}, R::NCRing=base_ring(x)) where T <: NCRingElement
-zero(x::MatrixElem{T}, r::Int, c::Int) where T <: NCRingElement

Return a zero matrix similar to the given matrix, with optionally different base ring or dimensions.

source
Base.oneMethod
one(a::MatSpace)

Return the identity matrix of given matrix space. The matrix space must contain square matrices or else an error is thrown.

source
Base.oneMethod
one(a::MatrixElem{T}) where T <: NCRingElement

Return the identity matrix in the same matrix space as $a$. If the space does not contain square matrices, an error is thrown.

source
AbstractAlgebra.lower_triangular_matrixMethod
lower_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}

Return the $n$ by $n$ matrix whose entries on and below the main diagonal are the elements of L, and which has zeroes elsewhere. The value of $n$ is determined by the condition that L has length $n(n+1)/2$.

An exception is thrown if there is no integer $n$ with this property.

Examples

julia> lower_triangular_matrix([1, 2, 3])
+zero(x::MatrixElem{T}, r::Int, c::Int) where T <: NCRingElement

Return a zero matrix similar to the given matrix, with optionally different base ring or dimensions.

source
Base.oneMethod
one(a::MatSpace)

Return the identity matrix of given matrix space. The matrix space must contain square matrices or else an error is thrown.

source
Base.oneMethod
one(a::MatrixElem{T}) where T <: NCRingElement

Return the identity matrix in the same matrix space as $a$. If the space does not contain square matrices, an error is thrown.

source
AbstractAlgebra.lower_triangular_matrixMethod
lower_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}

Return the $n$ by $n$ matrix whose entries on and below the main diagonal are the elements of L, and which has zeroes elsewhere. The value of $n$ is determined by the condition that L has length $n(n+1)/2$.

An exception is thrown if there is no integer $n$ with this property.

Examples

julia> lower_triangular_matrix([1, 2, 3])
 [1   0]
-[2   3]
source
AbstractAlgebra.upper_triangular_matrixMethod
upper_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}

Return the $n$ by $n$ matrix whose entries on and above the main diagonal are the elements of L, and which has zeroes elsewhere. The value of $n$ is determined by the condition that L has length $n(n+1)/2$.

An exception is thrown if there is no integer $n$ with this property.

Examples

julia> upper_triangular_matrix([1, 2, 3])
+[2   3]
source
AbstractAlgebra.upper_triangular_matrixMethod
upper_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}

Return the $n$ by $n$ matrix whose entries on and above the main diagonal are the elements of L, and which has zeroes elsewhere. The value of $n$ is determined by the condition that L has length $n(n+1)/2$.

An exception is thrown if there is no integer $n$ with this property.

Examples

julia> upper_triangular_matrix([1, 2, 3])
 [1   2]
-[0   3]
source
AbstractAlgebra.strictly_lower_triangular_matrixMethod
strictly_lower_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}

Return the $n$ by $n$ matrix whose entries below the main diagonal are the elements of L, and which has zeroes elsewhere. The value of $n$ is determined by the condition that L has length $(n-1)n/2$.

An exception is thrown if there is no integer $n$ with this property.

Examples

julia> strictly_lower_triangular_matrix([1, 2, 3])
+[0   3]
source
AbstractAlgebra.strictly_lower_triangular_matrixMethod
strictly_lower_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}

Return the $n$ by $n$ matrix whose entries below the main diagonal are the elements of L, and which has zeroes elsewhere. The value of $n$ is determined by the condition that L has length $(n-1)n/2$.

An exception is thrown if there is no integer $n$ with this property.

Examples

julia> strictly_lower_triangular_matrix([1, 2, 3])
 [0   0   0]
 [1   0   0]
-[2   3   0]
source
AbstractAlgebra.strictly_upper_triangular_matrixMethod
strictly_upper_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}

Return the $n$ by $n$ matrix whose entries above the main diagonal are the elements of L, and which has zeroes elsewhere. The value of $n$ is determined by the condition that L has length $(n-1)n/2$.

An exception is thrown if there is no integer $n$ with this property.

Examples

julia> strictly_upper_triangular_matrix([1, 2, 3])
+[2   3   0]
source
AbstractAlgebra.strictly_upper_triangular_matrixMethod
strictly_upper_triangular_matrix(L::AbstractVector{T}) where {T <: NCRingElement}

Return the $n$ by $n$ matrix whose entries above the main diagonal are the elements of L, and which has zeroes elsewhere. The value of $n$ is determined by the condition that L has length $(n-1)n/2$.

An exception is thrown if there is no integer $n$ with this property.

Examples

julia> strictly_upper_triangular_matrix([1, 2, 3])
 [0   1   2]
 [0   0   3]
-[0   0   0]
source
AbstractAlgebra.is_lower_triangularMethod
is_lower_triangular(A::MatrixElem)

Return true if $A$ is an lower triangular matrix, that is, all entries above the main diagonal are zero. Note that this definition also applies to non-square matrices.

Alias for LinearAlgebra.istril.

Examples

julia> is_lower_triangular(QQ[1 2 ; 0 4])
+[0   0   0]
source
AbstractAlgebra.is_lower_triangularMethod
is_lower_triangular(A::MatrixElem)

Return true if $A$ is an lower triangular matrix, that is, all entries above the main diagonal are zero. Note that this definition also applies to non-square matrices.

Alias for LinearAlgebra.istril.

Examples

julia> is_lower_triangular(QQ[1 2 ; 0 4])
 false
 
 julia> is_lower_triangular(QQ[1 0 ; 3 4])
@@ -210,7 +210,7 @@
 false
 
 julia> is_lower_triangular(QQ[1 ; 2])
-true
source
AbstractAlgebra.is_upper_triangularMethod
is_upper_triangular(A::MatrixElem)

Return true if $A$ is an upper triangular matrix, that is, all entries below the main diagonal are zero. Note that this definition also applies to non-square matrices.

Alias for LinearAlgebra.istriu.

Examples

julia> is_upper_triangular(QQ[1 2 ; 0 4])
+true
source
AbstractAlgebra.is_upper_triangularMethod
is_upper_triangular(A::MatrixElem)

Return true if $A$ is an upper triangular matrix, that is, all entries below the main diagonal are zero. Note that this definition also applies to non-square matrices.

Alias for LinearAlgebra.istriu.

Examples

julia> is_upper_triangular(QQ[1 2 ; 0 4])
 true
 
 julia> is_upper_triangular(QQ[1 0 ; 3 4])
@@ -220,14 +220,14 @@
 true
 
 julia> is_upper_triangular(QQ[1 ; 2])
-false
source
AbstractAlgebra.is_diagonalMethod
is_diagonal(A::MatrixElem)

Return true if $A$ is a diagonal matrix, that is, all entries off the main diagonal are zero. Note that this definition also applies to non-square matrices.

Alias for LinearAlgebra.isdiag.

Examples

julia> is_diagonal(QQ[1 0 ; 0 4])
+false
source
AbstractAlgebra.is_diagonalMethod
is_diagonal(A::MatrixElem)

Return true if $A$ is a diagonal matrix, that is, all entries off the main diagonal are zero. Note that this definition also applies to non-square matrices.

Alias for LinearAlgebra.isdiag.

Examples

julia> is_diagonal(QQ[1 0 ; 0 4])
 true
 
 julia> is_diagonal(QQ[1 2 ; 3 4])
 false
 
 julia> is_diagonal(QQ[1 0 ;])
-true
source
AbstractAlgebra.change_base_ringMethod
change_base_ring(R::NCRing, M::MatrixElem{T}) where T <: NCRingElement

Return the matrix obtained by coercing each entry into R.

source
Base.mapMethod
map(f, a::MatrixElem{T}) where T <: NCRingElement

Transform matrix a by applying f on each element. This is equivalent to map_entries(f, a).

source
Base.map!Method
map!(f, dst::MatrixElem{T}, src::MatrixElem{U}) where {T <: NCRingElement, U <: NCRingElement}

Like map, but stores the result in dst rather than a new matrix. This is equivalent to map_entries!(f, dst, src).

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
+true
source
AbstractAlgebra.change_base_ringMethod
change_base_ring(R::NCRing, M::MatrixElem{T}) where T <: NCRingElement

Return the matrix obtained by coercing each entry into R.

source
Base.mapMethod
map(f, a::MatrixElem{T}) where T <: NCRingElement

Transform matrix a by applying f on each element. This is equivalent to map_entries(f, a).

source
Base.map!Method
map!(f, dst::MatrixElem{T}, src::MatrixElem{U}) where {T <: NCRingElement, U <: NCRingElement}

Like map, but stores the result in dst rather than a new matrix. This is equivalent to map_entries!(f, dst, src).

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S = matrix_space(R, 3, 3)
@@ -319,7 +319,7 @@
 [t + 1   t^2            -2]
 [    t     t         t + 2]
 [    1     t   t^2 + t + 1]
-
source

Submatrices

Submatrices are only available for matrix spaces, not for matrix algebras and generally only available for generic matrices built on Julia arrays.

Submatrices return a new matrix with the same entries as the submatrix with the given range of rows and columns. They are best illustrated with examples.

Examples

julia> M = matrix(ZZ, BigInt[1 2 3; 2 3 4; 3 4 5])
+
source

Submatrices

Submatrices are only available for matrix spaces, not for matrix algebras and generally only available for generic matrices built on Julia arrays.

Submatrices return a new matrix with the same entries as the submatrix with the given range of rows and columns. They are best illustrated with examples.

Examples

julia> M = matrix(ZZ, BigInt[1 2 3; 2 3 4; 3 4 5])
 [1   2   3]
 [2   3   4]
 [3   4   5]
@@ -336,7 +336,7 @@
 julia> N3 = M[2:3, 2:3]
 [3   4]
 [4   5]
-

Elementary row and column operations

AbstractAlgebra.add_columnMethod
add_column(a::MatrixElem{T}, s::RingElement, i::Int, j::Int, rows = 1:nrows(a)) where T <: RingElement

Create a copy of $a$ and add $s$ times the $i$-th row to the $j$-th row of $a$.

By default, the transformation is applied to all rows of $a$. This can be changed using the optional rows argument.

source
AbstractAlgebra.add_column!Method
add_column!(a::MatrixElem{T}, s::RingElement, i::Int, j::Int, rows = 1:nrows(a)) where T <: RingElement

Add $s$ times the $i$-th row to the $j$-th row of $a$.

By default, the transformation is applied to all rows of $a$. This can be changed using the optional rows argument.

source
AbstractAlgebra.add_rowMethod
add_row(a::MatrixElem{T}, s::RingElement, i::Int, j::Int, cols = 1:ncols(a)) where T <: RingElement

Create a copy of $a$ and add $s$ times the $i$-th row to the $j$-th row of $a$.

By default, the transformation is applied to all columns of $a$. This can be changed using the optional cols argument.

source
AbstractAlgebra.add_row!Method
add_row!(a::MatrixElem{T}, s::RingElement, i::Int, j::Int, cols = 1:ncols(a)) where T <: RingElement

Add $s$ times the $i$-th row to the $j$-th row of $a$.

By default, the transformation is applied to all columns of $a$. This can be changed using the optional cols argument.

source
AbstractAlgebra.multiply_columnMethod
multiply_column(a::MatrixElem{T}, s::RingElement, i::Int, rows = 1:nrows(a)) where T <: RingElement

Create a copy of $a$ and multiply the $i$th column of $a$ with $s$.

By default, the transformation is applied to all rows of $a$. This can be changed using the optional rows argument.

source
AbstractAlgebra.multiply_column!Method
multiply_column!(a::MatrixElem{T}, s::RingElement, i::Int, rows = 1:nrows(a)) where T <: RingElement

Multiply the $i$th column of $a$ with $s$.

By default, the transformation is applied to all rows of $a$. This can be changed using the optional rows argument.

source
AbstractAlgebra.multiply_rowMethod
multiply_row(a::MatrixElem{T}, s::RingElement, i::Int, cols = 1:ncols(a)) where T <: RingElement

Create a copy of $a$ and multiply the $i$th row of $a$ with $s$.

By default, the transformation is applied to all columns of $a$. This can be changed using the optional cols argument.

source
AbstractAlgebra.multiply_row!Method
multiply_row!(a::MatrixElem{T}, s::RingElement, i::Int, cols = 1:ncols(a)) where T <: RingElement

Multiply the $i$th row of $a$ with $s$.

By default, the transformation is applied to all columns of $a$. This can be changed using the optional cols argument.

source

Examples

julia> M = ZZ[1 2 3; 2 3 4; 4 5 5]
+

Elementary row and column operations

AbstractAlgebra.add_columnMethod
add_column(a::MatrixElem{T}, s::RingElement, i::Int, j::Int, rows = 1:nrows(a)) where T <: RingElement

Create a copy of $a$ and add $s$ times the $i$-th row to the $j$-th row of $a$.

By default, the transformation is applied to all rows of $a$. This can be changed using the optional rows argument.

source
AbstractAlgebra.add_column!Method
add_column!(a::MatrixElem{T}, s::RingElement, i::Int, j::Int, rows = 1:nrows(a)) where T <: RingElement

Add $s$ times the $i$-th row to the $j$-th row of $a$.

By default, the transformation is applied to all rows of $a$. This can be changed using the optional rows argument.

source
AbstractAlgebra.add_rowMethod
add_row(a::MatrixElem{T}, s::RingElement, i::Int, j::Int, cols = 1:ncols(a)) where T <: RingElement

Create a copy of $a$ and add $s$ times the $i$-th row to the $j$-th row of $a$.

By default, the transformation is applied to all columns of $a$. This can be changed using the optional cols argument.

source
AbstractAlgebra.add_row!Method
add_row!(a::MatrixElem{T}, s::RingElement, i::Int, j::Int, cols = 1:ncols(a)) where T <: RingElement

Add $s$ times the $i$-th row to the $j$-th row of $a$.

By default, the transformation is applied to all columns of $a$. This can be changed using the optional cols argument.

source
AbstractAlgebra.multiply_columnMethod
multiply_column(a::MatrixElem{T}, s::RingElement, i::Int, rows = 1:nrows(a)) where T <: RingElement

Create a copy of $a$ and multiply the $i$th column of $a$ with $s$.

By default, the transformation is applied to all rows of $a$. This can be changed using the optional rows argument.

source
AbstractAlgebra.multiply_column!Method
multiply_column!(a::MatrixElem{T}, s::RingElement, i::Int, rows = 1:nrows(a)) where T <: RingElement

Multiply the $i$th column of $a$ with $s$.

By default, the transformation is applied to all rows of $a$. This can be changed using the optional rows argument.

source
AbstractAlgebra.multiply_rowMethod
multiply_row(a::MatrixElem{T}, s::RingElement, i::Int, cols = 1:ncols(a)) where T <: RingElement

Create a copy of $a$ and multiply the $i$th row of $a$ with $s$.

By default, the transformation is applied to all columns of $a$. This can be changed using the optional cols argument.

source
AbstractAlgebra.multiply_row!Method
multiply_row!(a::MatrixElem{T}, s::RingElement, i::Int, cols = 1:ncols(a)) where T <: RingElement

Multiply the $i$th row of $a$ with $s$.

By default, the transformation is applied to all columns of $a$. This can be changed using the optional cols argument.

source

Examples

julia> M = ZZ[1 2 3; 2 3 4; 4 5 5]
 [1   2   3]
 [2   3   4]
 [4   5   5]
@@ -372,7 +372,7 @@
 julia> M  # was not modified
 [1   0   0]
 [0   1   0]
-[0   0   1]
source
AbstractAlgebra.swap_rows!Method
swap_rows!(a::MatrixElem{T}, i::Int, j::Int) where T <: NCRingElement

Swap the $i$th and $j$th row of $a$ in place. The function returns the mutated matrix (since matrices are assumed to be mutable in AbstractAlgebra.jl).

Examples

julia> M = identity_matrix(ZZ, 3)
+[0   0   1]
source
AbstractAlgebra.swap_rows!Method
swap_rows!(a::MatrixElem{T}, i::Int, j::Int) where T <: NCRingElement

Swap the $i$th and $j$th row of $a$ in place. The function returns the mutated matrix (since matrices are assumed to be mutable in AbstractAlgebra.jl).

Examples

julia> M = identity_matrix(ZZ, 3)
 [1   0   0]
 [0   1   0]
 [0   0   1]
@@ -385,7 +385,7 @@
 julia> M  # was modified
 [0   1   0]
 [1   0   0]
-[0   0   1]
source
AbstractAlgebra.swap_colsMethod
swap_cols(a::MatrixElem{T}, i::Int, j::Int) where T <: NCRingElement

Return a matrix $b$ with the entries of $a$, where the $i$th and $j$th row are swapped.

source
AbstractAlgebra.swap_cols!Method
swap_cols!(a::MatrixElem{T}, i::Int, j::Int) where T <: NCRingElement

Swap the $i$th and $j$th column of $a$ in place. The function returns the mutated matrix (since matrices are assumed to be mutable in AbstractAlgebra.jl).

source

Swap the rows of M in place. The function returns the mutated matrix (since matrices are assumed to be mutable in AbstractAlgebra.jl).

Concatenation

The following are only available for matrix spaces, not for matrix algebras.

hcat(M::T, N::T) where T <: MatElem

Return the horizontal concatenation of $M$ and $N$. It is assumed that the number of rows of $M$ and $N$ are the same.

vcat(M::T, N::T) where T <: MatElem

Return the vertical concatenation of $M$ and $N$. It is assumed that the number of columns of $M$ and $N$ are the same.

Examples

julia> M = matrix(ZZ, BigInt[1 2 3; 2 3 4; 3 4 5])
+[0   0   1]
source
AbstractAlgebra.swap_colsMethod
swap_cols(a::MatrixElem{T}, i::Int, j::Int) where T <: NCRingElement

Return a matrix $b$ with the entries of $a$, where the $i$th and $j$th row are swapped.

source
AbstractAlgebra.swap_cols!Method
swap_cols!(a::MatrixElem{T}, i::Int, j::Int) where T <: NCRingElement

Swap the $i$th and $j$th column of $a$ in place. The function returns the mutated matrix (since matrices are assumed to be mutable in AbstractAlgebra.jl).

source

Swap the rows of M in place. The function returns the mutated matrix (since matrices are assumed to be mutable in AbstractAlgebra.jl).

Concatenation

The following are only available for matrix spaces, not for matrix algebras.

hcat(M::T, N::T) where T <: MatElem

Return the horizontal concatenation of $M$ and $N$. It is assumed that the number of rows of $M$ and $N$ are the same.

vcat(M::T, N::T) where T <: MatElem

Return the vertical concatenation of $M$ and $N$. It is assumed that the number of columns of $M$ and $N$ are the same.

Examples

julia> M = matrix(ZZ, BigInt[1 2 3; 2 3 4; 3 4 5])
 [1   2   3]
 [2   3   4]
 [3   4   5]
@@ -460,14 +460,14 @@
 [7   8   9]
 
 julia> is_symmetric(N)
-false
source
AbstractAlgebra.is_skew_symmetricMethod
is_skew_symmetric(M::MatrixElem)

Return true if the given matrix is skew symmetric with respect to its main diagonal, i.e., transpose(M) == -M, otherwise return false.

Examples

julia> M = matrix(ZZ, [0 -1 -2; 1 0 -3; 2 3 0])
+false
source
AbstractAlgebra.is_skew_symmetricMethod
is_skew_symmetric(M::MatrixElem)

Return true if the given matrix is skew symmetric with respect to its main diagonal, i.e., transpose(M) == -M, otherwise return false.

Examples

julia> M = matrix(ZZ, [0 -1 -2; 1 0 -3; 2 3 0])
 [0   -1   -2]
 [1    0   -3]
 [2    3    0]
 
 julia> is_skew_symmetric(M)
 true
-
source

Powering

AbstractAlgebra.powersMethod
powers(a::Union{NCRingElement, MatElem}, d::Int)

Return an array $M$ of "powers" of a where $M[i + 1] = a^i$ for $i = 0..d$.

Examples

julia> M = ZZ[1 2 3; 2 3 4; 4 5 5]
+
source

Powering

AbstractAlgebra.powersMethod
powers(a::Union{NCRingElement, MatElem}, d::Int)

Return an array $M$ of "powers" of a where $M[i + 1] = a^i$ for $i = 0..d$.

Examples

julia> M = ZZ[1 2 3; 2 3 4; 4 5 5]
 [1   2   3]
 [2   3   4]
 [4   5   5]
@@ -479,7 +479,7 @@
  [17 23 26; 24 33 38; 34 48 57]
  [167 233 273; 242 337 394; 358 497 579]
  [1725 2398 2798; 2492 3465 4044; 3668 5102 5957]
-
source

Gram matrix

AbstractAlgebra.gramMethod
gram(x::MatElem)

Return the Gram matrix of $x$, i.e. if $x$ is an $r\times c$ matrix return the $r\times r$ matrix whose entries $i, j$ are the dot products of the $i$-th and $j$-th rows, respectively.

Examples

julia> R, t = polynomial_ring(QQ, :t)
+
source

Gram matrix

AbstractAlgebra.gramMethod
gram(x::MatElem)

Return the Gram matrix of $x$, i.e. if $x$ is an $r\times c$ matrix return the $r\times r$ matrix whose entries $i, j$ are the dot products of the $i$-th and $j$-th rows, respectively.

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S = matrix_space(R, 3, 3)
@@ -495,7 +495,7 @@
 [2*t^2 + 2*t + 2   t^3 + 2*t^2 + t                   2*t^2 + t - 1]
 [t^3 + 2*t^2 + t       t^4 + 2*t^2                       t^3 + 3*t]
 [  2*t^2 + t - 1         t^3 + 3*t   t^4 + 2*t^3 + 4*t^2 + 6*t + 9]
-
source

Trace

LinearAlgebra.trMethod
tr(x::MatrixElem{T}) where T <: NCRingElement

Return the trace of the matrix $a$, i.e. the sum of the diagonal elements. We require the matrix to be square.

Examples

julia> R, t = polynomial_ring(QQ, :t)
+
source

Trace

LinearAlgebra.trMethod
tr(x::MatrixElem{T}) where T <: NCRingElement

Return the trace of the matrix $a$, i.e. the sum of the diagonal elements. We require the matrix to be square.

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S = matrix_space(R, 3, 3)
@@ -509,7 +509,7 @@
 
 julia> b = tr(A)
 t^2 + 3*t + 2
-
source

Content

AbstractAlgebra.contentMethod
content(x::MatrixElem{T}) where T <: RingElement

Return the content of the matrix $a$, i.e. the greatest common divisor of all its entries, assuming it exists.

Examples

julia> R, t = polynomial_ring(QQ, :t)
+
source

Content

AbstractAlgebra.contentMethod
content(x::MatrixElem{T}) where T <: RingElement

Return the content of the matrix $a$, i.e. the greatest common divisor of all its entries, assuming it exists.

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S = matrix_space(R, 3, 3)
@@ -523,7 +523,7 @@
 
 julia> b = content(A)
 1
-
source

Permutation

Base.:*Method
*(P::Perm, x::MatrixElem{T}) where T <: NCRingElement

Apply the pemutation $P$ to the rows of the matrix $x$ and return the result.

Examples

julia> R, t = polynomial_ring(QQ, :t)
+
source

Permutation

Base.:*Method
*(P::Perm, x::MatrixElem{T}) where T <: NCRingElement

Apply the pemutation $P$ to the rows of the matrix $x$ and return the result.

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S = matrix_space(R, 3, 3)
@@ -545,7 +545,7 @@
 [t + 1       t             1]
 [   -2   t + 2   t^2 + t + 1]
 [  t^2       t             t]
-
source

LU factorisation

LinearAlgebra.luMethod
lu(A::MatrixElem{T}, P = SymmetricGroup(nrows(A))) where {T <: FieldElement}

Return a tuple $r, p, L, U$ consisting of the rank of $A$, a permutation $p$ of $A$ belonging to $P$, a lower triangular matrix $L$ and an upper triangular matrix $U$ such that $p(A) = LU$, where $p(A)$ stands for the matrix whose rows are the given permutation $p$ of the rows of $A$.

source
AbstractAlgebra.ffluMethod
fflu(A::MatrixElem{T}, P = SymmetricGroup(nrows(A))) where {T <: RingElement}

Return a tuple $r, d, p, L, U$ consisting of the rank of $A$, a denominator $d$, a permutation $p$ of $A$ belonging to $P$, a lower triangular matrix $L$ and an upper triangular matrix $U$ such that $p(A) = LDU$, where $p(A)$ stands for the matrix whose rows are the given permutation $p$ of the rows of $A$ and such that $D$ is the diagonal matrix diag$(p_1, p_1p_2, \ldots, p_{n-2}p_{n-1}, p_{n-1}p_n)$ where the $p_i$ are the inverses of the diagonal entries of $L$. The denominator $d$ is set to $\pm \mathrm{det}(S)$ where $S$ is an appropriate submatrix of $A$ ($S = A$ if $A$ is square and nonsingular) and the sign is decided by the parity of the permutation.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
+
source

LU factorisation

LinearAlgebra.luMethod
lu(A::MatrixElem{T}, P = SymmetricGroup(nrows(A))) where {T <: FieldElement}

Return a tuple $r, p, L, U$ consisting of the rank of $A$, a permutation $p$ of $A$ belonging to $P$, a lower triangular matrix $L$ and an upper triangular matrix $U$ such that $p(A) = LU$, where $p(A)$ stands for the matrix whose rows are the given permutation $p$ of the rows of $A$.

source
AbstractAlgebra.ffluMethod
fflu(A::MatrixElem{T}, P = SymmetricGroup(nrows(A))) where {T <: RingElement}

Return a tuple $r, d, p, L, U$ consisting of the rank of $A$, a denominator $d$, a permutation $p$ of $A$ belonging to $P$, a lower triangular matrix $L$ and an upper triangular matrix $U$ such that $p(A) = LDU$, where $p(A)$ stands for the matrix whose rows are the given permutation $p$ of the rows of $A$ and such that $D$ is the diagonal matrix diag$(p_1, p_1p_2, \ldots, p_{n-2}p_{n-1}, p_{n-1}p_n)$ where the $p_i$ are the inverses of the diagonal entries of $L$. The denominator $d$ is set to $\pm \mathrm{det}(S)$ where $S$ is an appropriate submatrix of $A$ ($S = A$ if $A$ is square and nonsingular) and the sign is decided by the parity of the permutation.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> K, = residue_field(R, x^3 + 3x + 1); a = K(x);
@@ -564,7 +564,7 @@
 
 julia> r, d, P, L, U = fflu(A)
 (2, 3*x^2 - 10*x - 8, (1,2), [x^2-2 0 0; 0 3*x^2-10*x-8 0; x^2-2 0 1], [x^2-2 x-1 2*x; 0 3*x^2-10*x-8 -4*x^2-x-2; 0 0 0])
-

Reduced row-echelon form

AbstractAlgebra.rref_rationalMethod
rref_rational(M::MatrixElem{T}) where {T <: RingElement}

Return a tuple $(r, A, d)$ consisting of the rank $r$ of $M$ and a denominator $d$ in the base ring of $M$ and a matrix $A$ such that $A/d$ is the reduced row echelon form of $M$. Note that the denominator is not usually minimal.

source
AbstractAlgebra.rrefMethod
rref(M::MatrixElem{T}) where {T <: FieldElement}

Return a tuple $(r, A)$ consisting of the rank $r$ of $M$ and a reduced row echelon form $A$ of $M$.

source
AbstractAlgebra.is_rrefMethod
is_rref(M::MatrixElem{T}) where {T <: RingElement}

Return true if $M$ is in reduced row echelon form, otherwise return false.

source
AbstractAlgebra.is_rrefMethod
is_rref(M::MatrixElem{T}) where {T <: RingElement}

Return true if $M$ is in reduced row echelon form, otherwise return false.

source
is_rref(M::MatrixElem{T}) where {T <: FieldElement}

Return true if $M$ is in reduced row echelon form, otherwise return false.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
+

Reduced row-echelon form

AbstractAlgebra.rref_rationalMethod
rref_rational(M::MatrixElem{T}) where {T <: RingElement}

Return a tuple $(r, A, d)$ consisting of the rank $r$ of $M$ and a denominator $d$ in the base ring of $M$ and a matrix $A$ such that $A/d$ is the reduced row echelon form of $M$. Note that the denominator is not usually minimal.

source
AbstractAlgebra.rrefMethod
rref(M::MatrixElem{T}) where {T <: FieldElement}

Return a tuple $(r, A)$ consisting of the rank $r$ of $M$ and a reduced row echelon form $A$ of $M$.

source
AbstractAlgebra.is_rrefMethod
is_rref(M::MatrixElem{T}) where {T <: RingElement}

Return true if $M$ is in reduced row echelon form, otherwise return false.

source
AbstractAlgebra.is_rrefMethod
is_rref(M::MatrixElem{T}) where {T <: RingElement}

Return true if $M$ is in reduced row echelon form, otherwise return false.

source
is_rref(M::MatrixElem{T}) where {T <: FieldElement}

Return true if $M$ is in reduced row echelon form, otherwise return false.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> K, = residue_field(R, x^3 + 3x + 1); a = K(x);
@@ -606,10 +606,10 @@
 julia> A = R[x 1; 1 x^2];
 
 julia> d = det(A)
-x^3 - 1
source

Rank

LinearAlgebra.rankMethod
rank(M::MatrixElem{T}) where {T <: RingElement}

Return the rank of the matrix $M$.

Examples

julia> A = QQ[1 2; 3 4];
+x^3 - 1
source

Rank

LinearAlgebra.rankMethod
rank(M::MatrixElem{T}) where {T <: RingElement}

Return the rank of the matrix $M$.

Examples

julia> A = QQ[1 2; 3 4];
 
 julia> d = rank(A)
-2
source

Nilpotency

AbstractAlgebra.is_nilpotentMethod
is_nilpotent(A::MatrixElem{T}) where {T <: RingElement}

Return if A is nilpotent, i.e. if there exists a natural number $k$ such that $A^k = 0$. If A is not square an exception is raised.

source

Minors

AbstractAlgebra.minorsMethod
minors(A::MatElem, k::Int)

Return an array consisting of the k-minors of A.

Examples

julia> A = ZZ[1 2 3; 4 5 6]
+2
source

Nilpotency

AbstractAlgebra.is_nilpotentMethod
is_nilpotent(A::MatrixElem{T}) where {T <: RingElement}

Return if A is nilpotent, i.e. if there exists a natural number $k$ such that $A^k = 0$. If A is not square an exception is raised.

source

Minors

AbstractAlgebra.minorsMethod
minors(A::MatElem, k::Int)

Return an array consisting of the k-minors of A.

Examples

julia> A = ZZ[1 2 3; 4 5 6]
 [1   2   3]
 [4   5   6]
 
@@ -618,12 +618,12 @@
  -3
  -6
  -3
-
source

Exterior power

AbstractAlgebra.exterior_powerMethod
exterior_power(A::MatElem, k::Int) -> MatElem

Return the k-th exterior power of A.

Examples

julia> A = matrix(ZZ, 3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
+
source

Exterior power

AbstractAlgebra.exterior_powerMethod
exterior_power(A::MatElem, k::Int) -> MatElem

Return the k-th exterior power of A.

Examples

julia> A = matrix(ZZ, 3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
 
 julia> exterior_power(A, 2)
 [-3    -6   -3]
 [-6   -12   -6]
-[-3    -6   -3]
source

Pfaffian

AbstractAlgebra.pfaffianMethod
pfaffian(M::MatElem)

Return the Pfaffian of a skew-symmetric matrix M.

source
AbstractAlgebra.pfaffiansMethod
pfaffians(M::MatElem, k::Int)

Return a vector consisting of the k-Pfaffians of a skew-symmetric matrix M.

source

Examples

julia> R, x = polynomial_ring(QQ, ["x$i" for i in 1:6])
+[-3    -6   -3]
source

Pfaffian

AbstractAlgebra.pfaffianMethod
pfaffian(M::MatElem)

Return the Pfaffian of a skew-symmetric matrix M.

source
AbstractAlgebra.pfaffiansMethod
pfaffians(M::MatElem, k::Int)

Return a vector consisting of the k-Pfaffians of a skew-symmetric matrix M.

source

Examples

julia> R, x = polynomial_ring(QQ, ["x$i" for i in 1:6])
 (Multivariate polynomial ring in 6 variables over rationals, AbstractAlgebra.Generic.MPoly{Rational{BigInt}}[x1, x2, x3, x4, x5, x6])
 
 julia> M = R[0 x[1] x[2] x[3]; -x[1] 0 x[4] x[5]; -x[2] -x[4] 0 x[6]; -x[3] -x[5] -x[6] 0]
@@ -643,7 +643,7 @@
  x3
  x5
  x6
- 

Linear solving

See Linear Solving & Kernel

Inverse

Base.invMethod
inv(M::MatrixElem{T}) where {T <: RingElement}

Given a non-singular $n\times n$ matrix over a ring, return an $n\times n$ matrix $X$ such that $MX = I_n$, where $I_n$ is the $n\times n$ identity matrix. If $M$ is not invertible over the base ring an exception is raised.

source
AbstractAlgebra.is_invertible_with_inverseMethod
is_invertible_with_inverse(A::MatrixElem{T}; side::Symbol = :left) where {T <: RingElement}

Given an $n \times m$ matrix $A$ over a ring, return a tuple (flag, B). If side is :right and flag is true, $B$ is a right inverse of $A$ i.e. $A B$ is the $n \times n$ unit matrix. If side is :left and flag is true, $B$ is a left inverse of $A$ i.e. $B A$ is the $m \times m$ unit matrix. If flag is false, no right or left inverse exists.

To get the space of all inverses, note that if $B$ and $C$ are both right inverses, then $A (B - C) = 0$, and similar for left inverses. Hence from one inverse one can find all by making suitable use of kernel.

source
AbstractAlgebra.is_invertibleMethod
is_invertible(A::MatrixElem{T}) where {T <: RingElement}

Return true if a given square matrix is invertible, false otherwise. If the inverse should also be computed, use is_invertible_with_inverse.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
+ 

Linear solving

See Linear Solving & Kernel

Inverse

Base.invMethod
inv(M::MatrixElem{T}) where {T <: RingElement}

Given a non-singular $n\times n$ matrix over a ring, return an $n\times n$ matrix $X$ such that $MX = I_n$, where $I_n$ is the $n\times n$ identity matrix. If $M$ is not invertible over the base ring an exception is raised.

source
AbstractAlgebra.is_invertible_with_inverseMethod
is_invertible_with_inverse(A::MatrixElem{T}; side::Symbol = :left) where {T <: RingElement}

Given an $n \times m$ matrix $A$ over a ring, return a tuple (flag, B). If side is :right and flag is true, $B$ is a right inverse of $A$ i.e. $A B$ is the $n \times n$ unit matrix. If side is :left and flag is true, $B$ is a left inverse of $A$ i.e. $B A$ is the $m \times m$ unit matrix. If flag is false, no right or left inverse exists.

To get the space of all inverses, note that if $B$ and $C$ are both right inverses, then $A (B - C) = 0$, and similar for left inverses. Hence from one inverse one can find all by making suitable use of kernel.

source
AbstractAlgebra.is_invertibleMethod
is_invertible(A::MatrixElem{T}) where {T <: RingElement}

Return true if a given square matrix is invertible, false otherwise. If the inverse should also be computed, use is_invertible_with_inverse.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> K, = residue_field(R, x^3 + 3x + 1); a = K(x);
@@ -699,7 +699,7 @@
 [-10*x^2 + 10*x + 20   -20*x^2 + 70*x - 25   150*x^2 - 140*x - 85   105*x^2 + 90*x - 50]
 
 julia> n, N = nullspace(M)
-(2, [1320*x^4-330*x^2-1320*x-1320 1056*x^4+1254*x^3+1848*x^2-66*x-330; -660*x^4+1320*x^3+1188*x^2-1848*x-1056 -528*x^4+132*x^3+1584*x^2+660*x-264; 396*x^3-396*x^2-792*x 0; 0 396*x^3-396*x^2-792*x])
source
nullspace(M::MatElem{T}) where {T <: FieldElement}

Return a tuple $(\nu, N)$ consisting of the nullity $\nu$ of $M$ and a basis $N$ (consisting of column vectors) for the right nullspace of $M$, i.e. such that $MN$ is the zero matrix. If $M$ is an $m\times n$ matrix $N$ will be an $n\times \nu$ matrix.

source

Hessenberg form

LinearAlgebra.hessenbergMethod
hessenberg(A::MatrixElem{T}) where {T <: RingElement}

Return the Hessenberg form of $M$, i.e. an upper Hessenberg matrix which is similar to $M$. The upper Hessenberg form has nonzero entries above and on the diagonal and in the diagonal line immediately below the diagonal.

source
AbstractAlgebra.is_hessenbergMethod
is_hessenberg(A::MatrixElem{T}) where {T <: RingElement}

Return true if $M$ is in Hessenberg form, otherwise returns false.

source

Examples

julia> R, = residue_ring(ZZ, 7);
+(2, [1320*x^4-330*x^2-1320*x-1320 1056*x^4+1254*x^3+1848*x^2-66*x-330; -660*x^4+1320*x^3+1188*x^2-1848*x-1056 -528*x^4+132*x^3+1584*x^2+660*x-264; 396*x^3-396*x^2-792*x 0; 0 396*x^3-396*x^2-792*x])
source
nullspace(M::MatElem{T}) where {T <: FieldElement}

Return a tuple $(\nu, N)$ consisting of the nullity $\nu$ of $M$ and a basis $N$ (consisting of column vectors) for the right nullspace of $M$, i.e. such that $MN$ is the zero matrix. If $M$ is an $m\times n$ matrix $N$ will be an $n\times \nu$ matrix.

source

Hessenberg form

LinearAlgebra.hessenbergMethod
hessenberg(A::MatrixElem{T}) where {T <: RingElement}

Return the Hessenberg form of $M$, i.e. an upper Hessenberg matrix which is similar to $M$. The upper Hessenberg form has nonzero entries above and on the diagonal and in the diagonal line immediately below the diagonal.

source
AbstractAlgebra.is_hessenbergMethod
is_hessenberg(A::MatrixElem{T}) where {T <: RingElement}

Return true if $M$ is in Hessenberg form, otherwise returns false.

source

Examples

julia> R, = residue_ring(ZZ, 7);
 
 julia> S = matrix_space(R, 4, 4)
 Matrix space of 4 rows and 4 columns
@@ -741,7 +741,7 @@
 y^4 + 2*y^2 + 6*y + 2
 
 julia> A = charpoly(M)
-x^4 + 2*x^2 + 6*x + 2
source

Minimal polynomial

AbstractAlgebra.minpolyMethod
minpoly(M::MatElem{T}, charpoly_only::Bool = false) where {T <: RingElement}
+x^4 + 2*x^2 + 6*x + 2
source

Minimal polynomial

AbstractAlgebra.minpolyMethod
minpoly(M::MatElem{T}, charpoly_only::Bool = false) where {T <: RingElement}
 minpoly(S::PolyRing{T}, M::MatElem{T}, charpoly_only::Bool = false) where {T <: RingElement}

Return the minimal polynomial $p$ of the square matrix $M$. If a polynomial ring $S$ over the same base ring as $Y$ is supplied, the resulting polynomial is an element of it.

Examples

julia> R = GF(13)
 Finite field F_13
 
@@ -760,7 +760,7 @@
 
 julia> A = minpoly(M)
 x^2 + 10*x
-
source

Transforms

AbstractAlgebra.similarity!Method
similarity!(A::MatrixElem{T}, r::Int, d::T) where {T <: RingElement}

Applies a similarity transform to the $n\times n$ matrix $M$ in-place. Let $P$ be the $n\times n$ identity matrix that has had all zero entries of row $r$ replaced with $d$, then the transform applied is equivalent to $M = P^{-1}MP$. We require $M$ to be a square matrix. A similarity transform preserves the minimal and characteristic polynomials of a matrix.

Examples

julia> R, = residue_ring(ZZ, 7);
+
source

Transforms

AbstractAlgebra.similarity!Method
similarity!(A::MatrixElem{T}, r::Int, d::T) where {T <: RingElement}

Applies a similarity transform to the $n\times n$ matrix $M$ in-place. Let $P$ be the $n\times n$ identity matrix that has had all zero entries of row $r$ replaced with $d$, then the transform applied is equivalent to $M = P^{-1}MP$. We require $M$ to be a square matrix. A similarity transform preserves the minimal and characteristic polynomials of a matrix.

Examples

julia> R, = residue_ring(ZZ, 7);
 
 julia> S = matrix_space(R, 4, 4)
 Matrix space of 4 rows and 4 columns
@@ -774,7 +774,7 @@
 [1   1   3   5]
 
 julia> similarity!(M, 1, R(3))
-
source

Hermite normal form

AbstractAlgebra.hnfMethod
hnf(A::MatrixElem{T}) where {T <: RingElement}

Return the upper right row Hermite normal form of $A$.

source
AbstractAlgebra.hnf_with_transformMethod
hnf_with_transform(A)

Return the tuple $H, U$ consisting of the upper right row Hermite normal form $H$ of $A$ together with invertible matrix $U$ such that $UA = H$.

source
AbstractAlgebra.is_hnfMethod
is_hnf(M::MatrixElem{T}) where T <: RingElement

Return true if the matrix is in Hermite normal form.

source

Examples

julia> A = matrix(ZZ, [2 3 -1; 3 5 7; 11 1 12])
+
source

Hermite normal form

AbstractAlgebra.hnfMethod
hnf(A::MatrixElem{T}) where {T <: RingElement}

Return the upper right row Hermite normal form of $A$.

source
AbstractAlgebra.hnf_with_transformMethod
hnf_with_transform(A)

Return the tuple $H, U$ consisting of the upper right row Hermite normal form $H$ of $A$ together with invertible matrix $U$ such that $UA = H$.

source
AbstractAlgebra.is_hnfMethod
is_hnf(M::MatrixElem{T}) where T <: RingElement

Return true if the matrix is in Hermite normal form.

source

Examples

julia> A = matrix(ZZ, [2 3 -1; 3 5 7; 11 1 12])
 [ 2   3   -1]
 [ 3   5    7]
 [11   1   12]
@@ -793,7 +793,7 @@
 julia> U*A
 [1   0   255]
 [0   1    17]
-[0   0   281]

Smith normal form

AbstractAlgebra.is_snfMethod
is_snf(A::MatrixElem{T}) where T <: RingElement

Return true if $A$ is in Smith Normal Form.

source
AbstractAlgebra.snfMethod
snf(A::MatrixElem{T}) where {T <: RingElement}

Return the Smith normal form of $A$.

source
AbstractAlgebra.snf_with_transformMethod
snf_with_transform(A)

Return the tuple $S, T, U$ consisting of the Smith normal form $S$ of $A$ together with invertible matrices $T$ and $U$ such that $TAU = S$.

source

Examples

julia> A = matrix(ZZ, [2 3 -1; 3 5 7; 11 1 12])
+[0   0   281]

Smith normal form

AbstractAlgebra.is_snfMethod
is_snf(A::MatrixElem{T}) where T <: RingElement

Return true if $A$ is in Smith Normal Form.

source
AbstractAlgebra.snfMethod
snf(A::MatrixElem{T}) where {T <: RingElement}

Return the Smith normal form of $A$.

source
AbstractAlgebra.snf_with_transformMethod
snf_with_transform(A)

Return the tuple $S, T, U$ consisting of the Smith normal form $S$ of $A$ together with invertible matrices $T$ and $U$ such that $TAU = S$.

source

Examples

julia> A = matrix(ZZ, [2 3 -1; 3 5 7; 11 1 12])
 [ 2   3   -1]
 [ 3   5    7]
 [11   1   12]
@@ -809,7 +809,7 @@
 julia> T*A*U
 [1   0     0]
 [0   1     0]
-[0   0   281]

(Weak) Popov form

AbstractAlgebra.jl provides algorithms for computing the (weak) Popov of a matrix with entries in a univariate polynomial ring over a field.

AbstractAlgebra.is_weak_popovMethod
is_weak_popov(P::MatrixElem{T}, rank::Int) where T <: PolyRingElem

Return true if $P$ is a matrix in weak Popov form of the given rank.

source
AbstractAlgebra.weak_popovMethod
weak_popov(A::MatElem{T}) where {T <: PolyRingElem}

Return the weak Popov form of $A$.

source
AbstractAlgebra.weak_popov_with_transformMethod
weak_popov_with_transform(A::MatElem{T}) where {T <: PolyRingElem}

Compute a tuple $(P, U)$ where $P$ is the weak Popov form of $A$ and $U$ is a transformation matrix so that $P = UA$.

source
AbstractAlgebra.popovMethod
popov(A::MatElem{T}) where {T <: PolyRingElem}

Return the Popov form of $A$.

source
AbstractAlgebra.popov_with_transformMethod
popov_with_transform(A::MatElem{T}) where {T <: PolyRingElem}

Compute a tuple $(P, U)$ where $P$ is the Popov form of $A$ and $U$ is a transformation matrix so that $P = UA$.

source

Examples

julia> R, x = polynomial_ring(QQ, :x);
+[0   0   281]

(Weak) Popov form

AbstractAlgebra.jl provides algorithms for computing the (weak) Popov of a matrix with entries in a univariate polynomial ring over a field.

AbstractAlgebra.is_weak_popovMethod
is_weak_popov(P::MatrixElem{T}, rank::Int) where T <: PolyRingElem

Return true if $P$ is a matrix in weak Popov form of the given rank.

source
AbstractAlgebra.weak_popovMethod
weak_popov(A::MatElem{T}) where {T <: PolyRingElem}

Return the weak Popov form of $A$.

source
AbstractAlgebra.weak_popov_with_transformMethod
weak_popov_with_transform(A::MatElem{T}) where {T <: PolyRingElem}

Compute a tuple $(P, U)$ where $P$ is the weak Popov form of $A$ and $U$ is a transformation matrix so that $P = UA$.

source
AbstractAlgebra.popovMethod
popov(A::MatElem{T}) where {T <: PolyRingElem}

Return the Popov form of $A$.

source
AbstractAlgebra.popov_with_transformMethod
popov_with_transform(A::MatElem{T}) where {T <: PolyRingElem}

Compute a tuple $(P, U)$ where $P$ is the Popov form of $A$ and $U$ is a transformation matrix so that $P = UA$.

source

Examples

julia> R, x = polynomial_ring(QQ, :x);
 
 julia> A = matrix(R, map(R, Any[1 2 3 x; x 2*x 3*x x^2; x x^2+1 x^3+x^2 x^4+x^2+1]))
 [1         2           3               x]
@@ -827,4 +827,4 @@
 julia> U*A
 [   1                        2                    3   x]
 [   0                        0                    0   0]
-[-x^3   -2*x^3 + x^2 - 2*x + 1   -2*x^3 + x^2 - 3*x   1]
+[-x^3 -2*x^3 + x^2 - 2*x + 1 -2*x^3 + x^2 - 3*x 1] diff --git a/dev/matrix_algebras/index.html b/dev/matrix_algebras/index.html index 808f28933..cfb8e2843 100644 --- a/dev/matrix_algebras/index.html +++ b/dev/matrix_algebras/index.html @@ -20,10 +20,10 @@ [11 0 0] [ 0 11 0] [ 0 0 11] -

Matrix algebra element constructors

The following additional constructors are provided for constructing various kinds of matrices in a matrix algebra.

AbstractAlgebra.identity_matrixMethod
identity_matrix(M::MatElem{T}) where T <: NCRingElement

Construct the identity matrix in the same matrix space as M, i.e. with ones down the diagonal and zeroes elsewhere. M must be square. This is an alias for one(M).

source
identity_matrix(M::MatRingElem{T}) where T <: RingElement

Return the identity matrix over the same base ring as $M$ and with the same dimensions.

source

Examples

S = matrix_ring(ZZ, 2)
+

Matrix algebra element constructors

The following additional constructors are provided for constructing various kinds of matrices in a matrix algebra.

AbstractAlgebra.identity_matrixMethod
identity_matrix(M::MatElem{T}) where T <: NCRingElement

Construct the identity matrix in the same matrix space as M, i.e. with ones down the diagonal and zeroes elsewhere. M must be square. This is an alias for one(M).

source
identity_matrix(M::MatRingElem{T}) where T <: RingElement

Return the identity matrix over the same base ring as $M$ and with the same dimensions.

source

Examples

S = matrix_ring(ZZ, 2)
 M = zero(S)
 
-P = identity_matrix(M)

Matrix algebra functionality provided by AbstractAlgebra.jl

Most of the generic matrix functionality described in the generic matrix section of the documentation is available for both matrix spaces and matrix algebras. Exceptions include functions that do not return or accept square matrices or which cannot specify a parent. Such functions include solve and nullspace which can't be provided for matrix algebras.

In addition to the functionality described for matrix spaces, matrix algebras support all noncommutative ring operations, and matrix algebras can be used as a base ring for other generic constructs that accept a noncommutative base ring (NCRing).

In this section we describe functionality provided for matrix algebras only.

Basic matrix functionality

As well as the Ring and Matrix interfaces, the following functions are provided to manipulate matrices.

AbstractAlgebra.degreeMethod
degree(a::MatRingElem{T}) where T <: RingElement

Return the degree $n$ of the given matrix algebra.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
+P = identity_matrix(M)

Matrix algebra functionality provided by AbstractAlgebra.jl

Most of the generic matrix functionality described in the generic matrix section of the documentation is available for both matrix spaces and matrix algebras. Exceptions include functions that do not return or accept square matrices or which cannot specify a parent. Such functions include solve and nullspace which can't be provided for matrix algebras.

In addition to the functionality described for matrix spaces, matrix algebras support all noncommutative ring operations, and matrix algebras can be used as a base ring for other generic constructs that accept a noncommutative base ring (NCRing).

In this section we describe functionality provided for matrix algebras only.

Basic matrix functionality

As well as the Ring and Matrix interfaces, the following functions are provided to manipulate matrices.

AbstractAlgebra.degreeMethod
degree(a::MatRingElem{T}) where T <: RingElement

Return the degree $n$ of the given matrix algebra.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S = matrix_ring(R, 3)
@@ -37,4 +37,4 @@
 
 julia> n = degree(A)
 3
-
+ diff --git a/dev/matrix_interface/index.html b/dev/matrix_interface/index.html index eba75c71d..e8c247845 100644 --- a/dev/matrix_interface/index.html +++ b/dev/matrix_interface/index.html @@ -13,4 +13,4 @@ zero(x::MyMat{T}, R::Ring=base_ring(x)) where T <: RingElem

Construct the matrix with the same dimensions as the given matrix, and the same base ring unless explicitly specified.

similar(x::MyMat{T}, R::Ring, r::Int, c::Int) where T <: RingElem
 similar(x::MyMat{T}, r::Int, c::Int) where T <: RingElem
 zero(x::MyMat{T}, R::Ring, r::Int, c::Int) where T <: RingElem
-zero(x::MyMat{T}, r::Int, c::Int) where T <: RingElem

Construct the $r\times c$ matrix with R as base ring (which defaults to the base ring of the the given matrix). If $x$ belongs to a matrix algebra and $r \neq c$, an exception is raised, and it's also possible to specify only one Int as the order (e.g. similar(x, n)).

Custom matrices and rings may choose which specific matrix type is best-suited to return for the given ring and dimensionality. If they do not specialize these functions, the default is a Generic.MatSpaceElem matrix, or Generic.MatRingElem for matrix algebras. The default implementation of zero calls out to similar, so it's generally sufficient to specialize only similar. For both similar and zero, only the most general method has to be implemented (e.g. similar(x::MyMat, R::Ring, r::Int, c::Int), as all other methods (which have defaults) call out to this more general method.

Base.isassigned(M::MyMat, i, j)

Test whether the given matrix has a value associated with indices i and j. It is recommended to overload this method for custom matrices.

Optional symmetry test

is_symmetric(a::MatrixElem)

Return true if the given matrix is symmetric with respect to its main diagonal, otherwise return false.

+zero(x::MyMat{T}, r::Int, c::Int) where T <: RingElem

Construct the $r\times c$ matrix with R as base ring (which defaults to the base ring of the the given matrix). If $x$ belongs to a matrix algebra and $r \neq c$, an exception is raised, and it's also possible to specify only one Int as the order (e.g. similar(x, n)).

Custom matrices and rings may choose which specific matrix type is best-suited to return for the given ring and dimensionality. If they do not specialize these functions, the default is a Generic.MatSpaceElem matrix, or Generic.MatRingElem for matrix algebras. The default implementation of zero calls out to similar, so it's generally sufficient to specialize only similar. For both similar and zero, only the most general method has to be implemented (e.g. similar(x::MyMat, R::Ring, r::Int, c::Int), as all other methods (which have defaults) call out to this more general method.

Base.isassigned(M::MyMat, i, j)

Test whether the given matrix has a value associated with indices i and j. It is recommended to overload this method for custom matrices.

Optional symmetry test

is_symmetric(a::MatrixElem)

Return true if the given matrix is symmetric with respect to its main diagonal, otherwise return false.

diff --git a/dev/matrix_introduction/index.html b/dev/matrix_introduction/index.html index b9cfab146..aeaf59e7f 100644 --- a/dev/matrix_introduction/index.html +++ b/dev/matrix_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

AbstractAlgebra provides matrix spaces (mxn matrices) and matrix algebras (nxn matrices) over a ring. Whilst both types of matrix provide matrix multiplication for matrices whose dimensions are compatible for multiplication, only the latter kind of matrices form rings in the system.

Matrix spaces provide a large number of linear algebra operations, including linear solving, elementary row operations, various canonical forms. The system also provides characteristic and minimal polynomial computations, LU decomposition, determinant, matrix inverse, kernel computations.

There is also code for computation of the Hermite and Smith normal forms over Euclidean domains and Popov form for matrices over polynomial rings over a field.

Most of this generic functionality is provided for arbitrary matrix types that satisfy the AbstractAlgebra matrix interface.

+Introduction · AbstractAlgebra.jl

Introduction

AbstractAlgebra provides matrix spaces (mxn matrices) and matrix algebras (nxn matrices) over a ring. Whilst both types of matrix provide matrix multiplication for matrices whose dimensions are compatible for multiplication, only the latter kind of matrices form rings in the system.

Matrix spaces provide a large number of linear algebra operations, including linear solving, elementary row operations, various canonical forms. The system also provides characteristic and minimal polynomial computations, LU decomposition, determinant, matrix inverse, kernel computations.

There is also code for computation of the Hermite and Smith normal forms over Euclidean domains and Popov form for matrices over polynomial rings over a field.

Most of this generic functionality is provided for arbitrary matrix types that satisfy the AbstractAlgebra matrix interface.

diff --git a/dev/misc/index.html b/dev/misc/index.html index 06404144b..da211d9e7 100644 --- a/dev/misc/index.html +++ b/dev/misc/index.html @@ -1,5 +1,5 @@ -Miscellaneous · AbstractAlgebra.jl

Miscellaneous

Printing options

AbstractAlgebra supports printing to LaTeX using the MIME type "text/latex". To enable LaTeX rendering in Jupyter notebooks and query for the current state, use the following functions:

Updating the type diagrams

Updating the diagrams of the documentation can be done by modifying and running the script docs/create_type_diagrams.jl. Note that this requires the package Kroki.

Attributes

Often it is desirable to have a flexible way to attach additional data to mathematical structures such as groups, rings, fields, etc. beyond what the original implementation covers. To facilitate this, we provide an attributes system: for objects of suitable types, one may use set_attribute! to attach key-value pairs to the object, and query them using has_attribute, get_attribute and get_attribute!.

Attributes are supported for all singletons (i.e., instances of an empty struct type), as well as for instances of mutable struct type for which attribute storage was enabled. There are two ways to enable attribute storage for such types:

  1. By applying @attributes to a mutable struct declaration, storage is reserved inside that struct type itself (this increases the size of each struct by 8 bytes if no attributes are set).
  2. By applying @attributes to the name of a mutable struct type, methods are installed which store attributes to instances of the type in a WeakKeyDict outside the struct.
AbstractAlgebra.@attributesMacro
@attributes typedef

This is a helper macro that ensures that there is storage for attributes in the type declared in the expression typedef, which must be either a mutable struct definition expression, or the name of a mutable struct type.

The latter variant is useful to enable attribute storage for types defined in other packages. Note that @attributes is idempotent: when applied to a type for which attribute storage is already available, it does nothing.

For singleton types, attribute storage is also supported, and in fact always enabled. Thus it is not necessary to apply this macro to such a type.

Note

When applied to a struct definition this macro adds a new field to the struct. For structs without constructor, this will change the signature of the default inner constructor, which requires explicit values for every field, including the attribute storage field this macro adds. Usually it is thus preferable to add an explicit default constructor, as in the example below.

Examples

Applying the macro to a struct definition results in internal storage of the attributes:

julia> @attributes mutable struct MyGroup
+Miscellaneous · AbstractAlgebra.jl

Miscellaneous

Printing options

AbstractAlgebra supports printing to LaTeX using the MIME type "text/latex". To enable LaTeX rendering in Jupyter notebooks and query for the current state, use the following functions:

Updating the type diagrams

Updating the diagrams of the documentation can be done by modifying and running the script docs/create_type_diagrams.jl. Note that this requires the package Kroki.

Attributes

Often it is desirable to have a flexible way to attach additional data to mathematical structures such as groups, rings, fields, etc. beyond what the original implementation covers. To facilitate this, we provide an attributes system: for objects of suitable types, one may use set_attribute! to attach key-value pairs to the object, and query them using has_attribute, get_attribute and get_attribute!.

Attributes are supported for all singletons (i.e., instances of an empty struct type), as well as for instances of mutable struct type for which attribute storage was enabled. There are two ways to enable attribute storage for such types:

  1. By applying @attributes to a mutable struct declaration, storage is reserved inside that struct type itself (this increases the size of each struct by 8 bytes if no attributes are set).
  2. By applying @attributes to the name of a mutable struct type, methods are installed which store attributes to instances of the type in a WeakKeyDict outside the struct.
AbstractAlgebra.@attributesMacro
@attributes typedef

This is a helper macro that ensures that there is storage for attributes in the type declared in the expression typedef, which must be either a mutable struct definition expression, or the name of a mutable struct type.

The latter variant is useful to enable attribute storage for types defined in other packages. Note that @attributes is idempotent: when applied to a type for which attribute storage is already available, it does nothing.

For singleton types, attribute storage is also supported, and in fact always enabled. Thus it is not necessary to apply this macro to such a type.

Note

When applied to a struct definition this macro adds a new field to the struct. For structs without constructor, this will change the signature of the default inner constructor, which requires explicit values for every field, including the attribute storage field this macro adds. Usually it is thus preferable to add an explicit default constructor, as in the example below.

Examples

Applying the macro to a struct definition results in internal storage of the attributes:

julia> @attributes mutable struct MyGroup
            order::Int
            MyGroup(order::Int) = new(order)
        end
@@ -23,7 +23,7 @@
 julia> set_attribute!(G, :isfinite, :true)
 
 julia> get_attribute(G, :isfinite)
-true
source
AbstractAlgebra.@attrMacro
@attr RetType funcdef

This macro is applied to the definition of a unary function, and enables caching ("memoization") of its return values based on the argument. This assumes the argument supports attribute storing (see @attributes) via get_attribute!.

The name of the function is used as name for the underlying attribute.

Effectively, this turns code like this:

@attr RetType function myattr(obj::Foo)
+true
source
AbstractAlgebra.@attrMacro
@attr RetType funcdef

This macro is applied to the definition of a unary function, and enables caching ("memoization") of its return values based on the argument. This assumes the argument supports attribute storing (see @attributes) via get_attribute!.

The name of the function is used as name for the underlying attribute.

Effectively, this turns code like this:

@attr RetType function myattr(obj::Foo)
    # ... expensive computation
    return result
 end

into something essentially equivalent to this:

function myattr(obj::Foo)
@@ -49,13 +49,13 @@
 
 julia> myattr(obj) # second time uses the cached result
 120
-
source
AbstractAlgebra.get_attributeFunction
get_attribute(f::Function, G::Any, attr::Symbol)

Return the value stored for the attribute attr, or if no value has been set, return f().

This is intended to be called using do block syntax.

get_attribute(obj, attr) do
+
source
AbstractAlgebra.get_attributeFunction
get_attribute(f::Function, G::Any, attr::Symbol)

Return the value stored for the attribute attr, or if no value has been set, return f().

This is intended to be called using do block syntax.

get_attribute(obj, attr) do
     # default value calculated here if needed
     ...
-end
source
get_attribute(G::Any, attr::Symbol, default::Any = nothing)

Return the value stored for the attribute attr, or if no value has been set, return default.

source
AbstractAlgebra.get_attribute!Function
get_attribute!(f::Function, G::Any, attr::Symbol)

Return the value stored for the attribute attr of G, or if no value has been set, store key => f() and return f().

This is intended to be called using do block syntax.

get_attribute!(obj, attr) do
+end
source
get_attribute(G::Any, attr::Symbol, default::Any = nothing)

Return the value stored for the attribute attr, or if no value has been set, return default.

source
AbstractAlgebra.get_attribute!Function
get_attribute!(f::Function, G::Any, attr::Symbol)

Return the value stored for the attribute attr of G, or if no value has been set, store key => f() and return f().

This is intended to be called using do block syntax.

get_attribute!(obj, attr) do
     # default value calculated here if needed
     ...
-end
source
get_attribute!(G::Any, attr::Symbol, default::Any)

Return the value stored for the attribute attr of G, or if no value has been set, store key => default, and return default.

source
AbstractAlgebra.set_attribute!Function
set_attribute!(G::Any, data::Pair{Symbol, <:Any}...)

Attach the given sequence of key=>value pairs as attributes of G.

source
set_attribute!(G::Any, attr::Symbol, value::Any)

Attach the given value as attribute attr of G.

source

Advanced printing

Self-given names

We provide macros @show_name, @show_special and @show_special_elem to change the way certain objects are printed.

In compact and terse printing mode, @show_name tries to determine a suitable name to print instead of the object (see AbstractAlgebra.get_name).

@show_special checks if an attribute :show is present. If so, it has to be a function taking IO, optionally a MIME-type, and the object. This is then called instead of the usual show function.

Similarly, @show_special_elem checks if an attribute :show_elem is present in the object's parent. The semantics are the same as for @show_special.

All are supposed to be used within the usual show function, where @show_special_elem is only relevant for element types of algebraic structures.

@attributes MyObj
+end
source
get_attribute!(G::Any, attr::Symbol, default::Any)

Return the value stored for the attribute attr of G, or if no value has been set, store key => default, and return default.

source
AbstractAlgebra.set_attribute!Function
set_attribute!(G::Any, data::Pair{Symbol, <:Any}...)

Attach the given sequence of key=>value pairs as attributes of G.

source
set_attribute!(G::Any, attr::Symbol, value::Any)

Attach the given value as attribute attr of G.

source

Advanced printing

Self-given names

We provide macros @show_name, @show_special and @show_special_elem to change the way certain objects are printed.

In compact and terse printing mode, @show_name tries to determine a suitable name to print instead of the object (see AbstractAlgebra.get_name).

@show_special checks if an attribute :show is present. If so, it has to be a function taking IO, optionally a MIME-type, and the object. This is then called instead of the usual show function.

Similarly, @show_special_elem checks if an attribute :show_elem is present in the object's parent. The semantics are the same as for @show_special.

All are supposed to be used within the usual show function, where @show_special_elem is only relevant for element types of algebraic structures.

@attributes MyObj
 
 function show(io::IO, A::MyObj)
    @show_name(io, A)
@@ -94,7 +94,7 @@
 => The One True Ring <=
 
 julia> R   # show for R uses @show_special, so we can observe the effect directly
-=> The One True Ring <=
source
@show_special(io::IO, mime, obj)

If the obj has a show attribute, this gets called with io, mime and obj (if applicable) and io and obj otherwise, and returns from the current scope. Otherwise, does nothing.

If obj does not have attribute storage available, this macro does nothing.

It is supposed to be used at the start of show methods as shown in the documentation.

Examples

julia> R = @polynomial_ring(QQ, :x; cached=false)
+=> The One True Ring <=
source
@show_special(io::IO, mime, obj)

If the obj has a show attribute, this gets called with io, mime and obj (if applicable) and io and obj otherwise, and returns from the current scope. Otherwise, does nothing.

If obj does not have attribute storage available, this macro does nothing.

It is supposed to be used at the start of show methods as shown in the documentation.

Examples

julia> R = @polynomial_ring(QQ, :x; cached=false)
 Univariate polynomial ring in x over rationals
 
 julia> AbstractAlgebra.@show_special(stdout, MIME"text/plain"(), R)
@@ -109,7 +109,7 @@
 => The One True Ring with mime type text/plain <=
 
 julia> R   # show for R uses @show_special, so we can observe the effect directly
-=> The One True Ring <=
source
AbstractAlgebra.PrettyPrinting.@show_special_elemMacro
@show_special_elem(io::IO, obj)

If the parent of obj has a show_elem attribute, this gets called with io and obj and returns from the current scope. Otherwise, does nothing.

If parent(obj) does not have attribute storage available, this macro does nothing.

It is supposed to be used at the start of show methods as shown in the documentation.

Examples

julia> R = @polynomial_ring(QQ, :x; cached=false)
+=> The One True Ring <=
source
AbstractAlgebra.PrettyPrinting.@show_special_elemMacro
@show_special_elem(io::IO, obj)

If the parent of obj has a show_elem attribute, this gets called with io and obj and returns from the current scope. Otherwise, does nothing.

If parent(obj) does not have attribute storage available, this macro does nothing.

It is supposed to be used at the start of show methods as shown in the documentation.

Examples

julia> R = @polynomial_ring(QQ, :x; cached=false)
 Univariate polynomial ring in x over rationals
 
 julia> AbstractAlgebra.@show_special_elem(stdout, x)
@@ -120,7 +120,7 @@
 => x <=
 
 julia> x   # show for x does not uses @show_special_elem, so x prints as before
-x
source
@show_special_elem(io::IO, mime, obj)

If the parent of obj has a show_elem attribute, this gets called with io, mime and obj (if applicable) and io and obj otherwise, and returns from the current scope. Otherwise, does nothing.

If parent(obj) does not have attribute storage available, this macro does nothing.

It is supposed to be used at the start of show methods as shown in the documentation.

Examples

julia> R = @polynomial_ring(QQ, :x; cached=false)
+x
source
@show_special_elem(io::IO, mime, obj)

If the parent of obj has a show_elem attribute, this gets called with io, mime and obj (if applicable) and io and obj otherwise, and returns from the current scope. Otherwise, does nothing.

If parent(obj) does not have attribute storage available, this macro does nothing.

It is supposed to be used at the start of show methods as shown in the documentation.

Examples

julia> R = @polynomial_ring(QQ, :x; cached=false)
 Univariate polynomial ring in x over rationals
 
 julia> AbstractAlgebra.@show_special_elem(stdout, MIME"text/plain"(), x)
@@ -131,7 +131,7 @@
 => x with mime type text/plain <=
 
 julia> x   # show for x does not uses @show_special_elem, so x prints as before
-x
source
AbstractAlgebra.PrettyPrinting.@show_nameMacro
@show_name(io::IO, obj)

If either is_terse(io) is true or property :compact is set to true for io (see IOContext), print the name get_name(obj) of the object obj to the io stream, then return from the current scope. Otherwise, do nothing.

It is supposed to be used at the start of show methods as shown in the documentation.

source
AbstractAlgebra.PrettyPrinting.set_name!Function
set_name!(obj, name::String; override::Bool=true)

Sets the name of the object obj to name. This name is used for printing using AbstractAlgebra.@show_name. If override is false, the name is only set if there is no name already set.

This function errors if obj does not support attribute storage.

source
set_name!(obj; override::Bool=true)

Sets the name of the object obj to the name of a variable in global (Main module) namespace with value bound to the object obj, if such a variable exists (see AbstractAlgebra.PrettyPrinting.find_name). This name is used for printing using AbstractAlgebra.@show_name. If override is false, the name is only set if there is no name already set.

This function errors if obj does not support attribute storage.

source
AbstractAlgebra.PrettyPrinting.find_nameFunction
find_name(obj, M = Main; all::Bool = false) -> Union{String,Nothing}

Return name of a variable in M's namespace with value bound to the object obj, or nothing if no such variable exists. If all is true, private and non-exported variables are also searched.

Note

If the object is stored in several variables, the first one will be used, but a name returned once is kept until the variable no longer contains this object.

For this to work in doctests, one should call AbstractAlgebra.set_current_module(@__MODULE__) in the value argument of Documenter.DocMeta.setdocmeta! and keep the default value of M = Main here.

Warning

This function should not be used directly, but rather through AbstractAlgebra.get_name.

source

Indentation and Decapitalization

To facilitate printing of nested mathematical structures, we provide a modified IOCustom object, that supports indentation and decapitalization.

Example

We illustrate this with an example

struct A{T}
+x
source
AbstractAlgebra.PrettyPrinting.@show_nameMacro
@show_name(io::IO, obj)

If either is_terse(io) is true or property :compact is set to true for io (see IOContext), print the name get_name(obj) of the object obj to the io stream, then return from the current scope. Otherwise, do nothing.

It is supposed to be used at the start of show methods as shown in the documentation.

source
AbstractAlgebra.PrettyPrinting.set_name!Function
set_name!(obj, name::String; override::Bool=true)

Sets the name of the object obj to name. This name is used for printing using AbstractAlgebra.@show_name. If override is false, the name is only set if there is no name already set.

This function errors if obj does not support attribute storage.

source
set_name!(obj; override::Bool=true)

Sets the name of the object obj to the name of a variable in global (Main module) namespace with value bound to the object obj, if such a variable exists (see AbstractAlgebra.PrettyPrinting.find_name). This name is used for printing using AbstractAlgebra.@show_name. If override is false, the name is only set if there is no name already set.

This function errors if obj does not support attribute storage.

source
AbstractAlgebra.PrettyPrinting.find_nameFunction
find_name(obj, M = Main; all::Bool = false) -> Union{String,Nothing}

Return name of a variable in M's namespace with value bound to the object obj, or nothing if no such variable exists. If all is true, private and non-exported variables are also searched.

Note

If the object is stored in several variables, the first one will be used, but a name returned once is kept until the variable no longer contains this object.

For this to work in doctests, one should call AbstractAlgebra.set_current_module(@__MODULE__) in the value argument of Documenter.DocMeta.setdocmeta! and keep the default value of M = Main here.

Warning

This function should not be used directly, but rather through AbstractAlgebra.get_name.

source

Indentation and Decapitalization

To facilitate printing of nested mathematical structures, we provide a modified IOCustom object, that supports indentation and decapitalization.

Example

We illustrate this with an example

struct A{T}
   x::T
 end
 
@@ -159,31 +159,31 @@
 
 julia> A(B())
 Something of type A
-  over Hilbert thing

Documentation

AbstractAlgebra.PrettyPrinting.IndentType
Indent

When printed to an IOCustom object, increases the indentation level by one.

Examples

julia> io = AbstractAlgebra.pretty(stdout);
+  over Hilbert thing

Documentation

AbstractAlgebra.PrettyPrinting.IndentType
Indent

When printed to an IOCustom object, increases the indentation level by one.

Examples

julia> io = AbstractAlgebra.pretty(stdout);
 
 julia> print(io, AbstractAlgebra.Indent(), "This is indented")
-  This is indented
source
AbstractAlgebra.PrettyPrinting.DedentType
Dedent

When printed to an IOCustom object, decreases the indentation level by one.

Examples

julia> io = AbstractAlgebra.pretty(stdout);
 
 julia> print(io, AbstractAlgebra.Indent(), AbstractAlgebra.Dedent(), "This is indented")
-This is indented
source
AbstractAlgebra.PrettyPrinting.LowercaseType
Lowercase

When printed to an IOCustom object, the next letter printed will be lowercase.

Examples

julia> io = AbstractAlgebra.pretty(stdout);
 
 julia> print(io, AbstractAlgebra.Lowercase(), "Foo")
-foo
source
AbstractAlgebra.PrettyPrinting.LowercaseOffType
LowercaseOff

When printed to an IOCustom object, the case of the next letter will not be changed when printed.

Examples

julia> io = AbstractAlgebra.pretty(stdout);
 
 julia> print(io, AbstractAlgebra.Lowercase(), AbstractAlgebra.LowercaseOff(), "Foo")
-Foo
source

Linear solving interface for developers

AbstractAlgebra has a generic interface for linear solving and we describe here how one may extend this interface. For the user-facing functionality of linear solving, see Linear Solving.

Notice that the functionality is implemented in the module AbstractAlgebra.Solve and the internal functions are not exported from there.

Matrix normal forms

To distinguish between different algorithms, we use type traits of abstract type MatrixNormalFormTrait which usually correspond to a certain matrix normal form. The available algorithms/normal forms are

  • HowellFormTrait: uses a Howell form;
  • HermiteFormTrait: uses a Hermite normal form;
  • RREFTrait: uses a row-reduced echelon form over fields;
  • LUTrait: uses a LU factoring of the matrix;
  • FFLUTrait: uses a "fraction-free" LU factoring of the matrix over fraction fields;
  • MatrixInterpolateTrait: uses interpolation of polynomials for fraction fields of polynomial rings.

To select a normal form type for rings of type NewRing, implement the function

Solve.matrix_normal_form_type(::NewRing) = Bla()

where Bla <: MatrixNormalFormTrait. A new type trait can be added via

struct NewTrait <: Solve.MatrixNormalFormTrait end

Internal solving functionality

If a new ring type NewRing can make use of one of the available MatrixNormalFormTraits, then it suffices to specify this normal form as described above to use the generic solving functionality. (However, for example HermiteFormTrait requires that the function hermite_form_with_transformation is implemented.)

For a new trait NewTrait <: MatrixNormalFormTrait, one needs to implement the function

Solve._can_solve_internal_no_check(
+true
source

Linear solving interface for developers

AbstractAlgebra has a generic interface for linear solving and we describe here how one may extend this interface. For the user-facing functionality of linear solving, see Linear Solving.

Notice that the functionality is implemented in the module AbstractAlgebra.Solve and the internal functions are not exported from there.

Matrix normal forms

To distinguish between different algorithms, we use type traits of abstract type MatrixNormalFormTrait which usually correspond to a certain matrix normal form. The available algorithms/normal forms are

To select a normal form type for rings of type NewRing, implement the function

Solve.matrix_normal_form_type(::NewRing) = Bla()

where Bla <: MatrixNormalFormTrait. A new type trait can be added via

struct NewTrait <: Solve.MatrixNormalFormTrait end

Internal solving functionality

If a new ring type NewRing can make use of one of the available MatrixNormalFormTraits, then it suffices to specify this normal form as described above to use the generic solving functionality. (However, for example HermiteFormTrait requires that the function hermite_form_with_transformation is implemented.)

For a new trait NewTrait <: MatrixNormalFormTrait, one needs to implement the function

Solve._can_solve_internal_no_check(
   ::NewTrait, A::MatElem{T}, b::MatElem{T}, task::Symbol; side::Symbol = :left
   ) where T

Inside this function, one can assume that A and b have the same base ring and have compatible dimensions. Further, task and side are set to "legal" options. (All this is checked in Solve._can_solve_internal.) This function should then (try to) solve Ax = b (side == :right) or xA = b (side == :left) possibly with kernel. The function must always return a tuple (::Bool, ::MatElem{T}, ::MatElem{T}) consisting of:

The input task may be:

One should further implement the function

kernel(::NewTrait, A::MatElem; side::Symbol = :left)

which computes a left (or right) kernel of A.

Internal solve context functionality

To efficiently solve several linear systems with the same matrix A, we provide the "solve contexts objects" of type Solve.SolveCtx. These can be extended for a ring of type NewRing as follows.

Solve context type

For a new ring type, one may have to define the type parameters of a SolveCtx object. First of all, one needs to implement the function

function Solve.solve_context_type(::NewRing)
   return Solve.solve_context_type(::NormalFormTrait, elem_type(NewRing))
@@ -193,4 +193,4 @@
 Solve._init_reduce_transpose(C::SolveCtx{T, NewTrait}) where T

These should fill the corresponding fields of the solve context C with a "reduced matrix" (that is, a matrix in normal form) of matrix(C), respectively transpose(matrix(C)), and other information necessary to solve a linear system. The fields can be accessed via reduced_matrix, reduced_matrix_of_transpose, etc. New fields may also be added via attributes.

Internal solving functionality

As above, one finally needs to implement the functions

Solve._can_solve_internal_no_check(
   ::NewTrait, C::SolveCtx{T, NewTrait}, b::MatElem{T}, task::Symbol;
   side::Symbol = :left
-  ) where T

and

kernel(::NewTrait, C::SolveCtx{T, NewTrait}; side::Symbol = :left)
+ ) where T

and

kernel(::NewTrait, C::SolveCtx{T, NewTrait}; side::Symbol = :left)
diff --git a/dev/module/index.html b/dev/module/index.html index 8c9a8c06f..823c8ee0d 100644 --- a/dev/module/index.html +++ b/dev/module/index.html @@ -38,19 +38,19 @@ Vector space of dimension 2 over rationals julia> z = zero(M) -(0//1, 0//1)

Element indexing

Base.getindexMethod
getindex(a::Fac, b) -> Int

If $b$ is a factor of $a$, the corresponding exponent is returned. Otherwise an error is thrown.

source

Examples

julia> F = free_module(ZZ, 3)
+(0//1, 0//1)

Element indexing

Base.getindexMethod
getindex(a::Fac, b) -> Int

If $b$ is a factor of $a$, the corresponding exponent is returned. Otherwise an error is thrown.

source

Examples

julia> F = free_module(ZZ, 3)
 Free module of rank 3 over integers
 
 julia> m = F(BigInt[2, -5, 4])
 (2, -5, 4)
 
 julia> m[1]
-2

Module comparison

Base.:==Method
==(M::FPModule{T}, N::FPModule{T}) where T <: RingElement

Return true if the modules are (constructed to be) the same module elementwise. This is not object equality and it is not isomorphism. In fact, each method of constructing modules (submodules, quotient modules, products, etc.) must extend this notion of equality to the modules they create.

source

Examples

julia> M = free_module(QQ, 2)
+2

Module comparison

Base.:==Method
==(M::FPModule{T}, N::FPModule{T}) where T <: RingElement

Return true if the modules are (constructed to be) the same module elementwise. This is not object equality and it is not isomorphism. In fact, each method of constructing modules (submodules, quotient modules, products, etc.) must extend this notion of equality to the modules they create.

source

Examples

julia> M = free_module(QQ, 2)
 Vector space of dimension 2 over rationals
 
 julia> M == M
 true
-

Isomorphism

AbstractAlgebra.is_isomorphicMethod
is_isomorphic(M::FPModule{T}, N::FPModule{T}) where T <: RingElement

Return true if the modules $M$ and $N$ are isomorphic.

source
Note

Note that this function relies on the Smith normal form over the base ring of the modules being able to be made unique. This is true for Euclidean domains for which divrem has a fixed choice of quotient and remainder, but it will not in general be true for Euclidean rings that are not domains.

Examples

julia> M = free_module(ZZ, 3)
+

Isomorphism

AbstractAlgebra.is_isomorphicMethod
is_isomorphic(M::FPModule{T}, N::FPModule{T}) where T <: RingElement

Return true if the modules $M$ and $N$ are isomorphic.

source
Note

Note that this function relies on the Smith normal form over the base ring of the modules being able to be made unique. This is true for Euclidean domains for which divrem has a fixed choice of quotient and remainder, but it will not in general be true for Euclidean rings that are not domains.

Examples

julia> M = free_module(ZZ, 3)
 Free module of rank 3 over integers
 
 julia> m1 = rand(M, -10:10)
@@ -67,7 +67,7 @@
 
 julia> is_isomorphic(S, I)
 true
-

Invariant Factor Decomposition

For modules over a euclidean domain one can take the invariant factor decomposition to determine the structure of the module. The invariant factors are unique up to multiplication by a unit, and even unique if a canonical_unit is available for the ring that canonicalises elements.

AbstractAlgebra.snfMethod
snf(m::FPModule{T}) where T <: RingElement

Return a pair M, f consisting of the invariant factor decomposition $M$ of the module m and a module homomorphism (isomorphisms) $f : M \to m$. The module M is itself a module which can be manipulated as any other module in the system.

source
AbstractAlgebra.invariant_factorsMethod
invariant_factors(m::FPModule{T}) where T <: RingElement

Return a vector of the invariant factors of the module $M$.

source

Examples

julia> M = free_module(ZZ, 3)
+

Invariant Factor Decomposition

For modules over a euclidean domain one can take the invariant factor decomposition to determine the structure of the module. The invariant factors are unique up to multiplication by a unit, and even unique if a canonical_unit is available for the ring that canonicalises elements.

AbstractAlgebra.snfMethod
snf(m::FPModule{T}) where T <: RingElement

Return a pair M, f consisting of the invariant factor decomposition $M$ of the module m and a module homomorphism (isomorphisms) $f : M \to m$. The module M is itself a module which can be manipulated as any other module in the system.

source
AbstractAlgebra.invariant_factorsMethod
invariant_factors(m::FPModule{T}) where T <: RingElement

Return a vector of the invariant factors of the module $M$.

source

Examples

julia> M = free_module(ZZ, 3)
 Free module of rank 3 over integers
 
 julia> m1 = rand(M, -10:10)
@@ -89,4 +89,4 @@
 julia> invs = invariant_factors(Q)
 1-element Vector{BigInt}:
  0
-
+ diff --git a/dev/module_homomorphism/index.html b/dev/module_homomorphism/index.html index cc930f2f4..4d5f0e267 100644 --- a/dev/module_homomorphism/index.html +++ b/dev/module_homomorphism/index.html @@ -1,7 +1,7 @@ Module Homomorphisms · AbstractAlgebra.jl

Module Homomorphisms

Abstract Algebra provides homomorphisms of finitely presented modules.

Generic module homomorphism types

AbstractAlgebra defines two module homomorphism types, namely Generic.ModuleHomomorphism and Generic.ModuleIsomorphism. Functionality for these is implemented in src/generic/ModuleHomomorphism.jl.

Abstract types

The Generic.ModuleHomomorphism and Generic.ModuleIsomorphism types inherit from Map(FPModuleHomomorphism).

Generic functionality

The following generic functionality is provided for module homomorphisms.

Constructors

Homomorphisms of AbstractAlgebra modules, $f : R^s \to R^t$, can be represented by $s\times t$ matrices over $R$.

AbstractAlgebra.ModuleHomomorphismMethod
ModuleHomomorphism(M1::FPModule{T},
-                   M2::FPModule{T}, m::MatElem{T}) where T <: RingElement

Create the homomorphism $f : M_1 \to M_2$ represented by the matrix $m$.

source
AbstractAlgebra.ModuleIsomorphismMethod
ModuleIsomorphism(M1::FPModule{T}, M2::FPModule{T}, M::MatElem{T},
-                  minv::MatElem{T}) where T <: RingElement

Create the isomorphism $f : M_1 \to M_2$ represented by the matrix $M$. The inverse morphism is automatically computed.

source

Examples

julia> M = free_module(ZZ, 2)
+                   M2::FPModule{T}, m::MatElem{T}) where T <: RingElement

Create the homomorphism $f : M_1 \to M_2$ represented by the matrix $m$.

source
AbstractAlgebra.ModuleIsomorphismMethod
ModuleIsomorphism(M1::FPModule{T}, M2::FPModule{T}, M::MatElem{T},
+                  minv::MatElem{T}) where T <: RingElement

Create the isomorphism $f : M_1 \to M_2$ represented by the matrix $M$. The inverse morphism is automatically computed.

source

Examples

julia> M = free_module(ZZ, 2)
 Free module of rank 2 over integers
 
 julia> f = ModuleHomomorphism(M, M, matrix(ZZ, 2, 2, [1, 2, 3, 4]))
@@ -14,7 +14,7 @@
 
 julia> f(m)
 (7, 10)
-

They can also be created by giving images (in the codomain) of the generators of the domain:

ModuleHomomorphism(M1::FPModule{T}, M2::FPModule{T}, v::Vector{<:FPModuleElem{T}}) where T <: RingElement

Kernels

AbstractAlgebra.kernelMethod
kernel(f::ModuleHomomorphism{T}) where T <: RingElement

Return a pair K, g consisting of the kernel object $K$ of the given module homomorphism $f$ (as a submodule of its domain) and the canonical injection from the kernel into the domain of $f$.

source

Examples

julia> M = free_module(ZZ, 3)
+

They can also be created by giving images (in the codomain) of the generators of the domain:

ModuleHomomorphism(M1::FPModule{T}, M2::FPModule{T}, v::Vector{<:FPModuleElem{T}}) where T <: RingElement

Kernels

AbstractAlgebra.kernelMethod
kernel(f::ModuleHomomorphism{T}) where T <: RingElement

Return a pair K, g consisting of the kernel object $K$ of the given module homomorphism $f$ (as a submodule of its domain) and the canonical injection from the kernel into the domain of $f$.

source

Examples

julia> M = free_module(ZZ, 3)
 Free module of rank 3 over integers
 
 julia> m = M([ZZ(1), ZZ(2), ZZ(3)])
@@ -28,7 +28,7 @@
 
 julia> kernel(g)
 (Submodule over integers with 1 generator and no relations, Hom: submodule over integers with 1 generator and no relations -> M)
-

Images

AbstractAlgebra.imageMethod
image(f::Map(FPModuleHomomorphism))

Return a pair I, g consisting of the image object $I$ of the given module homomorphism $f$ (as a submodule of its codomain) and the canonical injection from the image into the codomain of $f$

source
M = free_module(ZZ, 3)
+

Images

AbstractAlgebra.imageMethod
image(f::Map(FPModuleHomomorphism))

Return a pair I, g consisting of the image object $I$ of the given module homomorphism $f$ (as a submodule of its codomain) and the canonical injection from the image into the codomain of $f$

source
M = free_module(ZZ, 3)
 
 m = M([ZZ(1), ZZ(2), ZZ(3)])
 
@@ -37,7 +37,7 @@
 K, k = kernel(g)
 
 image(compose(k, g))

Preimages

AbstractAlgebra.preimageMethod
preimage(f::Map(FPModuleHomomorphism),
-         v::FPModuleElem{T}) where T <: RingElement

Return a preimage of $v$ under the homomorphism $f$, i.e. an element of the domain of $f$ that maps to $v$ under $f$. Note that this has no special mathematical properties. It is an element of the set theoretical preimage of the map $f$ as a map of sets, if one exists. The preimage is neither unique nor chosen in a canonical way in general. When no such element exists, an exception is raised.

source
M = free_module(ZZ, 3)
+         v::FPModuleElem{T}) where T <: RingElement

Return a preimage of $v$ under the homomorphism $f$, i.e. an element of the domain of $f$ that maps to $v$ under $f$. Note that this has no special mathematical properties. It is an element of the set theoretical preimage of the map $f$ as a map of sets, if one exists. The preimage is neither unique nor chosen in a canonical way in general. When no such element exists, an exception is raised.

source
M = free_module(ZZ, 3)
 
 m = M([ZZ(1), ZZ(2), ZZ(3)])
 
@@ -47,8 +47,8 @@
 m = rand(M, -10:10)
 n = g(m)
 
-p = preimage(g, n)

Inverses

Module isomorphisms can be cheaply inverted.

Base.invMethod
Base.inv(f::Map(ModuleIsomorphism))

Return the inverse map of the given module isomorphism. This is computed cheaply.

source
M = free_module(ZZ, 2)
+p = preimage(g, n)

Inverses

Module isomorphisms can be cheaply inverted.

Base.invMethod
Base.inv(f::Map(ModuleIsomorphism))

Return the inverse map of the given module isomorphism. This is computed cheaply.

source
M = free_module(ZZ, 2)
 N = matrix(ZZ, 2, 2, BigInt[1, 0, 0, 1])
 f = ModuleIsomorphism(M, M, N)
 
-g = inv(f)
+g = inv(f) diff --git a/dev/module_interface/index.html b/dev/module_interface/index.html index 1787ad80c..ea941a592 100644 --- a/dev/module_interface/index.html +++ b/dev/module_interface/index.html @@ -1,2 +1,2 @@ -Module Interface · AbstractAlgebra.jl

Module Interface

Note

The module infrastructure in AbstractAlgebra should be considered experimental at this stage. This means that the interface may change in the future.

AbstractAlgebra allows the construction of finitely presented modules (i.e. with finitely many generators and relations), starting from free modules. The generic code provided by AbstractAlgebra will only work for modules over euclidean domains, however there is nothing preventing a library from implementing more general modules using the same interface.

All finitely presented module types in AbstractAlgebra follow the following interface which is a loose interface of functions, without much generic infrastructure built on top.

Free modules can be built over both commutative and noncommutative rings. Other types of module are restricted to fields and euclidean rings.

Abstract types

AbstractAlgebra provides two abstract types for finitely presented modules and their elements:

  • FPModule{T} is the abstract type for finitely presented module parent

types

  • FPModuleElem{T} is the abstract type for finitely presented module

element types

Note that the abstract types are parameterised. The type T should usually be the type of elements of the ring the module is over.

Required functionality for modules

We suppose that R is a fictitious base ring and that S is a module over R with parent object S of type MyModule{T}. We also assume the elements in the module have type MyModuleElem{T}, where T is the type of elements of the ring the module is over.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElement or NCRingElem.

We describe the functionality below for modules over commutative rings, i.e. with element type belonging to RingElement, however similar constructors should be available for element types belonging to NCRingElem instead, for free modules over a noncommutative ring.

Although not part of the module interface, implementations of modules that wish to follow our interface should use the same function names for submodules, quotient modules, direct sums and module homomorphisms if they wish to remain compatible with our module generics in the future.

Basic manipulation

iszero(m::MyModuleElem{T}) where T <: RingElement

Return true if the given module element is zero.

number_of_generators(M::MyModule{T}) where T <: RingElement

Return the number of generators of the module $M$ in its current representation.

gen(M::MyModule{T}, i::Int) where T <: RingElement

Return the $i$-th generator (indexed from $1$) of the module $M$.

gens(M::MyModule{T}) where T <: RingElement

Return a Julia array of the generators of the module $M$.

rels(M::MyModule{T}) where T <: RingElement

Return a Julia vector of all the relations between the generators of M. Each relation is given as an AbstractAlgebra row matrix.

Element constructors

We can construct elements of a module $M$ by specifying linear combinations of the generators of $M$. This is done by passing a vector of ring elements.

(M::Module{T})(v::Vector{T}) where T <: RingElement

Construct the element of the module $M$ corresponding to $\sum_i g[i]v[i]$ where $g[i]$ are the generators of the module $M$. The resulting element will lie in the module $M$.

Coercions

Given a module $M$ and an element $n$ of a module $N$, it is possible to coerce $n$ into $M$ using the notation $M(n)$ in certain circumstances.

In particular the element $n$ will be automatically coerced along any canonical injection of a submodule map and along any canonical projection of a quotient map. There must be a path from $N$ to $M$ along such maps.

Arithmetic operators

Elements of a module can be added, subtracted or multiplied by an element of the ring the module is defined over and compared for equality.

In the case of a noncommutative ring, both left and right scalar multiplication are defined.

+Module Interface · AbstractAlgebra.jl

Module Interface

Note

The module infrastructure in AbstractAlgebra should be considered experimental at this stage. This means that the interface may change in the future.

AbstractAlgebra allows the construction of finitely presented modules (i.e. with finitely many generators and relations), starting from free modules. The generic code provided by AbstractAlgebra will only work for modules over euclidean domains, however there is nothing preventing a library from implementing more general modules using the same interface.

All finitely presented module types in AbstractAlgebra follow the following interface which is a loose interface of functions, without much generic infrastructure built on top.

Free modules can be built over both commutative and noncommutative rings. Other types of module are restricted to fields and euclidean rings.

Abstract types

AbstractAlgebra provides two abstract types for finitely presented modules and their elements:

  • FPModule{T} is the abstract type for finitely presented module parent

types

  • FPModuleElem{T} is the abstract type for finitely presented module

element types

Note that the abstract types are parameterised. The type T should usually be the type of elements of the ring the module is over.

Required functionality for modules

We suppose that R is a fictitious base ring and that S is a module over R with parent object S of type MyModule{T}. We also assume the elements in the module have type MyModuleElem{T}, where T is the type of elements of the ring the module is over.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElement or NCRingElem.

We describe the functionality below for modules over commutative rings, i.e. with element type belonging to RingElement, however similar constructors should be available for element types belonging to NCRingElem instead, for free modules over a noncommutative ring.

Although not part of the module interface, implementations of modules that wish to follow our interface should use the same function names for submodules, quotient modules, direct sums and module homomorphisms if they wish to remain compatible with our module generics in the future.

Basic manipulation

iszero(m::MyModuleElem{T}) where T <: RingElement

Return true if the given module element is zero.

number_of_generators(M::MyModule{T}) where T <: RingElement

Return the number of generators of the module $M$ in its current representation.

gen(M::MyModule{T}, i::Int) where T <: RingElement

Return the $i$-th generator (indexed from $1$) of the module $M$.

gens(M::MyModule{T}) where T <: RingElement

Return a Julia array of the generators of the module $M$.

rels(M::MyModule{T}) where T <: RingElement

Return a Julia vector of all the relations between the generators of M. Each relation is given as an AbstractAlgebra row matrix.

Element constructors

We can construct elements of a module $M$ by specifying linear combinations of the generators of $M$. This is done by passing a vector of ring elements.

(M::Module{T})(v::Vector{T}) where T <: RingElement

Construct the element of the module $M$ corresponding to $\sum_i g[i]v[i]$ where $g[i]$ are the generators of the module $M$. The resulting element will lie in the module $M$.

Coercions

Given a module $M$ and an element $n$ of a module $N$, it is possible to coerce $n$ into $M$ using the notation $M(n)$ in certain circumstances.

In particular the element $n$ will be automatically coerced along any canonical injection of a submodule map and along any canonical projection of a quotient map. There must be a path from $N$ to $M$ along such maps.

Arithmetic operators

Elements of a module can be added, subtracted or multiplied by an element of the ring the module is defined over and compared for equality.

In the case of a noncommutative ring, both left and right scalar multiplication are defined.

diff --git a/dev/module_introduction/index.html b/dev/module_introduction/index.html index 328d6c01c..e88f30b88 100644 --- a/dev/module_introduction/index.html +++ b/dev/module_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

As with many generic constructions in AbstractAlgebra, the modules that are provided in AbstractAlgebra itself work over a Euclidean domain. Moreover, they are limited to finitely presented modules.

Free modules and vector spaces are provided over Euclidean domains and fields respectively and then submodule, quotient module and direct sum module constructions are possible recursively over these.

It's also possible to compute an invariant decomposition using the Smith Normal Form.

The system also provides module homomorphisms and isomorphisms, building on top of the map interface.

As for rings and fields, modules follow an interface which other modules are expected to follow. However, very little generic functionality is provided automatically once this interface is implemented by a new module type.

The purpose of the module interface is simply to encourage uniformity in the module interfaces of systems that build on AbstractAlgebra. Of course modules are so diverse that this is a very loosely defined interface to accommodate the diversity of possible representations and implementations.

+Introduction · AbstractAlgebra.jl

Introduction

As with many generic constructions in AbstractAlgebra, the modules that are provided in AbstractAlgebra itself work over a Euclidean domain. Moreover, they are limited to finitely presented modules.

Free modules and vector spaces are provided over Euclidean domains and fields respectively and then submodule, quotient module and direct sum module constructions are possible recursively over these.

It's also possible to compute an invariant decomposition using the Smith Normal Form.

The system also provides module homomorphisms and isomorphisms, building on top of the map interface.

As for rings and fields, modules follow an interface which other modules are expected to follow. However, very little generic functionality is provided automatically once this interface is implemented by a new module type.

The purpose of the module interface is simply to encourage uniformity in the module interfaces of systems that build on AbstractAlgebra. Of course modules are so diverse that this is a very loosely defined interface to accommodate the diversity of possible representations and implementations.

diff --git a/dev/mpoly_interface/index.html b/dev/mpoly_interface/index.html index e5f628c0a..38a849029 100644 --- a/dev/mpoly_interface/index.html +++ b/dev/mpoly_interface/index.html @@ -1,7 +1,7 @@ Multivariate Polynomial Ring Interface · AbstractAlgebra.jl

Multivariate Polynomial Ring Interface

Multivariate polynomial rings are supported in AbstractAlgebra.jl, and in addition to the standard Ring interface, numerous additional functions are provided.

Unlike other kinds of rings, even complex operations such as GCD depend heavily on the multivariate representation. Therefore AbstractAlgebra.jl cannot provide much in the way of additional functionality to external multivariate implementations.

This means that external libraries must be able to implement their multivariate formats in whatever way they see fit. The required interface here should be implemented, even if it is not optimal. But it can be extended, either by implementing one of the optional interfaces, or by extending the required interface in some other way.

Naturally, any multivariate polynomial ring implementation provides the full Ring interface, in order to be treated as a ring for the sake of AbstractAlgebra.jl.

Considerations which make it impossible for AbstractAlgebra.jl to provide generic functionality on top of an arbitrary multivariate module include:

  • orderings (lexical, degree, weighted, block, arbitrary)
  • sparse or dense representation
  • distributed or recursive representation
  • packed or unpacked exponents
  • exponent bounds (and whether adaptive or not)
  • random access or iterators
  • whether monomials and polynomials have the same type
  • whether special cache aware data structures such as Geobuckets are used

Types and parents

AbstractAlgebra.jl provides two abstract types for multivariate polynomial rings and their elements:

  • MPolyRing{T} is the abstract type for multivariate polynomial ring parent types
  • MPolyRingElem{T} is the abstract type for multivariate polynomial types

We have that MPolyRing{T} <: Ring and MPolyRingElem{T} <: RingElem.

Note that both abstract types are parameterised. The type T should usually be the type of elements of the coefficient ring of the polynomial ring. For example, in the case of $\mathbb{Z}[x, y]$ the type T would be the type of an integer, e.g. BigInt.

Multivariate polynomial rings should be made unique on the system by caching parent objects (unless an optional cache parameter is set to false). Multivariate polynomial rings should at least be distinguished based on their base (coefficient) ring and number of variables. But if they have the same base ring, symbols (for their variables/generators) and ordering, they should certainly have the same parent object.

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Required functionality for multivariate polynomials

In addition to the required functionality for the Ring interface, the Multivariate Polynomial interface has the following required functions.

We suppose that R is a fictitious base ring (coefficient ring) and that S is a multivariate polynomial ring over R (i.e. $S = R[x, y, \ldots]$) with parent object S of type MyMPolyRing{T}. We also assume the polynomials in the ring have type MyMPoly{T}, where T is the type of elements of the base (coefficient) ring.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElem or more generally the union type RingElement which includes the Julia integer, rational and floating point types.

Constructors

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

AbstractAlgebra.polynomial_ringMethod
polynomial_ring(R::Ring, varnames::Vector{Symbol}; cached=true, internal_ordering=:lex)

Given a coefficient ring R and variable names, say varnames = [:x1, :x2, ...], return a tuple S, [x1, x2, ...] of the polynomial ring $S = R[x1, x2, \dots]$ and its generators $x1, x2, \dots$.

By default (cached=true), the output S will be cached, i.e. if 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.

The monomial ordering used for the internal storage of polynomials in S can be set with internal_ordering and must be one of :lex, :deglex or :degrevlex.

See also: polynomial_ring(::Ring, ::Vararg), @polynomial_ring.

Example

julia> S, generators = polynomial_ring(ZZ, [:x, :y, :z])
-(Multivariate polynomial ring in 3 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y, z])
source

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 polynomial data type is random access, and so the constructor functions must be reimplemented for all other types of polynomials.

MPolyBuildCtx(R::MPolyRing)

Return a build context for creating polynomials in the given polynomial ring.

push_term!(M::MPolyBuildCtx, c::RingElem, v::Vector{Int})

Add the term with coefficient $c$ and exponent vector $v$ to the polynomial under construction in the build context $M$.

finish(M::MPolyBuildCtx)

Finish construction of the polynomial, sort the terms, remove duplicate and zero terms and return the created polynomial.

Data type and parent object methods

symbols(S::MyMPolyRing{T}) where T <: RingElem

Return an array of Symbols representing the variables (generators) of the polynomial ring. Note that these are Symbols not Strings, though their string values will usually be used when printing polynomials.

number_of_variables(f::MyMPolyRing{T}) where T <: RingElem

Return the number of variables of the polynomial ring.

gens(S::MyMPolyRing{T}) where T <: RingElem

Return an array of all the generators (variables) of the given polynomial ring (as polynomials).

The first entry in the array will be the variable with most significance with respect to the ordering.

gen(S::MyMPolyRing{T}, i::Int) where T <: RingElem

Return the $i$-th generator (variable) of the given polynomial ring (as a polynomial).

internal_ordering(S::MyMPolyRing{T})

Return the ordering of the given polynomial ring as a symbol. Supported values currently include :lex, :deglex and :degrevlex.

Basic manipulation of rings and elements

length(f::MyMPoly{T}) where T <: RingElem

Return the number of nonzero terms of the given polynomial. The length of the zero polynomial is defined to be $0$. The return value should be of type Int.

degrees(f::MyMPoly{T}) where T <: RingElem

Return an array of the degrees of the polynomial $f$ in each of the variables.

total_degree(f::MyMPoly{T}) where T <: RingElem

Return the total degree of the polynomial $f$, i.e. the highest sum of exponents occurring in any term of $f$.

is_gen(x::MyMPoly{T}) where T <: RingElem

Return true if $x$ is a generator of the polynomial ring.

coefficients(p::MyMPoly{T}) where T <: RingElem

Return an iterator for the coefficients of the polynomial $p$, starting with the coefficient of the most significant term with respect to the ordering. Generic code will provide this function automatically for random access polynomials that implement the coeff function.

monomials(p::MyMPoly{T}) where T <: RingElem

Return an iterator for the monomials of the polynomial $p$, starting with the monomial of the most significant term with respect to the ordering. Monomials in AbstractAlgebra are defined to have coefficient $1$. See the function terms if you also require the coefficients, however note that only monomials can be compared. Generic code will provide this function automatically for random access polynomials that implement the monomial function.

terms(p::MyMPoly{T}) where T <: RingElem

Return an iterator for the terms of the polynomial $p$, starting with the most significant term with respect to the ordering. Terms in AbstractAlgebra include the coefficient. Generic code will provide this function automatically for random access polynomials that implement the term function.

exponent_vectors(a::MyMPoly{T}) where T <: RingElement

Return an iterator for the exponent vectors for each of the terms of the polynomial starting with the most significant term with respect to the ordering. Each exponent vector is an array of Ints, one for each variable, in the order given when the polynomial ring was created. Generic code will provide this function automatically for random access polynomials that implement the exponent_vector function.

Exact division

For any ring that implements exact division, the following can be implemented.

divexact(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return the exact quotient of $f$ by $g$ if it exists, otherwise throw an error.

divides(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return a tuple (flag, q) where flag is true if $g$ divides $f$, in which case $q$ will be the exact quotient, or flag is false and $q$ is set to zero.

remove(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return a tuple $(v, q)$ such that the highest power of $g$ that divides $f$ is $g^v$ and the cofactor is $q$.

valuation(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return $v$ such that the highest power of $g$ that divides $f$ is $g^v$.

Ad hoc exact division

For any ring that implements exact division, the following can be implemented.

divexact(f::MyMPoly{T}, c::Integer) where T <: RingElem
+(Multivariate polynomial ring in 3 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y, z])
source

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 polynomial data type is random access, and so the constructor functions must be reimplemented for all other types of polynomials.

MPolyBuildCtx(R::MPolyRing)

Return a build context for creating polynomials in the given polynomial ring.

push_term!(M::MPolyBuildCtx, c::RingElem, v::Vector{Int})

Add the term with coefficient $c$ and exponent vector $v$ to the polynomial under construction in the build context $M$.

finish(M::MPolyBuildCtx)

Finish construction of the polynomial, sort the terms, remove duplicate and zero terms and return the created polynomial.

Data type and parent object methods

symbols(S::MyMPolyRing{T}) where T <: RingElem

Return an array of Symbols representing the variables (generators) of the polynomial ring. Note that these are Symbols not Strings, though their string values will usually be used when printing polynomials.

number_of_variables(f::MyMPolyRing{T}) where T <: RingElem

Return the number of variables of the polynomial ring.

gens(S::MyMPolyRing{T}) where T <: RingElem

Return an array of all the generators (variables) of the given polynomial ring (as polynomials).

The first entry in the array will be the variable with most significance with respect to the ordering.

gen(S::MyMPolyRing{T}, i::Int) where T <: RingElem

Return the $i$-th generator (variable) of the given polynomial ring (as a polynomial).

internal_ordering(S::MyMPolyRing{T})

Return the ordering of the given polynomial ring as a symbol. Supported values currently include :lex, :deglex and :degrevlex.

Basic manipulation of rings and elements

length(f::MyMPoly{T}) where T <: RingElem

Return the number of nonzero terms of the given polynomial. The length of the zero polynomial is defined to be $0$. The return value should be of type Int.

degrees(f::MyMPoly{T}) where T <: RingElem

Return an array of the degrees of the polynomial $f$ in each of the variables.

total_degree(f::MyMPoly{T}) where T <: RingElem

Return the total degree of the polynomial $f$, i.e. the highest sum of exponents occurring in any term of $f$.

is_gen(x::MyMPoly{T}) where T <: RingElem

Return true if $x$ is a generator of the polynomial ring.

coefficients(p::MyMPoly{T}) where T <: RingElem

Return an iterator for the coefficients of the polynomial $p$, starting with the coefficient of the most significant term with respect to the ordering. Generic code will provide this function automatically for random access polynomials that implement the coeff function.

monomials(p::MyMPoly{T}) where T <: RingElem

Return an iterator for the monomials of the polynomial $p$, starting with the monomial of the most significant term with respect to the ordering. Monomials in AbstractAlgebra are defined to have coefficient $1$. See the function terms if you also require the coefficients, however note that only monomials can be compared. Generic code will provide this function automatically for random access polynomials that implement the monomial function.

terms(p::MyMPoly{T}) where T <: RingElem

Return an iterator for the terms of the polynomial $p$, starting with the most significant term with respect to the ordering. Terms in AbstractAlgebra include the coefficient. Generic code will provide this function automatically for random access polynomials that implement the term function.

exponent_vectors(a::MyMPoly{T}) where T <: RingElement

Return an iterator for the exponent vectors for each of the terms of the polynomial starting with the most significant term with respect to the ordering. Each exponent vector is an array of Ints, one for each variable, in the order given when the polynomial ring was created. Generic code will provide this function automatically for random access polynomials that implement the exponent_vector function.

Exact division

For any ring that implements exact division, the following can be implemented.

divexact(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return the exact quotient of $f$ by $g$ if it exists, otherwise throw an error.

divides(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return a tuple (flag, q) where flag is true if $g$ divides $f$, in which case $q$ will be the exact quotient, or flag is false and $q$ is set to zero.

remove(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return a tuple $(v, q)$ such that the highest power of $g$ that divides $f$ is $g^v$ and the cofactor is $q$.

valuation(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return $v$ such that the highest power of $g$ that divides $f$ is $g^v$.

Ad hoc exact division

For any ring that implements exact division, the following can be implemented.

divexact(f::MyMPoly{T}, c::Integer) where T <: RingElem
 divexact(f::MyMPoly{T}, c::Rational) where T <: RingElem
 divexact(f::MyMPoly{T}, c::T) where T <: RingElem

Divide the polynomial exactly by the constant $c$.

Euclidean division

Although multivariate polynomial rings are not in general Euclidean, it is possible to define a quotient with remainder function that depends on the polynomial ordering in the case that the quotient ring is a field or a Euclidean domain. In the case that a polynomial $g$ divides a polynomial $f$, the result no longer depends on the ordering and the remainder is zero, with the quotient agreeing with the exact quotient.

divrem(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return a tuple $(q, r)$ such that $f = qg + r$, where the coefficients of terms of $r$ whose monomials are divisible by the leading monomial of $g$ are reduced modulo the leading coefficient of $g$ (according to the Euclidean function on the coefficients).

Note that the result of this function depends on the ordering of the polynomial ring.

div(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

As per the divrem function, but returning the quotient only. Especially when the quotient happens to be exact, this function can be exceedingly fast.

GCD

In cases where there is a meaningful Euclidean structure on the coefficient ring, it is possible to compute the GCD of multivariate polynomials.

gcd(f::MyMPoly{T}, g::MyMPoly{T}) where T <: RingElem

Return a greatest common divisor of $f$ and $g$.

Square root

Over rings for which an exact square root is available, it is possible to take the square root of a polynomial or test whether it is a square.

sqrt(f::MyMPoly{T}, check::Bool=true) where T <: RingElem

Return the square root of the polynomial $f$ and raise an exception if it is not a square. If check is set to false, the input is assumed to be a perfect square and this assumption is not fully checked. This can be significantly faster.

is_square(::MyMPoly{T}) where T <: RingElem

Return true if $f$ is a square.

Interface for sparse distributed, random access multivariates

The following additional functions should be implemented by libraries that provide a sparse distributed polynomial format, stored in a representation for which terms can be accessed in constant time (e.g. where arrays are used to store coefficients and exponent vectors).

Sparse distributed, random access constructors

In addition to the standard constructors, the following constructor, taking arrays of coefficients and exponent vectors, should be provided.

(S::MyMPolyRing{T})(A::Vector{T}, m::Vector{Vector{Int}}) where T <: RingElem

Create the polynomial in the given ring with nonzero coefficients specified by the elements of $A$ and corresponding exponent vectors given by the elements of $m$.

There is no assumption about coefficients being nonzero or terms being in order or unique. Zero terms are removed by the function, duplicate terms are combined (added) and the terms are sorted so that they are in the correct order.

Each exponent vector uses a separate integer for each exponent field, the first of which should be the exponent for the most significant variable with respect to the ordering. All exponents must be non-negative.

A library may also optionally provide an interface that makes use of BigInt (or any other big integer type) for exponents instead of Int.

Sparse distributed, random access basic manipulation

coeff(f::MyMPoly{T}, n::Int) where T <: RingElem

Return the coefficient of the $n$-th term of $f$. The first term should be the most significant term with respect to the ordering.

coeff(a::MyMPoly{T}, exps::Vector{Int}) where T <: RingElement

Return the coefficient of the term with the given exponent vector, or zero if there is no such term.

monomial(f::MyMPoly{T}, n::Int) where T <: RingElem
 monomial!(m::MyMPoly{T}, f::MyMPoly{T}, n::Int) where T <: RingElem

Return the $n$-th monomial of $f$ or set $m$ to the $n$-th monomial of $f$, respectively. The first monomial should be the most significant term with respect to the ordering. Monomials have coefficient $1$ in AbstractAlgebra. See the function term if you also require the coefficient, however, note that only monomials can be compared.

term(f::MyMPoly{T}, n::Int) where T <: RingElem

Return the $n$-th term of $f$. The first term should be the one whose monomial is most significant with respect to the ordering.

exponent(f::MyMPoly{T}, i::Int, j::Int) where T <: RingElem

Return the exponent of the $j$-th variable in the $i$-th term of the polynomial $f$. The first term is the one with whose monomial is most significant with respect to the ordering.

exponent_vector(a::MyMPoly{T}, i::Int) where T <: RingElement

Return a vector of exponents, corresponding to the exponent vector of the i-th term of the polynomial. Term numbering begins at $1$ and the exponents are given in the order of the variables for the ring, as supplied when the ring was created.

setcoeff!(a::MyMPoly, exps::Vector{Int}, c::S) where S <: RingElement

Set the coefficient of the term with the given exponent vector to the given value $c$. If no such term exists (and $c \neq 0$), one will be inserted. This function takes $O(\log n)$ operations if a term with the given exponent already exists and $c \neq 0$, or if the term is inserted at the end of the polynomial. Otherwise it can take $O(n)$ operations in the worst case. This function must return the modified polynomial.

Unsafe functions

The following functions must be provided, but are considered unsafe, as they may leave the polynomials in an inconsistent state and they mutate their inputs. As usual, such functions should only be applied on polynomials that have no references elsewhere in the system and are mainly intended to be used in carefully written library code, rather than by users.

Users should instead build polynomials using the constructors described above.

fit!(f::MyMPoly{T}, n::Int) where T <: RingElem

Ensure that the polynomial $f$ internally has space for $n$ nonzero terms. This function must mutate the function in-place if it is mutable. It does not return the mutated polynomial. Immutable types can still be supported by defining this function to do nothing.

setcoeff!(a::MyMPoly{T}, i::Int, c::T) where T <: RingElement
-setcoeff!(a::MyMPoly{T}, i::Int, c::U) where {T <: RingElement, U <: Integer}

Set the $i$-th coefficient of the polynomial $a$ to $c$. No check is performed on the index $i$ or for $c = 0$. It may be necessary to call combine_like_terms after calls to this function, to remove zero terms. The function must return the modified polynomial.

combine_like_terms!(a::MyMPoly{T}) where T <: RingElement

Remove zero terms and combine any adjacent terms with the same exponent vector (by adding them). It is assumed that all the exponent vectors are already in the correct order with respect to the ordering. The function must return the resulting polynomial.

set_exponent_vector!(a::MyMPoly{T}, i::Int, exps::Vector{Int}) where T <: RingElement

Set the $i$-th exponent vector to the given exponent vector. No check is performed on the index $i$, which is assumed to be valid (or that the polynomial has enough space allocated). No sorting of exponents is performed by this function. To sort the terms after setting any number of exponents with this function, run the sort_terms! function. The function must return the modified polynomial.

sort_terms!(a::MyMPoly{T}) where {T <: RingElement}

Sort the terms of the given polynomial according to the polynomial ring ordering. Zero terms and duplicate exponents are ignored. To deal with those call combine_like_terms. The sorted polynomial must be returned by the function.

Optional functionality for multivariate polynomials

The following functions can optionally be implemented for multivariate polynomial types.

Reduction by an ideal

divrem(f::MyMPoly{T}, G::Vector{MyMPoly{T}}) where T <: RingElem

As per the divrem function above, except that each term of $r$ starting with the most significant term, is reduced modulo the leading terms of each of the polynomials in the array $G$ for which the leading monomial is a divisor.

A tuple $(Q, r)$ is returned from the function, where $Q$ is an array of polynomials of the same length as $G$, and such that $f = r + \sum Q[i]G[i]$.

The result is again dependent on the ordering in general, but if the polynomials in $G$ are over a field and the reduced generators of a Groebner basis, then the result is unique.

Evaluation

evaluate(a::MyMPoly{T}, A::Vector{T}) where T <: RingElem

Evaluate the polynomial at the given values in the coefficient ring of the polynomial. The result should be an element of the coefficient ring.

evaluate(f::MyMPoly{T}, A::Vector{U}) where {T <: RingElem, U <: Integer}

Evaluate the polynomial $f$ at the values specified by the entries of the array $A$.

(a::MyMPoly{T})(vals::Union{NCRingElem, RingElement}...) where T <: RingElement

Evaluate the polynomial at the given arguments. This provides functional notation for polynomial evaluation, i.e. $f(a, b, c)$. It must be defined for each supported polynomial type (Julia does not allow functional notation to be defined for an abstract type).

The code for this function in MPoly.jl can be used when implementing this as it provides the most general possible evaluation, which is much more general than the case of evaluation at elements of the same ring.

The evaluation should succeed for any set of values for which a multiplication is defined with the product of a coefficient and all the values before it.

Note

The values at which a polynomial is evaluated may be in non-commutative rings. Products are performed in the order of the variables in the polynomial ring that the polynomial belongs to, preceded by a multiplication by the coefficient on the left.

Derivations

The following function allows to compute derivations of multivariate polynomials of type MPoly.

derivative(f::MyMPoly{T}, j::Int) where T <: RingElem

Compute the derivative of $f$ with respect to the $j$-th variable of the polynomial ring.

+setcoeff!(a::MyMPoly{T}, i::Int, c::U) where {T <: RingElement, U <: Integer}

Set the $i$-th coefficient of the polynomial $a$ to $c$. No check is performed on the index $i$ or for $c = 0$. It may be necessary to call combine_like_terms after calls to this function, to remove zero terms. The function must return the modified polynomial.

combine_like_terms!(a::MyMPoly{T}) where T <: RingElement

Remove zero terms and combine any adjacent terms with the same exponent vector (by adding them). It is assumed that all the exponent vectors are already in the correct order with respect to the ordering. The function must return the resulting polynomial.

set_exponent_vector!(a::MyMPoly{T}, i::Int, exps::Vector{Int}) where T <: RingElement

Set the $i$-th exponent vector to the given exponent vector. No check is performed on the index $i$, which is assumed to be valid (or that the polynomial has enough space allocated). No sorting of exponents is performed by this function. To sort the terms after setting any number of exponents with this function, run the sort_terms! function. The function must return the modified polynomial.

sort_terms!(a::MyMPoly{T}) where {T <: RingElement}

Sort the terms of the given polynomial according to the polynomial ring ordering. Zero terms and duplicate exponents are ignored. To deal with those call combine_like_terms. The sorted polynomial must be returned by the function.

Optional functionality for multivariate polynomials

The following functions can optionally be implemented for multivariate polynomial types.

Reduction by an ideal

divrem(f::MyMPoly{T}, G::Vector{MyMPoly{T}}) where T <: RingElem

As per the divrem function above, except that each term of $r$ starting with the most significant term, is reduced modulo the leading terms of each of the polynomials in the array $G$ for which the leading monomial is a divisor.

A tuple $(Q, r)$ is returned from the function, where $Q$ is an array of polynomials of the same length as $G$, and such that $f = r + \sum Q[i]G[i]$.

The result is again dependent on the ordering in general, but if the polynomials in $G$ are over a field and the reduced generators of a Groebner basis, then the result is unique.

Evaluation

evaluate(a::MyMPoly{T}, A::Vector{T}) where T <: RingElem

Evaluate the polynomial at the given values in the coefficient ring of the polynomial. The result should be an element of the coefficient ring.

evaluate(f::MyMPoly{T}, A::Vector{U}) where {T <: RingElem, U <: Integer}

Evaluate the polynomial $f$ at the values specified by the entries of the array $A$.

(a::MyMPoly{T})(vals::Union{NCRingElem, RingElement}...) where T <: RingElement

Evaluate the polynomial at the given arguments. This provides functional notation for polynomial evaluation, i.e. $f(a, b, c)$. It must be defined for each supported polynomial type (Julia does not allow functional notation to be defined for an abstract type).

The code for this function in MPoly.jl can be used when implementing this as it provides the most general possible evaluation, which is much more general than the case of evaluation at elements of the same ring.

The evaluation should succeed for any set of values for which a multiplication is defined with the product of a coefficient and all the values before it.

Note

The values at which a polynomial is evaluated may be in non-commutative rings. Products are performed in the order of the variables in the polynomial ring that the polynomial belongs to, preceded by a multiplication by the coefficient on the left.

Derivations

The following function allows to compute derivations of multivariate polynomials of type MPoly.

derivative(f::MyMPoly{T}, j::Int) where T <: RingElem

Compute the derivative of $f$ with respect to the $j$-th variable of the polynomial ring.

diff --git a/dev/mpolynomial/index.html b/dev/mpolynomial/index.html index 4ad5abf64..51abfedb4 100644 --- a/dev/mpolynomial/index.html +++ b/dev/mpolynomial/index.html @@ -1,6 +1,6 @@ Sparse distributed multivariate polynomials · AbstractAlgebra.jl

Sparse distributed multivariate polynomials

AbstractAlgebra.jl provides a module, implemented in src/MPoly.jl for sparse distributed multivariate polynomials over any commutative ring belonging to the AbstractAlgebra abstract type hierarchy.

Generic sparse distributed multivariable polynomial types

AbstractAlgebra provides a generic multivariate polynomial type Generic.MPoly{T} where T is the type of elements of the coefficient ring.

The polynomials are implemented using a Julia array of coefficients and a 2-dimensional Julia array of UInts for the exponent vectors. Note that exponent $n$ is represented by the $n$-th column of the exponent array, not the $n$-th row. This is because Julia uses a column major representation. See the file src/generic/GenericTypes.jl for details.

The top bit of each UInt is reserved for overflow detection.

Parent objects of such polynomials have type Generic.MPolyRing{T}.

The string representation of the variables of the polynomial ring and the base/coefficient ring $R$ and the ordering are stored in the parent object.

Abstract types

The polynomial element types belong to the abstract type MPolyRingElem{T} and the polynomial ring types belong to the abstract type MPolyRing{T}.

Note

Note that both the generic polynomial ring type Generic.MPolyRing{T} and the abstract type it belongs to, MPolyRing{T} are both called MPolyRing. The former is a (parameterised) concrete type for a polynomial ring over a given base ring whose elements have type T. The latter is an abstract type representing all multivariate polynomial ring types in AbstractAlgebra.jl, whether generic or very specialised (e.g. supplied by a C library).

Polynomial ring constructors

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

AbstractAlgebra.polynomial_ringMethod
polynomial_ring(R::Ring, varnames::Vector{Symbol}; cached=true, internal_ordering=:lex)

Given a coefficient ring R and variable names, say varnames = [:x1, :x2, ...], return a tuple S, [x1, x2, ...] of the polynomial ring $S = R[x1, x2, \dots]$ and its generators $x1, x2, \dots$.

By default (cached=true), the output S will be cached, i.e. if 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.

The monomial ordering used for the internal storage of polynomials in S can be set with internal_ordering and must be one of :lex, :deglex or :degrevlex.

See also: polynomial_ring(::Ring, ::Vararg), @polynomial_ring.

Example

julia> S, generators = polynomial_ring(ZZ, [:x, :y, :z])
-(Multivariate polynomial ring in 3 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y, z])
source
AbstractAlgebra.polynomial_ringMethod
polynomial_ring(R::Ring, varnames...; cached=true, internal_ordering=:lex)
+(Multivariate polynomial ring in 3 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y, z])
source
AbstractAlgebra.polynomial_ringMethod
polynomial_ring(R::Ring, varnames...; cached=true, internal_ordering=:lex)
 polynomial_ring(R::Ring, varnames::Tuple; cached=true, internal_ordering=:lex)

Like polynomial_ring(::Ring, ::Vector{Symbol}) with more ways to give varnames as specified in variable_names.

Return a tuple S, generators... with generators[i] corresponding to varnames[i].

Note

In the first method, varnames must not be empty, and if it consists of only one name, the univariate polynomial_ring(R::NCRing, s::VarName) method is called instead.

Examples

julia> S, (a, b, c) = polynomial_ring(ZZ, [:a, :b, :c])
 (Multivariate polynomial ring in 3 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[a, b, c])
 
@@ -19,7 +19,7 @@
 3-element Vector{AbstractAlgebra.Generic.MPoly{BigInt}}:
  y[1]
  y[2]
- y[3]
source
AbstractAlgebra.polynomial_ringMethod
polynomial_ring(R::Ring, varnames...; cached=true, internal_ordering=:lex)
 polynomial_ring(R::Ring, varnames::Tuple; cached=true, internal_ordering=:lex)

Like polynomial_ring(::Ring, ::Vector{Symbol}) with more ways to give varnames as specified in variable_names.

Return a tuple S, generators... with generators[i] corresponding to varnames[i].

Note

In the first method, varnames must not be empty, and if it consists of only one name, the univariate polynomial_ring(R::NCRing, s::VarName) method is called instead.

Examples

julia> S, (a, b, c) = polynomial_ring(ZZ, [:a, :b, :c])
 (Multivariate polynomial ring in 3 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[a, b, c])
 
@@ -38,8 +38,8 @@
 3-element Vector{AbstractAlgebra.Generic.MPoly{BigInt}}:
  y[1]
  y[2]
- y[3]
source
polynomial_ring(R::Ring, n::Int, s::Symbol=:x; cached=true, internal_ordering=:lex)

Same as polynomial_ring(::Ring, ["s$i" for i in 1:n]).

Example

julia> S, x = polynomial_ring(ZZ, 3)
-(Multivariate polynomial ring in 3 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x1, x2, x3])
source
AbstractAlgebra.@polynomial_ringMacro
@polynomial_ring(R::Ring, varnames...; cached=true, internal_ordering=:lex)

Return polynomial ring from polynomial_ring(::Ring, ::Vararg) and introduce the generators into the current scope.

Examples

julia> S = @polynomial_ring(ZZ, "x#" => (1:2, 1:2), "y#" => 1:3)
+ y[3]
source
polynomial_ring(R::Ring, n::Int, s::Symbol=:x; cached=true, internal_ordering=:lex)

Same as polynomial_ring(::Ring, ["s$i" for i in 1:n]).

Example

julia> S, x = polynomial_ring(ZZ, 3)
+(Multivariate polynomial ring in 3 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x1, x2, x3])
source
AbstractAlgebra.@polynomial_ringMacro
@polynomial_ring(R::Ring, varnames...; cached=true, internal_ordering=:lex)

Return polynomial ring from polynomial_ring(::Ring, ::Vararg) and introduce the generators into the current scope.

Examples

julia> S = @polynomial_ring(ZZ, "x#" => (1:2, 1:2), "y#" => 1:3)
 Multivariate polynomial ring in 7 variables x11, x21, x12, x22, ..., y3
   over integers
 
@@ -50,7 +50,7 @@
 (y1, y2, y3)
 
 julia> (S, [x11 x12; x21 x22], [y1, y2, y3]) == polynomial_ring(ZZ, "x#" => (1:2, 1:2), "y#" => 1:3)
-true
source

Like for univariate polynomials, a shorthand constructor is provided when the number of generators is greater than 1: given a base ring R, we abbreviate the constructor as follows:

R[:x, :y, ...]

Here are some examples of creating multivariate polynomial rings and making use of the resulting parent objects to coerce various elements into the polynomial ring.

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y]; internal_ordering=:deglex)
+true
source

Like for univariate polynomials, a shorthand constructor is provided when the number of generators is greater than 1: given a base ring R, we abbreviate the constructor as follows:

R[:x, :y, ...]

Here are some examples of creating multivariate polynomial rings and making use of the resulting parent objects to coerce various elements into the polynomial ring.

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y]; internal_ordering=:deglex)
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
 
 julia> T, (z, t) = QQ[:z, :t]
@@ -83,7 +83,7 @@
 

Polynomial constructors

Multivariate polynomials can be constructed from the generators in the usual way using arithmetic operations.

Also, all of the standard ring element constructors may be used to construct multivariate polynomials.

(R::MPolyRing{T})() where T <: RingElement
 (R::MPolyRing{T})(c::Integer) where T <: RingElement
 (R::MPolyRing{T})(a::elem_type(R)) where T <: RingElement
-(R::MPolyRing{T})(a::T) where T <: RingElement

For more efficient construction of multivariate polynomial, one can use the MPoly build context, where terms (coefficient followed by an exponent vector) are pushed onto a context one at a time and then the polynomial constructed from those terms in one go using the finish function.

AbstractAlgebra.Generic.push_term!Method
push_term!(M::MPolyBuildCtx, c::RingElem, v::Vector{Int})

Add the term with coefficient c and exponent vector v to the polynomial under construction in the build context M.

source
AbstractAlgebra.Generic.finishMethod
finish(M::MPolyBuildCtx)

Finish construction of the polynomial, sort the terms, remove duplicate and zero terms and return the created polynomial.

source

Note that the finish function resets the build context so that it can be used to construct multiple polynomials..

When a multivariate polynomial type has a representation that allows constant time access (e.g. it is represented internally by arrays), the following additional constructor is available. It takes and array of coefficients and and array of exponent vectors.

(S::MPolyRing{T})(A::Vector{T}, m::Vector{Vector{Int}}) where T <: RingElem

Create the polynomial in the given ring with nonzero coefficients specified by the elements of $A$ and corresponding exponent vectors given by the elements of $m$.

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
+(R::MPolyRing{T})(a::T) where T <: RingElement

For more efficient construction of multivariate polynomial, one can use the MPoly build context, where terms (coefficient followed by an exponent vector) are pushed onto a context one at a time and then the polynomial constructed from those terms in one go using the finish function.

AbstractAlgebra.Generic.push_term!Method
push_term!(M::MPolyBuildCtx, c::RingElem, v::Vector{Int})

Add the term with coefficient c and exponent vector v to the polynomial under construction in the build context M.

source
AbstractAlgebra.Generic.finishMethod
finish(M::MPolyBuildCtx)

Finish construction of the polynomial, sort the terms, remove duplicate and zero terms and return the created polynomial.

source

Note that the finish function resets the build context so that it can be used to construct multiple polynomials..

When a multivariate polynomial type has a representation that allows constant time access (e.g. it is represented internally by arrays), the following additional constructor is available. It takes and array of coefficients and and array of exponent vectors.

(S::MPolyRing{T})(A::Vector{T}, m::Vector{Vector{Int}}) where T <: RingElem

Create the polynomial in the given ring with nonzero coefficients specified by the elements of $A$ and corresponding exponent vectors given by the elements of $m$.

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
 
 julia> C = MPolyBuildCtx(R)
@@ -125,7 +125,7 @@
 monomial!(m::T, f::T, n::Int) where T <: MPolyRingElem

The second version writes the result into a preexisting polynomial object to save an allocation.

term(f::MPolyRingElem, n::Int)
exponent(f::MyMPolyRingElem, i::Int, j::Int)

Return the exponent of the $j$-th variable in the $i$-th term of the polynomial $f$.

exponent_vector(a::MPolyRingElem, i::Int)
setcoeff!(a::MPolyRingElem{T}, exps::Vector{Int}, c::T) where T <: RingElement

Although multivariate polynomial rings are not usually Euclidean, the following functions from the Euclidean interface are often provided.

divides(f::T, g::T) where T <: MPolyRingElem
 remove(f::T, g::T) where T <: MPolyRingElem
 valuation(f::T, g::T) where T <: MPolyRingElem
divrem(f::T, g::T) where T <: MPolyRingElem
-div(f::T, g::T) where T <: MPolyRingElem

Compute a tuple $(q, r)$ such that $f = qg + r$, where the coefficients of terms of $r$ whose monomials are divisible by the leading monomial of $g$ are reduced modulo the leading coefficient of $g$ (according to the Euclidean function on the coefficients). The divrem version returns both quotient and remainder whilst the div version only returns the quotient.

Note that the result of these functions depend on the ordering of the polynomial ring.

gcd(f::T, g::T) where T <: MPolyRingElem

The following functionality is also provided for all multivariate polynomials.

AbstractAlgebra.is_univariateMethod
is_univariate(R::MPolyRing)

Returns true if $R$ is a univariate polynomial ring, i.e. has exactly one variable, and false otherwise.

source
AbstractAlgebra.varsMethod
vars(p::MPolyRingElem{T}) where {T <: RingElement}

Return the variables actually occurring in $p$.

source
AbstractAlgebra.var_indexMethod
var_index(p::MPolyRingElem{T}) where {T <: RingElement}

Return the index of the given variable $x$. If $x$ is not a variable in a multivariate polynomial ring, an exception is raised.

source
AbstractAlgebra.degreeMethod
degree(f::MPolyRingElem{T}, i::Int) where T <: RingElement

Return the degree of the polynomial $f$ in terms of the i-th variable.

source
AbstractAlgebra.degreeMethod
degree(f::MPolyRingElem{T}, x::MPolyRingElem{T}) where T <: RingElement

Return the degree of the polynomial $f$ in terms of the variable $x$.

source
AbstractAlgebra.degreesMethod
degrees(f::MPolyRingElem{T}) where T <: RingElement

Return an array of the degrees of the polynomial $f$ in terms of each variable.

source
AbstractAlgebra.is_constantMethod
is_constant(x::MPolyRingElem{T}) where T <: RingElement

Return true if x is a degree zero polynomial or the zero polynomial, i.e. a constant polynomial.

source
AbstractAlgebra.is_univariateMethod
is_univariate(p::MPolyRingElem)

Returns true if $p$ is a univariate polynomial, i.e. involves at most one variable (thus constant polynomials are considered univariate), and false otherwise. The result depends on the terms of the polynomial, not simply on the number of variables in the polynomial ring.

source
AbstractAlgebra.coeffMethod
coeff(f::MPolyRingElem{T}, m::MPolyRingElem{T}) where T <: RingElement

Return the coefficient of the monomial $m$ of the polynomial $f$. If there is no such monomial, zero is returned.

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
+div(f::T, g::T) where T <: MPolyRingElem

Compute a tuple $(q, r)$ such that $f = qg + r$, where the coefficients of terms of $r$ whose monomials are divisible by the leading monomial of $g$ are reduced modulo the leading coefficient of $g$ (according to the Euclidean function on the coefficients). The divrem version returns both quotient and remainder whilst the div version only returns the quotient.

Note that the result of these functions depend on the ordering of the polynomial ring.

gcd(f::T, g::T) where T <: MPolyRingElem

The following functionality is also provided for all multivariate polynomials.

AbstractAlgebra.is_univariateMethod
is_univariate(R::MPolyRing)

Returns true if $R$ is a univariate polynomial ring, i.e. has exactly one variable, and false otherwise.

source
AbstractAlgebra.varsMethod
vars(p::MPolyRingElem{T}) where {T <: RingElement}

Return the variables actually occurring in $p$.

source
AbstractAlgebra.var_indexMethod
var_index(p::MPolyRingElem{T}) where {T <: RingElement}

Return the index of the given variable $x$. If $x$ is not a variable in a multivariate polynomial ring, an exception is raised.

source
AbstractAlgebra.degreeMethod
degree(f::MPolyRingElem{T}, i::Int) where T <: RingElement

Return the degree of the polynomial $f$ in terms of the i-th variable.

source
AbstractAlgebra.degreeMethod
degree(f::MPolyRingElem{T}, x::MPolyRingElem{T}) where T <: RingElement

Return the degree of the polynomial $f$ in terms of the variable $x$.

source
AbstractAlgebra.degreesMethod
degrees(f::MPolyRingElem{T}) where T <: RingElement

Return an array of the degrees of the polynomial $f$ in terms of each variable.

source
AbstractAlgebra.is_constantMethod
is_constant(x::MPolyRingElem{T}) where T <: RingElement

Return true if x is a degree zero polynomial or the zero polynomial, i.e. a constant polynomial.

source
AbstractAlgebra.is_univariateMethod
is_univariate(p::MPolyRingElem)

Returns true if $p$ is a univariate polynomial, i.e. involves at most one variable (thus constant polynomials are considered univariate), and false otherwise. The result depends on the terms of the polynomial, not simply on the number of variables in the polynomial ring.

source
AbstractAlgebra.coeffMethod
coeff(f::MPolyRingElem{T}, m::MPolyRingElem{T}) where T <: RingElement

Return the coefficient of the monomial $m$ of the polynomial $f$. If there is no such monomial, zero is returned.

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
 
 julia> f = x^2 + 2x + 1
@@ -297,7 +297,7 @@
 3-element Vector{Vector{Int64}}:
  [3, 1]
  [1, 2]
- [0, 0]

Changing base (coefficient) rings

In order to substitute the variables of a polynomial $f$ over a ring $T$ by elements in a $T$-algebra $S$, you first have to change the base ring of $f$ using the following function, where $g$ is a function representing the structure homomorphism of the $T$-algebra $S$.

AbstractAlgebra.change_base_ringMethod
change_base_ring(R::Ring, p::MPolyRingElem{<: RingElement}; parent::MPolyRing, cached::Bool=true)

Return the polynomial obtained by coercing the non-zero coefficients of p into R.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source
AbstractAlgebra.change_coefficient_ringMethod
change_coefficient_ring(R::Ring, p::MPolyRingElem{<: RingElement}; parent::MPolyRing, cached::Bool=true)

Return the polynomial obtained by coercing the non-zero coefficients of p into R.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source
AbstractAlgebra.map_coefficientsMethod
map_coefficients(f, p::MPolyRingElem{<: RingElement}; parent::MPolyRing)

Transform the polynomial p by applying f on each non-zero coefficient.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
+ [0, 0]

Changing base (coefficient) rings

In order to substitute the variables of a polynomial $f$ over a ring $T$ by elements in a $T$-algebra $S$, you first have to change the base ring of $f$ using the following function, where $g$ is a function representing the structure homomorphism of the $T$-algebra $S$.

AbstractAlgebra.change_base_ringMethod
change_base_ring(R::Ring, p::MPolyRingElem{<: RingElement}; parent::MPolyRing, cached::Bool=true)

Return the polynomial obtained by coercing the non-zero coefficients of p into R.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source
AbstractAlgebra.change_coefficient_ringMethod
change_coefficient_ring(R::Ring, p::MPolyRingElem{<: RingElement}; parent::MPolyRing, cached::Bool=true)

Return the polynomial obtained by coercing the non-zero coefficients of p into R.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source
AbstractAlgebra.map_coefficientsMethod
map_coefficients(f, p::MPolyRingElem{<: RingElement}; parent::MPolyRing)

Transform the polynomial p by applying f on each non-zero coefficient.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
 
 julia> fz = x^2*y^2 + x + 1
@@ -318,7 +318,7 @@
 x^5 + y^3 + 1
 
 julia> fq = change_base_ring(QQ, fz, parent=S)
-x^5 + y^3 + 1

Multivariate coefficients

In order to return the "coefficient" (as a multivariate polynomial in the same ring), of a given monomial (in which some of the variables may not appear and others may be required to appear to exponent zero), we can use the following function.

AbstractAlgebra.coeffMethod
coeff(a::MPolyRingElem{T}, vars::Vector{Int}, exps::Vector{Int}) where T <: RingElement

Return the "coefficient" of $a$ (as a multivariate polynomial in the same ring) of the monomial consisting of the product of the variables of the given indices raised to the given exponents (note that not all variables need to appear and the exponents can be zero). E.g. coeff(f, [1, 3], [0, 2]) returns the coefficient of $x^0*z^2$ in the polynomial $f$ (assuming variables $x, y, z$ in that order).

source
AbstractAlgebra.coeffMethod
coeff(a::T, vars::Vector{T}, exps::Vector{Int}) where T <: MPolyRingElem

Return the "coefficient" of $a$ (as a multivariate polynomial in the same ring) of the monomial consisting of the product of the given variables to the given exponents (note that not all variables need to appear and the exponents can be zero). E.g. coeff(f, [x, z], [0, 2]) returns the coefficient of $x^0*z^2$ in the polynomial $f$.

source

Examples

julia> R, (x, y, z) = polynomial_ring(ZZ, [:x, :y, :z])
+x^5 + y^3 + 1

Multivariate coefficients

In order to return the "coefficient" (as a multivariate polynomial in the same ring), of a given monomial (in which some of the variables may not appear and others may be required to appear to exponent zero), we can use the following function.

AbstractAlgebra.coeffMethod
coeff(a::MPolyRingElem{T}, vars::Vector{Int}, exps::Vector{Int}) where T <: RingElement

Return the "coefficient" of $a$ (as a multivariate polynomial in the same ring) of the monomial consisting of the product of the variables of the given indices raised to the given exponents (note that not all variables need to appear and the exponents can be zero). E.g. coeff(f, [1, 3], [0, 2]) returns the coefficient of $x^0*z^2$ in the polynomial $f$ (assuming variables $x, y, z$ in that order).

source
AbstractAlgebra.coeffMethod
coeff(a::T, vars::Vector{T}, exps::Vector{Int}) where T <: MPolyRingElem

Return the "coefficient" of $a$ (as a multivariate polynomial in the same ring) of the monomial consisting of the product of the given variables to the given exponents (note that not all variables need to appear and the exponents can be zero). E.g. coeff(f, [x, z], [0, 2]) returns the coefficient of $x^0*z^2$ in the polynomial $f$.

source

Examples

julia> R, (x, y, z) = polynomial_ring(ZZ, [:x, :y, :z])
 (Multivariate polynomial ring in 3 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y, z])
 
 julia> f = x^4*y^2*z^2 - 2x^4*y*z^2 + 4x^4*z^2 + 2x^2*y^2 + x + 1
@@ -326,7 +326,7 @@
 
 julia> coeff(f, [1, 3], [4, 2]) == coeff(f, [x, z], [4, 2])
 true
-

Inflation/deflation

AbstractAlgebra.deflationMethod
deflation(f::MPolyRingElem{T}) where T <: RingElement

Compute deflation parameters for the exponents of the polynomial $f$. This is a pair of arrays of integers, the first array of which (the shift) gives the minimum exponent for each variable of the polynomial, and the second of which (the deflation) gives the gcds of all the exponents after subtracting the shift, again per variable. This functionality is used by gcd (and can be used by factorisation algorithms).

source
AbstractAlgebra.deflateMethod
deflate(f::MPolyRingElem{T}, shift::Vector{Int}, defl::Vector{Int}) where T <: RingElement

Return a polynomial with the same coefficients as $f$ but whose exponents have been reduced by the given shifts (supplied as an array of shifts, one for each variable), then deflated (divided) by the given exponents (again supplied as an array of deflation factors, one for each variable). The algorithm automatically replaces a deflation of $0$ by $1$, to avoid division by $0$.

source
AbstractAlgebra.deflateMethod
deflate(f::MPolyRingElem{T}, defl::Vector{Int}) where T <: RingElement

Return a polynomial with the same coefficients as $f$ but whose exponents have been deflated (divided) by the given exponents (supplied as an array of deflation factors, one for each variable).

The algorithm automatically replaces a deflation of $0$ by $1$, to avoid division by $0$.

source
AbstractAlgebra.deflateMethod
deflate(f::MPolyRingElem{T}, defl::Vector{Int}) where T <: RingElement

Return a polynomial with the same coefficients as $f$ but whose exponents have been deflated maximally, i.e. with each exponent divide by the largest integer which divides the degrees of all exponents of that variable in $f$.

source
AbstractAlgebra.deflateMethod
deflate(f::MPolyRingElem, vars::Vector{Int}, shift::Vector{Int}, defl::Vector{Int})

Return a polynomial with the same coefficients as $f$ but where exponents of some variables (supplied as an array of variable indices) have been reduced by the given shifts (supplied as an array of shifts), then deflated (divided) by the given exponents (again supplied as an array of deflation factors). The algorithm automatically replaces a deflation of $0$ by $1$, to avoid division by $0$.

source
AbstractAlgebra.deflateMethod
deflate(f::T, vars::Vector{T}, shift::Vector{Int}, defl::Vector{Int}) where T <: MPolyRingElem

Return a polynomial with the same coefficients as $f$ but where the exponents of the given variables have been reduced by the given shifts (supplied as an array of shifts), then deflated (divided) by the given exponents (again supplied as an array of deflation factors). The algorithm automatically replaces a deflation of $0$ by $1$, to avoid division by $0$.

source
AbstractAlgebra.inflateMethod
inflate(f::MPolyRingElem{T}, shift::Vector{Int}, defl::Vector{Int}) where T <: RingElement

Return a polynomial with the same coefficients as $f$ but whose exponents have been inflated (multiplied) by the given deflation exponents (supplied as an array of inflation factors, one for each variable) and then increased by the given shifts (again supplied as an array of shifts, one for each variable).

source
AbstractAlgebra.inflateMethod
inflate(f::MPolyRingElem{T}, defl::Vector{Int}) where T <: RingElement

Return a polynomial with the same coefficients as $f$ but whose exponents have been inflated (multiplied) by the given deflation exponents (supplied as an array of inflation factors, one for each variable).

source
AbstractAlgebra.inflateMethod
inflate(f::MPolyRingElem, vars::Vector{Int}, shift::Vector{Int}, defl::Vector{Int})

Return a polynomial with the same coefficients as $f$ but where exponents of some variables (supplied as an array of variable indices) have been inflated (multiplied) by the given deflation exponents (supplied as an array of inflation factors) and then increased by the given shifts (again supplied as an array of shifts).

source
AbstractAlgebra.inflateMethod
inflate(f::T, vars::Vector{T}, shift::Vector{Int}, defl::Vector{Int}) where T <: MPolyRingElem

Return a polynomial with the same coefficients as $f$ but where the exponents of the given variables have been inflated (multiplied) by the given deflation exponents (supplied as an array of inflation factors) and then increased by the given shifts (again supplied as an array of shifts).

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
+

Inflation/deflation

AbstractAlgebra.deflationMethod
deflation(f::MPolyRingElem{T}) where T <: RingElement

Compute deflation parameters for the exponents of the polynomial $f$. This is a pair of arrays of integers, the first array of which (the shift) gives the minimum exponent for each variable of the polynomial, and the second of which (the deflation) gives the gcds of all the exponents after subtracting the shift, again per variable. This functionality is used by gcd (and can be used by factorisation algorithms).

source
AbstractAlgebra.deflateMethod
deflate(f::MPolyRingElem{T}, shift::Vector{Int}, defl::Vector{Int}) where T <: RingElement

Return a polynomial with the same coefficients as $f$ but whose exponents have been reduced by the given shifts (supplied as an array of shifts, one for each variable), then deflated (divided) by the given exponents (again supplied as an array of deflation factors, one for each variable). The algorithm automatically replaces a deflation of $0$ by $1$, to avoid division by $0$.

source
AbstractAlgebra.deflateMethod
deflate(f::MPolyRingElem{T}, defl::Vector{Int}) where T <: RingElement

Return a polynomial with the same coefficients as $f$ but whose exponents have been deflated (divided) by the given exponents (supplied as an array of deflation factors, one for each variable).

The algorithm automatically replaces a deflation of $0$ by $1$, to avoid division by $0$.

source
AbstractAlgebra.deflateMethod
deflate(f::MPolyRingElem{T}, defl::Vector{Int}) where T <: RingElement

Return a polynomial with the same coefficients as $f$ but whose exponents have been deflated maximally, i.e. with each exponent divide by the largest integer which divides the degrees of all exponents of that variable in $f$.

source
AbstractAlgebra.deflateMethod
deflate(f::MPolyRingElem, vars::Vector{Int}, shift::Vector{Int}, defl::Vector{Int})

Return a polynomial with the same coefficients as $f$ but where exponents of some variables (supplied as an array of variable indices) have been reduced by the given shifts (supplied as an array of shifts), then deflated (divided) by the given exponents (again supplied as an array of deflation factors). The algorithm automatically replaces a deflation of $0$ by $1$, to avoid division by $0$.

source
AbstractAlgebra.deflateMethod
deflate(f::T, vars::Vector{T}, shift::Vector{Int}, defl::Vector{Int}) where T <: MPolyRingElem

Return a polynomial with the same coefficients as $f$ but where the exponents of the given variables have been reduced by the given shifts (supplied as an array of shifts), then deflated (divided) by the given exponents (again supplied as an array of deflation factors). The algorithm automatically replaces a deflation of $0$ by $1$, to avoid division by $0$.

source
AbstractAlgebra.inflateMethod
inflate(f::MPolyRingElem{T}, shift::Vector{Int}, defl::Vector{Int}) where T <: RingElement

Return a polynomial with the same coefficients as $f$ but whose exponents have been inflated (multiplied) by the given deflation exponents (supplied as an array of inflation factors, one for each variable) and then increased by the given shifts (again supplied as an array of shifts, one for each variable).

source
AbstractAlgebra.inflateMethod
inflate(f::MPolyRingElem{T}, defl::Vector{Int}) where T <: RingElement

Return a polynomial with the same coefficients as $f$ but whose exponents have been inflated (multiplied) by the given deflation exponents (supplied as an array of inflation factors, one for each variable).

source
AbstractAlgebra.inflateMethod
inflate(f::MPolyRingElem, vars::Vector{Int}, shift::Vector{Int}, defl::Vector{Int})

Return a polynomial with the same coefficients as $f$ but where exponents of some variables (supplied as an array of variable indices) have been inflated (multiplied) by the given deflation exponents (supplied as an array of inflation factors) and then increased by the given shifts (again supplied as an array of shifts).

source
AbstractAlgebra.inflateMethod
inflate(f::T, vars::Vector{T}, shift::Vector{Int}, defl::Vector{Int}) where T <: MPolyRingElem

Return a polynomial with the same coefficients as $f$ but where the exponents of the given variables have been inflated (multiplied) by the given deflation exponents (supplied as an array of inflation factors) and then increased by the given shifts (again supplied as an array of shifts).

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
 
 julia> f = x^7*y^8 + 3*x^4*y^8 - x^4*y^2 + 5x*y^5 - x*y^2
@@ -355,7 +355,7 @@
 
 julia> g == g0 + y * g1
 true
-

Conversions

AbstractAlgebra.to_univariateMethod
to_univariate(R::PolyRing{T}, p::MPolyRingElem{T}) where T <: RingElement

Assuming the polynomial $p$ is actually a univariate polynomial, convert the polynomial to a univariate polynomial in the given univariate polynomial ring $R$. An exception is raised if the polynomial $p$ involves more than one variable.

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
+

Conversions

AbstractAlgebra.to_univariateMethod
to_univariate(R::PolyRing{T}, p::MPolyRingElem{T}) where T <: RingElement

Assuming the polynomial $p$ is actually a univariate polynomial, convert the polynomial to a univariate polynomial in the given univariate polynomial ring $R$. An exception is raised if the polynomial $p$ involves more than one variable.

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
 
 julia> S, z = polynomial_ring(ZZ, :z)
@@ -366,7 +366,7 @@
 
 julia> g = to_univariate(S, f)
 2*z^5 + 3*z^4 - 2*z^2 - 1
-

Evaluation

The following function allows evaluation of a polynomial at all its variables. The result is always in the ring that a product of a coefficient and one of the values belongs to, i.e. if all the values are in the coefficient ring, the result of the evaluation will be too.

AbstractAlgebra.evaluateMethod
evaluate(a::MPolyRingElem{T}, vals::Vector{U}) where {T <: RingElement, U <: RingElement}

Evaluate the polynomial expression by substituting in the array of values for each of the variables. The evaluation will succeed if multiplication is defined between elements of the coefficient ring of $a$ and elements of the supplied vector.

source

The following functions allow evaluation of a polynomial at some of its variables. Note that the result will be a product of values and an element of the polynomial ring, i.e. even if all the values are in the coefficient ring and all variables are given values, the result will be a constant polynomial, not a coefficient.

AbstractAlgebra.evaluateMethod
evaluate(a::MPolyRingElem{T}, vars::Vector{Int}, vals::Vector{U}) where {T <: RingElement, U <: RingElement}

Evaluate the polynomial expression by substituting in the supplied values in the array vals for the corresponding variables with indices given by the array vars. The evaluation will succeed if multiplication is defined between elements of the coefficient ring of $a$ and elements of vals.

source
AbstractAlgebra.evaluateMethod
evaluate(a::S, vars::Vector{S}, vals::Vector{U}) where {S <: MPolyRingElem{T}, U <: RingElement} where T <: RingElement

Evaluate the polynomial expression by substituting in the supplied values in the array vals for the corresponding variables (supplied as polynomials) given by the array vars. The evaluation will succeed if multiplication is defined between elements of the coefficient ring of $a$ and elements of vals.

source

The following function allows evaluation of a polynomial at values in a not necessarily commutative ring, e.g. elements of a matrix algebra.

AbstractAlgebra.evaluateMethod
evaluate(a::MPolyRingElem{T}, vals::Vector{U}) where {T <: RingElement, U <: NCRingElem}

Evaluate the polynomial expression at the supplied values, which may be any ring elements, commutative or non-commutative, but in the same ring. Evaluation always proceeds in the order of the variables as supplied when creating the polynomial ring to which $a$ belongs. The evaluation will succeed if a product of a coefficient of the polynomial by one of the values is defined.

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
+

Evaluation

The following function allows evaluation of a polynomial at all its variables. The result is always in the ring that a product of a coefficient and one of the values belongs to, i.e. if all the values are in the coefficient ring, the result of the evaluation will be too.

AbstractAlgebra.evaluateMethod
evaluate(a::MPolyRingElem{T}, vals::Vector{U}) where {T <: RingElement, U <: RingElement}

Evaluate the polynomial expression by substituting in the array of values for each of the variables. The evaluation will succeed if multiplication is defined between elements of the coefficient ring of $a$ and elements of the supplied vector.

source

The following functions allow evaluation of a polynomial at some of its variables. Note that the result will be a product of values and an element of the polynomial ring, i.e. even if all the values are in the coefficient ring and all variables are given values, the result will be a constant polynomial, not a coefficient.

AbstractAlgebra.evaluateMethod
evaluate(a::MPolyRingElem{T}, vars::Vector{Int}, vals::Vector{U}) where {T <: RingElement, U <: RingElement}

Evaluate the polynomial expression by substituting in the supplied values in the array vals for the corresponding variables with indices given by the array vars. The evaluation will succeed if multiplication is defined between elements of the coefficient ring of $a$ and elements of vals.

source
AbstractAlgebra.evaluateMethod
evaluate(a::S, vars::Vector{S}, vals::Vector{U}) where {S <: MPolyRingElem{T}, U <: RingElement} where T <: RingElement

Evaluate the polynomial expression by substituting in the supplied values in the array vals for the corresponding variables (supplied as polynomials) given by the array vars. The evaluation will succeed if multiplication is defined between elements of the coefficient ring of $a$ and elements of vals.

source

The following function allows evaluation of a polynomial at values in a not necessarily commutative ring, e.g. elements of a matrix algebra.

AbstractAlgebra.evaluateMethod
evaluate(a::MPolyRingElem{T}, vals::Vector{U}) where {T <: RingElement, U <: NCRingElem}

Evaluate the polynomial expression at the supplied values, which may be any ring elements, commutative or non-commutative, but in the same ring. Evaluation always proceeds in the order of the variables as supplied when creating the polynomial ring to which $a$ belongs. The evaluation will succeed if a product of a coefficient of the polynomial by one of the values is defined.

source

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
 
 julia> f = 2x^2*y^2 + 3x + y + 1
@@ -423,7 +423,7 @@
 
 julia> evaluate(f, [M1, M2, M3])
 [ 64    83]
-[124   149]

Leading and constant coefficients, leading monomials and leading terms

The leading and trailing coefficient, constant coefficient, leading monomial and leading term of a polynomial p are returned by the following functions:

AbstractAlgebra.trailing_coefficientMethod
trailing_coefficient(p::MPolyRingElem)

Return the trailing coefficient of the polynomial $p$, i.e. the coefficient of the last nonzero term, or zero if the polynomial is zero.

source
AbstractAlgebra.leading_termMethod
leading_term(p::MPolyRingElem)

Return the leading term of the polynomial p. This function throws an ArgumentError if $p$ is zero.

source
AbstractAlgebra.tailMethod
tail(p::MPolyRingElem)

Return the tail of the polynomial $p$, i.e. the polynomial without its leading term (if any).

source

Examples

using AbstractAlgebra
+[124   149]

Leading and constant coefficients, leading monomials and leading terms

The leading and trailing coefficient, constant coefficient, leading monomial and leading term of a polynomial p are returned by the following functions:

AbstractAlgebra.trailing_coefficientMethod
trailing_coefficient(p::MPolyRingElem)

Return the trailing coefficient of the polynomial $p$, i.e. the coefficient of the last nonzero term, or zero if the polynomial is zero.

source
AbstractAlgebra.leading_termMethod
leading_term(p::MPolyRingElem)

Return the leading term of the polynomial p. This function throws an ArgumentError if $p$ is zero.

source
AbstractAlgebra.tailMethod
tail(p::MPolyRingElem)

Return the tail of the polynomial $p$, i.e. the polynomial without its leading term (if any).

source

Examples

using AbstractAlgebra
 R,(x,y) = polynomial_ring(ZZ, [:x, :y], internal_ordering=:deglex)
 p = 2*x*y + 3*y^3 + 1
 leading_term(p)
@@ -431,7 +431,7 @@
 leading_coefficient(p)
 leading_term(p) == leading_coefficient(p) * leading_monomial(p)
 constant_coefficient(p)
-tail(p)

Least common multiple, greatest common divisor

The greatest common divisor of two polynomials a and b is returned by

Base.gcdMethod
gcd(a::MPoly{T}, a::MPoly{T}) where {T <: RingElement}

Return the greatest common divisor of a and b in parent(a).

source

Note that this functionality is currently only provided for AbstractAlgebra generic polynomials. It is not automatically provided for all multivariate rings that implement the multivariate interface.

However, if such a gcd is provided, the least common multiple of two polynomials a and b is returned by

Base.lcmMethod
lcm(a::AbstractAlgebra.MPolyRingElem{T}, a::AbstractAlgebra.MPolyRingElem{T}) where {T <: RingElement}

Return the least common multiple of a and b in parent(a).

source

Examples

julia> using AbstractAlgebra
+tail(p)

Least common multiple, greatest common divisor

The greatest common divisor of two polynomials a and b is returned by

Base.gcdMethod
gcd(a::MPoly{T}, a::MPoly{T}) where {T <: RingElement}

Return the greatest common divisor of a and b in parent(a).

source

Note that this functionality is currently only provided for AbstractAlgebra generic polynomials. It is not automatically provided for all multivariate rings that implement the multivariate interface.

However, if such a gcd is provided, the least common multiple of two polynomials a and b is returned by

Base.lcmMethod
lcm(a::AbstractAlgebra.MPolyRingElem{T}, a::AbstractAlgebra.MPolyRingElem{T}) where {T <: RingElement}

Return the least common multiple of a and b in parent(a).

source

Examples

julia> using AbstractAlgebra
 
 julia> R,(x,y) = polynomial_ring(ZZ, [:x, :y])
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
@@ -450,7 +450,7 @@
 
 julia> lcm(a,b) == a * b // gcd(a,b)
 true
-

Derivations

AbstractAlgebra.derivativeMethod
derivative(f::MPolyRingElem{T}, x::MPolyRingElem{T}) where T <: RingElement

Return the partial derivative of f with respect to x. The value x must be a generator of the polynomial ring of f.

source

Examples

julia> R, (x, y) = AbstractAlgebra.polynomial_ring(ZZ, [:x, :y])
+

Derivations

AbstractAlgebra.derivativeMethod
derivative(f::MPolyRingElem{T}, x::MPolyRingElem{T}) where T <: RingElement

Return the partial derivative of f with respect to x. The value x must be a generator of the polynomial ring of f.

source

Examples

julia> R, (x, y) = AbstractAlgebra.polynomial_ring(ZZ, [:x, :y])
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
 
 julia> f = x*y + x + y + 1
@@ -466,7 +466,7 @@
 y + 1
 
 julia> derivative(f, 2)
-x + 1

Homogeneous polynomials

It is possible to test whether a polynomial is homogeneous with respect to the standard grading using the function

Random generation

Random multivariate polynomials in a given ring can be constructed by passing a range of degrees for the variables and a range on the number of terms. Additional parameters are used to generate the coefficients of the polynomial.

Note that zero coefficients may currently be generated, leading to less than the requested number of terms.

rand(R::MPolyRing, exp_range::AbstractUnitRange{Int}, term_range::AbstractUnitRange{Int}, v...)

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
+x + 1

Homogeneous polynomials

It is possible to test whether a polynomial is homogeneous with respect to the standard grading using the function

Random generation

Random multivariate polynomials in a given ring can be constructed by passing a range of degrees for the variables and a range on the number of terms. Additional parameters are used to generate the coefficients of the polynomial.

Note that zero coefficients may currently be generated, leading to less than the requested number of terms.

rand(R::MPolyRing, exp_range::AbstractUnitRange{Int}, term_range::AbstractUnitRange{Int}, v...)

Examples

julia> R, (x, y) = polynomial_ring(ZZ, [:x, :y])
 (Multivariate polynomial ring in 2 variables over integers, AbstractAlgebra.Generic.MPoly{BigInt}[x, y])
 
 julia> f = rand(R, -1:2, 3:5, -10:10)
@@ -476,4 +476,4 @@
 (Multivariate polynomial ring in 2 variables over finite field F_7, AbstractAlgebra.Generic.MPoly{AbstractAlgebra.GFElem{Int64}}[x, y])
 
 julia> g = rand(S, -1:2, 3:5)
-4*x^3*y^4
+4*x^3*y^4 diff --git a/dev/mseries/index.html b/dev/mseries/index.html index 822702374..2d8f06da4 100644 --- a/dev/mseries/index.html +++ b/dev/mseries/index.html @@ -75,4 +75,4 @@ 1 + 3*y*x^2 + O(10) julia> one(R) -1 + O(10)

Power series functionality provided by AbstractAlgebra.jl

The functionality listed below is automatically provided by AbstractAlgebra.jl for absolute series over any commutative ring.

Basic functionality

The following are provided for weighted and unweighted series:

AbstractAlgebra.number_of_variablesMethod
number_of_variables(R::AbsMSeriesRing)

Return the number of variables in the series ring.

source
AbstractAlgebra.symbolsMethod
symbols(R::MSeriesRing)

Return a vector of symbols, one for each of the variables of the series ring $R$.

source
Base.precisionMethod
precision(a::AbsMSeries)

Return a vector of precisions, one for each variable in the series ring. If the ring is weighted the weighted precision is returned instead.

source
AbstractAlgebra.coeffMethod
coeff(a::AbsMSeries, n::Int)

Return the coefficient of the $n$-th nonzero term of the series (or zero if there are fewer than $n$ nonzero terms). Terms are numbered from the least significant term, i.e. the first term displayed when the series is printed.

source
AbstractAlgebra.characteristicMethod
characteristic(R::FracField{T}) where T <: RingElem

Return the characteristic of the given field.

source
AbstractAlgebra.genMethod
gen(R::AbsMSeriesRing, i::Int)

Return the $i$-th generator (variable) of the series ring $R$. Numbering starts from $1$ for the most significant variable.

source
AbstractAlgebra.gensMethod
gens(R::AbsMSeriesRing)

Return a vector of the generators (variables) of the series ring $R$, starting with the most significant.

source
AbstractAlgebra.is_genMethod
is_gen(a::AbsMSeries)

Return true if the series $a$ is a generator of its parent series ring.

source
AbstractAlgebra.is_unitMethod
is_unit(a::AbsMSeries)

Return true if the series is a unit in its series ring, i.e. if its constant term is a unit in the base ring.

source
Base.lengthMethod
length(a::AbsMSeries)

Return the number of nonzero terms in the series $a$.

source

The following are only available for unweighted series.

AbstractAlgebra.max_precisionMethod
max_precision(R::AbsMSeriesRing)

Return a vector of precision caps, one for each variable in the ring. Arithmetic operations will be performed to precisions not exceeding these values.

source
AbstractAlgebra.valuationMethod
valuation(a::AbsMSeries)

Return the valuation of $a$ as a vector of integers, one for each variable.

source

Iteration

AbstractAlgebra.coefficientsMethod
coefficients(a::AbsMSeries)

Return an array of the nonzero coefficients of the series, in the order they would be displayed, i.e. least significant term first.

source
AbstractAlgebra.exponent_vectorsMethod
exponent_vectors(a::AbsMSeries)

Return an array of the exponent vectors of the nonzero terms of the series, in the order they would be displayed, i.e. least significant term first.

source

Truncation

Base.truncateMethod
truncate(a::AbstractAlgebra.AbsMSeries, prec::Vector{Int})

Return $a$ truncated to (absolute) precisions given by the vector prec.

source
Base.truncateMethod
truncate(a::AbstractAlgebra.AbsMSeries, prec::Int)

Return $a$ truncated to precision prec. This either truncates by weight in the weighted cases or truncates each variable to precision prec in the unweighted case.

source

Exact division

AbstractAlgebra.divexactMethod
divexact(x::AbsMSeries{T}, y::AbsMSeries{T}; check::Bool=true) where T <: RingElement

Return the exact quotient of the series $x$ by the series $y$. This function currently assumes $y$ is an invertible series.

source

Evaluation

AbstractAlgebra.evaluateMethod
evaluate(a::U, vars::Vector{Int}, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the corresponding variables with indices given by the array vars. The values must be in the same ring as $a$.

source
AbstractAlgebra.evaluateMethod
evaluate(a::U, vars::Vector{U}, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the corresponding variables given by the array vars. The values must be in the same ring as $a$.

source
AbstractAlgebra.evaluateMethod
evaluate(a::U, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the variables the series ring to which $a$ belongs. The values must be in the same ring as $a$.

source

Random generation

Base.randMethod
rand(S::MSeriesRing, term_range, v...)

Return a random element of the series ring $S$ with number of terms in the range given by term_range and where coefficients of the series are randomly generated in the base ring using the data given by v. The exponents of the variable in the terms will be less than the precision caps for the Ring $S$ when it was created.

source
+1 + O(10)

Power series functionality provided by AbstractAlgebra.jl

The functionality listed below is automatically provided by AbstractAlgebra.jl for absolute series over any commutative ring.

Basic functionality

The following are provided for weighted and unweighted series:

AbstractAlgebra.number_of_variablesMethod
number_of_variables(R::AbsMSeriesRing)

Return the number of variables in the series ring.

source
AbstractAlgebra.symbolsMethod
symbols(R::MSeriesRing)

Return a vector of symbols, one for each of the variables of the series ring $R$.

source
Base.precisionMethod
precision(a::AbsMSeries)

Return a vector of precisions, one for each variable in the series ring. If the ring is weighted the weighted precision is returned instead.

source
AbstractAlgebra.coeffMethod
coeff(a::AbsMSeries, n::Int)

Return the coefficient of the $n$-th nonzero term of the series (or zero if there are fewer than $n$ nonzero terms). Terms are numbered from the least significant term, i.e. the first term displayed when the series is printed.

source
AbstractAlgebra.characteristicMethod
characteristic(R::FracField{T}) where T <: RingElem

Return the characteristic of the given field.

source
AbstractAlgebra.genMethod
gen(R::AbsMSeriesRing, i::Int)

Return the $i$-th generator (variable) of the series ring $R$. Numbering starts from $1$ for the most significant variable.

source
AbstractAlgebra.gensMethod
gens(R::AbsMSeriesRing)

Return a vector of the generators (variables) of the series ring $R$, starting with the most significant.

source
AbstractAlgebra.is_genMethod
is_gen(a::AbsMSeries)

Return true if the series $a$ is a generator of its parent series ring.

source
AbstractAlgebra.is_unitMethod
is_unit(a::AbsMSeries)

Return true if the series is a unit in its series ring, i.e. if its constant term is a unit in the base ring.

source
Base.lengthMethod
length(a::AbsMSeries)

Return the number of nonzero terms in the series $a$.

source

The following are only available for unweighted series.

AbstractAlgebra.max_precisionMethod
max_precision(R::AbsMSeriesRing)

Return a vector of precision caps, one for each variable in the ring. Arithmetic operations will be performed to precisions not exceeding these values.

source
AbstractAlgebra.valuationMethod
valuation(a::AbsMSeries)

Return the valuation of $a$ as a vector of integers, one for each variable.

source

Iteration

AbstractAlgebra.coefficientsMethod
coefficients(a::AbsMSeries)

Return an array of the nonzero coefficients of the series, in the order they would be displayed, i.e. least significant term first.

source
AbstractAlgebra.exponent_vectorsMethod
exponent_vectors(a::AbsMSeries)

Return an array of the exponent vectors of the nonzero terms of the series, in the order they would be displayed, i.e. least significant term first.

source

Truncation

Base.truncateMethod
truncate(a::AbstractAlgebra.AbsMSeries, prec::Vector{Int})

Return $a$ truncated to (absolute) precisions given by the vector prec.

source
Base.truncateMethod
truncate(a::AbstractAlgebra.AbsMSeries, prec::Int)

Return $a$ truncated to precision prec. This either truncates by weight in the weighted cases or truncates each variable to precision prec in the unweighted case.

source

Exact division

AbstractAlgebra.divexactMethod
divexact(x::AbsMSeries{T}, y::AbsMSeries{T}; check::Bool=true) where T <: RingElement

Return the exact quotient of the series $x$ by the series $y$. This function currently assumes $y$ is an invertible series.

source

Evaluation

AbstractAlgebra.evaluateMethod
evaluate(a::U, vars::Vector{Int}, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the corresponding variables with indices given by the array vars. The values must be in the same ring as $a$.

source
AbstractAlgebra.evaluateMethod
evaluate(a::U, vars::Vector{U}, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the corresponding variables given by the array vars. The values must be in the same ring as $a$.

source
AbstractAlgebra.evaluateMethod
evaluate(a::U, vals::Vector{U}) where {T <: RingElement, U <: AbsMSeries{T}}

Evaluate the series expression by substituting in the supplied values in the array vals for the variables the series ring to which $a$ belongs. The values must be in the same ring as $a$.

source

Random generation

Base.randMethod
rand(S::MSeriesRing, term_range, v...)

Return a random element of the series ring $S$ with number of terms in the range given by term_range and where coefficients of the series are randomly generated in the base ring using the data given by v. The exponents of the variable in the terms will be less than the precision caps for the Ring $S$ when it was created.

source
diff --git a/dev/ncpolynomial/index.html b/dev/ncpolynomial/index.html index 3dcd0ceef..370b66382 100644 --- a/dev/ncpolynomial/index.html +++ b/dev/ncpolynomial/index.html @@ -3,7 +3,7 @@ (Univariate polynomial ring in x over integers, x) julia> S, y = polynomial_ring(R, :y) -(Univariate polynomial ring in y over R, y)source

A shorthand version of this function is provided: given a base ring R, we abbreviate the constructor as follows.

R[:x]

Here are some examples of creating polynomial rings and making use of the resulting parent objects to coerce various elements into the polynomial ring.

Examples

julia> R = matrix_ring(ZZ, 2)
+(Univariate polynomial ring in y over R, y)
source

A shorthand version of this function is provided: given a base ring R, we abbreviate the constructor as follows.

R[:x]

Here are some examples of creating polynomial rings and making use of the resulting parent objects to coerce various elements into the polynomial ring.

Examples

julia> R = matrix_ring(ZZ, 2)
 Matrix ring of degree 2
   over integers
 
@@ -74,7 +74,7 @@
 Univariate polynomial ring in y over S
 
 julia> g == deepcopy(g)
-true

Polynomial functionality provided by AbstractAlgebra.jl

The functionality listed below is automatically provided by AbstractAlgebra.jl for any polynomial module that implements the full Univariate Polynomial Ring interface over a noncommutative ring. This includes AbstractAlgebra.jl's own generic polynomial rings.

But if a C library provides all the functionality documented in the Univariate Polynomial Ring interface over a noncommutative ring, then all the functions described here will also be automatically supplied by AbstractAlgebra.jl for that polynomial type.

Of course, modules are free to provide specific implementations of the functions described here, that override the generic implementation.

Basic functionality

AbstractAlgebra.leading_coefficientMethod
leading_coefficient(a::PolynomialElem)

Return the leading coefficient of the given polynomial. This will be the nonzero coefficient of the term with highest degree unless the polynomial in the zero polynomial, in which case a zero coefficient is returned.

source
AbstractAlgebra.trailing_coefficientMethod
trailing_coefficient(a::PolynomialElem)

Return the trailing coefficient of the given polynomial. This will be the nonzero coefficient of the term with lowest degree unless the polynomial is the zero polynomial, in which case a zero coefficient is returned.

source
AbstractAlgebra.genMethod
gen(R::NCPolyRing)

Return the generator of the given polynomial ring.

source
AbstractAlgebra.is_genMethod
is_gen(a::PolynomialElem)

Return true if the given polynomial is the constant generator of its polynomial ring, otherwise return false.

source
AbstractAlgebra.is_monomialMethod
is_monomial(a::PolynomialElem)

Return true if the given polynomial is a monomial.

source
AbstractAlgebra.is_termMethod
is_term(a::PolynomialElem)

Return true if the given polynomial has one term.

source

Examples

julia> R = matrix_ring(ZZ, 2)
+true

Polynomial functionality provided by AbstractAlgebra.jl

The functionality listed below is automatically provided by AbstractAlgebra.jl for any polynomial module that implements the full Univariate Polynomial Ring interface over a noncommutative ring. This includes AbstractAlgebra.jl's own generic polynomial rings.

But if a C library provides all the functionality documented in the Univariate Polynomial Ring interface over a noncommutative ring, then all the functions described here will also be automatically supplied by AbstractAlgebra.jl for that polynomial type.

Of course, modules are free to provide specific implementations of the functions described here, that override the generic implementation.

Basic functionality

AbstractAlgebra.leading_coefficientMethod
leading_coefficient(a::PolynomialElem)

Return the leading coefficient of the given polynomial. This will be the nonzero coefficient of the term with highest degree unless the polynomial in the zero polynomial, in which case a zero coefficient is returned.

source
AbstractAlgebra.trailing_coefficientMethod
trailing_coefficient(a::PolynomialElem)

Return the trailing coefficient of the given polynomial. This will be the nonzero coefficient of the term with lowest degree unless the polynomial is the zero polynomial, in which case a zero coefficient is returned.

source
AbstractAlgebra.genMethod
gen(R::NCPolyRing)

Return the generator of the given polynomial ring.

source
AbstractAlgebra.is_genMethod
is_gen(a::PolynomialElem)

Return true if the given polynomial is the constant generator of its polynomial ring, otherwise return false.

source
AbstractAlgebra.is_monomialMethod
is_monomial(a::PolynomialElem)

Return true if the given polynomial is a monomial.

source
AbstractAlgebra.is_termMethod
is_term(a::PolynomialElem)

Return true if the given polynomial has one term.

source

Examples

julia> R = matrix_ring(ZZ, 2)
 Matrix ring of degree 2
   over integers
 
@@ -116,7 +116,7 @@
 
 julia> is_monomial(y^2)
 true
-

Truncation

Base.truncateMethod
truncate(a::PolynomialElem, n::Int)

Return $a$ truncated to $n$ terms, i.e. the remainder upon division by $x^n$.

source
AbstractAlgebra.mullowMethod
mullow(a::NCPolyRingElem{T}, b::NCPolyRingElem{T}, n::Int) where T <: NCRingElem

Return $a\times b$ truncated to $n$ terms.

source

Examples

julia> R = matrix_ring(ZZ, 2)
+

Truncation

Base.truncateMethod
truncate(a::PolynomialElem, n::Int)

Return $a$ truncated to $n$ terms, i.e. the remainder upon division by $x^n$.

source
AbstractAlgebra.mullowMethod
mullow(a::NCPolyRingElem{T}, b::NCPolyRingElem{T}, n::Int) where T <: NCRingElem

Return $a\times b$ truncated to $n$ terms.

source

Examples

julia> R = matrix_ring(ZZ, 2)
 Matrix ring of degree 2
   over integers
 
@@ -137,7 +137,7 @@
 
 julia> k = mullow(f, g, 4)
 (x^2 + x)*y^3 + (x^4 + [3 0; 0 3]*x^2 + [4 0; 0 4]*x + 1)*y^2 + (x^4 + x^3 + [2 0; 0 2]*x^2 + [7 0; 0 7]*x + [5 0; 0 5])*y + [3 0; 0 3]*x^3 + [6 0; 0 6]*x + [6 0; 0 6]
-

Reversal

Base.reverseMethod
reverse(x::PolynomialElem, len::Int)

Return the reverse of the polynomial $x$, thought of as a polynomial of the given length (the polynomial will be notionally truncated or padded with zeroes before the leading term if necessary to match the specified length). The resulting polynomial is normalised. If len is negative we throw a DomainError().

source
Base.reverseMethod
reverse(x::PolynomialElem)

Return the reverse of the polynomial $x$, i.e. the leading coefficient of $x$ becomes the constant coefficient of the result, etc. The resulting polynomial is normalised.

source

Examples

julia> R = matrix_ring(ZZ, 2)
+

Reversal

Base.reverseMethod
reverse(x::PolynomialElem, len::Int)

Return the reverse of the polynomial $x$, thought of as a polynomial of the given length (the polynomial will be notionally truncated or padded with zeroes before the leading term if necessary to match the specified length). The resulting polynomial is normalised. If len is negative we throw a DomainError().

source
Base.reverseMethod
reverse(x::PolynomialElem)

Return the reverse of the polynomial $x$, i.e. the leading coefficient of $x$ becomes the constant coefficient of the result, etc. The resulting polynomial is normalised.

source

Examples

julia> R = matrix_ring(ZZ, 2)
 Matrix ring of degree 2
   over integers
 
@@ -155,7 +155,7 @@
 
 julia> h = reverse(f)
 [3 0; 0 3]*y^2 + (x + 1)*y + x
-

Shifting

AbstractAlgebra.shift_leftMethod
shift_left(f::PolynomialElem, n::Int)

Return the polynomial $f$ shifted left by $n$ terms, i.e. multiplied by $x^n$.

source
AbstractAlgebra.shift_rightMethod
shift_right(f::PolynomialElem, n::Int)

Return the polynomial $f$ shifted right by $n$ terms, i.e. divided by $x^n$.

source

Examples

julia> R = matrix_ring(ZZ, 2)
+

Shifting

AbstractAlgebra.shift_leftMethod
shift_left(f::PolynomialElem, n::Int)

Return the polynomial $f$ shifted left by $n$ terms, i.e. multiplied by $x^n$.

source
AbstractAlgebra.shift_rightMethod
shift_right(f::PolynomialElem, n::Int)

Return the polynomial $f$ shifted right by $n$ terms, i.e. divided by $x^n$.

source

Examples

julia> R = matrix_ring(ZZ, 2)
 Matrix ring of degree 2
   over integers
 
@@ -173,7 +173,7 @@
 
 julia> h = shift_right(f, 2)
 x
-

Evaluation

AbstractAlgebra.evaluateMethod
evaluate(a::NCPolyRingElem, b::T) where T <: NCRingElem

Evaluate the polynomial $a$ at the value $b$ and return the result.

source
AbstractAlgebra.evaluateMethod
evaluate(a::NCPolyRingElem, b::Union{Integer, Rational, AbstractFloat})

Evaluate the polynomial $a$ at the value $b$ and return the result.

source

We also overload the functional notation so that the polynomial $f$ can be evaluated at $a$ by writing $f(a)$.

Examples

julia> R = matrix_ring(ZZ, 2)
+

Evaluation

AbstractAlgebra.evaluateMethod
evaluate(a::NCPolyRingElem, b::T) where T <: NCRingElem

Evaluate the polynomial $a$ at the value $b$ and return the result.

source
AbstractAlgebra.evaluateMethod
evaluate(a::NCPolyRingElem, b::Union{Integer, Rational, AbstractFloat})

Evaluate the polynomial $a$ at the value $b$ and return the result.

source

We also overload the functional notation so that the polynomial $f$ can be evaluated at $a$ by writing $f(a)$.

Examples

julia> R = matrix_ring(ZZ, 2)
 Matrix ring of degree 2
   over integers
 
@@ -195,7 +195,7 @@
 
 julia> r = f(23)
 [552 0; 0 552]*x + [26 0; 0 26]
-

Derivative

AbstractAlgebra.derivativeMethod
derivative(a::PolynomialElem)

Return the derivative of the polynomial $a$.

source

Examples

julia> R = matrix_ring(ZZ, 2)
+

Derivative

AbstractAlgebra.derivativeMethod
derivative(a::PolynomialElem)

Return the derivative of the polynomial $a$.

source

Examples

julia> R = matrix_ring(ZZ, 2)
 Matrix ring of degree 2
   over integers
 
@@ -210,4 +210,4 @@
 
 julia> h = derivative(f)
 [2 0; 0 2]*x*y + x + 1
-
+ diff --git a/dev/ncring_interface/index.html b/dev/ncring_interface/index.html index 546a3d92e..e929c0c71 100644 --- a/dev/ncring_interface/index.html +++ b/dev/ncring_interface/index.html @@ -1,3 +1,3 @@ Noncommutative ring Interface · AbstractAlgebra.jl

Noncommutative ring Interface

AbstractAlgebra.jl supports commutative rings through its Ring interface. In this section we describe the corresponding interface for noncommutative rings. The two interfaces are very similar in terms of required functionality, and so we mainly document the differences here.

Noncommutative rings can be supported through the abstract types NCRing and NCRingElem. Note that we have Ring <: NCRing, etc., so the interface here should more correctly be called the Not-necessarily-Commutative-ring interface.

However, the fact remains that if one wishes to implement a noncommutative ring, one should make its type belong to NCRing but not to Ring. Therefore it is not too much of a mistake to think of the NCRing interface as being for noncommutative rings.

Types

As for the Ring interface, most noncommutative rings must supply two types:

  • a type for the parent object (representing the ring itself)
  • a type for elements of that ring

The parent type must belong to NCRing and the element type must belong to NCRingElem. Of course, the types may belong to these abstract types transitively via an intermediate abstract type.

Also as for the Ring interface, it is advised to make the types of generic parameterised rings that belong to NCRing and NCRingElem depend on the type of the elements of that parameter ring.

NCRingElement type union

As for the Ring interface, the NCRing interface provides a union type NCRingElement in src/julia/JuliaTypes.jl which is a union of NCRingElem and the Julia types Integer, Rational and AbstractFloat.

Most of the generic code in AbstractAlgebra for general rings makes use of the union type NCRingElement instead of NCRingElem so that the generic functions also accept the Julia Base ring types.

As per usual, one may need to implement one ad hoc binary operation for each concrete type belonging to NCRingElement to avoid ambiguity warnings.

Parent object caches

Parent object caches for the NCRing interface operate as per the Ring interface.

Required functions for all rings

Generic functions may only rely on required functionality for the NCRing interface, which must be implemented by all noncommutative rings.

Most of this required functionality is the same as for the Ring interface, so we refer the reader there for details, with the following modifications.

We give this interface for fictitious types MyParent for the type of the ring parent object R and MyElem for the type of the elements of the ring.

Exact division

divexact_left(f::MyElem, g::MyElem)
-divexact_right(f::MyElem, g::MyElem)

If $f = ga$ for some $a$ in the ring, the function divexact_left(f, g) returns a. If $f = ag$ then divexact_right(f, g) returns a. A DivideError() should be thrown if division is by zero. If no exact quotient exists or an impossible inverse is unavoidably encountered, an error should be thrown.

+divexact_right(f::MyElem, g::MyElem)

If $f = ga$ for some $a$ in the ring, the function divexact_left(f, g) returns a. If $f = ag$ then divexact_right(f, g) returns a. A DivideError() should be thrown if division is by zero. If no exact quotient exists or an impossible inverse is unavoidably encountered, an error should be thrown.

diff --git a/dev/perm/index.html b/dev/perm/index.html index 50d40866f..eabac5545 100644 --- a/dev/perm/index.html +++ b/dev/perm/index.html @@ -9,14 +9,14 @@ :cycles julia> Perm([2,3,1,5,4]) -(1,2,3)(4,5)source

Permutations constructors

There are several methods to construct permutations in AbstractAlgebra.jl.

AbstractAlgebra.PermType
Perm{T<:Integer}

The type of permutations. Fieldnames:

  • d::Vector{T} - vector representing the permutation
  • modified::Bool - bit to check the validity of cycle decomposition
  • cycles::CycleDec{T} - (cached) cycle decomposition

A permutation $p$ consists of a vector (p.d) of $n$ integers from $1$ to $n$. If the $i$-th entry of the vector is $j$, this corresponds to $p$ sending $i \to j$. The cycle decomposition (p.cycles) is computed on demand and should never be accessed directly. Use cycles(p) instead.

There are two inner constructors of Perm:

  • Perm(n::T) constructs the trivial Perm{T}-permutation of length $n$.
  • Perm(v::AbstractVector{<:Integer} [,check=true]) constructs a permutation represented by v. By default Perm constructor checks if the vector constitutes a valid permutation. To skip the check call Perm(v, false).

Examples

julia> Perm([1,2,3])
+(1,2,3)(4,5)
source

Permutations constructors

There are several methods to construct permutations in AbstractAlgebra.jl.

AbstractAlgebra.PermType
Perm{T<:Integer}

The type of permutations. Fieldnames:

  • d::Vector{T} - vector representing the permutation
  • modified::Bool - bit to check the validity of cycle decomposition
  • cycles::CycleDec{T} - (cached) cycle decomposition

A permutation $p$ consists of a vector (p.d) of $n$ integers from $1$ to $n$. If the $i$-th entry of the vector is $j$, this corresponds to $p$ sending $i \to j$. The cycle decomposition (p.cycles) is computed on demand and should never be accessed directly. Use cycles(p) instead.

There are two inner constructors of Perm:

  • Perm(n::T) constructs the trivial Perm{T}-permutation of length $n$.
  • Perm(v::AbstractVector{<:Integer} [,check=true]) constructs a permutation represented by v. By default Perm constructor checks if the vector constitutes a valid permutation. To skip the check call Perm(v, false).

Examples

julia> Perm([1,2,3])
 ()
    
 julia> g = Perm(Int32[2,3,1])
 (1,2,3)
 
 julia> typeof(g)
-Perm{Int32}
source

Since the parent object can be reconstructed from the permutation itself, you can work with permutations without explicitly constructing the parent object.

AbstractAlgebra.Generic.SymmetricGroupType
SymmetricGroup{T<:Integer}

The full symmetric group singleton type. SymmetricGroup(n) constructs the full symmetric group $S_n$ on $n$-symbols. The type of elements of the group is inferred from the type of n.

Examples

julia> G = SymmetricGroup(5)
+Perm{Int32}
source

Since the parent object can be reconstructed from the permutation itself, you can work with permutations without explicitly constructing the parent object.

AbstractAlgebra.Generic.SymmetricGroupType
SymmetricGroup{T<:Integer}

The full symmetric group singleton type. SymmetricGroup(n) constructs the full symmetric group $S_n$ on $n$-symbols. The type of elements of the group is inferred from the type of n.

Examples

julia> G = SymmetricGroup(5)
 Full symmetric group over 5 elements
 
 julia> elem_type(G)
@@ -26,7 +26,7 @@
 Full symmetric group over 5 elements
 
 julia> elem_type(H)
-Perm{UInt16}
source

A vector of integers can be then coerced to a permutation by calling a parent permutation group on it. The advantage is that the vector is automatically converted to the integer type fixed at the creation of the parent object.

Examples:

julia> G = SymmetricGroup(BigInt(5)); p = G([2,3,1,5,4])
+Perm{UInt16}
source

A vector of integers can be then coerced to a permutation by calling a parent permutation group on it. The advantage is that the vector is automatically converted to the integer type fixed at the creation of the parent object.

Examples:

julia> G = SymmetricGroup(BigInt(5)); p = G([2,3,1,5,4])
 (1,2,3)(4,5)
 
 julia> typeof(p)
@@ -52,14 +52,14 @@
 (1,3)(2,4)
 
 julia> parent(p) == SymmetricGroup(10)
-true
source

Permutation interface

The following basic functionality is provided by the default permutation group implementation in AbstractAlgebra.jl, to support construction of other generic constructions over permutation groups. Any custom permutation group implementation in AbstractAlgebra.jl should provide the group element arithmetic and comparison.

A custom implementation also needs to implement hash(::Perm, ::UInt) and (possibly) deepcopy_internal(::Perm, ::IdDict).

Note

Permutation group elements are mutable and so returning shallow copies is not sufficient.

getindex(a::Perm, n::Integer)

Allow access to entry $n$ of the given permutation via the syntax a[n]. Note that entries are $1$-indexed.

setindex!(a::Perm, d::Integer, n::Integer)

Set the $n$-th entry of the given permutation to $d$. This allows Julia to provide the syntax a[n] = d for setting entries of a permutation. Entries are $1$-indexed.

Note

Using setindex! invalidates the cycle decomposition cached in a permutation, which will be computed the next time it is needed.

Given the parent object G for a permutation group, the following coercion functions are provided to coerce various arguments into the permutation group. Developers provide these by overloading the permutation group parent objects.

one(G)

Return the identity permutation.

G(A::Vector{<:Integer})

Return the permutation whose entries are given by the elements of the supplied vector.

G(p::Perm)

Take a permutation that is already in the permutation group and simply return it. A copy of the original is not made if not necessary.

Basic manipulation

Numerous functions are provided to manipulate permutation group elements.

AbstractAlgebra.Generic.cyclesMethod
cycles(g::Perm)

Decompose permutation g into disjoint cycles.

Return a CycleDec object which iterates over disjoint cycles of g. The ordering of cycles is not guaranteed, and the order within each cycle is computed up to a cyclic permutation. The cycle decomposition is cached in g and used in future computation of permtype, parity, sign, order and ^ (powering).

Examples

julia> g = Perm([3,4,5,2,1,6])
+true
source

Permutation interface

The following basic functionality is provided by the default permutation group implementation in AbstractAlgebra.jl, to support construction of other generic constructions over permutation groups. Any custom permutation group implementation in AbstractAlgebra.jl should provide the group element arithmetic and comparison.

A custom implementation also needs to implement hash(::Perm, ::UInt) and (possibly) deepcopy_internal(::Perm, ::IdDict).

Note

Permutation group elements are mutable and so returning shallow copies is not sufficient.

getindex(a::Perm, n::Integer)

Allow access to entry $n$ of the given permutation via the syntax a[n]. Note that entries are $1$-indexed.

setindex!(a::Perm, d::Integer, n::Integer)

Set the $n$-th entry of the given permutation to $d$. This allows Julia to provide the syntax a[n] = d for setting entries of a permutation. Entries are $1$-indexed.

Note

Using setindex! invalidates the cycle decomposition cached in a permutation, which will be computed the next time it is needed.

Given the parent object G for a permutation group, the following coercion functions are provided to coerce various arguments into the permutation group. Developers provide these by overloading the permutation group parent objects.

one(G)

Return the identity permutation.

G(A::Vector{<:Integer})

Return the permutation whose entries are given by the elements of the supplied vector.

G(p::Perm)

Take a permutation that is already in the permutation group and simply return it. A copy of the original is not made if not necessary.

Basic manipulation

Numerous functions are provided to manipulate permutation group elements.

AbstractAlgebra.Generic.cyclesMethod
cycles(g::Perm)

Decompose permutation g into disjoint cycles.

Return a CycleDec object which iterates over disjoint cycles of g. The ordering of cycles is not guaranteed, and the order within each cycle is computed up to a cyclic permutation. The cycle decomposition is cached in g and used in future computation of permtype, parity, sign, order and ^ (powering).

Examples

julia> g = Perm([3,4,5,2,1,6])
 (1,3,5)(2,4)
 
 julia> collect(cycles(g))
 3-element Vector{Vector{Int64}}:
  [1, 3, 5]
  [2, 4]
- [6]
source

Cycle structure is cached in a permutation, since once available, it provides a convenient shortcut in many other algorithms.

AbstractAlgebra.Generic.parityMethod
parity(g::Perm)

Return the parity of the given permutation, i.e. the parity of the number of transpositions in any decomposition of g into transpositions.

parity returns $1$ if the number is odd and $0$ otherwise. parity uses cycle decomposition of g if already available, but will not compute it on demand. Since cycle structure is cached in g you may call cycles(g) before calling parity.

Examples

julia> g = Perm([3,4,1,2,5])
+ [6]
source

Cycle structure is cached in a permutation, since once available, it provides a convenient shortcut in many other algorithms.

AbstractAlgebra.Generic.parityMethod
parity(g::Perm)

Return the parity of the given permutation, i.e. the parity of the number of transpositions in any decomposition of g into transpositions.

parity returns $1$ if the number is odd and $0$ otherwise. parity uses cycle decomposition of g if already available, but will not compute it on demand. Since cycle structure is cached in g you may call cycles(g) before calling parity.

Examples

julia> g = Perm([3,4,1,2,5])
 (1,3)(2,4)
 
 julia> parity(g)
@@ -69,7 +69,7 @@
 (1,3,5)(2,4)
 
 julia> parity(g)
-1
source
Base.signMethod
sign(g::Perm)

Return the sign of a permutation.

sign returns $1$ if g is even and $-1$ if g is odd. sign represents the homomorphism from the permutation group to the unit group of $\mathbb{Z}$ whose kernel is the alternating group.

Examples

julia> g = Perm([3,4,1,2,5])
+1
source
Base.signMethod
sign(g::Perm)

Return the sign of a permutation.

sign returns $1$ if g is even and $-1$ if g is odd. sign represents the homomorphism from the permutation group to the unit group of $\mathbb{Z}$ whose kernel is the alternating group.

Examples

julia> g = Perm([3,4,1,2,5])
 (1,3)(2,4)
 
 julia> sign(g)
@@ -79,7 +79,7 @@
 (1,3,5)(2,4)
 
 julia> sign(g)
--1
source
AbstractAlgebra.Generic.permtypeMethod
permtype(g::Perm)

Return the type of permutation g, i.e. lengths of disjoint cycles in cycle decomposition of g.

The lengths are sorted in decreasing order by default. permtype(g) fully determines the conjugacy class of g.

Examples

julia> g = Perm([3,4,5,2,1,6])
+-1
source
AbstractAlgebra.Generic.permtypeMethod
permtype(g::Perm)

Return the type of permutation g, i.e. lengths of disjoint cycles in cycle decomposition of g.

The lengths are sorted in decreasing order by default. permtype(g) fully determines the conjugacy class of g.

Examples

julia> g = Perm([3,4,5,2,1,6])
 (1,3,5)(2,4)
 
 julia> permtype(g)
@@ -98,7 +98,7 @@
  1
  1
  1
- 1
source

Note that even an Int64 can be easily overflowed when computing with symmetric groups. Thus, by default, order returns (always correct) BigInts. If you are sure that the computation will not overflow, you may use order(::Type{T}, ...) to perform computations with machine integers. Julia's standard promotion rules apply for the returned value.

Since SymmetricGroup implements the iterator protocol, you may iterate over all permutations via a simple loop:

for p in SymmetricGroup(n)
+ 1
source

Note that even an Int64 can be easily overflowed when computing with symmetric groups. Thus, by default, order returns (always correct) BigInts. If you are sure that the computation will not overflow, you may use order(::Type{T}, ...) to perform computations with machine integers. Julia's standard promotion rules apply for the returned value.

Since SymmetricGroup implements the iterator protocol, you may iterate over all permutations via a simple loop:

for p in SymmetricGroup(n)
    ...
 end

Iteration over all permutations in reasonable time, (i.e. in terms of minutes) is possible when $n ≤ 13$.

You may also use the non-allocating Generic.elements! function for $n ≤ 14$ (or even $15$ if you are patient enough), which is an order of magnitude faster.

AbstractAlgebra.Generic.elements!Method
Generic.elements!(G::SymmetricGroup)

Return an unsafe iterator over all permutations in G. Only one permutation is allocated and then modified in-place using the non-recursive Heaps algorithm.

Note: you need to explicitly copy permutations intended to be stored or modified.

Examples

julia> elts = Generic.elements!(SymmetricGroup(5));
 
@@ -127,15 +127,15 @@
 
 julia> unique(A)
 1-element Vector{Perm{Int64}}:
- (1,3)
source

However, since all permutations yielded by elements! are aliased (modified "in-place"), collect(Generic.elements!(SymmetricGroup(n))) returns a vector of identical permutations.

Note

If you intend to use or store elements yielded by elements! you need to deepcopy them explicitly.

Arithmetic operators

Base.:*Method
*(g::Perm, h::Perm)

Return the composition $h ∘ g$ of two permutations.

This corresponds to the action of permutation group on the set [1..n] on the right and follows the convention of GAP.

If g and h are parametrized by different types, the result is promoted accordingly.

Examples

julia> Perm([2,3,1,4])*Perm([1,3,4,2]) # (1,2,3)*(2,3,4)
-(1,3)(2,4)
source
Base.:^Method
^(g::Perm, n::Integer)

Return the $n$-th power of a permutation g.

By default g^n is computed by cycle decomposition of g if n > 3. Generic.power_by_squaring provides a different method for powering which may or may not be faster, depending on the particular case. Due to caching of the cycle structure, repeated powering of g will be faster with the default method.

Examples

julia> g = Perm([2,3,4,5,1])
+ (1,3)
source

However, since all permutations yielded by elements! are aliased (modified "in-place"), collect(Generic.elements!(SymmetricGroup(n))) returns a vector of identical permutations.

Note

If you intend to use or store elements yielded by elements! you need to deepcopy them explicitly.

Arithmetic operators

Base.:*Method
*(g::Perm, h::Perm)

Return the composition $h ∘ g$ of two permutations.

This corresponds to the action of permutation group on the set [1..n] on the right and follows the convention of GAP.

If g and h are parametrized by different types, the result is promoted accordingly.

Examples

julia> Perm([2,3,1,4])*Perm([1,3,4,2]) # (1,2,3)*(2,3,4)
+(1,3)(2,4)
source
Base.:^Method
^(g::Perm, n::Integer)

Return the $n$-th power of a permutation g.

By default g^n is computed by cycle decomposition of g if n > 3. Generic.power_by_squaring provides a different method for powering which may or may not be faster, depending on the particular case. Due to caching of the cycle structure, repeated powering of g will be faster with the default method.

Examples

julia> g = Perm([2,3,4,5,1])
 (1,2,3,4,5)
 
 julia> g^3
 (1,4,2,5,3)
 
 julia> g^5
-()
source
Base.invMethod
Base.inv(g::Perm)

Return the inverse of the given permutation, i.e. the permutation $g^{-1}$ such that $g ∘ g^{-1} = g^{-1} ∘ g$ is the identity permutation.

source

Permutations parametrized by different types can be multiplied, and follow the standard julia integer promotion rules:

g = rand(SymmetricGroup(Int8(5)));
+()
source
Base.invMethod
Base.inv(g::Perm)

Return the inverse of the given permutation, i.e. the permutation $g^{-1}$ such that $g ∘ g^{-1} = g^{-1} ∘ g$ is the identity permutation.

source

Permutations parametrized by different types can be multiplied, and follow the standard julia integer promotion rules:

g = rand(SymmetricGroup(Int8(5)));
 h = rand(SymmetricGroup(UInt32(5)));
 typeof(g*h)
 
@@ -147,14 +147,14 @@
 (1,2,3)
 
 julia> g == h
-true
source
Base.:==Method
==(G::SymmetricGroup, H::SymmetricGroup)

Return true if permutation groups are equal, otherwise return false.

Permutation groups on the same number of letters, but parametrized by different integer types are considered different.

Examples

julia> G = SymmetricGroup(UInt(5))
+true
source
Base.:==Method
==(G::SymmetricGroup, H::SymmetricGroup)

Return true if permutation groups are equal, otherwise return false.

Permutation groups on the same number of letters, but parametrized by different integer types are considered different.

Examples

julia> G = SymmetricGroup(UInt(5))
 Permutation group over 5 elements
 
 julia> H = SymmetricGroup(5)
 Permutation group over 5 elements
 
 julia> G == H
-false
source

Misc

Base.randMethod
rand([rng=GLOBAL_RNG,] G::SymmetricGroup)

Return a random permutation from G.

source
AbstractAlgebra.Generic.matrix_reprMethod
matrix_repr(a::Perm)

Return the permutation matrix as a sparse matrix representing a via natural embedding of the permutation group into the general linear group over $\mathbb{Z}$.

Examples

julia> p = Perm([2,3,1])
+false
source

Misc

Base.randMethod
rand([rng=GLOBAL_RNG,] G::SymmetricGroup)

Return a random permutation from G.

source
AbstractAlgebra.Generic.matrix_reprMethod
matrix_repr(a::Perm)

Return the permutation matrix as a sparse matrix representing a via natural embedding of the permutation group into the general linear group over $\mathbb{Z}$.

Examples

julia> p = Perm([2,3,1])
 (1,2,3)
 
 julia> matrix_repr(p)
@@ -167,22 +167,22 @@
 3×3 Matrix{Int64}:
  0  1  0
  0  0  1
- 1  0  0
source
matrix_repr(Y::YoungTableau)

Construct sparse integer matrix representing the tableau.

Examples

julia> y = YoungTableau([4,3,1]);
+ 1  0  0
source
matrix_repr(Y::YoungTableau)

Construct sparse integer matrix representing the tableau.

Examples

julia> y = YoungTableau([4,3,1]);
 
 
 julia> matrix_repr(y)
 3×4 SparseArrays.SparseMatrixCSC{Int64, Int64} with 8 stored entries:
  1  2  3  4
  5  6  7  ⋅
- 8  ⋅  ⋅  ⋅
source
AbstractAlgebra.Generic.embMethod
emb(G::SymmetricGroup, V::Vector{Int}, check::Bool=true)

Return the natural embedding of a permutation group into G as the subgroup permuting points indexed by V.

Examples

julia> p = Perm([2,3,1])
+ 8  ⋅  ⋅  ⋅
source
AbstractAlgebra.Generic.embMethod
emb(G::SymmetricGroup, V::Vector{Int}, check::Bool=true)

Return the natural embedding of a permutation group into G as the subgroup permuting points indexed by V.

Examples

julia> p = Perm([2,3,1])
 (1,2,3)
 
 julia> f = Generic.emb(SymmetricGroup(5), [3,2,5]);
 
 
 julia> f(p)
-(2,5,3)
source
AbstractAlgebra.Generic.emb!Method
emb!(result::Perm, p::Perm, V)

Embed permutation p into permutation result on the indices given by V.

This corresponds to the natural embedding of $S_k$ into $S_n$ as the subgroup permuting points indexed by V.

Examples

julia> p = Perm([2,1,4,3])
+(2,5,3)
source
AbstractAlgebra.Generic.emb!Method
emb!(result::Perm, p::Perm, V)

Embed permutation p into permutation result on the indices given by V.

This corresponds to the natural embedding of $S_k$ into $S_n$ as the subgroup permuting points indexed by V.

Examples

julia> p = Perm([2,1,4,3])
 (1,2)(3,4)
 
 julia> Generic.emb!(Perm(collect(1:5)), p, [3,1,4,5])
-(1,3)(4,5)
source
+(1,3)(4,5)source diff --git a/dev/poly_interface/index.html b/dev/poly_interface/index.html index b1eb3ae20..4f2743c77 100644 --- a/dev/poly_interface/index.html +++ b/dev/poly_interface/index.html @@ -1,4 +1,4 @@ Univariate Polynomial Ring Interface · AbstractAlgebra.jl

Univariate Polynomial Ring Interface

Univariate polynomial rings are supported in AbstractAlgebra, and in addition to the standard Ring interface, numerous additional functions are required to be present for univariate polynomial rings.

Univariate polynomial rings can be built over both commutative and noncommutative rings.

Univariate polynomial rings over a field are also Euclidean and therefore such rings must implement the Euclidean interface.

Since a sparse distributed multivariate format can generally also handle sparse univariate polynomials, the univariate polynomial interface is designed around the assumption that they are dense. This is not a requirement, but it may be easier to use the multivariate interface for sparse univariate types.

Types and parents

AbstractAlgebra provides two abstract types for polynomial rings and their elements over a commutative ring:

  • PolyRing{T} is the abstract type for univariate polynomial ring parent types
  • PolyRingElem{T} is the abstract type for univariate polynomial types

Similarly there are two abstract types for polynomial rings and their elements over a noncommutative ring:

  • NCPolyRing{T} is the abstract type for univariate polynomial ring parent types
  • NCPolyRingElem{T} is the abstract type for univariate polynomial types

We have that PolyRing{T} <: Ring and PolyRingElem{T} <: RingElem. Similarly we have that NCPolyRing{T} <: NCRing and NCPolyRingElem{T} <: NCRingElem.

Note that the abstract types are parameterised. The type T should usually be the type of elements of the coefficient ring of the polynomial ring. For example, in the case of $\mathbb{Z}[x]$ the type T would be the type of an integer, e.g. BigInt.

If the parent object for such a ring has type MyZX and polynomials in that ring have type MyZXPoly then one would have:

  • MyZX <: PolyRing{BigInt}
  • MyZXPoly <: PolyRingElem{BigInt}

Polynomial rings should be made unique on the system by caching parent objects (unless an optional cache parameter is set to false). Polynomial rings should at least be distinguished based on their base (coefficient) ring. But if they have the same base ring and symbol (for their variable/generator), they should certainly have the same parent object.

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Required functionality for univariate polynomials

In addition to the required functionality for the Ring/NCRing interface (and in the case of polynomials over a field, the Euclidean Ring interface), the Polynomial Ring interface has the following required functions.

We suppose that R is a fictitious base ring (coefficient ring) and that S is a univariate polynomial ring over R (i.e. $S = R[x]$) with parent object S of type MyPolyRing{T}. We also assume the polynomials in the ring have type MyPoly{T}, where T is the type of elements of the base (coefficient) ring.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElem or NCRingElem.

We describe the functionality below for polynomials over commutative rings, i.e. with element type belonging to RingElem, however similar constructors should be available for element types belonging to NCRingElem instead, if the coefficient ring is noncommutative.

Constructors

In addition to the standard constructors, the following constructors, taking an array of coefficients, must be available.

(S::MyPolyRing{T})(A::Vector{T}) where T <: RingElem
 (S::MyPolyRing{T})(A::Vector{U}) where T <: RingElem, U <: RingElem
-(S::MyPolyRing{T})(A::Vector{U}) where T <: RingElem, U <: Integer

Create the polynomial in the given ring whose degree $i$ coefficient is given by A[1 + i]. The elements of the array are assumed to be able to be coerced into the base ring R. If the argument is an empty vector, the zero polynomial shall be returned.

It may be desirable to have a additional version of the function that accepts an array of Julia Int values if this can be done more efficiently.

It is also possible to create polynomials directly without first creating the corresponding polynomial ring.

polynomial(R::Ring, arr::Vector{T}, var::VarName=:x; cached::Bool=true)

Given an array of coefficients construct the polynomial with those coefficients over the given ring and with the given variable.

Note

If cached is set to false then the parent ring of the created polynomial is not cached. However, this means that subsequent polynomials created in the same way will not be compatible. Instead, one should use the parent object of the first polynomial to create subsequent polynomials instead of calling this function repeatedly with cached=false.

Data type and parent object methods

var(S::MyPolyRing{T}) where T <: RingElem

Return a Symbol representing the variable (generator) of the polynomial ring. Note that this is a Symbol not a String, though its string value will usually be used when printing polynomials.

symbols(S::MyPolyRing{T}) where T <: RingElem

Return the array [s] where s is a Symbol representing the variable of the given polynomial ring. This is provided for uniformity with the multivariate interface, where there is more than one variable and hence an array of symbols.

dense_poly_type(::Type{T}) where T <: RingElement

Return the type of a polynomial whose coefficients have the given type. In our example MyPoly{T}.

This function is defined for generic polynomials and only needs to be defined for custom polynomial rings, e.g. ones defined by a C implementation.

The default implementation figures out the appropriate polynomial ring type via dense_poly_type and calls its constructor with R, s, cached as arguments. In our example, this would be

MyPolyRing{T}(R, s, cached)

Accordingly, polynomial_ring_only only needs to be defined, if such a constructor does not exist or other behaviour is wanted.

Basic manipulation of rings and elements

length(f::MyPoly{T}) where T <: RingElem

Return the length of the given polynomial. The length of the zero polynomial is defined to be $0$, otherwise the length is the degree plus $1$. The return value should be of type Int.

set_length!(f::MyPoly{T}, n::Int) where T <: RingElem

This function must zero any coefficients beyond the requested length $n$ and then set the length of the polynomial to $n$. This function does not need to normalise the polynomial and is not useful to the user, but is used extensively by the AbstractAlgebra generic functionality.

This function returns the resulting polynomial.

coeff(f::MyPoly{T}, n::Int) where T <: RingElem

Return the coefficient of the polynomial f of degree n. If n is larger than the degree of the polynomial, it should return zero in the coefficient ring.

setcoeff!(f::MyPoly{T}, n::Int, a::T) where T <: RingElem

Set the degree $n$ coefficient of $f$ to $a$. This mutates the polynomial in-place if possible and returns the mutated polynomial (so that immutable types can also be supported). The function must not assume that the polynomial already has space for $n + 1$ coefficients. The polynomial must be resized if this is not the case.

Note that this function is not required to normalise the polynomial and is not necessarily useful to the user, but is used extensively by the generic functionality in AbstractAlgebra.jl. It is for setting raw coefficients in the representation.

normalise(f::MyPoly{T}, n::Int) where T <: RingElem

Given a polynomial whose length is currently $n$, including any leading zero coefficients, return the length of the normalised polynomial (either zero or the length of the polynomial with nonzero leading coefficient). Note that the function does not actually perform the normalisation.

fit!(f::MyPoly{T}, n::Int) where T <: RingElem

Ensure that the polynomial $f$ internally has space for $n$ coefficients. This function must mutate the function in-place if it is mutable. It does not return the mutated polynomial. Immutable types can still be supported by defining this function to do nothing.

Some interfaces for C polynomial types automatically manage the internal allocation of polynomials in every function that can be called on them. Explicit adjustment by the generic code in AbstractAlgebra.jl is not required. In such cases, this function can also be defined to do nothing.

Optional functionality for polynomial rings

Sometimes parts of the Euclidean Ring interface can and should be implemented for polynomials over a ring that is not necessarily a field.

When divisibility testing can be implemented for a polynomial ring over a field, it should be possible to implement the following functions from the Euclidean Ring interface:

  • divides
  • remove
  • valuation

When the given polynomial ring is a GCD domain, with an effective GCD algorithm, it may be possible to implement the following functions:

  • gcd
  • lcm

Polynomial rings can optionally implement any part of the generic univariate polynomial functionality provided by AbstractAlgebra.jl, using the same interface.

Obviously additional functionality can also be added to that provided by AbstractAlgebra.jl on an ad hoc basis.

Similar

The similar function is available for all univariate polynomial types, but new polynomial rings can define a specialised version of it if required.

similar(x::MyPoly{T}, R::Ring=base_ring(x), var::VarName=var(parent(x))) where T <: RingElem

Construct the zero polynomial with the given variable and coefficients in the given ring, if specified, and with the defaults shown if not.

Custom polynomial rings may choose which polynomial type is best-suited to return for any given arguments. If they don't specialise the function the default polynomial type returned is a Generic.Poly.

+(S::MyPolyRing{T})(A::Vector{U}) where T <: RingElem, U <: Integer

Create the polynomial in the given ring whose degree $i$ coefficient is given by A[1 + i]. The elements of the array are assumed to be able to be coerced into the base ring R. If the argument is an empty vector, the zero polynomial shall be returned.

It may be desirable to have a additional version of the function that accepts an array of Julia Int values if this can be done more efficiently.

It is also possible to create polynomials directly without first creating the corresponding polynomial ring.

polynomial(R::Ring, arr::Vector{T}, var::VarName=:x; cached::Bool=true)

Given an array of coefficients construct the polynomial with those coefficients over the given ring and with the given variable.

Note

If cached is set to false then the parent ring of the created polynomial is not cached. However, this means that subsequent polynomials created in the same way will not be compatible. Instead, one should use the parent object of the first polynomial to create subsequent polynomials instead of calling this function repeatedly with cached=false.

Data type and parent object methods

var(S::MyPolyRing{T}) where T <: RingElem

Return a Symbol representing the variable (generator) of the polynomial ring. Note that this is a Symbol not a String, though its string value will usually be used when printing polynomials.

symbols(S::MyPolyRing{T}) where T <: RingElem

Return the array [s] where s is a Symbol representing the variable of the given polynomial ring. This is provided for uniformity with the multivariate interface, where there is more than one variable and hence an array of symbols.

dense_poly_type(::Type{T}) where T <: RingElement

Return the type of a polynomial whose coefficients have the given type. In our example MyPoly{T}.

This function is defined for generic polynomials and only needs to be defined for custom polynomial rings, e.g. ones defined by a C implementation.

AbstractAlgebra.polynomial_ring_onlyMethod
polynomial_ring_only(R::NCRing, s::Symbol; cached::Bool=true)

Like polynomial_ring(R::NCRing, s::Symbol) but return only the polynomial ring.

source

The default implementation figures out the appropriate polynomial ring type via dense_poly_type and calls its constructor with R, s, cached as arguments. In our example, this would be

MyPolyRing{T}(R, s, cached)

Accordingly, polynomial_ring_only only needs to be defined, if such a constructor does not exist or other behaviour is wanted.

Basic manipulation of rings and elements

length(f::MyPoly{T}) where T <: RingElem

Return the length of the given polynomial. The length of the zero polynomial is defined to be $0$, otherwise the length is the degree plus $1$. The return value should be of type Int.

set_length!(f::MyPoly{T}, n::Int) where T <: RingElem

This function must zero any coefficients beyond the requested length $n$ and then set the length of the polynomial to $n$. This function does not need to normalise the polynomial and is not useful to the user, but is used extensively by the AbstractAlgebra generic functionality.

This function returns the resulting polynomial.

coeff(f::MyPoly{T}, n::Int) where T <: RingElem

Return the coefficient of the polynomial f of degree n. If n is larger than the degree of the polynomial, it should return zero in the coefficient ring.

setcoeff!(f::MyPoly{T}, n::Int, a::T) where T <: RingElem

Set the degree $n$ coefficient of $f$ to $a$. This mutates the polynomial in-place if possible and returns the mutated polynomial (so that immutable types can also be supported). The function must not assume that the polynomial already has space for $n + 1$ coefficients. The polynomial must be resized if this is not the case.

Note that this function is not required to normalise the polynomial and is not necessarily useful to the user, but is used extensively by the generic functionality in AbstractAlgebra.jl. It is for setting raw coefficients in the representation.

normalise(f::MyPoly{T}, n::Int) where T <: RingElem

Given a polynomial whose length is currently $n$, including any leading zero coefficients, return the length of the normalised polynomial (either zero or the length of the polynomial with nonzero leading coefficient). Note that the function does not actually perform the normalisation.

fit!(f::MyPoly{T}, n::Int) where T <: RingElem

Ensure that the polynomial $f$ internally has space for $n$ coefficients. This function must mutate the function in-place if it is mutable. It does not return the mutated polynomial. Immutable types can still be supported by defining this function to do nothing.

Some interfaces for C polynomial types automatically manage the internal allocation of polynomials in every function that can be called on them. Explicit adjustment by the generic code in AbstractAlgebra.jl is not required. In such cases, this function can also be defined to do nothing.

Optional functionality for polynomial rings

Sometimes parts of the Euclidean Ring interface can and should be implemented for polynomials over a ring that is not necessarily a field.

When divisibility testing can be implemented for a polynomial ring over a field, it should be possible to implement the following functions from the Euclidean Ring interface:

When the given polynomial ring is a GCD domain, with an effective GCD algorithm, it may be possible to implement the following functions:

Polynomial rings can optionally implement any part of the generic univariate polynomial functionality provided by AbstractAlgebra.jl, using the same interface.

Obviously additional functionality can also be added to that provided by AbstractAlgebra.jl on an ad hoc basis.

Similar

The similar function is available for all univariate polynomial types, but new polynomial rings can define a specialised version of it if required.

similar(x::MyPoly{T}, R::Ring=base_ring(x), var::VarName=var(parent(x))) where T <: RingElem

Construct the zero polynomial with the given variable and coefficients in the given ring, if specified, and with the defaults shown if not.

Custom polynomial rings may choose which polynomial type is best-suited to return for any given arguments. If they don't specialise the function the default polynomial type returned is a Generic.Poly.

diff --git a/dev/polynomial/index.html b/dev/polynomial/index.html index b19aada7d..a9d5917a3 100644 --- a/dev/polynomial/index.html +++ b/dev/polynomial/index.html @@ -3,7 +3,7 @@ (Univariate polynomial ring in x over integers, x) julia> S, y = polynomial_ring(R, :y) -(Univariate polynomial ring in y over R, y)source

A shorthand version of this function is provided: given a base ring R, we abbreviate the constructor as follows.

R[:x]

Here are some examples of creating polynomial rings and their associated generators.

Examples

julia> T, z = QQ[:z]
+(Univariate polynomial ring in y over R, y)
source

A shorthand version of this function is provided: given a base ring R, we abbreviate the constructor as follows.

R[:x]

Here are some examples of creating polynomial rings and their associated generators.

Examples

julia> T, z = QQ[:z]
 (Univariate polynomial ring in z over rationals, z)
 
 julia> U, x = polynomial_ring(ZZ)
@@ -151,8 +151,8 @@
 one(R::PolyRing)
 iszero(a::PolyRingElem)
 isone(a::PolyRingElem)
divexact(a::T, b::T) where T <: PolyRingElem

All functions in the polynomial interface are provided. The most important are the following.

var(S::PolyRing)
-symbols(S::PolyRing{T}) where T <: RingElem

Return a symbol or length 1 array of symbols, respectively, specifying the variable of the polynomial ring. This symbol is converted to a string when printing polynomials in that ring.

In addition, the following basic functions are provided.

AbstractAlgebra.modulusMethod
modulus(a::PolyRingElem{T}) where {T <: ResElem}

Return the modulus of the coefficients of the given polynomial.

source
AbstractAlgebra.leading_coefficientMethod
leading_coefficient(a::PolynomialElem)

Return the leading coefficient of the given polynomial. This will be the nonzero coefficient of the term with highest degree unless the polynomial in the zero polynomial, in which case a zero coefficient is returned.

source
leading_coefficient(p::MPolyRingElem)

Return the leading coefficient of the polynomial $p$.

source
AbstractAlgebra.trailing_coefficientMethod
trailing_coefficient(a::PolynomialElem)

Return the trailing coefficient of the given polynomial. This will be the nonzero coefficient of the term with lowest degree unless the polynomial is the zero polynomial, in which case a zero coefficient is returned.

source
trailing_coefficient(p::MPolyRingElem)

Return the trailing coefficient of the polynomial $p$, i.e. the coefficient of the last nonzero term, or zero if the polynomial is zero.

source
AbstractAlgebra.constant_coefficientMethod
constant_coefficient(a::PolynomialElem)

Return the constant coefficient of the given polynomial. If the polynomial is the zero polynomial, the function will return zero.

source
AbstractAlgebra.set_coefficient!Method
set_coefficient!(c::PolynomialElem{T}, n::Int, a::T) where T <: RingElement
-set_coefficient!(c::PolynomialElem{T}, n::Int, a::U) where {T <: RingElement, U <: Integer}

Set the coefficient of degree $n$ to $a$.

source
AbstractAlgebra.tailMethod
tail(a::PolynomialElem)

Return the tail of the given polynomial, i.e. the polynomial without its leading term (if any).

source
AbstractAlgebra.genMethod
gen(a::MPolyRing{T}, i::Int) where {T <: RingElement}

Return the $i$-th generator (variable) of the given polynomial ring.

source
gen(R::AbsPowerSeriesRing{T}) where T <: RingElement

Return the generator of the power series ring, i.e. $x + O(x^n)$ where $n$ is the precision of the power series ring $R$.

source
AbstractAlgebra.is_genMethod
is_gen(a::PolynomialElem)

Return true if the given polynomial is the constant generator of its polynomial ring, otherwise return false.

source
is_gen(x::MPoly{T}) where {T <: RingElement}

Return true if the given polynomial is a generator (variable) of the polynomial ring it belongs to.

source
AbstractAlgebra.is_monicMethod
is_monic(a::PolynomialElem)

Return true if the given polynomial is monic, i.e. has leading coefficient equal to one, otherwise return false.

source
AbstractAlgebra.is_squareMethod
is_square(f::PolyRingElem{T}) where T <: RingElement

Return true if $f$ is a perfect square.

source
is_square(a::FracElem{T}) where T <: RingElem

Return true if $a$ is a square.

source
Base.lengthMethod
length(a::PolynomialElem)

Return the length of the polynomial. The length of a univariate polynomial is defined to be the number of coefficients in its dense representation, including zero coefficients. Thus naturally the zero polynomial has length zero and additionally for nonzero polynomials the length is one more than the degree. (Note that the leading coefficient will always be nonzero.)

source
AbstractAlgebra.degreeMethod
degree(a::PolynomialElem)

Return the degree of the given polynomial. This is defined to be one less than the length, even for constant polynomials.

source
AbstractAlgebra.is_monomialMethod
is_monomial(a::PolynomialElem)

Return true if the given polynomial is a monomial.

source
is_monomial(x::MPolyRingElem)

Return true if the given polynomial has precisely one term whose coefficient is one.

source
AbstractAlgebra.is_monomial_recursiveMethod
is_monomial_recursive(a::PolynomialElem)

Return true if the given polynomial is a monomial. This function is recursive, with all scalar types returning true.

source
AbstractAlgebra.is_termMethod
is_term(a::PolynomialElem)

Return true if the given polynomial has one term.

source
is_term(x::MPolyRingElem)

Return true if the given polynomial has precisely one term.

source
AbstractAlgebra.is_term_recursiveMethod
is_term_recursive(a::PolynomialElem)

Return true if the given polynomial has one term. This function is recursive, with all scalar types returning true.

source
AbstractAlgebra.is_constantMethod
is_constant(a::PolynomialElem)

Return true if a is a degree zero polynomial or the zero polynomial, i.e. a constant polynomial.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+symbols(S::PolyRing{T}) where T <: RingElem

Return a symbol or length 1 array of symbols, respectively, specifying the variable of the polynomial ring. This symbol is converted to a string when printing polynomials in that ring.

In addition, the following basic functions are provided.

AbstractAlgebra.modulusMethod
modulus(a::PolyRingElem{T}) where {T <: ResElem}

Return the modulus of the coefficients of the given polynomial.

source
AbstractAlgebra.leading_coefficientMethod
leading_coefficient(a::PolynomialElem)

Return the leading coefficient of the given polynomial. This will be the nonzero coefficient of the term with highest degree unless the polynomial in the zero polynomial, in which case a zero coefficient is returned.

source
leading_coefficient(p::MPolyRingElem)

Return the leading coefficient of the polynomial $p$.

source
AbstractAlgebra.trailing_coefficientMethod
trailing_coefficient(a::PolynomialElem)

Return the trailing coefficient of the given polynomial. This will be the nonzero coefficient of the term with lowest degree unless the polynomial is the zero polynomial, in which case a zero coefficient is returned.

source
trailing_coefficient(p::MPolyRingElem)

Return the trailing coefficient of the polynomial $p$, i.e. the coefficient of the last nonzero term, or zero if the polynomial is zero.

source
AbstractAlgebra.constant_coefficientMethod
constant_coefficient(a::PolynomialElem)

Return the constant coefficient of the given polynomial. If the polynomial is the zero polynomial, the function will return zero.

source
AbstractAlgebra.set_coefficient!Method
set_coefficient!(c::PolynomialElem{T}, n::Int, a::T) where T <: RingElement
+set_coefficient!(c::PolynomialElem{T}, n::Int, a::U) where {T <: RingElement, U <: Integer}

Set the coefficient of degree $n$ to $a$.

source
AbstractAlgebra.tailMethod
tail(a::PolynomialElem)

Return the tail of the given polynomial, i.e. the polynomial without its leading term (if any).

source
AbstractAlgebra.genMethod
gen(a::MPolyRing{T}, i::Int) where {T <: RingElement}

Return the $i$-th generator (variable) of the given polynomial ring.

source
gen(R::AbsPowerSeriesRing{T}) where T <: RingElement

Return the generator of the power series ring, i.e. $x + O(x^n)$ where $n$ is the precision of the power series ring $R$.

source
AbstractAlgebra.is_genMethod
is_gen(a::PolynomialElem)

Return true if the given polynomial is the constant generator of its polynomial ring, otherwise return false.

source
is_gen(x::MPoly{T}) where {T <: RingElement}

Return true if the given polynomial is a generator (variable) of the polynomial ring it belongs to.

source
AbstractAlgebra.is_monicMethod
is_monic(a::PolynomialElem)

Return true if the given polynomial is monic, i.e. has leading coefficient equal to one, otherwise return false.

source
AbstractAlgebra.is_squareMethod
is_square(f::PolyRingElem{T}) where T <: RingElement

Return true if $f$ is a perfect square.

source
is_square(a::FracElem{T}) where T <: RingElem

Return true if $a$ is a square.

source
Base.lengthMethod
length(a::PolynomialElem)

Return the length of the polynomial. The length of a univariate polynomial is defined to be the number of coefficients in its dense representation, including zero coefficients. Thus naturally the zero polynomial has length zero and additionally for nonzero polynomials the length is one more than the degree. (Note that the leading coefficient will always be nonzero.)

source
AbstractAlgebra.degreeMethod
degree(a::PolynomialElem)

Return the degree of the given polynomial. This is defined to be one less than the length, even for constant polynomials.

source
AbstractAlgebra.is_monomialMethod
is_monomial(a::PolynomialElem)

Return true if the given polynomial is a monomial.

source
is_monomial(x::MPolyRingElem)

Return true if the given polynomial has precisely one term whose coefficient is one.

source
AbstractAlgebra.is_monomial_recursiveMethod
is_monomial_recursive(a::PolynomialElem)

Return true if the given polynomial is a monomial. This function is recursive, with all scalar types returning true.

source
AbstractAlgebra.is_termMethod
is_term(a::PolynomialElem)

Return true if the given polynomial has one term.

source
is_term(x::MPolyRingElem)

Return true if the given polynomial has precisely one term.

source
AbstractAlgebra.is_term_recursiveMethod
is_term_recursive(a::PolynomialElem)

Return true if the given polynomial has one term. This function is recursive, with all scalar types returning true.

source
AbstractAlgebra.is_constantMethod
is_constant(a::PolynomialElem)

Return true if a is a degree zero polynomial or the zero polynomial, i.e. a constant polynomial.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -256,7 +256,7 @@
        end
 2
 0
-1

Truncation

Base.truncateMethod
truncate(a::PolynomialElem, n::Int)

Return $a$ truncated to $n$ terms, i.e. the remainder upon division by $x^n$.

source
AbstractAlgebra.mullowMethod
mullow(a::PolyRingElem{T}, b::PolyRingElem{T}, n::Int) where T <: RingElement

Return $a\times b$ truncated to $n$ terms.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+1

Truncation

Base.truncateMethod
truncate(a::PolynomialElem, n::Int)

Return $a$ truncated to $n$ terms, i.e. the remainder upon division by $x^n$.

source
AbstractAlgebra.mullowMethod
mullow(a::PolyRingElem{T}, b::PolyRingElem{T}, n::Int) where T <: RingElement

Return $a\times b$ truncated to $n$ terms.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -273,7 +273,7 @@
 
 julia> k = mullow(f, g, 4)
 (x^2 + x)*y^3 + (x^4 + 3*x^2 + 4*x + 1)*y^2 + (x^4 + x^3 + 2*x^2 + 7*x + 5)*y + 3*x^3 + 6*x + 6
-

Reversal

Base.reverseMethod
reverse(x::PolynomialElem, len::Int)

Return the reverse of the polynomial $x$, thought of as a polynomial of the given length (the polynomial will be notionally truncated or padded with zeroes before the leading term if necessary to match the specified length). The resulting polynomial is normalised. If len is negative we throw a DomainError().

source
Base.reverseMethod
reverse(x::PolynomialElem)

Return the reverse of the polynomial $x$, i.e. the leading coefficient of $x$ becomes the constant coefficient of the result, etc. The resulting polynomial is normalised.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+

Reversal

Base.reverseMethod
reverse(x::PolynomialElem, len::Int)

Return the reverse of the polynomial $x$, thought of as a polynomial of the given length (the polynomial will be notionally truncated or padded with zeroes before the leading term if necessary to match the specified length). The resulting polynomial is normalised. If len is negative we throw a DomainError().

source
Base.reverseMethod
reverse(x::PolynomialElem)

Return the reverse of the polynomial $x$, i.e. the leading coefficient of $x$ becomes the constant coefficient of the result, etc. The resulting polynomial is normalised.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -287,7 +287,7 @@
 
 julia> h = reverse(f)
 3*y^2 + (x + 1)*y + x
-

Shifting

AbstractAlgebra.shift_leftMethod
shift_left(f::PolynomialElem, n::Int)

Return the polynomial $f$ shifted left by $n$ terms, i.e. multiplied by $x^n$.

source
AbstractAlgebra.shift_rightMethod
shift_right(f::PolynomialElem, n::Int)

Return the polynomial $f$ shifted right by $n$ terms, i.e. divided by $x^n$.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+

Shifting

AbstractAlgebra.shift_leftMethod
shift_left(f::PolynomialElem, n::Int)

Return the polynomial $f$ shifted left by $n$ terms, i.e. multiplied by $x^n$.

source
AbstractAlgebra.shift_rightMethod
shift_right(f::PolynomialElem, n::Int)

Return the polynomial $f$ shifted right by $n$ terms, i.e. divided by $x^n$.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -301,12 +301,12 @@
 
 julia> h = shift_right(f, 2)
 x
-

Inflation and deflation

AbstractAlgebra.deflationMethod
deflation(p::PolyRingElem)

Return a tuple (shift, defl) where shift is the exponent of the trailing term of $p$ and defl is the gcd of the distance between the exponents of the nonzero terms of $p$. If $p = 0$, both shift and defl will be zero.

source
AbstractAlgebra.inflateMethod
inflate(f::PolyRingElem, shift::Int64, n::Int64) -> PolyRingElem

Given a polynomial $f$ in $x$, return $f(x^n)*x^j$, i.e. multiply all exponents by $n$ and shift $f$ left by $j$.

source
AbstractAlgebra.inflateMethod
inflate(f::PolyRingElem, n::Int64) -> PolyRingElem

Given a polynomial $f$ in $x$, return $f(x^n)$, i.e. multiply all exponents by $n$.

source
AbstractAlgebra.deflateMethod
deflate(f::PolyRingElem, shift::Int64, n::Int64) -> PolyRingElem

Given a polynomial $g$ in $x^n$ such that f = g(x)*x^{shift}, write $f$ as a polynomial in $x$, i.e. divide all exponents of $g$ by $n$.

source
AbstractAlgebra.deflateMethod
deflate(f::PolyRingElem, n::Int64) -> PolyRingElem

Given a polynomial $f$ in $x^n$, write it as a polynomial in $x$, i.e. divide all exponents by $n$.

source
AbstractAlgebra.deflateMethod
deflate(x::PolyRingElem) -> PolyRingElem, Int

Deflate the polynomial $f$ maximally, i.e. find the largest $n$ s.th. $f$ can be deflated by $n$, i.e. $f$ is actually a polynomial in $x^n$. Return $g, n$ where $g$ is the deflation of $f$.

source

Square root

Base.sqrtMethod
Base.sqrt(f::PolyRingElem{T}; check::Bool=true) where T <: RingElement

Return the square root of $f$. By default the function checks the input is square and raises an exception if not. If check=false this check is omitted.

source
sqrt(a::Generic.PuiseuxSeriesElem{T}; check::Bool=true) where T <: RingElement

Return the square root of the given Puiseux series $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source

Examples

R, x = polynomial_ring(ZZ, :x)
+

Inflation and deflation

AbstractAlgebra.deflationMethod
deflation(p::PolyRingElem)

Return a tuple (shift, defl) where shift is the exponent of the trailing term of $p$ and defl is the gcd of the distance between the exponents of the nonzero terms of $p$. If $p = 0$, both shift and defl will be zero.

source
AbstractAlgebra.inflateMethod
inflate(f::PolyRingElem, shift::Int64, n::Int64) -> PolyRingElem

Given a polynomial $f$ in $x$, return $f(x^n)*x^j$, i.e. multiply all exponents by $n$ and shift $f$ left by $j$.

source
AbstractAlgebra.inflateMethod
inflate(f::PolyRingElem, n::Int64) -> PolyRingElem

Given a polynomial $f$ in $x$, return $f(x^n)$, i.e. multiply all exponents by $n$.

source
AbstractAlgebra.deflateMethod
deflate(f::PolyRingElem, shift::Int64, n::Int64) -> PolyRingElem

Given a polynomial $g$ in $x^n$ such that f = g(x)*x^{shift}, write $f$ as a polynomial in $x$, i.e. divide all exponents of $g$ by $n$.

source
AbstractAlgebra.deflateMethod
deflate(f::PolyRingElem, n::Int64) -> PolyRingElem

Given a polynomial $f$ in $x^n$, write it as a polynomial in $x$, i.e. divide all exponents by $n$.

source
AbstractAlgebra.deflateMethod
deflate(x::PolyRingElem) -> PolyRingElem, Int

Deflate the polynomial $f$ maximally, i.e. find the largest $n$ s.th. $f$ can be deflated by $n$, i.e. $f$ is actually a polynomial in $x^n$. Return $g, n$ where $g$ is the deflation of $f$.

source

Square root

Base.sqrtMethod
Base.sqrt(f::PolyRingElem{T}; check::Bool=true) where T <: RingElement

Return the square root of $f$. By default the function checks the input is square and raises an exception if not. If check=false this check is omitted.

source
sqrt(a::Generic.PuiseuxSeriesElem{T}; check::Bool=true) where T <: RingElement

Return the square root of the given Puiseux series $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source

Examples

R, x = polynomial_ring(ZZ, :x)
 g = x^2+6*x+1
-sqrt(g^2)

Change of base ring

AbstractAlgebra.change_base_ringMethod
change_base_ring(R::Ring, p::PolyRingElem{<: RingElement}; parent::PolyRing)

Return the polynomial obtained by coercing the non-zero coefficients of p into R.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source
AbstractAlgebra.change_coefficient_ringMethod
change_coefficient_ring(R::Ring, p::PolyRingElem{<: RingElement}; parent::PolyRing)

Return the polynomial obtained by coercing the non-zero coefficients of p into R.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source
AbstractAlgebra.map_coefficientsMethod
map_coefficients(f, p::PolyRingElem{<: RingElement}; cached::Bool=true, parent::PolyRing)

Transform the polynomial p by applying f on each non-zero coefficient.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source

Examples

R, x = polynomial_ring(ZZ, :x)
+sqrt(g^2)

Change of base ring

AbstractAlgebra.change_base_ringMethod
change_base_ring(R::Ring, p::PolyRingElem{<: RingElement}; parent::PolyRing)

Return the polynomial obtained by coercing the non-zero coefficients of p into R.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source
AbstractAlgebra.change_coefficient_ringMethod
change_coefficient_ring(R::Ring, p::PolyRingElem{<: RingElement}; parent::PolyRing)

Return the polynomial obtained by coercing the non-zero coefficients of p into R.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source
AbstractAlgebra.map_coefficientsMethod
map_coefficients(f, p::PolyRingElem{<: RingElement}; cached::Bool=true, parent::PolyRing)

Transform the polynomial p by applying f on each non-zero coefficient.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source

Examples

R, x = polynomial_ring(ZZ, :x)
 g = x^3+6*x + 1
 change_base_ring(GF(2), g)
-change_coefficient_ring(GF(2), g)

Pseudodivision

Given two polynomials $a, b$, pseudodivision computes polynomials $q$ and $r$ with length$(r) <$ length$(b)$ such that $L^d a = bq + r,$ where $d =$ length$(a) -$ length$(b) + 1$ and $L$ is the leading coefficient of $b$.

We call $q$ the pseudoquotient and $r$ the pseudoremainder.

AbstractAlgebra.pseudoremMethod
pseudorem(f::PolyRingElem{T}, g::PolyRingElem{T}) where T <: RingElement

Return the pseudoremainder of $f$ divided by $g$. If $g = 0$ we throw a DivideError().

source
AbstractAlgebra.pseudodivremMethod
pseudodivrem(f::PolyRingElem{T}, g::PolyRingElem{T}) where T <: RingElement

Return a tuple $(q, r)$ consisting of the pseudoquotient and pseudoremainder of $f$ divided by $g$. If $g = 0$ we throw a DivideError().

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+change_coefficient_ring(GF(2), g)

Pseudodivision

Given two polynomials $a, b$, pseudodivision computes polynomials $q$ and $r$ with length$(r) <$ length$(b)$ such that $L^d a = bq + r,$ where $d =$ length$(a) -$ length$(b) + 1$ and $L$ is the leading coefficient of $b$.

We call $q$ the pseudoquotient and $r$ the pseudoremainder.

AbstractAlgebra.pseudoremMethod
pseudorem(f::PolyRingElem{T}, g::PolyRingElem{T}) where T <: RingElement

Return the pseudoremainder of $f$ divided by $g$. If $g = 0$ we throw a DivideError().

source
AbstractAlgebra.pseudodivremMethod
pseudodivrem(f::PolyRingElem{T}, g::PolyRingElem{T}) where T <: RingElement

Return a tuple $(q, r)$ consisting of the pseudoquotient and pseudoremainder of $f$ divided by $g$. If $g = 0$ we throw a DivideError().

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -323,13 +323,13 @@
 
 julia> q, r = pseudodivrem(f, g)
 ((x^2 + x)*y - x^4 - x^2 + 1, x^7 + 3*x^5 + 2*x^4 + x^3 + 5*x^2 + 4*x + 1)
-

Content and primitive part

AbstractAlgebra.contentMethod
content(a::PolyRingElem)

Return the content of $a$, i.e. the greatest common divisor of its coefficients.

source
AbstractAlgebra.primpartMethod
primpart(a::PolyRingElem)

Return the primitive part of $a$, i.e. the polynomial divided by its content.

source

Examples

R, x = polynomial_ring(ZZ, :x)
+

Content and primitive part

AbstractAlgebra.contentMethod
content(a::PolyRingElem)

Return the content of $a$, i.e. the greatest common divisor of its coefficients.

source
AbstractAlgebra.primpartMethod
primpart(a::PolyRingElem)

Return the primitive part of $a$, i.e. the polynomial divided by its content.

source

Examples

R, x = polynomial_ring(ZZ, :x)
 S, y = polynomial_ring(R, :y)
 
 k = x*y^2 + (x + 1)*y + 3
 
 n = content(k)
-p = primpart(k*(x^2 + 1))

Evaluation, composition and substitution

AbstractAlgebra.evaluateMethod
evaluate(a::PolyRingElem, b::T) where T <: RingElement

Evaluate the polynomial expression $a$ at the value $b$ and return the result.

source
AbstractAlgebra.composeMethod
compose(f::PolyRingElem, g::PolyRingElem; inner)

Compose the polynomial $a$ with the polynomial $b$ and return the result.

  • If inner = :right, then f(g) is returned.
  • If inner = :left, then g(f) is returned.
source
AbstractAlgebra.substMethod
subst(f::PolyRingElem{T}, a::Any) where T <: RingElement

Evaluate the polynomial $f$ at $a$. Note that $a$ can be anything, whether a ring element or not.

source

We also overload the functional notation so that the polynomial $f$ can be evaluated at $a$ by writing $f(a)$.

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+p = primpart(k*(x^2 + 1))

Evaluation, composition and substitution

AbstractAlgebra.evaluateMethod
evaluate(a::PolyRingElem, b::T) where T <: RingElement

Evaluate the polynomial expression $a$ at the value $b$ and return the result.

source
AbstractAlgebra.composeMethod
compose(f::PolyRingElem, g::PolyRingElem; inner)

Compose the polynomial $a$ with the polynomial $b$ and return the result.

  • If inner = :right, then f(g) is returned.
  • If inner = :left, then g(f) is returned.
source
AbstractAlgebra.substMethod
subst(f::PolyRingElem{T}, a::Any) where T <: RingElement

Evaluate the polynomial $f$ at $a$. Note that $a$ can be anything, whether a ring element or not.

source

We also overload the functional notation so that the polynomial $f$ can be evaluated at $a$ by writing $f(a)$.

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -364,21 +364,21 @@
 
 julia> r = f(23)
 552*x + 26
-

Derivative and integral

AbstractAlgebra.derivativeMethod
derivative(a::PolynomialElem)

Return the derivative of the polynomial $a$.

source
derivative(f::AbsPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

source
derivative(f::RelPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
+

Derivative and integral

AbstractAlgebra.derivativeMethod
derivative(a::PolynomialElem)

Return the derivative of the polynomial $a$.

source
derivative(f::AbsPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

source
derivative(f::RelPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
 (Univariate power series ring in x over Rationals, x + O(x^11))
 
 julia> f = 2 + x + 3x^3
 2 + x + 3*x^3 + O(x^10)
 
 julia> derivative(f)
-1 + 9*x^2 + O(x^9)
source
derivative(f::MPolyRingElem{T}, j::Int) where {T <: RingElement}

Return the partial derivative of f with respect to $j$-th variable of the polynomial ring.

source
derivative(f::MPolyRingElem{T}, x::MPolyRingElem{T}) where T <: RingElement

Return the partial derivative of f with respect to x. The value x must be a generator of the polynomial ring of f.

source
derivative(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the derivative of the given Puiseux series $a$.

source
AbstractAlgebra.integralMethod
integral(x::PolyRingElem{T}) where {T <: Union{ResElem, FieldElement}}

Return the integral of the polynomial $x$.

source
integral(f::AbsPowerSeriesRingElem{T})

Return the integral of the power series $f$.

source
integral(f::RelPowerSeriesRingElem{T})

Return the integral of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
+1 + 9*x^2 + O(x^9)
source
derivative(f::MPolyRingElem{T}, j::Int) where {T <: RingElement}

Return the partial derivative of f with respect to $j$-th variable of the polynomial ring.

source
derivative(f::MPolyRingElem{T}, x::MPolyRingElem{T}) where T <: RingElement

Return the partial derivative of f with respect to x. The value x must be a generator of the polynomial ring of f.

source
derivative(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the derivative of the given Puiseux series $a$.

source
AbstractAlgebra.integralMethod
integral(x::PolyRingElem{T}) where {T <: Union{ResElem, FieldElement}}

Return the integral of the polynomial $x$.

source
integral(f::AbsPowerSeriesRingElem{T})

Return the integral of the power series $f$.

source
integral(f::RelPowerSeriesRingElem{T})

Return the integral of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
 (Univariate power series ring in x over Rationals, x + O(x^11))
 
 julia> f = 2 + x + 3x^3
 2 + x + 3*x^3 + O(x^10)
 
 julia> integral(f)
-2*x + 1//2*x^2 + 3//4*x^4 + O(x^11)
source
integral(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the integral of the given Puiseux series $a$.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+2*x + 1//2*x^2 + 3//4*x^4 + O(x^11)
source
integral(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the integral of the given Puiseux series $a$.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -403,7 +403,7 @@
 
 julia> k = integral(g)
 (1//3*z^2 + 2//3*z + 1//3)*w^3 + (1//2*z + 1//2)*w^2 + (-2*z + 4)*w
-

Resultant and discriminant

AbstractAlgebra.sylvester_matrixMethod
sylvester_matrix(p::PolyRingElem, q::PolyRingElem)

Return the sylvester matrix of the given polynomials.

source
AbstractAlgebra.resultantMethod
resultant(p::PolyRingElem{T}, q::PolyRingElem{T}) where T <: RingElement

Return the resultant of the given polynomials.

source
AbstractAlgebra.resxMethod
resx(a::PolyRingElem{T}, b::PolyRingElem{T}) where T <: RingElement

Return a tuple $(r, s, t)$ such that $r$ is the resultant of $a$ and $b$ and such that $r = a\times s + b\times t$.

source
AbstractAlgebra.discriminantMethod
discriminant(a::PolyRingElem)

Return the discriminant of the given polynomial.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+

Resultant and discriminant

AbstractAlgebra.sylvester_matrixMethod
sylvester_matrix(p::PolyRingElem, q::PolyRingElem)

Return the sylvester matrix of the given polynomials.

source
AbstractAlgebra.resultantMethod
resultant(p::PolyRingElem{T}, q::PolyRingElem{T}) where T <: RingElement

Return the resultant of the given polynomials.

source
AbstractAlgebra.resxMethod
resx(a::PolyRingElem{T}, b::PolyRingElem{T}) where T <: RingElement

Return a tuple $(r, s, t)$ such that $r$ is the resultant of $a$ and $b$ and such that $r = a\times s + b\times t$.

source
AbstractAlgebra.discriminantMethod
discriminant(a::PolyRingElem)

Return the discriminant of the given polynomial.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -425,7 +425,7 @@
 
 julia> k = discriminant(f)
 x^2 - 34*x + 1
-

Newton representation

AbstractAlgebra.monomial_to_newton!Method
monomial_to_newton!(P::Vector{T}, roots::Vector{T}) where T <: RingElement

Converts a polynomial $p$, given as an array of coefficients, in-place from its coefficients given in the standard monomial basis to the Newton basis for the roots $r_0, r_1, \ldots, r_{n-2}$. In other words, this determines output coefficients $c_i$ such that $c_0 + c_1(x-r_0) + c_2(x-r_0)(x-r_1) + \ldots + c_{n-1}(x-r_0)(x-r_1)\cdots(x-r_{n-2})$ is equal to the input polynomial.

source
AbstractAlgebra.newton_to_monomial!Method
newton_to_monomial!(P::Vector{T}, roots::Vector{T}) where T <: RingElement

Converts a polynomial $p$, given as an array of coefficients, in-place from its coefficients given in the Newton basis for the roots $r_0, r_1, \ldots, r_{n-2}$ to the standard monomial basis. In other words, this evaluates $c_0 + c_1(x-r_0) + c_2(x-r_0)(x-r_1) + \ldots + c_{n-1}(x-r_0)(x-r_1)\cdots(x-r_{n-2})$ where $c_i$ are the input coefficients given by $p$.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+

Newton representation

AbstractAlgebra.monomial_to_newton!Method
monomial_to_newton!(P::Vector{T}, roots::Vector{T}) where T <: RingElement

Converts a polynomial $p$, given as an array of coefficients, in-place from its coefficients given in the standard monomial basis to the Newton basis for the roots $r_0, r_1, \ldots, r_{n-2}$. In other words, this determines output coefficients $c_i$ such that $c_0 + c_1(x-r_0) + c_2(x-r_0)(x-r_1) + \ldots + c_{n-1}(x-r_0)(x-r_1)\cdots(x-r_{n-2})$ is equal to the input polynomial.

source
AbstractAlgebra.newton_to_monomial!Method
newton_to_monomial!(P::Vector{T}, roots::Vector{T}) where T <: RingElement

Converts a polynomial $p$, given as an array of coefficients, in-place from its coefficients given in the Newton basis for the roots $r_0, r_1, \ldots, r_{n-2}$ to the standard monomial basis. In other words, this evaluates $c_0 + c_1(x-r_0) + c_2(x-r_0)(x-r_1) + \ldots + c_{n-1}(x-r_0)(x-r_1)\cdots(x-r_{n-2})$ where $c_i$ are the input coefficients given by $p$.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -445,7 +445,7 @@
 
 julia> monomial_to_newton!(g.coeffs, roots)
 
-julia> newton_to_monomial!(g.coeffs, roots)

Roots

AbstractAlgebra.Generic.rootsMethod
roots(f::PolyRingElem)

Returns the roots of the polynomial f in the base ring of f as an array.

source
AbstractAlgebra.Generic.rootsMethod
roots(R::Field, f::PolyRingElem)

Returns the roots of the polynomial f in the field R as an array.

source

Interpolation

AbstractAlgebra.interpolateMethod
interpolate(S::PolyRing, x::Vector{T}, y::Vector{T}) where T <: RingElement

Given two arrays of values $xs$ and $ys$ of the same length $n$, find the polynomial $f$ in the polynomial ring $R$ of length at most $n$ such that $f$ has the value $ys$ at the points $xs$. The values in the arrays $xs$ and $ys$ must belong to the base ring of the polynomial ring $R$. If no such polynomial exists, an exception is raised.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+julia> newton_to_monomial!(g.coeffs, roots)

Roots

AbstractAlgebra.Generic.rootsMethod
roots(f::PolyRingElem)

Returns the roots of the polynomial f in the base ring of f as an array.

source
AbstractAlgebra.Generic.rootsMethod
roots(R::Field, f::PolyRingElem)

Returns the roots of the polynomial f in the field R as an array.

source

Interpolation

AbstractAlgebra.interpolateMethod
interpolate(S::PolyRing, x::Vector{T}, y::Vector{T}) where T <: RingElement

Given two arrays of values $xs$ and $ys$ of the same length $n$, find the polynomial $f$ in the polynomial ring $R$ of length at most $n$ such that $f$ has the value $ys$ at the points $xs$. The values in the arrays $xs$ and $ys$ must belong to the base ring of the polynomial ring $R$. If no such polynomial exists, an exception is raised.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -467,8 +467,8 @@
 
 julia> f = interpolate(S, xs, ys)
 y^2
-

Power sums

AbstractAlgebra.polynomial_to_power_sumsMethod
polynomial_to_power_sums(f::PolyRingElem{T}, n::Int=degree(f)) where T <: RingElement -> Vector{T}

Uses Newton (or Newton-Girard) formulas to compute the first $n$ sums of powers of the roots of $f$ from the coefficients of $f$, starting with the sum of (first powers of) the roots. The input polynomial must be monic, at least degree $1$ and have nonzero constant coefficient.

source
AbstractAlgebra.power_sums_to_polynomialMethod
power_sums_to_polynomial(P::Vector{T};
-                 parent::PolyRing{T}=PolyRing(parent(P[1])) where T <: RingElement -> PolyRingElem{T}

Uses the Newton (or Newton-Girard) identities to obtain the polynomial with given sums of powers of roots. The list must be nonempty and contain degree(f) entries where $f$ is the polynomial to be recovered. The list must start with the sum of first powers of the roots.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+

Power sums

AbstractAlgebra.polynomial_to_power_sumsMethod
polynomial_to_power_sums(f::PolyRingElem{T}, n::Int=degree(f)) where T <: RingElement -> Vector{T}

Uses Newton (or Newton-Girard) formulas to compute the first $n$ sums of powers of the roots of $f$ from the coefficients of $f$, starting with the sum of (first powers of) the roots. The input polynomial must be monic, at least degree $1$ and have nonzero constant coefficient.

source
AbstractAlgebra.power_sums_to_polynomialMethod
power_sums_to_polynomial(P::Vector{T};
+                 parent::PolyRing{T}=PolyRing(parent(P[1])) where T <: RingElement -> PolyRingElem{T}

Uses the Newton (or Newton-Girard) identities to obtain the polynomial with given sums of powers of roots. The list must be nonempty and contain degree(f) entries where $f$ is the polynomial to be recovered. The list must start with the sum of first powers of the roots.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> f = x^4 - 2*x^3 + 10*x^2 + 7*x - 5
@@ -482,7 +482,7 @@
   20
 
 julia> power_sums_to_polynomial(V)
-x^4 - 2*x^3 + 10*x^2 + 7*x - 5

Special functions

The following special functions can be computed for any polynomial ring. Typically one uses the generator $x$ of a polynomial ring to get the respective special polynomials expressed in terms of that generator.

AbstractAlgebra.chebyshev_tMethod
chebyshev_t(n::Int, x::PolyRingElem)

Return the Chebyshev polynomial of the first kind $T_n(x)$, defined by $T_n(x) = \cos(n \cos^{-1}(x))$.

source
AbstractAlgebra.chebyshev_uMethod
chebyshev_u(n::Int, x::PolyRingElem)

Return the Chebyshev polynomial of the first kind $U_n(x)$, defined by $(n+1) U_n(x) = T'_{n+1}(x)$.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
+x^4 - 2*x^3 + 10*x^2 + 7*x - 5

Special functions

The following special functions can be computed for any polynomial ring. Typically one uses the generator $x$ of a polynomial ring to get the respective special polynomials expressed in terms of that generator.

AbstractAlgebra.chebyshev_tMethod
chebyshev_t(n::Int, x::PolyRingElem)

Return the Chebyshev polynomial of the first kind $T_n(x)$, defined by $T_n(x) = \cos(n \cos^{-1}(x))$.

source
AbstractAlgebra.chebyshev_uMethod
chebyshev_u(n::Int, x::PolyRingElem)

Return the Chebyshev polynomial of the first kind $U_n(x)$, defined by $(n+1) U_n(x) = T'_{n+1}(x)$.

source

Examples

julia> R, x = polynomial_ring(ZZ, :x)
 (Univariate polynomial ring in x over integers, x)
 
 julia> S, y = polynomial_ring(R, :y)
@@ -513,4 +513,4 @@
 julia> G = hom(Zx, Fpy, c -> Fp(c), y^3);
 
 julia> G(5*x + 1)
-2*y^3 + 1
source +2*y^3 + 1source diff --git a/dev/puiseux/index.html b/dev/puiseux/index.html index f5ce6422c..c898547b3 100644 --- a/dev/puiseux/index.html +++ b/dev/puiseux/index.html @@ -64,7 +64,7 @@ julia> p = precision(f) 10//1 -

Puiseux series functionality provided by AbstractAlgebra.jl

The functionality below is automatically provided by AbstractAlgebra.jl for any Puiseux series.

Of course, modules are encouraged to provide specific implementations of the functions described here, that override the generic implementation.

Basic functionality

coeff(a::Generic.PuiseuxSeriesElem, n::Int)
coeff(a::Generic.PuiseuxSeriesElem, n::Rational{Int})

Return the coefficient of the term of exponent $n$ of the given power series. If $n$ exceeds the current precision of the power series or does not correspond to a nonzero term of the Puiseux series, the function returns a zero coefficient.

AbstractAlgebra.modulusMethod
modulus(a::Generic.PuiseuxSeriesElem{T}) where {T <: ResElem}

Return the modulus of the coefficients of the given Puiseux series.

source
AbstractAlgebra.is_genMethod
is_gen(a::Generic.PuiseuxSeriesElem)

Return true if the given Puiseux series is arithmetically equal to the generator of its Puiseux series ring to its current precision, otherwise return false.

source

Examples

julia> R, t = puiseux_series_ring(QQ, 10, :t)
+

Puiseux series functionality provided by AbstractAlgebra.jl

The functionality below is automatically provided by AbstractAlgebra.jl for any Puiseux series.

Of course, modules are encouraged to provide specific implementations of the functions described here, that override the generic implementation.

Basic functionality

coeff(a::Generic.PuiseuxSeriesElem, n::Int)
coeff(a::Generic.PuiseuxSeriesElem, n::Rational{Int})

Return the coefficient of the term of exponent $n$ of the given power series. If $n$ exceeds the current precision of the power series or does not correspond to a nonzero term of the Puiseux series, the function returns a zero coefficient.

AbstractAlgebra.modulusMethod
modulus(a::Generic.PuiseuxSeriesElem{T}) where {T <: ResElem}

Return the modulus of the coefficients of the given Puiseux series.

source
AbstractAlgebra.is_genMethod
is_gen(a::Generic.PuiseuxSeriesElem)

Return true if the given Puiseux series is arithmetically equal to the generator of its Puiseux series ring to its current precision, otherwise return false.

source

Examples

julia> R, t = puiseux_series_ring(QQ, 10, :t)
 (Puiseux series field in t over rationals, t + O(t^11))
 
 julia> S, x = puiseux_series_ring(R, 30, :x)
@@ -90,7 +90,7 @@
 
 julia> c = coeff(b, 2)
 1 + t^2 + O(t^10)
-

Division

Base.invMethod
inv(M::MatrixElem{T}) where {T <: RingElement}

Given a non-singular $n\times n$ matrix over a ring, return an $n\times n$ matrix $X$ such that $MX = I_n$, where $I_n$ is the $n\times n$ identity matrix. If $M$ is not invertible over the base ring an exception is raised.

source
Base.inv(a::PuiseuxSeriesElem{T}) where T <: RingElement

Return the inverse of the power series $a$, i.e. $1/a$, if it exists. Otherwise an exception is raised.

source
 inv(a::LocalizedEuclideanRingElem{T}, checked::Bool = true)  where {T <: RingElem}

Returns the inverse element of $a$ if $a$ is a unit. If 'checked = false' the invertibility of $a$ is not checked and the corresponding inverse element of the Fraction Field is returned.

source

Examples

julia> R, x = puiseux_series_ring(QQ, 30, :x)
+

Division

Base.invMethod
inv(M::MatrixElem{T}) where {T <: RingElement}

Given a non-singular $n\times n$ matrix over a ring, return an $n\times n$ matrix $X$ such that $MX = I_n$, where $I_n$ is the $n\times n$ identity matrix. If $M$ is not invertible over the base ring an exception is raised.

source
Base.inv(a::PuiseuxSeriesElem{T}) where T <: RingElement

Return the inverse of the power series $a$, i.e. $1/a$, if it exists. Otherwise an exception is raised.

source
 inv(a::LocalizedEuclideanRingElem{T}, checked::Bool = true)  where {T <: RingElem}

Returns the inverse element of $a$ if $a$ is a unit. If 'checked = false' the invertibility of $a$ is not checked and the corresponding inverse element of the Fraction Field is returned.

source

Examples

julia> R, x = puiseux_series_ring(QQ, 30, :x)
 (Puiseux series field in x over rationals, x + O(x^31))
 
 julia> a = 1 + x + 2x^2 + O(x^5)
@@ -104,21 +104,21 @@
 
 julia> d = inv(b)
 -1 + O(x^30)
-

Derivative and integral

AbstractAlgebra.derivativeMethod
derivative(f::AbsPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

source
derivative(f::RelPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
+

Derivative and integral

AbstractAlgebra.derivativeMethod
derivative(f::AbsPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

source
derivative(f::RelPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
 (Univariate power series ring in x over Rationals, x + O(x^11))
 
 julia> f = 2 + x + 3x^3
 2 + x + 3*x^3 + O(x^10)
 
 julia> derivative(f)
-1 + 9*x^2 + O(x^9)
source
derivative(f::MPolyRingElem{T}, j::Int) where {T <: RingElement}

Return the partial derivative of f with respect to $j$-th variable of the polynomial ring.

source
derivative(f::MPolyRingElem{T}, x::MPolyRingElem{T}) where T <: RingElement

Return the partial derivative of f with respect to x. The value x must be a generator of the polynomial ring of f.

source
derivative(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the derivative of the given Puiseux series $a$.

source
AbstractAlgebra.integralMethod
integral(f::AbsPowerSeriesRingElem{T})

Return the integral of the power series $f$.

source
integral(f::RelPowerSeriesRingElem{T})

Return the integral of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
+1 + 9*x^2 + O(x^9)
source
derivative(f::MPolyRingElem{T}, j::Int) where {T <: RingElement}

Return the partial derivative of f with respect to $j$-th variable of the polynomial ring.

source
derivative(f::MPolyRingElem{T}, x::MPolyRingElem{T}) where T <: RingElement

Return the partial derivative of f with respect to x. The value x must be a generator of the polynomial ring of f.

source
derivative(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the derivative of the given Puiseux series $a$.

source
AbstractAlgebra.integralMethod
integral(f::AbsPowerSeriesRingElem{T})

Return the integral of the power series $f$.

source
integral(f::RelPowerSeriesRingElem{T})

Return the integral of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
 (Univariate power series ring in x over Rationals, x + O(x^11))
 
 julia> f = 2 + x + 3x^3
 2 + x + 3*x^3 + O(x^10)
 
 julia> integral(f)
-2*x + 1//2*x^2 + 3//4*x^4 + O(x^11)
source
integral(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the integral of the given Puiseux series $a$.

source

Examples

julia> R, x = puiseux_series_ring(QQ, 10, :x)
+2*x + 1//2*x^2 + 3//4*x^4 + O(x^11)
source
integral(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the integral of the given Puiseux series $a$.

source

Examples

julia> R, x = puiseux_series_ring(QQ, 10, :x)
 (Puiseux series field in x over rationals, x + O(x^11))
 
 julia> f = x^(5//3) + x^(7//3) + x^(11//3)
@@ -128,7 +128,7 @@
 5//3*x^(2//3) + 7//3*x^(4//3) + 11//3*x^(8//3) + O(x^4)
 
 julia> derivative(integral(f)) == f
-true

Special functions

Base.logMethod
log(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the logarithm of the given Puiseux series $a$.

source
Base.expMethod
exp(a::AbsPowerSeriesRingElem)

Return the exponential of the power series $a$.

source
exp(a::RelPowerSeriesRingElem)

Return the exponential of the power series $a$.

source
exp(a::Generic.LaurentSeriesElem)

Return the exponential of the power series $a$.

source
exp(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the exponential of the given Puiseux series $a$.

source
Base.sqrtMethod
Base.sqrt(f::PolyRingElem{T}; check::Bool=true) where T <: RingElement

Return the square root of $f$. By default the function checks the input is square and raises an exception if not. If check=false this check is omitted.

source
Base.sqrt(a::FracElem{T}; check::Bool=true) where T <: RingElem

Return the square root of $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source
sqrt(a::Generic.PuiseuxSeriesElem{T}; check::Bool=true) where T <: RingElement

Return the square root of the given Puiseux series $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
+true

Special functions

Base.logMethod
log(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the logarithm of the given Puiseux series $a$.

source
Base.expMethod
exp(a::AbsPowerSeriesRingElem)

Return the exponential of the power series $a$.

source
exp(a::RelPowerSeriesRingElem)

Return the exponential of the power series $a$.

source
exp(a::Generic.LaurentSeriesElem)

Return the exponential of the power series $a$.

source
exp(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the exponential of the given Puiseux series $a$.

source
Base.sqrtMethod
Base.sqrt(f::PolyRingElem{T}; check::Bool=true) where T <: RingElement

Return the square root of $f$. By default the function checks the input is square and raises an exception if not. If check=false this check is omitted.

source
Base.sqrt(a::FracElem{T}; check::Bool=true) where T <: RingElem

Return the square root of $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source
sqrt(a::Generic.PuiseuxSeriesElem{T}; check::Bool=true) where T <: RingElement

Return the square root of the given Puiseux series $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S, x = puiseux_series_ring(R, 30, :x)
@@ -154,4 +154,4 @@
 
 julia> h = sqrt(a)
 1 + 1//2*z + 11//8*z^2 - 11//16*z^3 - 77//128*z^4 + O(z^5)
-
+ diff --git a/dev/quotient_module/index.html b/dev/quotient_module/index.html index 9c706468f..a342cdbf9 100644 --- a/dev/quotient_module/index.html +++ b/dev/quotient_module/index.html @@ -1,5 +1,5 @@ -Quotient modules · AbstractAlgebra.jl

Quotient modules

AbstractAlgebra allows the construction of quotient modules/spaces of AbstractAlgebra modules over euclidean domains. These are given as the quotient of a module by a submodule of that module.

We define two quotient modules to be equal if they are quotients of the same module $M$ by two equal submodules.

Generic quotient module type

AbstractAlgebra implements the generic quotient module type Generic.QuotientModule{T} where T is the element type of the base ring, in src/generic/QuotientModule.jl.

Elements of generic quotient modules have type Generic.QuotientModuleElem{T}.

Abstract types

Quotient module types belong to the FPModule{T} abstract type and their elements to FPModuleElem{T}.

Constructors

AbstractAlgebra.quoMethod
quo(m::FPModule{T}, subm::FPModule{T}) where T <: RingElement

Return the quotient M of the module m by the module subm (which must have been (transitively) constructed as a submodule of m or be m itself) along with the canonical quotient map from m to M.

source

Note that a preimage of the canonical projection can be obtained using the preimage function described in the section on module homomorphisms. Note that a preimage element of the canonical projection is not unique and has no special properties.

Examples

julia> M = free_module(ZZ, 2)
+Quotient modules · AbstractAlgebra.jl

Quotient modules

AbstractAlgebra allows the construction of quotient modules/spaces of AbstractAlgebra modules over euclidean domains. These are given as the quotient of a module by a submodule of that module.

We define two quotient modules to be equal if they are quotients of the same module $M$ by two equal submodules.

Generic quotient module type

AbstractAlgebra implements the generic quotient module type Generic.QuotientModule{T} where T is the element type of the base ring, in src/generic/QuotientModule.jl.

Elements of generic quotient modules have type Generic.QuotientModuleElem{T}.

Abstract types

Quotient module types belong to the FPModule{T} abstract type and their elements to FPModuleElem{T}.

Constructors

AbstractAlgebra.quoMethod
quo(m::FPModule{T}, subm::FPModule{T}) where T <: RingElement

Return the quotient M of the module m by the module subm (which must have been (transitively) constructed as a submodule of m or be m itself) along with the canonical quotient map from m to M.

source

Note that a preimage of the canonical projection can be obtained using the preimage function described in the section on module homomorphisms. Note that a preimage element of the canonical projection is not unique and has no special properties.

Examples

julia> M = free_module(ZZ, 2)
 Free module of rank 2 over integers
 
 julia> m = M([ZZ(1), ZZ(2)])
@@ -28,7 +28,7 @@
 
 julia> Q, g = quo(V, N)
 (Quotient space over rationals with 1 generator and no relations, Hom: V -> Q)
-

Functionality for submodules

In addition to the Module interface, AbstractAlgebra submodules implement the following functionality.

Basic manipulation

Examples

julia> M = free_module(ZZ, 2)
+

Functionality for submodules

In addition to the Module interface, AbstractAlgebra submodules implement the following functionality.

Basic manipulation

Examples

julia> M = free_module(ZZ, 2)
 Free module of rank 2 over integers
 
 julia> m = M([ZZ(2), ZZ(3)])
@@ -61,4 +61,4 @@
 
 julia> dim(Q)
 1
-
+
diff --git a/dev/rand/index.html b/dev/rand/index.html index 06a66d384..e48879626 100644 --- a/dev/rand/index.html +++ b/dev/rand/index.html @@ -50,4 +50,4 @@ R, x = polynomial_ring(ZZ, :x) -test_rand(R, -1:10, -10:10)

In general, we try to use UnitRange's to specify how 'big' we want the random instance to be, e.g. the range of degrees a polynomial could take, the range random integers could lie in, etc. The objective is to make it easy for the user to control the 'size' of random values in test code.

+test_rand(R, -1:10, -10:10)

In general, we try to use UnitRange's to specify how 'big' we want the random instance to be, e.g. the range of degrees a polynomial could take, the range random integers could lie in, etc. The objective is to make it easy for the user to control the 'size' of random values in test code.

diff --git a/dev/rational/index.html b/dev/rational/index.html index 4c273ace3..450be053e 100644 --- a/dev/rational/index.html +++ b/dev/rational/index.html @@ -55,4 +55,4 @@ true julia> root(ZZ(27)//64, 3) -3//4 +3//4 diff --git a/dev/real/index.html b/dev/real/index.html index e7e5cfde4..74ffd3d12 100644 --- a/dev/real/index.html +++ b/dev/real/index.html @@ -48,4 +48,4 @@ julia> m = inv(g) 0.07291666666666666666666666666666666666666666666666666666666666666666666666666631 - + diff --git a/dev/residue/index.html b/dev/residue/index.html index 433140719..09c80b7c5 100644 --- a/dev/residue/index.html +++ b/dev/residue/index.html @@ -1,5 +1,5 @@ -Generic residue rings · AbstractAlgebra.jl

Generic residue rings

AbstractAlgebra.jl provides modules, implemented in src/Residue.jl and src/residue_field for residue rings and fields, respectively, over any Euclidean domain (in practice most of the functionality is provided for GCD domains that provide a meaningful GCD function) belonging to the AbstractAlgebra.jl abstract type hierarchy.

Generic residue types

AbstractAlgebra.jl implements generic residue rings of Euclidean rings with type EuclideanRingResidueRingElem{T} or in the case of residue rings that are known to be fields, EuclideanRingResidueFieldElem{T}, where T is the type of elements of the base ring. See the file src/generic/GenericTypes.jl for details.

Parent objects of generic residue ring elements have type EuclideanRingResidueRing{T} and those of residue fields have type EuclideanRingResidueField{T}.

The defining modulus of the residue ring is stored in the parent object.

Abstract types

All residue element types belong to the abstract type ResElem{T} or ResFieldElem{T} in the case of residue fields, and the residue ring types belong to the abstract type ResidueRing{T} or ResidueField{T} respectively. This enables one to write generic functions that can accept any AbstractAlgebra residue type.

Residue ring constructors

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

residue_ring(R::Ring, m::RingElem; cached::Bool = true)
residue_field(R::Ring, m::RingElem; cached::Bool = true)

Given a base ring R and residue $m$ contained in this ring, return the parent object of the residue ring $R/(m)$ together with the canonical projection. By default the parent object S will depend only on R and m and will be cached. Setting the optional argument cached to false will prevent the parent object S from being cached.

The residue_field constructor does the same thing as the residue_ring constructor, but the resulting object has type belonging to Field rather than Ring, so it can be used anywhere a field is expected in AbstractAlgebra.jl. No check is made for maximality of the ideal generated by $m$.

There are also the following for constructing residue rings and fields.

AbstractAlgebra.quoMethod
quo(R::Ring, a::RingElement; cached::Bool = true)

Returns S, f where S = residue_ring(R, a) and f is the projection map from R to S. This map is supplied as a map with section where the section is the lift of an element of the residue field back to the ring R.

source
AbstractAlgebra.quoMethod
quo(::Type{Field}, R::Ring, a::RingElement; cached::Bool = true)

Returns S, f where S = residue_field(R, a) and f is the projection map from R to S. This map is supplied as a map with section where the section is the lift of an element of the residue field back to the ring R.

source

Here are some examples of creating residue rings and making use of the resulting parent objects to coerce various elements into the residue ring.

Examples

julia> R, x = polynomial_ring(QQ, :x)
+Generic residue rings · AbstractAlgebra.jl

Generic residue rings

AbstractAlgebra.jl provides modules, implemented in src/Residue.jl and src/residue_field for residue rings and fields, respectively, over any Euclidean domain (in practice most of the functionality is provided for GCD domains that provide a meaningful GCD function) belonging to the AbstractAlgebra.jl abstract type hierarchy.

Generic residue types

AbstractAlgebra.jl implements generic residue rings of Euclidean rings with type EuclideanRingResidueRingElem{T} or in the case of residue rings that are known to be fields, EuclideanRingResidueFieldElem{T}, where T is the type of elements of the base ring. See the file src/generic/GenericTypes.jl for details.

Parent objects of generic residue ring elements have type EuclideanRingResidueRing{T} and those of residue fields have type EuclideanRingResidueField{T}.

The defining modulus of the residue ring is stored in the parent object.

Abstract types

All residue element types belong to the abstract type ResElem{T} or ResFieldElem{T} in the case of residue fields, and the residue ring types belong to the abstract type ResidueRing{T} or ResidueField{T} respectively. This enables one to write generic functions that can accept any AbstractAlgebra residue type.

Residue ring constructors

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

residue_ring(R::Ring, m::RingElem; cached::Bool = true)
residue_field(R::Ring, m::RingElem; cached::Bool = true)

Given a base ring R and residue $m$ contained in this ring, return the parent object of the residue ring $R/(m)$ together with the canonical projection. By default the parent object S will depend only on R and m and will be cached. Setting the optional argument cached to false will prevent the parent object S from being cached.

The residue_field constructor does the same thing as the residue_ring constructor, but the resulting object has type belonging to Field rather than Ring, so it can be used anywhere a field is expected in AbstractAlgebra.jl. No check is made for maximality of the ideal generated by $m$.

There are also the following for constructing residue rings and fields.

AbstractAlgebra.quoMethod
quo(R::Ring, a::RingElement; cached::Bool = true)

Returns S, f where S = residue_ring(R, a) and f is the projection map from R to S. This map is supplied as a map with section where the section is the lift of an element of the residue field back to the ring R.

source
AbstractAlgebra.quoMethod
quo(::Type{Field}, R::Ring, a::RingElement; cached::Bool = true)

Returns S, f where S = residue_field(R, a) and f is the projection map from R to S. This map is supplied as a map with section where the section is the lift of an element of the residue field back to the ring R.

source

Here are some examples of creating residue rings and making use of the resulting parent objects to coerce various elements into the residue ring.

Examples

julia> R, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> S, = residue_ring(R, x^3 + 3x + 1);
@@ -29,7 +29,7 @@
 iszero(a::NCRingElement)
 isone(a::NCRingElement)
divexact(a::T, b::T) where T <: RingElement
 inv(a::T)

The Residue Ring interface is also implemented.

modulus(S::ResidueRing)
data(f::ResElem)
-lift(f::ResElem)

Return a lift of the residue to the base ring.

The following functions are also provided for residues.

AbstractAlgebra.modulusMethod
modulus(R::ResElem)

Return the modulus $a$ of the residue ring $S = R/(a)$ that the supplied residue $r$ belongs to.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
+lift(f::ResElem)

Return a lift of the residue to the base ring.

The following functions are also provided for residues.

AbstractAlgebra.modulusMethod
modulus(R::ResElem)

Return the modulus $a$ of the residue ring $S = R/(a)$ that the supplied residue $r$ belongs to.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> S, = residue_ring(R, x^3 + 3x + 1);
@@ -71,7 +71,7 @@
 true
 
 julia> R, x = polynomial_ring(QQ, :x)
-(Univariate polynomial ring in x over rationals, x)

Inversion

Base.invMethod
Base.inv(a::ResElem)

Return the inverse of the element $a$ in the residue ring. If an impossible inverse is encountered, an exception is raised.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
+(Univariate polynomial ring in x over rationals, x)

Inversion

Base.invMethod
Base.inv(a::ResElem)

Return the inverse of the element $a$ in the residue ring. If an impossible inverse is encountered, an exception is raised.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> S, = residue_ring(R, x^3 + 3x + 1);
@@ -81,7 +81,7 @@
 
 julia> g = inv(f)
 1//3*x^2 - 1//3*x + 4//3
-

Greatest common divisor

Base.gcdMethod
gcd(a::ResElem{T}, b::ResElem{T}) where {T <: RingElement}

Return a greatest common divisor of $a$ and $b$ if one exists. This is done by taking the greatest common divisor of the data associated with the supplied residues and taking its greatest common divisor with the modulus.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
+

Greatest common divisor

Base.gcdMethod
gcd(a::ResElem{T}, b::ResElem{T}) where {T <: RingElement}

Return a greatest common divisor of $a$ and $b$ if one exists. This is done by taking the greatest common divisor of the data associated with the supplied residues and taking its greatest common divisor with the modulus.

source

Examples

julia> R, x = polynomial_ring(QQ, :x)
 (Univariate polynomial ring in x over rationals, x)
 
 julia> S, = residue_ring(R, x^3 + 3x + 1);
@@ -94,7 +94,7 @@
 
 julia> h = gcd(f, g)
 1
-

Square Root

Base.sqrtMethod
sqrt(a::ResFieldElem{T}; check::Bool=true) where T <: Integer

Return the square root of $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source

Examples

julia> R = residue_field(ZZ, 733)
+

Square Root

Base.sqrtMethod
sqrt(a::ResFieldElem{T}; check::Bool=true) where T <: Integer

Return the square root of $a$. By default the function will throw an exception if the input is not square. If check=false this test is omitted.

source

Examples

julia> R = residue_field(ZZ, 733)
 Residue field of Integers modulo 733
 
 julia> a = R(86)
@@ -113,4 +113,4 @@
 (Univariate polynomial ring in x over rationals, x)
 
 julia> g = rand(S, 2:2, -10:10)
--1//4*x^2 - 2//7*x + 1
+-1//4*x^2 - 2//7*x + 1
diff --git a/dev/residue_interface/index.html b/dev/residue_interface/index.html index 5da8bb4f2..b8c11e4c1 100644 --- a/dev/residue_interface/index.html +++ b/dev/residue_interface/index.html @@ -1,3 +1,3 @@ Residue Ring Interface · AbstractAlgebra.jl

Residue Ring Interface

Residue rings (currently a quotient ring modulo a principal ideal) are supported in AbstractAlgebra.jl, at least for Euclidean base rings. There is also partial support for residue rings of polynomial rings where the modulus has invertible leading coefficient.

In addition to the standard Ring interface, some additional functions are required to be present for residue rings.

Types and parents

AbstractAlgebra provides four abstract types for residue rings and their elements:

  • ResidueRing{T} is the abstract type for residue ring parent types
  • ResidueField{T} is the abstract type for residue rings known to be fields
  • ResElem{T} is the abstract type for types of elements of residue rings (residues)
  • ResFieldElem{T} is the abstract type for types of elements of residue fields

We have that ResidueRing{T} <: AbstractAlgebra.Ring and ResElem{T} <: AbstractAlgebra.RingElem.

Note that these abstract types are parameterised. The type T should usually be the type of elements of the base ring of the residue ring/field.

If the parent object for a residue ring has type MyResRing and residues in that ring have type MyRes then one would have:

  • MyResRing <: ResidueRing{BigInt}
  • MyRes <: ResElem{BigInt}

Residue rings should be made unique on the system by caching parent objects (unless an optional cache parameter is set to false). Residue rings should at least be distinguished based on their base ring and modulus (the principal ideal one is taking a quotient of the base ring by).

See src/generic/GenericTypes.jl for an example of how to implement such a cache (which usually makes use of a dictionary).

Required functionality for residue rings

In addition to the required functionality for the Ring interface the Residue Ring interface has the following required functions.

We suppose that R is a fictitious base ring, $m$ is an element of that ring, and that S is the residue ring (quotient ring) $R/(m)$ with parent object S of type MyResRing{T}. We also assume the residues $r \pmod{m}$ in the residue ring have type MyRes{T}, where T is the type of elements of the base ring.

Of course, in practice these types may not be parameterised, but we use parameterised types here to make the interface clearer.

Note that the type T must (transitively) belong to the abstract type RingElem.

Data type and parent object methods

modulus(S::MyResRing{T}) where T <: AbstractAlgebra.RingElem

Return the modulus of the given residue ring, i.e. if the residue ring $S$ was specified to be $R/(m)$, return $m$.

Basic manipulation of rings and elements

data(f::MyRes{T}) where T <: RingElem
-lift(f::MyRes{T}) where T <: RingElem

Given a residue $r \pmod{m}$, represented as such, return $r$. In the special case where machine integers are used to represent the residue, data will return the machine integer, whereas lift will return a multiprecision integer. Otherwise lift falls back to data by default.

+lift(f::MyRes{T}) where T <: RingElem

Given a residue $r \pmod{m}$, represented as such, return $r$. In the special case where machine integers are used to represent the residue, data will return the machine integer, whereas lift will return a multiprecision integer. Otherwise lift falls back to data by default.

diff --git a/dev/ring/index.html b/dev/ring/index.html index eed72fd4f..4627b869e 100644 --- a/dev/ring/index.html +++ b/dev/ring/index.html @@ -18,18 +18,18 @@ show(io::IO, a::NCRingElement)

Basic functionality for inexact rings only

By default, inexact ring elements in AbstractAlgebra compare equal if they are the same to the minimum precision of the two elements. However, we also provide the following more strict notion of equality, which also requires the precisions to be the same.

isequal(a::T, b::T) where T <: NCRingElement

For floating point and ball arithmetic it is sometimes useful to be able to check if two elements are approximately equal, e.g. to suppress numerical noise in comparisons. For this, the following are provided.

isapprox(a::T, b::T; atol::Real=sqrt(eps())) where T <: RingElement

Similarly, for a parameterised ring with type MyElem{T} over such an inexact ring we have the following.

isapprox(a::MyElem{T}, b::T; atol::Real=sqrt(eps())) where T <: RingElement
 isapprox(a::T, b::MyElem{T}; atol::Real=sqrt(eps())) where T <: RingElement

These notionally perform a coercion into the parameterised ring before doing the approximate equality test.

Basic functionality for commutative rings only

divexact(a::T, b::T) where T <: RingElement
 inv(a::T)

Return a/b or 1/a respectively, where the slash here refers to the mathematical notion of division in the ring, not Julia's floating point division operator.

Basic functionality for noncommutative rings only

divexact_left(a::T, b::T) where T <: NCRingElement
-divexact_right(a::T, b::T) where T <: NCRingElement

As per divexact above, except that division by b happens on the left or right, respectively, of a.

Unsafe ring operators

To speed up polynomial and matrix arithmetic, it sometimes makes sense to mutate values in place rather than replace them with a newly created object every time they are modified.

For this purpose, certain mutating operators are required. In order to support immutable types (struct in Julia) and systems that don't have in-place operators, all unsafe operators must return the (ostensibly) mutated value. Only the returned value is used in computations, so this lifts the requirement that the unsafe operators actually mutate the value.

Note the exclamation point is a convention, which indicates that the object may be mutated in-place.

To make use of these functions, one must be certain that no other references are held to the object being mutated, otherwise those values will also be changed!

The results of deepcopy and all arithmetic operations, including powering and division can be assumed to be new objects without other references being held, as can objects returned from constructors.

Note

It is important to recognise that R(a) where R is the ring a belongs to, does not create a new value. For this case, use deepcopy(a).

AbstractAlgebra.zero!Function
zero!(a)

Return zero(parent(a)), possibly modifying the object a in the process.

source
AbstractAlgebra.one!Function
one!(a)

Return one(parent(a)), possibly modifying the object a in the process.

source
AbstractAlgebra.add!Function
add!(z, a, b)
-add!(a, b)

Return a + b, possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for add!(a, a, b).

source
AbstractAlgebra.sub!Function
sub!(z, a, b)
-sub!(a, b)

Return a - b, possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for sub!(a, a, b).

source
AbstractAlgebra.mul!Function
mul!(z, a, b)
-mul!(a, b)

Return a * b, possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for mul!(a, a, b).

source
AbstractAlgebra.neg!Function
neg!(z, a)
-neg!(a)

Return -a, possibly modifying the object z in the process. Aliasing is permitted. The unary version is a shorthand for neg!(a, a).

source
AbstractAlgebra.inv!Function
inv!(z, a)
-inv!(a)

Return AbstractAlgebra.inv(a), possibly modifying the object z in the process. Aliasing is permitted. The unary version is a shorthand for inv!(a, a).

Note

AbstractAlgebra.inv and Base.inv differ only in their behavior on julia types like Integer and Rational{Int}. The former makes it adhere to the Ring interface.

source
AbstractAlgebra.addmul!Function
addmul!(z, a, b, t)
-addmul!(z, a, b)

Return z + a * b, possibly modifying the objects z and t in the process.

The second version is usually a shorthand for addmul!(z, a, b, parent(z)()), but in some cases may be more efficient. For multiple operations in a row that use temporary storage, it is still best to use the four argument version.

source
AbstractAlgebra.submul!Function
submul!(z, a, b, t)
-submul!(z, a, b)

Return z - a * b, possibly modifying the objects z and t in the process.

The second version is usually a shorthand for submul!(z, a, b, parent(z)()), but in some cases may be more efficient. For multiple operations in a row that use temporary storage, it is still best to use the four argument version.

source
AbstractAlgebra.divexact!Function
divexact!(z, a, b)
-divexact!(a, b)

Return divexact(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for divexact(a, a, b).

source
AbstractAlgebra.div!Function
div!(z, a, b)
-div!(a, b)

Return div(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for div(a, a, b).

Note

AbstractAlgebra.div and Base.div differ only in their behavior on julia types like Integer and Rational{Int}. The former makes it adhere to the Ring interface.

source
AbstractAlgebra.rem!Function
rem!(z, a, b)
-rem!(a, b)

Return rem(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for rem(a, a, b).

source
AbstractAlgebra.mod!Function
mod!(z, a, b)
-mod!(a, b)

Return mod(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for mod(a, a, b).

source
AbstractAlgebra.gcd!Function
gcd!(z, a, b)
-gcd!(a, b)

Return gcd(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for gcd(a, a, b).

source
AbstractAlgebra.lcm!Function
lcm!(z, a, b)
-lcm!(a, b)

Return lcm(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for lcm(a, a, b).

source

Random generation

The Julia random interface is implemented for all ring parents (instead of for types). The exact interface differs depending on the ring, but the parameters supplied are usually ranges, e.g. -1:10 for the range of allowed degrees for a univariate polynomial.

rand(R::NCRing, v...)

Factorization

For commutative rings supporting factorization and irreducibility testing, the following optional functions may be implemented.

AbstractAlgebra.is_irreducibleMethod
is_irreducible(a::RingElement)

Return true if $a$ is irreducible, else return false. Zero and units are by definition never irreducible.

source
AbstractAlgebra.is_squarefreeMethod
is_squarefree(a::RingElement)

Return true if $a$ is squarefree, else return false. An element is squarefree if it it is not divisible by any squares except the squares of units.

source
factor(a::T) where T <: RingElement
-factor_squarefree(a::T) where T <: RingElement

Return a factorization into irreducible or squarefree elements, respectively. The return is an object of type Fac{T}.

AbstractAlgebra.FacType
Fac{T <: RingElement}

Type for factored ring elements. The structure holds a unit of type T and is an iterable collection of T => Int pairs for the factors and exponents.

See unit(a::Fac), evaluate(a::Fac).

source
AbstractAlgebra.unitMethod
unit(a::Fac{T}) -> T

Return the unit of the factorization.

source
AbstractAlgebra.evaluateMethod
evaluate(a::Fac{T}) -> T

Multiply out the factorization into a single element.

source
Base.getindexMethod
getindex(a::Fac, b) -> Int

If $b$ is a factor of $a$, the corresponding exponent is returned. Otherwise an error is thrown.

source
Base.setindex!Method
setindex!(a::Fac{T}, c::Int, b::T)

If $b$ is a factor of $a$, the corresponding entry is set to $c$.

source
+divexact_right(a::T, b::T) where T <: NCRingElement

As per divexact above, except that division by b happens on the left or right, respectively, of a.

Unsafe ring operators

To speed up polynomial and matrix arithmetic, it sometimes makes sense to mutate values in place rather than replace them with a newly created object every time they are modified.

For this purpose, certain mutating operators are required. In order to support immutable types (struct in Julia) and systems that don't have in-place operators, all unsafe operators must return the (ostensibly) mutated value. Only the returned value is used in computations, so this lifts the requirement that the unsafe operators actually mutate the value.

Note the exclamation point is a convention, which indicates that the object may be mutated in-place.

To make use of these functions, one must be certain that no other references are held to the object being mutated, otherwise those values will also be changed!

The results of deepcopy and all arithmetic operations, including powering and division can be assumed to be new objects without other references being held, as can objects returned from constructors.

Note

It is important to recognise that R(a) where R is the ring a belongs to, does not create a new value. For this case, use deepcopy(a).

AbstractAlgebra.zero!Function
zero!(a)

Return zero(parent(a)), possibly modifying the object a in the process.

source
AbstractAlgebra.one!Function
one!(a)

Return one(parent(a)), possibly modifying the object a in the process.

source
AbstractAlgebra.add!Function
add!(z, a, b)
+add!(a, b)

Return a + b, possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for add!(a, a, b).

source
AbstractAlgebra.sub!Function
sub!(z, a, b)
+sub!(a, b)

Return a - b, possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for sub!(a, a, b).

source
AbstractAlgebra.mul!Function
mul!(z, a, b)
+mul!(a, b)

Return a * b, possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for mul!(a, a, b).

source
AbstractAlgebra.neg!Function
neg!(z, a)
+neg!(a)

Return -a, possibly modifying the object z in the process. Aliasing is permitted. The unary version is a shorthand for neg!(a, a).

source
AbstractAlgebra.inv!Function
inv!(z, a)
+inv!(a)

Return AbstractAlgebra.inv(a), possibly modifying the object z in the process. Aliasing is permitted. The unary version is a shorthand for inv!(a, a).

Note

AbstractAlgebra.inv and Base.inv differ only in their behavior on julia types like Integer and Rational{Int}. The former makes it adhere to the Ring interface.

source
AbstractAlgebra.addmul!Function
addmul!(z, a, b, t)
+addmul!(z, a, b)

Return z + a * b, possibly modifying the objects z and t in the process.

The second version is usually a shorthand for addmul!(z, a, b, parent(z)()), but in some cases may be more efficient. For multiple operations in a row that use temporary storage, it is still best to use the four argument version.

source
AbstractAlgebra.submul!Function
submul!(z, a, b, t)
+submul!(z, a, b)

Return z - a * b, possibly modifying the objects z and t in the process.

The second version is usually a shorthand for submul!(z, a, b, parent(z)()), but in some cases may be more efficient. For multiple operations in a row that use temporary storage, it is still best to use the four argument version.

source
AbstractAlgebra.divexact!Function
divexact!(z, a, b)
+divexact!(a, b)

Return divexact(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for divexact(a, a, b).

source
AbstractAlgebra.div!Function
div!(z, a, b)
+div!(a, b)

Return div(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for div(a, a, b).

Note

AbstractAlgebra.div and Base.div differ only in their behavior on julia types like Integer and Rational{Int}. The former makes it adhere to the Ring interface.

source
AbstractAlgebra.rem!Function
rem!(z, a, b)
+rem!(a, b)

Return rem(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for rem(a, a, b).

source
AbstractAlgebra.mod!Function
mod!(z, a, b)
+mod!(a, b)

Return mod(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for mod(a, a, b).

source
AbstractAlgebra.gcd!Function
gcd!(z, a, b)
+gcd!(a, b)

Return gcd(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for gcd(a, a, b).

source
AbstractAlgebra.lcm!Function
lcm!(z, a, b)
+lcm!(a, b)

Return lcm(a, b), possibly modifying the object z in the process. Aliasing is permitted. The two argument version is a shorthand for lcm(a, a, b).

source

Random generation

The Julia random interface is implemented for all ring parents (instead of for types). The exact interface differs depending on the ring, but the parameters supplied are usually ranges, e.g. -1:10 for the range of allowed degrees for a univariate polynomial.

rand(R::NCRing, v...)

Factorization

For commutative rings supporting factorization and irreducibility testing, the following optional functions may be implemented.

AbstractAlgebra.is_irreducibleMethod
is_irreducible(a::RingElement)

Return true if $a$ is irreducible, else return false. Zero and units are by definition never irreducible.

source
AbstractAlgebra.is_squarefreeMethod
is_squarefree(a::RingElement)

Return true if $a$ is squarefree, else return false. An element is squarefree if it it is not divisible by any squares except the squares of units.

source
factor(a::T) where T <: RingElement
+factor_squarefree(a::T) where T <: RingElement

Return a factorization into irreducible or squarefree elements, respectively. The return is an object of type Fac{T}.

AbstractAlgebra.FacType
Fac{T <: RingElement}

Type for factored ring elements. The structure holds a unit of type T and is an iterable collection of T => Int pairs for the factors and exponents.

See unit(a::Fac), evaluate(a::Fac).

source
AbstractAlgebra.unitMethod
unit(a::Fac{T}) -> T

Return the unit of the factorization.

source
AbstractAlgebra.evaluateMethod
evaluate(a::Fac{T}) -> T

Multiply out the factorization into a single element.

source
Base.getindexMethod
getindex(a::Fac, b) -> Int

If $b$ is a factor of $a$, the corresponding exponent is returned. Otherwise an error is thrown.

source
Base.setindex!Method
setindex!(a::Fac{T}, c::Int, b::T)

If $b$ is a factor of $a$, the corresponding entry is set to $c$.

source
diff --git a/dev/ring_interface/index.html b/dev/ring_interface/index.html index 039601489..1a1ca7501 100644 --- a/dev/ring_interface/index.html +++ b/dev/ring_interface/index.html @@ -298,4 +298,4 @@ # output Test Summary: | Pass Total Time -Euclidean Ring interface for Constant polynomials over integers of type ConstPolyRing{BigInt} | 2212 2212 0.1s +Euclidean Ring interface for Constant polynomials over integers of type ConstPolyRing{BigInt} | 2212 2212 0.1s diff --git a/dev/ring_introduction/index.html b/dev/ring_introduction/index.html index 36c7c9c6f..8b0a43d9f 100644 --- a/dev/ring_introduction/index.html +++ b/dev/ring_introduction/index.html @@ -1,2 +1,2 @@ -Introduction · AbstractAlgebra.jl

Introduction

A rich ring hierarchy is provided, supporting both commutative and noncommutative rings.

A number of basic rings are provided, such as the integers, integers mod n and numerous fields.

A recursive rings implementation is then built on top of the basic rings via a number of generic ring constructions. These include univariate and multivariate polynomials and power series, univariate Laurent and Puiseux series, residue rings, matrix algebras, etc.

Where possible, these constructions can be built on top of one another in generic towers.

The ring hierarchy can be extended by implementing new rings to follow one or more ring interfaces. Generic functionality provided by the system is then automatically available for the new rings. These implementations can either be generic or can be specialised implementations provided by, for example, a C library.

In most cases, the interfaces consist of a set of constructors and functions that must be implemented to satisfy the interface. These are the functions that the generic code relies on being available.

+Introduction · AbstractAlgebra.jl

Introduction

A rich ring hierarchy is provided, supporting both commutative and noncommutative rings.

A number of basic rings are provided, such as the integers, integers mod n and numerous fields.

A recursive rings implementation is then built on top of the basic rings via a number of generic ring constructions. These include univariate and multivariate polynomials and power series, univariate Laurent and Puiseux series, residue rings, matrix algebras, etc.

Where possible, these constructions can be built on top of one another in generic towers.

The ring hierarchy can be extended by implementing new rings to follow one or more ring interfaces. Generic functionality provided by the system is then automatically available for the new rings. These implementations can either be generic or can be specialised implementations provided by, for example, a C library.

In most cases, the interfaces consist of a set of constructors and functions that must be implemented to satisfy the interface. These are the functions that the generic code relies on being available.

diff --git a/dev/series/index.html b/dev/series/index.html index a0f5c5112..8e79d77fc 100644 --- a/dev/series/index.html +++ b/dev/series/index.html @@ -74,7 +74,7 @@ iszero(a::SeriesElem) isone(a::SeriesElem)
divexact(a::T, b::T) where T <: SeriesElem
 inv(a::SeriesElem) 

Series also implement the Series Interface, the most important basic functions being the following.

var(S::SeriesRing)

Return a symbol for the variable of the given series ring.

max_precision(S::SeriesRing)

Return the precision cap of the given series ring.

precision(f::SeriesElem)
-valuation(f::SeriesElem)
gen(R::SeriesRing)

The following functions are also provided for all series.

coeff(a::SeriesElem, n::Int)

Return the degree $n$ coefficient of the given power series. Note coefficients are numbered from $n = 0$ for the constant coefficient. If $n$ exceeds the current precision of the power series, the function returns a zero coefficient.

For power series types, $n$ must be non-negative. Laurent series do not have this restriction.

AbstractAlgebra.modulusMethod
modulus(a::SeriesElem{T}) where {T <: ResElem}

Return the modulus of the coefficients of the given power series.

source
AbstractAlgebra.is_genMethod
is_gen(a::RelPowerSeriesRingElem)

Return true if the given power series is arithmetically equal to the generator of its power series ring to its current precision, otherwise return false.

source

Examples

julia> S, x = power_series_ring(ZZ, 10, :x)
+valuation(f::SeriesElem)
gen(R::SeriesRing)

The following functions are also provided for all series.

coeff(a::SeriesElem, n::Int)

Return the degree $n$ coefficient of the given power series. Note coefficients are numbered from $n = 0$ for the constant coefficient. If $n$ exceeds the current precision of the power series, the function returns a zero coefficient.

For power series types, $n$ must be non-negative. Laurent series do not have this restriction.

AbstractAlgebra.modulusMethod
modulus(a::SeriesElem{T}) where {T <: ResElem}

Return the modulus of the coefficients of the given power series.

source
AbstractAlgebra.is_genMethod
is_gen(a::RelPowerSeriesRingElem)

Return true if the given power series is arithmetically equal to the generator of its power series ring to its current precision, otherwise return false.

source

Examples

julia> S, x = power_series_ring(ZZ, 10, :x)
 (Univariate power series ring over integers, x + O(x^11))
 
 julia> f = 1 + 3x + x^3 + O(x^10)
@@ -167,7 +167,7 @@
 julia> fit!(g, 8)
 
 julia> g = setcoeff!(g, 7, BigInt(4))
-x^3 + 2*x^4 + 11*x^5 + O(x^10)

Change base ring

AbstractAlgebra.map_coefficientsMethod
map_coefficients(f, p::SeriesElem{<: RingElement}; cached::Bool=true, parent::PolyRing)

Transform the series p by applying f on each non-zero coefficient.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source
AbstractAlgebra.change_base_ringMethod
change_base_ring(R::Ring, p::SeriesElem{<: RingElement}; parent::PolyRing)

Return the series obtained by coercing the non-zero coefficients of p into R.

If the optional parent keyword is provided, the series will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source

Examples

julia> R, x = power_series_ring(ZZ, 10, :x)
+x^3 + 2*x^4 + 11*x^5 + O(x^10)

Change base ring

AbstractAlgebra.map_coefficientsMethod
map_coefficients(f, p::SeriesElem{<: RingElement}; cached::Bool=true, parent::PolyRing)

Transform the series p by applying f on each non-zero coefficient.

If the optional parent keyword is provided, the polynomial will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source
AbstractAlgebra.change_base_ringMethod
change_base_ring(R::Ring, p::SeriesElem{<: RingElement}; parent::PolyRing)

Return the series obtained by coercing the non-zero coefficients of p into R.

If the optional parent keyword is provided, the series will be an element of parent. The caching of the parent object can be controlled via the cached keyword argument.

source

Examples

julia> R, x = power_series_ring(ZZ, 10, :x)
 (Univariate power series ring over integers, x + O(x^11))
 
 julia> f = 4*x^6 + x^7 + 9*x^8 + 16*x^9 + 25*x^10 + O(x^11)
@@ -177,7 +177,7 @@
 2*x^6 + x^7 + 3*x^8 + 4*x^9 + 5*x^10 + O(x^11)
 
 julia> change_base_ring(QQ, f)
-4*x^6 + x^7 + 9*x^8 + 16*x^9 + 25*x^10 + O(x^11)

Shifting

AbstractAlgebra.shift_leftMethod
shift_left(x::RelPowerSeriesRingElem{T}, n::Int) where T <: RingElement

Return the power series $x$ shifted left by $n$ terms, i.e. multiplied by $x^n$.

source
AbstractAlgebra.shift_rightMethod
shift_right(x::RelPowerSeriesRingElem{T}, n::Int) where T <: RingElement

Return the power series $x$ shifted right by $n$ terms, i.e. divided by $x^n$.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
+4*x^6 + x^7 + 9*x^8 + 16*x^9 + 25*x^10 + O(x^11)

Shifting

AbstractAlgebra.shift_leftMethod
shift_left(x::RelPowerSeriesRingElem{T}, n::Int) where T <: RingElement

Return the power series $x$ shifted left by $n$ terms, i.e. multiplied by $x^n$.

source
AbstractAlgebra.shift_rightMethod
shift_right(x::RelPowerSeriesRingElem{T}, n::Int) where T <: RingElement

Return the power series $x$ shifted right by $n$ terms, i.e. divided by $x^n$.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S, x = power_series_ring(R, 30, :x)
@@ -206,7 +206,7 @@
 
 julia> k = shift_right(d, 3)
 1 + O(x^1)
-

Truncation

Base.truncateMethod
truncate(a::RelPowerSeriesRingElem{T}, n::Int) where T <: RingElement

Return $a$ truncated to (absolute) precision $n$.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
+

Truncation

Base.truncateMethod
truncate(a::RelPowerSeriesRingElem{T}, n::Int) where T <: RingElement

Return $a$ truncated to (absolute) precision $n$.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S, x = power_series_ring(R, 30, :x)
@@ -235,7 +235,7 @@
 
 julia> k = truncate(d, 5)
 2*x + x^3 + O(x^4)
-

Division

Base.invMethod
Base.inv(a::RelPowerSeriesRingElem)

Return the inverse of the power series $a$, i.e. $1/a$.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
+

Division

Base.invMethod
Base.inv(a::RelPowerSeriesRingElem)

Return the inverse of the power series $a$, i.e. $1/a$.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S, x = power_series_ring(R, 30, :x)
@@ -252,21 +252,21 @@
 
 julia> d = inv(b)
 -1 + O(x^30)
-

Composition

AbstractAlgebra.composeMethod
compose(f::RelPowerSeriesRingElem, g::RelPowerSeriesRingElem; inner)

Compose the series $a$ with the series $b$ and return the result.

  • If inner = :second, then f(g) is returned and g must have positive valuation.
  • If inner = :first, then g(f) is returned and f must have positive valuation.
source

Note that subst can be used instead of compose, however the provided functionality is the same. General series substitution is not well-defined.

Derivative and integral

AbstractAlgebra.derivativeMethod
derivative(f::AbsPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

source
derivative(f::RelPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
+

Composition

AbstractAlgebra.composeMethod
compose(f::RelPowerSeriesRingElem, g::RelPowerSeriesRingElem; inner)

Compose the series $a$ with the series $b$ and return the result.

  • If inner = :second, then f(g) is returned and g must have positive valuation.
  • If inner = :first, then g(f) is returned and f must have positive valuation.
source

Note that subst can be used instead of compose, however the provided functionality is the same. General series substitution is not well-defined.

Derivative and integral

AbstractAlgebra.derivativeMethod
derivative(f::AbsPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

source
derivative(f::RelPowerSeriesRingElem{T})

Return the derivative of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
 (Univariate power series ring in x over Rationals, x + O(x^11))
 
 julia> f = 2 + x + 3x^3
 2 + x + 3*x^3 + O(x^10)
 
 julia> derivative(f)
-1 + 9*x^2 + O(x^9)
source
derivative(f::MPolyRingElem{T}, j::Int) where {T <: RingElement}

Return the partial derivative of f with respect to $j$-th variable of the polynomial ring.

source
derivative(f::MPolyRingElem{T}, x::MPolyRingElem{T}) where T <: RingElement

Return the partial derivative of f with respect to x. The value x must be a generator of the polynomial ring of f.

source
derivative(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the derivative of the given Puiseux series $a$.

source
AbstractAlgebra.integralMethod
integral(f::AbsPowerSeriesRingElem{T})

Return the integral of the power series $f$.

source
integral(f::RelPowerSeriesRingElem{T})

Return the integral of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
+1 + 9*x^2 + O(x^9)
source
derivative(f::MPolyRingElem{T}, j::Int) where {T <: RingElement}

Return the partial derivative of f with respect to $j$-th variable of the polynomial ring.

source
derivative(f::MPolyRingElem{T}, x::MPolyRingElem{T}) where T <: RingElement

Return the partial derivative of f with respect to x. The value x must be a generator of the polynomial ring of f.

source
derivative(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the derivative of the given Puiseux series $a$.

source
AbstractAlgebra.integralMethod
integral(f::AbsPowerSeriesRingElem{T})

Return the integral of the power series $f$.

source
integral(f::RelPowerSeriesRingElem{T})

Return the integral of the power series $f$.

julia> R, x = power_series_ring(QQ, 10, :x)
 (Univariate power series ring in x over Rationals, x + O(x^11))
 
 julia> f = 2 + x + 3x^3
 2 + x + 3*x^3 + O(x^10)
 
 julia> integral(f)
-2*x + 1//2*x^2 + 3//4*x^4 + O(x^11)
source
integral(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the integral of the given Puiseux series $a$.

source

Special functions

Base.logMethod
log(a::SeriesElem{T}) where T <: FieldElement

Return the logarithm of the power series $a$.

source
log(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the logarithm of the given Puiseux series $a$.

source
Base.expMethod
exp(a::AbsPowerSeriesRingElem)

Return the exponential of the power series $a$.

source
exp(a::RelPowerSeriesRingElem)

Return the exponential of the power series $a$.

source
exp(a::Generic.LaurentSeriesElem)

Return the exponential of the power series $a$.

source
exp(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the exponential of the given Puiseux series $a$.

source
Base.sqrtMethod
sqrt(a::RelPowerSeriesRingElem)

Return the square root of the power series $a$. By default the function raises an exception if the input is not a square. If check=false this check is omitted.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
+2*x + 1//2*x^2 + 3//4*x^4 + O(x^11)
source
integral(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the integral of the given Puiseux series $a$.

source

Special functions

Base.logMethod
log(a::SeriesElem{T}) where T <: FieldElement

Return the logarithm of the power series $a$.

source
log(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the logarithm of the given Puiseux series $a$.

source
Base.expMethod
exp(a::AbsPowerSeriesRingElem)

Return the exponential of the power series $a$.

source
exp(a::RelPowerSeriesRingElem)

Return the exponential of the power series $a$.

source
exp(a::Generic.LaurentSeriesElem)

Return the exponential of the power series $a$.

source
exp(a::Generic.PuiseuxSeriesElem{T}) where T <: RingElement

Return the exponential of the given Puiseux series $a$.

source
Base.sqrtMethod
sqrt(a::RelPowerSeriesRingElem)

Return the square root of the power series $a$. By default the function raises an exception if the input is not a square. If check=false this check is omitted.

source

Examples

julia> R, t = polynomial_ring(QQ, :t)
 (Univariate polynomial ring in t over rationals, t)
 
 julia> S, x = power_series_ring(R, 30, :x)
@@ -299,4 +299,4 @@
 (Univariate power series ring over integers, x + O(x^11))
 
 julia> f = rand(R, 3:5, -10:10)
-3*x^4 - x^5 + 4*x^7 + 4*x^8 - 7*x^9 + 2*x^10 + 4*x^11 - x^12 - 4*x^13 + O(x^14)
+3*x^4 - x^5 + 4*x^7 + 4*x^8 - 7*x^9 + 2*x^10 + 4*x^11 - x^12 - 4*x^13 + O(x^14) diff --git a/dev/series_interface/index.html b/dev/series_interface/index.html index 32b03bea7..ff2947767 100644 --- a/dev/series_interface/index.html +++ b/dev/series_interface/index.html @@ -15,4 +15,4 @@ zero(x::MySeries, R::Ring, max_prec::Int, var::VarName; cached::Bool=true) zero(x::MySeries, R::Ring, var::VarName; cached::Bool=true) zero(x::MySeries, max_prec::Int, var::VarName; cached::Bool=true) -zero(x::MySeries, var::VarName; cached::Bool=true)

As above, but use the precision cap of the parent ring of x and the base_ring of x if these are not specified.

Custom series rings may choose which series type is best-suited to return for the given coefficient ring, precision cap and variable, however they should return a series with the same model as x, i.e. relative or series.

If custom implementations don't specialise these function the default return type is a Generic.AbsSeries or Generic.RelSeries.

The default implementation of zero calls out to similar, so it's generally sufficient to specialise only similar. For both similar and zero only the most general method has to be implemented as all other methods call out to this more general method.

+zero(x::MySeries, var::VarName; cached::Bool=true)

As above, but use the precision cap of the parent ring of x and the base_ring of x if these are not specified.

Custom series rings may choose which series type is best-suited to return for the given coefficient ring, precision cap and variable, however they should return a series with the same model as x, i.e. relative or series.

If custom implementations don't specialise these function the default return type is a Generic.AbsSeries or Generic.RelSeries.

The default implementation of zero calls out to similar, so it's generally sufficient to specialise only similar. For both similar and zero only the most general method has to be implemented as all other methods call out to this more general method.

diff --git a/dev/submodule/index.html b/dev/submodule/index.html index dbbe85b5a..08725ca10 100644 --- a/dev/submodule/index.html +++ b/dev/submodule/index.html @@ -1,5 +1,5 @@ -Submodules · AbstractAlgebra.jl

Submodules

AbstractAlgebra allows the construction of submodules/subvector spaces of AbstractAlgebra modules over euclidean domains. These are given as the submodule generated by a finite list of elements in the original module.

We define two submodules to be equal if they are (transitively) submodules of the same module $M$ and their generators generate the same set of elements.

Generic submodule type

AbstractAlgebra implements a generic submodule type Generic.Submodule{T} where T is the element type of the base ring in src/generic/Submodule.jl. See src/generic/GenericTypes.jl for more details of the type definition.

Elements of a generic submodule have type Generic.SubmoduleElem{T}.

Abstract types

Submodule types belong to the abstract type FPModule{T} and their elements to FPModuleElem{T}.

Constructors

AbstractAlgebra.subMethod
sub(m::FPModule{T}, gens::Vector{<:FPModuleElem{T}}) where T <: RingElement

Return the submodule of the module m generated by the given generators, given as elements of m.

source
AbstractAlgebra.subMethod
sub(m::Module{T}, subs::Vector{<:Generic.Submodule{T}}) where T <: RingElement

Return the submodule S of the module m generated by the union of the given submodules of $m$, and a map which is the canonical injection from S to m.

source

Note that the preimage of the canonical injection can be obtained using the preimage function described in the section on module homomorphisms. As the canonical injection is injective, this is unique.

Examples

julia> M = free_module(ZZ, 2)
+Submodules · AbstractAlgebra.jl

Submodules

AbstractAlgebra allows the construction of submodules/subvector spaces of AbstractAlgebra modules over euclidean domains. These are given as the submodule generated by a finite list of elements in the original module.

We define two submodules to be equal if they are (transitively) submodules of the same module $M$ and their generators generate the same set of elements.

Generic submodule type

AbstractAlgebra implements a generic submodule type Generic.Submodule{T} where T is the element type of the base ring in src/generic/Submodule.jl. See src/generic/GenericTypes.jl for more details of the type definition.

Elements of a generic submodule have type Generic.SubmoduleElem{T}.

Abstract types

Submodule types belong to the abstract type FPModule{T} and their elements to FPModuleElem{T}.

Constructors

AbstractAlgebra.subMethod
sub(m::FPModule{T}, gens::Vector{<:FPModuleElem{T}}) where T <: RingElement

Return the submodule of the module m generated by the given generators, given as elements of m.

source
AbstractAlgebra.subMethod
sub(m::Module{T}, subs::Vector{<:Generic.Submodule{T}}) where T <: RingElement

Return the submodule S of the module m generated by the union of the given submodules of $m$, and a map which is the canonical injection from S to m.

source

Note that the preimage of the canonical injection can be obtained using the preimage function described in the section on module homomorphisms. As the canonical injection is injective, this is unique.

Examples

julia> M = free_module(ZZ, 2)
 Free module of rank 2 over integers
 
 julia> m = M([ZZ(1), ZZ(2)])
@@ -28,7 +28,7 @@
 
 julia> N, f = sub(V, [m, n])
 (Subspace over rationals with 2 generators and no relations, Hom: N -> V)
-

Functionality for submodules

In addition to the Module interface, AbstractAlgebra submodules implement the following functionality.

Basic manipulation

AbstractAlgebra.Generic.is_submoduleMethod
is_submodule(M::AbstractAlgebra.FPModule{T}, N::AbstractAlgebra.FPModule{T}) where T <: RingElement

Return true if $N$ was constructed as a submodule of $M$. The relation is taken transitively (i.e. subsubmodules are submodules for the purposes of this relation, etc). The module $M$ is also considered a submodule of itself for this relation.

source
AbstractAlgebra.Generic.is_compatibleMethod
is_compatible(M::AbstractAlgebra.FPModule{T}, N::AbstractAlgebra.FPModule{T}) where T <: RingElement

Return true, P if the given modules are compatible, i.e. that they are (transitively) submodules of the same module, P. Otherwise return false, M.

source

Examples

julia> M = free_module(ZZ, 2)
+

Functionality for submodules

In addition to the Module interface, AbstractAlgebra submodules implement the following functionality.

Basic manipulation

AbstractAlgebra.Generic.is_submoduleMethod
is_submodule(M::AbstractAlgebra.FPModule{T}, N::AbstractAlgebra.FPModule{T}) where T <: RingElement

Return true if $N$ was constructed as a submodule of $M$. The relation is taken transitively (i.e. subsubmodules are submodules for the purposes of this relation, etc). The module $M$ is also considered a submodule of itself for this relation.

source
AbstractAlgebra.Generic.is_compatibleMethod
is_compatible(M::AbstractAlgebra.FPModule{T}, N::AbstractAlgebra.FPModule{T}) where T <: RingElement

Return true, P if the given modules are compatible, i.e. that they are (transitively) submodules of the same module, P. Otherwise return false, M.

source

Examples

julia> M = free_module(ZZ, 2)
 Free module of rank 2 over integers
 
 julia> m = M([ZZ(2), ZZ(3)])
@@ -65,7 +65,7 @@
 2
 
 julia> dim(N)
-1

Intersection

Base.intersectMethod
intersect(M::FPModule{T}, N::FPModule{T}) where T <: RingElement

Return the intersection of the modules $M$ as a submodule of $M$. Note that $M$ and $N$ must be (constructed as) submodules (transitively) of some common module $P$.

source

Examples

julia> M = free_module(ZZ, 2)
+1

Intersection

Base.intersectMethod
intersect(M::FPModule{T}, N::FPModule{T}) where T <: RingElement

Return the intersection of the modules $M$ as a submodule of $M$. Note that $M$ and $N$ must be (constructed as) submodules (transitively) of some common module $P$.

source

Examples

julia> M = free_module(ZZ, 2)
 Free module of rank 2 over integers
 
 julia> m = M([ZZ(2), ZZ(3)])
@@ -81,4 +81,4 @@
 (Submodule over integers with 1 generator and no relations, Hom: submodule over integers with 1 generator and no relations -> M)
 
 julia> I = intersect(N1, N2)
-Any[]
+Any[]
diff --git a/dev/total_fraction/index.html b/dev/total_fraction/index.html index b8caa856c..542bf180b 100644 --- a/dev/total_fraction/index.html +++ b/dev/total_fraction/index.html @@ -104,4 +104,4 @@ Total ring of fractions of R julia> g = rand(S, -1:3, -10:10) -(4*x + 4)//(-4*x^2 - x + 4) +(4*x + 4)//(-4*x^2 - x + 4) diff --git a/dev/types/index.html b/dev/types/index.html index 807c489f0..86ea30065 100644 --- a/dev/types/index.html +++ b/dev/types/index.html @@ -15,4 +15,4 @@ true julia> parent(f) == R -true +true diff --git a/dev/univpolynomial/index.html b/dev/univpolynomial/index.html index 0c0dba79e..d137fa3f9 100644 --- a/dev/univpolynomial/index.html +++ b/dev/univpolynomial/index.html @@ -9,7 +9,7 @@ (y, z) julia> x*y - z -x*y - zsource

Adding variables

There are two ways to add variables to a universal polynomial ring S.

gen(S::UniversalPolyRing, var::VarName)
+x*y - z
source

Adding variables

There are two ways to add variables to a universal polynomial ring S.

gen(S::UniversalPolyRing, var::VarName)
 gens(S::UniversalPolyRing, vars::Vector{VarName})

Examples

julia> S = universal_polynomial_ring(ZZ)
 Universal Polynomial Ring over Integers
 
@@ -23,4 +23,4 @@
 (y, z)
 
 julia> number_of_generators(S)
-3

Universal polynomial functionality

The universal polynomial ring behaves exactly like a multivariate polynomial ring with the few differences noted above.

The only functionality not implemented is the ability to do divrem by an ideal of polynomials.

The universal polynomial ring is very useful for doing symbolic manipulation. However, it is important to understand that AbstractAlgebra is not a symbolic system and the performance of the universal polynomial ring will closely match that of a multivariate polynomial ring with the same number of variables.

The disadvantage of this approach to symbolic manipulation is that some manipulations that would be offered by a symbolic system are not available, as variables are not identified by their names alone in AbstractAlgebra, as would be the case symbolically, but by objects.

The most powerful symbolic tools we offer are the generalised evaluation functions, the multivariate coefficient functionality, the ability to change coefficient ring and to map coefficients according to a supplied function and the ability to convert a multivariate which happens to have just one variable into a dense univariate polynomial.

Further facilities may be added in future to ease symbolic manipulations.

+3

Universal polynomial functionality

The universal polynomial ring behaves exactly like a multivariate polynomial ring with the few differences noted above.

The only functionality not implemented is the ability to do divrem by an ideal of polynomials.

The universal polynomial ring is very useful for doing symbolic manipulation. However, it is important to understand that AbstractAlgebra is not a symbolic system and the performance of the universal polynomial ring will closely match that of a multivariate polynomial ring with the same number of variables.

The disadvantage of this approach to symbolic manipulation is that some manipulations that would be offered by a symbolic system are not available, as variables are not identified by their names alone in AbstractAlgebra, as would be the case symbolically, but by objects.

The most powerful symbolic tools we offer are the generalised evaluation functions, the multivariate coefficient functionality, the ability to change coefficient ring and to map coefficients according to a supplied function and the ability to convert a multivariate which happens to have just one variable into a dense univariate polynomial.

Further facilities may be added in future to ease symbolic manipulations.

diff --git a/dev/visualizing_types/index.html b/dev/visualizing_types/index.html index 31a3ecf08..73b9ff1f9 100644 --- a/dev/visualizing_types/index.html +++ b/dev/visualizing_types/index.html @@ -1,2 +1,2 @@ -Visualization of the types of AbstractAlgebra.jl · AbstractAlgebra.jl

Visualization of the types of AbstractAlgebra.jl

AbstractAlgebra.jl implements a couple of abstract types which can be extended.

Abstract parents

The following diagram shows a complete list of all abstract types in AbstractAlgebra.jl.

Diagram of parent types

Abstract elements

Similarly the following diagram shows a complete list of all abstract types in AbstractAlgebra.jl.

Diagram of element types

Concrete types in AbstractAlgebra.jl

Until now we have discussed the abstract types of AbstractAlgebra.jl. Under this subsection we will instead give some examples of concrete types in AbstractAlgebra.jl.

In parentheses we put the types of the corresponding parent objects.

  • Perm{<:Integer} (SymmetricGroup{<:Integer})
  • GFElem{<:Integer} (GFField{<:Integer})

We also think of various Julia types as though they were AbstractAlgebra.jl types:

  • BigInt (Integers{BigInt})
  • Rational{BigInt} (Rationals{BigInt})

Then there are various types for generic constructions over a base ring. They are all parameterised by a type T which is the type of the elements of the base ring they are defined over.

  • Generic.Poly{T} (Generic.PolyRing{T})
  • Generic.MPoly{T} (Generic.MPolyRing{T})
  • Generic.RelSeries{T} (Generic.RelPowerSeriesRing{T})
  • Generic.AbsSeries{T} (Generic.AbsPowerSeriesRing{T})
  • Generic.LaurentSeriesRingElem{T} (Generic.LaurentSeriesRing{T})
  • Generic.LaurentSeriesFieldElem{T} (Generic.LaurentSeriesField{T})
  • Generic.ResidueRingElem{T} (Generic.ResidueRing{T})
  • Generic.FracFieldElem{T} (Generic.FracField{T})
  • Generic.Mat{T} (MatSpace{T})
+Visualization of the types of AbstractAlgebra.jl · AbstractAlgebra.jl

Visualization of the types of AbstractAlgebra.jl

AbstractAlgebra.jl implements a couple of abstract types which can be extended.

Abstract parents

The following diagram shows a complete list of all abstract types in AbstractAlgebra.jl.

Diagram of parent types

Abstract elements

Similarly the following diagram shows a complete list of all abstract types in AbstractAlgebra.jl.

Diagram of element types

Concrete types in AbstractAlgebra.jl

Until now we have discussed the abstract types of AbstractAlgebra.jl. Under this subsection we will instead give some examples of concrete types in AbstractAlgebra.jl.

In parentheses we put the types of the corresponding parent objects.

  • Perm{<:Integer} (SymmetricGroup{<:Integer})
  • GFElem{<:Integer} (GFField{<:Integer})

We also think of various Julia types as though they were AbstractAlgebra.jl types:

  • BigInt (Integers{BigInt})
  • Rational{BigInt} (Rationals{BigInt})

Then there are various types for generic constructions over a base ring. They are all parameterised by a type T which is the type of the elements of the base ring they are defined over.

  • Generic.Poly{T} (Generic.PolyRing{T})
  • Generic.MPoly{T} (Generic.MPolyRing{T})
  • Generic.RelSeries{T} (Generic.RelPowerSeriesRing{T})
  • Generic.AbsSeries{T} (Generic.AbsPowerSeriesRing{T})
  • Generic.LaurentSeriesRingElem{T} (Generic.LaurentSeriesRing{T})
  • Generic.LaurentSeriesFieldElem{T} (Generic.LaurentSeriesField{T})
  • Generic.ResidueRingElem{T} (Generic.ResidueRing{T})
  • Generic.FracFieldElem{T} (Generic.FracField{T})
  • Generic.Mat{T} (MatSpace{T})
diff --git a/dev/ytabs/index.html b/dev/ytabs/index.html index b7b068945..e105d7cca 100644 --- a/dev/ytabs/index.html +++ b/dev/ytabs/index.html @@ -3,8 +3,8 @@ 4₁2₁1₃ julia> p.n == sum(p.part) -truesource

Array interface

Partition is a concrete (immutable) subtype of AbstractVector{Integer} and implements the standard Array interface.

Base.sizeMethod
size(p::Partition)

Return the size of the vector which represents the partition.

Examples

julia> p = Partition([4,3,1]); size(p)
-(3,)
source
Base.getindexMethod
getindex(p::Partition, i::Integer)

Return the i-th part (in non-increasing order) of the partition.

source

These functions work on the level of p.part vector.

One can easily iterate over all partitions of $n$ using the Generic.partitions function.

AbstractAlgebra.Generic.partitionsFunction
partitions(n::Integer)

Return the vector of all permutations of n. For an unsafe generator version see partitions!.

Examples

julia> Generic.partitions(5)
+true
source

Array interface

Partition is a concrete (immutable) subtype of AbstractVector{Integer} and implements the standard Array interface.

Base.sizeMethod
size(p::Partition)

Return the size of the vector which represents the partition.

Examples

julia> p = Partition([4,3,1]); size(p)
+(3,)
source
Base.getindexMethod
getindex(p::Partition, i::Integer)

Return the i-th part (in non-increasing order) of the partition.

source

These functions work on the level of p.part vector.

One can easily iterate over all partitions of $n$ using the Generic.partitions function.

AbstractAlgebra.Generic.partitionsFunction
partitions(n::Integer)

Return the vector of all permutations of n. For an unsafe generator version see partitions!.

Examples

julia> Generic.partitions(5)
 7-element Vector{AbstractAlgebra.Generic.Partition{Int64}}:
  1₅
  2₁1₃
@@ -12,11 +12,11 @@
  2₂1₁
  4₁1₁
  3₁2₁
- 5₁
source

You may also have a look at JuLie.jl package for more utilities related to partitions.

The number of all partitions can be computed by the hidden function _numpart. Much faster implementation is available in Nemo.jl.

AbstractAlgebra.Generic._numpartFunction
_numpart(n::Integer)

Return the number of all distinct integer partitions of n. The function uses Euler pentagonal number theorem for recursive formula. For more details see OEIS sequence A000041. Note that _numpart(0) = 1 by convention.

source

Since Partition is a subtype of AbstractVector generic functions which operate on vectors should work in general. However the meaning of conj has been changed to agree with the traditional understanding of conjugation of Partitions:

Base.conjMethod
conj(part::Partition)

Return the conjugated partition of part, i.e. the partition corresponding to the Young diagram of part reflected through the main diagonal.

Examples

julia> p = Partition([4,2,1,1,1])
+ 5₁
source

You may also have a look at JuLie.jl package for more utilities related to partitions.

The number of all partitions can be computed by the hidden function _numpart. Much faster implementation is available in Nemo.jl.

AbstractAlgebra.Generic._numpartFunction
_numpart(n::Integer)

Return the number of all distinct integer partitions of n. The function uses Euler pentagonal number theorem for recursive formula. For more details see OEIS sequence A000041. Note that _numpart(0) = 1 by convention.

source

Since Partition is a subtype of AbstractVector generic functions which operate on vectors should work in general. However the meaning of conj has been changed to agree with the traditional understanding of conjugation of Partitions:

Base.conjMethod
conj(part::Partition)

Return the conjugated partition of part, i.e. the partition corresponding to the Young diagram of part reflected through the main diagonal.

Examples

julia> p = Partition([4,2,1,1,1])
 4₁2₁1₃
 
 julia> conj(p)
-5₁2₁1₂
source
Base.conjMethod
conj(part::Partition, v::Vector)

Return the conjugated partition of part together with permuted vector v.

source

Young Diagrams and Young Tableaux

Mathematically speaking Young diagram is a diagram which consists of rows of square boxes such that the number of boxes in each row is no less than the number of boxes in the previous row. For example partition $4_1 3_2 1$ represents the following diagram.

┌───┬───┬───┬───┐
+5₁2₁1₂
source
Base.conjMethod
conj(part::Partition, v::Vector)

Return the conjugated partition of part together with permuted vector v.

source

Young Diagrams and Young Tableaux

Mathematically speaking Young diagram is a diagram which consists of rows of square boxes such that the number of boxes in each row is no less than the number of boxes in the previous row. For example partition $4_1 3_2 1$ represents the following diagram.

┌───┬───┬───┬───┐
 │   │   │   │   │
 ├───┼───┼───┼───┘
 │   │   │   │
@@ -53,8 +53,8 @@
  5
  6
  7
- 8
source

For convenience there exists an alternative constructor of YoungTableau, which accepts a vector of integers and constructs Partition internally.

YoungTableau(p::Vector{Integer}[, fill=collect(1:sum(p))])

Array interface

To make YoungTableaux array-like we implement the following functions:

Base.sizeMethod
size(Y::YoungTableau)

Return size of the smallest array containing Y, i.e. the tuple of the number of rows and the number of columns of Y.

Examples

julia> y = YoungTableau([4,3,1]); size(y)
-(3, 4)
source
Base.getindexMethod
getindex(Y::YoungTableau, n::Integer)

Return the column-major linear index into the size(Y)-array. If a box is outside of the array return 0.

Examples

julia> y = YoungTableau([4,3,1])
+ 8
source

For convenience there exists an alternative constructor of YoungTableau, which accepts a vector of integers and constructs Partition internally.

YoungTableau(p::Vector{Integer}[, fill=collect(1:sum(p))])

Array interface

To make YoungTableaux array-like we implement the following functions:

Base.sizeMethod
size(Y::YoungTableau)

Return size of the smallest array containing Y, i.e. the tuple of the number of rows and the number of columns of Y.

Examples

julia> y = YoungTableau([4,3,1]); size(y)
+(3, 4)
source
Base.getindexMethod
getindex(Y::YoungTableau, n::Integer)

Return the column-major linear index into the size(Y)-array. If a box is outside of the array return 0.

Examples

julia> y = YoungTableau([4,3,1])
 ┌───┬───┬───┬───┐
 │ 1 │ 2 │ 3 │ 4 │
 ├───┼───┼───┼───┘
@@ -73,7 +73,7 @@
 2
 
 julia> y[6]
-0
source

Also the double-indexing corresponds to (row, column) access to an abstract array.

julia> y = YoungTableau([4,3,1])
+0
source

Also the double-indexing corresponds to (row, column) access to an abstract array.

julia> y = YoungTableau([4,3,1])
 ┌───┬───┬───┬───┐
 │ 1 │ 2 │ 3 │ 4 │
 ├───┼───┼───┼───┘
@@ -107,7 +107,7 @@
 │ 3 │ 7 │
 ├───┼───┘
 │ 4 │
-└───┘
source

Pretty-printing

Similarly to permutations we have two methods of displaying Young Diagrams:

AbstractAlgebra.Generic.setyoungtabstyleFunction
setyoungtabstyle(format::Symbol)

Select the style in which Young tableaux are displayed (in REPL or in general as string). This can be either

  • :array - as matrices of integers, or
  • :diagram - as filled Young diagrams (the default).

The difference is purely esthetical.

Examples

julia> Generic.setyoungtabstyle(:array)
+└───┘
source

Pretty-printing

Similarly to permutations we have two methods of displaying Young Diagrams:

AbstractAlgebra.Generic.setyoungtabstyleFunction
setyoungtabstyle(format::Symbol)

Select the style in which Young tableaux are displayed (in REPL or in general as string). This can be either

  • :array - as matrices of integers, or
  • :diagram - as filled Young diagrams (the default).

The difference is purely esthetical.

Examples

julia> Generic.setyoungtabstyle(:array)
 :array
 
 julia> p = Partition([4,3,1]); YoungTableau(p)
@@ -125,7 +125,7 @@
 │ 5 │ 6 │ 7 │
 ├───┼───┴───┘
 │ 8 │
-└───┘
source

Ulitility functions

AbstractAlgebra.Generic.matrix_reprMethod
matrix_repr(a::Perm)

Return the permutation matrix as a sparse matrix representing a via natural embedding of the permutation group into the general linear group over $\mathbb{Z}$.

Examples

julia> p = Perm([2,3,1])
+└───┘
source

Ulitility functions

AbstractAlgebra.Generic.matrix_reprMethod
matrix_repr(a::Perm)

Return the permutation matrix as a sparse matrix representing a via natural embedding of the permutation group into the general linear group over $\mathbb{Z}$.

Examples

julia> p = Perm([2,3,1])
 (1,2,3)
 
 julia> matrix_repr(p)
@@ -138,14 +138,14 @@
 3×3 Matrix{Int64}:
  0  1  0
  0  0  1
- 1  0  0
source
matrix_repr(Y::YoungTableau)

Construct sparse integer matrix representing the tableau.

Examples

julia> y = YoungTableau([4,3,1]);
+ 1  0  0
source
matrix_repr(Y::YoungTableau)

Construct sparse integer matrix representing the tableau.

Examples

julia> y = YoungTableau([4,3,1]);
 
 
 julia> matrix_repr(y)
 3×4 SparseArrays.SparseMatrixCSC{Int64, Int64} with 8 stored entries:
  1  2  3  4
  5  6  7  ⋅
- 8  ⋅  ⋅  ⋅
source
Base.fill!Method
fill!(Y::YoungTableaux, V::Vector{<:Integer})

Replace the fill vector Y.fill by V. No check if the resulting tableau is standard (i.e. increasing along rows and columns) is performed.

Examples

julia> y = YoungTableau([4,3,1])
+ 8  ⋅  ⋅  ⋅
source
Base.fill!Method
fill!(Y::YoungTableaux, V::Vector{<:Integer})

Replace the fill vector Y.fill by V. No check if the resulting tableau is standard (i.e. increasing along rows and columns) is performed.

Examples

julia> y = YoungTableau([4,3,1])
 ┌───┬───┬───┬───┐
 │ 1 │ 2 │ 3 │ 4 │
 ├───┼───┼───┼───┘
@@ -161,7 +161,7 @@
 │ 6 │ 7 │ 8 │
 ├───┼───┴───┘
 │ 9 │
-└───┘
source

Characters of permutation groups

Irreducible characters (at least over field of characteristic $0$) of the full group of permutations $S_n$ correspond via Specht modules to partitions of $n$.

AbstractAlgebra.Generic.characterMethod
character(lambda::Partition)

Return the $\lambda$-th irreducible character of permutation group on sum(lambda) symbols. The returned character function is of the following signature:

chi(p::Perm[, check::Bool=true]) -> BigInt

The function checks (if p belongs to the appropriate group) can be switched off by calling chi(p, false). The values computed by $\chi$ are cached in look-up table.

The computation follows the Murnaghan-Nakayama formula: $\chi_\lambda(\sigma) = \sum_{\text{rimhook }\xi\subset \lambda}(-1)^{ll(\lambda\backslash\xi)} \chi_{\lambda \backslash\xi}(\tilde\sigma)$ where $\lambda\backslash\xi$ denotes the skew diagram of $\lambda$ with $\xi$ removed, $ll$ denotes the leg-length (i.e. number of rows - 1) and $\tilde\sigma$ is permutation obtained from $\sigma$ by the removal of the longest cycle.

For more details see e.g. Chapter 2.8 of Group Theory and Physics by S.Sternberg.

Examples

julia> G = SymmetricGroup(4)
+└───┘
source

Characters of permutation groups

Irreducible characters (at least over field of characteristic $0$) of the full group of permutations $S_n$ correspond via Specht modules to partitions of $n$.

AbstractAlgebra.Generic.characterMethod
character(lambda::Partition)

Return the $\lambda$-th irreducible character of permutation group on sum(lambda) symbols. The returned character function is of the following signature:

chi(p::Perm[, check::Bool=true]) -> BigInt

The function checks (if p belongs to the appropriate group) can be switched off by calling chi(p, false). The values computed by $\chi$ are cached in look-up table.

The computation follows the Murnaghan-Nakayama formula: $\chi_\lambda(\sigma) = \sum_{\text{rimhook }\xi\subset \lambda}(-1)^{ll(\lambda\backslash\xi)} \chi_{\lambda \backslash\xi}(\tilde\sigma)$ where $\lambda\backslash\xi$ denotes the skew diagram of $\lambda$ with $\xi$ removed, $ll$ denotes the leg-length (i.e. number of rows - 1) and $\tilde\sigma$ is permutation obtained from $\sigma$ by the removal of the longest cycle.

For more details see e.g. Chapter 2.8 of Group Theory and Physics by S.Sternberg.

Examples

julia> G = SymmetricGroup(4)
 Full symmetric group over 4 elements
 
 julia> chi = character(Partition([3,1])); # character of the regular representation
@@ -171,7 +171,7 @@
 3
 
 julia> chi(perm"(1,3)(2,4)")
--1
source
AbstractAlgebra.Generic.characterMethod
character(lambda::Partition, p::Perm, check::Bool=true) -> BigInt

Return the value of lambda-th irreducible character of the permutation group on permutation p.

source
AbstractAlgebra.Generic.characterMethod
character(lambda::Partition, mu::Partition, check::Bool=true) -> BigInt

Return the value of lambda-th irreducible character on the conjugacy class represented by partition mu.

source

The values computed by characters are cached in an internal dictionary Dict{Tuple{BitVector,Vector{Int}}, BigInt}. Note that all of the above functions return BigInts. If you are sure that the computations do not overflow, variants of the last two functions using Int are available:

character(::Type{Int}, lambda::Partition, p::Perm[, check::Bool=true])
+-1
source
AbstractAlgebra.Generic.characterMethod
character(lambda::Partition, p::Perm, check::Bool=true) -> BigInt

Return the value of lambda-th irreducible character of the permutation group on permutation p.

source
AbstractAlgebra.Generic.characterMethod
character(lambda::Partition, mu::Partition, check::Bool=true) -> BigInt

Return the value of lambda-th irreducible character on the conjugacy class represented by partition mu.

source

The values computed by characters are cached in an internal dictionary Dict{Tuple{BitVector,Vector{Int}}, BigInt}. Note that all of the above functions return BigInts. If you are sure that the computations do not overflow, variants of the last two functions using Int are available:

character(::Type{Int}, lambda::Partition, p::Perm[, check::Bool=true])
 character(::Type{Int}, lambda::Partition, mu::Partition[, check::Bool=true])

The dimension $\dim \lambda$ of the irreducible module corresponding to partition $\lambda$ can be computed using Hook length formula

AbstractAlgebra.Generic.rowlengthFunction
rowlength(Y::YoungTableau, i, j)

Return the row length of Y at box (i,j), i.e. the number of boxes in the i-th row of the diagram of Y located to the right of the (i,j)-th box.

Examples

julia> y = YoungTableau([4,3,1])
 ┌───┬───┬───┬───┐
 │ 1 │ 2 │ 3 │ 4 │
@@ -188,7 +188,7 @@
 0
 
 julia> Generic.rowlength(y, 3,3)
-0
source
AbstractAlgebra.Generic.collengthFunction
collength(Y::YoungTableau, i, j)

Return the column length of Y at box (i,j), i.e. the number of boxes in the j-th column of the diagram of Y located below of the (i,j)-th box.

Examples

julia> y = YoungTableau([4,3,1])
+0
source
AbstractAlgebra.Generic.collengthFunction
collength(Y::YoungTableau, i, j)

Return the column length of Y at box (i,j), i.e. the number of boxes in the j-th column of the diagram of Y located below of the (i,j)-th box.

Examples

julia> y = YoungTableau([4,3,1])
 ┌───┬───┬───┬───┐
 │ 1 │ 2 │ 3 │ 4 │
 ├───┼───┼───┼───┘
@@ -204,7 +204,7 @@
 1
 
 julia> Generic.collength(y, 2,4)
-0
source
AbstractAlgebra.Generic.hooklengthFunction
hooklength(Y::YoungTableau, i, j)

Return the hook-length of an element in Y at position (i,j), i.e the number of cells in the i-th row to the right of (i,j)-th box, plus the number of cells in the j-th column below the (i,j)-th box, plus 1.

Return 0 for (i,j) not in the tableau Y.

Examples

julia> y = YoungTableau([4,3,1])
+0
source
AbstractAlgebra.Generic.hooklengthFunction
hooklength(Y::YoungTableau, i, j)

Return the hook-length of an element in Y at position (i,j), i.e the number of cells in the i-th row to the right of (i,j)-th box, plus the number of cells in the j-th column below the (i,j)-th box, plus 1.

Return 0 for (i,j) not in the tableau Y.

Examples

julia> y = YoungTableau([4,3,1])
 ┌───┬───┬───┬───┐
 │ 1 │ 2 │ 3 │ 4 │
 ├───┼───┼───┼───┘
@@ -220,11 +220,11 @@
 3
 
 julia> hooklength(y, 2,4)
-0
source
AbstractAlgebra.Generic.dimMethod
dim(Y::YoungTableau) -> BigInt

Return the dimension (using hook-length formula) of the irreducible representation of permutation group $S_n$ associated the partition Y.part.

Since the computation overflows easily BigInt is returned. You may perform the computation of the dimension in different type by calling dim(Int, Y).

Examples

julia> dim(YoungTableau([4,3,1]))
+0
source
AbstractAlgebra.Generic.dimMethod
dim(Y::YoungTableau) -> BigInt

Return the dimension (using hook-length formula) of the irreducible representation of permutation group $S_n$ associated the partition Y.part.

Since the computation overflows easily BigInt is returned. You may perform the computation of the dimension in different type by calling dim(Int, Y).

Examples

julia> dim(YoungTableau([4,3,1]))
 70
 
 julia> dim(YoungTableau([3,1])) # the regular representation of S_4
-3
source

The character associated with Y.part can also be used to compute the dimension, but as it is expected the Murnaghan-Nakayama is much slower even though (due to caching) consecutive calls are fast:

julia> λ = Partition(collect(12:-1:1))
+3
source

The character associated with Y.part can also be used to compute the dimension, but as it is expected the Murnaghan-Nakayama is much slower even though (due to caching) consecutive calls are fast:

julia> λ = Partition(collect(12:-1:1))
 12₁11₁10₁9₁8₁7₁6₁5₁4₁3₁2₁1₁
 
 julia> @time dim(YoungTableau(λ))
@@ -244,9 +244,9 @@
 
 julia> @time character(λ, one(G))
   0.001439 seconds (195 allocations: 24.453 KiB)
-9079590132732747656880081324531330222983622187548672000

Low-level functions and characters

As mentioned above character functions use the Murnaghan-Nakayama rule for evaluation. The implementation follows

Dan Bernstein, The computational complexity of rules for the character table of $S_n$ Journal of Symbolic Computation, 37 (6), 2004, p. 727-748,

implementing the following functions. For precise definitions and meaning please consult the paper cited.

AbstractAlgebra.Generic.partitionseqFunction
partitionseq(lambda::Partition)

Return a sequence (as BitVector) of falses and trues constructed from lambda: tracing the lower contour of the Young Diagram associated to lambda from left to right a true is inserted for every horizontal and false for every vertical step. The sequence always starts with true and ends with false.

source
partitionseq(seq::BitVector)

Return the essential part of the sequence seq, i.e. a subsequence starting at first true and ending at last false.

source
AbstractAlgebra.Generic.is_rimhookMethod
is_rimhook(R::BitVector, idx::Integer, len::Integer)

R[idx:idx+len] forms a rim hook in the Young Diagram of partition corresponding to R iff R[idx] == true and R[idx+len] == false.

source
AbstractAlgebra.Generic.MN1innerFunction
MN1inner(R::BitVector, mu::Partition, t::Integer, charvals)

Return the value of $\lambda$-th irreducible character on conjugacy class of permutations represented by partition mu, where R is the (binary) partition sequence representing $\lambda$. Values already computed are stored in charvals::Dict{Tuple{BitVector,Vector{Int}}, Int}. This is an implementation (with slight modifications) of the Murnaghan-Nakayama formula as described in

Dan Bernstein,
+9079590132732747656880081324531330222983622187548672000

Low-level functions and characters

As mentioned above character functions use the Murnaghan-Nakayama rule for evaluation. The implementation follows

Dan Bernstein, The computational complexity of rules for the character table of $S_n$ Journal of Symbolic Computation, 37 (6), 2004, p. 727-748,

implementing the following functions. For precise definitions and meaning please consult the paper cited.

AbstractAlgebra.Generic.partitionseqFunction
partitionseq(lambda::Partition)

Return a sequence (as BitVector) of falses and trues constructed from lambda: tracing the lower contour of the Young Diagram associated to lambda from left to right a true is inserted for every horizontal and false for every vertical step. The sequence always starts with true and ends with false.

source
partitionseq(seq::BitVector)

Return the essential part of the sequence seq, i.e. a subsequence starting at first true and ending at last false.

source
AbstractAlgebra.Generic.is_rimhookMethod
is_rimhook(R::BitVector, idx::Integer, len::Integer)

R[idx:idx+len] forms a rim hook in the Young Diagram of partition corresponding to R iff R[idx] == true and R[idx+len] == false.

source
AbstractAlgebra.Generic.MN1innerFunction
MN1inner(R::BitVector, mu::Partition, t::Integer, charvals)

Return the value of $\lambda$-th irreducible character on conjugacy class of permutations represented by partition mu, where R is the (binary) partition sequence representing $\lambda$. Values already computed are stored in charvals::Dict{Tuple{BitVector,Vector{Int}}, Int}. This is an implementation (with slight modifications) of the Murnaghan-Nakayama formula as described in

Dan Bernstein,
 "The computational complexity of rules for the character table of Sn"
-_Journal of Symbolic Computation_, 37(6), 2004, p. 727-748.
source

Skew Diagrams

Skew diagrams are formally differences of two Young diagrams. Given $\lambda$ and $\mu$, two partitions of $n+m$ and $m$ (respectively). Suppose that each of cells of $\mu$ is a cell of $\lambda$ (i.e. parts of $\mu$ are no greater than the corresponding parts of $\lambda$). Then the skew diagram denoted by $\lambda/\mu$ is the set theoretic difference the of sets of boxes, i.e. is a diagram with exactly $n$ boxes:

AbstractAlgebra.Generic.SkewDiagramType
SkewDiagram(lambda::Partition, mu::Partition) <: AbstractMatrix{Int}

Implements a skew diagram, i.e. a difference of two Young diagrams represented by partitions lambda and mu. (below dots symbolise the removed entries)

Examples

julia> l = Partition([4,3,2])
+_Journal of Symbolic Computation_, 37(6), 2004, p. 727-748.
source

Skew Diagrams

Skew diagrams are formally differences of two Young diagrams. Given $\lambda$ and $\mu$, two partitions of $n+m$ and $m$ (respectively). Suppose that each of cells of $\mu$ is a cell of $\lambda$ (i.e. parts of $\mu$ are no greater than the corresponding parts of $\lambda$). Then the skew diagram denoted by $\lambda/\mu$ is the set theoretic difference the of sets of boxes, i.e. is a diagram with exactly $n$ boxes:

AbstractAlgebra.Generic.SkewDiagramType
SkewDiagram(lambda::Partition, mu::Partition) <: AbstractMatrix{Int}

Implements a skew diagram, i.e. a difference of two Young diagrams represented by partitions lambda and mu. (below dots symbolise the removed entries)

Examples

julia> l = Partition([4,3,2])
 4₁3₁2₁
 
 julia> m = Partition([3,1,1])
@@ -257,4 +257,4 @@
  ⋅  ⋅  ⋅  1
  ⋅  1  1
  ⋅  1
-
source

SkewDiagram implements array interface with the following functions:

Base.sizeMethod
size(xi::SkewDiagram)

Return the size of array where xi is minimally contained. See size(Y::YoungTableau) for more details.

source
Base.inMethod
in(t::Tuple{Integer,Integer}, xi::SkewDiagram)

Check if box at position (i,j) belongs to the skew diagram xi.

source
Base.getindexMethod
getindex(xi::SkewDiagram, n::Integer)

Return 1 if linear index n corresponds to (column-major) entry in xi.lam which is not contained in xi.mu. Otherwise return 0.

source

The support for skew diagrams is very rudimentary. The following functions are available:

AbstractAlgebra.Generic.leglengthFunction
leglength(xi::SkewDiagram[, check::Bool=true])

Compute the leglength of a rim-hook xi, i.e. the number of rows with non-zero entries minus one. If check is false function will not check whether xi is actually a rim-hook.

source
AbstractAlgebra.Generic.matrix_reprMethod
matrix_repr(xi::SkewDiagram)

Return a sparse representation of the diagram xi, i.e. a sparse array A where A[i,j] == 1 if and only if (i,j) is in xi.lam but not in xi.mu.

source
+source

SkewDiagram implements array interface with the following functions:

Base.sizeMethod
size(xi::SkewDiagram)

Return the size of array where xi is minimally contained. See size(Y::YoungTableau) for more details.

source
Base.inMethod
in(t::Tuple{Integer,Integer}, xi::SkewDiagram)

Check if box at position (i,j) belongs to the skew diagram xi.

source
Base.getindexMethod
getindex(xi::SkewDiagram, n::Integer)

Return 1 if linear index n corresponds to (column-major) entry in xi.lam which is not contained in xi.mu. Otherwise return 0.

source

The support for skew diagrams is very rudimentary. The following functions are available:

AbstractAlgebra.Generic.is_rimhookMethod
is_rimhook(xi::SkewDiagram)

Check if xi represents a rim-hook diagram, i.e. its diagram is edge-connected and contains no $2\times 2$ squares.

source
AbstractAlgebra.Generic.leglengthFunction
leglength(xi::SkewDiagram[, check::Bool=true])

Compute the leglength of a rim-hook xi, i.e. the number of rows with non-zero entries minus one. If check is false function will not check whether xi is actually a rim-hook.

source
AbstractAlgebra.Generic.matrix_reprMethod
matrix_repr(xi::SkewDiagram)

Return a sparse representation of the diagram xi, i.e. a sparse array A where A[i,j] == 1 if and only if (i,j) is in xi.lam but not in xi.mu.

source