From a26c456067b5d35fcf65c6665760c61966e03504 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Wed, 31 Jul 2024 16:10:44 +0200 Subject: [PATCH 01/15] Allow free modules over non-commutative rings. --- src/Modules/ModuleTypes.jl | 6 +++--- src/Modules/UngradedModules/FreeMod.jl | 2 ++ src/Modules/UngradedModules/FreeModElem.jl | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Modules/ModuleTypes.jl b/src/Modules/ModuleTypes.jl index b771dfac76a2..ab42a158c370 100644 --- a/src/Modules/ModuleTypes.jl +++ b/src/Modules/ModuleTypes.jl @@ -70,8 +70,8 @@ Moreover, canonical incoming and outgoing morphisms are stored if the correspond option is set in suitable functions. `FreeMod{T}` is a subtype of `AbstractFreeMod{T}`. """ -@attributes mutable struct FreeMod{T <: RingElem} <: AbstractFreeMod{T} - R::Ring +@attributes mutable struct FreeMod{T <: NCRingElem} <: AbstractFreeMod{T} + R::NCRing n::Int S::Vector{Symbol} d::Union{Vector{FinGenAbGroupElem}, Nothing} @@ -91,7 +91,7 @@ option is set in suitable functions. incoming::WeakKeyIdDict{<:ModuleFP, <:Tuple{<:SMat, <:Any}} outgoing::WeakKeyIdDict{<:ModuleFP, <:Tuple{<:SMat, <:Any}} - function FreeMod{T}(n::Int,R::Ring,S::Vector{Symbol}) where T <: RingElem + function FreeMod{T}(n::Int,R::NCRing,S::Vector{Symbol}) where T <: RingElem r = new{elem_type(R)}() r.n = n r.R = R diff --git a/src/Modules/UngradedModules/FreeMod.jl b/src/Modules/UngradedModules/FreeMod.jl index 6531cf49367c..cf2820faccca 100644 --- a/src/Modules/UngradedModules/FreeMod.jl +++ b/src/Modules/UngradedModules/FreeMod.jl @@ -76,6 +76,8 @@ free_module(R::MPolyQuoRing, p::Int, name::VarName = :e; cached::Bool = false) = free_module(R::MPolyLocRing, p::Int, name::VarName = :e; cached::Bool = false) = FreeMod(R, p, name, cached = cached) free_module(R::MPolyQuoLocRing, p::Int, name::VarName = :e; cached::Bool = false) = FreeMod(R, p, name, cached = cached) +#free_module(R::NCRing, p::Int, name::VarName = :e; cached::Bool = false) = FreeMod(R, p, name, cached = cached) + #=XXX this cannot be as it is inherently ambiguous - free_module(R, n) - direct sum of rings, ie. a ring diff --git a/src/Modules/UngradedModules/FreeModElem.jl b/src/Modules/UngradedModules/FreeModElem.jl index e70b3508cfe2..59f787576d8e 100644 --- a/src/Modules/UngradedModules/FreeModElem.jl +++ b/src/Modules/UngradedModules/FreeModElem.jl @@ -277,6 +277,8 @@ end *(a::Integer, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) *(a::QQFieldElem, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) +*(a::T, b::AbstractFreeModElem{T}) where T = parent(b)(base_ring(parent(b))(a)*coordinates(b)) + @doc raw""" zero(F::AbstractFreeMod) From 46ca6bebcccddbca25c56db88d0ff53d2f84beea Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Fri, 2 Aug 2024 01:30:11 +0200 Subject: [PATCH 02/15] Make modules accept non-commutative rings. --- src/Modules/ModuleTypes.jl | 2 +- src/Modules/ModulesGraded.jl | 33 +++++++++++----------- src/Modules/UngradedModules/FreeMod.jl | 6 ++-- src/Modules/UngradedModules/FreeModElem.jl | 4 ++- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/Modules/ModuleTypes.jl b/src/Modules/ModuleTypes.jl index ab42a158c370..2b595b1c5121 100644 --- a/src/Modules/ModuleTypes.jl +++ b/src/Modules/ModuleTypes.jl @@ -91,7 +91,7 @@ option is set in suitable functions. incoming::WeakKeyIdDict{<:ModuleFP, <:Tuple{<:SMat, <:Any}} outgoing::WeakKeyIdDict{<:ModuleFP, <:Tuple{<:SMat, <:Any}} - function FreeMod{T}(n::Int,R::NCRing,S::Vector{Symbol}) where T <: RingElem + function FreeMod{T}(n::Int,R::NCRing,S::Vector{Symbol}) where T <: NCRingElem r = new{elem_type(R)}() r.n = n r.R = R diff --git a/src/Modules/ModulesGraded.jl b/src/Modules/ModulesGraded.jl index 63d186a83de2..eb9147d72b3b 100644 --- a/src/Modules/ModulesGraded.jl +++ b/src/Modules/ModulesGraded.jl @@ -5,14 +5,14 @@ ############################################################################### @doc raw""" - graded_free_module(R::Ring, p::Int, W::Vector{FinGenAbGroupElem}=[grading_group(R)[0] for i in 1:p], name::String="e") + graded_free_module(R::NCRing, p::Int, W::Vector{FinGenAbGroupElem}=[grading_group(R)[0] for i in 1:p], name::String="e") Given a graded ring `R` with grading group `G`, say, and given a vector `W` with `p` elements of `G`, create the free module $R^p$ equipped with its basis of standard unit vectors, and assign weights to these vectors according to the entries of `W`. Return the resulting graded free module. - graded_free_module(R::Ring, W::Vector{FinGenAbGroupElem}, name::String="e") + graded_free_module(R::NCRing, W::Vector{FinGenAbGroupElem}, name::String="e") As above, with `p = length(W)`. @@ -36,7 +36,7 @@ julia> graded_free_module(R, [G[1], 2*G[1]]) Graded free module R^1([-1]) + R^1([-2]) of rank 2 over R ``` """ -function graded_free_module(R::Ring, p::Int, W::Vector{FinGenAbGroupElem}=[grading_group(R)[0] for i in 1:p], name::String="e") +function graded_free_module(R::NCRing, p::Int, W::Vector{FinGenAbGroupElem}=[grading_group(R)[0] for i in 1:p], name::String="e") @assert length(W) == p @assert is_graded(R) all(x -> parent(x) == grading_group(R), W) || error("entries of W must be elements of the grading group of the base ring") @@ -45,7 +45,7 @@ function graded_free_module(R::Ring, p::Int, W::Vector{FinGenAbGroupElem}=[gradi return M end -function graded_free_module(R::Ring, p::Int, W::Vector{Any}, name::String="e") +function graded_free_module(R::NCRing, p::Int, W::Vector{Any}, name::String="e") @assert length(W) == p @assert is_graded(R) p == 0 || error("W should be either an empty array or a Vector{FinGenAbGroupElem}") @@ -53,12 +53,12 @@ function graded_free_module(R::Ring, p::Int, W::Vector{Any}, name::String="e") return graded_free_module(R, p, W, name) end -function graded_free_module(R::Ring, W::Vector{FinGenAbGroupElem}, name::String="e") +function graded_free_module(R::NCRing, W::Vector{FinGenAbGroupElem}, name::String="e") p = length(W) return graded_free_module(R, p, W, name) end -function graded_free_module(R::Ring, W::Vector{Any}, name::String="e") +function graded_free_module(R::NCRing, W::Vector{Any}, name::String="e") p = length(W) @assert is_graded(R) p == 0 || error("W should be either an empty array or a Vector{FinGenAbGroupElem}") @@ -67,7 +67,7 @@ function graded_free_module(R::Ring, W::Vector{Any}, name::String="e") end @doc raw""" - graded_free_module(R::Ring, W::Vector{<:Vector{<:IntegerUnion}}, name::String="e") + graded_free_module(R::NCRing, W::Vector{<:Vector{<:IntegerUnion}}, name::String="e") Given a graded ring `R` with grading group $G = \mathbb Z^m$, and given a vector `W` of integer vectors of the same size `p`, say, create the free @@ -75,11 +75,11 @@ module $R^p$ equipped with its basis of standard unit vectors, and assign weight vectors according to the entries of `W`, converted to elements of `G`. Return the resulting graded free module. - graded_free_module(R::Ring, W::Union{ZZMatrix, Matrix{<:IntegerUnion}}, name::String="e") + graded_free_module(R::NCRing, W::Union{ZZMatrix, Matrix{<:IntegerUnion}}, name::String="e") As above, converting the columns of `W`. - graded_free_module(R::Ring, W::Vector{<:IntegerUnion}, name::String="e") + graded_free_module(R::NCRing, W::Vector{<:IntegerUnion}, name::String="e") Given a graded ring `R` with grading group $G = \mathbb Z$, and given a vector `W` of integers, set `p = length(W)`, create the free module $R^p$ @@ -113,7 +113,7 @@ julia> FF == FFF true ``` """ -function graded_free_module(R::Ring, W::Vector{<:Vector{<:IntegerUnion}}, name::String="e") +function graded_free_module(R::NCRing, W::Vector{<:Vector{<:IntegerUnion}}, name::String="e") @assert is_zm_graded(R) n = length(W[1]) @assert all(x->length(x) == n, W) @@ -122,14 +122,14 @@ function graded_free_module(R::Ring, W::Vector{<:Vector{<:IntegerUnion}}, name:: return graded_free_module(R, length(W), d, name) end -function graded_free_module(R::Ring, W::Union{ZZMatrix, Matrix{<:IntegerUnion}}, name::String="e") +function graded_free_module(R::NCRing, W::Union{ZZMatrix, Matrix{<:IntegerUnion}}, name::String="e") @assert is_zm_graded(R) A = grading_group(R) d = [A(W[:, i]) for i = 1:size(W, 2)] return graded_free_module(R, size(W, 2), d, name) end -function graded_free_module(R::Ring, W::Vector{<:IntegerUnion}, name::String="e") +function graded_free_module(R::NCRing, W::Vector{<:IntegerUnion}, name::String="e") @assert is_graded(R) A = grading_group(R) d = [W[i] * A[1] for i in 1:length(W)] @@ -543,7 +543,8 @@ end const AnyGradedRingElem = Union{<:MPolyDecRingElem, <:MPolyQuoRingElem{<:MPolyDecRingElem}, <:MPolyLocRingElem{<:Ring, <:RingElem, <:MPolyDecRing}, - <:MPolyQuoLocRingElem{<:Ring, <:RingElem, <:MPolyDecRing} + <:MPolyQuoLocRingElem{<:Ring, <:RingElem, <:MPolyDecRing}, + <:NCRingElement } @doc raw""" @@ -652,7 +653,7 @@ function graded_map(A::MatElem) return graded_map(Fcdm, A) end -function graded_map(F::FreeMod{T}, A::MatrixElem{T}; check::Bool=true) where {T <: RingElement} +function graded_map(F::FreeMod{T}, A::MatrixElem{T}; check::Bool=true) where {T <: NCRingElement} R = base_ring(F) G = grading_group(R) source_degrees = Vector{eltype(G)}() @@ -669,7 +670,7 @@ function graded_map(F::FreeMod{T}, A::MatrixElem{T}; check::Bool=true) where {T return phi end -function graded_map(F::FreeMod{T}, V::Vector{<:AbstractFreeModElem{T}}; check::Bool=true) where {T <: RingElement} +function graded_map(F::FreeMod{T}, V::Vector{<:AbstractFreeModElem{T}}; check::Bool=true) where {T <: NCRingElement} R = base_ring(F) G = grading_group(R) nrows = length(V) @@ -697,7 +698,7 @@ function graded_map(F::FreeMod{T}, V::Vector{<:AbstractFreeModElem{T}}; check::B end -function graded_map(F::SubquoModule{T}, V::Vector{<:ModuleFPElem{T}}; check::Bool=true) where {T <: RingElement} +function graded_map(F::SubquoModule{T}, V::Vector{<:ModuleFPElem{T}}; check::Bool=true) where {T <: NCRingElement} R = base_ring(F) G = grading_group(R) nrows = length(V) diff --git a/src/Modules/UngradedModules/FreeMod.jl b/src/Modules/UngradedModules/FreeMod.jl index cf2820faccca..f9b21c8a17ce 100644 --- a/src/Modules/UngradedModules/FreeMod.jl +++ b/src/Modules/UngradedModules/FreeMod.jl @@ -10,15 +10,15 @@ Additionally one can provide names for the generators. If one does not provide names for the generators, the standard names e_i are used for the standard unit vectors. """ -function FreeMod(R::Ring, n::Int, name::VarName = :e; cached::Bool = false) # TODO cached? +function FreeMod(R::NCRing, n::Int, name::VarName = :e; cached::Bool = false) # TODO cached? return FreeMod{elem_type(R)}(n, R, [Symbol("$name[$i]") for i=1:n]) end -function FreeMod(R::Ring, names::Vector{String}; cached::Bool=false) +function FreeMod(R::NCRing, names::Vector{String}; cached::Bool=false) return FreeMod{elem_type(R)}(length(names), R, Symbol.(names)) end -function FreeMod(R::Ring, names::Vector{Symbol}; cached::Bool=false) +function FreeMod(R::NCRing, names::Vector{Symbol}; cached::Bool=false) return FreeMod{elem_type(R)}(length(names), R, names) end diff --git a/src/Modules/UngradedModules/FreeModElem.jl b/src/Modules/UngradedModules/FreeModElem.jl index 59f787576d8e..43c9a42099b6 100644 --- a/src/Modules/UngradedModules/FreeModElem.jl +++ b/src/Modules/UngradedModules/FreeModElem.jl @@ -277,7 +277,9 @@ end *(a::Integer, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) *(a::QQFieldElem, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) -*(a::T, b::AbstractFreeModElem{T}) where T = parent(b)(base_ring(parent(b))(a)*coordinates(b)) +function *(a::T, b::AbstractFreeModElem{T}) where T + return parent(b)(base_ring(parent(b))(a)*coordinates(b)) +end @doc raw""" zero(F::AbstractFreeMod) From c7a5f4c39c104ecd8e3509c771f20d36400b19f2 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Fri, 2 Aug 2024 22:01:45 +0200 Subject: [PATCH 03/15] Allow scalar multiplication with non-commutative ring elements. --- src/Modules/UngradedModules/SubquoModuleElem.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/UngradedModules/SubquoModuleElem.jl b/src/Modules/UngradedModules/SubquoModuleElem.jl index 493f940164fd..76ef28f697de 100644 --- a/src/Modules/UngradedModules/SubquoModuleElem.jl +++ b/src/Modules/UngradedModules/SubquoModuleElem.jl @@ -409,7 +409,7 @@ function *(a::MPolyRingElem, b::SubquoModuleElem) return SubquoModuleElem(a*repres(b), b.parent) end -function *(a::RingElem, b::SubquoModuleElem) +function *(a::NCRingElem, b::SubquoModuleElem) if parent(a) !== base_ring(parent(b)) return base_ring(parent(b))(a)*b # this will throw if conversion is not possible end From 4bd5b9e1b40b2bb280caf6ba0e9ab4be2c2cda00 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Mon, 5 Aug 2024 08:00:27 +0200 Subject: [PATCH 04/15] Allow scalar multiplication for non-comutattive rings. --- src/Modules/UngradedModules/SubQuoHom.jl | 4 ++-- src/Modules/UngradedModules/SubquoModule.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Modules/UngradedModules/SubQuoHom.jl b/src/Modules/UngradedModules/SubQuoHom.jl index 948c369009f2..778fedc1f6dd 100644 --- a/src/Modules/UngradedModules/SubQuoHom.jl +++ b/src/Modules/UngradedModules/SubQuoHom.jl @@ -964,12 +964,12 @@ function +(h::ModuleFPHom{D, C, Nothing}, g::ModuleFPHom{D, C, Nothing}) where { return hom(domain(h), codomain(h), elem_type(codomain(h))[h(x) + g(x) for x in gens(domain(h))], check=false) end -function *(a::RingElem, g::ModuleFPHom{D, C, Nothing}) where {D, C} +function *(a::NCRingElem, g::ModuleFPHom{D, C, Nothing}) where {D, C} @assert base_ring(codomain(g)) === parent(a) return hom(domain(g), codomain(g), elem_type(codomain(g))[a*g(x) for x in gens(domain(g))], check=false) end -function *(a::RingElem, g::ModuleFPHom{D, C, T}) where {D, C, T} +function *(a::NCRingElem, g::ModuleFPHom{D, C, T}) where {D, C, T} @assert base_ring(codomain(g)) === parent(a) return hom(domain(g), codomain(g), elem_type(codomain(g))[a*g(x) for x in gens(domain(g))], base_ring_map(g), check=false) end diff --git a/src/Modules/UngradedModules/SubquoModule.jl b/src/Modules/UngradedModules/SubquoModule.jl index 8c66a77c44a6..6075aa7f1bfb 100644 --- a/src/Modules/UngradedModules/SubquoModule.jl +++ b/src/Modules/UngradedModules/SubquoModule.jl @@ -157,7 +157,7 @@ end Construct the subquotient with ambient free module `F`, generators `g` and relations `q`. """ -function SubquoModule(F::FreeMod{T}, g::Vector{FreeModElem{T}}, q::Vector{FreeModElem{T}}) where {T<:RingElem} +function SubquoModule(F::FreeMod{T}, g::Vector{FreeModElem{T}}, q::Vector{FreeModElem{T}}) where {T<:NCRingElem} return SubquoModule(SubModuleOfFreeModule(F, g), SubModuleOfFreeModule(F, q)) end From 04ed6fb9f65ea8ba1f1aea3a4dc4d58ab247d360 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Mon, 5 Aug 2024 14:17:57 +0200 Subject: [PATCH 05/15] Remove NCRingElem from the list of graded elements. --- src/Modules/ModulesGraded.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Modules/ModulesGraded.jl b/src/Modules/ModulesGraded.jl index eb9147d72b3b..fa4bb9a9e844 100644 --- a/src/Modules/ModulesGraded.jl +++ b/src/Modules/ModulesGraded.jl @@ -543,8 +543,7 @@ end const AnyGradedRingElem = Union{<:MPolyDecRingElem, <:MPolyQuoRingElem{<:MPolyDecRingElem}, <:MPolyLocRingElem{<:Ring, <:RingElem, <:MPolyDecRing}, - <:MPolyQuoLocRingElem{<:Ring, <:RingElem, <:MPolyDecRing}, - <:NCRingElement + <:MPolyQuoLocRingElem{<:Ring, <:RingElem, <:MPolyDecRing} } @doc raw""" From 0e806e1abeb4be979517f6a511fc4ddac15e472d Mon Sep 17 00:00:00 2001 From: Matthias Zach <85350711+HechtiDerLachs@users.noreply.github.com> Date: Thu, 8 Aug 2024 12:17:38 +0200 Subject: [PATCH 06/15] Update src/Modules/UngradedModules/FreeModElem.jl --- src/Modules/UngradedModules/FreeModElem.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Modules/UngradedModules/FreeModElem.jl b/src/Modules/UngradedModules/FreeModElem.jl index 43c9a42099b6..e0bbc4ee8f8a 100644 --- a/src/Modules/UngradedModules/FreeModElem.jl +++ b/src/Modules/UngradedModules/FreeModElem.jl @@ -277,7 +277,8 @@ end *(a::Integer, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) *(a::QQFieldElem, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) -function *(a::T, b::AbstractFreeModElem{T}) where T +function *(a::T, b::AbstractFreeModElem{T}) where {T <: NCRingElem} + parent(a) === base_ring(parent(b)) && return parent(b)(a*coordinates(b)) return parent(b)(base_ring(parent(b))(a)*coordinates(b)) end From 918b8eb2a55457f0de2d1451144454dd0b74377a Mon Sep 17 00:00:00 2001 From: Lax202 Date: Mon, 1 Jul 2024 13:49:55 +0200 Subject: [PATCH 07/15] priliminary tests --- test/Modules/PBWModules.jl | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 test/Modules/PBWModules.jl diff --git a/test/Modules/PBWModules.jl b/test/Modules/PBWModules.jl new file mode 100644 index 000000000000..a613e24f765c --- /dev/null +++ b/test/Modules/PBWModules.jl @@ -0,0 +1,61 @@ +@testset "modules over PBWAlgQuo" begin + #Free Module tests + E,x = exterior_algebra(QQ, 3) + M = free_module(E, 3) + @test ngens(M) == 3 + @test gens(M)[1] in M + @test parent(M[1]) == M + v = [x[1], x[1] + x[2], x[1]*x[2]] + @test v == Vector(M(v)) + + #SubModuleOfFreeModule tests + N = Oscar.SubModuleOfFreeModule(M, gens(M)[1:2]) + @test gens(N) == gens(M)[1:2] + @test N[1] in M + #fails! #NEEDS A 'DEFAULT ORDERING' on the PBWAlgQuo ie on E + #@test M(v) in N + + #FreeModuleHom tests + W = free_module(E,2) + G = hom(W,M, gens(M)[1:2]) + @test ngens(image(G)[1]) == 2 + + #SubQuoModule tests + Q1 = SubquoModule(M, [x[1]*M[1]]) + Q2 = SubquoModule(M, [x[2]*M[1]]) + #fail! #NEEDS A 'DEFAULT ORDERING' on the PBWAlgQuo ie on E + #@test !is_canonically_isomorphic(Q2,Q1) + #simplify(Q[1]) +end + +@testset "modules over PBWAlgRing" begin + R, (x, y, z) = QQ["x", "y", "z"] + L = [x*y, x*z, y*z + 1] + REL = strictly_upper_triangular_matrix(L) + A, (x, y, z) = pbw_algebra(R, REL, deglex(gens(R))) + M = free_module(A, 3) + @test ngens(M) == 3 + @test gens(M)[1] in M + @test parent(M[1]) == M + v = [x, x+y, x*y] + @test v == Vector(M(v)) + + #SubModuleOfFreeModule tests + N = Oscar.SubModuleOfFreeModule(M, gens(M)[1:2]) + @test gens(N) == gens(M)[1:2] + @test N[1] in M + #fails! #NEEDS A 'DEFAULT ORDERING' on the PBWAlgQuo ie on E + #@test M(v) in N + + #FreeModuleHom tests + W = free_module(A,2) + G = hom(W,M, gens(M)[1:2]) + @test ngens(image(G)[1]) == 2 + + #SubQuoModule tests + Q1 = SubquoModule(M, [x*M[1]]) + Q2 = SubquoModule(M, [y*M[1]]) + #fail! #NEEDS A 'DEFAULT ORDERING' on the PBWAlgQuo ie on E + #@test !is_canonically_isomorphic(Q2,Q1) + #simplify(Q[1]) +end \ No newline at end of file From 0ccc13fd93f23e1ec63aba4b210543fc1eea361d Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Thu, 8 Aug 2024 12:37:56 +0200 Subject: [PATCH 08/15] Remove ambiguity introducing method. --- src/Modules/UngradedModules/FreeModElem.jl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Modules/UngradedModules/FreeModElem.jl b/src/Modules/UngradedModules/FreeModElem.jl index e0bbc4ee8f8a..90c23b711f7a 100644 --- a/src/Modules/UngradedModules/FreeModElem.jl +++ b/src/Modules/UngradedModules/FreeModElem.jl @@ -266,13 +266,6 @@ function *(a::MPolyRingElem, b::AbstractFreeModElem) return parent(b)(a*coordinates(b)) end -function *(a::RingElem, b::AbstractFreeModElem) - if parent(a) !== base_ring(parent(b)) - return base_ring(parent(b))(a)*b # this will throw if conversion is not possible - end - return parent(b)(a*coordinates(b)) -end - *(a::Int, b::AbstractFreeModElem) = parent(b)(a*coordinates(b)) *(a::Integer, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) *(a::QQFieldElem, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) From 9d9380e77852c68b92424637c0529119d8dfd693 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Thu, 8 Aug 2024 12:44:51 +0200 Subject: [PATCH 09/15] Clean up methods for scalar multiplication. --- src/Modules/UngradedModules/FreeModElem.jl | 24 ++++++++-------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/Modules/UngradedModules/FreeModElem.jl b/src/Modules/UngradedModules/FreeModElem.jl index 90c23b711f7a..6d681ecff290 100644 --- a/src/Modules/UngradedModules/FreeModElem.jl +++ b/src/Modules/UngradedModules/FreeModElem.jl @@ -254,27 +254,21 @@ function Base.deepcopy_internal(a::AbstractFreeModElem, dict::IdDict) end # scalar multiplication with polynomials, integers -function *(a::MPolyDecRingElem, b::AbstractFreeModElem) - @req parent(a) === base_ring(parent(b)) "elements not compatible" - return parent(b)(a*coordinates(b)) -end - -function *(a::MPolyRingElem, b::AbstractFreeModElem) - if parent(a) !== base_ring(parent(b)) - return base_ring(parent(b))(a)*b # this will throw if conversion is not possible - end - return parent(b)(a*coordinates(b)) -end - -*(a::Int, b::AbstractFreeModElem) = parent(b)(a*coordinates(b)) -*(a::Integer, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) -*(a::QQFieldElem, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) +*(a::Any, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) function *(a::T, b::AbstractFreeModElem{T}) where {T <: NCRingElem} parent(a) === base_ring(parent(b)) && return parent(b)(a*coordinates(b)) return parent(b)(base_ring(parent(b))(a)*coordinates(b)) end +function *(b::AbstractFreeModElem{T}, a::T) where {T <: NCRingElem} + error("all modules are left-modules by default") +end + +function *(b::AbstractFreeModElem{T}, a::Any) where {T <: RingElem} + error("scalar multiplication from the right is not defined; use left-multiplication instead") +end + @doc raw""" zero(F::AbstractFreeMod) From b0405fb672b709bec6161b8cfdaa7a3e16fdb317 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Thu, 8 Aug 2024 13:04:53 +0200 Subject: [PATCH 10/15] Fix tests. --- test/Modules/PBWModules.jl | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/Modules/PBWModules.jl b/test/Modules/PBWModules.jl index a613e24f765c..1045b5b3793a 100644 --- a/test/Modules/PBWModules.jl +++ b/test/Modules/PBWModules.jl @@ -1,12 +1,11 @@ @testset "modules over PBWAlgQuo" begin #Free Module tests E,x = exterior_algebra(QQ, 3) - M = free_module(E, 3) + M = FreeMod(E, 3) @test ngens(M) == 3 - @test gens(M)[1] in M - @test parent(M[1]) == M - v = [x[1], x[1] + x[2], x[1]*x[2]] - @test v == Vector(M(v)) + @test parent(M[1]) === M + v = [x[1], x[1] + x[2], 5*x[1]*x[2]] + @test M(2*v) == 2*M(v) #SubModuleOfFreeModule tests N = Oscar.SubModuleOfFreeModule(M, gens(M)[1:2]) @@ -16,7 +15,7 @@ #@test M(v) in N #FreeModuleHom tests - W = free_module(E,2) + W = FreeMod(E,2) G = hom(W,M, gens(M)[1:2]) @test ngens(image(G)[1]) == 2 @@ -33,7 +32,7 @@ end L = [x*y, x*z, y*z + 1] REL = strictly_upper_triangular_matrix(L) A, (x, y, z) = pbw_algebra(R, REL, deglex(gens(R))) - M = free_module(A, 3) + M = FreeMod(A, 3) @test ngens(M) == 3 @test gens(M)[1] in M @test parent(M[1]) == M @@ -48,7 +47,7 @@ end #@test M(v) in N #FreeModuleHom tests - W = free_module(A,2) + W = FreeMod(A,2) G = hom(W,M, gens(M)[1:2]) @test ngens(image(G)[1]) == 2 @@ -58,4 +57,4 @@ end #fail! #NEEDS A 'DEFAULT ORDERING' on the PBWAlgQuo ie on E #@test !is_canonically_isomorphic(Q2,Q1) #simplify(Q[1]) -end \ No newline at end of file +end From 6bde5502b1329702846e36b06079977a29910879 Mon Sep 17 00:00:00 2001 From: Matthias Zach <85350711+HechtiDerLachs@users.noreply.github.com> Date: Fri, 13 Sep 2024 14:45:46 +0200 Subject: [PATCH 11/15] Apply conclusions from discussion. --- src/Modules/UngradedModules/FreeModElem.jl | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Modules/UngradedModules/FreeModElem.jl b/src/Modules/UngradedModules/FreeModElem.jl index 6d681ecff290..abe37b154462 100644 --- a/src/Modules/UngradedModules/FreeModElem.jl +++ b/src/Modules/UngradedModules/FreeModElem.jl @@ -257,18 +257,37 @@ end *(a::Any, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) function *(a::T, b::AbstractFreeModElem{T}) where {T <: NCRingElem} + @assert is_left(parent(b)) "left multiplication is not defined for non-left module $(parent(b))" parent(a) === base_ring(parent(b)) && return parent(b)(a*coordinates(b)) return parent(b)(base_ring(parent(b))(a)*coordinates(b)) end function *(b::AbstractFreeModElem{T}, a::T) where {T <: NCRingElem} - error("all modules are left-modules by default") + @assert is_right(parent(b)) "right multiplication not defined for non-right module $(parent(b))" + error("right multiplication is not supported at the moment") end function *(b::AbstractFreeModElem{T}, a::Any) where {T <: RingElem} - error("scalar multiplication from the right is not defined; use left-multiplication instead") + error("scalar multiplication from the right is not yet supported") end +# Methods to determine whether a module is a left-, right-, or bi-module. +# We plan to have flags set for this. But for the moment the generic code only supports left-multiplication, +# so we can decide this from the type alone. How we do it in the long run is not yet decided, but in either case +# we want to use these functions to decide as they are already there for ideals. +is_left(M::ModuleFP) = is_left_module(typeof(M)) +is_left(::Type{T}) where {RET<:RingElem, T<:ModuleFP{T}} = true +is_left(::Type{T}) where {RET<:NCRingElem, T<:ModuleFP{T}} = true # Left multiplication is generically supported + +is_right(M::ModuleFP) = is_right_module(typeof(M)) +is_right(::Type{T}) where {RET<:RingElem, T<:ModuleFP{T}} = true +is_right(::Type{T}) where {RET<:NCRingElem, T<:ModuleFP{T}} = false # Right multiplication is not supported by the generic code at the moment, but we plan to do so eventually. + +is_two_sided(M::ModuleFP) = is_right_module(typeof(M)) +is_two_sided(::Type{T}) where {RET<:RingElem, T<:ModuleFP{T}} = true +is_two_sided(::Type{T}) where {RET<:NCRingElem, T<:ModuleFP{T}} = false # see above + + @doc raw""" zero(F::AbstractFreeMod) From 140dcdcfb9f5f17da70b8d0da6f40820a96532c0 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Fri, 13 Sep 2024 15:09:44 +0200 Subject: [PATCH 12/15] Apply the conclusions from the discussion. --- src/Modules/ModuleTypes.jl | 13 ++++++--- src/Modules/ModulesGraded.jl | 30 ++++++++++----------- src/Modules/UngradedModules/FreeMod.jl | 6 ++--- src/Modules/UngradedModules/FreeModElem.jl | 18 ++++++------- src/Modules/UngradedModules/SubQuoHom.jl | 4 +-- src/Modules/UngradedModules/SubquoModule.jl | 2 +- 6 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/Modules/ModuleTypes.jl b/src/Modules/ModuleTypes.jl index 2b595b1c5121..07fdf16c7374 100644 --- a/src/Modules/ModuleTypes.jl +++ b/src/Modules/ModuleTypes.jl @@ -1,12 +1,19 @@ import AbstractAlgebra.WeakKeyIdDict +# The following type union gathers all types for elements for which +# we expect the `ModuleFP` framework to be functional and/or working. +# It can gradually be extended, but should not be considered to be +# visible or accessible to the outside world. +const AdmissibleModuleFPRingElem = Union{RingElem, PBWAlgQuoElem, PBWAlgElem} +const AdmissibleModuleFPRing = Union{Ring, PBWAlgQuo, PBWAlgRing} + @doc raw""" ModuleFP{T} The abstract supertype of all finitely presented modules. The type variable `T` refers to the type of the elements of the base ring. """ -abstract type ModuleFP{T} <: AbstractAlgebra.Module{T} end +abstract type ModuleFP{T <: AdmissibleModuleFPRingElem} <: AbstractAlgebra.Module{T} end @doc raw""" AbstractFreeMod{T} <: ModuleFP{T} @@ -70,7 +77,7 @@ Moreover, canonical incoming and outgoing morphisms are stored if the correspond option is set in suitable functions. `FreeMod{T}` is a subtype of `AbstractFreeMod{T}`. """ -@attributes mutable struct FreeMod{T <: NCRingElem} <: AbstractFreeMod{T} +@attributes mutable struct FreeMod{T} <: AbstractFreeMod{T} R::NCRing n::Int S::Vector{Symbol} @@ -91,7 +98,7 @@ option is set in suitable functions. incoming::WeakKeyIdDict{<:ModuleFP, <:Tuple{<:SMat, <:Any}} outgoing::WeakKeyIdDict{<:ModuleFP, <:Tuple{<:SMat, <:Any}} - function FreeMod{T}(n::Int,R::NCRing,S::Vector{Symbol}) where T <: NCRingElem + function FreeMod{T}(n::Int, R::AdmissibleModuleFPRing, S::Vector{Symbol}) where T <: AdmissibleModuleFPRingElem r = new{elem_type(R)}() r.n = n r.R = R diff --git a/src/Modules/ModulesGraded.jl b/src/Modules/ModulesGraded.jl index fa4bb9a9e844..2e9458312b0b 100644 --- a/src/Modules/ModulesGraded.jl +++ b/src/Modules/ModulesGraded.jl @@ -5,14 +5,14 @@ ############################################################################### @doc raw""" - graded_free_module(R::NCRing, p::Int, W::Vector{FinGenAbGroupElem}=[grading_group(R)[0] for i in 1:p], name::String="e") + graded_free_module(R::AdmissibleModuleFPRing, p::Int, W::Vector{FinGenAbGroupElem}=[grading_group(R)[0] for i in 1:p], name::String="e") Given a graded ring `R` with grading group `G`, say, and given a vector `W` with `p` elements of `G`, create the free module $R^p$ equipped with its basis of standard unit vectors, and assign weights to these vectors according to the entries of `W`. Return the resulting graded free module. - graded_free_module(R::NCRing, W::Vector{FinGenAbGroupElem}, name::String="e") + graded_free_module(R::AdmissibleModuleFPRing, W::Vector{FinGenAbGroupElem}, name::String="e") As above, with `p = length(W)`. @@ -36,7 +36,7 @@ julia> graded_free_module(R, [G[1], 2*G[1]]) Graded free module R^1([-1]) + R^1([-2]) of rank 2 over R ``` """ -function graded_free_module(R::NCRing, p::Int, W::Vector{FinGenAbGroupElem}=[grading_group(R)[0] for i in 1:p], name::String="e") +function graded_free_module(R::AdmissibleModuleFPRing, p::Int, W::Vector{FinGenAbGroupElem}=[grading_group(R)[0] for i in 1:p], name::String="e") @assert length(W) == p @assert is_graded(R) all(x -> parent(x) == grading_group(R), W) || error("entries of W must be elements of the grading group of the base ring") @@ -45,7 +45,7 @@ function graded_free_module(R::NCRing, p::Int, W::Vector{FinGenAbGroupElem}=[gra return M end -function graded_free_module(R::NCRing, p::Int, W::Vector{Any}, name::String="e") +function graded_free_module(R::AdmissibleModuleFPRing, p::Int, W::Vector{Any}, name::String="e") @assert length(W) == p @assert is_graded(R) p == 0 || error("W should be either an empty array or a Vector{FinGenAbGroupElem}") @@ -53,12 +53,12 @@ function graded_free_module(R::NCRing, p::Int, W::Vector{Any}, name::String="e") return graded_free_module(R, p, W, name) end -function graded_free_module(R::NCRing, W::Vector{FinGenAbGroupElem}, name::String="e") +function graded_free_module(R::AdmissibleModuleFPRing, W::Vector{FinGenAbGroupElem}, name::String="e") p = length(W) return graded_free_module(R, p, W, name) end -function graded_free_module(R::NCRing, W::Vector{Any}, name::String="e") +function graded_free_module(R::AdmissibleModuleFPRing, W::Vector{Any}, name::String="e") p = length(W) @assert is_graded(R) p == 0 || error("W should be either an empty array or a Vector{FinGenAbGroupElem}") @@ -67,7 +67,7 @@ function graded_free_module(R::NCRing, W::Vector{Any}, name::String="e") end @doc raw""" - graded_free_module(R::NCRing, W::Vector{<:Vector{<:IntegerUnion}}, name::String="e") + graded_free_module(R::AdmissibleModuleFPRing, W::Vector{<:Vector{<:IntegerUnion}}, name::String="e") Given a graded ring `R` with grading group $G = \mathbb Z^m$, and given a vector `W` of integer vectors of the same size `p`, say, create the free @@ -75,11 +75,11 @@ module $R^p$ equipped with its basis of standard unit vectors, and assign weight vectors according to the entries of `W`, converted to elements of `G`. Return the resulting graded free module. - graded_free_module(R::NCRing, W::Union{ZZMatrix, Matrix{<:IntegerUnion}}, name::String="e") + graded_free_module(R::AdmissibleModuleFPRing, W::Union{ZZMatrix, Matrix{<:IntegerUnion}}, name::String="e") As above, converting the columns of `W`. - graded_free_module(R::NCRing, W::Vector{<:IntegerUnion}, name::String="e") + graded_free_module(R::AdmissibleModuleFPRing, W::Vector{<:IntegerUnion}, name::String="e") Given a graded ring `R` with grading group $G = \mathbb Z$, and given a vector `W` of integers, set `p = length(W)`, create the free module $R^p$ @@ -113,7 +113,7 @@ julia> FF == FFF true ``` """ -function graded_free_module(R::NCRing, W::Vector{<:Vector{<:IntegerUnion}}, name::String="e") +function graded_free_module(R::AdmissibleModuleFPRing, W::Vector{<:Vector{<:IntegerUnion}}, name::String="e") @assert is_zm_graded(R) n = length(W[1]) @assert all(x->length(x) == n, W) @@ -122,14 +122,14 @@ function graded_free_module(R::NCRing, W::Vector{<:Vector{<:IntegerUnion}}, name return graded_free_module(R, length(W), d, name) end -function graded_free_module(R::NCRing, W::Union{ZZMatrix, Matrix{<:IntegerUnion}}, name::String="e") +function graded_free_module(R::AdmissibleModuleFPRing, W::Union{ZZMatrix, Matrix{<:IntegerUnion}}, name::String="e") @assert is_zm_graded(R) A = grading_group(R) d = [A(W[:, i]) for i = 1:size(W, 2)] return graded_free_module(R, size(W, 2), d, name) end -function graded_free_module(R::NCRing, W::Vector{<:IntegerUnion}, name::String="e") +function graded_free_module(R::AdmissibleModuleFPRing, W::Vector{<:IntegerUnion}, name::String="e") @assert is_graded(R) A = grading_group(R) d = [W[i] * A[1] for i in 1:length(W)] @@ -652,7 +652,7 @@ function graded_map(A::MatElem) return graded_map(Fcdm, A) end -function graded_map(F::FreeMod{T}, A::MatrixElem{T}; check::Bool=true) where {T <: NCRingElement} +function graded_map(F::FreeMod{T}, A::MatrixElem{T}; check::Bool=true) where {T <: AdmissibleModuleFPRingElem} R = base_ring(F) G = grading_group(R) source_degrees = Vector{eltype(G)}() @@ -669,7 +669,7 @@ function graded_map(F::FreeMod{T}, A::MatrixElem{T}; check::Bool=true) where {T return phi end -function graded_map(F::FreeMod{T}, V::Vector{<:AbstractFreeModElem{T}}; check::Bool=true) where {T <: NCRingElement} +function graded_map(F::FreeMod{T}, V::Vector{<:AbstractFreeModElem{T}}; check::Bool=true) where {T <: AdmissibleModuleFPRingElem} R = base_ring(F) G = grading_group(R) nrows = length(V) @@ -697,7 +697,7 @@ function graded_map(F::FreeMod{T}, V::Vector{<:AbstractFreeModElem{T}}; check::B end -function graded_map(F::SubquoModule{T}, V::Vector{<:ModuleFPElem{T}}; check::Bool=true) where {T <: NCRingElement} +function graded_map(F::SubquoModule{T}, V::Vector{<:ModuleFPElem{T}}; check::Bool=true) where {T <: AdmissibleModuleFPRingElem} R = base_ring(F) G = grading_group(R) nrows = length(V) diff --git a/src/Modules/UngradedModules/FreeMod.jl b/src/Modules/UngradedModules/FreeMod.jl index f9b21c8a17ce..a204a0385b60 100644 --- a/src/Modules/UngradedModules/FreeMod.jl +++ b/src/Modules/UngradedModules/FreeMod.jl @@ -10,15 +10,15 @@ Additionally one can provide names for the generators. If one does not provide names for the generators, the standard names e_i are used for the standard unit vectors. """ -function FreeMod(R::NCRing, n::Int, name::VarName = :e; cached::Bool = false) # TODO cached? +function FreeMod(R::AdmissibleModuleFPRing, n::Int, name::VarName = :e; cached::Bool = false) # TODO cached? return FreeMod{elem_type(R)}(n, R, [Symbol("$name[$i]") for i=1:n]) end -function FreeMod(R::NCRing, names::Vector{String}; cached::Bool=false) +function FreeMod(R::AdmissibleModuleFPRing, names::Vector{String}; cached::Bool=false) return FreeMod{elem_type(R)}(length(names), R, Symbol.(names)) end -function FreeMod(R::NCRing, names::Vector{Symbol}; cached::Bool=false) +function FreeMod(R::AdmissibleModuleFPRing, names::Vector{Symbol}; cached::Bool=false) return FreeMod{elem_type(R)}(length(names), R, names) end diff --git a/src/Modules/UngradedModules/FreeModElem.jl b/src/Modules/UngradedModules/FreeModElem.jl index abe37b154462..6a197b1b64fc 100644 --- a/src/Modules/UngradedModules/FreeModElem.jl +++ b/src/Modules/UngradedModules/FreeModElem.jl @@ -256,13 +256,13 @@ end # scalar multiplication with polynomials, integers *(a::Any, b::AbstractFreeModElem) = parent(b)(base_ring(parent(b))(a)*coordinates(b)) -function *(a::T, b::AbstractFreeModElem{T}) where {T <: NCRingElem} +function *(a::T, b::AbstractFreeModElem{T}) where {T <: AdmissibleModuleFPRingElem} @assert is_left(parent(b)) "left multiplication is not defined for non-left module $(parent(b))" parent(a) === base_ring(parent(b)) && return parent(b)(a*coordinates(b)) return parent(b)(base_ring(parent(b))(a)*coordinates(b)) end -function *(b::AbstractFreeModElem{T}, a::T) where {T <: NCRingElem} +function *(b::AbstractFreeModElem{T}, a::T) where {T <: AdmissibleModuleFPRingElem} @assert is_right(parent(b)) "right multiplication not defined for non-right module $(parent(b))" error("right multiplication is not supported at the moment") end @@ -275,17 +275,17 @@ end # We plan to have flags set for this. But for the moment the generic code only supports left-multiplication, # so we can decide this from the type alone. How we do it in the long run is not yet decided, but in either case # we want to use these functions to decide as they are already there for ideals. -is_left(M::ModuleFP) = is_left_module(typeof(M)) -is_left(::Type{T}) where {RET<:RingElem, T<:ModuleFP{T}} = true -is_left(::Type{T}) where {RET<:NCRingElem, T<:ModuleFP{T}} = true # Left multiplication is generically supported +is_left(M::ModuleFP) = is_left(typeof(M)) +is_left(::Type{T}) where {RET<:RingElem, T<:ModuleFP{RET}} = true +is_left(::Type{T}) where {RET<:AdmissibleModuleFPRingElem, T<:ModuleFP{RET}} = true # Left multiplication is generically supported is_right(M::ModuleFP) = is_right_module(typeof(M)) -is_right(::Type{T}) where {RET<:RingElem, T<:ModuleFP{T}} = true -is_right(::Type{T}) where {RET<:NCRingElem, T<:ModuleFP{T}} = false # Right multiplication is not supported by the generic code at the moment, but we plan to do so eventually. +is_right(::Type{T}) where {RET<:RingElem, T<:ModuleFP{RET}} = true +is_right(::Type{T}) where {RET<:AdmissibleModuleFPRingElem, T<:ModuleFP{RET}} = false # Right multiplication is not supported by the generic code at the moment, but we plan to do so eventually. is_two_sided(M::ModuleFP) = is_right_module(typeof(M)) -is_two_sided(::Type{T}) where {RET<:RingElem, T<:ModuleFP{T}} = true -is_two_sided(::Type{T}) where {RET<:NCRingElem, T<:ModuleFP{T}} = false # see above +is_two_sided(::Type{T}) where {RET<:RingElem, T<:ModuleFP{RET}} = true +is_two_sided(::Type{T}) where {RET<:AdmissibleModuleFPRingElem, T<:ModuleFP{RET}} = false # see above @doc raw""" diff --git a/src/Modules/UngradedModules/SubQuoHom.jl b/src/Modules/UngradedModules/SubQuoHom.jl index 778fedc1f6dd..ee7da3ad97cf 100644 --- a/src/Modules/UngradedModules/SubQuoHom.jl +++ b/src/Modules/UngradedModules/SubQuoHom.jl @@ -964,12 +964,12 @@ function +(h::ModuleFPHom{D, C, Nothing}, g::ModuleFPHom{D, C, Nothing}) where { return hom(domain(h), codomain(h), elem_type(codomain(h))[h(x) + g(x) for x in gens(domain(h))], check=false) end -function *(a::NCRingElem, g::ModuleFPHom{D, C, Nothing}) where {D, C} +function *(a::AdmissibleModuleFPRingElem, g::ModuleFPHom{D, C, Nothing}) where {D, C} @assert base_ring(codomain(g)) === parent(a) return hom(domain(g), codomain(g), elem_type(codomain(g))[a*g(x) for x in gens(domain(g))], check=false) end -function *(a::NCRingElem, g::ModuleFPHom{D, C, T}) where {D, C, T} +function *(a::AdmissibleModuleFPRingElem, g::ModuleFPHom{D, C, T}) where {D, C, T} @assert base_ring(codomain(g)) === parent(a) return hom(domain(g), codomain(g), elem_type(codomain(g))[a*g(x) for x in gens(domain(g))], base_ring_map(g), check=false) end diff --git a/src/Modules/UngradedModules/SubquoModule.jl b/src/Modules/UngradedModules/SubquoModule.jl index 6075aa7f1bfb..1fd90ec88deb 100644 --- a/src/Modules/UngradedModules/SubquoModule.jl +++ b/src/Modules/UngradedModules/SubquoModule.jl @@ -157,7 +157,7 @@ end Construct the subquotient with ambient free module `F`, generators `g` and relations `q`. """ -function SubquoModule(F::FreeMod{T}, g::Vector{FreeModElem{T}}, q::Vector{FreeModElem{T}}) where {T<:NCRingElem} +function SubquoModule(F::FreeMod{T}, g::Vector{FreeModElem{T}}, q::Vector{FreeModElem{T}}) where {T<:AdmissibleModuleFPRingElem} return SubquoModule(SubModuleOfFreeModule(F, g), SubModuleOfFreeModule(F, q)) end From 2e1f1dba92f8394858849b356cad699a388fa016 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Fri, 13 Sep 2024 15:33:51 +0200 Subject: [PATCH 13/15] Adjust parameter restrictions. --- src/Modules/ModuleTypes.jl | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Modules/ModuleTypes.jl b/src/Modules/ModuleTypes.jl index 07fdf16c7374..cdbfe1ed9571 100644 --- a/src/Modules/ModuleTypes.jl +++ b/src/Modules/ModuleTypes.jl @@ -20,14 +20,14 @@ abstract type ModuleFP{T <: AdmissibleModuleFPRingElem} <: AbstractAlgebra.Modul The abstract supertype of all finitely generated free modules. """ -abstract type AbstractFreeMod{T} <: ModuleFP{T} end +abstract type AbstractFreeMod{T <: AdmissibleModuleFPRingElem} <: ModuleFP{T} end @doc raw""" AbstractSubQuo{T} <: ModuleFP{T} The abstract supertype of all finitely presented subquotient modules. """ -abstract type AbstractSubQuo{T} <: ModuleFP{T} end +abstract type AbstractSubQuo{T <: AdmissibleModuleFPRingElem} <: ModuleFP{T} end @doc raw""" @@ -35,21 +35,21 @@ abstract type AbstractSubQuo{T} <: ModuleFP{T} end The abstract supertype of all elements of finitely presented modules. """ -abstract type ModuleFPElem{T} <: ModuleElem{T} end +abstract type ModuleFPElem{T <: AdmissibleModuleFPRingElem} <: ModuleElem{T} end @doc raw""" AbstractFreeModElem{T} <: ModuleFPElem{T} The abstract supertype of all elements of finitely generated free modules. """ -abstract type AbstractFreeModElem{T} <: ModuleFPElem{T} end +abstract type AbstractFreeModElem{T <: AdmissibleModuleFPRingElem} <: ModuleFPElem{T} end @doc raw""" AbstractSubQuoElem{T} <: ModuleFPElem{T} The abstract supertype of all elements of subquotient modules. """ -abstract type AbstractSubQuoElem{T} <: ModuleFPElem{T} end +abstract type AbstractSubQuoElem{T <: AdmissibleModuleFPRingElem} <: ModuleFPElem{T} end abstract type ModuleFPHomDummy end @@ -77,7 +77,7 @@ Moreover, canonical incoming and outgoing morphisms are stored if the correspond option is set in suitable functions. `FreeMod{T}` is a subtype of `AbstractFreeMod{T}`. """ -@attributes mutable struct FreeMod{T} <: AbstractFreeMod{T} +@attributes mutable struct FreeMod{T <: AdmissibleModuleFPRingElem} <: AbstractFreeMod{T} R::NCRing n::Int S::Vector{Symbol} @@ -112,7 +112,7 @@ option is set in suitable functions. end @doc raw""" - FreeModElem{T} <: AbstractFreeModElem{T} + FreeModElem{T <: AdmissibleModuleFPRingElem} <: AbstractFreeModElem{T} The type of free module elements. An element of a free module $F$ is given by a sparse row (`SRow`) which specifies its coordinates with respect to the basis of standard unit vectors of $F$. @@ -138,7 +138,7 @@ julia> f == g true ``` """ -mutable struct FreeModElem{T} <: AbstractFreeModElem{T} +mutable struct FreeModElem{T <: AdmissibleModuleFPRingElem} <: AbstractFreeModElem{T} coords::SRow{T} # also usable via coeffs() parent::FreeMod{T} d::Union{FinGenAbGroupElem, Nothing} @@ -162,7 +162,7 @@ and all the conversion is taken care of here. This data structure is also used for representing Gröbner / standard bases. Relative Gröbner / standard bases are also supported. """ -@attributes mutable struct ModuleGens{T} # T is the type of the elements of the ground ring. +@attributes mutable struct ModuleGens{T <: AdmissibleModuleFPRingElem} # T is the type of the elements of the ground ring. O::Vector{FreeModElem{T}} S::Singular.smodule F::FreeMod{T} @@ -173,7 +173,7 @@ Relative Gröbner / standard bases are also supported. ordering::ModuleOrdering quo_GB::ModuleGens{T} # Pointer to the quotient GB when having a relative GB - function ModuleGens{T}(O::Vector{<:FreeModElem}, F::FreeMod{T}) where {T} + function ModuleGens{T}(O::Vector{<:FreeModElem}, F::FreeMod{T}) where {T <: AdmissibleModuleFPRingElem} r = new{T}() r.O = O r.F = F @@ -182,7 +182,7 @@ Relative Gröbner / standard bases are also supported. # ModuleGens from an Array of Oscar free module elements, specifying the free module # and Singular free module, only useful indirectly - function ModuleGens{T}(O::Vector{<:FreeModElem}, F::FreeMod{T}, SF::Singular.FreeMod) where {T} + function ModuleGens{T}(O::Vector{<:FreeModElem}, F::FreeMod{T}, SF::Singular.FreeMod) where {T <: AdmissibleModuleFPRingElem} r = new{T}() r.O = O r.SF = SF @@ -191,7 +191,7 @@ Relative Gröbner / standard bases are also supported. end # ModuleGens from a Singular submodule - function ModuleGens{S}(F::FreeMod{S}, s::Singular.smodule) where {S} # FreeMod is necessary due to type S + function ModuleGens{S}(F::FreeMod{S}, s::Singular.smodule) where {S <: AdmissibleModuleFPRingElem} # FreeMod is necessary due to type S r = new{S}() r.F = F if Singular.ngens(s) == 0 @@ -205,14 +205,14 @@ Relative Gröbner / standard bases are also supported. end @doc raw""" - SubModuleOfFreeModule{T} <: ModuleFP{T} + SubModuleOfFreeModule{T <: AdmissibleModuleFPRingElem} <: ModuleFP{T} Data structure for submodules of free modules. `SubModuleOfFreeModule` shouldn't be used by the end user. When computed, a standard basis (computed via `standard_basis()`) and generating matrix (that is the rows of the matrix generate the submodule) (computed via `generator_matrix()`) are cached. """ -@attributes mutable struct SubModuleOfFreeModule{T} <: ModuleFP{T} +@attributes mutable struct SubModuleOfFreeModule{T <: AdmissibleModuleFPRingElem} <: ModuleFP{T} F::FreeMod{T} gens::ModuleGens{T} groebner_basis::Dict{ModuleOrdering, ModuleGens{T}} @@ -231,7 +231,7 @@ end @doc raw""" - SubquoModule{T} <: AbstractSubQuo{T} + SubquoModule{T <: AdmissibleModuleFPRingElem} <: AbstractSubQuo{T} The type of subquotient modules. A subquotient module $M$ is a module where $M = A + B / B$ where $A$ and $B$ are @@ -243,7 +243,7 @@ Moreover, canonical incoming and outgoing morphisms are stored if the correspond option is set in suitable functions. `SubquoModule{T}` is a subtype of `ModuleFP{T}`. """ -@attributes mutable struct SubquoModule{T} <: AbstractSubQuo{T} +@attributes mutable struct SubquoModule{T <: AdmissibleModuleFPRingElem} <: AbstractSubQuo{T} #meant to represent sub+ quo mod quo - as lazy as possible F::FreeMod{T} sub::SubModuleOfFreeModule @@ -271,7 +271,7 @@ end @doc raw""" - SubquoModuleElem{T} <: AbstractSubQuoElem{T} + SubquoModuleElem{T <: AdmissibleModuleFPRingElem} <: AbstractSubQuoElem{T} The type of subquotient elements. An element $f$ of a subquotient $M$ over the ring $R$ is given by a sparse row (`SRow`) which specifies the coefficients of an $R$-linear @@ -315,13 +315,13 @@ julia> f == g true ``` """ -mutable struct SubquoModuleElem{T} <: AbstractSubQuoElem{T} +mutable struct SubquoModuleElem{T <: AdmissibleModuleFPRingElem} <: AbstractSubQuoElem{T} parent::SubquoModule{T} coeffs::SRow{T} # Need not be defined! Use `coordinates` as getter repres::FreeModElem{T} # Need not be defined! Use `repres` as getter is_reduced::Bool # `false` by default. Will be set by `simplify` and `simplify!`. - function SubquoModuleElem{R}(v::SRow{R}, SQ::SubquoModule) where {R} + function SubquoModuleElem{R}(v::SRow{R}, SQ::SubquoModule) where {R <: AdmissibleModuleFPRingElem} @assert length(v) <= ngens(SQ.sub) if isempty(v) r = new{R}(SQ, v, zero(SQ.F)) @@ -333,7 +333,7 @@ mutable struct SubquoModuleElem{T} <: AbstractSubQuoElem{T} return r end - function SubquoModuleElem{R}(a::FreeModElem{R}, SQ::SubquoModule; is_reduced::Bool=false) where {R} + function SubquoModuleElem{R}(a::FreeModElem{R}, SQ::SubquoModule; is_reduced::Bool=false) where {R <: AdmissibleModuleFPRingElem} @assert a.parent === SQ.F r = new{R}(SQ) r.repres = a From 7268642e57977e35cdc3275f6507eff8be5d703d Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Fri, 13 Sep 2024 16:58:41 +0200 Subject: [PATCH 14/15] Attempt to fix doctests. --- src/Modules/UngradedModules/SubQuoHom.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Modules/UngradedModules/SubQuoHom.jl b/src/Modules/UngradedModules/SubQuoHom.jl index ee7da3ad97cf..be65c668a968 100644 --- a/src/Modules/UngradedModules/SubQuoHom.jl +++ b/src/Modules/UngradedModules/SubQuoHom.jl @@ -267,8 +267,8 @@ julia> is_welldefined(c) false ``` """ -hom(M::SubquoModule, N::ModuleFP{T}, V::Vector{<:ModuleFPElem{T}}; check::Bool=true) where T = SubQuoHom(M, N, V; check) -hom(M::SubquoModule, N::ModuleFP{T}, A::MatElem{T}; check::Bool=true) where T = SubQuoHom(M, N, A; check) +hom(M::SubquoModule{T}, N::ModuleFP{T}, V::Vector{<:ModuleFPElem{T}}; check::Bool=true) where T = SubQuoHom(M, N, V; check) +hom(M::SubquoModule{T}, N::ModuleFP{T}, A::MatElem{T}; check::Bool=true) where T = SubQuoHom(M, N, A; check) @doc raw""" From 046c51f8bef71c981dae2f67489d07c965ca2bd8 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Fri, 13 Sep 2024 17:54:31 +0200 Subject: [PATCH 15/15] Fix missing ring map. --- .../Schemes/ProjectiveSchemes/Morphisms/Methods.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AlgebraicGeometry/Schemes/ProjectiveSchemes/Morphisms/Methods.jl b/src/AlgebraicGeometry/Schemes/ProjectiveSchemes/Morphisms/Methods.jl index 5f86d5c6ad19..f3e7e1feef23 100644 --- a/src/AlgebraicGeometry/Schemes/ProjectiveSchemes/Morphisms/Methods.jl +++ b/src/AlgebraicGeometry/Schemes/ProjectiveSchemes/Morphisms/Methods.jl @@ -231,7 +231,7 @@ function pushforward(inc::ProjectiveClosedEmbedding, M::SubquoModule) G, inc_G = sub(FT, vcat(gT, relT)) Q, inc_Q = sub(G, gens(G)[length(gT)+1:end]) MT = cokernel(inc_Q) - id = hom(MT, M, vcat(gens(M), elem_type(M)[zero(M) for i in 1:length(relT)]); check=false) + id = hom(MT, M, vcat(gens(M), elem_type(M)[zero(M) for i in 1:length(relT)]), S; check=false) return MT, id end