From dbe4e2ae18b812b81514bac935bc603ebf3a7594 Mon Sep 17 00:00:00 2001 From: Mikelis Emils Mikelsons Date: Fri, 27 Jun 2025 11:47:32 +0200 Subject: [PATCH 1/4] Document ideal interface --- docs/make.jl | 1 + docs/src/ideal_interface.md | 126 ++++++++++++++++++++++++++++++++++++ src/Poly.jl | 2 +- 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 docs/src/ideal_interface.md diff --git a/docs/make.jl b/docs/make.jl index 45bb42ef2c..56635fb3f3 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -90,6 +90,7 @@ makedocs( "field_interface.md", "fraction_interface.md", "module_interface.md", + "ideal_inteface.md", "matrix_interface.md", "map_interface.md", "rand.md", diff --git a/docs/src/ideal_interface.md b/docs/src/ideal_interface.md new file mode 100644 index 0000000000..0a4e4b5b26 --- /dev/null +++ b/docs/src/ideal_interface.md @@ -0,0 +1,126 @@ +```@meta +CurrentModule = AbstractAlgebra +DocTestSetup = AbstractAlgebra.doctestsetup() +``` + +# Ideal Interface + +AbstractAlgebra.jl generic code makes use of a standardised set of functions which it +expects to be implemented by anyone implementing ideals for AbstractAlgebra rings. +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 ideals. +There are already many helper methods in AbstractAlgebra.jl for the methods mentioned below. + +In addition to the required functions, there are also optional functions which can be +provided for certain types of ideals e.g., for ideals of polynomial rings. If implemented, +these allow the generic code to provide additional functionality for those ideals, or in +some cases, to select more efficient algorithms. + +Currently AbstractAlgebra.jl provides ideals of a Euclidean domain (assuming the existence of a `gcdx` function) +or of a univariate or multivariate polynomial ring over the integers. +Univariate and multivariate polynomial rings over other +domains (other than fields) are not supported at this time. + +## Types and parents + +New implementations of ideals needn't necessarily supply new types and could just extend +the existing functionality for new rings as AbstractAlgebra.jl provides a generic ideal type +based on Julia arrays which is implemented in `src/generic/Ideal.jl`. For information +about implementing new rings, see the [Ring interface](@ref "Ring Interface"). + +The generic ideals have type `Generic.Ideal{T}` where `T` is the type of +elements of the ring the ideals belong to. Internally they consist of a Julia +array of generators and some additional fields for a parent object, etc. See +the file `src/generic/GenericTypes.jl` for details. + +Parent objects of ideals have type `Generic.IdealSet{T}`. + +All ideal types belong to the abstract type `Ideal{T}` and their parents belong +to the abstract type `Set`. This enables one to write generic functions that +can accept any AbstractAlgebra ideal type. + +New ideal types should come with the following methods: + +```julia +ideal_type(NewRingType) = NewIdealType +ideal_type(R::NewRing) = ideal_type(typeof(R)) +base_ring_type(I::NewIdealType) = NewRingType +parent_type(I::NewIdealType{T}) = DefaultIdealSet{T} +``` +## Required functionality for ideals + +In the following, we list all the functions that are required to be provided for ideals +in AbstractAlgebra.jl or by external libraries wanting to use AbstractAlgebra.jl. + +We give this interface for fictitious type `NewIdeal` and `Ring` or `NewRing` for the type of the base ring +object `R`, and `RingElem` for the type of the elements of the ring. +We assume that the function + +```julia +ideal(R::Ring, xs::Vector{U}) +``` + +with `U === elem_type(Ring)` and `xs` a list of generators, +is implemented by anyone implementing ideals for AbstractAlgebra rings. +Additionally, the following constructors should be supported: + +```julia +ideal(R::Ring, x::U) +ideal(xs::Vector{U}) = ideal(parent(xs[1]), xs) +ideal(x::U) = ideal(parent(x), x) +*(x::RingElem, R::Ring) +*(R::Ring, x::RingElem) +``` + +An implementation of an Ideal subtype should also provide the +following methods: + +```julia +base_ring(I::NewIdeal) +``` +```julia +gen(I::NewIdeal, k::Int) +``` +```julia +gens(I::NewIdeal) +``` +```julia +ngens(I::NewIdeal) +``` + +## Optional functionality for ideals + +Some functionality is difficult or impossible to implement for all ideals. +If it is provided, additional functionality or performance may become available. Here +is a list of all functions that are considered optional and can't be relied on by +generic functions in the AbstractAlgebra Ideal interface. + +It may be that no algorithm, or no efficient algorithm is known to implement these +functions. As these functions are optional, they do not need to exist. Julia will +already inform the user that the function has not been implemented if it is called but +doesn't exist. + +```julia +in(v::RingElem, I::NewIdeal) +``` +```julia +issubset(I::NewIdeal, J::NewIdeal) +``` +```julia +iszero(I::NewIdeal) +``` +```julia ++(I::T, J::T) where {T <: NewIdeal} +``` +```julia +*(I::T, J::T) where {T <: NewIdeal} +``` +```julia +intersect(I::T, J::T) where {T <: NewIdeal} +``` +```julia +==(I::T, J::T) where {T <: NewIdeal} +``` +```julia +reduce_gens(I::NewIdeal) +``` diff --git a/src/Poly.jl b/src/Poly.jl index 83c122d834..df325cbac4 100644 --- a/src/Poly.jl +++ b/src/Poly.jl @@ -3398,7 +3398,7 @@ is_separable(::PolyRingElem) function is_separable(f::PolyRingElem{<:RingElement}) # Ford, Separable Algebras, 4.6.1 and 8.3.8 - return is_one(ideal(base_ring(f), [f, derivative(f)])) + return gens(Generic.Ideal(parent(f), [f, derivative(f)])) == [1] end function is_separable(f::PolyRingElem{<:FieldElement}) From da32f87c0b63159578e1733e394bfe0d1946e355 Mon Sep 17 00:00:00 2001 From: Mikelis Emils Mikelsons Date: Fri, 27 Jun 2025 12:50:24 +0200 Subject: [PATCH 2/4] Fix typo --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 56635fb3f3..92c1a11f9e 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -90,7 +90,7 @@ makedocs( "field_interface.md", "fraction_interface.md", "module_interface.md", - "ideal_inteface.md", + "ideal_interface.md", "matrix_interface.md", "map_interface.md", "rand.md", From ff4562a679d173c0ad0f374de6a5ea47d85e9ecf Mon Sep 17 00:00:00 2001 From: Mikelis Emils Mikelsons Date: Fri, 27 Jun 2025 13:44:13 +0200 Subject: [PATCH 3/4] Apply suggestions from code review --- docs/src/ideal_interface.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/src/ideal_interface.md b/docs/src/ideal_interface.md index 0a4e4b5b26..21166faefd 100644 --- a/docs/src/ideal_interface.md +++ b/docs/src/ideal_interface.md @@ -39,13 +39,12 @@ All ideal types belong to the abstract type `Ideal{T}` and their parents belong to the abstract type `Set`. This enables one to write generic functions that can accept any AbstractAlgebra ideal type. -New ideal types should come with the following methods: +New ideal types should come with the following type information: ```julia -ideal_type(NewRingType) = NewIdealType -ideal_type(R::NewRing) = ideal_type(typeof(R)) -base_ring_type(I::NewIdealType) = NewRingType -parent_type(I::NewIdealType{T}) = DefaultIdealSet{T} +ideal_type(::Type{NewRing}) = NewIdealType +base_ring_type(::Type{NewIdeal}) = NewRingType +parent_type(::Type{NewIdeal{T}}) = DefaultIdealSet{T} ``` ## Required functionality for ideals @@ -62,7 +61,7 @@ ideal(R::Ring, xs::Vector{U}) with `U === elem_type(Ring)` and `xs` a list of generators, is implemented by anyone implementing ideals for AbstractAlgebra rings. -Additionally, the following constructors should be supported: +Additionally, the following constructors are already implemented generically: ```julia ideal(R::Ring, x::U) From b9b49aebafcc307cf91bb2577871483f71f3ae4e Mon Sep 17 00:00:00 2001 From: Mikelis Emils Mikelsons Date: Fri, 27 Jun 2025 20:41:57 +0200 Subject: [PATCH 4/4] Update Poly.jl --- src/Poly.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Poly.jl b/src/Poly.jl index df325cbac4..83c122d834 100644 --- a/src/Poly.jl +++ b/src/Poly.jl @@ -3398,7 +3398,7 @@ is_separable(::PolyRingElem) function is_separable(f::PolyRingElem{<:RingElement}) # Ford, Separable Algebras, 4.6.1 and 8.3.8 - return gens(Generic.Ideal(parent(f), [f, derivative(f)])) == [1] + return is_one(ideal(base_ring(f), [f, derivative(f)])) end function is_separable(f::PolyRingElem{<:FieldElement})