diff --git a/docs/src/InvariantTheory/finite_groups.md b/docs/src/InvariantTheory/finite_groups.md index 04e67f731cf2..79306c35acdb 100644 --- a/docs/src/InvariantTheory/finite_groups.md +++ b/docs/src/InvariantTheory/finite_groups.md @@ -124,64 +124,64 @@ false ## The Reynolds Operator ```@docs -reynolds_operator(IR::InvRing{FldT, GrpT, T}, f::T) where {FldT, GrpT, T <: MPolyRingElem} +reynolds_operator(IR::FinGroupInvarRing{FldT, GrpT, T}, f::T) where {FldT, GrpT, T <: MPolyRingElem} -reynolds_operator(IR::InvRing{FldT, GrpT, T}, f::T, chi::GAPGroupClassFunction) where {FldT, GrpT, T <: MPolyRingElem} +reynolds_operator(IR::FinGroupInvarRing{FldT, GrpT, T}, f::T, chi::GAPGroupClassFunction) where {FldT, GrpT, T <: MPolyRingElem} ``` ## Invariants of a Given Degree ```@docs -basis(IR::InvRing, d::Int, algorithm::Symbol = :default) +basis(IR::FinGroupInvarRing, d::Int, algorithm::Symbol = :default) -basis(IR::InvRing, d::Int, chi::GAPGroupClassFunction) +basis(IR::FinGroupInvarRing, d::Int, chi::GAPGroupClassFunction) ``` ```@docs -iterate_basis(IR::InvRing, d::Int, algorithm::Symbol = :default) +iterate_basis(IR::FinGroupInvarRing, d::Int, algorithm::Symbol = :default) -iterate_basis(IR::InvRing, d::Int, chi::GAPGroupClassFunction) +iterate_basis(IR::FinGroupInvarRing, d::Int, chi::GAPGroupClassFunction) ``` ## The Molien Series ```@docs - molien_series([S::PolyRing], I::InvRing, [chi::GAPGroupClassFunction]) + molien_series([S::PolyRing], I::FinGroupInvarRing, [chi::GAPGroupClassFunction]) ``` ## Primary Invariants ```@docs -primary_invariants(IR::InvRing) +primary_invariants(IR::FinGroupInvarRing) ``` ## Secondary Invariants ```@docs -secondary_invariants(IR::InvRing) +secondary_invariants(IR::FinGroupInvarRing) ``` ```@docs -irreducible_secondary_invariants(IR::InvRing) +irreducible_secondary_invariants(IR::FinGroupInvarRing) ``` ```@docs -module_syzygies(RG::InvRing) +module_syzygies(RG::FinGroupInvarRing) ``` ## Fundamental Systems of Invariants ```@docs -fundamental_invariants(IR::InvRing, algorithm::Symbol = :default; beta::Int = 0) +fundamental_invariants(IR::FinGroupInvarRing, algorithm::Symbol = :default; beta::Int = 0) ``` ## Invariant Rings as Affine Algebras ```@docs -affine_algebra(IR::InvRing) +affine_algebra(IR::FinGroupInvarRing) ``` ## Semi-invariants / relative invariants ```@docs -semi_invariants(IR::InvRing, chi::GAPGroupClassFunction) +semi_invariants(IR::FinGroupInvarRing, chi::GAPGroupClassFunction) ``` diff --git a/docs/src/InvariantTheory/reductive_groups.md b/docs/src/InvariantTheory/reductive_groups.md index cc42ff60bbb9..e85a9365149d 100644 --- a/docs/src/InvariantTheory/reductive_groups.md +++ b/docs/src/InvariantTheory/reductive_groups.md @@ -75,13 +75,13 @@ invariant_ring(R::MPolyDecRing, r::RepresentationLinearlyReductiveGroup) ### The Reynolds Operator ```@docs -reynolds_operator(R::RedGrpInvRing, f::MPolyRingElem) +reynolds_operator(R::RedGroupInvarRing, f::MPolyRingElem) ``` ## Fundamental Systems of Invariants ```@docs -fundamental_invariants(RG::RedGrpInvRing) +fundamental_invariants(RG::RedGroupInvarRing) ``` diff --git a/docs/src/InvariantTheory/tori.md b/docs/src/InvariantTheory/tori.md index ef9fbdbfc939..46b9a1522163 100644 --- a/docs/src/InvariantTheory/tori.md +++ b/docs/src/InvariantTheory/tori.md @@ -41,12 +41,12 @@ invariant_ring(r::RepresentationTorusGroup) ## Fundamental Systems of Invariants ```@docs -fundamental_invariants(RT::TorGrpInvRing) +fundamental_invariants(RT::TorGroupInvarRing) ``` ## Invariant Rings as Affine Algebras ```@docs -affine_algebra(RT::TorGrpInvRing) +affine_algebra(RT::TorGroupInvarRing) ``` diff --git a/experimental/InvariantTheory/src/InvariantTheory.jl b/experimental/InvariantTheory/src/InvariantTheory.jl index 43d7dfe9ec9d..1cfde8782f86 100644 --- a/experimental/InvariantTheory/src/InvariantTheory.jl +++ b/experimental/InvariantTheory/src/InvariantTheory.jl @@ -3,9 +3,20 @@ #Then we set up the invariant ring of the group. The fundamental invariants are computed using Derksen's alg. #As of now, the only reynolds operator that is implemented is the one for SLm, using Cayley's Omega process. -export LinearlyReductiveGroup, linearly_reductive_group, representation_matrix, group, reynolds_operator, group_ideal, canonical_representation, natural_representation -export RepresentationLinearlyReductiveGroup, representation_reductive_group, representation_on_forms, representation_matrix, direct_sum, tensor -export RedGrpInvRing, invariant_ring, fundamental_invariants, NullConeIdeal, polynomial_ring, representation, affine_algebra +export canonical_representation +export group_ideal +export LinearlyReductiveGroup +export linearly_reductive_group +export natural_representation +export null_cone_ideal +export RedGroupInvarRing +export representation +export RepresentationLinearlyReductiveGroup +export representation_matrix +export representation_reductive_group +export representation_on_forms +export tensor + ########################## #Setting up Reductive Groups ########################## @@ -239,14 +250,14 @@ end function rep_mat_(G::LinearlyReductiveGroup, sym_deg::Int) G.group[1] == :SL || error("Only implemented for SLm") m = G.group[2] - R = base_ring(G.group_ideal) # TODO: probably should have a getter function for this + R = base_ring(group_ideal(G)) mixed_ring, t = polynomial_ring(R, "t" => 1:m) group_mat = natural_representation(G) new_vars = group_mat*t - - b = degree_basis(mixed_ring,sym_deg) + + b = [ multinomial(sym_deg, first(AbstractAlgebra.exponent_vectors(a)))*a for a in monomials_of_degree(mixed_ring, sym_deg) ] n = length(b) - + # transform the b elements images_of_b = [evaluate(f, new_vars) for f in b] @@ -254,7 +265,7 @@ function rep_mat_(G::LinearlyReductiveGroup, sym_deg::Int) for j in 1:n f = images_of_b[j] x = mixed_ring() - # express f as a linear combination of degree_basis + # express f as a linear combination of elements in b for i in 1:n c = coeff(f, leading_exponent(b[i])) mat[i,j] = c / leading_coefficient(b[i]) @@ -263,33 +274,8 @@ function rep_mat_(G::LinearlyReductiveGroup, sym_deg::Int) return mat end -#computes symmetric degree basis (of the first m variables) WITH multinomial coefficients! -function degree_basis(R::MPolyRing, t::Int) - m = ngens(R) - C = zero_matrix(ZZ, m, m) - for i in 1:m - C[i,i] = -1 - end - d = zeros(Int, m) - A = ones(Int, m) - b = [t] - P = polyhedron((C, d), (A, b)) - L = lattice_points(P) - W = Vector{MPolyRingElem}(undef,0) - for l in L - v = R(1) - for i in 1:m - v = v*gen(R,i)^l[i] - end - v = v*multinomial(t,l) - push!(W,v) - end - #we reverse here to get the natural order of a degree basis, eg x^2, 2xy, y^2. - return reverse(W) -end - -#used to compute multinomial expansion coefficients (used in degree_basis) -function multinomial(n::Int, v::Union{Vector{T},PointVector{T}}) where T <: IntegerUnion +#used to compute multinomial expansion coefficients +function multinomial(n::Int, v::AbstractVector{<:IntegerUnion}) x = prod(factorial, v) return Int(factorial(n)/x) end @@ -297,40 +283,46 @@ end ########################## #Invariant Rings of Reductive groups ########################## -@attributes mutable struct RedGrpInvRing - field::Field - poly_ring::MPolyDecRing #graded - +@attributes mutable struct RedGroupInvarRing{FldT, PolyRingElemT, PolyRingT} + field::FldT + poly_ring::PolyRingT # graded + group::LinearlyReductiveGroup representation::RepresentationLinearlyReductiveGroup - + reynolds_operator::Function - + + fundamental::Vector{PolyRingElemT} + presentation::MPolyAnyMap{MPolyQuoRing{PolyRingElemT}, PolyRingT, Nothing, PolyRingElemT} + #Invariant ring of reductive group G (in representation R), no other input. - function RedGrpInvRing(R::RepresentationLinearlyReductiveGroup) #here G already contains information n and rep_mat - z = new() + function RedGroupInvarRing(R::RepresentationLinearlyReductiveGroup) #here G already contains information n and rep_mat + G = group(R) + K = field(G) n = ncols(R.rep_mat) + poly_ring, _ = graded_polynomial_ring(K, "X" => 1:n) + z = new{typeof(K), elem_type(poly_ring), typeof(poly_ring)}() z.representation = R - z.group = R.group - G = z.group - z.field = G.field - z.poly_ring, __ = graded_polynomial_ring(G.field, "X" => 1:n) + z.group = G + z.field = K + z.poly_ring = poly_ring z.reynolds_operator = reynolds_v_slm return z end - + #to compute invariant ring ring^G where G is the reductive group of R. - function RedGrpInvRing(R::RepresentationLinearlyReductiveGroup, ring::MPolyDecRing) + function RedGroupInvarRing(R::RepresentationLinearlyReductiveGroup, ring::MPolyDecRing) n = ncols(R.rep_mat) n == ngens(ring) || error("The given polynomial ring is not compatible.") - z = new() + G = group(R) + K = field(G) + z = new{typeof(K), elem_type(ring), typeof(ring)}() if isdefined(R, :weights) #dosomething end z.representation = R - z.group = R.group - G = R.group - z.field = G.field + z.group = G + z.field = K z.poly_ring = ring z.reynolds_operator = reynolds_v_slm return z @@ -354,7 +346,7 @@ graded multivariate polynomial ring in 3 variables over QQ under group action of SL2 ``` """ -invariant_ring(R::RepresentationLinearlyReductiveGroup) = RedGrpInvRing(R) +invariant_ring(R::RepresentationLinearlyReductiveGroup) = RedGroupInvarRing(R) @doc raw""" invariant_ring(R::MPolyDecRing, r::RepresentationLinearlyReductiveGroup) @@ -375,22 +367,20 @@ graded multivariate polynomial ring in 10 variables over QQ under group action of SL3 ``` """ -invariant_ring(ring::MPolyDecRing, R::RepresentationLinearlyReductiveGroup) = RedGrpInvRing(R, ring) +invariant_ring(ring::MPolyDecRing, R::RepresentationLinearlyReductiveGroup) = RedGroupInvarRing(R, ring) -@attr MPolyIdeal function NullConeIdeal(R::RedGrpInvRing) +@attr MPolyIdeal function null_cone_ideal(R::RedGroupInvarRing) Z = R.representation I, _ = proj_of_image_ideal(group(Z), Z.rep_mat) return ideal(generators(Z.group, I, Z.rep_mat)) end -polynomial_ring(R::RedGrpInvRing) = R.poly_ring -group(R::RedGrpInvRing) = R.group -representation(R::RedGrpInvRing) = R.representation - - +polynomial_ring(R::RedGroupInvarRing) = R.poly_ring +group(R::RedGroupInvarRing) = R.group +representation(R::RedGroupInvarRing) = R.representation @doc raw""" - fundamental_invariants(RG::RedGrpInvRing) + fundamental_invariants(RG::RedGroupInvarRing) Return a system of fundamental invariants for `RG`. @@ -408,14 +398,17 @@ julia> fundamental_invariants(RG) ``` """ -@attr function fundamental_invariants(z::RedGrpInvRing) #unable to use abstract type - R = z.representation - I, M = proj_of_image_ideal(R.group, R.rep_mat) - NullConeIdeal(z) = ideal(generators(R.group, I, R.rep_mat)) - return inv_generators(NullConeIdeal(z), R.group, z.poly_ring, M, z.reynolds_operator) +function fundamental_invariants(z::RedGroupInvarRing) #unable to use abstract type + if !isdefined(z, :fundamental) + R = z.representation + I, M = proj_of_image_ideal(R.group, R.rep_mat) + null_cone_ideal(z) = ideal(generators(R.group, I, R.rep_mat)) + z.fundamental = inv_generators(null_cone_ideal(z), R.group, z.poly_ring, M, z.reynolds_operator) + end + return copy(z.fundamental) end -function Base.show(io::IO, R::RedGrpInvRing) +function Base.show(io::IO, R::RedGroupInvarRing) io = pretty(io) println(io, "Invariant Ring of") println(io, Lowercase(), R.poly_ring) @@ -614,7 +607,7 @@ function reynolds_operator(X::RepresentationLinearlyReductiveGroup, elem::MPolyR end @doc raw""" - reynolds_operator(RG::RedGrpInvRing, f::MPolyRingElem) + reynolds_operator(RG::RedGroupInvarRing, f::MPolyRingElem) Return the image of `f` under the Reynolds operator corresponding to `RG`. @@ -632,7 +625,7 @@ julia> 75*reynolds_operator(RG, x[5]^4) x[1]*x[4]*x[8]*x[10] - x[1]*x[4]*x[9]^2 - x[1]*x[5]*x[7]*x[10] + x[1]*x[5]*x[8]*x[9] + x[1]*x[6]*x[7]*x[9] - x[1]*x[6]*x[8]^2 - x[2]^2*x[8]*x[10] + x[2]^2*x[9]^2 + x[2]*x[3]*x[7]*x[10] - x[2]*x[3]*x[8]*x[9] + x[2]*x[4]*x[5]*x[10] - x[2]*x[4]*x[6]*x[9] - 2*x[2]*x[5]^2*x[9] + 3*x[2]*x[5]*x[6]*x[8] - x[2]*x[6]^2*x[7] - x[3]^2*x[7]*x[9] + x[3]^2*x[8]^2 - x[3]*x[4]^2*x[10] + 3*x[3]*x[4]*x[5]*x[9] - x[3]*x[4]*x[6]*x[8] - 2*x[3]*x[5]^2*x[8] + x[3]*x[5]*x[6]*x[7] + x[4]^2*x[6]^2 - 2*x[4]*x[5]^2*x[6] + x[5]^4 ``` """ -function reynolds_operator(R::RedGrpInvRing, elem::MPolyRingElem) +function reynolds_operator(R::RedGroupInvarRing, elem::MPolyRingElem) X = R.representation return reynolds_operator(X, elem) end @@ -643,7 +636,7 @@ include("TorusInvariantsFast.jl") #####################Invariant rings as affine algebras @doc raw""" - affine_algebra(RG::RedGrpInvRing) + affine_algebra(RG::RedGroupInvarRing) Return the invariant ring `RG` as an affine algebra (this amounts to compute the algebra syzygies among the fundamental invariants of `RG`). @@ -664,18 +657,21 @@ julia> A, AtoS = affine_algebra(RG) (Quotient of multivariate polynomial ring by ideal (0), Hom: A -> S) ``` """ -@attr function affine_algebra(R::RedGrpInvRing) - V = fundamental_invariants(R) - s = length(V) - weights_ = zeros(Int, s) - for i in 1:s - weights_[i] = total_degree(V[i]) - end - S,_ = graded_polynomial_ring(field(group(representation(R))), "t"=>1:s; weights = weights_) - R_ = polynomial_ring(R) - StoR = hom(S,R_,V) - I = kernel(StoR) - Q, StoQ = quo(S,I) - QtoR = hom(Q,R_,V) - return Q, QtoR +function affine_algebra(R::RedGroupInvarRing) + if !isdefined(R, :presentation) + V = fundamental_invariants(R) + s = length(V) + weights_ = zeros(Int, s) + for i in 1:s + weights_[i] = total_degree(V[i]) + end + S,_ = graded_polynomial_ring(field(group(representation(R))), "t"=>1:s; weights = weights_) + R_ = polynomial_ring(R) + StoR = hom(S,R_,V) + I = kernel(StoR) + Q, StoQ = quo(S,I) + QtoR = hom(Q,R_,V) + R.presentation = QtoR + end + return domain(R.presentation), R.presentation end diff --git a/experimental/InvariantTheory/src/TorusInvariantsFast.jl b/experimental/InvariantTheory/src/TorusInvariantsFast.jl index 8d6e2ce245e2..7cbc628df96c 100644 --- a/experimental/InvariantTheory/src/TorusInvariantsFast.jl +++ b/experimental/InvariantTheory/src/TorusInvariantsFast.jl @@ -1,4 +1,6 @@ -export torus_group, rank, field, representation_from_weights, weights, group, invariant_ring, polynomial_ring, representation, fundamental_invariants, affine_algebra +export field +export representation_from_weights +export torus_group ##################### #Setting up tori for fast torus algorithm @@ -6,7 +8,7 @@ export torus_group, rank, field, representation_from_weights, weights, group, in struct TorusGroup field::Field - rank::Int + rank::Int #weights::Vector{Vector{ZZRingElem}} end @@ -159,25 +161,30 @@ end #Setting up invariant ring for fast torus algorithm. ##################### -@attributes mutable struct TorGrpInvRing - field::Field - poly_ring::MPolyDecRing #graded - +@attributes mutable struct TorGroupInvarRing{FldT, PolyRingElemT, PolyRingT} + field::FldT + poly_ring::PolyRingT #graded + group::TorusGroup representation::RepresentationTorusGroup - + + fundamental::Vector{PolyRingElemT} + presentation::MPolyAnyMap{MPolyQuoRing{PolyRingElemT}, PolyRingT, Nothing, PolyRingElemT} + + #Invariant ring of reductive group G (in representation R), no other input. - function TorGrpInvRing(R::RepresentationTorusGroup) #here G already contains information n and rep_mat + function TorGroupInvarRing(R::RepresentationTorusGroup) #here G already contains information n and rep_mat n = length(weights(R)) - super_ring, __ = graded_polynomial_ring(field(group(R)), "X"=>1:n) - return TorGrpInvRing(R, super_ring) + super_ring, _ = graded_polynomial_ring(field(group(R)), "X"=>1:n) + return TorGroupInvarRing(R, super_ring) end - + #to compute invariant ring ring^G where G is the reductive group of R. - function TorGrpInvRing(R::RepresentationTorusGroup, ring_::MPolyDecRing) - z = new() + function TorGroupInvarRing(R::RepresentationTorusGroup, ring_::MPolyDecRing) + K = field(group(R)) + z = new{typeof(K), elem_type(ring_), typeof(ring_)}() n = length(weights(R)) - z.field = field(group(R)) + z.field = K z.poly_ring = ring_ z.representation = R z.group = group(R) @@ -204,10 +211,10 @@ Invariant Ring of graded multivariate polynomial ring in 4 variables over QQ under group action of torus of rank2 ``` """ -invariant_ring(R::RepresentationTorusGroup) = TorGrpInvRing(R) +invariant_ring(R::RepresentationTorusGroup) = TorGroupInvarRing(R) @doc raw""" - polynomial_ring(RT::TorGrpInvRing) + polynomial_ring(RT::TorGroupInvarRing) # Examples ```jldoctest @@ -216,10 +223,10 @@ Torus of rank 2 over QQ ``` """ -polynomial_ring(R::TorGrpInvRing) = R.poly_ring +polynomial_ring(R::TorGroupInvarRing) = R.poly_ring @doc raw""" - group(RT::TorGrpInvRing) + group(RT::TorGroupInvarRing) # Examples ```jldoctest @@ -228,10 +235,10 @@ Torus of rank 2 over QQ ``` """ -group(R::TorGrpInvRing) = R.group +group(R::TorGroupInvarRing) = R.group @doc raw""" - representation(RT::TorGrpInvRing) + representation(RT::TorGroupInvarRing) # Examples ```jldoctest @@ -240,10 +247,10 @@ Torus of rank 2 over QQ ``` """ -representation(R::TorGrpInvRing) = R.representation +representation(R::TorGroupInvarRing) = R.representation @doc raw""" - fundamental_invariants(RT::TorGrpInvRing) + fundamental_invariants(RT::TorGroupInvarRing) Return a system of fundamental invariants for `RT`. @@ -262,12 +269,15 @@ julia> fundamental_invariants(RT) X[2]^2*X[3] ``` """ -@attr function fundamental_invariants(z::TorGrpInvRing) - R = z.representation - return torus_invariants_fast(weights(R), polynomial_ring(z)) +function fundamental_invariants(z::TorGroupInvarRing) + if !isdefined(z, :fundamental) + R = z.representation + z.fundamental = torus_invariants_fast(weights(R), polynomial_ring(z)) + end + return copy(z.fundamental) end -function Base.show(io::IO, R::TorGrpInvRing) +function Base.show(io::IO, R::TorGroupInvarRing) io = pretty(io) println(io, "Invariant Ring of") print(io, Lowercase(), R.poly_ring) @@ -367,7 +377,7 @@ end #####################Invariant rings as affine algebras @doc raw""" - affine_algebra(RT::TorGrpInvRing) + affine_algebra(RT::TorGroupInvarRing) Return the invariant ring `RT` as an affine algebra (this amounts to compute the algebra syzygies among the fundamental invariants of `RT`). @@ -392,18 +402,21 @@ julia> affine_algebra(RT) (Quotient of multivariate polynomial ring by ideal (-t[1]*t[3] + t[2]^2), Hom: quotient of multivariate polynomial ring -> graded multivariate polynomial ring) ``` """ -@attr function affine_algebra(R::TorGrpInvRing) - V = fundamental_invariants(R) - s = length(V) - weights_ = zeros(Int, s) - for i in 1:s - weights_[i] = total_degree(V[i]) - end - S,_ = graded_polynomial_ring(field(group(representation(R))), "t"=>1:s; weights = weights_) - R_ = polynomial_ring(R) - StoR = hom(S,R_,V) - I = kernel(StoR) - Q, StoQ = quo(S,I) - QtoR = hom(Q,R_,V) - return Q, QtoR +function affine_algebra(R::TorGroupInvarRing) + if !isdefined(R, :presentation) + V = fundamental_invariants(R) + s = length(V) + weights_ = zeros(Int, s) + for i in 1:s + weights_[i] = total_degree(V[i]) + end + S,_ = graded_polynomial_ring(field(group(representation(R))), "t"=>1:s; weights = weights_) + R_ = polynomial_ring(R) + StoR = hom(S,R_,V) + I = kernel(StoR) + Q, StoQ = quo(S,I) + QtoR = hom(Q,R_,V) + R.presentation = QtoR + end + return domain(R.presentation), R.presentation end diff --git a/src/InvariantTheory/affine_algebra.jl b/src/InvariantTheory/affine_algebra.jl index 354a30cf9c48..a8c35e1f32f5 100644 --- a/src/InvariantTheory/affine_algebra.jl +++ b/src/InvariantTheory/affine_algebra.jl @@ -5,7 +5,7 @@ ################################################################################ @doc raw""" - affine_algebra(IR::InvRing; + affine_algebra(IR::FinGroupInvarRing; algo_gens::Symbol = :default, algo_rels::Symbol = :groebner_basis) Given an invariant ring `IR` with underlying graded polynomial ring, say `R`, @@ -68,7 +68,7 @@ julia> affine_algebra(IR) (Quotient of multivariate polynomial ring by ideal with 1 generator, Hom: quotient of multivariate polynomial ring -> graded multivariate polynomial ring) ``` """ -function affine_algebra(IR::InvRing; algo_gens::Symbol = :default, algo_rels::Symbol = :groebner_basis) +function affine_algebra(IR::FinGroupInvarRing; algo_gens::Symbol = :default, algo_rels::Symbol = :groebner_basis) if !isdefined(IR, :presentation) if algo_gens == :king && algo_rels == :linear_algebra error("Combination of arguments :$(algo_gens) for algo_gens and :$(algo_rels) for algo_rels not possible") @@ -91,7 +91,7 @@ end # ################################################################################ -function relations_via_groebner_basis(RG::InvRing, algo_fundamental::Symbol = :default) +function relations_via_groebner_basis(RG::FinGroupInvarRing, algo_fundamental::Symbol = :default) R = polynomial_ring(RG) fund_invars = fundamental_invariants(RG, algo_fundamental) @@ -103,7 +103,7 @@ function relations_via_groebner_basis(RG::InvRing, algo_fundamental::Symbol = :d return Q, QtoR end -function relations_via_linear_algebra(RG::InvRing) +function relations_via_linear_algebra(RG::FinGroupInvarRing) fund_invars = fundamental_invariants(RG, :primary_and_secondary) @assert RG.fundamental.via_primary_and_secondary "Cached fundamental invariants do not come from primary and secondary invariants" @@ -123,7 +123,7 @@ end # Relations between primary and irreducible secondary invariants, see # [KS99, Section 17.5.5] or [DK15, Section 3.8.3]. -function relations_primary_and_irreducible_secondary(RG::InvRing) +function relations_primary_and_irreducible_secondary(RG::FinGroupInvarRing) Rgraded = polynomial_ring(RG) R = forget_grading(Rgraded) K = coefficient_ring(R) @@ -252,7 +252,7 @@ end ################################################################################ @doc raw""" - module_syzygies(RG::InvRing) + module_syzygies(RG::FinGroupInvarRing) Given an invariant ring `RG` over a ring `R`, compute a presentation of `RG` as a module over the subalgebra generated by a system of primary invariants. @@ -260,7 +260,7 @@ Return a module `M` over a ring `S`, a map `M \to R` which is onto `RG` by mapping the generators of `M` to a system of secondary invariants, and a map `S \to R` which is onto the subalgebra generated by the primary invariants. """ -function module_syzygies(RG::InvRing) +function module_syzygies(RG::FinGroupInvarRing) # Follow the strategy described in DK15, p. 110. That is: # Let S be the subalgebra generated by the primary invariants. We choose free # generators of R as an S-module, so we set up an isomorphism R \cong S^r for diff --git a/src/InvariantTheory/fundamental_invariants.jl b/src/InvariantTheory/fundamental_invariants.jl index 677474d787d9..90c502c7be05 100644 --- a/src/InvariantTheory/fundamental_invariants.jl +++ b/src/InvariantTheory/fundamental_invariants.jl @@ -20,7 +20,7 @@ function _groebner_basis(I::MPolyIdeal, d::Int; ordering::MonomialOrdering = def end # [Kin13, p. 5] See also [DK15, Algorithm 3.8.2] -function fundamental_invariants_via_king(RG::InvRing, beta::Int = 0) +function fundamental_invariants_via_king(RG::FinGroupInvarRing, beta::Int = 0) @assert !is_modular(RG) Rgraded = _internal_polynomial_ring(RG) @@ -112,7 +112,7 @@ end # Hence if we take the primary and irreducible secondary invariants, we only have # to make sure, that none of the *primary* invariants is in the algebra # generated by the others. -function fundamental_invariants_via_primary_and_secondary(IR::InvRing) +function fundamental_invariants_via_primary_and_secondary(IR::FinGroupInvarRing) R = polynomial_ring(IR) K = coefficient_ring(R) @@ -160,7 +160,7 @@ end ################################################################################ @doc raw""" - fundamental_invariants(IR::InvRing, algorithm::Symbol = :default; beta::Int = 0) + fundamental_invariants(IR::FinGroupInvarRing, algorithm::Symbol = :default; beta::Int = 0) Return a system of fundamental invariants for `IR`. @@ -215,7 +215,7 @@ julia> fundamental_invariants(IR) x[1]^3*x[2]^6 + x[1]^6*x[3]^3 + x[2]^3*x[3]^6 ``` """ -function fundamental_invariants(IR::InvRing, algorithm::Symbol = :default; beta::Int = 0) +function fundamental_invariants(IR::FinGroupInvarRing, algorithm::Symbol = :default; beta::Int = 0) if !isdefined(IR, :fundamental) if algorithm == :default algorithm = is_modular(IR) ? :primary_and_secondary : :king diff --git a/src/InvariantTheory/invariant_rings.jl b/src/InvariantTheory/invariant_rings.jl index d268552298f7..c1509e040b9b 100644 --- a/src/InvariantTheory/invariant_rings.jl +++ b/src/InvariantTheory/invariant_rings.jl @@ -4,17 +4,17 @@ # ################################################################################ -coefficient_ring(I::InvRing) = I.field +coefficient_ring(I::FinGroupInvarRing) = I.field -polynomial_ring(I::InvRing) = I.poly_ring +polynomial_ring(I::FinGroupInvarRing) = I.poly_ring -action(I::InvRing) = I.action +action(I::FinGroupInvarRing) = I.action -group(I::InvRing) = I.group +group(I::FinGroupInvarRing) = I.group -is_modular(I::InvRing) = I.modular +is_modular(I::FinGroupInvarRing) = I.modular -function _internal_polynomial_ring(I::InvRing) +function _internal_polynomial_ring(I::FinGroupInvarRing) if isdefined(I, :poly_ring_internal) return I.poly_ring_internal end @@ -32,7 +32,7 @@ function __cast_forced(R::MPolyRing{T}, f::MPolyRingElem{T}) where T end # Assumes that parent(f) === I.poly_ring -function _cast_in_internal_poly_ring(I::InvRing, f::MPolyRingElem) +function _cast_in_internal_poly_ring(I::FinGroupInvarRing, f::MPolyRingElem) if !isdefined(I, :poly_ring_internal) return f end @@ -41,7 +41,7 @@ end # Assumes that parent(f) === I.poly_ring_internal, if this is assigned, # and parent(f) === I.poly_ring otherwise -function _cast_in_external_poly_ring(I::InvRing, f::MPolyRingElem) +function _cast_in_external_poly_ring(I::FinGroupInvarRing, f::MPolyRingElem) if !isdefined(I, :poly_ring_internal) return f end @@ -116,27 +116,27 @@ Rational field """ function invariant_ring(G::MatrixGroup) action = mat_elem_type(typeof(G))[g.elm for g in gens(G)] - return InvRing(base_ring(G), G, action) + return FinGroupInvarRing(base_ring(G), G, action) end function invariant_ring(R::MPolyDecRing, G::MatrixGroup) action = mat_elem_type(typeof(G))[g.elm for g in gens(G)] - return InvRing(base_ring(G), G, action, R) + return FinGroupInvarRing(base_ring(G), G, action, R) end -invariant_ring(K::Field, G::PermGroup) = InvRing(K, G, gens(G)) +invariant_ring(K::Field, G::PermGroup) = FinGroupInvarRing(K, G, gens(G)) invariant_ring(G::PermGroup) = invariant_ring(QQ, G) -invariant_ring(R::MPolyDecRing, G::PermGroup) = InvRing(coefficient_ring(R), G, gens(G), R) +invariant_ring(R::MPolyDecRing, G::PermGroup) = FinGroupInvarRing(coefficient_ring(R), G, gens(G), R) -function Base.show(io::IO, ::MIME"text/plain", RG::InvRing) +function Base.show(io::IO, ::MIME"text/plain", RG::FinGroupInvarRing) io = pretty(io) println(io, "Invariant ring") print(io, Indent(), "of ", Lowercase(), group(RG), Dedent()) end -function Base.show(io::IO, RG::InvRing) +function Base.show(io::IO, RG::FinGroupInvarRing) if get(io, :supercompact, false) print(io, "Invariant ring") else @@ -198,7 +198,7 @@ right_action(f::MPolyRingElem, p::PermGroupElem) = right_action(parent(f), p)(f) # ################################################################################ -function reynolds_operator(IR::InvRing{FldT, GrpT, PolyRingElemT}) where {FldT, GrpT, PolyRingElemT} +function reynolds_operator(IR::FinGroupInvarRing{FldT, GrpT, PolyRingElemT}) where {FldT, GrpT, PolyRingElemT} @assert !is_modular(IR) if isdefined(IR, :reynolds_operator) @@ -219,7 +219,7 @@ function reynolds_operator(IR::InvRing{FldT, GrpT, PolyRingElemT}) where {FldT, end @doc raw""" - reynolds_operator(IR::InvRing{FldT, GrpT, T}, f::T) where {FldT, GrpT, T <: MPolyRingElem} + reynolds_operator(IR::FinGroupInvarRing{FldT, GrpT, T}, f::T) where {FldT, GrpT, T <: MPolyRingElem} In the non-modular case, return the image of `f` under the Reynolds operator projecting onto `IR`. @@ -303,7 +303,7 @@ julia> reynolds_operator(IR, f) 0 ``` """ -function reynolds_operator(IR::InvRing{FldT, GrpT, T}, f::T) where {FldT, GrpT, T <: MPolyRingElem} +function reynolds_operator(IR::FinGroupInvarRing{FldT, GrpT, T}, f::T) where {FldT, GrpT, T <: MPolyRingElem} @assert !is_modular(IR) @assert parent(f) === polynomial_ring(IR) @@ -313,12 +313,12 @@ function reynolds_operator(IR::InvRing{FldT, GrpT, T}, f::T) where {FldT, GrpT, return IR.reynolds_operator(f) end -function reynolds_operator(IR::InvRing, f::MPolyRingElem) +function reynolds_operator(IR::FinGroupInvarRing, f::MPolyRingElem) @assert parent(f) === forget_grading(polynomial_ring(IR)) return reynolds_operator(IR, polynomial_ring(IR)(f)) end -function reynolds_operator(IR::InvRing{FldT, GrpT, PolyRingElemT}, chi::GAPGroupClassFunction) where {FldT, GrpT, PolyRingElemT} +function reynolds_operator(IR::FinGroupInvarRing{FldT, GrpT, PolyRingElemT}, chi::GAPGroupClassFunction) where {FldT, GrpT, PolyRingElemT} # I expect that this also works in the non-modular case, but haven't found a reference. # The only reference for this version of the reynolds operator appears to be [Gat96]. @assert is_zero(characteristic(coefficient_ring(IR))) @@ -342,7 +342,7 @@ function reynolds_operator(IR::InvRing{FldT, GrpT, PolyRingElemT}, chi::GAPGroup end @doc raw""" - reynolds_operator(IR::InvRing{FldT, GrpT, T}, f::T, chi::GAPGroupClassFunction) + reynolds_operator(IR::FinGroupInvarRing{FldT, GrpT, T}, f::T, chi::GAPGroupClassFunction) where {FldT, GrpT, T <: MPolyRingElem} In the case of characteristic zero, return the image of `f` under the twisted @@ -396,11 +396,11 @@ julia> reynolds_operator(IR, x[1], chi) 1//2*x[1] - 1//2*x[2] ``` """ -function reynolds_operator(IR::InvRing{FldT, GrpT, T}, f::T, chi::GAPGroupClassFunction) where {FldT, GrpT, T <: MPolyRingElem} +function reynolds_operator(IR::FinGroupInvarRing{FldT, GrpT, T}, f::T, chi::GAPGroupClassFunction) where {FldT, GrpT, T <: MPolyRingElem} return reynolds_operator(IR, chi)(f) end -function reynolds_operator(IR::InvRing, f::MPolyRingElem, chi::GAPGroupClassFunction) +function reynolds_operator(IR::FinGroupInvarRing, f::MPolyRingElem, chi::GAPGroupClassFunction) @assert parent(f) === forget_grading(polynomial_ring(IR)) return reynolds_operator(IR, polynomial_ring(IR)(f), chi) end @@ -412,7 +412,7 @@ end ################################################################################ @doc raw""" - basis(IR::InvRing, d::Int, algorithm::Symbol = :default) + basis(IR::FinGroupInvarRing, d::Int, algorithm::Symbol = :default) Given an invariant ring `IR` and an integer `d`, return a basis for the invariants in degree `d`. @@ -477,10 +477,10 @@ julia> basis(IR, 3) x[1]^2*x[3] + 2*x[2]^2*x[3] ``` """ -basis(IR::InvRing, d::Int, algorithm::Symbol = :default) = collect(iterate_basis(IR, d, algorithm)) +basis(IR::FinGroupInvarRing, d::Int, algorithm::Symbol = :default) = collect(iterate_basis(IR, d, algorithm)) @doc raw""" - basis(IR::InvRing, d::Int, chi::GAPGroupClassFunction) + basis(IR::FinGroupInvarRing, d::Int, chi::GAPGroupClassFunction) Given an invariant ring `IR`, an integer `d` and an irreducible character `chi`, return a basis for the semi-invariants (or relative invariants) in degree `d` @@ -528,7 +528,7 @@ julia> basis(R, 3, chi) ``` """ -basis(IR::InvRing, d::Int, chi::GAPGroupClassFunction) = collect(iterate_basis(IR, d, chi)) +basis(IR::FinGroupInvarRing, d::Int, chi::GAPGroupClassFunction) = collect(iterate_basis(IR, d, chi)) ################################################################################ # @@ -552,7 +552,7 @@ basis(IR::InvRing, d::Int, chi::GAPGroupClassFunction) = collect(iterate_basis(I # ################################################################################ -function _molien_series_char0(S::PolyRing, I::InvRing) +function _molien_series_char0(S::PolyRing, I::FinGroupInvarRing) G = group(I) n = degree(G) K = coefficient_ring(I) @@ -578,7 +578,7 @@ function _molien_series_char0(S::PolyRing, I::InvRing) return num//den end -function _molien_series_nonmodular_via_gap(S::PolyRing, I::InvRing, chi::Union{GAPGroupClassFunction, Nothing} = nothing) +function _molien_series_nonmodular_via_gap(S::PolyRing, I::FinGroupInvarRing, chi::Union{GAPGroupClassFunction, Nothing} = nothing) @assert !is_modular(I) G = group(I) @assert G isa MatrixGroup || G isa PermGroup @@ -608,7 +608,7 @@ function _molien_series_nonmodular_via_gap(S::PolyRing, I::InvRing, chi::Union{G end @doc raw""" - molien_series([S::PolyRing], I::InvRing, [chi::GAPGroupClassFunction]) + molien_series([S::PolyRing], I::FinGroupInvarRing, [chi::GAPGroupClassFunction]) In the non-modular case, return the Molien series of `I` as a rational function. @@ -659,7 +659,7 @@ julia> molien_series(IR, chi) t//(t^3 - t^2 - t + 1) ``` """ -function molien_series(S::PolyRing, I::InvRing, chi::Union{GAPGroupClassFunction, Nothing} = nothing) +function molien_series(S::PolyRing, I::FinGroupInvarRing, chi::Union{GAPGroupClassFunction, Nothing} = nothing) if isdefined(I, :molien_series) && chi === nothing if parent(I.molien_series) === S return I.molien_series @@ -680,7 +680,7 @@ function molien_series(S::PolyRing, I::InvRing, chi::Union{GAPGroupClassFunction end end -function molien_series(I::InvRing, chi::Union{GAPGroupClassFunction, Nothing} = nothing) +function molien_series(I::FinGroupInvarRing, chi::Union{GAPGroupClassFunction, Nothing} = nothing) if chi === nothing if !isdefined(I, :molien_series) S, t = polynomial_ring(QQ, "t", cached = false) @@ -696,7 +696,7 @@ end # There are some situations where one needs to know whether one can ask for the # Molien series without throwing an error. # And maybe some day we can also compute Molien series in some modular cases. -is_molien_series_implemented(I::InvRing) = !is_modular(I) +is_molien_series_implemented(I::FinGroupInvarRing) = !is_modular(I) ################################################################################ # diff --git a/src/InvariantTheory/iterators.jl b/src/InvariantTheory/iterators.jl index a85cd51d9df5..b62881617792 100644 --- a/src/InvariantTheory/iterators.jl +++ b/src/InvariantTheory/iterators.jl @@ -155,7 +155,7 @@ end # Return the dimension of the graded component of degree d. # If we cannot compute the Molien series (so far in the modular case), we return # -1. -function dimension_via_molien_series(::Type{T}, R::InvRing, d::Int, chi::Union{GAPGroupClassFunction, Nothing} = nothing) where T <: IntegerUnion +function dimension_via_molien_series(::Type{T}, R::FinGroupInvarRing, d::Int, chi::Union{GAPGroupClassFunction, Nothing} = nothing) where T <: IntegerUnion if !is_molien_series_implemented(R) return -1 end @@ -168,7 +168,7 @@ function dimension_via_molien_series(::Type{T}, R::InvRing, d::Int, chi::Union{G end @doc raw""" - iterate_basis(IR::InvRing, d::Int, algorithm::Symbol = :default) + iterate_basis(IR::FinGroupInvarRing, d::Int, algorithm::Symbol = :default) Given an invariant ring `IR` and an integer `d`, return an iterator over a basis for the invariants in degree `d`. @@ -241,7 +241,7 @@ julia> collect(B) x[3]^2 ``` """ -function iterate_basis(R::InvRing, d::Int, algorithm::Symbol = :default) +function iterate_basis(R::FinGroupInvarRing, d::Int, algorithm::Symbol = :default) @assert d >= 0 "Degree must be non-negative" if algorithm == :default @@ -279,7 +279,7 @@ function iterate_basis(R::InvRing, d::Int, algorithm::Symbol = :default) end @doc raw""" - iterate_basis(IR::InvRing, d::Int, chi::GAPGroupClassFunction) + iterate_basis(IR::FinGroupInvarRing, d::Int, chi::GAPGroupClassFunction) Given an invariant ring `IR`, an integer `d` and an irreducible character `chi`, return an iterator over a basis for the semi-invariants (or relative invariants) @@ -337,9 +337,9 @@ julia> collect(B) ``` """ -iterate_basis(R::InvRing, d::Int, chi::GAPGroupClassFunction) = iterate_basis_reynolds(R, d, chi) +iterate_basis(R::FinGroupInvarRing, d::Int, chi::GAPGroupClassFunction) = iterate_basis_reynolds(R, d, chi) -function iterate_basis_reynolds(R::InvRing, d::Int, chi::Union{GAPGroupClassFunction, Nothing} = nothing) +function iterate_basis_reynolds(R::FinGroupInvarRing, d::Int, chi::Union{GAPGroupClassFunction, Nothing} = nothing) @assert !is_modular(R) @assert d >= 0 "Degree must be non-negative" if chi !== nothing @@ -358,11 +358,11 @@ function iterate_basis_reynolds(R::InvRing, d::Int, chi::Union{GAPGroupClassFunc N = zero_matrix(base_ring(polynomial_ring(R)), 0, 0) - return InvRingBasisIterator{typeof(R), typeof(reynolds), typeof(monomials), eltype(monomials), typeof(N)}(R, d, k, true, reynolds, monomials, Vector{eltype(monomials)}(), N) + return FinGroupInvarRingBasisIterator{typeof(R), typeof(reynolds), typeof(monomials), eltype(monomials), typeof(N)}(R, d, k, true, reynolds, monomials, Vector{eltype(monomials)}(), N) end # Sadly, we can't really do much iteratively here. -function iterate_basis_linear_algebra(IR::InvRing, d::Int) +function iterate_basis_linear_algebra(IR::FinGroupInvarRing, d::Int) @assert d >= 0 "Degree must be non-negative" R = polynomial_ring(IR) @@ -372,7 +372,7 @@ function iterate_basis_linear_algebra(IR::InvRing, d::Int) N = zero_matrix(base_ring(R), 0, 0) mons = elem_type(R)[] dummy_mons = monomials_of_degree(R, 0) - return InvRingBasisIterator{typeof(IR), Nothing, typeof(dummy_mons), eltype(mons), typeof(N)}(IR, d, k, false, nothing, dummy_mons, mons, N) + return FinGroupInvarRingBasisIterator{typeof(IR), Nothing, typeof(dummy_mons), eltype(mons), typeof(N)}(IR, d, k, false, nothing, dummy_mons, mons, N) end mons_iterator = monomials_of_degree(R, d) @@ -380,7 +380,7 @@ function iterate_basis_linear_algebra(IR::InvRing, d::Int) if d == 0 N = identity_matrix(base_ring(R), 1) dummy_mons = monomials_of_degree(R, 0) - return InvRingBasisIterator{typeof(IR), Nothing, typeof(mons_iterator), eltype(mons), typeof(N)}(IR, d, k, false, nothing, mons_iterator, mons, N) + return FinGroupInvarRingBasisIterator{typeof(IR), Nothing, typeof(mons_iterator), eltype(mons), typeof(N)}(IR, d, k, false, nothing, mons_iterator, mons, N) end mons_to_rows = Dict{elem_type(R), Int}(mons .=> 1:length(mons)) @@ -412,14 +412,14 @@ function iterate_basis_linear_algebra(IR::InvRing, d::Int) end N = kernel(M, side = :right) - return InvRingBasisIterator{typeof(IR), Nothing, typeof(mons_iterator), eltype(mons), typeof(N)}(IR, d, ncols(N), false, nothing, mons_iterator, mons, N) + return FinGroupInvarRingBasisIterator{typeof(IR), Nothing, typeof(mons_iterator), eltype(mons), typeof(N)}(IR, d, ncols(N), false, nothing, mons_iterator, mons, N) end -Base.eltype(BI::InvRingBasisIterator) = elem_type(polynomial_ring(BI.R)) +Base.eltype(BI::FinGroupInvarRingBasisIterator) = elem_type(polynomial_ring(BI.R)) -Base.length(BI::InvRingBasisIterator) = BI.dim +Base.length(BI::FinGroupInvarRingBasisIterator) = BI.dim -function Base.show(io::IO, ::MIME"text/plain", BI::InvRingBasisIterator) +function Base.show(io::IO, ::MIME"text/plain", BI::FinGroupInvarRingBasisIterator) io = pretty(io) println(io, "Iterator over a basis of the component of degree $(BI.degree)") print(io, Indent(), "of ", Lowercase(), BI.R, Dedent()) @@ -429,7 +429,7 @@ function Base.show(io::IO, ::MIME"text/plain", BI::InvRingBasisIterator) end end -function Base.show(io::IO, BI::InvRingBasisIterator) +function Base.show(io::IO, BI::FinGroupInvarRingBasisIterator) if get(io, :supercompact, false) print(io, "Iterator") else @@ -439,21 +439,21 @@ function Base.show(io::IO, BI::InvRingBasisIterator) end end -function Base.iterate(BI::InvRingBasisIterator) +function Base.iterate(BI::FinGroupInvarRingBasisIterator) if BI.reynolds return iterate_reynolds(BI) end return iterate_linear_algebra(BI) end -function Base.iterate(BI::InvRingBasisIterator, state) +function Base.iterate(BI::FinGroupInvarRingBasisIterator, state) if BI.reynolds return iterate_reynolds(BI, state) end return iterate_linear_algebra(BI, state) end -function iterate_reynolds(BI::InvRingBasisIterator) +function iterate_reynolds(BI::FinGroupInvarRingBasisIterator) @assert BI.reynolds if BI.dim == 0 return nothing @@ -484,7 +484,7 @@ function iterate_reynolds(BI::InvRingBasisIterator) end end -function iterate_reynolds(BI::InvRingBasisIterator, state) +function iterate_reynolds(BI::FinGroupInvarRingBasisIterator, state) @assert BI.reynolds B = state[1] @@ -518,7 +518,7 @@ function iterate_reynolds(BI::InvRingBasisIterator, state) end end -function iterate_linear_algebra(BI::InvRingBasisIterator) +function iterate_linear_algebra(BI::FinGroupInvarRingBasisIterator) @assert !BI.reynolds if BI.dim == 0 return nothing @@ -540,7 +540,7 @@ function iterate_linear_algebra(BI::InvRingBasisIterator) return inv(AbstractAlgebra.leading_coefficient(f))*f, 2 end -function iterate_linear_algebra(BI::InvRingBasisIterator, state::Int) +function iterate_linear_algebra(BI::FinGroupInvarRingBasisIterator, state::Int) @assert !BI.reynolds if state > BI.dim return nothing diff --git a/src/InvariantTheory/primary_invariants.jl b/src/InvariantTheory/primary_invariants.jl index bac9a6cb186f..95df0f9447d4 100644 --- a/src/InvariantTheory/primary_invariants.jl +++ b/src/InvariantTheory/primary_invariants.jl @@ -4,7 +4,7 @@ # coefficients respectively non-negative integer coefficients in the non-modular # case. # See DK15, pp. 94, 95. -function test_primary_degrees_via_hilbert_series(R::InvRing, degrees::Vector{Int}) +function test_primary_degrees_via_hilbert_series(R::FinGroupInvarRing, degrees::Vector{Int}) fl, h = _reduce_hilbert_series_by_primary_degrees(R, degrees) if !fl return false @@ -20,13 +20,13 @@ function test_primary_degrees_via_hilbert_series(R::InvRing, degrees::Vector{Int return true end -function reduce_hilbert_series_by_primary_degrees(R::InvRing, chi::Union{GAPGroupClassFunction, Nothing} = nothing) +function reduce_hilbert_series_by_primary_degrees(R::FinGroupInvarRing, chi::Union{GAPGroupClassFunction, Nothing} = nothing) fl, h = _reduce_hilbert_series_by_primary_degrees(R, [ total_degree(forget_grading(f)) for f in primary_invariants(R) ], chi) @assert fl return h end -function _reduce_hilbert_series_by_primary_degrees(R::InvRing, degrees::Vector{Int}, chi::Union{GAPGroupClassFunction, Nothing} = nothing) +function _reduce_hilbert_series_by_primary_degrees(R::FinGroupInvarRing, degrees::Vector{Int}, chi::Union{GAPGroupClassFunction, Nothing} = nothing) mol = molien_series(R, chi) f = numerator(mol) g = denominator(mol) @@ -40,7 +40,7 @@ end # Return possible degrees of primary invariants d_1, ..., d_n with # d_1 \cdots d_n == k*|G|, where G = group(R). # (Note that |G| must divide d_1 \cdots d_n, see DK15, Prop. 3.5.5.) -function candidates_primary_degrees(R::InvRing, k::Int, bad_prefixes::Vector{Vector{Int}} = Vector{Vector{Int}}()) +function candidates_primary_degrees(R::FinGroupInvarRing, k::Int, bad_prefixes::Vector{Vector{Int}} = Vector{Vector{Int}}()) factors = MSet{Int}() for n in [ k, order(group(R)) ] @@ -112,7 +112,7 @@ end # RG/< invars, f_1, ..., f_k > has Krull dimension n - k, where n == length(invars). # If the base field is finite, the answer "true" might be wrong (for theoretical reasons). # See Kem99, Theorem 2. -function check_primary_degrees(RG::InvRing{FldT, GrpT, PolyRingElemT}, degrees::Vector{Int}, invars::Vector{PolyRingElemT}, k::Int, iters::Dict{Int, <: VectorSpaceIterator}, ideals::Dict{Set{PolyRingElemT}, Tuple{MPolyIdeal{PolyRingElemT}, Int}}) where {FldT, GrpT, PolyRingElemT} +function check_primary_degrees(RG::FinGroupInvarRing{FldT, GrpT, PolyRingElemT}, degrees::Vector{Int}, invars::Vector{PolyRingElemT}, k::Int, iters::Dict{Int, <: VectorSpaceIterator}, ideals::Dict{Set{PolyRingElemT}, Tuple{MPolyIdeal{PolyRingElemT}, Int}}) where {FldT, GrpT, PolyRingElemT} R = polynomial_ring(RG) n = length(degrees) @@ -141,7 +141,7 @@ function check_primary_degrees(RG::InvRing{FldT, GrpT, PolyRingElemT}, degrees:: return true end -function _primary_invariants_via_optimal_hsop(RG::InvRing; ensure_minimality::Int = 0, degree_bound::Int = 1, primary_degrees::Vector{Int} = Int[]) +function _primary_invariants_via_optimal_hsop(RG::FinGroupInvarRing; ensure_minimality::Int = 0, degree_bound::Int = 1, primary_degrees::Vector{Int} = Int[]) iters = Dict{Int, VectorSpaceIterator}() ideals = Dict{Set{elem_type(polynomial_ring(RG))}, Tuple{MPolyIdeal{elem_type(polynomial_ring(RG))}, Int}}() @@ -174,7 +174,7 @@ end # b == true iff primary invariants of the given degrees exist. In this case # invars_cache will contain those invariants. # k is only needed for recursive calls of the function. -function primary_invariants_via_optimal_hsop!(RG::InvRing{FldT, GrpT, PolyRingElemT}, degrees::Vector{Int}, invars_cache::PrimaryInvarsCache{PolyRingElemT}, iters::Dict{Int, <: VectorSpaceIterator}, ideals::Dict{Set{PolyRingElemT}, Tuple{MPolyIdeal{PolyRingElemT}, Int}}, ensure_minimality::Int = 0, k::Int = 0) where {FldT, GrpT, PolyRingElemT} +function primary_invariants_via_optimal_hsop!(RG::FinGroupInvarRing{FldT, GrpT, PolyRingElemT}, degrees::Vector{Int}, invars_cache::PrimaryInvarsCache{PolyRingElemT}, iters::Dict{Int, <: VectorSpaceIterator}, ideals::Dict{Set{PolyRingElemT}, Tuple{MPolyIdeal{PolyRingElemT}, Int}}, ensure_minimality::Int = 0, k::Int = 0) where {FldT, GrpT, PolyRingElemT} n = length(degrees) - length(invars_cache.invars) R = polynomial_ring(RG) @@ -235,7 +235,7 @@ function primary_invariants_via_optimal_hsop!(RG::InvRing{FldT, GrpT, PolyRingEl end @doc raw""" - primary_invariants(IR::InvRing; + primary_invariants(IR::FinGroupInvarRing; ensure_minimality::Int = 0, degree_bound::Int = 1, primary_degrees::Vector{Int} = Int[]) @@ -292,7 +292,7 @@ julia> primary_invariants(IR, primary_degrees = [ 3, 6, 6 ]) ``` """ -function primary_invariants(RG::InvRing; ensure_minimality::Int = 0, degree_bound::Int = 1, primary_degrees::Vector{Int} = Int[]) +function primary_invariants(RG::FinGroupInvarRing; ensure_minimality::Int = 0, degree_bound::Int = 1, primary_degrees::Vector{Int} = Int[]) if !isdefined(RG, :primary) RG.primary = _primary_invariants_via_optimal_hsop(RG; ensure_minimality = ensure_minimality, degree_bound = degree_bound, primary_degrees = primary_degrees) end @@ -300,7 +300,7 @@ function primary_invariants(RG::InvRing; ensure_minimality::Int = 0, degree_boun end # Access the (possibly) cached ideal generated by the primary invariants -function ideal_of_primary_invariants(RG::InvRing) +function ideal_of_primary_invariants(RG::FinGroupInvarRing) _ = primary_invariants(RG) if !isdefined(RG.primary, :ideal) RG.primary.ideal = ideal(polynomial_ring(RG), RG.primary.invars) diff --git a/src/InvariantTheory/secondary_invariants.jl b/src/InvariantTheory/secondary_invariants.jl index 0dd33251bcd4..a20152519d3e 100644 --- a/src/InvariantTheory/secondary_invariants.jl +++ b/src/InvariantTheory/secondary_invariants.jl @@ -17,7 +17,7 @@ end ################################################################################ # DK15, Algorithm 3.7.5 -function secondary_invariants_modular(RG::InvRing) +function secondary_invariants_modular(RG::FinGroupInvarRing) Rgraded = polynomial_ring(RG) # We have to compute a lot with these polynomials and the grading only # gets in the way (one cannot ask for total_degree and even if one could @@ -154,7 +154,7 @@ end ################################################################################ # DK15, Algorithm 3.7.2 and Kin07, Section 4 "Improved new algorithm" -function secondary_invariants_nonmodular(RG::InvRing) +function secondary_invariants_nonmodular(RG::FinGroupInvarRing) @assert !is_modular(RG) Rext = polynomial_ring(RG) Rgraded = _internal_polynomial_ring(RG) @@ -286,7 +286,7 @@ end # ################################################################################ -function _secondary_invariants(IR::InvRing) +function _secondary_invariants(IR::FinGroupInvarRing) if isdefined(IR, :secondary) return nothing end @@ -299,7 +299,7 @@ function _secondary_invariants(IR::InvRing) end @doc raw""" - secondary_invariants(IR::InvRing) + secondary_invariants(IR::FinGroupInvarRing) Return a system of secondary invariants for `IR` as a `Vector` sorted by increasing degree. The result is cached, so calling this function again @@ -332,13 +332,13 @@ julia> secondary_invariants(IR) x[1]^3*x[2]^6 + x[1]^6*x[3]^3 + x[2]^3*x[3]^6 ``` """ -function secondary_invariants(IR::InvRing) +function secondary_invariants(IR::FinGroupInvarRing) _secondary_invariants(IR) return copy(IR.secondary.invars) end @doc raw""" - irreducible_secondary_invariants(IR::InvRing) + irreducible_secondary_invariants(IR::FinGroupInvarRing) Return a system of irreducible secondary invariants for `IR` as a `Vector` sorted by increasing degree. The result is cached, so calling this function again will @@ -387,7 +387,7 @@ julia> irreducible_secondary_invariants(IR) x[3]*x[4]^2 + x[3]^2*x[5] + x[4]*x[5]^2 ``` """ -function irreducible_secondary_invariants(IR::InvRing) +function irreducible_secondary_invariants(IR::FinGroupInvarRing) _secondary_invariants(IR) is_invars = elem_type(polynomial_ring(IR))[] for i = 1:length(IR.secondary.invars) @@ -404,8 +404,8 @@ end # Gat96, Algorithm 3.16 and DK15, Algorithm 3.7.2 @doc raw""" - semi_invariants(IR::InvRing, chi::GAPGroupClassFunction) - relative_invariants(IR::InvRing, chi::GAPGroupClassFunction) + semi_invariants(IR::FinGroupInvarRing, chi::GAPGroupClassFunction) + relative_invariants(IR::FinGroupInvarRing, chi::GAPGroupClassFunction) Given an irreducible character `chi` of the underlying group, return a system of semi-invariants (or relative invariants) with respect to `chi`. @@ -436,7 +436,7 @@ julia> semi_invariants(RS2, chi) ``` """ -function semi_invariants(RG::InvRing, chi::GAPGroupClassFunction) +function semi_invariants(RG::FinGroupInvarRing, chi::GAPGroupClassFunction) @assert is_zero(characteristic(coefficient_ring(RG))) @assert is_irreducible(chi) @@ -494,4 +494,4 @@ function semi_invariants(RG::InvRing, chi::GAPGroupClassFunction) return semi_invars end -relative_invariants(RG::InvRing, chi::GAPGroupClassFunction) = semi_invariants(RG, chi) +relative_invariants(RG::FinGroupInvarRing, chi::GAPGroupClassFunction) = semi_invariants(RG, chi) diff --git a/src/InvariantTheory/types.jl b/src/InvariantTheory/types.jl index c300cff9853f..31b11e816481 100644 --- a/src/InvariantTheory/types.jl +++ b/src/InvariantTheory/types.jl @@ -49,7 +49,7 @@ mutable struct FundamentalInvarsCache{PolyRingElemT, PolyRingT} end end -mutable struct InvRing{FldT, GrpT, PolyRingElemT, PolyRingT, ActionT} +mutable struct FinGroupInvarRing{FldT, GrpT, PolyRingElemT, PolyRingT, ActionT} field::FldT poly_ring::PolyRingT @@ -75,15 +75,15 @@ mutable struct InvRing{FldT, GrpT, PolyRingElemT, PolyRingT, ActionT} molien_series::Generic.FracFieldElem{QQPolyRingElem} - function InvRing(K::FldT, G::GrpT, action::Vector{ActionT}) where {FldT <: Field, GrpT <: AbstractAlgebra.Group, ActionT} + function FinGroupInvarRing(K::FldT, G::GrpT, action::Vector{ActionT}) where {FldT <: Field, GrpT <: AbstractAlgebra.Group, ActionT} n = degree(G) # We want to use divrem w.r.t. degrevlex for the computation of secondary # invariants and fundamental invariants R, = graded_polynomial_ring(K, "x" => 1:n, cached = false, internal_ordering = :degrevlex) - return InvRing(K, G, action, R) + return FinGroupInvarRing(K, G, action, R) end - function InvRing(K::FldT, G::GrpT, action::Vector{ActionT}, poly_ring::PolyRingT) where {FldT <: Field, GrpT <: AbstractAlgebra.Group, ActionT, PolyRingT <: MPolyDecRing} + function FinGroupInvarRing(K::FldT, G::GrpT, action::Vector{ActionT}, poly_ring::PolyRingT) where {FldT <: Field, GrpT <: AbstractAlgebra.Group, ActionT, PolyRingT <: MPolyDecRing} @assert coefficient_ring(poly_ring) === K @assert ngens(poly_ring) == degree(G) @@ -142,8 +142,8 @@ struct AllMonomials{PolyRingT} end end -struct InvRingBasisIterator{InvRingT, ReynoldsT, IteratorT, PolyRingElemT, MatrixT} - R::InvRingT +struct FinGroupInvarRingBasisIterator{FinGroupInvarRingT, ReynoldsT, IteratorT, PolyRingElemT, MatrixT} + R::FinGroupInvarRingT degree::Int dim::Int reynolds::Bool