Structural Computations
Abelian groups support a wide range of structural operations such as
- enumeration of subgroups
- (outer) direct products
- tensor and
homconstructions - free resolutions and general complexes
- (co)-homology and tensor and
hom-functors
snf — Methodsnf(A::GrpAbFinGen) -> GrpAbFinGen, GrpAbFinGenMapReturn a pair $(G, f)$, where $G$ is an abelian group in canonical Smith normal form isomorphic to $A$ and an isomorphism $f : G \to A$.
find_isomorphism — Methodfind_isomorphism(G, op, A::GrpAb) -> Dict, DictGiven an abelian group $A$ and a collection $G$ which is an abelian group with the operation op, this functions returns isomorphisms $G \to A$ and $A \to G$ encoded as dictionaries.
It is assumed that $G$ and $A$ are isomorphic.
Subgroups and Quotients
torsion_subgroup — Methodtorsion_subgroup(G::GrpAbFinGen) -> GrpAbFinGen, MapReturn the torsion subgroup of G.
sub — Methodsub(G::GrpAbFinGen, s::Vector{GrpAbFinGenElem}) -> GrpAbFinGen, GrpAbFinGenMapCreate the subgroup $H$ of $G$ generated by the elements in s together with the injection $\iota : H \to G$.
sub — Methodsub(F::FreeMod{T}, V::Vector{<:FreeModElem{T}}, task::Symbol = :with_morphism) where TGiven a vector V of (homogeneous) elements of F, return the (graded) submodule of F generated by these elements.
Put more precisely, return the submodule as an object of type SubquoModule.
Additionally, if N denotes this object,
- return the inclusion map
N$\to$Fiftask = :with_morphism(default), - return and cache the inclusion map
N$\to$Fiftask = :cache_morphism, - do none of the above if
task = :none.
If task = :only_morphism, return only the inclusion map.
sub(F::FreeMod{T}, A::MatElem{T}, task::Symbol = :with_morphism) where {T}Given a (homogeneous) matrix A, return the (graded) submodule of F generated by the rows of A.
Put more precisely, return this submodule as an object of type SubquoModule.
Additionally, if N denotes this submodule,
- return the inclusion map
N$\to$Fiftask = :with_morphism(default), - return and cache the inclusion map
N$\to$Fiftask = :cache_morphism, - do none of the above if
task = :none.
If task = :only_morphism, return only the inclusion map.
sub(F::FreeMod{T}, O::Vector{<:SubquoModuleElem{T}}, task::Symbol = :with_morphism) where TReturn S as a submodule of F, where S is generated by O. The embedding module of the parent of the elements of O must be F. If task is set to :none or to :module return only S. If task is set to :with_morphism (default option) or to :both return also the canonical injection morphism $S \to F$. If task is set to :cache_morphism the morphism is also cached. If task is set to :only_morphism return only the morphism.
sub(F::FreeMod{T}, s::SubquoModule{T}, task::Symbol = :with_morphism) where TReturn s as a submodule of F, that is the embedding free module of s must be F and s has no relations. If task is set to :none or to :module return only s. If task is set to :with_morphism (default option) or to :both return also the canonical injection morphism $s \to F$. If task is set to :cache_morphism the morphism is also cached. If task is set to :only_morphism return only the morphism.
sub(M::SubquoModule{T}, V::Vector{<:SubquoModuleElem{T}}, task::Symbol = :with_morphism) where TGiven a vector V of (homogeneous) elements of M, return the (graded) submodule of M generated by these elements.
Put more precisely, return this submodule as an object of type SubquoModule.
Additionally, if N denotes this object,
- return the inclusion map
N$\to$Miftask = :with_morphism(default), - return and cache the inclusion map
N$\to$Miftask = :cache_morphism, - do none of the above if
task = :none.
If task = :only_morphism, return only the inclusion map.
sub(M::ModuleFP{T}, V::Vector{<:ModuleFPElem{T}}, task::Symbol = :with_morphism) where TGiven a vector V of (homogeneous) elements of M, return the (graded) submodule of M generated by these elements.
Put more precisely, return this submodule as an object of type SubquoModule.
Additionally, if N denotes this object,
- return the inclusion map
N$\to$Miftask = :with_morphism(default), - return and cache the inclusion map
N$\to$Miftask = :cache_morphism, - do none of the above if
task = :none.
If task = :only_morphism, return only the inclusion map.
Examples
julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = free_module(R, 1);
julia> V = [x^2*F[1]; y^3*F[1]; z^4*F[1]];
julia> N, incl = sub(F, V);
julia> N
Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
represented as subquotient with no relations.
julia> incl
Map with following data
Domain:
=======
Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
represented as subquotient with no relations.
Codomain:
=========
Free module of rank 1 over Multivariate polynomial ring in 3 variables over QQsub(A::SMat, r::UnitRange, c::UnitRange) -> SMatReturn the submatrix of $A$, where the rows correspond to $r$ and the columns correspond to $c$.
sub(s::Vector{GrpAbFinGenElem}) -> GrpAbFinGen, GrpAbFinGenMapAssuming that the non-empty array s contains elements of an abelian group $G$, this functions returns the subgroup $H$ of $G$ generated by the elements in s together with the injection $\iota : H \to G$.
sub — Methodsub(G::GrpAbFinGen, M::ZZMatrix) -> GrpAbFinGen, GrpAbFinGenMapCreate the subgroup $H$ of $G$ generated by the elements corresponding to the rows of $M$ together with the injection $\iota : H \to G$.
sub — Methodsub(G::GrpAbFinGen, n::ZZRingElem) -> GrpAbFinGen, GrpAbFinGenMapCreate the subgroup $n \cdot G$ of $G$ together with the injection $\iota : n\cdot G \to G$.
sub — Methodsub(G::GrpAbFinGen, n::Integer) -> GrpAbFinGen, MapCreate the subgroup $n \cdot G$ of $G$ together with the injection $\iota : n \cdot G \to G$.
psylow_subgroup — Methodpsylow_subgroup(G::GrpAbFinGen, p::IntegerUnion) -> GrpAbFinGen, GrpAbFinGenMapReturn the $p$-Sylow subgroup of G.
has_quotient — Methodhas_quotient(G::GrpAbFinGen, invariant::Vector{Int}) -> BoolGiven an abelian group $G$, return true if it has a quotient with given elementary divisors and false otherwise.
has_complement — Methodhas_complement(f::GrpAbFinGenMap) -> Bool, GrpAbFinGenMap
has_complement(U::GrpAbFinGen, G::GrpAbFinGen) -> Bool, GrpAbFinGenMapGiven a map representing a subgroup of a group $G$, or a subgroup U of a group G, return either true and an injection of a complement in $G$, or false.
See also: is_pure
is_pure — Methodis_pure(U::GrpAbFinGen, G::GrpAbFinGen) -> BoolA subgroup U of G is called pure if for all n an element in U that is in the image of the multiplication by n map of G is also a multiple of an element in U.
For finite abelian groups this is equivalent to U having a complement in G. They are also know as isolated subgroups and serving subgroups.
See also: is_neat, has_complement
EXAMPLES
julia> G = abelian_group([2, 8]);
julia> U, _ = sub(G, [G[1]+2*G[2]]);
julia> is_pure(U, G)
false
julia> U, _ = sub(G, [G[1]+4*G[2]]);
julia> is_pure(U)
true
julia> has_complement(U, G)[1]
trueis_neat — Methodis_neat(U::GrpAbFinGen, G::GrpAbFinGen) -> BoolA subgroup U of G is called neat if for all primes p an element in U that is in the image of the multiplication by p map of G is also a multiple of an element in U.
See also: is_pure
EXAMPLES
julia> G = abelian_group([2, 8]);
julia> U, _ = sub(G, [G[1] + 2*G[2]]);
julia> is_neat(U, G)
true
julia> is_pure(U, G)
falsesaturate — Methodsaturate(U::GrpAbFinGen, G::GrpAbFinGen) -> GrpAbFinGenFor a subgroup U of G find a minimal overgroup that is pure, and thus has a complement.
See also: is_pure, has_complement
A sophisticated algorithm for the enumeration of all (or selected) subgroups of a finite abelian group is available.
psubgroups — Methodpsubgroups(g::GrpAbFinGen, p::Integer;
subtype = :all,
quotype = :all,
index = -1,
order = -1)Return an iterator for the subgroups of $G$ of the specific form. Note that subtype (and quotype) is the type of the subgroup as an abelian $p$-group.
julia> G = abelian_group([6, 12])GrpAb: Z/6 x Z/12julia> shapes = MSet{Vector{ZZRingElem}}()MSet{Vector{ZZRingElem}}()julia> for U = psubgroups(G, 2) push!(shapes, elementary_divisors(U[1])) endjulia> shapesMSet(ZZRingElem[], ZZRingElem[4] : 2, ZZRingElem[2, 4], ZZRingElem[2] : 3, ZZRingElem[2, 2])
So there are $2$ subgroups isomorphic to $C_4$ (ZZRingElem[4] : 2), $1$ isomorphic to $C_2\times C_4$, 1 trivial and $3$ $C_2$ subgroups.
subgroups — Methodsubgroups(g::GrpAbFinGen;
subtype = :all ,
quotype = :all,
index = -1,
order = -1)Return an iterator for the subgroups of $G$ of the specific form.
julia> for U = subgroups(G, subtype = [2]) @show U[1], map(U[2], gens(U[1])) end(U[1], map(U[2], gens(U[1]))) = (GrpAb: Z/2, GrpAbFinGenElem[Element of GrpAb: Z/6 x Z/12 with components [0 6]]) (U[1], map(U[2], gens(U[1]))) = (GrpAb: Z/2, GrpAbFinGenElem[Element of GrpAb: Z/6 x Z/12 with components [3 6]]) (U[1], map(U[2], gens(U[1]))) = (GrpAb: Z/2, GrpAbFinGenElem[Element of GrpAb: Z/6 x Z/12 with components [3 0]])julia> for U = subgroups(G, quotype = [2]) @show U[1], map(U[2], gens(U[1])) end(U[1], map(U[2], gens(U[1]))) = ((General) abelian group with relation matrix [4 0 0; 0 3 0; 0 0 3], GrpAbFinGenElem[Element of GrpAb: Z/6 x Z/12 with components [3 3], Element of GrpAb: Z/6 x Z/12 with components [0 4], Element of GrpAb: Z/6 x Z/12 with components [2 0]]) (U[1], map(U[2], gens(U[1]))) = ((General) abelian group with relation matrix [4 0 0; 0 3 0; 0 0 3], GrpAbFinGenElem[Element of GrpAb: Z/6 x Z/12 with components [0 3], Element of GrpAb: Z/6 x Z/12 with components [0 4], Element of GrpAb: Z/6 x Z/12 with components [2 0]]) (U[1], map(U[2], gens(U[1]))) = ((General) abelian group with relation matrix [2 0 0 0; 0 2 0 0; 0 0 3 0; 0 0 0 3], GrpAbFinGenElem[Element of GrpAb: Z/6 x Z/12 with components [3 6], Element of GrpAb: Z/6 x Z/12 with components [0 6], Element of GrpAb: Z/6 x Z/12 with components [0 4], Element of GrpAb: Z/6 x Z/12 with components [2 0]])
quo — Methodquo(G::GrpAbFinGen, s::Vector{GrpAbFinGenElem}) -> GrpAbFinGen, GrpAbfinGemMapCreate the quotient $H$ of $G$ by the subgroup generated by the elements in $s$, together with the projection $p : G \to H$.
quo — Methodquo(G::GrpAbFinGen, M::ZZMatrix) -> GrpAbFinGen, GrpAbFinGenMapCreate the quotient $H$ of $G$ by the subgroup generated by the elements corresponding to the rows of $M$, together with the projection $p : G \to H$.
quo — Methodquo(G::GrpAbFinGen, n::Integer}) -> GrpAbFinGen, Map
quo(G::GrpAbFinGen, n::ZZRingElem}) -> GrpAbFinGen, MapReturns the quotient $H = G/nG$ together with the projection $p : G \to H$.
quo — Methodquo(G::GrpAbFinGen, n::Integer}) -> GrpAbFinGen, Map
quo(G::GrpAbFinGen, n::ZZRingElem}) -> GrpAbFinGen, MapReturns the quotient $H = G/nG$ together with the projection $p : G \to H$.
quo — Methodquo(G::GrpAbFinGen, U::GrpAbFinGen) -> GrpAbFinGen, MapCreate the quotient $H$ of $G$ by $U$, together with the projection $p : G \to H$.
For 2 subgroups U and V of the same group G, U+V returns the smallest subgroup of G containing both. Similarly, $U\cap V$ computes the intersection and $U \subset V$ tests for inclusion. The difference between issubset = $\subset$ and is_subgroup is that the inclusion map is also returned in the 2nd call.
intersect — Methodintersect(mG::GrpAbFinGenMap, mH::GrpAbFinGenMap) -> GrpAbFinGen, MapGiven two injective maps of abelian groups with the same codomain $G$, return the intersection of the images as a subgroup of $G$.
Direct Products
direct_product — Methoddirect_product(G::GrpAbFinGen...) -> GrpAbFinGen, Vector{GrpAbFinGenMap}Return the direct product $D$ of the (finitely many) abelian groups $G_i$, together with the projections $D \to G_i$.
For finite abelian groups, finite direct sums and finite direct products agree and they are therefore called biproducts. If one wants to obtain $D$ as a direct sum together with the injections $D \to G_i$, one should call direct_sum(G...). If one wants to obtain $D$ as a biproduct together with the projections and the injections, one should call biproduct(G...).
Otherwise, one could also call canonical_injections(D) or canonical_projections(D) later on.
canonical_injection — Methodcanonical_injection(G::GrpAbFinGen, i::Int) -> GrpAbFinGenMapGiven a group $G$ that was created as a direct product, return the injection from the $i$th component.
canonical_projection — Methodcanonical_projection(G::GrpAbFinGen, i::Int) -> GrpAbFinGenMapGiven a group $G$ that was created as a direct product, return the projection onto the $i$th component.
flat — Methodflat(G::GrpAbFinGen) -> GrpAbFinGenMapGiven a group $G$ that is created using (iterated) direct products, or (iterated) tensor products, return a group isomorphism into a flat product: for $G := (A \oplus B) \oplus C$, it returns the isomorphism $G \to A \oplus B \oplus C$ (resp. $\otimes$).
Tensor Producs
tensor_product — Methodtensor_product(G::GrpAbFinGen...; task::Symbol = :map) -> GrpAbFinGen, MapGiven groups $G_i$, compute the tensor product $G_1\otimes \cdots \otimes G_n$. If task is set to ":map", a map $\phi$ is returned that maps tuples in $G_1 \times \cdots \times G_n$ to pure tensors $g_1 \otimes \cdots \otimes g_n$. The map admits a preimage as well.
hom — Methodhom(G::GrpAbFinGen, H::GrpAbFinGen, A::Vector{ <: Map{GrpAbFinGen, GrpAbFinGen}}) -> MapGiven groups $G = G_1 \otimes \cdots \otimes G_n$ and $H = H_1 \otimes \cdot \otimes H_n$ as well as maps $\phi_i: G_i\to H_i$, compute the tensor product of the maps.
Hom-Group
hom — Methodhom(G::GrpAbFinGen, H::GrpAbFinGen; task::Symbol = :map) -> GrpAbFinGen, MapComputes the group of all homomorpisms from $G$ to $H$ as an abstract group. If task is ":map", then a map $\phi$ is computed that can be used to obtain actual homomorphisms. This map also allows preimages. Set task to ":none" to not compute the map.