Invariants of Finite Groups
In this section, with notation as in the introduction to this chapter, $G$ will be a finite group.
The ssumption that $G$ is finite implies:
By a result of Emmy Noether, $K[V]$ is integral over $K[V]^G$. In particular,
$\; \; \; \; \; \dim K[V]^G = \dim K[V] = n.$
Moreover, $K[V]^G$ is finitely generated as a $K$-algebra.
If the group order $|G|$ is invertible in $K$, then we have the explicit Reynolds operator
\[\; \; \; \; \; \mathcal R: K[V] \to K[V], f\mapsto \frac{1}{|G|}\sum_{\pi\in G}(f \;\! . \;\! \pi).\]
We speak of non-modular invariant theory if $|G|$ is invertible in $K$, and of modular invariant theory otherwise.
In the non-modular case, using Emmy Noether's result and the Reynolds operator, it is not too difficult to show that $K[V]^G$ is a free module over any of its graded Noether normalizations. That is, $K[V]^G$ is Cohen-Macaulay. In the modular case, $K[V]^G$ may not be Cohen-Macaulay.
Knowing the Hilbert series means to know the dimension of each graded piece $K[V]^G_d$. This information can often be used to speed up algorithms for finding invariants. The most basic task here is to compute the invariants of some given degree $d$, that is, to find an explicit $K$-basis of $K[V]^G_d$. There are two different approaches:
- The Reynolds Operator Method, available in the non-modular case, applies the Reynolds operator to sufficiently many monomials in $K[x_1, \dots, x_n]_d\cong K[V]_d$, and extracts a $K$-basis from the resulting generating set.
- The Linear Algebra Method, available in the non-modular and the modular case, finds the elements of a $K$-basis all at once by setting up and solving an appropriate $K$-linear system of equations.
These methods are, in particular, crucial to the computation of primary and secondary invariants. Primary invariants and irreducible secondary invariants together generate $K[V]^G$ as a $K$-algebra. Omitting redundant generators yields a system of fundamental invariants. In the non-modular case, an alternative and typically more effective way to compute generators of $K[V]^G$ is King's algorithm which finds a system of fundamental invariants directly, without computing primary and secondary invariants. See [Kin13].
We discuss the relevant OSCAR functionality below.
Creating Invariant Rings
How Finite Groups are Given
The invariant theory part of OSCAR distinguishes two ways of how finite groups and their actions on $K[x_1, \dots, x_n]\cong K[V]$ are specified:
Matrix Groups
Here, $G$ will be explicitly given as a matrix group $G\subset \text{GL}_n(K)\cong \text{GL}(V) $ by (finitely many) generating matrices, acting on $K[x_1, \dots, x_n]\cong K[V]$ by linear substitution:
\[(f \;\! . \;\! \pi) (x_1, \dots, x_n) = f((x_1, \dots, x_n) \cdot \rho(\pi)) \text{ for all } \pi\in G.\]
Permutation Groups
Here, $G$ will be given as a permutation group, acting on $K[x_1, \dots, x_n]\cong K[V]$ by permuting the variables.
Constructors for Invariant Rings
invariant_ring
— Methodinvariant_ring(G::MatrixGroup)
invariant_ring(K::Field = QQ, G::PermGroup)
invariant_ring(R::MPolyDecRing, G::MatrixGroup)
invariant_ring(R::MPolyDecRing, G::PermGroup)
Return the invariant ring of the finite matrix group or permutation group G
.
In the latter case, use the specified field K
as the coefficient field. The default value for K
is QQ
.
The polynomial ring R
on which G
acts can be supplied as a first argument, in case an existing ring should be used.
The creation of invariant rings is lazy in the sense that no explicit computations are done until specifically invoked (for example, by the primary_invariants
function).
Examples
julia> K, a = cyclotomic_field(3, "a");
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0]);
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1]);
julia> G = matrix_group(M1, M2);
julia> IRm = invariant_ring(G)
Invariant ring
of matrix group of degree 3 over K
julia> IRp = invariant_ring(symmetric_group(3))
Invariant ring
of Sym(3)
julia> coefficient_ring(IRp)
Rational field
Basic Data Associated to Invariant Rings
If IR
is the invariant ring $K[x_1,..., x_n]^G$ of a finite matrix group $G$, then
group(IR)
refers to $G$,coefficient_ring(IR)
to $K$, andpolynomial_ring(IR)
to $K[x_1,..., x_n]$.
Moreover, is_modular(IR)
returns true
in the modular case, and false
otherwise.
Examples
julia> K, a = cyclotomic_field(3, "a")
(Cyclotomic field of order 3, a)
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0])
[0 0 1]
[1 0 0]
[0 1 0]
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1])
[1 0 0]
[0 a 0]
[0 0 -a - 1]
julia> G = matrix_group(M1, M2)
Matrix group of degree 3
over cyclotomic field of order 3
julia> IR = invariant_ring(G)
Invariant ring
of matrix group of degree 3 over K
julia> group(IR)
Matrix group of degree 3
over cyclotomic field of order 3
julia> coefficient_ring(IR)
Number field with defining polynomial _$^2 + _$ + 1
over rational field
julia> R = polynomial_ring(IR)
Multivariate polynomial ring in 3 variables over K graded by
x[1] -> [1]
x[2] -> [1]
x[3] -> [1]
julia> x = gens(R)
3-element Vector{MPolyDecRingElem{AbsSimpleNumFieldElem, AbstractAlgebra.Generic.MPoly{AbsSimpleNumFieldElem}}}:
x[1]
x[2]
x[3]
julia> is_modular(IR)
false
The Reynolds Operator
reynolds_operator
— Methodreynolds_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
.
Examples
julia> K, a = cyclotomic_field(3, "a")
(Cyclotomic field of order 3, a)
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0])
[0 0 1]
[1 0 0]
[0 1 0]
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1])
[1 0 0]
[0 a 0]
[0 0 -a - 1]
julia> G = matrix_group(M1, M2)
Matrix group of degree 3
over cyclotomic field of order 3
julia> IR = invariant_ring(G)
Invariant ring
of matrix group of degree 3 over K
julia> R = polynomial_ring(IR)
Multivariate polynomial ring in 3 variables over K graded by
x[1] -> [1]
x[2] -> [1]
x[3] -> [1]
julia> x = gens(R)
3-element Vector{MPolyDecRingElem{AbsSimpleNumFieldElem, AbstractAlgebra.Generic.MPoly{AbsSimpleNumFieldElem}}}:
x[1]
x[2]
x[3]
julia> f = x[1]^3
x[1]^3
julia> reynolds_operator(IR, f)
1//3*x[1]^3 + 1//3*x[2]^3 + 1//3*x[3]^3
julia> M = matrix(GF(3), [0 1 0; -1 0 0; 0 0 -1])
[0 1 0]
[2 0 0]
[0 0 2]
julia> G = matrix_group(M)
Matrix group of degree 3
over prime field of characteristic 3
julia> IR = invariant_ring(G)
Invariant ring
of matrix group of degree 3 over GF(3)
julia> R = polynomial_ring(IR)
Multivariate polynomial ring in 3 variables over GF(3) graded by
x[1] -> [1]
x[2] -> [1]
x[3] -> [1]
julia> x = gens(R)
3-element Vector{MPolyDecRingElem{FqFieldElem, FqMPolyRingElem}}:
x[1]
x[2]
x[3]
julia> f = x[1]^2
x[1]^2
julia> reynolds_operator(IR, f)
2*x[1]^2 + 2*x[2]^2
julia> f = x[1]^3
x[1]^3
julia> reynolds_operator(IR, f)
0
reynolds_operator
— Methodreynolds_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 Reynolds operator projecting onto the isotypic component of the polynomial ring with respect to chi
, that is, the semi-invariants (or relative invariants) with respect to chi
, see [Sta79]. It is assumed that chi
is an irreducible character.
In case chi
is a linear character, the returned polynomial, say h
, fulfils h^g = chi(g)h
for all g
in group(IR)
(possibly h
is zero).
If coefficient_ring(IR)
does not contain all character values of chi
, an error is raised.
Examples
julia> K, a = cyclotomic_field(3, "a");
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0]);
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1]);
julia> G = matrix_group(M1, M2);
julia> IR = invariant_ring(G);
julia> R = polynomial_ring(IR);
julia> x = gens(R);
julia> f = x[1]^3
x[1]^3
julia> reynolds_operator(IR, f, trivial_character(G))
1//3*x[1]^3 + 1//3*x[2]^3 + 1//3*x[3]^3
julia> S2 = symmetric_group(2);
julia> IR = invariant_ring(QQ, S2);
julia> R = polynomial_ring(IR);
julia> x = gens(R);
julia> F = abelian_closure(QQ)[1];
julia> chi = Oscar.class_function(S2, [ F(sign(representative(c))) for c in conjugacy_classes(S2) ])
class_function(character table of S2, [1, -1])
julia> reynolds_operator(IR, x[1], chi)
1//2*x[1] - 1//2*x[2]
Invariants of a Given Degree
basis
— Functionbasis(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
.
The optional argument algorithm
specifies the algorithm to be used. If algorithm = :reynolds
, the Reynolds operator is utilized (this method is only available in the non-modular case). Setting algorithm = :linear_algebra
means that plain linear algebra is used. The default option algorithm = :default
asks to select the heuristically best algorithm.
See also iterate_basis
.
Examples
julia> K, a = cyclotomic_field(3, "a")
(Cyclotomic field of order 3, a)
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0])
[0 0 1]
[1 0 0]
[0 1 0]
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1])
[1 0 0]
[0 a 0]
[0 0 -a - 1]
julia> G = matrix_group(M1, M2)
Matrix group of degree 3
over cyclotomic field of order 3
julia> IR = invariant_ring(G)
Invariant ring
of matrix group of degree 3 over K
julia> basis(IR, 6)
4-element Vector{MPolyDecRingElem{AbsSimpleNumFieldElem, AbstractAlgebra.Generic.MPoly{AbsSimpleNumFieldElem}}}:
x[1]^2*x[2]^2*x[3]^2
x[1]^4*x[2]*x[3] + x[1]*x[2]^4*x[3] + x[1]*x[2]*x[3]^4
x[1]^3*x[2]^3 + x[1]^3*x[3]^3 + x[2]^3*x[3]^3
x[1]^6 + x[2]^6 + x[3]^6
julia> M = matrix(GF(3), [0 1 0; -1 0 0; 0 0 -1])
[0 1 0]
[2 0 0]
[0 0 2]
julia> G = matrix_group(M)
Matrix group of degree 3
over prime field of characteristic 3
julia> IR = invariant_ring(G)
Invariant ring
of matrix group of degree 3 over GF(3)
julia> basis(IR, 2)
2-element Vector{MPolyDecRingElem{FqFieldElem, FqMPolyRingElem}}:
x[1]^2 + x[2]^2
x[3]^2
julia> basis(IR, 3)
2-element Vector{MPolyDecRingElem{FqFieldElem, FqMPolyRingElem}}:
x[1]*x[2]*x[3]
x[1]^2*x[3] + 2*x[2]^2*x[3]
basis
— Methodbasis(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
with respect to chi
.
This function is only implemented in the case of characteristic zero.
If coefficient_ring(IR)
does not contain all character values of chi
, an error is raised.
See also iterate_basis
.
Examples
julia> K, a = cyclotomic_field(3, "a");
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0]);
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1]);
julia> G = matrix_group(M1, M2);
julia> IR = invariant_ring(G);
julia> basis(IR, 6, trivial_character(G))
4-element Vector{MPolyDecRingElem{AbsSimpleNumFieldElem, AbstractAlgebra.Generic.MPoly{AbsSimpleNumFieldElem}}}:
x[1]^6 + x[2]^6 + x[3]^6
x[1]^4*x[2]*x[3] + x[1]*x[2]^4*x[3] + x[1]*x[2]*x[3]^4
x[1]^3*x[2]^3 + x[1]^3*x[3]^3 + x[2]^3*x[3]^3
x[1]^2*x[2]^2*x[3]^2
julia> S2 = symmetric_group(2);
julia> R = invariant_ring(QQ, S2);
julia> F = abelian_closure(QQ)[1];
julia> chi = Oscar.class_function(S2, [ F(sign(representative(c))) for c in conjugacy_classes(S2) ])
class_function(character table of group Sym( [ 1 .. 2 ] ), [1, -1])
julia> basis(R, 3, chi)
2-element Vector{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}:
x[1]^3 - x[2]^3
x[1]^2*x[2] - x[1]*x[2]^2
iterate_basis
— Functioniterate_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
.
The optional argument algorithm
specifies the algorithm to be used. If algorithm = :reynolds
, the Reynolds operator is utilized (this method is only available in the non-modular case). Setting algorithm = :linear_algebra
means that plain linear algebra is used. The default option algorithm = :default
asks to select the heuristically best algorithm.
When using the Reynolds operator, the basis is constructed element-by-element. With linear algebra, this is not possible and the basis will be constructed all at once when calling the function.
See also basis
.
Examples
julia> K, a = cyclotomic_field(3, "a")
(Cyclotomic field of order 3, a)
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0])
[0 0 1]
[1 0 0]
[0 1 0]
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1])
[1 0 0]
[0 a 0]
[0 0 -a - 1]
julia> G = matrix_group(M1, M2)
Matrix group of degree 3
over cyclotomic field of order 3
julia> IR = invariant_ring(G)
Invariant ring
of matrix group of degree 3 over K
julia> B = iterate_basis(IR, 6)
Iterator over a basis of the component of degree 6
of invariant ring of G
julia> collect(B)
4-element Vector{MPolyDecRingElem{AbsSimpleNumFieldElem, AbstractAlgebra.Generic.MPoly{AbsSimpleNumFieldElem}}}:
x[1]^2*x[2]^2*x[3]^2
x[1]^4*x[2]*x[3] + x[1]*x[2]^4*x[3] + x[1]*x[2]*x[3]^4
x[1]^3*x[2]^3 + x[1]^3*x[3]^3 + x[2]^3*x[3]^3
x[1]^6 + x[2]^6 + x[3]^6
julia> M = matrix(GF(3), [0 1 0; -1 0 0; 0 0 -1])
[0 1 0]
[2 0 0]
[0 0 2]
julia> G = matrix_group(M)
Matrix group of degree 3
over prime field of characteristic 3
julia> IR = invariant_ring(G)
Invariant ring
of matrix group of degree 3 over GF(3)
julia> B = iterate_basis(IR, 2)
Iterator over a basis of the component of degree 2
of invariant ring of G
julia> collect(B)
2-element Vector{MPolyDecRingElem{FqFieldElem, FqMPolyRingElem}}:
x[1]^2 + x[2]^2
x[3]^2
iterate_basis
— Methoditerate_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) in degree d
with respect to chi
.
This function is only implemented in the case of characteristic zero.
If coefficient_ring(IR)
does not contain all character values of chi
, an error is raised.
See also basis
.
Examples
julia> K, a = cyclotomic_field(3, "a");
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0]);
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1]);
julia> G = matrix_group(M1, M2);
julia> IR = invariant_ring(G);
julia> B = iterate_basis(IR, 6, trivial_character(G))
Iterator over a basis of the component of degree 6
of invariant ring of G
relative to a character
julia> collect(B)
4-element Vector{MPolyDecRingElem{AbsSimpleNumFieldElem, AbstractAlgebra.Generic.MPoly{AbsSimpleNumFieldElem}}}:
x[1]^6 + x[2]^6 + x[3]^6
x[1]^4*x[2]*x[3] + x[1]*x[2]^4*x[3] + x[1]*x[2]*x[3]^4
x[1]^3*x[2]^3 + x[1]^3*x[3]^3 + x[2]^3*x[3]^3
x[1]^2*x[2]^2*x[3]^2
julia> S2 = symmetric_group(2);
julia> R = invariant_ring(QQ, S2);
julia> F = abelian_closure(QQ)[1];
julia> chi = Oscar.class_function(S2, [ F(sign(representative(c))) for c in conjugacy_classes(S2) ])
class_function(character table of S2, [1, -1])
julia> B = iterate_basis(R, 3, chi)
Iterator over a basis of the component of degree 3
of invariant ring of S2
relative to a character
julia> collect(B)
2-element Vector{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}:
x[1]^3 - x[2]^3
x[1]^2*x[2] - x[1]*x[2]^2
The Molien Series
molien_series
— Methodmolien_series([S::PolyRing], I::FinGroupInvarRing, [chi::GAPGroupClassFunction])
In the non-modular case, return the Molien series of I
as a rational function.
If a univariate polynomial ring with rational coefficients is specified by the optional argument S::PolyRing
, then return the Molien series as an element of the fraction field of that ring.
If a character chi
is specified, the series relative to chi
is returned. This is the Molien series of the module of semi-invariants (or relative invariants) with respect to chi
, see [Sta79].
Examples
julia> K, a = cyclotomic_field(3, "a");
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0]);
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1]);
julia> G = matrix_group(M1, M2);
julia> IR = invariant_ring(G);
julia> MS = molien_series(IR)
(-t^6 + t^3 - 1)//(t^9 - 3*t^6 + 3*t^3 - 1)
julia> parent(MS)
Fraction field
of univariate polynomial ring in t over QQ
julia> expand(MS, 10)
1 + 2*t^3 + 4*t^6 + 7*t^9 + O(t^11)
julia> S2 = symmetric_group(2);
julia> IR = invariant_ring(QQ, S2);
julia> F = abelian_closure(QQ)[1];
julia> chi = Oscar.class_function(S2, [ F(sign(representative(c))) for c in conjugacy_classes(S2) ])
class_function(character table of S2, [1, -1])
julia> molien_series(IR)
1//(t^3 - t^2 - t + 1)
julia> molien_series(IR, chi)
t//(t^3 - t^2 - t + 1)
Primary Invariants
primary_invariants
— Methodprimary_invariants(IR::FinGroupInvarRing;
ensure_minimality::Int = 0, degree_bound::Int = 1,
primary_degrees::Vector{Int} = Int[])
Return a system of primary invariants for IR
as a Vector
sorted by increasing degree. The result is cached, so calling this function again with argument IR
will be fast and give the same result.
The primary invariants are computed using the algorithm in [Kem99].
The product of the degrees $d_1,\dots, d_n$ of the returned primary invariants is guaranteed to be minimal among all possible sets of primary invariants.
Expert users (or users happy to experiment) may enter the following keyword arguments to speed up the computation. Note that all of these options are ignored if there are already primary invariants cached. If admissible degrees $d_1,\dots, d_n$ for a system of primary invariants are known a priori, these degrees can be specified by primary_degrees = [d_1, ..., d_n]
. Note that an error is raised if in fact no primary invariants of the given degrees exist. An a priori known number $k \geq 1$ with $d_1\cdots d_n \geq k \cdot |G|$, where $G$ is the underlying group, can be specified by degree_bound = k
. The default value is degree_bound = 1
. In some situations, the runtime of the algorithm might be improved by assigning a positive integer to ensure_minimality
. This leads to an early cancelation of loops in the algorithm and the described minimality of the degrees is not guaranteed anymore. A smaller (positive) value of ensure_minimality
corresponds to an earlier cancelation. However, the default value ensure_minimality = 0
corresponds to no cancelation.
Examples
julia> K, a = cyclotomic_field(3, "a");
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0]);
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1]);
julia> G = matrix_group(M1, M2);
julia> IR = invariant_ring(G);
julia> primary_invariants(IR)
3-element Vector{MPolyDecRingElem{AbsSimpleNumFieldElem, AbstractAlgebra.Generic.MPoly{AbsSimpleNumFieldElem}}}:
x[1]*x[2]*x[3]
x[1]^3 + x[2]^3 + x[3]^3
x[1]^3*x[2]^3 + x[1]^3*x[3]^3 + x[2]^3*x[3]^3
julia> IR = invariant_ring(G); # "New" ring to avoid caching
julia> primary_invariants(IR, primary_degrees = [ 3, 6, 6 ])
3-element Vector{MPolyDecRingElem{AbsSimpleNumFieldElem, AbstractAlgebra.Generic.MPoly{AbsSimpleNumFieldElem}}}:
x[1]*x[2]*x[3]
x[1]^3*x[2]^3 + x[1]^3*x[3]^3 + x[2]^3*x[3]^3
x[1]^6 + x[2]^6 + x[3]^6
Secondary Invariants
secondary_invariants
— Methodsecondary_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 with argument IR
will be fast and give the same result. Note that the secondary invariants are defined with respect to the currently cached system of primary invariants for IR
(if no system of primary invariants for IR
is cached, such a system is computed and cached first).
Implemented Algorithms
For the non-modular case, the function relies on Algorithm 3.7.2 in [DK15], enhanced by ideas from [Kin07]. In the modular case, Algorithm 3.7.5 in [DK15] is used.
Examples
julia> K, a = cyclotomic_field(3, "a");
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0]);
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1]);
julia> G = matrix_group(M1, M2);
julia> IR = invariant_ring(G);
julia> secondary_invariants(IR)
2-element Vector{MPolyDecRingElem{AbsSimpleNumFieldElem, AbstractAlgebra.Generic.MPoly{AbsSimpleNumFieldElem}}}:
1
x[1]^3*x[2]^6 + x[1]^6*x[3]^3 + x[2]^3*x[3]^6
irreducible_secondary_invariants
— Methodirreducible_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 be fast and give the same result. Here, a secondary invariant is called irreducible, if it cannot be written as a polynomial expression in the primary invariants and the other secondary invariants.
Note that the secondary invariants and hence the irreducible secondary invariants are defined with respect to the currently cached system of primary invariants for IR
(if no system of primary invariants for IR
is cached, such a system is computed and cached first).
Examples
julia> M = matrix(QQ, [0 -1 0 0 0; 1 -1 0 0 0; 0 0 0 0 1; 0 0 1 0 0; 0 0 0 1 0]);
julia> G = matrix_group(M);
julia> IR = invariant_ring(G);
julia> secondary_invariants(IR)
12-element Vector{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}:
1
x[1]*x[3] - x[2]*x[3] + x[2]*x[4] - x[1]*x[5]
x[3]^2 + x[4]^2 + x[5]^2
x[1]^3 - 3*x[1]*x[2]^2 + x[2]^3
x[1]^2*x[3] - x[1]*x[2]*x[3] - x[1]*x[2]*x[4] + x[2]^2*x[4] + x[1]*x[2]*x[5]
x[1]*x[3]^2 - x[2]*x[3]^2 + x[2]*x[4]^2 - x[1]*x[5]^2
x[1]^2*x[3] + x[1]^2*x[4] - 2*x[1]*x[2]*x[4] + x[2]^2*x[4] + x[2]^2*x[5]
x[1]*x[3]*x[4] - x[2]*x[3]*x[4] - x[1]*x[3]*x[5] + x[2]*x[4]*x[5]
x[3]*x[4]^2 + x[3]^2*x[5] + x[4]*x[5]^2
x[1]*x[3]^3 - x[2]*x[3]^3 + x[2]*x[3]^2*x[4] + x[1]*x[3]*x[4]^2 - x[2]*x[3]*x[4]^2 + x[2]*x[4]^3 - x[1]*x[3]^2*x[5] - x[1]*x[4]^2*x[5] + x[1]*x[3]*x[5]^2 - x[2]*x[3]*x[5]^2 + x[2]*x[4]*x[5]^2 - x[1]*x[5]^3
x[3]^4 + 2*x[3]^2*x[4]^2 + x[4]^4 + 2*x[3]^2*x[5]^2 + 2*x[4]^2*x[5]^2 + x[5]^4
x[1]*x[3]^5 - x[2]*x[3]^5 + x[2]*x[3]^4*x[4] + 2*x[1]*x[3]^3*x[4]^2 - 2*x[2]*x[3]^3*x[4]^2 + 2*x[2]*x[3]^2*x[4]^3 + x[1]*x[3]*x[4]^4 - x[2]*x[3]*x[4]^4 + x[2]*x[4]^5 - x[1]*x[3]^4*x[5] - 2*x[1]*x[3]^2*x[4]^2*x[5] - x[1]*x[4]^4*x[5] + 2*x[1]*x[3]^3*x[5]^2 - 2*x[2]*x[3]^3*x[5]^2 + 2*x[2]*x[3]^2*x[4]*x[5]^2 + 2*x[1]*x[3]*x[4]^2*x[5]^2 - 2*x[2]*x[3]*x[4]^2*x[5]^2 + 2*x[2]*x[4]^3*x[5]^2 - 2*x[1]*x[3]^2*x[5]^3 - 2*x[1]*x[4]^2*x[5]^3 + x[1]*x[3]*x[5]^4 - x[2]*x[3]*x[5]^4 + x[2]*x[4]*x[5]^4 - x[1]*x[5]^5
julia> irreducible_secondary_invariants(IR)
8-element Vector{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}:
x[1]*x[3] - x[2]*x[3] + x[2]*x[4] - x[1]*x[5]
x[3]^2 + x[4]^2 + x[5]^2
x[1]^3 - 3*x[1]*x[2]^2 + x[2]^3
x[1]^2*x[3] - x[1]*x[2]*x[3] - x[1]*x[2]*x[4] + x[2]^2*x[4] + x[1]*x[2]*x[5]
x[1]*x[3]^2 - x[2]*x[3]^2 + x[2]*x[4]^2 - x[1]*x[5]^2
x[1]^2*x[3] + x[1]^2*x[4] - 2*x[1]*x[2]*x[4] + x[2]^2*x[4] + x[2]^2*x[5]
x[1]*x[3]*x[4] - x[2]*x[3]*x[4] - x[1]*x[3]*x[5] + x[2]*x[4]*x[5]
x[3]*x[4]^2 + x[3]^2*x[5] + x[4]*x[5]^2
module_syzygies
— Methodmodule_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. 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.
Fundamental Systems of Invariants
fundamental_invariants
— Functionfundamental_invariants(IR::FinGroupInvarRing, algorithm::Symbol = :default; beta::Int = 0)
Return a system of fundamental invariants for IR
.
The result is cached, so calling this function again with argument IR
will be fast and give the same result.
Implemented Algorithms
In the non-modular case the function relies on King's algorithm [Kin13] which finds a system of fundamental invariants directly, without computing primary and secondary invariants. If an upper bound for the degrees of fundamental invariants is known, this can be supplied by the keyword argument beta
and might result in an earlier termination of the algorithm. By default, the algorithm uses the bounds from [DH00] and [Sez02].
Alternatively, if specified by algorithm = :primary_and_secondary
, the function computes fundamental invariants from a collection of primary and irreducible secondary invariants. The optional keyword argument beta
is ignored for this algorithm.
In the modular case, only the second method is available for theoretical reasons.
Examples
julia> K, a = cyclotomic_field(3, "a")
(Cyclotomic field of order 3, a)
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0])
[0 0 1]
[1 0 0]
[0 1 0]
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1])
[1 0 0]
[0 a 0]
[0 0 -a - 1]
julia> G = matrix_group(M1, M2)
Matrix group of degree 3
over cyclotomic field of order 3
julia> IR = invariant_ring(G)
Invariant ring
of matrix group of degree 3 over K
julia> fundamental_invariants(IR)
4-element Vector{MPolyDecRingElem{AbsSimpleNumFieldElem, AbstractAlgebra.Generic.MPoly{AbsSimpleNumFieldElem}}}:
x[1]*x[2]*x[3]
x[1]^3 + x[2]^3 + x[3]^3
x[1]^3*x[2]^3 + x[1]^3*x[3]^3 + x[2]^3*x[3]^3
x[1]^3*x[2]^6 + x[1]^6*x[3]^3 + x[2]^3*x[3]^6
Invariant Rings as Affine Algebras
affine_algebra
— Methodaffine_algebra(IR::FinGroupInvarRing;
algo_gens::Symbol = :default, algo_rels::Symbol = :groebner_basis)
Given an invariant ring IR
with underlying graded polynomial ring, say R
, return a graded affine algebra, say A
, together with a graded algebra homomorphism A
$\to$ R
which maps A
isomorphically onto IR
.
If a system of fundamental invariants for IR
is already cached, the function makes use of that system. Otherwise, such a system is computed and cached first. The algebra A
is graded according to the degrees of the fundamental invariants, the modulus of A
is generated by the algebra relations on these invariants, and the algebra homomorphism A
$\to$ R
is defined by sending the i
-th generator of A
to the i
-th fundamental invariant.
Optional arguments
Using the arguments :king
or :primary_and_secondary
for algo_gens
selects the algorithm for the computation of the fundamental invariants (see fundamental_invariants
for details). The argument :groebner_basis
or :linear_algebra
for algo_rels
controls which algorithm for the computation of the relations between the fundamental invariants is used. With :groebner_basis
, the relations are computed via the standard computation of a kernel of a morphism between multivariate polynomial rings. The option :linear_algebra
uses an algorithm by Kemper and Steel [KS99], Section 17.5.5, to compute the relations without the use of Groebner bases. Note that this option is only available, if the fundamental invariants are computed via primary and secondary invariants (i.e. algo_gens = :primary_and_secondary
).
If a presentation of IR
is already computed (and hence cached), this cached presentation will be returned and the values of algo_gens
and algo_rels
will be ignored. Further, if fundamental invariants are already computed and cached, the value of algo_gens
might be ignored, as the cached system is used.
Examples
julia> K, a = cyclotomic_field(3, "a")
(Cyclotomic field of order 3, a)
julia> M1 = matrix(K, [0 0 1; 1 0 0; 0 1 0])
[0 0 1]
[1 0 0]
[0 1 0]
julia> M2 = matrix(K, [1 0 0; 0 a 0; 0 0 -a-1])
[1 0 0]
[0 a 0]
[0 0 -a - 1]
julia> G = matrix_group(M1, M2)
Matrix group of degree 3
over cyclotomic field of order 3
julia> IR = invariant_ring(G)
Invariant ring
of matrix group of degree 3 over K
julia> affine_algebra(IR)
(Quotient of multivariate polynomial ring by ideal (9*y1^6 + y1^3*y2^3 - 6*y1^3*y2*y3 + 3*y1^3*y4 - y2*y3*y4 + y3^3 + y4^2), Hom: quotient of multivariate polynomial ring -> graded multivariate polynomial ring)
Semi-invariants / relative invariants
semi_invariants
— Methodsemi_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
. By this, we mean a set of free generators of the isotypic component of the of the polynomial ring with respect to chi
as a module over the algebra generated by primary invariants for IR
. See also [Gat96] and [Sta79].
If coefficient_ring(IR)
does not contain all character values of chi
, an error is raised.
This function is so far only implemented in the case of characteristic zero.
Examples
julia> S2 = symmetric_group(2);
julia> RS2 = invariant_ring(S2);
julia> F = abelian_closure(QQ)[1];
julia> chi = Oscar.class_function(S2, [ F(sign(representative(c))) for c in conjugacy_classes(S2) ])
class_function(character table of S2, [1, -1])
julia> semi_invariants(RS2, chi)
1-element Vector{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}:
x[1] - x[2]