Basic cohomology code for groups of prime power order¶
This module contains COHO
, that provides a framework for the
computation of the cohomology rings with coefficients in \(\mathbb
F_p\) for any finite \(p\)group. It is based on algorithms of David
Green and Dave Benson. See pGroupCohomology
for an extensive
introduction. Note that MODCOHO
,
the basic class for the non prime power case, inherits from COHO
,
so that many methods of the former work in the non prime power case
as well.
AUTHORS:
 Simon King <simon.king@unijena.de>

class
pGroupCohomology.cohomology.
COHO
(*args, **kwds)¶ Modular Cohomology Rings of Finite \(p\)Groups with coefficients in \(\mathbb F_p\).
AUTHORS:
 Simon King <simon.king@unijena.de>
INPUT:
A finite \(p\)group, either given by its coordinates in the SmallGroups library of Hans Ulrich Besche, Bettina Eick and Eamonn O’Brien, or given as a group in the libgap interface.
OUTPUT:
An object set up to compute the cohomology ring of the given \(p\)group with coefficients in \(\mathbb F_p\).
ALGORITHM:
The methods are based on algorithms due to Dave Benson, David Green, Simon King and Peter Symonds.
Eventually, a minimal generating set for the cohomology ring and a minimal set of algebraic relations is computed, together with various other information (e.g., Poincaré series).
By
global_options()
and by various parameters (see below), it can be influenced by what methods the results are computed, how the computation is documented, and where files created during the computation are stored.The purpose of this examples is to document some internals of the implementation. For examples of the actual use of this package, we refer to
pGroupCohomology
. Note that usually one would not construct an instance of the class COHO directly. Just for documentation, we use COHO in all but the first example. In the first example, we use the constructorpGroupCohomology.CohomologyRing()
, which is the recommended way of creating a cohomology ring.EXAMPLES:
First, a small example with logging enabled. We use the constructor
pGroupCohomology.CohomologyRing()
in a way that prevents the ring from being downloaded from the web repository or reloaded from the data based shipped with this package.When setting up the cohomology ring, the cohomology of various elementary abelian subgroups is computed first. But if they’d happen to be found in the local sources, they would simply be loaded from there. In order to make the doctest independent of the contents of this database, we compute the two rings in question separately and insist on a computation from scratch. For one of them, we show details of the computation by logging:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: tmp_root = tmp_dir() sage: CohomologyRing.set_workspace(tmp_root) sage: X = CohomologyRing(4,2, from_scratch=True) sage: X.make() sage: X = CohomologyRing(2,1, from_scratch=True, options='info') _get_p_group_from_scratch: We compute this cohomology ring from scratch H^*(SmallGroup(2,1); GF(2)): Initialising maximal pelementary abelian subgroups sage: X.make() Resolution of GF(2)[SmallGroup(2,1)]: Computing next term > rk P_02 = 1 H^*(SmallGroup(2,1); GF(2)): We have to choose 1 new generator in degree 1 > There is 1 Duflot regular generator in degree 1 Summary: 0 relations and 1 generators in degree 1 Ring approximation computed out to degree 1! Storing approximation data Determine degree 2 standard monomials We got 1 standard monomials There is no new generator in degree 2 Summary: 0 relations and 0 generators in degree 2 Ring approximation computed out to degree 2! Storing approximation data
Since the group of order two is abelian, it is known a priori that the cohomology ring can be presented in degree at most two. So, we don’t need to use any complicated completeness criterion. Now, for the dihedral group of order 8. This package contains a list of custom names for some groups from the SmallGroups library, and the dihedral group is part of that list.
Note that we don’t need to give the argument
options='info'
again, since this option is already in use.sage: H = CohomologyRing(8,3, from_scratch=True) _get_p_group_from_scratch: We compute this cohomology ring from scratch Computing basic setup for Small Group number 3 of order 8 H^*(D8; GF(2)): Initialising maximal pelementary abelian subgroups Inserting SmallGroup(2,1) as a subgroup ... Computing Dickson invariants in elementary abelian subgroup of rank 2
Now, the basic setup is done. We compute the ring structure, logging the computation:
sage: H H^*(D8; GF(2)) sage: H.make() Compute group_is_abelian We have no degree bound yet Start computation in Degree 1 Resolution of GF(2)[D8]: Make degree 1 autolift data H^*(D8; GF(2)): There are new generators, we have to lift the restriction maps Resolution of GF(2)[D8]: Computing next term > rk P_02 = 3 Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(2,1); GF(2)): lift in the source resolution lift in the target resolution to degree 1 Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): lift in the source resolution lift in the target resolution to degree 1 Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): lift in the source resolution lift in the target resolution to degree 1 H^*(D8; GF(2)): We have to choose 2 new generators in degree 1 > There are 0 nilpotent generators in degree 1 > There are 2 "boring" generators in degree 1 Summary: 0 relations and 2 generators in degree 1 Try to lift 1st power of 0th Dickson invariant Simultaneously lifting subgroup cochains of degree 1 Simultaneous lift was successful! Factorising an element; it can be interrupted with Ctrlc Ring approximation computed out to degree 1! Storing approximation data We expect a relation in degree at least 2 Start computation in Degree 2 Determine degree 2 standard monomials We got 3 standard monomials There are new generators, we have to lift the restriction maps Resolution of GF(2)[D8]: Computing next term > rk P_03 = 4 Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(2,1); GF(2)): lift in the source resolution lift in the target resolution to degree 2 Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): lift in the source resolution lift in the target resolution to degree 2 Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): lift in the source resolution lift in the target resolution to degree 2 H^*(D8; GF(2)): We have to choose 1 new generator in degree 2 > There are 0 nilpotent generators in degree 2 > There are 0 "boring" generators in degree 2 > There is 1 Duflot regular generator in degree 2 Summary: 1 relations and 1 generators in degree 2 Ring approximation computed out to degree 2! Storing approximation data Compute dependent_parameters Try to find a set of generators over which the cohomology ring is finite. Computing complete Groebner basis H^*(SmallGroup(4,2); GF(2)): Computing complete Groebner basis H^*(D8; GF(2)): Trying Symonds' criterion Successful application of the Symonds criterion Finished computation of the ring structure Storing approximation data sage: CohomologyRing.global_options('warn') sage: print(H) Cohomology ring of Dihedral group of order 8 with coefficients in GF(2) <BLANKLINE> Computation complete Minimal list of generators: [c_2_2: 2Cocycle in H^*(D8; GF(2)), b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))] Minimal list of algebraic relations: [b_1_0*b_1_1]
Now, without logging, an example using a group defined in Gap. This time, just for documentation, we invoke the class COHO directly (but in practice, one should of course use
CohomologyRing()
).sage: from pGroupCohomology.cohomology import COHO sage: CohomologyRing.global_options('warn') sage: G = libgap.DihedralGroup(8) sage: G <pc group of size 8 with 3 generators> sage: G.SetName("OtherName") <BLANKLINE> sage: G OtherName sage: H2 = COHO(G,root=tmp_root) sage: H2 H^*(OtherName; GF(2)) sage: H2.make() sage: print(H2) Cohomology ring of OtherName with coefficients in GF(2) <BLANKLINE> Computation complete Minimal list of generators: [c_2_2: 2Cocycle in H^*(OtherName; GF(2)), b_1_0: 1Cocycle in H^*(OtherName; GF(2)), b_1_1: 1Cocycle in H^*(OtherName; GF(2))] Minimal list of algebraic relations: [b_1_0*b_1_1+b_1_0^2]
Next, a slightly bigger example:
sage: H4 = COHO(64,14,root=tmp_root) sage: H4.make() # about 20 seconds sage: H4.gens() [1, a_2_1: 2Cocycle in H^*(SmallGroup(64,14); GF(2)), c_2_2: 2Cocycle in H^*(SmallGroup(64,14); GF(2)), c_4_4: 4Cocycle in H^*(SmallGroup(64,14); GF(2)), a_1_0: 1Cocycle in H^*(SmallGroup(64,14); GF(2)), a_1_1: 1Cocycle in H^*(SmallGroup(64,14); GF(2)), a_3_3: 3Cocycle in H^*(SmallGroup(64,14); GF(2))]
It depends on the python version whether or not the relations are tailreduced and how they are sorted:
sage: if (2, 8) < sys.version_info: ....: expected_rels = ['a_1_0^2', 'a_1_0*a_1_1', 'a_1_1^3', 'a_2_1*a_1_0', ....: 'a_2_1^2+a_2_1*a_1_1^2', 'a_1_0*a_3_3+a_2_1*a_1_1^2', ....: 'a_1_1*a_3_3+a_2_1*a_1_1^2', 'a_2_1*a_3_3', 'a_3_3^2'] ....: else: ....: expected_rels = ['a_1_0^2', 'a_1_0*a_1_1', 'a_1_1^3', 'a_2_1*a_1_0', ....: 'a_2_1^2+a_2_1*a_1_1^2', 'a_1_1*a_3_3+a_2_1^2', ....: 'a_1_0*a_3_3+a_2_1^2', 'a_2_1*a_3_3', 'a_3_3^2'] ....: sage: H4.rels() == expected_rels True
An example with \(p=3\), so that the cohomology ring is noncommutative:
sage: R = COHO(27,3,root=tmp_root) sage: R.make() sage: R.gens() [1, b_2_0: 2Cocycle in H^*(E27; GF(3)), b_2_1: 2Cocycle in H^*(E27; GF(3)), b_2_2: 2Cocycle in H^*(E27; GF(3)), b_2_3: 2Cocycle in H^*(E27; GF(3)), c_6_8: 6Cocycle in H^*(E27; GF(3)), a_1_0: 1Cocycle in H^*(E27; GF(3)), a_1_1: 1Cocycle in H^*(E27; GF(3)), a_3_4: 3Cocycle in H^*(E27; GF(3)), a_3_5: 3Cocycle in H^*(E27; GF(3))] sage: print(R('a_1_0*a_3_4')) 4Cocycle in H^*(E27; GF(3)), represented by [1 0 0 0 0 0 0] sage: print(R('a_3_4*a_1_0')) 4Cocycle in H^*(E27; GF(3)), represented by [2 0 0 0 0 0 0] sage: print(R.6*R.8) 4Cocycle in H^*(E27; GF(3)), represented by [1 0 0 0 0 0 0] sage: c=R('a_1_0*a_1_1*b_2_0+b_2_1^2') sage: c.name() '((a_1_0)*(a_1_1))*(b_2_0)+(b_2_1)**2' sage: c.setname('C') sage: c C: 4Cocycle in H^*(E27; GF(3)) sage: R.poincare_series() (t^4 + 2*t^2 + 1)/(t^6  2*t^5 + 2*t^4  2*t^3 + 2*t^2  2*t + 1) sage: R._poincare_without_parameters() (t^4 + 2*t^2 + 1)/(t^6  2*t^5 + 2*t^4  2*t^3 + 2*t^2  2*t + 1)
We return to our standard example, the cohomology of the dihedral group of order 8:
sage: CohomologyRing.set_workspace(tmp_root) sage: H = CohomologyRing(8,3) sage: H.make()
First of all, the attribute ‘completed’ tells whether the cohomology computation has been successfully finished. The attribute ‘knownDeg’ tells up to what degree the ring structure is explored, ‘lastRel’ is the degree of the last found relation, and ‘_method’ states whose criterion was used to prove completeness:
sage: H.completed True sage: H.knownDeg 2 sage: H.lastRel 2 sage: H._method 'Symonds'
A cohomology ring is based on some minimal projective resolution (see
RESL
):sage: H.resolution() Resolution of GF(2)[D8]
The lists of generators and relations of a cohomology ring can be obtained with
gens()
andrels()
.The attribute
H.GenS
provides a ring defined in the Singular interface, andH.RelG
is a list of strings defining a Groebner basis for the relation ideal. The cohomology ring is isomorphic to the quotient ofH.GenS
by the ideal ofH.RelG
. The same ring is created when puttingH
into the singular interface:sage: H.GenS.set_ring() sage: I=H.GenS.parent().ideal(H.RelG) sage: s=H.GenS.parent().eval('qring Q = %s'%(I.name())) sage: H.GenS.parent()('Q') polynomial ring, over a field, global ordering // coefficients: ZZ/2 // number of vars : 3 // block 1 : ordering M // : names c_2_2 b_1_0 b_1_1 // : weights 2 1 1 // : weights 1 0 0 // : weights 0 1 0 // block 2 : ordering C // quotient ring from ideal _[1]=b_1_0*b_1_1 sage: singular(H) polynomial ring, over a field, global ordering // coefficients: ZZ/2 // number of vars : 3 // block 1 : ordering M // : names c_2_2 b_1_0 b_1_1 // : weights 2 1 1 // : weights 1 0 0 // : weights 0 1 0 // block 2 : ordering C // quotient ring from ideal ...
The computation of a cohomology ring makes heavy use of the Singular interface. The names of all data in Singular that are related with a specific cohomology ring
H
have a common prefix, namelyH.prefix
. The prefix is chosen automatically and is different for any instance ofCOHO
:sage: H.prefix==H.subgps[(4,2)].prefix False
In the Singular interface, a graded commutative polynomial ring is defined and can be addressed as follows:
sage: print(singular.eval('%sr(%d)'%(H.prefix,H.knownDeg))) // coefficients: ZZ/2 // number of vars : 3 // block 1 : ordering M // : names c_2_2 b_1_0 b_1_1 // : weights 2 1 1 // : weights 1 0 0 // : weights 0 1 0 // block 2 : ordering C
Note that in Singular, ideals are only available if the ring to which the ideal belongs is Singular’s current
basering
. Currently, the quotient ring defined above isbasering
. We change the base ring, and then a Groebner basis at least up to degreeH.knownDeg
is given as follows:sage: H.set_ring() sage: singular('%sI'%(H.prefix)) b_1_0*b_1_1
We change the base ring again,
sage: H.subgroups()[(4,2)].set_ring()
and then of course the relation ideal of
H
is not available anymore:sage: singular('%sI'%(H.prefix)) Traceback (most recent call last): ... TypeError: Singular error: ? ... is undefined ? error occurred in ...: `def ...;`
Custom attributes
In Python, it is possible to add attributes to any object. However, when adding a Python attribute to a cohomology ring, it would be lost when saving.
Therefore we provide another way to add custom “attributes” to a cohomology ring. We refer to such attribute as a “property” of the ring.
Properties can be retreived in the same way as usual attributes, they are visible in tab completion and in introspection, and they are preserved when the cohomology ring is saved and reloaded. This is very useful for adding more information.
When an attribute of the requested name (
Status
in the following example) does not exist, it is checked whether a property of that name has yet been defined. If this is the case, it is returned, otherwise None is returned. Note that for cohomology rings you will never get an ``AttributeError`` except for attributes that start and end with an underscore:sage: H._foobar_ Traceback (most recent call last): ... AttributeError: 'COHO' object has no attribute '_foobar_' sage: print(H.Status) # not defined at that point, hence "None" None sage: 'Status' in dir(H) False sage: H.setprop('Status','Our main example') sage: H.Status 'Our main example' sage: 'Status' in dir(H) True
Usually, cohomology rings that are created using the constructor
CohomologyRing()
are cached:sage: H is loads(dumps(H)) True
We destroy the cache on purpose and demonstrate that the additional property is preserved by pickling:
sage: del CohomologyRing._cache[H._key] sage: HR = loads(dumps(H)) sage: HR is H False sage: HR.Status 'Our main example'
Among many other data, the group name (that we passed on by the parameter
GroupName
) and a more detailed autogenerated group description (that can be overwritten usingsetprop('GroupDescr',...)
) are provided in form of custom attributes:sage: H.GroupName # This comes from a list of known group names 'D8' sage: H.GroupDescr # This comes from a list of known group descriptions 'Dihedral group of order 8'
The custom attribute ‘Status’ can be deleted with
sage: H.delprop('Status') sage: print(H.Status) None sage: 'Status' in dir(H) False
TESTS:
As mentioned above, there are various global options (both in the definition of a cohomology ring and by using CohomologyRing.global_options(…)) that influence the choice of algorithm. For unit testing, we repeat here one of the examples from above. In order to not loose too much time, we now allow to reload data.
sage: CohomologyRing.global_options('reload')
First, we use linear algebra and not elimination for finding the Dickson classes:
sage: H4 = COHO(64,14,root=tmp_root, useElimination=False) sage: H4.make() sage: H4.gens() [1, a_2_1: 2Cocycle in H^*(SmallGroup(64,14); GF(2)), c_2_2: 2Cocycle in H^*(SmallGroup(64,14); GF(2)), c_4_4: 4Cocycle in H^*(SmallGroup(64,14); GF(2)), a_1_0: 1Cocycle in H^*(SmallGroup(64,14); GF(2)), a_1_1: 1Cocycle in H^*(SmallGroup(64,14); GF(2)), a_3_3: 3Cocycle in H^*(SmallGroup(64,14); GF(2))]
It depends on the python version whether or not the relations are tailreduced and how they are sorted:
sage: if (2, 8) < sys.version_info: ....: expected_rels = ['a_1_0^2', 'a_1_0*a_1_1', 'a_1_1^3', 'a_2_1*a_1_0', ....: 'a_2_1^2+a_2_1*a_1_1^2', 'a_1_0*a_3_3+a_2_1*a_1_1^2', ....: 'a_1_1*a_3_3+a_2_1*a_1_1^2', 'a_2_1*a_3_3', 'a_3_3^2'] ....: else: ....: expected_rels = ['a_1_0^2', 'a_1_0*a_1_1', 'a_1_1^3', 'a_2_1*a_1_0', ....: 'a_2_1^2+a_2_1*a_1_1^2', 'a_1_1*a_3_3+a_2_1^2', ....: 'a_1_0*a_3_3+a_2_1^2', 'a_2_1*a_3_3', 'a_3_3^2'] ....: sage: H4.rels() == expected_rels True
We repeat the example, but this time use elimination.
sage: H4 = COHO(64,14,root=tmp_root, useElimination=True) sage: H4.make() sage: H4.gens() [1, a_2_1: 2Cocycle in H^*(SmallGroup(64,14); GF(2)), c_2_2: 2Cocycle in H^*(SmallGroup(64,14); GF(2)), c_4_4: 4Cocycle in H^*(SmallGroup(64,14); GF(2)), a_1_0: 1Cocycle in H^*(SmallGroup(64,14); GF(2)), a_1_1: 1Cocycle in H^*(SmallGroup(64,14); GF(2)), a_3_3: 3Cocycle in H^*(SmallGroup(64,14); GF(2))] sage: H4.rels() == expected_rels True
Now we switch the ‘sparse’ option on:
sage: CohomologyRing.global_options('sparse') sage: H4 = COHO(64,14,root=tmp_root) sage: H4.make() sage: H4.gens() [1, a_2_1: 2Cocycle in H^*(SmallGroup(64,14); GF(2)), c_2_2: 2Cocycle in H^*(SmallGroup(64,14); GF(2)), c_4_4: 4Cocycle in H^*(SmallGroup(64,14); GF(2)), a_1_0: 1Cocycle in H^*(SmallGroup(64,14); GF(2)), a_1_1: 1Cocycle in H^*(SmallGroup(64,14); GF(2)), a_3_3: 3Cocycle in H^*(SmallGroup(64,14); GF(2))] sage: H4.rels() == expected_rels True sage: CohomologyRing.global_options('nosparse')
And finally, we allow to convert to Sage matrices in some steps of the computation:
sage: H4 = COHO(64,14,root=tmp_root) sage: CohomologyRing.global_options('nouseMTX') sage: H4.make() sage: H4.gens() [1, a_2_1: 2Cocycle in H^*(SmallGroup(64,14); GF(2)), c_2_2: 2Cocycle in H^*(SmallGroup(64,14); GF(2)), c_4_4: 4Cocycle in H^*(SmallGroup(64,14); GF(2)), a_1_0: 1Cocycle in H^*(SmallGroup(64,14); GF(2)), a_1_1: 1Cocycle in H^*(SmallGroup(64,14); GF(2)), a_3_3: 3Cocycle in H^*(SmallGroup(64,14); GF(2))] sage: H4.rels() == expected_rels True sage: CohomologyRing.global_options('useMTX')

BensonTest
(FRS, dv, forced=False)¶ A modified version of Benson’s completeness criterion.
INPUT:
FRS
, a list of strings providing elements ofself
that are known to provide a filter regular HSOP for the cohomology ringdv
, the degrees (list of integers) of these parametersforced
[optional, default =False
]: IfTrue
, perform Benson’s test even if it seems to be too low degree
OUTPUT:
True
if the test succeededNone
if the test was not conclusiveFalse
if the test showed that the ring is incomplete.
The attribute
suffDeg
may be modified.THEORY:
See [GreenKing] and the outline we gave in
pGroupCohomology
.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(64,6, useElimination=True, from_scratch=True) sage: H.next()
There are no suitable parameters of the current ring approximation, so that a completion test wouldn’t make sense yet. So, we continue, and succeed with finding filter regular parameters:
sage: H.filter_regular_parameters() sage: H.next() sage: H.filter_regular_parameters() ['c_2_2', 'c_2_3', 'b_1_1']
It is not reasonable to apply Benson’s test, yet, since we expect a relation in degree 4:
sage: H.expect_last_relation() 4
And of course, the degrees of the parameters do not allow to prove completeness already in degree two:
sage: CohomologyRing.global_options('info') sage: H.BensonTest(H.filter_regular_parameters(),[2,2,1]) H^*(SmallGroup(64,6); GF(2)): Testing whether it makes sense to try Benson's completeness criterion We expect that Benson's test will not apply before degree 3
So, we must go ahead. The log states that Benson’s test will not apply before degree three. Perhaps it does apply in that degree, although we expect a relation in degree four?
sage: CohomologyRing.global_options('warn') sage: H.next() sage: CohomologyRing.global_options('info') sage: H.BensonTest(H.filter_regular_parameters(),[2,2,1]) H^*(SmallGroup(64,6); GF(2)): Testing whether it makes sense to try Benson's completeness criterion It is possible that Benson's degree bound applies Compute raw_filter_degree_type Computing complete Groebner basis Test filter regularity > Sequence is NOT filter regular. Sorry. False
It does not. But in degree 4, everything works:
sage: CohomologyRing.global_options('warn') sage: H.next() sage: CohomologyRing.global_options('info') sage: H.BensonTest(H.filter_regular_parameters(),[2,2,1]) H^*(SmallGroup(64,6); GF(2)): Testing whether it makes sense to try Benson's completeness criterion It is possible that Benson's degree bound applies Compute raw_filter_degree_type Computing complete Groebner basis Test filter regularity Filter degree type: [1, 2, 3, 3] True
Now the ‘sufficient degree’ is less than or equal to the known degree, hence, we are done:
sage: H.suffDeg 3 sage: H.knownDeg 4 sage: CohomologyRing.global_options('warn')

Hom
(other, category=None)¶ Return a homset of induced homomorphisms between two cohomology rings.
INPUT:
 A cohomology ring that will be the codomain for all elements of the homset
cat
(not implemented) a category of homomorphisms.
EXAMPLES:
We first create the cohomology rings for two different presentations of the dihedral group of order 8.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H1 = CohomologyRing(8,3) sage: H2 = CohomologyRing(libgap.DihedralGroup(8), GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H1.Hom(H2) Set of Homomorphisms from H^*(D8; GF(2)) to H^*(DihedralGroup(8); GF(2))

InitSubgroups
()¶ Initialise maximal elementary abelian subgroups.
If self is the cohomology ring of a nonabelian \(p\)group then
InitSubgroups
initialises various group theoretic data, such as the \(p\)rank or the rank of the center; it also creates or reloads the cohomology rings of the greatest central and the maximal elementary abelian subgroups, and, if applicable, computes the Dickson classes of the maximal elementary abelian subgroups.NOTE:
This function should only be of internal use and will be invoked when initializing a cohomology ring. It requires the presence of a certain GAPreadable file that is created during initialisation of the cohomology ring.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True)
Now we destroy and reconstruct the subgroups and the respective restriction maps:
sage: H.subgps={} sage: H.RestrMaps={} sage: H.InitSubgroups() sage: sorted(H.subgroups().items()) [((2, 1), H^*(SmallGroup(2,1); GF(2))), ((4, 2), H^*(SmallGroup(4,2); GF(2)))] sage: sorted(H.restriction_maps().items()) [(1, [(2, 1), Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(2,1); GF(2))]), (2, [(4, 2), Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2))]), (3, [(4, 2), Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2))])] sage: H.subgpDickson {(4, 2): [c_1_1: 1Cocycle in H^*(SmallGroup(4,2); GF(2))]}
Finally, we show location and content of the GAPreadable file that defines the subgroup structure:
sage: print(open(os.path.join(H.inc_folder,H.GStem+'.sgs')).read()) # Subgroup information for 8gp3 local numSpecialSubgps, specialSubgpId, CrankPos, numMaxels, maxelRankPos, numBoltons, Bolton; numSpecialSubgps := 3; specialSubgpId := [ [ 2, 1 ], [ 4, 2 ], [ 4, 2 ] ]; CrankPos := [ 1, 1 ]; numMaxels := 2; maxelRankPos := [ [ 2, 2 ], [ 2, 3 ] ]; numBoltons := 0; Bolton := []; return [numSpecialSubgps, specialSubgpId, CrankPos, numMaxels, maxelRankPos, numBoltons, Bolton];

InsertSubgroup
(q, nr, n)¶ Initialize the restriction map to some subgroup.
INPUT:
q
 the order of the subgroupnr
 the position of this group in the Small Group Libraryn
 the subgroup is addressed as subgroup numbern
NOTE:
 This method will normally be of internal use only. It is invoked by
the method
InitSubgroups()
 It reads the data for the inclusion map from a file whose name is
determined by
self.GStem
andn
. The necessary files are created bymakeGroupData()
or ormakeSpecialGroupData()
during iniitialisation of the cohomology ring.  Normally, we only consider elementary abelian subgroups. This method probably also allows for insertion of other interesting subgroups, provided a file with data for the inclusion map exists. However, PLEASE DO NOT INSERT SUBGROUPS MANUALLY! The computations crucially depend on the restrictions to certain elementary abelian subgroups, and it is essential that only elementary abelian abelian subgroups are inserted, including the greatest central elementary abelian (this must be subgroup number one) and one representative for each conjugacy class of maximal elementary abelian subgroups.
 The method will try to read a file in a specific location (see example below). This file should provide a MeatAxe matrix that describes the inclusion map of the algebra of the subgroup into the algebra of the ambient group.
 When a cohomology ring is initialized, the greatest central elementary abelian subgroup will be inserted as special subgroup number 1. Moreover, representatives for the conjugacy classes of maximal elementary subgroups will be inserted.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: sorted(H.subgroups().items()) [((2, 1), H^*(SmallGroup(2,1); GF(2))), ((4, 2), H^*(SmallGroup(4,2); GF(2)))] sage: sorted(H.restriction_maps().items()) [(1, [(2, 1), Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(2,1); GF(2))]), (2, [(4, 2), Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2))]), (3, [(4, 2), Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2))])]
Hence, there are 3 special subgroups, that are of two different isomorphism types. We now destroy them on purpose:
sage: H.RestrMaps={} sage: H.subgps={}
Next, we put them back manually. Note that it is attempted to reload the subgroups from cache or from disk:
sage: H.InsertSubgroup(2,1,1) sage: H.InsertSubgroup(4,2,2)
The third subgroup has the same automorphism type as the second, so, there is no need to reload it, but it doesn’t hurt either:
sage: H.InsertSubgroup(4,2,3) sage: sorted(H.subgroups().items()) [((2, 1), H^*(SmallGroup(2,1); GF(2))), ((4, 2), H^*(SmallGroup(4,2); GF(2)))] sage: sorted(H.restriction_maps().items()) [(1, [(2, 1), Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(2,1); GF(2))]), (2, [(4, 2), Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2))]), (3, [(4, 2), Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2))])]
Next, we show where to find the files defining the inclusion of the second and third subgroup. Although they are isomorphic, the inclusions are, of course, different:
sage: from sage.matrix.matrix_gfpn_dense import Matrix_gfpn_dense as MTX sage: print(MTX.from_filename(os.path.join(H.inc_folder,H.GStem+'sg2.ima'))) [1 0 0 0 0 0 0 0] [0 0 0 1 1 1 1 1] [0 0 1 0 0 0 0 0] [0 0 0 0 0 0 1 1] sage: print(MTX.from_filename(os.path.join(H.inc_folder,H.GStem+'sg3.ima'))) [1 0 0 0 0 0 0 0] [0 0 0 1 1 1 1 1] [0 1 0 0 0 0 0 0] [0 0 0 0 0 1 0 1]
Finally, we demonstrate how to continue the computation. After reinserting the special subgroups, it is necessary to recompute the Dickson classes in the special subgroups (using the method dickson_in_subgroup), or to use the elimination method. We chose the second way:
sage: H.setprop('useElimination',True) sage: CohomologyRing.global_options('warn') sage: H.make() sage: print(H) Cohomology ring of Dihedral group of order 8 with coefficients in GF(2) <BLANKLINE> Computation complete Minimal list of generators: [c_2_2: 2Cocycle in H^*(D8; GF(2)), b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))] Minimal list of algebraic relations: [b_1_0*b_1_1]

MonToProd
(expV)¶ Return the element corresponding to a list of exponents.
INPUT:
expV
: a list of nonnegative integers (exponents of a list of monomials)OUTPUT:
An element of
self
(COCH
), given by a power product of generators.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: H.make() sage: H.MonToProd([0,2,1]) (b_1_0)*((b_1_0)*(b_1_1)): 3Cocycle in H^*(D8; GF(2))

PrescribedRestrictions
(L)¶ Try to construct a cochain of
self
that has given restrictions to the elementary abelian subgroups.INPUT:
L
: a list of elements of the form[i,C]
, wherei
: the identifier (integer) of a special subgroupC
: an element of thei
th special subgroup
OUTPUT:
A cochain that has restrictions prescribed in
L
, orNone
, if such cochain doesn’t exist.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make()
To simplify notation, we give names to the two isomorphism types of special subgroups:
sage: Z = H.subgps[(2,1)] sage: M = H.subgps[(4,2)]
We define cochains in
Z
and inM
, and try to find common lifts inH
. Note thatM
corresponds to two pairwise nonconjugate maximal elementary abelian subgroups of the dihedral group, whileZ
corresponds to the greatest central elementary abelian subgroup.sage: c = Z.standardCochain(2,0) sage: m1 = M.standardCochain(2,0) sage: m2 = M.standardCochain(2,1) sage: m3 = M.standardCochain(2,2) sage: print(H.PrescribedRestrictions([[1,c],[2,m2]])) None sage: print(H.PrescribedRestrictions([[1,c],[2,m1+m2]])) 2Cocycle in H^*(D8; GF(2)), represented by [0 0 1]
Note that the lift is not unique. If we also prescribe a cochain in the third pecial subgroup, we still get a lift of
[1,c]
and[2,m1+m2]
, but a different lift:sage: print(H.PrescribedRestrictions([[1,c],[2,m1+m2],[3,m1+m2+m3]])) 2Cocycle in H^*(D8; GF(2)), represented by [0 1 1]
Finally, we test whether we really have the restrictions that we want:
sage: L = H.PrescribedRestrictions([[1,c],[2,m1+m2],[3,m1+m2+m3]]) sage: H.restriction_maps()[1][1](L) == c True sage: H.restriction_maps()[2][1](L) == m1+m2 True sage: H.restriction_maps()[3][1](L) == m1+m2+m3 True

SymondsTest
(hsop, dv, forced=False)¶ Apply the Symonds test.
INPUT:
hsop
: A list of strings defining a homogeneous system of parameters for the current ring approximation.dv
: The degrees (list of integers) ofhsop
.
OUTPUT:
True
,False
orNone
, depending on whether the criterion proves completeness, the approximation is provably incomplete, or there is no conclusive application of the criterion possible yet. The attribute
_max_module_deg
is set.
ASSUMPTION:
The ring approximation contains paramters for the cohomology ring.
THEORY:
By [Symonds], under the above assumption, the ring approximation is complete if it is known to a degree greater than the sum of the degrees in
hsop
minus their number, and the ring approximation is generated at most out to that degree as a module over the algebra generated byhsop
.NOTE:
The method
test_for_completion()
chooses between the modified Benson test and the Symonds test.EXAMPLES:
We compute a cohomology ring out to degree 10, avoiding automatic application of the criterion.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(64,32, from_scratch=True) sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.knownDeg 10
There are fairly small parameters:
sage: H.parameters() ['c_4_11', 'b_2_3+b_2_2+b_2_1', 'b_2_2+b_2_1', 'b_1_1'] sage: H.verify_parameters_exist() True
The previous line asserts that the assumption of this criterion is satisfied. Indeed, the criterion applies:
sage: H.SymondsTest(H.parameters(),[4,2,2,1]) True
As a module, the ring is generated in degree at most five:
sage: H._max_module_deg 5

a_invariants
()¶ Permanently cached method: Return the \(a\)invariants of
self
.THEORY:
A filter regular homogeneous system of paramaters can be used for an iterative computation of the \(a\)invariants, provided the parameters are of sufficiently high degree. Often the data obtained by verifying Benson’s completeness criterion are sufficient for the computation of \(a\)invariants. However, in some cases it is needed to raise the parameters occuring in Benson’s criterion to some power.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, useElimination=True, from_scratch=True) sage: H.make() sage: H.a_invariants() [Infinity, Infinity, 2]
The attribute
H.A_INV_Expos
tells whether it was needed to raise the parameters to some power (this is not the case here):sage: H.A_INV_Expos [1, 1]

autosave_name
()¶ Return the name of the file under which
self
is automatically saved.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: K = load(H.autosave_name()) sage: print(K) Cohomology ring of Dihedral group of order 8 with coefficients in GF(2) <BLANKLINE> Computation complete Minimal list of generators: [c_2_2: 2Cocycle in H^*(D8; GF(2)), b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))] Minimal list of algebraic relations: [b_1_0*b_1_1]

bar_code
(command, degree=1)¶ Permanently cached method: Compute the persistent cohomology for a specified normal subgroup series.
ASSUMPTION:
The subgroups and quotient groups can be found in the SmallGroups library.
INPUT:
command
: The name (string) of a Gap command that produces a series of normal subgroups when applied to the
group
self.group()
, starting withself.group()
and terminating with the trivial group. degree=1
: Optional parameter. Ifdegree>=0
then only the bar code in the specified degree is computed; otherwise, all degrees are studied simultaneously, by Poincaré series.
OUTPUT:
self
’s full bar code (classBarCode
) respectively bar code of the given degree (classBarCode2d
), associated with the specified normal series.THEORY:
Any sequence of group homomorphisms \(\phi_i: G_i \to G_{i+1}\) with \(i=1,...,n\) gives rise to a series of induced homomorphisms of cohomology rings. Persistent group cohomology, introduced by [EllisKing], asks how long cocycles in a given degree”survive” being mapped by the induced homomorphisms. For a given degree \(d\), the persistent cohomology can be described by an upper triangular matrix of nonnegative integers, where entry \(i,j\) (\(i\le j\)) is the dimension of the image of the degree \(d\) part of \(H^*(G_j)\) in \(H^*(G_i)\) under the induced homomorphism given by the composition of \(\phi_i,\phi_{i+1},...,\phi_{j1}\), including the case \(i=j\) in which the matrix entry simply gives the dimension of the degree \(d\) part of \(H^*(G_i)\).
As usual, the sequence of dimensions sorted by degree gives rise to a Poincaré series. Hence, an upper triangular matrix of rational functions results and this provides information for all degrees.
EXAMPLES:
We work here with groups of order 64, that are part of the cohomology data base shipped with this package.
sage: from pGroupCohomology import CohomologyRing sage: H158 = CohomologyRing(64,158) sage: H158.make() sage: H160 = CohomologyRing(64,160) sage: H160.make()
The Poincaré series, the \(a\)invariants, the degrees of generators and of relations of the cohomology rings coincide:
sage: H158.poincare_series() (t^4 + t^3 + t^2 + t + 1)/(t^6  2*t^5 + 3*t^4  4*t^3 + 3*t^2  2*t + 1) sage: H160.poincare_series() (t^4 + t^3 + t^2 + t + 1)/(t^6  2*t^5 + 3*t^4  4*t^3 + 3*t^2  2*t + 1) sage: H158.degvec [4, 4, 1, 1, 1, 3, 3] sage: H160.degvec [4, 4, 1, 1, 1, 3, 3] sage: H158.set_ring() sage: [singular('deg(%s)'%r) for r in H158.rels()] [2, 2, 3, 3, 4, 4, 5, 6, 6, 6] sage: H160.set_ring() sage: [singular('deg(%s)'%r) for r in H160.rels()] [2, 2, 3, 3, 4, 4, 5, 6, 6, 6] sage: H158.a_invariants() [Infinity, Infinity, 2] sage: H160.a_invariants() [Infinity, Infinity, 2]
We consider here the bar codes associated with the upper central series. It turns out that the nontrivial terms of the upper central series and the resulting factor groups are isomorphic:
sage: G158 = libgap.SmallGroup(64,158) sage: G160 = libgap.SmallGroup(64,160) sage: [(G.IdGroup(), (G158/G).IdGroup()) for G in G158.UpperCentralSeries()] [([ 64, 158 ], [ 1, 1 ]), ([ 16, 2 ], [ 4, 2 ]), ([ 4, 2 ], [ 16, 11 ]), ([ 1, 1 ], [ 64, 158 ])] sage: [(G.IdGroup(), (G160/G).IdGroup()) for G in G160.UpperCentralSeries()] [([ 64, 160 ], [ 1, 1 ]), ([ 16, 2 ], [ 4, 2 ]), ([ 4, 2 ], [ 16, 11 ]), ([ 1, 1 ], [ 64, 160 ])]
Nevertheless, the groups can be distinguished using the bar codes associated with the upper central series:
sage: B158 = H158.bar_code('UpperCentralSeries') sage: B160 = H160.bar_code('UpperCentralSeries') sage: B158 == B160 False
Indeed, the bar codes differ in degree 3; graphically:
sage: ascii_art(B158[3]) * * ** ** * * * * * * ** ** * * * * * * * * * * sage: ascii_art(B160[3]) * * ** * * * * * * * *** ** * ** * * * * * * *
These pictures (bar codes) can be interpreted as follows. Let \(G\) be a finite \(p\)group and let \(G=G_0 > G_1 > ... > G_n > 1\) be a normal series; in our example, we have \(n=2\). The first \(n+1\) columns of the bar code correspond to the normal subgroups groups \(G_n, G_{n1},..., G_0\), while the last \(n\) columns correspond to the factor groups \(G/G_n, G/G_{n1},..., G/G_1\). We consider the sequence of group homomorphisms given by inclusions and quotients. The stars in the bar code correspond to basis vectors of the degree \(d\) part of the cohomology rings of the respective groups. Stars are connected by a line (i.e., a hyphen) if the corresponding basis vectors are mapped to each other by the induced maps (which of course go from right to left).
In terms of the persistance matrix:
sage: B158[3].matrix() [ 4 0 0 0 0] [ 0 4 0 0 0] [ 0 0 4 2 0] [ 0 0 0 10 2] [ 0 0 0 0 4] sage: B160[3].matrix() [ 4 0 0 0 0] [ 0 4 1 0 0] [ 0 0 4 2 1] [ 0 0 0 10 2] [ 0 0 0 0 4]
The bar codes in degree 3 can also be computed directly, and of course it coincides with the bar codes obtained from the “full” bar codes (based on Poincaré series):
sage: B158[3] == H158.bar_code('UpperCentralSeries',degree=3) True sage: B160[3] == H160.bar_code('UpperCentralSeries',degree=3) True
Since apparently the
(2,4)
entries of the persistence matrices differ, we show here how the Poincaré series in that position look like:sage: B158.matrix()[2,4] 2*t^2 + 2*t + 1 sage: B160.matrix()[2,4] t^3 + 2*t^2 + 2*t + 1
Hence, the image of the map \(H^*(G/G_2) \to H^*(G)\) induced by the quotient map contains only finitely many cocycles, where \(G\) is group number 158 or 160 of order 64, and \(G_2\) is the second term of the upper central series.

decomposable_classes
(n, forced=False)¶ Return a basis for the degree \(n\) cohomology, expressed by monomials.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: H.decomposable_classes(3) [(b_1_0)*((b_1_0)*(b_1_0)): 3Cocycle in H^*(D8; GF(2)), (b_1_1)*((b_1_1)*(b_1_1)): 3Cocycle in H^*(D8; GF(2)), (b_1_0)*(c_2_2): 3Cocycle in H^*(D8; GF(2)), (b_1_1)*(c_2_2): 3Cocycle in H^*(D8; GF(2))]

delprop
(key)¶ Delete a property of
self
.TESTS:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.setprop('_foobar_', 'It works!') sage: print(H._foobar_) It works! sage: H.delprop('_foobar_') sage: H._foobar_ Traceback (most recent call last): ... AttributeError: 'COHO' object has no attribute '_foobar_'

dependent_parameters
()¶ Permanently cached method: Parameters for the cohomology that are not guaranteed to be algebraically independent.
OUTPUT:
A subset of ring generators of the current ring approximation over which the cohomology ring is finite.
NOTE:
There is no guarantee that they give rise to parameters for the current ring approximation. There is no guarantee that the returned elements are algebraically independent.
Since elements of degree one do not contribute to the degree bound in Symonds’ completeness criterion, we always include the degree one generators.
This method is applied for the Symonds test (see
SymondsTest()
).EXAMPLE:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(32,32, from_scratch=True) sage: H.make(2)
The current ring approximation does not contain parameters for the cohomology ring, and thus we obtain:
sage: H.verify_parameters_exist() False sage: print(H.dependent_parameters()) None
In degree 4, at last we find that the cohomology ring is finite over the returned element list, so that it can eventually be used in a completeness test – even though the ring approximation isn’t finite over it, yet:
sage: H.make(4) sage: H.verify_parameters_exist() True sage: H.dependent_parameters() ['a_1_0', 'a_1_1', 'a_1_2', 'c_4_4', 'c_4_5'] sage: print(H) Cohomology ring of Small Group number 32 of order 32 with coefficients in GF(2) <BLANKLINE> Computed up to degree 4 Minimal list of generators: [c_4_4: 4Cocycle in H^*(SmallGroup(32,32); GF(2)), c_4_5: 4Cocycle in H^*(SmallGroup(32,32); GF(2)), a_1_0: 1Cocycle in H^*(SmallGroup(32,32); GF(2)), a_1_1: 1Cocycle in H^*(SmallGroup(32,32); GF(2)), a_1_2: 1Cocycle in H^*(SmallGroup(32,32); GF(2)), a_3_2: 3Cocycle in H^*(SmallGroup(32,32); GF(2)), a_3_3: 3Cocycle in H^*(SmallGroup(32,32); GF(2))] Minimal list of algebraic relations: [a_1_1^2+a_1_0*a_1_2, a_1_2^2+a_1_0*a_1_1+a_1_0^2, a_1_0^3, a_1_0^2*a_1_2+a_1_0^2*a_1_1, a_1_2*a_3_2+a_1_1*a_3_2+a_1_0*a_3_3+a_1_0*a_3_2, a_1_2*a_3_3+a_1_1*a_3_3+a_1_0*a_3_2]

depth
()¶ Permanently cached method: Return the depth of
self
, i.e., the length of a maximal regular sequence.NOTE:
By theorems of Duflot and Kuhn, the rank of the center of the underlying group is a lower bound for the depth. The \(p\)rank of the group is equal to the dimension of the cohomology ring, and thus is an upper bound.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(32,27) sage: H.make() sage: H.dimension() 4 sage: H.CenterRk 2 sage: H.depth() 3

depth_essential_ideal
(r)¶ Permanently cached method: Compute the \(r\)th depth essential ideal.
INPUT:
r
– an integer,self.CenterRk \le r \le self.dimension()
.OUTPUT:
The ideal formed by all elements of
self
that restrict to zero on the centralisers of all \(p\)elementary abelian subgroups of rankr
(it suffices to consider those that are contained in a Sylow \(p\)subgroup \(S\) and contain the greatest central elementary abelian subgroup of \(S\).THEORY:
If
r
is at most the depth ofself
, then the result is zero. It is conjectured by J. Carlson that it is nonzero wheneverr
exceeds the depth.EXAMPLE:
We choose a group of order 64 (that is contained in the local sources shipped with this package), and verify Carlson’s conjecture:
sage: from pGroupCohomology import CohomologyRing sage: H = CohomologyRing(64,23) sage: H.CenterRk 2 sage: H.depth() 3 sage: H.dimension() 4 sage: H.depth_essential_ideal(2) 0 sage: H.depth_essential_ideal(3) 0 sage: H.depth_essential_ideal(4) a_1_0, a_1_1, a_2_0

dickson_in_subgroup
(ID)¶ Compute Dickson classes for an elementary abelian group, considered as subgroup of the group of \(self\).
INPUT:
ID
: the small groups address (pair of integers) of some elementary abelian subgroup ofself
.
OUTPUT:
Let \(G\) be the finite \(p\)group whose cohomology ring
self
represents. The attributesubgbDickson
of self is changed and contains elements of degree \(p^{rz}p^{rzi}\) of the cohomology ring of the elementary abelian group \(V\) described byID
, where \(r\) is the \(p\)rank of \(G\), \(z\) is the rank of the centre of \(G\), and \(i = 1,...,rz\). These elements are constructed using Dickson invariants in the polynomial part of the cohomology of \(V\), vanishing on the first \(z\) generators. Note that in some cases a trivial element results, but it still has the stated degree.NOTE:
For applying Benson’s or Symonds’ completeness criterion, one has to find Dickson classes in the ambient group that simultaneously restrict to (powers of) the classes in the special subgroups found with dickson_in_subgroup. However, if \(p^{rz}p^{rzi}\) is too large, one should use
find_dickson()
, that avoids the construction of elements of high degrees.EXAMPLES:
We choose a group that has two different isomorphism classes of maximal elementary abelian subgroups:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(32,27, from_scratch=True)
The Dickson invariants for the maximal elementary abelian subgroups were already computed when creating
H
. We destroy them on purpose and reconstruct them:sage: H.subgpDickson = {} sage: H.dickson_in_subgroup((8,5)) sage: sorted(H.subgpDickson.items()) [((8, 5), [(c_1_2)**2: 2Cocycle in H^*(SmallGroup(8,5); GF(2)), 0: 3Cocycle in H^*(SmallGroup(8,5); GF(2))])] sage: H.dickson_in_subgroup((16,14)) sage: sorted(H.subgpDickson.items()) [((8, 5), [(c_1_2)**2: 2Cocycle in H^*(SmallGroup(8,5); GF(2)), 0: 3Cocycle in H^*(SmallGroup(8,5); GF(2))]), ((16, 14), [(c_1_2)*(c_1_2)+(c_1_2)*(c_1_3)+(c_1_3)*(c_1_3): 2Cocycle in H^*(SmallGroup(16,14); GF(2)), (c_1_2)*((c_1_2)*(c_1_3))+(c_1_2)*((c_1_3)*(c_1_3)): 3Cocycle in H^*(SmallGroup(16,14); GF(2))])]

dimension
()¶ Return the dimension of
self
.NOTE:
It is known that the dimension of self equals the \(p\)rank of the underlying group.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.dimension() 2

duflot_regular_sequence
()¶ Return a Duflot regular sequence that is maximal in the current ring approximation.
THEORY:
A sequence of elements is called Duflot regular, if its restrictions to the greatest \(p\)elementary abelian subgroup in the centre of a Sylow \(p\)subgroup is regular.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(144,186,prime=3, from_scratch=True) sage: H.sylow_cohomology().duflot_regular_sequence() ['c_2_1', 'c_2_2'] sage: H.make(4) sage: H.duflot_regular_sequence() ['c_4_0'] sage: H.make() sage: H.duflot_regular_sequence() ['c_4_0', 'c_8_1']
We compute the restrictions to the greatest central elementary abelian subgroup of a Sylow \(3\)subgroup is a regular sequence, which are indeed regular:
sage: r = H.restriction_maps()[1][1]; r Induced homomorphism of degree 0 from H^*(SmallGroup(144,186); GF(3)) to H^*(SmallGroup(9,2); GF(3)) sage: [r(H(t)).as_polynomial() for t in H.duflot_regular_sequence()] ['c_2_2^2+c_2_1^2', 'c_2_1^2*c_2_2^2']

element_as_polynomial
(c)¶ Express a cochain as polynomial in the generators of
self
.INPUT:
C
: an element of selfOUTPUT:
C
is changed inplace and then returned, so that its name representsC
as a polynomial in the ring generators.NOTE:
If needed, all decomposable classes in the degree of
C
will be computed and then kept in memory. The decomposable classes need to be obtained anyway when computing the ring structure. By default, for saving resources, the memory is cleared (except for elementary abelian groups). If the optional parameterKeepBases
isTrue
when creating the cohomology ring, the memory is not cleared.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: c=H.standardCochain(3,3) sage: c c_3_3: 3Cocycle in H^*(D8; GF(2)) sage: c is H.element_as_polynomial(c) True sage: c c_2_2*b_1_1: 3Cocycle in H^*(D8; GF(2)) sage: H('c_2_2*b_1_1')==c True

essential_ideal
(Subgroups=None)¶ Permanently cached method: Return the essential ideal, given by a Groebner basis.
INPUT:
Subgroups
– optional list or set of subgroups ofself.group()
OUTPUT:
The ideal of all elements of
singular(self)
that restrict to zero on all maximal subgroups ofself.group()
(resp. on the subgroups in the listSubgroups
). The generators of this ideal form a Groebner basis.If the optional argument is not provided, then the essential ideal with respect to all maximal subgroups is returned, and theoretical results are used that in some cases assert that there are no essential classes.
THEORY:
The essential ideal is formed by those elements of the cohomology ring whose restriction to any proper subgroup vanishes. We compute it by intersecting the kernels of the restriction maps to all maximal subgroups.
It is known that the essential ideal can only be nonzero if the group is of prime power order and if the depth does not exceed the Duflot bound.
EXAMPLES:
We compute the cohomology rings for the dihedral group of order 8, the quaternion group of order 8, the semidihedral group of order 16, and some group which is not of prime power order:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: D = CohomologyRing(8,3, from_scratch=True) sage: D.make() sage: Q = CohomologyRing(8,4, from_scratch=True) sage: Q.make() sage: SD = CohomologyRing(16,8, from_scratch=True) sage: SD.make() sage: S6 = CohomologyRing(720,763,prime=2, from_scratch=True) sage: S6.make()
The quaternion group is the smallest group that has a nonvanishing essential ideal:
sage: Q.essential_ideal() a_1_0^2, a_1_0*a_1_1
The dihedral group and the group of order 720 (which is the symmetric group on 6 elements) have no essential classes, for different reasons:
sage: CohomologyRing.global_options('info') sage: S6.essential_ideal() H^*(SmallGroup(720,763); GF(2)): Compute essential_ideal The group is not of prime power order  there is no essential ideal 0 sage: D.essential_ideal() H^*(D8; GF(2)): Compute essential_ideal Compute depth Computation of depth interruptible with Ctrlc Compute filter_regular_parameters Compute raw_filter_degree_type Test filter regularity Filter degree type: [1, 2, 2] The depth exceeds the Duflot bound  there is no essential ideal 0
Of course, if one provides the set of maximal subgroups as optional parameter, then the result is the same, but it makes no use of the theoretical result:
sage: D.essential_ideal(D.group().MaximalSubgroups()) Compute essential_ideal > computing kernel of an induced map Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): lift in the source resolution lift in the target resolution to degree 1 lift in the source resolution lift in the target resolution to degree 2 H^*(SmallGroup(4,2); GF(2)): Compute order_matrix Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): Compute preimages by elimination H^*(D8; GF(2)): > intersecting two ideals > computing kernel of an induced map Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): lift in the source resolution lift in the target resolution to degree 1 lift in the source resolution lift in the target resolution to degree 2 Compute preimages by elimination H^*(D8; GF(2)): > intersecting two ideals > preparing output 0 sage: CohomologyRing.global_options('warn') sage: S6.essential_ideal(S6.group().MaximalSubgroups()) 0
The depths of
SD
coincides with the Duflot bound. However, it has no essential classes:sage: SD.essential_ideal() 0
There are, of course, elements that are essential with respect to only a subset of all subgroups:
sage: SD.essential_ideal([SD.group().Centre(),SD.group().CommutatorSubgroup(SD.group())]) a_1_0, b_1_1, b_3_1
We now consider a more difficult example: The Sylow 2subgroup of \(U_3(4)\), which is of order 64 and is thus contained in the local sources.
sage: H = CohomologyRing(64,245) sage: H H^*(Syl2(U3(4)); GF(2)) sage: I = H.essential_ideal() #long time
It turns out that there is exactly one essential class that decomposes into a product of other essential classes. Note that this cohomology ring is one of only two known examples in which the square of the essential ideal does not vanish. In previous Sage versions, there has been a bug in Singular’s
interred
command, so that a second element is printed that apparently is a multiple of the first. But now it is fine:sage: (I*I).NF('std(0)').interred() #long time a_4_8*a_6_8*a_1_0^3*a_1_3 sage: singular(H).set_ring() sage: singular('NF((a_4_8*a_6_8*a_1_0^3*a_1_3)^2, std(0))') 0
The second example was discovered using this package. It is the direct product of the cyclic group of order two and
SmallGroup(64,245)
. Again, there is precisely one essential class that can be written as a product of other essential classes.

expect_last_relation
()¶ Returns a degree up to which there will provably be further nonobvious relations.
ALGORITHM:
 If there are two different generators of degree \(d_1\) and \(d_2\) that are both not Duflot regular, then we expect a relation at least in degree \(d_1+d_2\).
 If there is a nilpotent generator in degree \(d\), then there will certainly be a relation in degree \(2d\). In the case of \(p\)groups with \(p>2\), that relation is obvious for \(d\) odd and is not counted, and only part 1. applies.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(27,3, from_scratch=True) sage: H.make(3) sage: H.expect_last_relation() 6
Indeed, there are two different nonregular generators of degree 3:
sage: H.7 a_3_4: 3Cocycle in H^*(E27; GF(3)) sage: H.8 a_3_5: 3Cocycle in H^*(E27; GF(3))

exportMonomials
()¶ Save previously computed standard monomials in a standard location.
NOTE:
This method is used when saving a cohomology ring. The saved standard monomials can be reloaded with
importMonomials()
, but this requires that the dictionaryself.Monomials
has the key'bla'
.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: H.make() sage: L1 = list(H.Monomials.items()) sage: L1.sort() sage: L1 [('b_1_0', b_1_0: 1Cocycle in H^*(D8; GF(2))), ('b_1_0b_1_0', (b_1_0)*(b_1_0): 2Cocycle in H^*(D8; GF(2))), ('b_1_0b_1_1', (b_1_0)*(b_1_1): 2Cocycle in H^*(D8; GF(2))), ('b_1_1', b_1_1: 1Cocycle in H^*(D8; GF(2))), ('b_1_1b_1_1', (b_1_1)*(b_1_1): 2Cocycle in H^*(D8; GF(2))), ('c_2_2', c_2_2: 2Cocycle in H^*(D8; GF(2)))] sage: H.exportMonomials() sage: H.Monomials={'bla':1} sage: H.importMonomials() sage: L2 = list(H.Monomials.items()) sage: L2.sort() sage: L1 == L2 True

filter_degree_type
()¶ Return the filter degree type of
self
.OUTPUT:
The filter degree type (list of integers) of a filter regular system of parameters of self, or
None
, if the cohomology computation is not finished yet.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: print(H.filter_degree_type()) None sage: H.make()
Since by default data are stored on disk, when we now compute the filter degree type (which in some cases is a very long computation!), the stored data are updated:
sage: print(H.filter_degree_type()) H^*(D8; GF(2)): Updating stored data after computation of filter degree type [1, 2, 2]

filter_regular_gready_parameters
(first_parameters=[], BreakPoint=None, ignore_nilpotent=True)¶ Permanently cached method: Greadily explore smallest degree filter regular parameters.
INPUT:
first_parameters
(optional list) – list of strings defining some filter regular parameters that come after the Duflot elementsBreakPoint
(optional integer) – maximal number of parameter candidates tested in each degree. DefaultNone
means unbounded.ignore_nilpotent
(optional bool, default True) – whether to ignore nilpotent generators in the enumeration of filter regular parameters; there are filter regular parameters that can be expressed without nilpotent generators, but we are not sure if the smallest degree parameters can be obtained in that way, too.
OUTPUT:
 A system of filter regular parameters.
 The filter degree type is computed and stored. If the filter degree type of this ring has been computed before, it is asserted that the results are equal. Also it is tested whether the result contradicts the strong form of Dave Benson’s regularity conjecture.
..ALGORITHM:
It is assumed that the completeness of the ring has already been proved. The function starts with a Duflot regular sequence and finds the new parameters by enumerating potential parameters in a greedy way.
..WARNING:
We do not guarantee that this routine will always succeed, as we have no proof. However, on all groups of order 64 and 81, it works, and on about 10 percent of cases it yields filter regular parameters in smaller degrees than our previous methods.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(64,32,from_scratch=True) sage: H.make() sage: H.filter_regular_parameters() ['c_4_11', 'b_1_1*b_3_6+b_1_1^4+b_2_3^2+b_2_2^2+b_2_1^2', 'b_1_1^3*b_3_6+b_2_3^2*b_1_1^2+b_2_2*b_1_1*b_3_6+b_2_2*b_2_3^2+b_2_2^2*b_1_1^2+b_2_1*b_2_3^2', 'b_1_1']
So, we have parameters in degrees 4, 4, 6 and 1. Note that after computing the filter degree type, the ring is automatically stored, in order to preserve the result of this potentially very difficult computation (a warning is logged):
sage: H.filter_degree_type() H^*(SmallGroup(64,32); GF(2)): Updating stored data after computation of filter degree type [1, 2, 3, 4, 4]
We delete the previous result, compute filter regular parameters in degrees 4, 2, 2 and 1, and find that the filter degree type coincides with what was computed above:
sage: H.delprop('fdt') sage: CohomologyRing.global_options('info') sage: H.filter_regular_gready_parameters() H^*(SmallGroup(64,32); GF(2)): Compute filter_regular_gready_parameters Computing quotient modulo Duflot regular sequence ['c_4_11'] Exploring 2nd filterregular parameter in degree 2 Determine degree 2 standard monomials explore_one_parameter: 8 = (21)^1*2^3 parameter candidates We found a parameter. > But it is not filterregular. We found a parameter. > It is filterregular. H^*(SmallGroup(64,32); GF(2)): Exploring 3rd filterregular parameter in degree 2 Determine degree 2 standard monomials explore_one_parameter: 4 = (21)^1*2^2 parameter candidates We found a parameter. > It is filterregular. H^*(SmallGroup(64,32); GF(2)): Exploring 4th filterregular parameter in degree 2 Determine degree 2 standard monomials explore_one_parameter: 2 = (21)^1*2^1 parameter candidates We found a parameter. > It is filterregular. ['c_4_11', 'b_2_2+b_2_1', 'b_2_3', 'b_1_1^2'] sage: H.fdt [1, 2, 3, 4, 4]

filter_regular_parameters
()¶ Permanently cached method: Return elements of the ring approximation guaranteed to yield parameters in cohomology.
OUTPUT:
A list of strings, describing polynomials in
self
, orNone
.THEORY:
(Powers of) Dickson elements in the polynomial part of the cohomology rings of maximal elementary abelian subgroups in a Sylow \(p\)subgroup \(S\) of a finite group \(G\) give rise to a filter regular homogeneous system of parameters of the mod\(p\) cohomology of \(G\) restricting to these Dickson elements, according to [Benson].
The degree of these parameters may be very large. In [GreenKing], in the case that \(G=S\) is of prime power order, we propose to consider only Dickson elements in a complement of the greatest central elementary abelian subgroup \(C\) of \(S\) in the maximal abelian subgroups. We can show that these can be simultaneously lifted to cohomology elements of \(G\), to which we refer as the restricted Dickson elements. A filter regular hsop is then given by a maximal Duflot regular sequence, followed by the restricted Dickson elements. Moreover, parameters can be simplified by factorisation, potentially after adding a nilpotent element. This often yields fairly small parameters, but the factorisation may be quite difficult in some examples.
In the case \(G\not=S\), it is in general impossible to lift a power of the Dickson elements in complements of \(C\). But if it is, the previous construction still yields a filter regular hsop. Therefore, we test whether the restricted Dickson elements of the cohomology of \(S\) happen to be stable. If they are, they yield a filter regular homogeneous system of parameters for the cohomology of \(S\), together with a Duflot regular sequence. A factorisation may further simplify the parameters.
Moreover, in either case, the last parameter found by the above construction could be replaced by any other parameter of smaller degree. See
find_small_last_parameter()
EXAMPLES:
Since we will access data from the cohomology of a subgroup, we will force its computation from scratch first:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: X = CohomologyRing(64,138,from_scratch=True) sage: X.make() sage: G = libgap.AlternatingGroup(8) sage: H = CohomologyRing(G,prime=2,GroupName='A8', from_scratch=True)
We first demonstrate what happens in the cohomology ring of a sylow subgroup:
sage: H.sylow_cohomology() is X True sage: H.sylow_cohomology().filter_regular_parameters() ['c_4_18', 'b_1_2^4+b_1_1^2*b_1_2^2+b_1_1^4+b_1_0^4+b_2_6^2+b_2_4*b_2_6+b_2_4^2', 'b_1_1^2*b_1_2^4+b_1_1^4*b_1_2^2+b_2_6^2*b_1_2^2+b_2_6^2*b_1_0^2+b_2_4*b_2_6*b_1_0^2+b_2_4*b_2_6^2+b_2_4^2*b_1_1*b_1_2+b_2_4^2*b_1_1^2+b_2_4^2*b_1_0^2+b_2_4^2*b_2_6', 'b_1_0']
For computing the cohomology of \(G\), we use the cohomology ring of an intermediate subgroup. It turns out that a filter regular hsop for the cohomology ring of that subgroup can be found by using Dickson elements in a complement of the centre of a Sylow subgroup:
sage: H.subgroup_cohomology() H^*(SmallGroup(192,1493); GF(2)) sage: H.subgroup_cohomology().filter_regular_parameters() ['c_4_10', 'b_1_0^4+b_2_2^2+b_2_0*b_2_2+b_2_0^2', 'b_3_6^2+b_3_2*b_3_5+b_3_2^2+b_2_2^2*b_1_0^2+b_2_0*b_2_2*b_1_0^2+b_2_0*b_2_2^2+b_2_0^2*b_1_0^2+b_2_0^2*b_2_2', 'b_1_0']
We try if we can do the same for the cohomology of \(G\):
sage: H.make(8) sage: H.duflot_regular_sequence() ['c_4_1'] sage: H.filter_regular_parameters()
So, a maximal Duflot regular sequence is already available, but the remaining parameters are not. We compute out to degree 14 and then obtain filter regular parameters.
sage: H.make(14) sage: H.filter_regular_parameters() ['b_3_1*b_5_2+b_2_0^4+c_4_1^2', 'b_3_1^4+b_3_0^4+b_6_2*b_3_1^2+b_6_2^2+b_2_0^3*b_6_2+c_4_1*b_3_1*b_5_2+b_2_0*c_4_1*b_3_1^2+b_2_0^2*c_4_1^2', 'b_7_6^2+b_3_1^3*b_5_2+b_6_2*b_3_1*b_5_2+b_2_0*b_6_2*b_3_1^2+b_2_0^3*b_3_1*b_5_2+b_2_0^4*b_6_2+b_2_0^2*c_4_1*b_3_1^2+b_2_0^2*c_4_1*b_6_2+c_4_1^2*b_3_0^2', 'b_6_2']

find_dickson
()¶ Temporarily cached method: Find classes of self that simultaneously restrict to the Dickson classes for special subgroups.
NOTE:
The method first checks if the current ring approximation contains parameters. If this is not the case (e.g., if a maximal Duflot regular sequence can not be found yet) then nothing is done. If Dickson invariants have been previously constructed (perhaps by a different method) then nothing is done as well.
OUTPUT:
The attribute
Dickson
(a list) is changed. The entries corresponding to factors of successfully lifted Dickson classes are strings that define a polynomial in the generators of self yielding the lift.If the group is not of prime power order, the restrictions of the parameters constructed by this method to any maximal elementary abelian subgroup in a Sylow subgroup are Dickson invariants.
If the group is a \(p\)group, the restrictions to a complement of the greatest central elementary abelian subgroup in any maximal elementary abelian subgroup are Dickson invariants.
EXAMPLES:
We use the option
useElimination
, in order to avoid that the Dickson classes will be lifted by a different method.sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(64,33, useElimination=True, from_scratch=True)
The group is of \(p\)rank 3 and its center has rank 1. So, we will eventually get two Dickson classes:
sage: H.pRank 3 sage: H.CenterRk 1 sage: H.Dickson [None, None]
We try whether the Dickson classes can be lifted after computing the ring structure out to degree 2:
sage: H.make(2) sage: H.find_dickson() False sage: H.Dickson [None, None]
In degree 4, still nothing is done. This is since there is no Duflot regular sequence yet.
sage: H.make(4) sage: H.find_dickson() False sage: H.Dickson [None, None] sage: H.duflot_regular_sequence() []
We compute out to degree 8, since we happen to know that there is the Duflot regular generator waiting. When using
make()
, the Dickson invariants would be automatically determined. So, we work around.sage: H.make(7) sage: H.next() sage: H.Dickson [None, None]
Now, we construct the Dickson elements manually, and find that indeed they could have been found in degree 4 already:
sage: H.find_dickson() True sage: H.Dickson ['b_4_6+b_2_1^2', 'b_3_4+b_3_2']

find_dickson_in_subgroup
(n)¶ If possible, return a lift of the Dickson classes (type <SingularElement> matrix) and the nilradical (type <SingularElement> ideal) of the \(n\)th special subgroup. Result is cached.
EXAMPLES:
We use the option
useElimination
, in order to avoid that the Dickson classes will be lifted by a different method.sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(64,33, useElimination=True, from_scratch=True) sage: H.make(3) sage: H.find_dickson_in_subgroup(2) (None, None) sage: H.find_dickson_in_subgroup(3) (None, None) sage: H.make(4) sage: H.find_dickson_in_subgroup(2) (b_4_6+b_2_1^2,b_3_3, a_1_0, a_1_1, b_2_2, b_3_2, b_3_4+b_3_3, b_3_3^2+b_2_1*b_4_6, b_4_4^2+b_2_1^2*b_4_6) sage: H.find_dickson_in_subgroup(3) (b_4_6,b_3_4+b_3_2, a_1_0, a_1_1, b_2_1, b_3_3+b_3_2, b_4_4, b_3_2^2+b_2_2^3, b_3_4^2+b_2_2*b_4_6)

find_small_last_parameter
(Par, maxdeg=None)¶ Permanently cached method: Find an element of smallest degree that can replace the last element of a given HSOP.
INPUT:
Par
: a list of parameters for the cohomology ring living in the current ring approximation, given by strings. The last entry may beNone
.maxdeg
: the maximal degree (int) in which a parameter will be sought. Default: The minimum of the degree of the current ring approximation and the degree ofP[1]
(if not None) minus one.
OUTPUT:
Either a string defining a parameter in degree at most
maxdeg
, orP[1]
if such parameter does not exist. A value error is raised, ifPar[:1]
can not be extended to a HSOP of the cohomology ring.THEORY:
A set \(P\) of elements of the ring approximation provides parameters for the cohomology ring if and only if the cohomology rings of all maximal elementary abelian subgroups are finite over the restrictions of \(P\). If the ring approximation is lacking relations in higher degrees, then \(P\) is not necessarily a hsop for the approximation as well.
We obtain \(P'\) from \(P\) by replacing the last parameter with a parameter of smallest degree, that is obtained by enumeration of elements in small degrees.
If \(P\) is filter regular then so is \(P'\), which is proved in [GreenKing].
NOTE:
In each degree, a default of at most 512 candidates are tested; this default can be altered by assigning a value to
pGroupCohomology.resolution.coho_options['NrCandidates']
. The reason for setting the default to such a small number is that both in the modified Benson criterion and in the HilbertPoincaré criterion we can do with an existence proof for parameters. So, it is normally not crucial to have a very small last parameter (though it may simplify the test for filter regularity).EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: H.make(1) sage: print(H) Cohomology ring of Dihedral group of order 8 with coefficients in GF(2) <BLANKLINE> Computed up to degree 1 Minimal list of generators: [b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))] Minimal list of algebraic relations: []
Hence, the ring approximation has a hsop formed by the two generators. But the method realises that this would not yield parameters for the cohomology and consequently raises an error:
sage: H.find_small_last_parameter(['b_1_0', None]) Traceback (most recent call last): ... ValueError: The input can not be extended to a hsop
Later it will turn out that the sum of the degree one generators, together with a generator in degree two, forms a homogeneous system of parameters. The program can verify it by restriction to maximal elementary abelian subgroups, and so the error vanishes. But we only know the ring out to degree one, and so we still don’t find a second parameter:
sage: P = ['b_1_0 + b_1_1', None] sage: print(H.find_small_last_parameter(P)) None
Computing one degree further, we have success:
sage: H.next() sage: CohomologyRing.global_options('info') sage: P[1] = H.find_small_last_parameter(P); P[1] H^*(D8; GF(2)): Compute find_small_last_parameter Computing complete Groebner basis Compute _parameter_restrictions Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): Compute restricted parameters Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): Compute restricted parameters H^*(D8; GF(2)): Compute _get_obvious_parameter Compute _parameter_restrictions compute radicals of restricted parameter ideal Compute _parameter_restrictions Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): Compute restricted parameters Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)): Compute restricted parameters H^*(D8; GF(2)): Determine degree 1 standard monomials Compute _get_obvious_parameter Determine degree 2 standard monomials > Last parameter found in degree 2 'c_2_2'
Let us verify that the two elements form a filter regular hsop:
sage: H.raw_filter_degree_type(P) Compute raw_filter_degree_type Test filter regularity Filter degree type: [1, 2, 2] ([1, 1, 1], [[0], [0], [1, 1]], [1, 2]) sage: CohomologyRing.global_options('warn')

fraction_field
()¶ EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() sage: H = CohomologyRing(8,3) sage: H.fraction_field() Traceback (most recent call last): ... TypeError: A cohomology ring is, in general, not an integral domain.

from_base_ring
(r)¶ Return a degree zero cohomology class.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: H.from_base_ring(GF(2)(1)) 1: 0Cocycle in H^*(D8; GF(2))

gen
(i)¶ Return generators of
self
.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make()
Generator number zero is 1 in the base ring of
H
:sage: H.0 1 sage: H.1 # indirect doctest c_2_2: 2Cocycle in H^*(D8; GF(2)) sage: H.2 b_1_0: 1Cocycle in H^*(D8; GF(2)) sage: print(H.1*H.2) 3Cocycle in H^*(D8; GF(2)), represented by [0 0 1 0]

gens
()¶ Return the list of generators of
self
.NOTE:
We consider the scalar
1
as a generator. The list of generators may change if an incomplete cohomology computation is continued.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: H.make(1) sage: H.gens() [1, b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))] sage: H.make() sage: H.gens() [1, c_2_2: 2Cocycle in H^*(D8; GF(2)), b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))]

group
()¶ Return the group over which
self
is defined, as a permutation group.OUTPUT:
Let \(G\) be the group for which self is defined. Recall that in the case of prime power groups it is assumed that the first, say \(n\), generators of \(G\) form a minimal generating set. Then, the output of
group()
is a permutation group \(G_P\), defined in the libgap interface, with precisely \(n\) generators, so that mapping generator \(i\) of \(G\) to generator \(i\) of \(G_P\), for \(i=1,...,n\), results in a group isomorphismNOTE:
CohomologyRing(self.group())
is always equal toself
. It is often even identical withself
, namely if the Small Groups address can be determined, as in the following example.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: H.make() sage: G = H.group() sage: G Group([ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ]) sage: H1 = CohomologyRing(G, GroupName='NewD8') sage: H is H1 True

group_is_abelian
()¶ Permanently cached method: Tell whether the associated group is abelian.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: CohomologyRing(8,3).group_is_abelian() False sage: CohomologyRing(8,2).group_is_abelian() True

hom
(m, other, M=None, d=0)¶ Create an induced homomorphism.
INPUT:
m
, which usually is a group homomorphism defined in the libgap interface, but in principle could also be aMatrix_gfpn_dense
matrix describing a homomorphism of the group algebras (not documented). The domain must be equivalent to the underlying group ofother
, the codomain must be equivalent to the underlying group ofself
.other
, a cohomology ringM
(optionalMatrix_gfpn_dense
matrix): By this matrix one could prescribe a mapping of the first terms of the respective resolutions (not documented, and not needed for induced maps of group homomorphisms).d
(optional, default 0): Degree of the map. If it is nonzero thenM
must be provided.
NOTE:
The resulting homomorphism is cached.
EXAMPLES:
We first create the cohomology rings for two different presentations of the dihedral group of order 8.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: G1 = libgap.SmallGroup(8,3) sage: H1 = CohomologyRing(8,3) sage: H1.make() sage: G2 = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make()
In order to obtain reproducible doc tests, we switch to permutation groups that are, from the perspective of our programs, equivalent to
G1
andG2
, and provide an explicit group isomorphism:sage: phi = libgap.eval('GroupHomomorphismByImages( Group( [ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ] ), Group( [ (1,5)(2,6)(3,8)(4,7), (1,3,2,4)(5,7,6,8) ] ), [ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ], [ (1,5)(2,6)(3,8)(4,7), (1,8)(2,7)(3,6)(4,5) ] )') sage: H1.group()==phi.Source() True sage: H2.group().canonicalIsomorphism(phi.Range()) != libgap.eval('fail') True sage: phi.IsInjective() true sage: phi.IsSurjective() true
After ensuring that
phi
is printed nicely, we obtain the induced map:sage: phi.SetName('phi') sage: phi_star = H2.hom(phi,H1) sage: phi_star phi^* sage: phi_star.domain() H^*(DihedralGroup(8); GF(2)) sage: phi_star.codomain() H^*(D8; GF(2)) sage: [H1.element_as_polynomial(phi_star(X)) for X in H2.gens()] [1: 0Cocycle in H^*(D8; GF(2)), b_1_1^2+c_2_2: 2Cocycle in H^*(D8; GF(2)), b_1_1+b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))]
The induced maps are cached:
sage: phi_star is H2.hom(phi,H1) True sage: phi_star is loads(dumps(phi_star)) True
Cohomology rings of prime power and non prime power groups can be freely combined. We compute the mod2 cohomology ring of some group of order 48. The ring presentation depends on the choice of a generating system for its Sylow 2subgroup. Since an internal computation would yield a randomised result, we provide a Sylow 2subgroup explicitly.
sage: G = libgap.SmallGroup(48,36) sage: g1,g2,g3,g4,g5 = G.GeneratorsOfGroup() sage: S = g1.Group(g1*g2*g3,g2,g4) sage: HG = CohomologyRing(G,prime=2,Subgroup=S,GroupName='SmallGroup(48,36)', from_scratch=True) sage: HG.make()
There is an embedding of the dihedral group into
G
, and a quotient ofG
is isomorphic to the dihedral group.sage: G1toG = G1.GroupHomomorphismByImages(G, G1.GeneratorsOfGroup(), [g1*g2,g1*g2*g3,g4]) sage: g11,g12,g13 = G1.GeneratorsOfGroup() sage: GtoG1 = G.GroupHomomorphismByImages(G1, G.GeneratorsOfGroup(),[g12*g13,g13,g11*g12,g13,G1.Identity()]) sage: GtoG1.Image().IdGroup() [ 8, 3 ] sage: G1toG.Image().IdGroup() [ 8, 3 ] sage: GtoG1_star = H1.hom(GtoG1,HG) sage: G1toG_star = HG.hom(G1toG,H1) sage: [H1.element_as_polynomial(G1toG_star(x)) for x in HG.gens()] [1: 0Cocycle in H^*(D8; GF(2)), c_2_2: 2Cocycle in H^*(D8; GF(2)), b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2)), b_1_0: 1Cocycle in H^*(D8; GF(2))] sage: [HG.element_as_polynomial(GtoG1_star(x)) for x in H1.gens()[1:]] [b_1_1*c_1_2+b_1_0*c_1_2+c_2_5+c_1_2^2: 2Cocycle in H^*(SmallGroup(48,36); GF(2)), b_1_1: 1Cocycle in H^*(SmallGroup(48,36); GF(2)), b_1_0: 1Cocycle in H^*(SmallGroup(48,36); GF(2))]
And finally, we consider a homomorphism from
G
toG
, by composition of the previous homomorphisms:sage: GtoG = G1toG.CompositionMapping(GtoG1) sage: GtoG_star = HG.hom(GtoG,HG) sage: [HG.element_as_polynomial(GtoG_star(x)) for x in HG.gens()[1:]] [b_1_1*c_1_2+b_1_0*c_1_2+c_2_5+c_1_2^2: 2Cocycle in H^*(SmallGroup(48,36); GF(2)), b_1_1: 1Cocycle in H^*(SmallGroup(48,36); GF(2)), b_1_0: 1Cocycle in H^*(SmallGroup(48,36); GF(2)), b_1_1: 1Cocycle in H^*(SmallGroup(48,36); GF(2))]
GtoG
should coincide with the composition of the previous two induced homomorphisms, and indeed it does:sage: GtoG1_star*G1toG_star == GtoG_star True

htmlpage
(user=None)¶ Create a html page describing
self
OUTPUT:
A html file describing the cohomology ring
H
is written toos.path.join(H.root,repr(H.group().Order()),'web',H.GStem+'.html')
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: H.make() sage: H.htmlpage() sage: import os sage: print(open(os.path.join(H.root,'%dweb'%H.group().Order(),H.GStem+'.html')).read()) <html> <head> <title>Cohomology of Group number 3 of Order 8 </title> <!#config timefmt="%d.%m.%Y" > </head> <body> <BLANKLINE> <a name = "general"></a><h2> Cohomology of group number 3 of order 8 </h2> <p> <table border="1"> <tr> <td><a href="#general">About the group</a></td> <td><a href="#generators">Ring generators</a></td> <td><a href="#relations">Ring relations</a></td> <td><a href="#completion">Completion information</a></td> <td><a href="#restrict">Restriction maps</a></td> </tr> </table> <BLANKLINE> <p><hr></p> <h3> General information on the group </h3> <p><ul> <li> The group is also known as D8, the Dihedral group of order 8. </li> <li>The group has 2 minimal generators and exponent 4. </li> <li> It is nonabelian. </li> <li> It has pRank 2. </li> <li> Its centre has rank 1. </li> <li> It has 2 conjugacy classes of maximal elementary abelian subgroups, which are all of rank 2. </li> </ul></p> <p><hr></p> <h3> Structure of the cohomology ring </h3> <h4> General information </h4> <p><ul> <li> The cohomology ring is of dimension 2 and depth 2. </li> <li> The depth exceeds the Duflot bound, which is 1. </li> <li> The Poincaré series is <table style="color:black"><tr><td align="center"><nobr>1</nobr></td></tr> <tr><td><hr style="color:black"></td></tr><tr><td align="center"><nobr>( − 1  +  t)<sup>2</sup></nobr></td></tr> </table> </li> <li> The ainvariants are ∞,∞,2. They were obtained using the filter regular HSOP of the <a href="#completion">Symonds test</a>. </li> <li> The filter degree type of any filter regular HSOP is [1, 2, 2]. </li> </ul></p> <BLANKLINE> <BLANKLINE> <a name = "generators"></a> <p> <table border="1"> <tr> <td><a href="#general">About the group</a></td> <td><a href="#generators">Ring generators</a></td> <td><a href="#relations">Ring relations</a></td> <td><a href="#completion">Completion information</a></td> <td><a href="#restrict">Restriction maps</a></td> </tr> </table></p> <BLANKLINE> <h4> Ring generators </h4> <p>The cohomology ring has 3 minimal generators of maximal degree 2: </p> <ol> <li> <nobr>b_1_1</nobr>, an element of degree 1 </li> <li> <nobr>b_1_0</nobr>, an element of degree 1 </li> <li> <nobr>c_2_2</nobr>, a Duflot element of degree 2 </li> </ol> <BLANKLINE> <a name = "relations"></a> <p> <table border="1"> <tr> <td><a href="#general">About the group</a></td> <td><a href="#generators">Ring generators</a></td> <td><a href="#relations">Ring relations</a></td> <td><a href="#completion">Completion information</a></td> <td><a href="#restrict">Restriction maps</a></td> </tr> </table></p> <BLANKLINE> <h4> Ring relations </h4> <p>There is one minimal relation of degree 2: <ol> <li> <nobr>b_1_0·b_1_1</nobr> </li> </ol></p> <BLANKLINE> <a name = "completion"><p><hr></p></a> <p> <table border="1"> <tr> <td><a href="#general">About the group</a></td> <td><a href="#generators">Ring generators</a></td> <td><a href="#relations">Ring relations</a></td> <td><a href="#completion">Completion information</a></td> <td><a href="#restrict">Restriction maps</a></td> </tr> </table></p> <BLANKLINE> <h3> Data used for the Symonds test </h3> <p> <ul> <li> We proved completion in degree 2 using the Symonds criterion. </li> <li> The completion test was perfect: It applied in the last degree in which a generator or relation was found. </li> <li> The following is a filter regular homogeneous system of parameters: <ol> <li><nobr>c_2_2</nobr>, an element of degree 2 </li> <li><nobr>b_1_1 + b_1_0</nobr>, an element of degree 1 </li> </ol> </li> <li> A Duflot regular sequence is given by <nobr>c_2_2</nobr>. </li> <li> The Raw Filter Degree Type of the filter regular HSOP is [1, 1, 1]. </li> <li> We used the following parameters for the Symonds criterion: </li> <ol> <li><nobr>b_1_0</nobr>, an element of degree 1 </li> <li><nobr>b_1_1</nobr>, an element of degree 1 </li> <li><nobr>c_2_2</nobr>, an element of degree 2 </li> </ol> </li> <li> As a module over these parameters, the cohomology is generated in degree at most 0. </li> </ul></p> <p><a name="restrict"><hr></a></p> <p> <table border="1"> <tr> <td><a href="#general">About the group</a></td> <td><a href="#generators">Ring generators</a></td> <td><a href="#relations">Ring relations</a></td> <td><a href="#completion">Completion information</a></td> <td><a href="#restrict">Restriction maps</a></td> </tr> </table></p> <BLANKLINE> <h3> Restriction maps </h3> <h4> Restriction map to the greatest central el. ab. subgp., which is of rank 1 </h4> <ol> <li> <nobr>b_1_1</nobr> → <nobr>0</nobr>, an element of degree 1 </li> <li> <nobr>b_1_0</nobr> → <nobr>0</nobr>, an element of degree 1 </li> <li> <nobr>c_2_2</nobr> → <nobr>c_1_0<sup>2</sup></nobr>, an element of degree 2 </li> </ol> <BLANKLINE> <h4> Restriction map to a maximal el. ab. subgp. of rank 2 </h4> <ol> <li> <nobr>b_1_1</nobr> → <nobr>c_1_1</nobr>, an element of degree 1 </li> <li> <nobr>b_1_0</nobr> → <nobr>0</nobr>, an element of degree 1 </li> <li> <nobr>c_2_2</nobr> → <nobr>c_1_0·c_1_1 + c_1_0<sup>2</sup></nobr>, an element of degree 2 </li> </ol> <BLANKLINE> <h4> Restriction map to a maximal el. ab. subgp. of rank 2 </h4> <ol> <li> <nobr>b_1_1</nobr> → <nobr>0</nobr>, an element of degree 1 </li> <li> <nobr>b_1_0</nobr> → <nobr>c_1_1</nobr>, an element of degree 1 </li> <li> <nobr>c_2_2</nobr> → <nobr>c_1_0·c_1_1 + c_1_0<sup>2</sup></nobr>, an element of degree 2 </li> </ol> <BLANKLINE> <p><hr></p> <p> <table border="1"> <tr> <td><a href="#general">About the group</a></td> <td><a href="#generators">Ring generators</a></td> <td><a href="#relations">Ring relations</a></td> <td><a href="#completion">Completion information</a></td> <td><a href="#restrict">Restriction maps</a></td> </tr> </table></p> <BLANKLINE> <BLANKLINE> <br clear="all"> <P> <HR WIDTH="100%"> <HR WIDTH="100%"></P> Created with the <a href="http://www.sagemath.org/" style="fontvariant:smallcaps">Sage</a> <a href="https://users.fmi.unijena.de/cohomology/documentation/">cohomology package</a> written by <a href="https://users.fmi.unijena.de/~king/">Simon King</a> and <a href="https://users.fmi.unijena.de/~green/">David Green</a> <P> <HR WIDTH="100%"> <HR WIDTH="100%"></P> <p> <i>Last change: <!#echo var="LAST_MODIFIED" ></i> <hr> <BLANKLINE> </BODY> </HTML> <BLANKLINE>

importMonomials
()¶ Reload previously exported standard monomials.
NOTE:
This method is used when reloading a cohomology ring. There is no need to ever call this method explicitly, so, the following is not a use case.
The method requires that the dictionary self.Monomials has the key
'bla'
. Otherwise, the monomials, that are stored in some standard location, will not be reloaded.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: H.make() sage: L1 = list(H.Monomials.items()) sage: L1.sort() sage: L1 [('b_1_0', b_1_0: 1Cocycle in H^*(D8; GF(2))), ('b_1_0b_1_0', (b_1_0)*(b_1_0): 2Cocycle in H^*(D8; GF(2))), ('b_1_0b_1_1', (b_1_0)*(b_1_1): 2Cocycle in H^*(D8; GF(2))), ('b_1_1', b_1_1: 1Cocycle in H^*(D8; GF(2))), ('b_1_1b_1_1', (b_1_1)*(b_1_1): 2Cocycle in H^*(D8; GF(2))), ('c_2_2', c_2_2: 2Cocycle in H^*(D8; GF(2)))] sage: H.Monomials={'bla':1}
Since, by default, the cohomology ring was automatically saved, the monomials are available in some file. So, we can import them:
sage: H.importMonomials() sage: L2 = list(H.Monomials.items()) sage: L2.sort() sage: L2 == L1 True

is_isomorphic
(other)¶ Test whether two cohomology rings are isomorphic as graded rings.
INPUT:
other
, a cohomology ring
OUTPUT:
 False, if self is not isomorphic to the given other cohomology ring.
 None, if no conclusion on the isomorphy could be obtained.
 A tuple of strings defining the generator images in an isomorphism from self to other.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() sage: H173 = CohomologyRing(64, 173) sage: H176 = CohomologyRing(64, 176) sage: H173.make() sage: H176.make()
The rings are similar, but not identical:
sage: H173.rels() ['a_1_1*b_1_0+a_1_1^2', 'b_1_2^2+b_1_0*b_1_2', 'a_1_1^3', 'a_1_1*b_3_6', 'b_3_6^2+b_1_0^3*b_3_6+c_4_9*b_1_0^2+c_4_9*a_1_1^2'] sage: H176.rels() ['a_1_1*b_1_0+a_1_1^2', 'b_1_2^2+b_1_0*b_1_2', 'a_1_1^3', 'a_1_1*b_3_6', 'b_3_6^2+b_1_0^2*b_1_2*b_3_6+b_1_0^3*b_3_6+c_4_9*b_1_0^2+c_2_4*b_1_0^3*b_1_2+c_4_9*a_1_1^2']
The existence of an isomorphism will be determined by an enumeration of all possible ways to map the generators of the first ring to elements of the second ring. This would of course be a huge number, but it can be cut down by various tests (for instance, the ideal generated by the generator images need to have the same Poincaré series than the ideal generated by the mapped generators, and in some cases it is also helpful to take the Poincaré series of annihilators of ideals into account). Often, there only remains a single possibility to map some of the generators in a way that could potentially extend to an isomorphism.
In an attempt to keep the average computation time small, the number of possible assignments tested is cut off. If no conclusion can be made from these tests, then the cutoff is automatically adapted until a conclusion can be achieved:
sage: H173.is_isomorphic(H176) # long time ('1*c_2_4', '1*b_1_2*b_3_6+1*c_4_9+1*c_2_4*b_1_0*b_1_2', '1*a_1_1', '1*b_1_0', '1*b_1_2', '1*b_3_6')
We now demonstrate that even fairly similar cohomology rings can be shown to be nonisomorphic. In the following example, the Poincaré series, the generator degrees and the degrees of minimal relations coincide.
sage: H85 = CohomologyRing(64, 85) sage: H85.make() sage: H85.poincare_series() == H173.poincare_series() True sage: H85.degvec == H173.degvec True sage: H85.rels() ['a_1_0^2', 'a_1_1^2', 'a_1_0*b_1_2^2', 'a_1_0*a_3_6', 'a_3_6^2'] sage: H173.rels() ['a_1_1*b_1_0+a_1_1^2', 'b_1_2^2+b_1_0*b_1_2', 'a_1_1^3', 'a_1_1*b_3_6', 'b_3_6^2+b_1_0^3*b_3_6+c_4_9*b_1_0^2+c_4_9*a_1_1^2'] sage: CohomologyRing.global_options('info') sage: H85.is_isomorphic(H173) IsomorphismTest(H^*(SmallGroup(64,85); GF(2)), H^*(SmallGroup(64,173); GF(2))): Trying to find an isomorphism H^*(SmallGroup(64,85); GF(2)): Inserting SmallGroup(4,2) as a subgroup Inserting SmallGroup(8,5) as a subgroup Reconstructing subgroup data H^*(SmallGroup(64,173); GF(2)): Determine degree 1 standard monomials IsomorphismTest(H^*(SmallGroup(64,85); GF(2)), H^*(SmallGroup(64,173); GF(2))): gen(5) is rigid: b_1_2 > 1*b_1_0 H^*(SmallGroup(64,173); GF(2)): Determine degree 1 standard monomials IsomorphismTest(H^*(SmallGroup(64,85); GF(2)), H^*(SmallGroup(64,173); GF(2))): There cannot be a homomorphism, (gen(3)) cannot be mapped There cannot be a homomorphism, (gen(3)) cannot be mapped There cannot be a homomorphism, (gen(3)) cannot be mapped There cannot be a homomorphism, (gen(3)) cannot be mapped There is definitely no isomorphism False

item2html
(x)¶ Return a string that provides HTML code for the input.
INPUT:
Any object; but its intended use is for cohomology elements or for strings defining a polynomial.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: H.item2html(H.1) '<nobr>c_2_2</nobr>, a Duflot element of degree 2' sage: H.item2html(H.2*H.1^2) '<nobr>c_2_2<sup>2</sup>·b_1_0</nobr>, an element of degree 5' sage: H.item2html(H.poincare_series()) '<nobr>1/(t<sup>2 </sup> −  2·t  +  1)</nobr>'

label
()¶ Provide a short description of this cohomology ring.
NOTE:
In some cases, this is equal to the string representation.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.label() 'H^*(8gp3; GF(2))' sage: H H^*(D8; GF(2)) sage: H = CohomologyRing(64,167) sage: H H^*(SmallGroup(64,167); GF(2)) sage: H.label() 'H^*(64gp167; GF(2))'

last_interesting_degree
()¶ Presentation degree of the current ring approximation.
OUTPUT:
The highest degree of a generator or relation in the current ring approximation.
EXAMPLE:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace
In our example, we compute the mod2 cohomology of the Mathieu group \(M_{11}\).
sage: G = libgap.MathieuGroup(11) sage: H = CohomologyRing(G,prime=2,GroupName='M11', from_scratch=True)
The smallest generator is in degree three, so, we have:
sage: H.make(2) sage: H.last_interesting_degree() 0
The generator of highest degree is in degree 5, and there is no relation before degree 10. Hence, we obtain:
sage: H.make(9) sage: H.last_interesting_degree() 5
We now finish the cohomology computation.
sage: H.make() sage: H.last_interesting_degree() 10 sage: print(H) Cohomology ring of M11 with coefficients in GF(2) <BLANKLINE> Computation complete Minimal list of generators: [c_4_0: 4Cocycle in H^*(M11; GF(2)), b_3_0: 3Cocycle in H^*(M11; GF(2)), b_5_0: 5Cocycle in H^*(M11; GF(2))] Minimal list of algebraic relations: [b_5_0^2+c_4_0*b_3_0^2]

lift_dickson
(i, j)¶ Try to lift some power of some Dickson class.
INPUT:
 \(i = 0, 1, 2, ...\)  indicates which Dickson class of the maximal elementary abelian subgroups ought to be lifted.
 \(j = 0, 1, 2, ...\)  indicates which power of that Dickson class ought to be lifted.
OUTPUT:
If the underlying group is a finite \(p\)group then let \(n=p^j\), otherwise let \(n=j\). If it is possible to find a cochain of self that simultaneously restricts to the \(n\)th power of the \(i\)th Dickson classes of all maximal elementary abelian subgroups, potentially modified by nilpotent classes, then this cochain is returned.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: print(H.lift_dickson(0,0)) 1Cocycle in H^*(D8; GF(2)), represented by [1 1] sage: print(H.lift_dickson(0,1)) 2Cocycle in H^*(D8; GF(2)), represented by [1 1 0]
Indeed, the restrictions of these classes to the two maximal elementary abelian subgroups coincides with their Dickson classes, respectively the square of the Dickson classes:
sage: H.subgpDickson[4,2][0] == H.restriction_maps()[2][1](H.lift_dickson(0,0)) True sage: H.subgpDickson[4,2][0] == H.restriction_maps()[3][1](H.lift_dickson(0,0)) True sage: H.subgpDickson[4,2][0]**2 == H.restriction_maps()[2][1](H.lift_dickson(0,1)) True sage: H.subgpDickson[4,2][0]**2 == H.restriction_maps()[3][1](H.lift_dickson(0,1)) True

make
(max_deg=1)¶ Construct the visible ring structure.
INPUT:
max_deg
(optional positive integer): compute the complete ring structure at most up to degreemax_deg
. The default is a complete computation.
TESTS:
We first create a cohomology ring.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(32,5, from_scratch=True) sage: H.make(2) sage: print(H) Cohomology ring of Small Group number 5 of order 32 with coefficients in GF(2) <BLANKLINE> Computed up to degree 2 Minimal list of generators: [a_2_1: 2Cocycle in H^*(SmallGroup(32,5); GF(2)), c_2_2: 2Cocycle in H^*(SmallGroup(32,5); GF(2)), c_2_3: 2Cocycle in H^*(SmallGroup(32,5); GF(2)), a_1_0: 1Cocycle in H^*(SmallGroup(32,5); GF(2)), b_1_1: 1Cocycle in H^*(SmallGroup(32,5); GF(2))] Minimal list of algebraic relations: [a_1_0^2, a_1_0*b_1_1] sage: H.make() sage: print(H) Cohomology ring of Small Group number 5 of order 32 with coefficients in GF(2) <BLANKLINE> Computation complete Minimal list of generators: [a_2_1: 2Cocycle in H^*(SmallGroup(32,5); GF(2)), c_2_2: 2Cocycle in H^*(SmallGroup(32,5); GF(2)), c_2_3: 2Cocycle in H^*(SmallGroup(32,5); GF(2)), a_1_0: 1Cocycle in H^*(SmallGroup(32,5); GF(2)), b_1_1: 1Cocycle in H^*(SmallGroup(32,5); GF(2))] Minimal list of algebraic relations: [a_1_0^2, a_1_0*b_1_1, a_2_1*a_1_0, a_2_1^2]

make_groebner
(d=0)¶ Compute a Groebner basis for the relation ideal.
INPUT:
d
: (optional) degree bound. Default: no degree boundNOTE:
We keep track up to what degree a Groebner basis for the relation ideal is known. Hence, calling
make_groebner()
twice would only result in a recomputation if the relation ideal has changed in the meantime.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(27,3, from_scratch=True) sage: H.make(3) sage: CohomologyRing.global_options('info') sage: len(H.RelG) 5 sage: H.make_groebner(5) H^*(E27; GF(3)): Computing Groebner basis up to degree 5 sage: len(H.RelG) 8 sage: H.make_groebner() Computing complete Groebner basis
Since the Groebner basis is already completely known, it is avoided to repeat the computation when we now request a Groebner basis out to degree at least 5, which can be seen by the absence of any log messages:
sage: H.make_groebner(5)

massey_products
(all=True, *L)¶ All possible elements of
self
that realize the Massey product of the given input.INPUT:
C_1,C_2,...
: Elements of the cohomology ring.all
(optional, defaultTrue
): If it isFalse
, a set containing at most one cocycle is returned.
OUTPUT:
The set valued Massey product of
C_1,C_2,...
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: H.2 b_1_0: 1Cocycle in H^*(D8; GF(2)) sage: H.3 b_1_1: 1Cocycle in H^*(D8; GF(2)) sage: H.rels() ['b_1_0*b_1_1']
Since the product of
H.2
andH.3
vanishes, we can compute some triple Massey products, transforming the result into a sorted list for having reproducible doc tests:sage: sorted(list(H.massey_products(H.2,H.3,H.2))) [0: 2Cocycle in H^*(D8; GF(2)), b_1_0^2: 2Cocycle in H^*(D8; GF(2))] sage: sorted(list(H.massey_products(H.3,H.2,H.3))) [0: 2Cocycle in H^*(D8; GF(2)), b_1_1^2: 2Cocycle in H^*(D8; GF(2))]
Here is another example, for testing against a bug that occurred in a previous version of the code:
sage: H = CohomologyRing(16,2) sage: H.make() sage: sorted(list(H.massey_products(H.3*H.1,H.3,H.3*H.1))) [0: 6Cocycle in H^*(SmallGroup(16,2); GF(2)), c_2_1*c_2_2*c_1_0*c_1_1: 6Cocycle in H^*(SmallGroup(16,2); GF(2)), c_2_1^2*c_1_0*c_1_1: 6Cocycle in H^*(SmallGroup(16,2); GF(2)), c_2_1*c_2_2*c_1_0*c_1_1+c_2_1^2*c_1_0*c_1_1: 6Cocycle in H^*(SmallGroup(16,2); GF(2))]
If one is interested in only one element of the Massey product, one can use the optional parameter
all=False
:sage: H.massey_products(H.3*H.1,H.3,H.3*H.1,H.3*H.1, all=False) {c_2_1^4: 8Cocycle in H^*(SmallGroup(16,2); GF(2))}
There are various results on Massey products that can be used for testing our computations. We give one explicit computation in the documentation of
massey_power()
. Here, we test against a part of the Juggling Theorem (see [Ravenel] Section A1.4) that states\(\langle c_1,c_2,...,c_n\rangle c \subset \langle c_1,c_2,...,c_{n1},c_nc\rangle,\)where \(c,c_1,...,c_n\) are cocycles, and the multiplication on the left hand side is taken elementwise. For our example, we use the extraspecial 3group of order 27 and exponent 3:
sage: H = CohomologyRing(27,3) sage: H.make() sage: H.gens() [1, b_2_0: 2Cocycle in H^*(E27; GF(3)), b_2_1: 2Cocycle in H^*(E27; GF(3)), b_2_2: 2Cocycle in H^*(E27; GF(3)), b_2_3: 2Cocycle in H^*(E27; GF(3)), c_6_8: 6Cocycle in H^*(E27; GF(3)), a_1_0: 1Cocycle in H^*(E27; GF(3)), a_1_1: 1Cocycle in H^*(E27; GF(3)), a_3_4: 3Cocycle in H^*(E27; GF(3)), a_3_5: 3Cocycle in H^*(E27; GF(3))] sage: H.massey_products(H.6,H.6,H.6,all=False) {b_2_0: 2Cocycle in H^*(E27; GF(3))} sage: H.massey_products(H.6,H.6,H.6*H.5,all=False) {b_2_0^2*a_1_1*a_3_5+b_2_0^2*a_1_0*a_3_4b_2_0*c_6_8: 8Cocycle in H^*(E27; GF(3))}
Note that there is the summand
b_2_0*c_6_8
that we would expect. There remains to show that the other summands belong to the indeterminacy of the Massey product. More precisely, we show thatb_2_0^2*a_1_1*a_3_5+b_2_0^2*a_1_0*a_3_5
is a multiple ofH.6
:sage: H.6*(2*H.8*H.2*H.2+2*H.8*H.1*H.2 + H.1^2*H.9) == H('b_2_0^2*a_1_1*a_3_5+b_2_0^2*a_1_0*a_3_5') True
Hence,
H.massey_products(H.6,H.6,H.6*H.5)
containsb_2_0*c_6_8
.

next
(Forced=False, KeepDecomposables=False)¶ Compute generators and relations up to the next unknown degree.
TESTS:
We first create a cohomology ring.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, useElimination=True, from_scratch=True) sage: print(H) Cohomology ring of Dihedral group of order 8 with coefficients in GF(2) <BLANKLINE> Computed up to degree 0 Minimal list of generators: [] Minimal list of algebraic relations: [] sage: H.next() sage: print(H) Cohomology ring of Dihedral group of order 8 with coefficients in GF(2) <BLANKLINE> Computed up to degree 1 Minimal list of generators: [b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))] Minimal list of algebraic relations: [] sage: H.next() sage: print(H) Cohomology ring of Dihedral group of order 8 with coefficients in GF(2) <BLANKLINE> Computed up to degree 2 Minimal list of generators: [c_2_2: 2Cocycle in H^*(D8; GF(2)), b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))] Minimal list of algebraic relations: [b_1_0*b_1_1]

ngens
()¶ Return the number of generators of
self
.NOTE:
We consider the scalar
1
as a generator.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: H.ngens() 4 sage: len(H.gens()) 4

nil_preimage
(n)¶ Temporarily cached method: Preimage of the nilradical of the \(n\)th special subgroup.
INPUT:
n
: an integer indicating a special subgroupn=1
refers to the greatest central elementary abelian subgroupn>1
refers to a representative of conjugacy classes of maximal elementary abelian subgroups
OUTPUT:
An ideal in the Singular interface. It corresponds to the preimage of the nil radical of the cohomology of the \(n\)th special subgroup.
EXAMPLES:
We need to choose a \(p\)group with \(p>2\), since we would like to have an example where the cohomology of elementary abelian groups has nontrivial nil radical.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(27,3) sage: H.make() sage: H.nil_preimage(2) a_1_0, a_1_1, b_2_0, b_2_1, b_2_2, a_3_4, a_3_5 sage: _.parent() Singular sage: H.nil_preimage(3) a_1_0, a_1_1, b_2_1, b_2_2, b_2_3, a_3_4, a_3_5 sage: H.nil_preimage(4) a_1_0, a_1_1, b_2_1b_2_0, b_2_2, b_2_3b_2_0, a_3_4, a_3_5 sage: H.nil_preimage(5) a_1_0, a_1_1, b_2_1+b_2_0, b_2_2+b_2_0, b_2_3+b_2_0, a_3_4, a_3_5
A cohomology class is nilpotent if and only if its restriction to all maximal elementary abelian subgroups is nilpotent. Hence, the nil radical of
H
is the intersection of the above ideals, namely:sage: H.nil_preimage(2).intersect(H.nil_preimage(3)).intersect(H.nil_preimage(4)).intersect(H.nil_preimage(5)).groebner() a_1_0, a_1_1, a_3_4, a_3_5

nil_radical
()¶ Permanently cached method: Compute the nil radical of
self
.OUTPUT:
An ideal (Groebner basis) defined in the singular interface, representing the ideal of nilpotent elements of self.
THEORY:
An element of a cohomology ring is nilpotent if and only if its restriction to all maximal elementary abelian subgroups is nilpotent. Hence, we compute the intersection of the preimages of the nil radicals of the cohomology rings of the maximal elementary abelian subgroups. The ideal belongs to
singular(self)
.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(27,3) sage: H.make() sage: N = H.nil_radical() sage: singular(H).set_ring() sage: N a_1_0, a_1_1, a_3_4, a_3_5
It is not always the case that the nil radical is generated by nilpotent generators. Here is an example of order 64, that is part of the data base in this package. We verify that the generators of the nil radical are indeed nonzero and nilpotent:
sage: H = CohomologyRing(64,242) sage: H.make() sage: H.nil_radical() b_1_0*b_1_2+b_1_0^2, b_1_0*b_1_3+b_1_0*b_1_1+b_1_0^2 sage: print(H('b_1_0*b_1_2+b_1_0^2')) 2Cocycle in H^*(Syl2(L3(4)); GF(2)), represented by [1 0 1 0 0 0 0 0] sage: print(H('b_1_0*b_1_3+b_1_0*b_1_1+b_1_0^2')) 2Cocycle in H^*(Syl2(L3(4)); GF(2)), represented by [1 1 0 1 0 0 0 0] sage: print(H('b_1_0*b_1_2+b_1_0^2')^2) 4Cocycle in H^*(Syl2(L3(4)); GF(2)), represented by [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] sage: print(H('b_1_0*b_1_3+b_1_0*b_1_1+b_1_0^2')^2) 4Cocycle in H^*(Syl2(L3(4)); GF(2)), represented by [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
In a previous version, the nil radical of the cohomology ring of an abelian group was incorrectly computed. Let us test that it is fixed:
sage: H = CohomologyRing(16,2) sage: H.make() sage: H.nil_radical() c_1_0, c_1_1 sage: print(H) <BLANKLINE> Cohomology ring of Small Group number 2 of order 16 with coefficients in GF(2) <BLANKLINE> Computation complete Minimal list of generators: [c_2_1: 2Cocycle in H^*(SmallGroup(16,2); GF(2)), c_2_2: 2Cocycle in H^*(SmallGroup(16,2); GF(2)), c_1_0: 1Cocycle in H^*(SmallGroup(16,2); GF(2)), c_1_1: 1Cocycle in H^*(SmallGroup(16,2); GF(2))] Minimal list of algebraic relations: [c_1_0^2, c_1_1^2]

nilspace
(d)¶ Return a basis of the space of nilpotent elements in degree \(d\).
INPUT:
 \(d\), the degree (integer)
OUTPUT:
 A list of elements of
self
forming a basis of the degree \(d\) nilpotent elements.
NOTE:
The method
nil_radical()
returns the ideal formed by all nilpotent elements, which probably is more useful in practical applications. However, it may happen that the nil radical can not easily be computed, and then it may be helpful to compute it degree by degree.Warning
This method is only implemented in characteristic 2!
ALGORITHM:
An element of a mod\(2\) cohomology ring of a finite group \(G\) is nilpotent if and only if the restrictions to all maximal \(2\)elementary abelian subgroups of \(G\) is zero.
See also
EXAMPLES:
The following three cohomology rings have the same generator degrees and Poincaré series:
sage: from pGroupCohomology import CohomologyRing sage: H1 = CohomologyRing(64, 18) sage: H2 = CohomologyRing(64, 19) sage: H3 = CohomologyRing(64, 25) sage: H1.poincare_series() == H2.poincare_series() == H3.poincare_series() True sage: H1.degvec == H2.degvec == H3.degvec True
However, the cohomology rings are not isomorphic, which is shown by the Poincaré series of their nil radicals. We compute the difference with the Poincaré series of the cohomology ring, since this tells the dimension of the nil radical in each degree:
sage: p1 = H1.poincare_series()  H1._poincare_series_of_ideal_(H1.nil_radical()) sage: p2 = H2.poincare_series()  H2._poincare_series_of_ideal_(H2.nil_radical()) sage: p3 = H3.poincare_series()  H3._poincare_series_of_ideal_(H3.nil_radical()) sage: p1!=p2!=p3!=p1 True sage: P.<t> = PowerSeriesRing(QQ) sage: P(p1.numerator())/p1.denominator() 2*t + 2*t^2 + 4*t^3 + 4*t^4 + 6*t^5 + 8*t^6 + 9*t^7 + 10*t^8 + 13*t^9 + 14*t^10 + 17*t^11 + 18*t^12 + 21*t^13 + 24*t^14 + 26*t^15 + 28*t^16 + 32*t^17 + 34*t^18 + 38*t^19 + 40*t^20 + O(t^21) sage: P(p2.numerator())/p2.denominator() 2*t + 2*t^2 + 4*t^3 + 4*t^4 + 4*t^5 + 6*t^6 + 7*t^7 + 8*t^8 + 11*t^9 + 12*t^10 + 15*t^11 + 16*t^12 + 17*t^13 + 20*t^14 + 22*t^15 + 24*t^16 + 28*t^17 + 30*t^18 + 34*t^19 + 36*t^20 + O(t^21) sage: P(p3.numerator())/p3.denominator() 2*t + 2*t^2 + 4*t^3 + 4*t^4 + 5*t^5 + 7*t^6 + 8*t^7 + 9*t^8 + 12*t^9 + 13*t^10 + 16*t^11 + 17*t^12 + 19*t^13 + 22*t^14 + 24*t^15 + 26*t^16 + 30*t^17 + 32*t^18 + 36*t^19 + 38*t^20 + O(t^21)
Hence, we expect to see different dimensions of the nil radical starting in degree 5. Let is compare with the results of a degreewise computation:
sage: [len(H1.nilspace(d)) for d in range(10)] [0, 2, 2, 4, 4, 6, 8, 9, 10, 13] sage: [len(H2.nilspace(d)) for d in range(10)] [0, 2, 2, 4, 4, 4, 6, 7, 8, 11] sage: [len(H3.nilspace(d)) for d in range(10)] [0, 2, 2, 4, 4, 5, 7, 8, 9, 12]
Here are explicit bases in degree 5:
sage: H1.nilspace(5) [a_5_8: 5Cocycle in H^*(SmallGroup(64,18); GF(2)), a_5_5: 5Cocycle in H^*(SmallGroup(64,18); GF(2)), ((b_2_3)**2)*(a_1_1): 5Cocycle in H^*(SmallGroup(64,18); GF(2)), ((b_2_2)**2)*(a_1_0): 5Cocycle in H^*(SmallGroup(64,18); GF(2)), (a_2_0)*(b_3_5): 5Cocycle in H^*(SmallGroup(64,18); GF(2)), (a_2_0)*(b_3_4): 5Cocycle in H^*(SmallGroup(64,18); GF(2))] sage: H2.nilspace(5) [((b_2_2)**2)*(a_1_1): 5Cocycle in H^*(SmallGroup(64,19); GF(2)), (a_2_1)*(b_3_5): 5Cocycle in H^*(SmallGroup(64,19); GF(2)), (a_2_0)*(b_3_5): 5Cocycle in H^*(SmallGroup(64,19); GF(2)), (a_2_0)*(b_3_4): 5Cocycle in H^*(SmallGroup(64,19); GF(2))] sage: H3.nilspace(5) [a_5_4: 5Cocycle in H^*(SmallGroup(64,25); GF(2)), ((b_2_2)**2)*(a_1_1): 5Cocycle in H^*(SmallGroup(64,25); GF(2)), ((b_2_2)**2)*(a_1_0): 5Cocycle in H^*(SmallGroup(64,25); GF(2)), (a_2_1)*(b_3_5): 5Cocycle in H^*(SmallGroup(64,25); GF(2)), (a_2_0)*(b_3_5): 5Cocycle in H^*(SmallGroup(64,25); GF(2))]

nrels
()¶ Return the minimal number of relations of
self
.NOTE:
The list of relations may change if an incomplete cohomology computation is continued.
For \(p>2\), any generator \(x\) of odd degree of the modular cohomology ring of a finite \(p\)group gives rise to the relation \(x^2=0\). We refer to such relation as obvious. In the current version of our package, we count only the nonobvious relations, but this might change in future versions.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(16,3, from_scratch=True) sage: H.make(2) sage: H.nrels() 2 sage: H.make() sage: H.nrels() 4 sage: len(H.rels()) 4

order_matrix
()¶ Temporarily cached method: Return an integer matrix that defines the term order of
self
.Even if the order is \(dp\), a matrix is returned.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(32,6, from_scratch=True) sage: H.make(2) sage: H.order_matrix() [ 2 2 2 1 1] [ 0 0 0 1 0] [1 0 0 0 0] [ 0 1 0 0 0] [ 0 0 1 0 0] sage: H.make() sage: H.order_matrix() [ 2 2 2 4 1 1 3 3] [ 0 0 0 1 0 0 0 0] [ 0 0 0 0 1 0 0 0] [1 0 0 0 0 0 0 0] [ 0 1 0 0 0 0 0 0] [ 0 0 1 0 0 0 0 0] [ 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 0 1 0] sage: tmp = tmp_dir() sage: CohomologyRing.set_workspace(tmp) sage: H = CohomologyRing(32,6, from_scratch=True) sage: H.setprop('use_dp',True) sage: H.make(2) sage: H.order_matrix() [ 2 2 2 1 1] [ 0 0 0 0 1] [ 0 0 0 1 0] [ 0 0 1 0 0] [ 0 1 0 0 0] sage: H.make() sage: H.order_matrix() [ 2 2 2 4 1 1 3 3] [ 0 0 0 0 0 0 0 1] [ 0 0 0 0 0 0 1 0] [ 0 0 0 0 0 1 0 0] [ 0 0 0 0 1 0 0 0] [ 0 0 0 1 0 0 0 0] [ 0 0 1 0 0 0 0 0] [ 0 1 0 0 0 0 0 0]

parameters
(**kwds)¶ Permanently cached method: Return small parameters that are algebraically independent.
OUTPUT:
None
, if the ring approximation does not contain parameters for the cohomology ring. Otherwise, a sequence of elements, forming a hsop of the cohomology ring, but not necessarily of the ring approximation.THEORY:
We start with a filterregular hsop, as provided by
filter_regular_parameters()
. Then, we try to replace any of these parameters by a parameter of smaller degree. The result is not guaranteed to be filter regular, of course.NOTE:
Compared with previous versions of this spkg, the heuristics to find parameters in smaller degrees has substantially improved in version 2.1.4.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: G = libgap.AlternatingGroup(8) sage: H = CohomologyRing(G,prime=2,GroupName='A8', from_scratch=True) sage: H.make(7)
In this example, it was not automatically attempted to lift Dickson elements. Since the Dickson elements are the starting point of parameter construction in this case, we do not find parameters, even though they do exist:
sage: H.parameters() sage: H.verify_parameters_exist() True
We now use elimination to find paramters:
sage: H.find_dickson() True
The result of
parameters()
is cached as long as the ring structure doesn’t change. Here, the ring structure has changed since the previous call to the method, and indeed we can now find parameters:sage: H.parameters() ['b_2_0^2+c_4_1', 'b_3_1^4+b_3_0^4+b_6_2*b_3_1^2+b_6_2^2+b_2_0^3*b_6_2+c_4_1*b_3_1*b_5_2+b_2_0*c_4_1*b_3_1^2+b_2_0^2*c_4_1^2', 'b_7_6+c_4_1*b_3_1+c_4_1*b_3_0', 'b_6_2']
These elements are guaranteed to form a homogeneous system of parameters of the cohomology ring, but they are not parameters of the current ring approximation:
sage: I = H.relation_ideal() sage: singular.eval('degBound = 0') '' sage: print(singular.eval('dim(groebner(%s+ideal(%s)))'%(I.name(), ','.join(H.parameters())))) 4
Continuing to degree 14, thus, having more relations, the above parameters do indeed turn into parameters for the ring approximation:
sage: H.make(14) sage: I = H.relation_ideal() sage: print(singular.eval('dim(groebner(%s+ideal(%s)))'%(I.name(), ','.join(H.parameters())))) 0

poincare_series
(test_duality=False)¶ Temporarily cached method: Return the Poincaré series of
self
, a univariate rational function.ALGORITHM:
If Benson’s criterion was used to proof completeness of the ring structure, it was needed to verify that certain parameters of the ring are filter regular. This involves computing kernel and quotients of multiplication maps. These data are saved, and now used for the computation of the Poincaré series.
Otherwise, some standard way of computation from commutative algebra is used.
INPUT:
test_duality
– (bool, defaultFalse
) If this argument isTrue
and``self`` is already completed and happens to be CohenMacaulay, a self consistence check is applied, based on BensonCarlson duality [BensonCarlson].EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: H.poincare_series() 1/(t^2  2*t + 1)

potential_degree_bound
(FRS, dv, forced=1, previous_bound=None)¶ Return the potential degree bound obtained from the modified Benson test.
INPUT:
FRS
: a list of polynomials (given by strings)DV
: the list of degrees of the polynomials fromFRS
forced
(optional int); let \(n\) be the degree up to which the cohomology is known If
forced == 2
: return the best possible bound, even if it is smaller than \(n\)  If
forced == 1
: the best potential bound, if it is greater than \(n\), or some potential bound if it is at most \(n\).
 If
ASSUMPTION:
FRS
were a filter regular HSOP, provided self was completely computed.THEORY:
See [GreenKing], Proposition 3.2 and Theorem 3.3.
EXAMPLES:
We first create a cohomology ring. For constructing Dickson classes, we use the linear algebra method.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(27,3, useElimination=False, from_scratch=True)
The computational steps in this example will internally be done by
H.make()
. Here, we do them step by step.sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.next() sage: H.gens() [1, b_2_0: 2Cocycle in H^*(E27; GF(3)), b_2_1: 2Cocycle in H^*(E27; GF(3)), b_2_2: 2Cocycle in H^*(E27; GF(3)), b_2_3: 2Cocycle in H^*(E27; GF(3)), c_6_8: 6Cocycle in H^*(E27; GF(3)), a_1_0: 1Cocycle in H^*(E27; GF(3)), a_1_1: 1Cocycle in H^*(E27; GF(3)), a_3_4: 3Cocycle in H^*(E27; GF(3)), a_3_5: 3Cocycle in H^*(E27; GF(3))]
During these computations, Dickson classes have been computed. We found:
sage: H.Dickson ['b_2_3^2b_2_0*b_2_2b_2_0*b_2_1+b_2_0^2']
It is known that the Duflot regular generator
c_6_8
and the Dickson class form a filter regular homogeneous HSOP ofH
, provided the computation is complete. However, Benson’s criterion would only apply in degree 5+3+1=9. Now we test whether it is possible to replace the Dickson class by a parameter of smaller degree over some finite extension field. If there is more than one Dickson class, we would potentially replace several (but not necessarily all) of them. Note that our method is not constructive – we just show the existence of a filter regular HSOP! In general, it is inevitable to extend the coefficient field.sage: H.potential_degree_bound(['c_6_8','b_2_3^2b_2_0*b_2_2b_2_0*b_2_1+b_2_0^2'],[6,4]) 7
The previous line means: If
['c_6_8','b_2_3^2b_2_0*b_2_2b_2_0*b_2_1+b_2_0^2']
gives rise to a filter regular HSOP of a ring approximation out to degree at least seven, and if the \(n\)th term of the resulting filter degree type is not greater than \(n\) for all but the last term, then the ring approximation is complete. Indeed:sage: H.raw_filter_degree_type(['c_6_8','b_2_3^2b_2_0*b_2_2b_2_0*b_2_1+b_2_0^2']) ([1, 1, 8], [[0], [0], [1, 2, 4, 6, 6, 6, 4, 2, 1]], [6, 4]) sage: H.filter_degree_type() [1, 2, 2]
So, we have shown that the cohomology computation is complete.

printed_group_name
()¶ Group identifier used for printing.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.reset() sage: CohomologyRing(8,3).printed_group_name() 'D8' sage: CohomologyRing(64,167).printed_group_name() 'SmallGroup(64,167)'

properties
()¶ List the names of the custom attributes set with
setprop()
.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: sorted(H.properties()) ['DicksonExp', 'GroupDescr', 'GroupName', 'KeepBases', '_key', 'auto', 'root', 'sgpDickson', 'useElimination', 'useFactorization']
During the computation, more properties are added:
sage: H.make() sage: sorted(H.properties()) ['DicksonExp', 'GroupDescr', 'GroupName', 'KeepBases', '_SymondsTestdata', '_key', '_max_module_deg', '_method', '_parameters_for_criterion', 'auto', 'completeGroebner', 'root', 'sgpDickson', 'useElimination', 'useFactorization']

raw_filter_degree_type
(FRS)¶ Temporarily cached method: Test whether a given list of elements forms a filterregular HSOP.
INPUT:
FRS
: a list of strings defining elements of the cohomology ring
OUTPUT:
None
, if the input is not a filter regular HSOP. Otherwise, a triple of lists of numbers is returned:
 The “raw filter degree type” of that HSOP
 Data that are of internal use to compute the Poincaré series
 The degree vector of the parameters.
EXAMPLES:
We first create a cohomology ring. For constructing Dickson classes, we use the elimination method.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, useElimination=True, from_scratch=True) sage: H.next() sage: H.next() sage: H.next()
Of course, Dickson classes are not there, yet, so we construct them.
sage: H.Dickson [None] sage: H.find_dickson() True sage: H.Dickson ['b_1_1+b_1_0']
There is one Duflot regular class:
sage: [X for X in H.Gen if X.rdeg()] [c_2_2: 2Cocycle in H^*(D8; GF(2))]
So, if the computation was complete,
c_2_2
andb_1_1+b_1_0
were a filter regular HSOP in degrees 2 and 1. This is indeed the case, as we verify now:sage: H.raw_filter_degree_type(['c_2_2','b_1_1+b_1_0']) ([1, 1, 1], [[0], [0], [1, 1]], [2, 1])
The raw filter degree type is the first item in the above triple. The filter degree type of that HSOP is now available:
sage: H.filter_degree_type() [1, 2, 2]
Now, we try a slightly different sequence of elements:
sage: H.raw_filter_degree_type(['c_2_2^2','b_1_0^2+b_1_1^2']) ([1, 1, 4], [[0], [0], [1, 2, 2, 2, 1]], [4, 2])
It is known that the filter degree type is the same for any filter regular HSOP. But apparently the raw filter degree type is different.

reconstructSubgroups
()¶ When loading a cohomology ring, the subgroups are not reconstructed immediately. This is done here.
NOTE:
It is not necessary to call this function manually. It is done automaticall as soon as the subgroups are requested.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H=CohomologyRing(8,3)
In this example, we do not want that the cohomology rings are cached. Hence, we destroy cache:
sage: CohomologyRing._cache.clear() sage: K = loads(dumps(H)) sage: K is H False
The point is that
subgps
is an attribute that is not immediately created when a cohomology ring is loaded. So, althoughH
has this attribute,K
hasn’t:sage: 'subgps' in H.__dict__ True sage: 'subgps' in K.__dict__ False
It is created using this method:
sage: K.reconstructSubgroups() sage: 'subgps' in K.__dict__ True
The method is automatically called when trying to access the
subgps
attribute:sage: for k,v in list(CohomologyRing._cache.items()): ....: if v is K: ....: del CohomologyRing._cache[k] sage: L = loads(dumps(K)) sage: 'subgps' in L.__dict__ False sage: CohomologyRing.global_options('info') sage: sorted(L.subgps.items()) H^*(D8; GF(2)): Inserting SmallGroup(4,2) as a subgroup Inserting SmallGroup(2,1) as a subgroup Reconstructing subgroup data [((2, 1), H^*(SmallGroup(2,1); GF(2))), ((4, 2), H^*(SmallGroup(4,2); GF(2)))]

reconstruct_singular
()¶ Reconstruct data after the Singular interface crashed.
NOTE:
We tried to make this method robust emough that computations involving Singular can be interrupted at any point.
EXAMPLES:
We start a cohomology computation and carry it out to degree 3.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=2, from_scratch=True) sage: H.make(3)
We now simulate a crash of Singular. After reconstructing the data, the computation can proceed as usual. By logging, we show what happens internally.
sage: singular.quit() sage: CohomologyRing.global_options('info') sage: H.reconstruct_singular() H^*(SmallGroup(720,763); GF(2)): Reconstructing data in the Singular interface H^*(D8xC2; GF(2)): Reconstructing data in the Singular interface H^*(SmallGroup(8,5); GF(2)): Reconstructing data in the Singular interface H^*(SmallGroup(4,2); GF(2)): Reconstructing data in the Singular interface
Even after the simulated crash, we can continue with the computation:
sage: CohomologyRing.global_options('warn') sage: H.make(7) sage: H.find_dickson() True sage: H.parameters() ['c_1_0', 'c_2_1', 'b_3_3+c_3_2'] sage: H.make() sage: print(H) Cohomology ring of SmallGroup(720,763) with coefficients in GF(2) <BLANKLINE> Computation complete Minimal list of generators: [c_2_1: 2Cocycle in H^*(SmallGroup(720,763); GF(2)), c_1_0: 1Cocycle in H^*(SmallGroup(720,763); GF(2)), b_3_3: 3Cocycle in H^*(SmallGroup(720,763); GF(2)), c_3_2: 3Cocycle in H^*(SmallGroup(720,763); GF(2))] Minimal list of algebraic relations: [b_3_3*c_3_2+c_2_1*c_1_0*b_3_3]
Note that this method is automatically called when Singular is called on the cohomology ring:
sage: CohomologyRing.global_options('info') sage: singular(H) polynomial ring, over a field, global ordering // coefficients: ZZ/2 // number of vars : 4 // block 1 : ordering M // : names c_2_1 c_1_0 b_3_3 c_3_2 // : weights 2 1 3 3 // : weights 1 1 0 1 // : weights 1 0 0 0 // : weights 0 1 0 0 // block 2 : ordering C // quotient ring from ideal _[1]=b_3_3*c_3_2+c_2_1*c_1_0*b_3_3 sage: singular.quit() sage: singular(H) H^*(SmallGroup(720,763); GF(2)): Reconstructing data in the Singular interface H^*(D8xC2; GF(2)): Reconstructing data in the Singular interface H^*(SmallGroup(8,5); GF(2)): Reconstructing data in the Singular interface H^*(SmallGroup(4,2); GF(2)): Reconstructing data in the Singular interface polynomial ring, over a field, global ordering // coefficients: ZZ/2 // number of vars : 4 // block 1 : ordering M // : names c_2_1 c_1_0 b_3_3 c_3_2 // : weights 2 1 3 3 // : weights 1 1 0 1 // : weights 1 0 0 0 // : weights 0 1 0 0 // block 2 : ordering C // quotient ring from ideal _[1]=b_3_3*c_3_2+c_2_1*c_1_0*b_3_3
TESTS:
The following used to fail in at some point in the development of this package.
sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(48,50, prime=2) sage: H.make() sage: c = H.subgroup_cohomology()('c_1_1*c_1_2^2*c_1_3^3+c_1_1*c_1_2^4*c_1_3+c_1_1*c_1_2^5+c_1_1^2*c_1_3^4+c_1_1^2*c_1_2*c_1_3^3+c_1_1^2*c_1_2^3*c_1_3+c_1_1^3*c_1_2^2*c_1_3+c_1_1^3*c_1_2^3+c_1_1^4*c_1_3^2+c_1_1^4*c_1_2*c_1_3+c_1_1^4*c_1_2^2+c_1_1^5*c_1_2+c_1_0*c_1_3^5+c_1_0*c_1_2^2*c_1_3^3+c_1_0*c_1_2^3*c_1_3^2+c_1_0*c_1_1^2*c_1_2*c_1_3^2+c_1_0*c_1_1^2*c_1_2^2*c_1_3+c_1_0*c_1_1^2*c_1_2^3+c_1_0*c_1_1^3*c_1_3^2+c_1_0*c_1_1^3*c_1_2^2+c_1_0*c_1_1^4*c_1_3+c_1_0*c_1_1^5+c_1_0^2*c_1_3^4+c_1_0^2*c_1_2^2*c_1_3^2+c_1_0^2*c_1_2^3*c_1_3+c_1_0^2*c_1_2^4+c_1_0^2*c_1_1*c_1_3^3+c_1_0^2*c_1_1*c_1_2^2*c_1_3+c_1_0^2*c_1_1^2*c_1_2*c_1_3+c_1_0^2*c_1_1^2*c_1_2^2+c_1_0^2*c_1_1^3*c_1_2+c_1_0^3*c_1_2*c_1_3^2+c_1_0^3*c_1_1*c_1_2^2+c_1_0^3*c_1_1^2*c_1_3+c_1_0^3*c_1_1^3+c_1_0^4*c_1_3^2+c_1_0^4*c_1_2*c_1_3+c_1_0^4*c_1_2^2+c_1_0^4*c_1_1*c_1_2+c_1_0^4*c_1_1^2+c_1_0^5*c_1_3+c_1_0^5*c_1_1') sage: d = H.stable_to_polynomial(c); d c_3_6^2+c_3_2*c_3_7+c_3_2*c_3_6+c_3_0*c_3_7+c_3_0*c_3_6+c_3_0*c_3_5+c_3_0*c_3_4+c_3_0*c_3_3+c_2_3^3+c_2_2*c_2_3^2+c_2_1^2*c_2_3+c_2_1^3+c_2_0*c_2_3^2+c_2_0*c_2_1*c_2_2+c_2_0*c_2_1^2+c_2_0^2*c_2_3: 6Cocycle in H^*(SmallGroup(48,50); GF(2)) sage: R = H.find_relations(6) sage: [r.name() for r in R[0]] ['c_3_6*c_3_7+c_3_6^2+c_2_3^3', 'c_3_6^2+c_2_3^3', 'c_3_4*c_3_7+c_3_4*c_3_6+c_2_1*c_2_3^2', 'c_3_4*c_3_7', 'c_3_2*c_3_6+c_2_1^2*c_2_3', 'c_3_2*c_3_7', 'c_3_0*c_3_7+c_3_0*c_3_6+c_2_1^2*c_2_2+c_2_1^3+c_2_0*c_2_2*c_2_3', 'c_3_0*c_3_7', 'c_3_6^2', 'c_3_4*c_3_7+c_2_2*c_2_3^2', 'c_3_4*c_3_6', 'c_3_2*c_3_6+c_2_1*c_2_2*c_2_3+c_2_0*c_2_3^2', 'c_3_2*c_3_7+c_3_2*c_3_6+c_2_1*c_2_2*c_2_3+c_2_1^2*c_2_3', 'c_3_2*c_3_7+c_2_1^2*c_2_3', 'c_2_1^3+c_2_0*c_2_2*c_2_3+c_2_0*c_2_1*c_2_3', 'c_2_1^2*c_2_2+c_2_1^3+c_2_0*c_2_1*c_2_3', 'c_3_0*c_3_7+c_2_1^2*c_2_2', 'c_3_0*c_3_6+c_2_1^2*c_2_2+c_2_0*c_2_2*c_2_3', 'c_3_0*c_3_5+c_3_0*c_3_4+c_2_0*c_2_1^2', 'c_3_0*c_3_5+c_2_0*c_2_1^2+c_2_0^2*c_2_3', 'c_3_0*c_3_4+c_2_0*c_2_1*c_2_2+c_2_0*c_2_1^2', 'c_3_0*c_3_5+c_3_0*c_3_4+c_2_0^2*c_2_3', 'c_3_0*c_3_5+c_2_0*c_2_1*c_2_2+c_2_0^2*c_2_3', 'c_3_0*c_3_2+c_2_0^2*c_2_1', 'c_3_0*c_3_3', 'c_3_0*c_3_2+c_2_0^2*c_2_2+c_2_0^2*c_2_1', 'c_3_0*c_3_3+c_2_0^2*c_2_1', 'c_3_0*c_3_1+c_3_0^2+c_2_0^3', 'c_3_0^2+c_2_0^3', 'c_3_0^2'] sage: singular.quit() sage: d == H.stable_to_polynomial(c) #indirect doc test H^*(SmallGroup(16,14); GF(2)): Reconstructing data in the Singular interface H^*(SmallGroup(48,50); GF(2)): Reconstructing data in the Singular interface True sage: R == H.find_relations(6) True

rel
(i)¶ Return a relation of
self
, represented by a string.NOTE:
For \(p>2\), any generator \(x\) of odd degree of the modular cohomology ring of a finite \(p\)group gives rise to the relation \(x^2=0\). We refer to such relation as obvious. In the current version of our package, we list only the nonobvious relations, but this might change in future versions.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(16,3) sage: H.make() sage: H.rels() ['a_1_0^2', 'a_1_0*b_1_1', 'b_2_1*a_1_0', 'b_2_1^2+c_2_2*b_1_1^2'] sage: H.rel(0) 'a_1_0^2' sage: H.rel(2) 'b_2_1*a_1_0'

relation_ideal
()¶ Return the relation ideal for the current ring approximation.
OUTPUT:
An ideal in the Singular interface. It is a Groebner basis at least out to the known degree of the ring approximation.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(192,1493,prime=2, from_scratch=True) sage: H.make(4) sage: H.set_ring() sage: H.relation_ideal() b_1_0*b_3_0+b_2_1^2+b_2_0*b_2_2, b_1_0*b_3_2, b_1_0*b_3_5, b_1_0*b_3_6 sage: H.make() sage: H.set_ring() sage: H.relation_ideal() b_1_0*b_3_0+b_2_1^2+b_2_0*b_2_2, b_1_0*b_3_2, b_1_0*b_3_5, b_1_0*b_3_6, b_2_0*b_3_6+b_2_0*b_3_5, b_2_1*b_3_2+b_2_0*b_3_5, b_2_1*b_3_5+b_2_0*b_3_5, b_2_1*b_3_6+b_2_0*b_3_5, b_2_2*b_3_2+b_2_0*b_3_5, b_2_2*b_3_5+b_2_0*b_3_5, b_3_0^2+b_2_1^2*b_2_2+b_2_1^3+b_2_0*b_2_1*b_2_2+b_2_0*b_2_1^2+c_4_10*b_1_0^2, b_3_0*b_3_2, b_3_0*b_3_5, b_3_0*b_3_6, b_3_2*b_3_6+b_3_2*b_3_5, b_3_5^2+b_3_2*b_3_5, b_3_5*b_3_6+b_3_2*b_3_5, b_2_1^2*b_3_0+b_2_1^2*b_2_2*b_1_0+b_2_1^3*b_1_0+b_2_0*b_2_2*b_3_0+b_2_0*b_2_1*b_2_2*b_1_0+b_2_0*b_2_1^2*b_1_0+c_4_10*b_1_0^3, b_2_1^2*b_2_2*b_1_0^2+b_2_1^3*b_1_0^2+b_2_1^4+b_2_0*b_2_1*b_2_2*b_1_0^2+b_2_0*b_2_1^2*b_1_0^2+b_2_0^2*b_2_2^2+c_4_10*b_1_0^4

rels
()¶ Return the list of minimal relations of
self
, represented by strings.NOTE:
The list of relations may change if an incomplete cohomology computation is continued.
For \(p>2\), any generator \(x\) of odd degree of the modular cohomology ring of a finite \(p\)group gives rise to the relation \(x^2=0\). We refer to such relation as obvious. In the current version of our package, we list only the nonobvious relations, but this might change in future versions.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(16,3, from_scratch=True) sage: H.make(2) sage: H.rels() ['a_1_0^2', 'a_1_0*b_1_1'] sage: H.make() sage: H.rels() ['a_1_0^2', 'a_1_0*b_1_1', 'b_2_1*a_1_0', 'b_2_1^2+c_2_2*b_1_1^2']

resolution
()¶ Return the underlying resolution of
self
.Of course, when computing the cohomology ring in increasing degree, more and more terms of the resolution will be computed.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(16,5, from_scratch=True) sage: H H^*(SmallGroup(16,5); GF(2)) sage: print(H.resolution()) Resolution: 0 < GF(2) < GF(2)[SmallGroup(16,5)] sage: H.make() sage: print(H.resolution()) Resolution: 0 < GF(2) < GF(2)[SmallGroup(16,5)] < rank 2 < rank 3 < rank 4

restrict_to_subgroup
(n)¶ Returns the restriction of the cohomology ring generators to the \(n\)th subgroup.
SEE ALSO:
INPUT:
n
: an integer indicating a special subgroupn=1
refers to the greatest central elementary abelian subgroupn>1
refers to a representative of conjugacy classes of maximal elementary abelian subgroups
OUTPUT:
A list of cochains of the specified subgroup, obtained by restricting the generators of self
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make()
H has two isomorphism types of special subgroups, but 3 conjugacy classes:
sage: len(H.subgroups()) 2 sage: len(H.restriction_maps()) 3
We show the restriction to the three conjugacy classes. First, the greatest central elementary abelian subgroup:
sage: H.restrict_to_subgroup(1) [c_1_0^2: 2Cocycle in H^*(SmallGroup(2,1); GF(2)), 0: 1Cocycle in H^*(SmallGroup(2,1); GF(2)), 0: 1Cocycle in H^*(SmallGroup(2,1); GF(2))]
Now the restrictions to the maximal elementary abelian subgroups:
sage: H.restrict_to_subgroup(2) [c_1_0*c_1_1+c_1_0^2: 2Cocycle in H^*(SmallGroup(4,2); GF(2)), c_1_1: 1Cocycle in H^*(SmallGroup(4,2); GF(2)), 0: 1Cocycle in H^*(SmallGroup(4,2); GF(2))] sage: H.restrict_to_subgroup(3) [c_1_0*c_1_1+c_1_0^2: 2Cocycle in H^*(SmallGroup(4,2); GF(2)), 0: 1Cocycle in H^*(SmallGroup(4,2); GF(2)), c_1_1: 1Cocycle in H^*(SmallGroup(4,2); GF(2))]

restriction_maps
()¶ Return the dictionary of restriction maps of
self
.OUTPUT:
A dictionary of induced homomorphisms, namely the restriction maps of self to conjugacy classes of maximal elementary abelian subgroups or to the greatest central elementary abelian subgroup. The greatest central elementary abelian subgroup is available with the index
1
.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(16,3) sage: sorted(H.restriction_maps().items()) [(1, [(4, 2), Induced homomorphism of degree 0 from H^*(SmallGroup(16,3); GF(2)) to H^*(SmallGroup(4,2); GF(2))]), (2, [(8, 5), Induced homomorphism of degree 0 from H^*(SmallGroup(16,3); GF(2)) to H^*(SmallGroup(8,5); GF(2))])]

restrictions_as_string
(n)¶ Restriction of the cohomology ring generators to the \(n\)th subgroup as list of strings.
SEE ALSO:
INPUT:
n
: an integer indicating a special subgroupn=1
refers to the greatest central elementary abelian subgroupn>1
refers to a representative of conjugacy classes of maximal elementary abelian subgroups
OUTPUT:
A list of strings, representing a polynomial in the generators of the cohomology of the specified subgroup, yielding the restriction of the generators of self to that subgroup
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make()
H
has two isomorphism types of special subgroups, but 3 conjugacy classes:sage: len(H.subgroups()) 2 sage: len(H.restriction_maps()) 3
We show the restriction to the three conjugacy classes. First, the greatest central elementary abelian subgroup:
sage: H.restrictions_as_string(1) ['c_1_0^2', '0', '0']
Now the restrictions to the maximal elementary abelian subgroups:
sage: H.restrictions_as_string(2) ['c_1_0*c_1_1+c_1_0^2', 'c_1_1', '0'] sage: H.restrictions_as_string(3) ['c_1_0*c_1_1+c_1_0^2', '0', 'c_1_1']

set_ring
()¶ The underlying free graded commutative ring of
self
in the Singular interface becomes the base ring.NOTE:
This ring is, in general, not isomorphic to the cohomology ring, since the nonobvious relations are disregarded; the ring will only have the obvious quadratic relations that are common to any graded commutative ring in the Singular interface.
You can obtain a ring in the Singular interface isomorphic to a cohomology ring
H
by simply doingsingular(H)
.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: H.subgroups()[4,2].set_ring() sage: print(singular.eval('basering')) // coefficients: ZZ/2 // number of vars : 2 // block 1 : ordering M // : names c_1_0 c_1_1 // : weights 1 1 // : weights 1 0 // block 2 : ordering C sage: H.set_ring() sage: print(singular.eval('basering')) // coefficients: ZZ/2 // number of vars : 3 // block 1 : ordering M // : names c_2_2 b_1_0 b_1_1 // : weights 2 1 1 // : weights 1 0 0 // : weights 0 1 0 // block 2 : ordering C

setprop
(key, value)¶ Define a property of
self
.INPUT:
key
, a stringvalue
, any object
OUTPUT:
value
is now available as an attributekey
of self.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: print(H.foobar) None sage: print(H._foobar) None sage: print(H.foobar_) None
Note that if an attribute hasn’t been defined,
None
is returned. The only exceptions are undefined attributes that start and end with an underscore:sage: H._foobar_ Traceback (most recent call last): ... AttributeError: 'COHO' object has no attribute '_foobar_'
Now, we provide
_foobar_
with a meaning, and then it works:sage: H.setprop('_foobar_', 'It works!') sage: print(H._foobar_) It works!

small_factor
(C, enumerate=False)¶ Determine a small factor of an element, modulo nilpotent generators.
INPUT:
C
– an element ofself
or a polynomial in the Singular interface. If it is an element ofself
,C.name()
must expressC
as polynomial in the generators ofself
.enumerate
– (bool, defaultFalse
) IfTrue
, the factorisation takes into account the relations inself
, but may take a long time, as the factors are found by enumeration of elements in small degrees.
NOTE:
In order to express
C
as a polynomial in the generators ofself
, useelement_as_polynomial()
.OUTPUT:
A string, providing a small nonscalar factor of
C
, allowing modification by multiples of nilpotent generators.NOTE:
If the optional argument
enumerate
isTrue
, then in each degree, at most 1000 candidates are tested; this default can be altered by assigning a value topGroupCohomology.resolution.coho_options['NrCandidates']
.NOTE:
If the computation is interrupted with Ctrlc, the computation is continued in the next degree.
EXAMPLES:
We first load a cohomology ring of order 64 from the local sources shipped with this package.
sage: from pGroupCohomology import CohomologyRing sage: H = CohomologyRing(64,235) sage: H.gens() [1, c_4_13: 4Cocycle in H^*(SmallGroup(64,235); GF(2)), c_4_14: 4Cocycle in H^*(SmallGroup(64,235); GF(2)), a_1_1: 1Cocycle in H^*(SmallGroup(64,235); GF(2)), a_1_0: 1Cocycle in H^*(SmallGroup(64,235); GF(2)), b_1_2: 1Cocycle in H^*(SmallGroup(64,235); GF(2)), b_1_3: 1Cocycle in H^*(SmallGroup(64,235); GF(2)), b_3_10: 3Cocycle in H^*(SmallGroup(64,235); GF(2))]
We construct a cochain of degree 6. A factorisation with the default arguments does not yield a factor of smaller degree; only the obvious nilpotent summand is removed:
sage: p = H('b_1_3^3*b_3_10+c_4_14*b_1_3^2+c_4_14*b_1_2^2+c_4_13*b_1_3^2+c_4_13*b_1_2^2+c_4_13*a_1_0*a_1_1') sage: H.small_factor(p) 'b_1_3^3*b_3_10+c_4_14*b_1_3^2+c_4_14*b_1_2^2+c_4_13*b_1_3^2+c_4_13*b_1_2^2'
However, a smaller factor can be found if, in addition to nilpotent generators, the relations are taken into account, by using an optional argument:
sage: CohomologyRing.global_options('info') sage: H.small_factor(p, enumerate=True) H^*(SmallGroup(64,235); GF(2)): Factorising an element; it can be interrupted with Ctrlc Exploring factors of an element by enumeration (can be interrupted with Ctrlc) Determine degree 1 standard monomials > Start enumeration with 2 monomials 'b_1_3+b_1_2'
We verify that indeed the difference of
p
and some multiple of the returned factor is nilpotent of order exactly 3:sage: CohomologyRing.global_options('warn') sage: f1 = H('b_1_3+b_1_2') sage: f2 = H('(b_1_3*b_3_10+c_4_14+c_4_13)*(b_1_3+b_1_2)') sage: ((singular(f1)*singular(f2)  singular(p))^2).NF('std(0)') c_4_14*a_1_1*a_1_0*b_1_2^6+c_4_13*a_1_1*a_1_0*b_1_2^6 sage: ((singular(f1)*singular(f2)  singular(p))^3).NF('std(0)') 0

standardCochain
(n, i, rdeg=None, ydeg=None, name='c')¶ Standard cochain of
self
.INPUT:
n
: degree (integer) of a cochaini
: integerrdeg
,ydeg
: (optional) integers orNone
(defaultNone
).name
: (optional) string used to give the cochain a name (default'c'
)
OUTPUT:
A \(n\)cochain represented by
[0,...,0,1,0,...0]
with 1 at position \(i\) (counting from zero) and name'c_%d_%d'%(n,i)
. The letter'c'
in the name can be changed with the optional parameter ‘name’.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: c=H.standardCochain(3,2,rdeg=1,ydeg=0,name='X') sage: c X_3_2: 3Cocycle in H^*(D8; GF(2)) sage: print(c) 3Cocycle in H^*(D8; GF(2)), represented by [0 0 1 0] rdeg = 1 ydeg = 0

standard_monomials
(n)¶ Standard monomials of a prescribed degree.
INPUT:
\(n\): An integer, so that
self
is known at least out to degree \(n\).OUTPUT:
A list of strings, providing the degree\(n\) standard monomials, sorted in descending order.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,4, from_scratch=True) sage: H.make(2) sage: H.standard_monomials(2) ['a_1_0*a_1_1', 'a_1_0^2'] sage: H.standard_monomials(3) Traceback (most recent call last): ... ValueError: The cohomology ring is not known out to degree 3 sage: H.make()
We now know the cohomology ring entirely, although the explicit computation only went out to degree 4. But since we know all of the ring, we can now get the degree\(5\) standard monomials:
sage: H.knownDeg 4 sage: H.standard_monomials(5) ['c_4_0*a_1_1', 'c_4_0*a_1_0']

subgroups
()¶ Return the subgroup dictionary of
self
.OUTPUT:
A dictionary of cohomology rings of elementary abelian groups that occur as maximal elementary abelian subgroups or as the greatest central elementary abelian subgroup of the group over which self is defined. The dictionary is indexed by addresses for the SmallGroups libarary.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(16,3) sage: sorted(H.subgroups().items()) [((4, 2), H^*(SmallGroup(4,2); GF(2))), ((8, 5), H^*(SmallGroup(8,5); GF(2)))]

test_for_completion
(forced=False)¶ Test whether the current ring approximation is complete.
OUTPUT:
True
(complete),False
(incomplete) orNone
(can’t be decided yet)THEORY:
We choose between two criteria:
 The [Benson] criterion modified by [GreenKing]: It relies on the construction of a filter regular hsop for the ring approximation that is guaranteed to correspond to a hsop in cohomology, and on the existence of a filter regular hsop in small degrees over a finite extension of the coefficient field.
 The [Symonds] criterion: It relies on the construction of a hsop for the cohomology in small degrees, and the generator degree of the ring approximation as a module over these parameters. These parameters do not need to be algebraically independent.
The advantage of the Benson criterion is that often there exist fairly small parameters over a finite extension field that can not be found in the original cohomology ring; hence it may apply much earlier than the Symonds test. Note that if the rank of the centre of a Sylow subgroup is at least two then the degree bound drops by one.
The advantage of the Symonds test is that it does not rely on filter regularity. Often, one finds a general hsop in smaller degrees than a filter regular hsop. Moreover, it is not needed to compute the filter degree type of the ring, which can be a very difficult part of Benson’s test. Note that the rank of the centre of a Sylow subgroup has no influence on the degree bound.
We give more details in the documentation of
pGroupCohomology
.ALGORITHM:
 If the Symonds test has a chance to apply (which can be seen in the degrees of the hsop) then it is tried.
 If the Symonds test has no chance to apply yet, Benson’s test is chosen.
EXAMPLES:
We compute the rings in a way that avoids the automatic execution of this method.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H64 = CohomologyRing(64,6, useElimination=True, from_scratch=True) sage: H64.make(3) sage: H64.next()
Now, the ring structure is known out to degree four. A hsop can be found in sufficiently small degrees. Therefore, the Symonds test is chosen, which can be seen in the log and in the attribute
_method
:sage: H64.parameters() ['c_2_2', 'c_2_3', 'b_1_1'] sage: CohomologyRing.global_options('info') sage: H64.test_for_completion() H^*(SmallGroup(64,6); GF(2)): Compute dependent_parameters Try to find a set of generators over which the cohomology ring is finite. Trying Symonds' criterion Successful application of the Symonds criterion True sage: CohomologyRing.global_options('warn') sage: H64._method 'Symonds' sage: H64.completed True
In our second example, the Benson criterion is used. Again, we compute the ring structure to a sufficient degree, but avoiding the automatic completion testing.
sage: H81 = CohomologyRing(81,14, from_scratch=True) sage: H81.make(7) sage: H81.next()
We find filter regular parameters that would allow the original form of Benson’s test (see [Benson]) to apply in degree \(5+3+1=9\). We don’t find smaller algebraically independent parameters, but there are algebraically dependent parameters in rather small degree, so that the completeness can be proved using the [Symonds] criterion:
sage: H81.filter_regular_parameters() ['c_6_8', 'b_4_5b_2_4^2b_2_3^2'] sage: H81.parameters() ['c_6_8', 'b_4_5b_2_4^2b_2_3^2'] sage: H81.dependent_parameters() ['a_1_0', 'a_1_1', 'a_1_2', 'c_6_8', 'b_2_3', 'b_2_4'] sage: CohomologyRing.global_options('info') sage: H81.test_for_completion() H^*(E27*C9; GF(3)): Trying Symonds' criterion Successful application of the Symonds criterion True
Note that the modified Benson criterion of [GreenKing] applies in degree eight as well:
sage: H81.BensonTest(H81.filter_regular_parameters(),[6,4]) Testing whether it makes sense to try Benson's completeness criterion It is possible that Benson's degree bound applies Compute raw_filter_degree_type Test filter regularity Filter degree type: [1, 2, 2] True sage: CohomologyRing.global_options('warn') sage: H81.WhatFRS (1, 2)
By the last line, it is possible to replace one (namely the last) parameter by an element of degree two, over a finite extension of the field of coefficients. This suffices for the modified Benson criterion.

trait_names
()¶ Implement tab completion.
TESTS:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: H.make() sage: import sage.interfaces.tab_completion as tc sage: tc.completions('H.f',globals()) # indirect doctest ['H.filter_degree_type', 'H.filter_regular_gready_parameters', 'H.filter_regular_parameters', 'H.find_dickson', 'H.find_dickson_in_subgroup', 'H.find_small_last_parameter', 'H.firstOdd', 'H.fraction_field', 'H.from_base_ring']

verify_parameters_exist
()¶ Test whether the current ring approximation contains a HSOP for the cohomology ring.
THEORY:
The ring approximation contains a HSOP for the cohomology ring if and only if the cohomology rings of the maximal elementary abelian subgroups are finitely generated modules over the restriction of the ring approximation.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3, from_scratch=True) sage: H.make(1) sage: print(H) Cohomology ring of Dihedral group of order 8 with coefficients in GF(2) <BLANKLINE> Computed up to degree 1 Minimal list of generators: [b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))] Minimal list of algebraic relations: []
This ring is of Krull dimension two, which coincides with the dimension of the cohomology ring of
SmallGroup(8,3)
(which is the dihedral group with 8 elements). But the ring approximation does not contain parameters for the cohomology ring, yet:sage: H.verify_parameters_exist() False
Indeed, the restrictions of the current generators to any of the two maximal elementary abelian subgroups is only of Krull dimension one:
sage: H.restrictions_as_string(2) ['0', 'c_1_1'] sage: H.restrictions_as_string(3) ['c_1_1', '0']
Hence, we have to compute one step further, and then succeed:
sage: H.next() sage: H.verify_parameters_exist() True sage: H.parameters() ['c_2_2', 'b_1_1+b_1_0']

class
pGroupCohomology.cohomology.
COHO_Terminator
(S, prefix)¶ Remove cohomology data from the Singular interface.
This is an auxiliary class, with the purpose to remove all data from the Singualar interface that are related with a certain cohomology ring.
Each cohomology ring has a member that is an instance of this class. Hence, when the ring is deleted then the member’s
__del__
method is called, which clears the Singular interface.The somewhat hidden reason for introducing an auxiliar class is that circular references of cohomology rings can not be avoided; hence, if they had a
__del__
method, they could never be garbage collected (the reason is described in the Python references); hence, we moved the__del__
method to here.TESTS:
sage: from pGroupCohomology.cohomology import COHO_Terminator sage: T = COHO_Terminator(singular(1), 'MyPrefix') sage: singular.eval('ring MyPrefixR = 0,(a,b,c),dp') '' sage: print(singular.eval('MyPrefixR')) // coefficients: QQ // number of vars : 3 // block 1 : ordering dp // : names a b c // block 2 : ordering C sage: singular.eval('ideal MyPrefixI = a^2,b^2,c') '' sage: print(singular.eval('MyPrefixI')) MyPrefixI[1]=a2 MyPrefixI[2]=b2 MyPrefixI[3]=c sage: del T sage: singular('MyPrefixI') Traceback (most recent call last): ... TypeError: Singular error: ? `MyPrefixI` is undefined ? error occurred in ...

class
pGroupCohomology.cohomology.
COHO_prefix
¶ COHO_prefix()() returns the next safe prefix.
Used for naming Singular interface data of a
COHO
instance.TESTS:
sage: from pGroupCohomology.cohomology import COHO_prefix sage: COHO_prefix.instance=0 # initialization, for avoiding other doc tests to interfere sage: COHO_prefix()() 'COHO1' sage: COHO_prefix()() 'COHO2'

pGroupCohomology.cohomology.
COHO_unpickle
(GroupKey, StateFile)¶ Unpickling of a cohomology ring.
TESTS:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: H is loads(dumps(H)) # indirect doctest True

pGroupCohomology.cohomology.
FilterDegreeType
(dv, rt)¶ Compute the filter degree type.
INPUT:
d
 list of degrees (\(n\) integers) of a filter regular homogeneous system of parameters, andr
 the ‘raw filter degree type’ (list of \(n+1\) integers) of these parameters.
OUTPUT:
The filter degree type, a list of integers
EXAMPLES:
sage: from pGroupCohomology.cohomology import FilterDegreeType sage: d=[8,4,6,4] sage: r=[1,4,7,14,18] sage: FilterDegreeType(d,r) [1, 2, 3, 4, 4] sage: d=[8,4,6,3] sage: FilterDegreeType(d,r) [1, 2, 3, 3, 3]

class
pGroupCohomology.cohomology.
GapPickler
(G)¶ This is an auxiliary class for pickling data involving the libgap interface.
NOTE:
The only purpose of an instance of this class is to carry a string that allows for reconstruction of an object in Gap. Applying
pickle_gap_data()
to data will work recursively on dictionaries, lists and tuples, and will return most other data unchanged. But when it encounters an object in Gap, it will try whether the object can be reconstructed from its string representation. If this is the case, then it returns an instance ofGapPickler
. Whenunpickle_gap_data()
is applied to the result, then it will create an object in Gap in lieue of any string that is stored in aGapPickler
class.EXAMPLES:
sage: from pGroupCohomology.cohomology import GapPickler, unpickle_gap_data, pickle_gap_data sage: G = libgap.SmallGroup(8,3).IsomorphismPermGroup().Image() sage: D = {(1, G, "abc"):5} sage: unpickle_gap_data(pickle_gap_data(D)) == D # indirect doctest True

pGroupCohomology.cohomology.
HV2Poly
(L)¶ Translate a list of integers into a univariate polynomial, using the given integers as coefficients.
INPUT:
L
: a list of integersOUTPUT:
A univariate polynomials with coefficients given by
L
EXAMPLES:
sage: from pGroupCohomology.cohomology import HV2Poly sage: HV2Poly([3,2,4]) 4*t^2 + 2*t + 3

pGroupCohomology.cohomology.
Mul
(L, L0)¶ Compute the product of a list of elements, bracketed from the right.
INPUT:
[L_1,...,L_n]
, a list of elements that can be multipliedL_0
, an element
OUTPUT:
The product
(L_1...*(L_{n1}*(L_n*L_0))...)
EXAMPLES:
sage: from pGroupCohomology.cohomology import Mul sage: M=Matrix(GF(5),[[1,2],[1,1]]) sage: M1=Matrix(GF(5),[[1,2],[1,1]]) sage: M2=Matrix(GF(5),[[1,3],[2,1]]) sage: M3=Matrix(GF(5),[[1,4],[3,1]]) sage: Mul([M1,M2],M3) [0 0] [0 1] sage: Mul([M2,M3],M1) [2 2] [4 4] sage: M2*M3*M1==Mul([M2,M3],M1) True

pGroupCohomology.cohomology.
explore_one_parameter
(Id, L0, p, BreakPoint=None, regularity=0, H1=None, is_monomial=True)¶ Find a parameter for the quotient ring given by an ideal.
INPUT:
Id
– Ideal in a graded commutative ring of prime characteristic \(p\). Must be a Groebner basis.
L0
– a list of homogeneous elements (given by strings) of the same degree.p
– a prime.BreakPoint
– (optional integer or infinity) test at most that many candidates for a parameter (default: infinity).
regularity
– (optional int, default0
) If1
(not default), find a parameter that is filter regular modulo
Id
. If2
, find a parameter that is regular moduloId
.
H1
– (optional) the Hilbert Poincaré series ofId
.is_monomial
– (optional) whether the element inL0
are monomials.
OUTPUT:
 An element \(v\) in Singular that lowers the dimension of
Id
by one (aka “parameter” forId
),  A tuple of integers, namely the list of coefficients that defines
v
as linear combination of the monomials inL
.  The return value of
is_filter_regular
, ifregularity==1
, or[]
.
 An element \(v\) in Singular that lowers the dimension of
False, False, []
, if no linear combination of elements ofL
provides a parameter forId
, orNone, None, []
, if the search for a parameter was stopped since the number of candidates exceededBreakPoint
.
NOTE:
If \(is_monomial\) is true, then only lineare combinations of the standard monomials in
L0
relative toId
will be considered.TESTS:
sage: from pGroupCohomology import CohomologyRing sage: from pGroupCohomology.cohomology import explore_one_parameter sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(32,33) sage: H.make() sage: H.set_ring() sage: Id = H.relation_ideal() sage: L = H.standard_monomials(3) sage: explore_one_parameter(Id,L,2) (b_1_0^3, (0, 0, 0, 0, 0, 0, 0, 1, 0, 0), []) sage: explore_one_parameter(Id,L,2, regularity=1) (False, False, []) sage: Id.dim() 3 sage: Id.std('b_1_0^3').dim() 2
Now, we use two noncommutative examples. We do not need to distinguish Singular versions 311 and older versions, since in this example there are regular respectively filterregular parameters.
sage: H = CohomologyRing(27,4) sage: H.make() sage: H.dimension() 2 sage: H.depth() 1 sage: H.set_ring() sage: Id = H.relation_ideal() sage: L = H.standard_monomials(6) sage: explore_one_parameter(Id,L,3,regularity=2) (c_6_2, (0, 0, 0, 0, 0, 1), [0]) sage: Id = Id.std('c_6_2') sage: L = H.standard_monomials(2) sage: explore_one_parameter(Id,L,3) (b_2_1, (0, 0, 1, 0), []) sage: explore_one_parameter(Id,L,3,regularity=1) (b_2_1, (0, 0, 1, 0), [0, 1, 1, 1, 1]) sage: explore_one_parameter(Id,L,3,regularity=2) (False, False, [])

pGroupCohomology.cohomology.
is_filter_regular
(I, f, H1=None, I2=None)¶ Test if \(f\) is filterregular with respect to \(I\).
INPUT:
 \(I\), complete standard basis of a weighted homogeneous ideal; Singular element or string.
 \(f\), weighted homogeneous element; Singular element or string.
 \(H1\) (optional) – first Hilbert Poincaré series of \(I\), if that has already been computed
 \(I2\) (optional) –
std(I,f)
, if that has already been computed
OUTPUT:
Finite list of vector space dimensions of the annulator of \(f\) with respect to \(I\), i.e., \(\{pf\cdot p\in I\}\), or
False
if the annulator is not finite dimensional.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: from pGroupCohomology.cohomology import is_filter_regular sage: CohomologyRing.doctest_setup() sage: H = CohomologyRing(64, 23, from_scratch=True) sage: H.make(4) sage: F = H.filter_regular_parameters() sage: is_filter_regular(H.relation_ideal(), F[0]) False sage: is_filter_regular(H.relation_ideal().std(F[1]), F[0]) [0] sage: is_filter_regular(H.relation_ideal().std(F[0]).std(F[1]).std(F[2]), F[3]) False sage: H.make() sage: is_filter_regular(H.relation_ideal().std(F[0]).std(F[1]).std(F[2]), F[3]) [0, 2, 1, 1, 2]

pGroupCohomology.cohomology.
is_filter_regular_parameter_system
(I, FRS)¶ Test if \(FRS\) is a filterregular parameter system with respect to \(I\).
INPUT:
 \(I\), complete standard basis of a weighted homogeneous ideal; Singular element or string.
 \(FRS\), an iterable of Singular elements or strings representing weighted homogeneous elements.
OUTPUT:
False
, or the raw filter degree type, which is a list oflen(FRS)+1
lists of integers: The \(i\)th list provides the vector space dimensions of each degree layer of the annulator of the \(i\)th element of \(FRS\) modulo the preceeding elements; the last list provides the vector space dimensions of each degree layer of the quotient modulo \(FRS\). If some annulator or the final quotient is not finite dimensional, thenFalse
is returned.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() sage: H = CohomologyRing(64, 23, from_scratch=True) sage: H.make(4)
There exists a set of elements of degree at most four that are guaranteed to form a filter regular system of parameters of the cohomology ring:
sage: F = H.filter_regular_parameters() sage: F ['c_2_4', 'c_4_14', 'b_2_3+b_2_2+b_2_1', 'b_3_6']
However, they are not filter regular in the ring approximations out to degree 4 or 7. They are filter regular in the ring approximation out to degree 8, and this is in fact the complete cohomology ring:
sage: from pGroupCohomology.cohomology import is_filter_regular_parameter_system sage: is_filter_regular_parameter_system(H.relation_ideal(), F) False sage: H.make(7) sage: is_filter_regular_parameter_system(H.relation_ideal(), F) False sage: H.make(8) sage: is_filter_regular_parameter_system(H.relation_ideal(), F) [[0], [0], [0], [0, 2, 1, 1, 2], [1, 2, 3, 4, 5, 2, 0, 1]] sage: H.completed True

class
pGroupCohomology.cohomology.
permanent_result
(f)¶ Cache a method and reconstruct data in interfaces when needed.
NOTE:
The value
None
will not be cached.The decorator only works if it is used for a method of an instance
X
that either has an attribute_decorator_cache
(a dictionary) or allows its creation.If the result is in the Singular interface and Singular crashes, then sometimes it is necessary for reconstruction of data that
X
has an attributeGenS
whose parent is Singular, and it needs to have an interpretation in Singular.If the method arguments are in an interface then it is imperative that they can be reconstructed from its string representation.
If the method raised a
KeyboardInterrupt
, this is cached as well, but a new computation can be attempted with the optional argumentforced
added to the method’s arguments. Note thatforced
is not passed as an argument to the underlying function.NOTE:
Sometimes, the results stored with this decorator involve data defined in GAP. GAP does by default not provide data serialisation, and even GAP’s optional IO package would only write data directly to a file object, which is awkward when otherwise relying on Python’s pickling protocols. However, often a GAP object can be reconstructed from its string representation, and that’s what we are using here.
ASSUMPTION:
If the result is in the Singular interface, it is assumed that
singular(X).set_ring()
is possible and that the result either belongs to this ring or is ring independent.EXAMPLES:
This decorator is designed for use in cohomology rings, but the examples show that it works more generally:
sage: from pGroupCohomology.cohomology import permanent_result sage: class FOO: ....: def __init__(self,R): ....: self.R = R ....: self.GenS = singular.int(1) ....: def _singular_(self,S): ....: return S(self.R) ....: @permanent_result ....: def bar(self, G): ....: ''' ....: Here is the documentation. ....: ''' ....: singular(self).set_ring() ....: print('Group of order',G.Order()) ....: return singular.maxideal(G.Order()) sage: R.<x,y> = QQ[] sage: f = FOO(R) sage: G2 = libgap.eval('Group( [ (1,2) ] )') sage: G3 = libgap.eval('Group( [ (1,2,3) ] )')
It can be seen from the printed statement that the actual computation is only done when the method is called first.
sage: I2 = f.bar(G2); I2 Group of order 2 y^2, x*y, x^2 sage: f.bar(G2) y^2, x*y, x^2 sage: I3 = f.bar(G3); I3 Group of order 3 y^3, x*y^2, x^2*y, x^3 sage: f.bar(G3) y^3, x*y^2, x^2*y, x^3 sage: I2 is f.bar(G2) True
The point is that even when Singular crashes, the data can be reconstructed without a new computation (note that the printed statement does not appear):
sage: singular.quit() sage: G2 = libgap.eval('Group( [ (1,2) ] )') sage: f.bar(G2) y^2, x*y, x^2 sage: I2 is f.bar(G2) False sage: I2 = f.bar(G2)
Note, moreover, that the given doc string is modified by the decorator:
sage: print(f.bar.__doc__) Permanently cached method: Here is the documentation. <BLANKLINE>
Last, we simulate a
KeyboardInterrupt
being cached, and force recomputation afterwards:sage: f.bar.set_cache(KeyboardInterrupt('simulation'),G2) sage: try: ....: f.bar(G2) ....: except KeyboardInterrupt as msg: ....: print(msg) simulation sage: f.bar(G2, forced=True) Group of order 2 y^2, x*y, x^2 sage: I2 is f.bar(G2) False
Note that when a
KeyboardInterrupt
really occurs in the method, the error message will mention the possibility of forcing a recomputation. Here is an example:sage: class FOO: ....: _t = 0 ....: @permanent_result ....: def bar(self, n): ....: if not self._t: ....: raise KeyboardInterrupt ....: return n+self._t ....: @permanent_result ....: def foo(self,n): ....: return libgap.SymmetricGroup(self.bar(n)) sage: f = FOO() sage: try: ....: f.foo(1) ....: except KeyboardInterrupt as msg: ....: print(msg) bar interrupted. Force recomputation at <....FOO ... at ...> with ``forced=True`` foo interrupted. Force recomputation at <....FOO ... at ...> with ``forced=True``
The
KeyboardInterrupt
is cached. So, even if we set the attribute_t
above to a nonzero value, the error won’t go away, unless we force recomputation:sage: f._t = 2 sage: try: ....: f.bar(1) ....: except KeyboardInterrupt as msg: ....: print(msg) bar interrupted. Force recomputation at <....FOO ... at ...> with ``forced=True`` sage: f.bar(1, forced=True) 3 sage: try: ....: f.foo(1) ....: except KeyboardInterrupt as msg: ....: print(msg) bar interrupted. Force recomputation at <....FOO ... at ...> with ``forced=True`` foo interrupted. Force recomputation at <....FOO ... at ...> with ``forced=True`` sage: f.foo(1,forced=True) Sym( [ 1 .. 3 ] )
In the next example, we demonstrate that pickling works, even if Gap data are involved:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(184,5, prime=2) sage: H.make() sage: type(H.essential_ideal) <class 'pGroupCohomology.cohomology.permanent_result'> sage: H.essential_ideal([H.group().SylowSubgroup(2).Centre()]) b_1_0, b_1_1
Now, we store the result on disc, empty the cache, reload, and demonstrate by logging that the previously computed result has been stored, even though the data are defined in the Singular interface and are indexed by an object in Gap:
sage: save(H, H.autosave_name()) sage: CohomologyRing._cache.clear() sage: CohomologyRing.global_options('warn') sage: H2 = load(H.autosave_name()) sage: H2 is H False sage: H2.essential_ideal([H.group().SylowSubgroup(2).Centre()]) b_1_0, b_1_1 sage: CohomologyRing.global_options('warn') sage: H.group().SylowSubgroup(2).Centre().parent() C library interface to GAP sage: H2.essential_ideal([H.group().SylowSubgroup(2).Centre()]).parent() Singular

get_cache
(*args, **kwds)¶ Return the value that was saved using
set_cache()
.NOTE:
If necessary, data in interfaces (in particular in GAP and Singular) are reconstructed. This of course only works to some extent (e.g., for GAP, it is needed that the saved value can be reconstructed from its string representation, and in Singular, it needs to be reconstructible from the string representation and the type information.
EXAMPLE:
sage: from pGroupCohomology.cohomology import permanent_result sage: class FOO: ....: GenS = singular.int(0) # needed for Singular reconstruction ....: def _singular_(self, S): ....: return S(QQ['x','y']) ....: @permanent_result ....: def bar(self, n): ....: return libgap.SymmetricGroup(n) ....: @permanent_result ....: def foo(self, n): ....: singular(self).set_ring() ....: return singular.maxideal(n) sage: f = FOO() sage: f = FOO() sage: G = f.bar(4); G Sym( [ 1 .. 4 ] ) sage: G is f.bar(4) True
Setting the cache to a different value:
sage: f.bar.set_cache(gap.AlternatingGroup(3), 4) sage: f.bar(4) AlternatingGroup( [ 1 .. 3 ] ) sage: f.bar.get_cache(4) AlternatingGroup( [ 1 .. 3 ] )
Now, similarly for data in Singular:
sage: I = f.foo(3); I y^3, x*y^2, x^2*y, x^3 sage: I is f.foo(3) True sage: f.foo(3).typeof() ideal sage: f.foo.set_cache(singular.poly('x*y'),3) sage: f.foo.get_cache(3) x*y sage: f.foo(3).typeof() poly

set_cache
(val, *args, **kwds)¶ Set the cache for the given arguments to a certain value.
INPUT:
val
– any object, that is to be cached Any position and keyword arguments. They must be immutable or lists of immutables.
EXAMPLE:
sage: from pGroupCohomology.cohomology import permanent_result sage: class FOO: ....: @permanent_result ....: def bar(self, G): ....: return G.Order() ....: @permanent_result ....: def foo(self, G): ....: raise KeyboardInterrupt sage: f = FOO() sage: G2 = libgap.eval('Group( [ (1,2) ] )') sage: f.bar(G2) 2 sage: try: ....: f.foo(3) ....: except KeyboardInterrupt as msg: ....: print(msg) foo interrupted. Force recomputation at <....FOO ... at ...> with ``forced=True``
This results in creating a cache for
f
. Note that even theKeyboardInterrupt
is cached:sage: sorted(f._decorator_cache.items()) #indirect doctest [(('bar', Group([ (1,2) ])), [2]), (('foo', 3), [KeyboardInterrupt('foo interrupted. Force recomputation ...)])]


pGroupCohomology.cohomology.
pickle_gap_data
(G)¶ Pickle data involving objects in Gap.
INPUT:
G
: Any object.NOTE:
Applying this function to data will work recursively on dictionaries, lists and tuples, and will return most other data unchanged. But when it encounters an object in Gap, it will try whether the object can be reconstructed from its string representation. If this is the case, then it returns an instance of
GapPickler
. Whenunpickle_gap_data()
is applied to the result, then it will create an object in Gap in lieue of any string that is stored in aGapPickler
class.EXAMPLES:
sage: from pGroupCohomology.cohomology import GapPickler, unpickle_gap_data, pickle_gap_data sage: G = libgap.SmallGroup(8,3).IsomorphismPermGroup().Image() sage: D = {(1, G, "abc"):(5,G)} sage: unpickle_gap_data(pickle_gap_data(D)) == D True
If Gap data can not be reconstructed from its string representation, a type error is raised:
sage: G = libgap.SmallGroup(8,3) sage: D = {(1, G, "abc"):5} sage: pickle_gap_data(D) Traceback (most recent call last): ... TypeError: Can not pickle 'Group( [ f1, f2, f3 ] )'

pGroupCohomology.cohomology.
str2html
(s, linelength=80)¶ HTML representation of a string representation of a polynomial.
INPUT:
s
 a string representing a polynomiallinelength=80
 (optional) approximate line length of the output
OUTPUT:
HTML representation of the polynomial (string). If the polynomial is too long, there will be line breaks.
NOTE:
 It is expected that all exponents are positive integer numbers, written without signs.
 The multiplication sign ‘*’ is replaced by ‘·’
 In order to group the terms nicely, there is a small space around plus and minus signs.
 There is an indentation after a line break.
EXAMPLES:
sage: from pGroupCohomology.cohomology import str2html sage: R.<x,y>=QQ[] sage: s=str(x^2+2*x*y+y^4) sage: s 'y^4 + x^2 + 2*x*y' sage: str2html(s) '<nobr>y<sup>4 </sup> +  x<sup>2 </sup> +  2·x·y</nobr>'
If we choose a very small line length, the result breaks into several lines:
sage: str2html(s,linelength=15) '<nobr>y<sup>4 </sup> +  x<sup>2 </sup></nobr><br> <nobr> +  2·x·y</nobr>'

class
pGroupCohomology.cohomology.
temporary_result
(f)¶ Decorator for caching methods of a cohomology ring approximation.
NOTE:
This decorator is designed for application to cohomology rings (
COHO
). Unlikepermanent_result
, the cached value is recomputed if the structure of the ring approximation has changed, i.e., if a new generator or a new relation was found after the value was cached.KeyboardInterrupt
is cached – seepermanent_result
for more details.EXAMPLE:
The method
poincare_series()
uses our decorator for temporary results. In order to avoid using a stored value, we force a new computation in the first place.sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,4, from_scratch=True) sage: H.make(1) sage: CohomologyRing.global_options('info') sage: p = H.poincare_series(); p # indirect doctest H^*(Q8; GF(2)): Compute poincare_series Computing complete Groebner basis 1/(t^2  2*t + 1) sage: p is H.poincare_series() True
We now overwrite the cached value, also demonstrating that a
KeyboardInterrupt
is cached as well:sage: H.poincare_series.set_cache(KeyboardInterrupt('bla')) sage: try: ....: H.poincare_series() ....: except KeyboardInterrupt as msg: ....: print(msg) bla
We can use the optional argument
forced
for restoring the cache:sage: H.poincare_series(forced=True) Forced recomputation of poincare_series Compute poincare_series 1/(t^2  2*t + 1)
The value in the cache is automatically updated if the ring structure changes by a computation in higher degree. The use of the optional argument
forced
is not necessary in this case:sage: CohomologyRing.global_options('warn') sage: H.make(2) sage: CohomologyRing.global_options('info') sage: H.poincare_series() H^*(Q8; GF(2)): Compute poincare_series (t + 1)/(t + 1)

get_cache
(*args, **kwds)¶ Get the value that was cached for the given arguments.
NOTE:
If the ring structure has changed after storing the value, a
KeyError
is raised.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,4, from_scratch=True) sage: H.make(1) sage: p = H.poincare_series(); p 1/(t^2  2*t + 1) sage: p is H.poincare_series.get_cache() True sage: H.make(2) sage: H.poincare_series.get_cache() Traceback (most recent call last): ... KeyError: 'The saved data belong to a previous stage of the computation'

set_cache
(val, *args, **kwds)¶ Set the cache of this method to a specific value.
INPUT:
val
– the value to be cached. Any further position or keyword arguments that are suitable as dictionary keys (lists are automatically transformed into tuples).
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,4, from_scratch=True) sage: H.make(1) sage: H.poincare_series() 1/(t^2  2*t + 1) sage: H.poincare_series.set_cache('hello world',42,foo='bar') sage: H.poincare_series(42, foo='bar') 'hello world' sage: H.poincare_series(42, foo='bar', forced=True) Traceback (most recent call last): ... TypeError: poincare_series() got an unexpected keyword argument 'foo' sage: H.poincare_series(42, foo='bar') 'hello world'
Note that the cache is automatically cleared if the ring structure changes:
sage: H.make() sage: H.poincare_series(42, foo='bar') Traceback (most recent call last): ... TypeError: poincare_series() got an unexpected keyword argument 'foo' sage: H.poincare_series() (t^2  t  1)/(t^3  t^2 + t  1)


pGroupCohomology.cohomology.
unpickle_gap_data
(G)¶ Unpickle data involving objects in Gap.
INPUT:
G
: Any object.
NOTE:
Applying
pickle_gap_data()
to data will work recursively on dictionaries, lists and tuples, and will return most other data unchanged. But when it encounters an object in Gap, it will try whether the object can be reconstructed from its string representation. If this is the case, then it returns an instance ofGapPickler
. When this function is applied to the result, then it will create an object in Gap in lieue of any string that is stored in aGapPickler
class.EXAMPLES:
sage: from pGroupCohomology.cohomology import GapPickler, unpickle_gap_data, pickle_gap_data sage: G = libgap.SmallGroup(8,3).IsomorphismPermGroup().Image() sage: D = {(1, G, "abc"):5} sage: unpickle_gap_data(pickle_gap_data(D)) == D True