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:

class pGroupCohomology.cohomology.COHO(*args, **kwds)

Modular Cohomology Rings of Finite \(p\)-Groups with coefficients in \(\mathbb F_p\).

AUTHORS:

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 constructor pGroupCohomology.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 p-elementary 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 p-elementary 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 Ctrl-c
    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: 2-Cocycle in H^*(D8; GF(2)),
 b_1_0: 1-Cocycle in H^*(D8; GF(2)),
 b_1_1: 1-Cocycle 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: 2-Cocycle in H^*(OtherName; GF(2)),
 b_1_0: 1-Cocycle in H^*(OtherName; GF(2)),
 b_1_1: 1-Cocycle 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: 2-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 c_2_2: 2-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 c_4_4: 4-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_1_1: 1-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_3_3: 3-Cocycle in H^*(SmallGroup(64,14); GF(2))]

It depends on the python version whether or not the relations are tail-reduced 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 non-commutative:

sage: R = COHO(27,3,root=tmp_root)
sage: R.make()
sage: R.gens()
[1,
 b_2_0: 2-Cocycle in H^*(E27; GF(3)),
 b_2_1: 2-Cocycle in H^*(E27; GF(3)),
 b_2_2: 2-Cocycle in H^*(E27; GF(3)),
 b_2_3: 2-Cocycle in H^*(E27; GF(3)),
 c_6_8: 6-Cocycle in H^*(E27; GF(3)),
 a_1_0: 1-Cocycle in H^*(E27; GF(3)),
 a_1_1: 1-Cocycle in H^*(E27; GF(3)),
 a_3_4: 3-Cocycle in H^*(E27; GF(3)),
 a_3_5: 3-Cocycle in H^*(E27; GF(3))]
sage: print(R('a_1_0*a_3_4'))
4-Cocycle in H^*(E27; GF(3)),
represented by
[1 0 0 0 0 0 0]
sage: print(R('a_3_4*a_1_0'))
4-Cocycle in H^*(E27; GF(3)),
represented by
[2 0 0 0 0 0 0]
sage: print(R.6*R.8)
4-Cocycle 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: 4-Cocycle 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() and rels().

The attribute H.GenS provides a ring defined in the Singular interface, and H.RelG is a list of strings defining a Groebner basis for the relation ideal. The cohomology ring is isomorphic to the quotient of H.GenS by the ideal of H.RelG. The same ring is created when putting H 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, namely H.prefix. The prefix is chosen automatically and is different for any instance of COHO:

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 is basering. We change the base ring, and then a Groebner basis at least up to degree H.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 using setprop('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: 2-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 c_2_2: 2-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 c_4_4: 4-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_1_1: 1-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_3_3: 3-Cocycle in H^*(SmallGroup(64,14); GF(2))]

It depends on the python version whether or not the relations are tail-reduced 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: 2-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 c_2_2: 2-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 c_4_4: 4-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_1_1: 1-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_3_3: 3-Cocycle 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: 2-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 c_2_2: 2-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 c_4_4: 4-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_1_1: 1-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_3_3: 3-Cocycle 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: 2-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 c_2_2: 2-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 c_4_4: 4-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_1_1: 1-Cocycle in H^*(SmallGroup(64,14); GF(2)),
 a_3_3: 3-Cocycle 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 of self that are known to provide a filter regular HSOP for the cohomology ring

  • dv, the degrees (list of integers) of these parameters

  • forced [optional, default = False]: If True, perform Benson’s test even if it seems to be too low degree

OUTPUT:

  • True if the test succeeded

  • None if the test was not conclusive

  • False 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 non-abelian \(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 GAP-readable 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: 1-Cocycle in H^*(SmallGroup(4,2); GF(2))]}

Finally, we show location and content of the GAP-readable 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 subgroup

  • nr - the position of this group in the Small Group Library

  • n - the subgroup is addressed as subgroup number n

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 and n. The necessary files are created by makeGroupData() or or makeSpecialGroupData() 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 re-inserting the special subgroups, it is necessary to re-compute 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: 2-Cocycle in H^*(D8; GF(2)),
 b_1_0: 1-Cocycle in H^*(D8; GF(2)),
 b_1_1: 1-Cocycle 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 non-negative 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)): 3-Cocycle 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], where

    • i: the identifier (integer) of a special subgroup

    • C: an element of the i-th special subgroup

OUTPUT:

A cochain that has restrictions prescribed in L, or None, 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 in M, and try to find common lifts in H. Note that M corresponds to two pairwise non-conjugate maximal elementary abelian subgroups of the dihedral group, while Z 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]]))
2-Cocycle 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]]))
2-Cocycle 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) of hsop.

OUTPUT:

  • True, False or None, 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 by hsop.

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, from_scratch=True)
sage: H.make()
sage: H is load(H.autosave_name())
True
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 with self.group() and terminating with the trivial group.

degree=-1: Optional parameter. If degree>=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 (class BarCode) respectively bar code of the given degree (class BarCode2d), 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 non-negative 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_{j-1}\), 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 non-trivial 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_{n-1},..., G_0\), while the last \(n\) columns correspond to the factor groups \(G/G_n, G/G_{n-1},..., 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)): 3-Cocycle in H^*(D8; GF(2)),
 (b_1_1)*((b_1_1)*(b_1_1)): 3-Cocycle in H^*(D8; GF(2)),
 (b_1_0)*(c_2_2): 3-Cocycle in H^*(D8; GF(2)),
 (b_1_1)*(c_2_2): 3-Cocycle 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: 4-Cocycle in H^*(SmallGroup(32,32); GF(2)),
 c_4_5: 4-Cocycle in H^*(SmallGroup(32,32); GF(2)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(32,32); GF(2)),
 a_1_1: 1-Cocycle in H^*(SmallGroup(32,32); GF(2)),
 a_1_2: 1-Cocycle in H^*(SmallGroup(32,32); GF(2)),
 a_3_2: 3-Cocycle in H^*(SmallGroup(32,32); GF(2)),
 a_3_3: 3-Cocycle 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 rank r (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 of self, then the result is zero. It is conjectured by J. Carlson that it is non-zero whenever r 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 of self.

OUTPUT:

Let \(G\) be the finite \(p\)-group whose cohomology ring self represents. The attribute subgbDickson of self is changed and contains elements of degree \(p^{r-z}-p^{r-z-i}\) of the cohomology ring of the elementary abelian group \(V\) described by ID, where \(r\) is the \(p\)-rank of \(G\), \(z\) is the rank of the centre of \(G\), and \(i = 1,...,r-z\). 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^{r-z}-p^{r-z-i}\) 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: 2-Cocycle in H^*(SmallGroup(8,5); GF(2)),
   0: 3-Cocycle 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: 2-Cocycle in H^*(SmallGroup(8,5); GF(2)),
   0: 3-Cocycle 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): 2-Cocycle 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)): 3-Cocycle 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 self

OUTPUT:

C is changed in-place and then returned, so that its name represents C 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 parameter KeepBases is True 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: 3-Cocycle in H^*(D8; GF(2))
sage: c is H.element_as_polynomial(c)
True
sage: c
c_2_2*b_1_1: 3-Cocycle 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 of self.group()

OUTPUT:

The ideal of all elements of singular(self) that restrict to zero on all maximal subgroups of self.group() (resp. on the subgroups in the list Subgroups). 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 non-zero 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 semi-dihedral 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 non-vanishing 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 Ctrl-c
    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 2-subgroup 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 non-obvious relations.

ALGORITHM:

  1. 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\).

  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 non-regular generators of degree 3:

sage: H.7
a_3_4: 3-Cocycle in H^*(E27; GF(3))
sage: H.8
a_3_5: 3-Cocycle 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 dictionary self.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: 1-Cocycle in H^*(D8; GF(2))),
 ('b_1_0b_1_0', (b_1_0)*(b_1_0): 2-Cocycle in H^*(D8; GF(2))),
 ('b_1_0b_1_1', (b_1_0)*(b_1_1): 2-Cocycle in H^*(D8; GF(2))),
 ('b_1_1', b_1_1: 1-Cocycle in H^*(D8; GF(2))),
 ('b_1_1b_1_1', (b_1_1)*(b_1_1): 2-Cocycle in H^*(D8; GF(2))),
 ('c_2_2', c_2_2: 2-Cocycle 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 elements

  • BreakPoint (optional integer) – maximal number of parameter candidates tested in each degree. Default None 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 filter-regular parameter in degree 2
    Determine degree 2 standard monomials
explore_one_parameter:
    8 = (2-1)^1*2^3 parameter candidates
    We found a parameter.
    > But it is not filter-regular.
    We found a parameter.
    > It is filter-regular.
H^*(SmallGroup(64,32); GF(2)):
    Exploring 3rd filter-regular parameter in degree 2
    Determine degree 2 standard monomials
explore_one_parameter:
    4 = (2-1)^1*2^2 parameter candidates
    We found a parameter.
    > It is filter-regular.
H^*(SmallGroup(64,32); GF(2)):
    Exploring 4th filter-regular parameter in degree 2
    Determine degree 2 standard monomials
explore_one_parameter:
    2 = (2-1)^1*2^1 parameter candidates
    We found a parameter.
    > It is filter-regular.
['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, or None.

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 nil-radical (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 be None.

  • 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 of P[-1] (if not None) minus one.

OUTPUT:

Either a string defining a parameter in degree at most maxdeg, or P[-1] if such parameter does not exist. A value error is raised, if Par[:-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 Hilbert-Poincaré 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: 1-Cocycle in H^*(D8; GF(2)),
 b_1_1: 1-Cocycle 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: 0-Cocycle 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: 2-Cocycle in H^*(D8; GF(2))
sage: H.2
b_1_0: 1-Cocycle in H^*(D8; GF(2))
sage: print(H.1*H.2)
3-Cocycle 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: 1-Cocycle in H^*(D8; GF(2)), b_1_1: 1-Cocycle in H^*(D8; GF(2))]
sage: H.make()
sage: H.gens()
[1,
 c_2_2: 2-Cocycle in H^*(D8; GF(2)),
 b_1_0: 1-Cocycle in H^*(D8; GF(2)),
 b_1_1: 1-Cocycle 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 isomorphism-

NOTE:

CohomologyRing(self.group()) is always equal to self. It is often even identical with self, 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 a Matrix_gfpn_dense matrix describing a homomorphism of the group algebras (not documented). The domain must be equivalent to the underlying group of other, the codomain must be equivalent to the underlying group of self.

  • other, a cohomology ring

  • M (optional Matrix_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 non-zero then M 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 and G2, 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: 0-Cocycle in H^*(D8; GF(2)),
 b_1_1^2+c_2_2: 2-Cocycle in H^*(D8; GF(2)),
 b_1_1+b_1_0: 1-Cocycle in H^*(D8; GF(2)),
 b_1_1: 1-Cocycle 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 mod-2 cohomology ring of some group of order 48. The ring presentation depends on the choice of a generating system for its Sylow 2-subgroup. Since an internal computation would yield a randomised result, we provide a Sylow 2-subgroup 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 of G 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: 0-Cocycle in H^*(D8; GF(2)), c_2_2: 2-Cocycle in H^*(D8; GF(2)), b_1_0: 1-Cocycle in H^*(D8; GF(2)), b_1_1: 1-Cocycle in H^*(D8; GF(2)), b_1_0: 1-Cocycle 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: 2-Cocycle in H^*(SmallGroup(48,36); GF(2)), b_1_1: 1-Cocycle in H^*(SmallGroup(48,36); GF(2)), b_1_0: 1-Cocycle in H^*(SmallGroup(48,36); GF(2))]

And finally, we consider a homomorphism from G to G, 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: 2-Cocycle in H^*(SmallGroup(48,36); GF(2)), b_1_1: 1-Cocycle in H^*(SmallGroup(48,36); GF(2)), b_1_0: 1-Cocycle in H^*(SmallGroup(48,36); GF(2)), b_1_1: 1-Cocycle 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 to os.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 non-abelian.
  </li>
  <li> It has p-Rank 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&eacute; 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>(&thinsp;&#8722;&thinsp;1 &thinsp;+&thinsp; t)<sup>2</sup></nobr></td></tr>
    </table>
  </li>  <li> The a-invariants are -&infin;,-&infin;,-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&middot;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&thinsp;+&thinsp;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> &rarr; <nobr>0</nobr>, an element of degree 1
      </li>
      <li> <nobr>b_1_0</nobr> &rarr; <nobr>0</nobr>, an element of degree 1
      </li>
      <li> <nobr>c_2_2</nobr> &rarr; <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> &rarr; <nobr>c_1_1</nobr>, an element of degree 1
      </li>
      <li> <nobr>b_1_0</nobr> &rarr; <nobr>0</nobr>, an element of degree 1
      </li>
      <li> <nobr>c_2_2</nobr> &rarr; <nobr>c_1_0&middot;c_1_1&thinsp;+&thinsp;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> &rarr; <nobr>0</nobr>, an element of degree 1
      </li>
      <li> <nobr>b_1_0</nobr> &rarr; <nobr>c_1_1</nobr>, an element of degree 1
      </li>
      <li> <nobr>c_2_2</nobr> &rarr; <nobr>c_1_0&middot;c_1_1&thinsp;+&thinsp;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="font-variant:small-caps">Sage</a>
              <a href="https://users.fmi.uni-jena.de/cohomology/documentation/">cohomology package</a>
              written by <a href="https://users.fmi.uni-jena.de/~king/">Simon King</a>
              and <a href="https://users.fmi.uni-jena.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: 1-Cocycle in H^*(D8; GF(2))),
 ('b_1_0b_1_0', (b_1_0)*(b_1_0): 2-Cocycle in H^*(D8; GF(2))),
 ('b_1_0b_1_1', (b_1_0)*(b_1_1): 2-Cocycle in H^*(D8; GF(2))),
 ('b_1_1', b_1_1: 1-Cocycle in H^*(D8; GF(2))),
 ('b_1_1b_1_1', (b_1_1)*(b_1_1): 2-Cocycle in H^*(D8; GF(2))),
 ('c_2_2', c_2_2: 2-Cocycle 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 cut-off 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 non-isomorphic. 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>&middot;b_1_0</nobr>, an element of degree 5'
sage: H.item2html(H.poincare_series())
'<nobr>1/(t<sup>2 </sup>&thinsp;&#8722;&thinsp; 2&middot;t &thinsp;+&thinsp; 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 mod-2 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: 4-Cocycle in H^*(M11; GF(2)),
 b_3_0: 3-Cocycle in H^*(M11; GF(2)),
 b_5_0: 5-Cocycle 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))
1-Cocycle in H^*(D8; GF(2)),
represented by
[1 1]
sage: print(H.lift_dickson(0,1))
2-Cocycle 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 degree max_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: 2-Cocycle in H^*(SmallGroup(32,5); GF(2)),
 c_2_2: 2-Cocycle in H^*(SmallGroup(32,5); GF(2)),
 c_2_3: 2-Cocycle in H^*(SmallGroup(32,5); GF(2)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(32,5); GF(2)),
 b_1_1: 1-Cocycle 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: 2-Cocycle in H^*(SmallGroup(32,5); GF(2)),
 c_2_2: 2-Cocycle in H^*(SmallGroup(32,5); GF(2)),
 c_2_3: 2-Cocycle in H^*(SmallGroup(32,5); GF(2)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(32,5); GF(2)),
 b_1_1: 1-Cocycle 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 bound

NOTE:

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 re-computation 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, default True): If it is False, 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: 1-Cocycle in H^*(D8; GF(2))
sage: H.3
b_1_1: 1-Cocycle in H^*(D8; GF(2))
sage: H.rels()
['b_1_0*b_1_1']

Since the product of H.2 and H.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: 2-Cocycle in H^*(D8; GF(2)), b_1_0^2: 2-Cocycle in H^*(D8; GF(2))]
sage: sorted(list(H.massey_products(H.3,H.2,H.3)))
[0: 2-Cocycle in H^*(D8; GF(2)), b_1_1^2: 2-Cocycle 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: 6-Cocycle in H^*(SmallGroup(16,2); GF(2)),
 c_2_1*c_2_2*c_1_0*c_1_1: 6-Cocycle in H^*(SmallGroup(16,2); GF(2)),
 c_2_1^2*c_1_0*c_1_1: 6-Cocycle 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: 6-Cocycle 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: 8-Cocycle 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_{n-1},c_nc\rangle,\)

where \(c,c_1,...,c_n\) are cocycles, and the multiplication on the left hand side is taken element-wise. For our example, we use the extraspecial 3-group of order 27 and exponent 3:

sage: H = CohomologyRing(27,3)
sage: H.make()
sage: H.gens()
[1, b_2_0: 2-Cocycle in H^*(E27; GF(3)), b_2_1: 2-Cocycle in H^*(E27; GF(3)), b_2_2: 2-Cocycle in H^*(E27; GF(3)), b_2_3: 2-Cocycle in H^*(E27; GF(3)), c_6_8: 6-Cocycle in H^*(E27; GF(3)), a_1_0: 1-Cocycle in H^*(E27; GF(3)), a_1_1: 1-Cocycle in H^*(E27; GF(3)), a_3_4: 3-Cocycle in H^*(E27; GF(3)), a_3_5: 3-Cocycle in H^*(E27; GF(3))]
sage: H.massey_products(H.6,H.6,H.6,all=False)
{-b_2_0: 2-Cocycle 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_4-b_2_0*c_6_8: 8-Cocycle 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 that -b_2_0^2*a_1_1*a_3_5+b_2_0^2*a_1_0*a_3_5 is a multiple of H.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) contains -b_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: 1-Cocycle in H^*(D8; GF(2)),
b_1_1: 1-Cocycle 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: 2-Cocycle in H^*(D8; GF(2)),
b_1_0: 1-Cocycle in H^*(D8; GF(2)),
b_1_1: 1-Cocycle 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 nil-radical of the \(n\)-th special subgroup.

INPUT:

  • n: an integer indicating a special subgroup

    • n=1 refers to the greatest central elementary abelian subgroup

    • n>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 non-trivial 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_1-b_2_0,
b_2_2,
b_2_3-b_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 non-zero 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'))
2-Cocycle 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'))
2-Cocycle 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)
4-Cocycle 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)
4-Cocycle 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: 2-Cocycle in H^*(SmallGroup(16,2); GF(2)),
 c_2_2: 2-Cocycle in H^*(SmallGroup(16,2); GF(2)),
 c_1_0: 1-Cocycle in H^*(SmallGroup(16,2); GF(2)),
 c_1_1: 1-Cocycle 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

nil_radical()

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 degree-wise 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: 5-Cocycle in H^*(SmallGroup(64,18); GF(2)),
 a_5_5: 5-Cocycle in H^*(SmallGroup(64,18); GF(2)),
 ((b_2_3)**2)*(a_1_1): 5-Cocycle in H^*(SmallGroup(64,18); GF(2)),
 ((b_2_2)**2)*(a_1_0): 5-Cocycle in H^*(SmallGroup(64,18); GF(2)),
 (a_2_0)*(b_3_5): 5-Cocycle in H^*(SmallGroup(64,18); GF(2)),
 (a_2_0)*(b_3_4): 5-Cocycle in H^*(SmallGroup(64,18); GF(2))]
sage: H2.nilspace(5)
[((b_2_2)**2)*(a_1_1): 5-Cocycle in H^*(SmallGroup(64,19); GF(2)),
 (a_2_1)*(b_3_5): 5-Cocycle in H^*(SmallGroup(64,19); GF(2)),
 (a_2_0)*(b_3_5): 5-Cocycle in H^*(SmallGroup(64,19); GF(2)),
 (a_2_0)*(b_3_4): 5-Cocycle in H^*(SmallGroup(64,19); GF(2))]
sage: H3.nilspace(5)
[a_5_4: 5-Cocycle in H^*(SmallGroup(64,25); GF(2)),
 ((b_2_2)**2)*(a_1_1): 5-Cocycle in H^*(SmallGroup(64,25); GF(2)),
 ((b_2_2)**2)*(a_1_0): 5-Cocycle in H^*(SmallGroup(64,25); GF(2)),
 (a_2_1)*(b_3_5): 5-Cocycle in H^*(SmallGroup(64,25); GF(2)),
 (a_2_0)*(b_3_5): 5-Cocycle 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 non-obvious 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 filter-regular 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, default False) If this argument is True and``self`` is already completed and happens to be Cohen-Macaulay, a self consistence check is applied, based on Benson-Carlson 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 from FRS

  • 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\).

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: 2-Cocycle in H^*(E27; GF(3)),
 b_2_1: 2-Cocycle in H^*(E27; GF(3)),
 b_2_2: 2-Cocycle in H^*(E27; GF(3)),
 b_2_3: 2-Cocycle in H^*(E27; GF(3)),
 c_6_8: 6-Cocycle in H^*(E27; GF(3)),
 a_1_0: 1-Cocycle in H^*(E27; GF(3)),
 a_1_1: 1-Cocycle in H^*(E27; GF(3)),
 a_3_4: 3-Cocycle in H^*(E27; GF(3)),
 a_3_5: 3-Cocycle in H^*(E27; GF(3))]

During these computations, Dickson classes have been computed. We found:

sage: H.Dickson
['b_2_3^2-b_2_0*b_2_2-b_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 of H, 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^2-b_2_0*b_2_2-b_2_0*b_2_1+b_2_0^2'],[6,4])
7

The previous line means: If ['c_6_8','b_2_3^2-b_2_0*b_2_2-b_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^2-b_2_0*b_2_2-b_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 filter-regular 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: 2-Cocycle in H^*(D8; GF(2))]

So, if the computation was complete, c_2_2 and b_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, although H 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: 2-Cocycle in H^*(SmallGroup(720,763); GF(2)),
 c_1_0: 1-Cocycle in H^*(SmallGroup(720,763); GF(2)),
 b_3_3: 3-Cocycle in H^*(SmallGroup(720,763); GF(2)),
 c_3_2: 3-Cocycle 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: 6-Cocycle 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 non-obvious 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 non-obvious 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 subgroup

    • n=1 refers to the greatest central elementary abelian subgroup

    • n>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: 2-Cocycle in H^*(SmallGroup(2,1); GF(2)),
 0: 1-Cocycle in H^*(SmallGroup(2,1); GF(2)),
 0: 1-Cocycle 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: 2-Cocycle in H^*(SmallGroup(4,2); GF(2)),
 c_1_1: 1-Cocycle in H^*(SmallGroup(4,2); GF(2)),
 0: 1-Cocycle in H^*(SmallGroup(4,2); GF(2))]
sage: H.restrict_to_subgroup(3)
[c_1_0*c_1_1+c_1_0^2: 2-Cocycle in H^*(SmallGroup(4,2); GF(2)),
 0: 1-Cocycle in H^*(SmallGroup(4,2); GF(2)),
 c_1_1: 1-Cocycle 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 subgroup

    • n=1 refers to the greatest central elementary abelian subgroup

    • n>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 non-obvious 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 doing singular(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 string

  • value, any object

OUTPUT:

value is now available as an attribute key 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 of self or a polynomial in the Singular interface. If it is an element of self, C.name() must express C as polynomial in the generators of self.

  • enumerate – (bool, default False) If True, the factorisation takes into account the relations in self, 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 of self, use element_as_polynomial().

OUTPUT:

A string, providing a small non-scalar factor of C, allowing modification by multiples of nilpotent generators.

NOTE:

If the optional argument enumerate is True, then in each degree, at most 1000 candidates are tested; this default can be altered by assigning a value to pGroupCohomology.resolution.coho_options['NrCandidates'].

NOTE:

If the computation is interrupted with Ctrl-c, 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: 4-Cocycle in H^*(SmallGroup(64,235); GF(2)),
 c_4_14: 4-Cocycle in H^*(SmallGroup(64,235); GF(2)),
 a_1_1: 1-Cocycle in H^*(SmallGroup(64,235); GF(2)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(64,235); GF(2)),
 b_1_2: 1-Cocycle in H^*(SmallGroup(64,235); GF(2)),
 b_1_3: 1-Cocycle in H^*(SmallGroup(64,235); GF(2)),
 b_3_10: 3-Cocycle 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 Ctrl-c
    Exploring factors of an element by enumeration (can be interrupted with Ctrl-c)
    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 cochain

  • i: integer

  • rdeg, ydeg: (optional) integers or None (default None).

  • 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: 3-Cocycle in H^*(D8; GF(2))
sage: print(c)
3-Cocycle 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) or None (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_5-b_2_4^2-b_2_3^2']
sage: H81.parameters()
['c_6_8', 'b_4_5-b_2_4^2-b_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: 'H.filter_degree_type' in tc.completions('H.f',globals())  # indirect doctest
True
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: 1-Cocycle in H^*(D8; GF(2)),
 b_1_1: 1-Cocycle 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, and

  • r - 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 of GapPickler. When unpickle_gap_data() is applied to the result, then it will create an object in Gap in lieue of any string that is stored in a GapPickler 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 integers

OUTPUT:

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 multiplied

  • L_0, an element

OUTPUT:

The product (L_1...*(L_{n-1}*(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, default 0) If 1 (not default), find

    a parameter that is filter regular modulo Id. If 2, find a parameter that is regular modulo Id.

  • H1 – (optional) the Hilbert Poincaré series of Id.

  • is_monomial – (optional) whether the element in L0 are monomials.

OUTPUT:

    1. An element \(v\) in Singular that lowers the dimension of Id by one (aka “parameter” for Id),

    2. A tuple of integers, namely the list of coefficients that defines v as linear combination of the monomials in L.

    3. The return value of is_filter_regular, if regularity==1, or [].

  • False, False, [], if no linear combination of elements of L provides a parameter for Id, or

  • None, None, [], if the search for a parameter was stopped since the number of candidates exceeded BreakPoint.

NOTE:

If \(is_monomial\) is true, then only lineare combinations of the standard monomials in L0 relative to Id 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 non-commutative examples. We do not need to distinguish Singular versions 3-1-1 and older versions, since in this example there are regular respectively filter-regular 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 filter-regular 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., \(\{p|f\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 filter-regular 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 of len(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, then False 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 attribute GenS 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 argument forced added to the method’s arguments. Note that forced 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 re-computation at <....FOO ... at ...> with ``forced=True``
foo interrupted. Force re-computation at <....FOO ... at ...> with ``forced=True``

The KeyboardInterrupt is cached. So, even if we set the attribute _t above to a non-zero value, the error won’t go away, unless we force re-computation:

sage: f._t = 2
sage: try:
....:     f.bar(1)
....: except KeyboardInterrupt as msg:
....:     print(msg)
bar interrupted. Force re-computation 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 re-computation at <....FOO ... at ...> with ``forced=True``
foo interrupted. Force re-computation 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 re-computation at <....FOO ... at ...> with ``forced=True``

This results in creating a cache for f. Note that even the KeyboardInterrupt is cached:

sage: sorted(f._decorator_cache.items())    #indirect doctest
[(('bar', Group([ (1,2) ])), [2]),
 (('foo', 3),
  [KeyboardInterrupt('foo interrupted. Force re-computation ...)])]
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. When unpickle_gap_data() is applied to the result, then it will create an object in Gap in lieue of any string that is stored in a GapPickler 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 polynomial

  • linelength=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 ‘&middot;’

  • 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>&thinsp;+&thinsp; x<sup>2 </sup>&thinsp;+&thinsp; 2&middot;x&middot;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>&thinsp;+&thinsp; x<sup>2 </sup></nobr><br>&nbsp;&nbsp;<nobr>&thinsp;+&thinsp; 2&middot;x&middot;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). Unlike permanent_result, the cached value is re-computed 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 – see permanent_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 of GapPickler. 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 a GapPickler 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