Elements and maps of cohomology rings¶
AUTHORS:
 Simon King <simon.king@unijena.de>
This module provides elements of modular cohomology rings of
groups of prime power order (COCH
), of finite groups
that are not of prime power order (MODCOCH
), induced
maps between cohomology rings (ChMap
), and Yoneda
cochains for prime power groups (YCOCH
). While Yoneda
cochains are just a tool for our implementation of Massey
products and Kraines’ restricted Massey powers, the other
three classes are vital for cohomology computations.
The class COCH
provides elements of the mod\(p\) cohomology of
a finite \(p\)group \(P\). It is based on a minimal free resolutions of
\(F_pP\) provided by the class RESL
.
The cup product is computed by standard constructions from homological
algebra.
In contrast, MODCOCH
provides elements of the mod\(p\)
cohomology of any finite group \(G\). The underlying data are stable
elements of the mod\(p\) cohomology ring of a subgroup \(U\) of \(G\) whose
index is coprime to \(p\). This ring is represented in the Singular
interface. For instance, \(P\) may be a Sylow \(p\)subgroup of \(G\). It is
allowed that \(G=U\) is a finite \(p\)group, but in this case, the
cohomology ring of \(G\) must first be computed using COCH
.
Group homomorphisms induce maps in cohomology, and this is provided by
ChMap
. Induced homomorphisms are essential for the
computation of cohomology rings of finite groups that are not of prime
power order: The conditions defining stable elements are expressed in
terms of pairs of induced maps.
COCH
, MODCOCH
and ChMap
can quite easily be
combined, which can be seen in the following examples.
EXAMPLES:
We define two groups (one of them is of prime power order) and compute their cohomology rings.
sage: from pGroupCohomology import CohomologyRing
sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace
sage: S = libgap.SymmetricGroup(6)
sage: D = libgap.DihedralGroup(8)
sage: HS = CohomologyRing(S, prime=2, GroupName='Sym6', from_scratch=True)
sage: HS.make()
sage: HD = CohomologyRing(D, GroupName='D_8', from_scratch=True)
sage: HD.make()
We do some computations with cohomology elements, testing relations in
HS
and HD
:
sage: cD1 = HD.1+HD.2*HD.3; cD1
c_2_2+(b_1_0)*(b_1_1): 2Cocycle in H^*(D_8; GF(2))
sage: cD2 = HD.1+HD.3^2; cD2
c_2_2+(b_1_1)**2: 2Cocycle in H^*(D_8; GF(2))
sage: cD1 == cD2
True
sage: HD.rels()
['b_1_1^2+b_1_0*b_1_1']
sage: cS1 = HS.1*HS.2+HS.3; cS1
(c_2_1)*(c_1_0)+(b_3_2): 3Cocycle in H^*(Sym6; GF(2))
sage: cS2 = HS.1*HS.2+HS.4; cS2
(c_2_1)*(c_1_0)+(b_3_3): 3Cocycle in H^*(Sym6; GF(2))
sage: cS1*cS2 == HS.3*HS.4 + HS.1*HS.2*(HS.1*HS.2+HS.3+HS.4)
True
sage: HS.rels()
['b_3_2*b_3_3']
We define an embedding of D
in S
and compute the induced
map from HS
to HD
:
sage: emb = D.GroupHomomorphismByImages(S,D.GeneratorsOfGroup(),libgap.eval('[ (2,4), (1,2,3,4), (1,3)(2,4) ]'))
sage: resS_D = HS.hom(emb,HD)
sage: [resS_D(g).as_polynomial() for g in HS.gens()[1:]]
['b_1_0*b_1_1+b_1_0^2+c_2_2',
'b_1_1+b_1_0',
'c_2_2*b_1_1+c_2_2*b_1_0',
'b_1_0^2*b_1_1+c_2_2*b_1_1']
Note that the generators of HD
are COCH
, while those of
HS
are MODCOCH
. But the image of the induced map is
formed by MODCOCH
:
sage: type(HD.1)
<type 'pGroupCohomology.cochain.COCH'>
sage: type(HS.1)
<class 'pGroupCohomology.cochain.MODCOCH'>
sage: type(resS_D(HS.1))
<class 'pGroupCohomology.cochain.MODCOCH'>
It is possible to mix both classes in arithmetic expressions:
sage: resS_D(HS.2) == HD.2+HD.3
True
sage: resS_D(HS.1)*resS_D(HS.2) == resS_D(HS.1)*HD.2+resS_D(HS.1)*HD.3
True

class
pGroupCohomology.cochain.
COCH
¶ COCH extension class representing elements of cohomology rings.
INPUT:
H
– a cohomology ring (COHO
)n
– the degree of the cochain (integer)s
– name of the \(n\)cochain (string)M
– data describing the cochain. Either a \((1 \times d)\)
Matrix_gfpn_dense
matrix, or  a \(d\)tuple of integers
 a \((1 \times d)\)
where \(d\) is the projective rank of the \(n\)th term of the resolution that underlies
H
ydeg
(optional, defaultNone
) – ydegree of the cochainrdeg
(optional, defaultNone
) – rdegree of the cochain
OUTPUT:
A degree \(n\) element of
H
of name s.NOTE:
 Usually, a cochain will be created by doing algebra with the generators of a cohomology ring.
 In our application (see
pGroupCohomology
),rdeg==1
if and only if the cochain is a Duflot regular generator of a cohomology ring;ydeg==1
if and only if the cochain is a generator of a cohomology ring that is neither nilpotent nor Duflot regular.  Every cochain is provided with a name. When a cochain is the result of a computation then its name will by default describe its construction. We think that this is a very useful feature.
EXAMPLES:
First, we show how one would usually create a cochain:
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.2 sage: D = H.3 sage: C b_1_0: 1Cocycle in H^*(D8; GF(2)) sage: D b_1_1: 1Cocycle in H^*(D8; GF(2)) sage: C+D b_1_0+b_1_1: 1Cocycle in H^*(D8; GF(2)) sage: C*D (b_1_0)*(b_1_1): 2Cocycle in H^*(D8; GF(2)) sage: print(C^3) 3Cocycle in H^*(D8; GF(2)), represented by [1 0 0 0] sage: print(D^3) 3Cocycle in H^*(D8; GF(2)), represented by [0 1 0 0]
Next, we show a noncommutative example. Just for documentation, we create the cochains more directly:
sage: H = CohomologyRing(27,3, from_scratch=True) sage: print(H.resolution()) Resolution: 0 < GF(3) < GF(3)[E27]
Incidentally, we know that the projective rank of the second term of the resolution is four. So, we can define:
sage: from pGroupCohomology.cochain import COCH sage: C = COCH(H,2,'first',(1,0,1,2))
Now, the resolution is computed out to the second term, and the cochain
C
has the name ‘first’:sage: print(H.resolution()) Resolution: 0 < GF(3) < GF(3)[E27] < rank 2 < rank 4 sage: C first: 2Cocycle in H^*(E27; GF(3)) sage: print(C) 2Cocycle in H^*(E27; GF(3)), represented by [1 0 1 2]
Using
Matrix_gfpn_dense
matrices, we provide a slightly different way to create a cochain. The matrix must be immutable:sage: from sage.matrix.matrix_gfpn_dense import Matrix_gfpn_dense as MTX sage: D = COCH(H,2,'second', MTX(MatrixSpace(GF(3),1,4, implementation=MTX), [[0,1,0,1]], mutable=False))
Now, we can add or subtract the cochains:
sage: C+D first+second: 2Cocycle in H^*(E27; GF(3)) sage: print(C+D) 2Cocycle in H^*(E27; GF(3)), represented by [1 1 1 0] sage: print(CD) 2Cocycle in H^*(E27; GF(3)), represented by [1 2 1 1]
Scalar multiplication works as well:
sage: 2*C 2*(first): 2Cocycle in H^*(E27; GF(3)) sage: print(C*2) 2Cocycle in H^*(E27; GF(3)), represented by [2 0 2 1]
But certainly, in cohomology computations the cupproduct is the most interesting:
sage: C*D (first)*(second): 4Cocycle in H^*(E27; GF(3)) sage: print(H.resolution()) Resolution: 0 < GF(3) < GF(3)[E27] < rank 2 < rank 4 < rank 6 < rank 7 sage: E = C^2 sage: E = C^2+D*C*2 sage: E (first)**2+((second)*(first))*2: 4Cocycle in H^*(E27; GF(3)) sage: print(E) 4Cocycle in H^*(E27; GF(3)), represented by [2 2 0 1 0 0 2]
Since \(p>2\) in this example, the cohomology ring is noncommutative:
sage: X = COCH(H,3,'X',(1,1,1,0,0,0)) sage: Y = COCH(H,3,'Y',(0,0,0,1,1,1)) sage: print(X*Y) 6Cocycle in H^*(E27; GF(3)), represented by [2 1 1 0 0 0 0 0 0] sage: print(Y*X) 6Cocycle in H^*(E27; GF(3)), represented by [1 2 2 0 0 0 0 0 0]
The name (which by default describes the construction of the cochain) can be overwritten:
sage: E.name() '(first)**2+((second)*(first))*2' sage: E.setname('foo') sage: E foo: 4Cocycle in H^*(E27; GF(3))

MTX
(*args, **kwds)¶ COCH.MTX(self) > Matrix_gfpn_dense
Return the
Matrix_gfpn_dense
matrix by whichself
is defined.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.2*H.1 sage: print(C.MTX()) [0 0 1 0]

as_polynomial
()¶ Return a string that represents
self
as a polynomial in its parent.NOTE:
The name of
self
will be modified inplaceEXAMPLES:
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.1*H.2+H.3^3 sage: c (c_2_2)*(b_1_0)+(b_1_1)**3: 3Cocycle in H^*(D8; GF(2)) sage: c.setname('foo') sage: c foo: 3Cocycle in H^*(D8; GF(2)) sage: c.as_polynomial() 'b_1_1^3+c_2_2*b_1_0' sage: c b_1_1^3+c_2_2*b_1_0: 3Cocycle in H^*(D8; GF(2))

deg
()¶ Return the degree 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() sage: C=H.2*H.1 sage: C.deg() 3

is_nilpotent
()¶ Tells whether this cocycle is nilpotent.
An elemenet of a mod\(p\) cohomology ring of a finite group is nilpotent if and only if the restrictions to all maximal \(p\)elementary abelian subgroups are.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace
An example in even characteristic:
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: H('b_1_0*b_1_2+b_1_0^2').is_nilpotent() True sage: H('b_1_0*b_1_3+b_1_0*b_1_2').is_nilpotent() False sage: H('b_1_0*b_1_3+b_1_0*b_1_1+b_1_0^2').is_nilpotent() True
An example in odd characteristic:
sage: H = CohomologyRing(81,13) sage: H.make() sage: H.nil_radical() a_1_0, a_1_1, a_1_2, a_3_6, a_5_10 sage: c = H('a_1_2*a_5_10') sage: bool(c) True sage: c.is_nilpotent() True sage: c.nilpotency_degree() 2
Two abelian examples, that gave a wrong answer with previous versions of the spkg:
sage: H = CohomologyRing(3^4,gap.NumberSmallGroups(3^4)) sage: H.make() sage: (H.5*H.6+H.7*H.8).is_nilpotent() True sage: (H.5*H.6+H.7*H.8).nilpotency_degree() 3 sage: H = CohomologyRing(16,2) sage: H.make() sage: H.3.is_nilpotent() True sage: H.3.nilpotency_degree() 2

label
()¶ COCH.name(self)
Return the name of
self
.NOTE:
When a
COCH
instance is created by invoking the init method, a name must be given. When furtherCOCH
instances are created by arithmetic operations, the name of the result describes its construction.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.2*H.1 sage: print(C.name()) (b_1_0)*(c_2_2) sage: H(C.name()) == C True
Note that there is no automatic simplification when the result represents the trivial cochain:
sage: (C*2).name() '((b_1_0)*(c_2_2))*0' sage: print(C*2) 3Cocycle in H^*(D8; GF(2)), represented by [0 0 0 0]

massey_power
(i=1)¶ Return the \(p^i\)fold restricted Massey product of
self
, orNone
if it does not exist.INPUT:
i
(optional integer, default 1)OUTPUT:
A cochain with the same parent as
self
, named"<%s; %d>"%(self.name(),i)
.NOTE:
We refer to the \(p^i\)fold restricted Massey product as the \(i\)th restricted Massey power.
According to [Kraines], for \(p > 2\), the 1st restricted Massey power of a cocycle \(C\) of odd degree in a cohomology ring with coefficients in \(\mathbb F_p\) is minus the Bockstein of the Steenrod \(p\)th power, \(\beta P^1(C)\).
EXAMPLES:
First, we study an example in the cohomology ring of an elementary abelian \(p\)group. The cohomology ring is simple enough to allow for an explicit computation of Bockstein and Steenrod powers.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(9,2) sage: H.make() sage: H.gens() [1, c_2_1: 2Cocycle in H^*(SmallGroup(9,2); GF(3)), c_2_2: 2Cocycle in H^*(SmallGroup(9,2); GF(3)), a_1_0: 1Cocycle in H^*(SmallGroup(9,2); GF(3)), a_1_1: 1Cocycle in H^*(SmallGroup(9,2); GF(3))]
We compute the 1st restricted Massey powers of the degree one generators. Of course, the degree two generators have no Massey power, as they are not nilpotent.
sage: print(H.1.massey_power()) None sage: H.element_as_polynomial(H.3.massey_power()) c_2_1: 2Cocycle in H^*(SmallGroup(9,2); GF(3)) sage: H.element_as_polynomial(H.4.massey_power()) c_2_2: 2Cocycle in H^*(SmallGroup(9,2); GF(3))
Since indeed \(c_{2,1}\) and \(c_{2,2}\) are the Bocksteins of \(a_{1,0}\) and \(a_{1,1}\), Kraines’ formula is verified in degree one. But it also holds in degree three, as we are now going to show.
We consider \(C = a_{1,0}c_{2,1}\). By Cartan formula and since \(P^0\) is the identity, we have \(P^1(C) = P^1(a_{1,0})c_{2,1} + a_{1,0}P(c_{2,1})\). Since \(P^1\) vanishes in degree one and acts as the \(p\)th power in degree two, we get \(P^1(C) = a_{1,0}c_{2,1}^3\). Applying the Bockstein operator \(\beta\), we get \(\beta P^1(C) = c_{2,1}^4\), since \(\beta(c_{2,1}) = \beta^2(c_{1,0}) = 0\) and since \(\beta(xy)=\beta(x)y + (1)^{\deg x}x\beta(y)\). Hence, according to Kraines, we should get \(\langle a_{1,0}c_{2,1}; 1\rangle =  c_{2,1}^4\). And indeed:
sage: (H.1*H.3).massey_power() <(c_2_1)*(a_1_0); 1>: 8Cocycle in H^*(SmallGroup(9,2); GF(3)) sage: H.element_as_polynomial(_) c_2_1^4: 8Cocycle in H^*(SmallGroup(9,2); GF(3))
We now consider a more advanced example, namely the extraspecial 3group of order 27 and exponent 3:
sage: H = CohomologyRing(27,3) sage: H.make()
We compute generators for the nil radical of
H
and compute the 3fold Massey product for each generator that is of degree not more than 5:sage: singular(H).set_ring() sage: N = [H(str(X)) for X in H.nil_radical()] sage: MP = [X.massey_power() for X in N] sage: MP [<a_1_0; 1>: 2Cocycle in H^*(E27; GF(3)), <a_1_1; 1>: 2Cocycle in H^*(E27; GF(3)), <a_3_4; 1>: 8Cocycle in H^*(E27; GF(3)), <a_3_5; 1>: 8Cocycle in H^*(E27; GF(3))]
After expressing them as polynomials in the cohomology generators, we obtain
sage: [H.element_as_polynomial(X) for X in MP] [b_2_0: 2Cocycle in H^*(E27; GF(3)), b_2_3: 2Cocycle in H^*(E27; GF(3)), 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: 8Cocycle in H^*(E27; GF(3)), b_2_0^3*b_2_2b_2_0^2*a_1_1*a_3_5b_2_0^2*a_1_0*a_3_5+b_2_3*c_6_8+b_2_0*c_6_8: 8Cocycle in H^*(E27; GF(3))]
Hence, particularly interesting seems to be the first restricted Massey power of the degree three generators of
H
. We take the restriction maps to the four classes of maximal elementary abelian subgroups, which are all of order 9:sage: r1 = H.restriction_maps()[2][1] sage: r1 Induced homomorphism of degree 0 from H^*(E27; GF(3)) to H^*(SmallGroup(9,2); GF(3)) sage: r2 = H.restriction_maps()[3][1] sage: r3 = H.restriction_maps()[4][1] sage: r4 = H.restriction_maps()[5][1] sage: C = H.8 sage: C a_3_4: 3Cocycle in H^*(E27; GF(3)) sage: U = r1.codomain() sage: U.element_as_polynomial(r1(C)) 0: 3Cocycle in H^*(SmallGroup(9,2); GF(3)) sage: U.element_as_polynomial(r2(C)) c_2_2*a_1_0+c_2_1*a_1_1: 3Cocycle in H^*(SmallGroup(9,2); GF(3)) sage: U.element_as_polynomial(r3(C)) c_2_2*a_1_0+c_2_1*a_1_1: 3Cocycle in H^*(SmallGroup(9,2); GF(3)) sage: U.element_as_polynomial(r4(C)) c_2_2*a_1_1c_2_2*a_1_0+c_2_1*a_1_1: 3Cocycle in H^*(SmallGroup(9,2); GF(3))
Hence, after computing Bockstein and Steenrod power in
U
as above, and since Steenrod power and Bockstein commute with restriction maps, the theorem of Kraines tells us that \(\langle C; 1\rangle\) should restrict to \(0\), \(c_{2,1}c_{2,2}^3  c_{2,1}^3c_{2,2}\), \(c_{2,1}c_{2,2}^3  c_{2,1}^3c_{2,2}\), and \(c_{2,2}^4  c_{2,1}c_{2,2}^3 + c_{2,1}^3c_{2,2}\). It does:sage: CP = C.massey_power() sage: U.element_as_polynomial(r1(CP)) 0: 8Cocycle in H^*(SmallGroup(9,2); GF(3)) sage: U.element_as_polynomial(r2(CP)) c_2_1*c_2_2^3c_2_1^3*c_2_2: 8Cocycle in H^*(SmallGroup(9,2); GF(3)) sage: U.element_as_polynomial(r3(CP)) c_2_1*c_2_2^3c_2_1^3*c_2_2: 8Cocycle in H^*(SmallGroup(9,2); GF(3)) sage: U.element_as_polynomial(r4(CP)) c_2_2^4+c_2_1*c_2_2^3c_2_1^3*c_2_2: 8Cocycle in H^*(SmallGroup(9,2); GF(3))
It is known that for this group, a cocycle is uniquely determined by its restrictions to the maximal elementary abelian subgroups. Hence, we have verified the computation of the first restricted Massey power of
C
.We don’t know of general results in the case of even characteristic. However, even in this case, we find that cocycles of higher degree can be produced by restricted Massey powers, for example for the cohomology ring of \(C_4\times C_4\):
sage: H = CohomologyRing(16,2) sage: H.make() sage: x,a,b,c,d = H.gens() sage: c c_1_0: 1Cocycle in H^*(SmallGroup(16,2); GF(2)) sage: d c_1_1: 1Cocycle in H^*(SmallGroup(16,2); GF(2)) sage: H.element_as_polynomial(c.massey_power()) 0: 2Cocycle in H^*(SmallGroup(16,2); GF(2)) sage: H.element_as_polynomial(d.massey_power()) 0: 2Cocycle in H^*(SmallGroup(16,2); GF(2)) sage: H.element_as_polynomial(c.massey_power(2)) c_2_1: 2Cocycle in H^*(SmallGroup(16,2); GF(2)) sage: H.element_as_polynomial(d.massey_power(2)) c_2_2: 2Cocycle in H^*(SmallGroup(16,2); GF(2))
We verify that the result is consistent with the setvalued nonrestricted Massey products:
sage: sorted(list(H.massey_products(c,c,c,c))) [c_2_1: 2Cocycle in H^*(SmallGroup(16,2); GF(2)), c_2_1+c_1_0*c_1_1: 2Cocycle in H^*(SmallGroup(16,2); GF(2))] sage: sorted(list(H.massey_products(d,d,d,d))) [c_2_2: 2Cocycle in H^*(SmallGroup(16,2); GF(2)), c_2_2+c_1_0*c_1_1: 2Cocycle in H^*(SmallGroup(16,2); GF(2))]

name
()¶ Return the name of
self
.NOTE:
When a
COCH
instance is created by invoking the init method, a name must be given. When furtherCOCH
instances are created by arithmetic operations, the name of the result describes its construction.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.2*H.1 sage: print(C.name()) (b_1_0)*(c_2_2) sage: H(C.name()) == C True
Note that there is no automatic simplification when the result represents the trivial cochain:
sage: (C*2).name() '((b_1_0)*(c_2_2))*0' sage: print(C*2) 3Cocycle in H^*(D8; GF(2)), represented by [0 0 0 0]

nilpotency_degree
()¶ The smallest exponent by which this cocycle becomes zero.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(64,18) sage: H.make() sage: H.nil_radical() a_1_0, a_1_1, a_2_0, a_2_1, a_5_5, a_5_8, a_6_7, a_6_10 sage: c = H('a_5_5') sage: c.nilpotency_degree() 4
The following takes quite long, as it is needed to compute the resolution of this cohomology ring out to degree 20. However, it confirms the stated nilpotency degree:
sage: bool(c^2), bool(c^3), bool(c^4) (True, True, False)
If the cocycle is not nilpotent, infinity is returned:
sage: c = H('b_2_3') sage: c.is_nilpotent() False sage: c.nilpotency_degree() +Infinity
Of course, a zero cochain has nilpotency degree one:
sage: (c*0).nilpotency_degree() 1

normalize
()¶ Scale
self
inplace so that its leading coefficient is 1 (if nonzero).OUTPUT:
True
if self is a nullcochain, andNone
otherwiseEXAMPLES:
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: C=2*H.1+H.2 sage: print(C) 2Cocycle in H^*(E27; GF(3)), represented by [2 1 0 0] sage: C.normalize() sage: print(C) 2Cocycle in H^*(E27; GF(3)), represented by [1 2 0 0] sage: C (2*(b_2_0)+b_2_1)/2: 2Cocycle in H^*(E27; GF(3)) sage: D = 0*H.2 sage: D.normalize() True sage: D 0*(b_2_1): 2Cocycle in H^*(E27; GF(3))

rdeg
()¶ Return the \(r\)degree of
self
.NOTE:
The rdegree plays an important role in the computation of cohomology rings. A generator of a cohomology ring has
rdeg==1
if and only if it is a Duflot regular generator, which means that its restriction to the greatest central elementary abelian subgroup is not nilpotent.EXAMPLES:
The example produces files. For safety reasons, we choose files in a temporary directory; it will be removed as soon as Sage is quit:
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.1.rdeg() 1 sage: H.2.rdeg() 0 sage: H.3.rdeg() 0

resolution
()¶ Return the underlying resolution.
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: from pGroupCohomology.cochain import COCH sage: C=COCH(H,2,'foo',(1,1,0))
Note that the needed terms of the resolution are automatically computed:
sage: print(C.resolution()) Resolution: 0 < GF(2) < GF(2)[D8] < rank 2 < rank 3 sage: C.resolution() is H.resolution() True

right_multiplication
()¶ Return the cohomology ring endomorphism given by rightmultiplication with
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() sage: print(H) Cohomology ring of Dihedral group of order 8 with coefficients in GF(2) <BLANKLINE> Computation complete Minimal list of generators: [c_2_2: 2Cocycle in H^*(D8; GF(2)), b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))] Minimal list of algebraic relations: [b_1_0*b_1_1] sage: x,a,b,c = H.gens() sage: B = b.right_multiplication() sage: C = c.right_multiplication() sage: B(a) == a*b True sage: A = a.right_multiplication() sage: BA = A(B) sage: BA(a) == a*a*b True sage: r = H.restriction_maps()[2][1] sage: rB = r(B) sage: r(a)*r(b) == rB(a) True

set_latex_name
(s)¶ Declare how self should be typeset in LaTeX.
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: latex(H.2) b_{1,0} sage: (H.2).set_latex_name('H_2') sage: latex(H.2) H_2

setname
(s, is_polyrep=False)¶ Set the name of
self
.INPUT:
s – a string providing the new 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.2*H.1 sage: C (b_1_0)*(c_2_2): 3Cocycle in H^*(D8; GF(2)) sage: C.setname('foo') sage: C foo: 3Cocycle in H^*(D8; GF(2))

ydeg
()¶ Return the \(y\)degree of
self
.NOTE:
The ydegree plays an important role in the computation of cohomology rings. A generator of a cohomology ring has
ydeg==1
if and only if it is nilpotent.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: print(H) Cohomology ring of Small Group number 3 of order 16 with coefficients in GF(2) <BLANKLINE> Computation complete Minimal list of generators: [b_2_1: 2Cocycle in H^*(SmallGroup(16,3); GF(2)), c_2_2: 2Cocycle in H^*(SmallGroup(16,3); GF(2)), c_2_3: 2Cocycle in H^*(SmallGroup(16,3); GF(2)), a_1_0: 1Cocycle in H^*(SmallGroup(16,3); GF(2)), b_1_1: 1Cocycle in H^*(SmallGroup(16,3); GF(2))] Minimal list of algebraic relations: [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.1.rdeg(),H.1.ydeg() (0, 0) sage: H.2.rdeg(),H.2.ydeg() (1, 0) sage: H.4.rdeg(),H.4.ydeg() (0, 1)

yoneda_cocycle
()¶ Express
self
as a Yoneda cocycle.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: Y21 = H.2.yoneda_cocycle()*H.1.yoneda_cocycle() sage: X21 = (H.2*H.1).yoneda_cocycle() sage: Y21[0] == X21[0] True sage: Y21[1] == X21[1] True sage: Y21[2] == X21[2] True

class
pGroupCohomology.cochain.
COCH_unpickle_class
¶ Unpickling a cochain.
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: C=H.2 sage: type(C) <type 'pGroupCohomology.cochain.COCH'> sage: D = loads(dumps(C)) #indirect doctest sage: print(C) 1Cocycle in H^*(D8; GF(2)), represented by [1 0] rdeg = 0 ydeg = 0 sage: print(D) 1Cocycle in H^*(D8; GF(2)), represented by [1 0] rdeg = 0 ydeg = 0
C
andD
are different objects, but of course their parents are the same, and the cochains are equal:sage: D is C False sage: D.parent() is C.parent() True sage: D == C True

class
pGroupCohomology.cochain.
ChMap
¶ Extension class representing induced homomorphisms of cohomology rings.
EXAMPLES:
Usually, an induced homomorphism is created by defining two groups and a homomorphism between them, computing the cohomology rings of the groups, and then invoking the
hom`()
method of cohomology rings.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, from_scratch=True) sage: H1.make() sage: G2 = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make()
In order to obtain reproducible doc tests, we switch to permutation groups that are, from the perspective of our programs, equivalent to
G1
andG2
, and provide an explicit group isomorphism:sage: phi = libgap.eval('GroupHomomorphismByImages( Group( [ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ] ), Group( [ (1,5)(2,6)(3,8)(4,7), (1,3,2,4)(5,7,6,8) ] ), [ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ], [ (1,7)(2,8)(3,5)(4,6), (1,6)(2,5)(3,7)(4,8) ] )') sage: H1.group()==phi.Source() True sage: H2.group().canonicalIsomorphism(phi.Range()) [ (1,2)(3,8)(4,6)(5,7), (1,3,4,7)(2,5,6,8) ] > [ (1,5)(2,6)(3,8)(4,7), (1,3,2,4)(5,7,6,8) ] 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) #indirect doctest sage: phi_star phi^* sage: phi_star.domain() H^*(DihedralGroup(8); GF(2)) sage: phi_star.codomain() H^*(D8; GF(2)) sage: print([H1.element_as_polynomial(phi_star(X)) for X in H2.gens()]) [1: 0Cocycle in H^*(D8; GF(2)), b_1_0^2+c_2_2: 2Cocycle in H^*(D8; GF(2)), b_1_1+b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_0: 1Cocycle in H^*(D8; GF(2))]
Similarly, we get the induced map of the inverse map:
sage: Src = phi.Source() sage: Rng = phi.Range() sage: Gens = Rng.GeneratorsOfGroup() sage: phi_inv = Rng.GroupHomomorphismByImages(Src, Gens, [phi.PreImagesRepresentative(g) for g in Gens]) sage: phi_star_inv = H1.hom(phi_inv,H2) sage: print([H2.element_as_polynomial(phi_star_inv(X)) for X in H1.gens()]) [1: 0Cocycle in H^*(DihedralGroup(8); GF(2)), b_1_0*b_1_1+c_2_2: 2Cocycle in H^*(DihedralGroup(8); GF(2)), b_1_1: 1Cocycle in H^*(DihedralGroup(8); GF(2)), b_1_1+b_1_0: 1Cocycle in H^*(DihedralGroup(8); GF(2))]
One can compose induced maps by multiplication respectively by applying one map to the other. Here, we test that the composition of the induced map and its inverse is the identity:
sage: [X == phi_star_inv(phi_star(X)) == (phi_star_inv*phi_star)(X) == phi_star_inv(phi_star)(X) for X in H2.gens()] [True, True, True, True] sage: [X == phi_star(phi_star_inv(X)) == (phi_star*phi_star_inv)(X) == phi_star(phi_star_inv)(X) for X in H1.gens()] [True, True, True, True]
It is possible to convert an induced homomorphism into a map of quotient rings in the Singular interface. This allows for working with cohomology ring elements of very high degrees. However, it is always needed to take care of the
basering
in Singular:sage: S_phi_star = singular(phi_star) sage: singular(H2).set_ring() sage: I = singular.ideal(['c_2_2^50','b_1_0^50','b_1_1^50']) sage: singular(H1).set_ring() sage: imI = S_phi_star(I)
Note that Singular does pfte not do automatic reduction in quotient rings. So, eventually we do the reductions explicitly, in two ways, with the same result:
sage: imI.reduce(singular('ideal(0)')) b_1_0^100+c_2_2^2*b_1_0^96+c_2_2^16*b_1_0^68+c_2_2^18*b_1_0^64+c_2_2^32*b_1_0^36+c_2_2^34*b_1_0^32+c_2_2^48*b_1_0^4+c_2_2^50, b_1_1^50+b_1_0^50, b_1_0^50 sage: singular(H2).set_ring() sage: I_red = I.reduce(singular('ideal(0)')) sage: singular(H1).set_ring() sage: S_phi_star(I_red).reduce(singular('ideal(0)')) b_1_0^100+c_2_2^2*b_1_0^96+c_2_2^16*b_1_0^68+c_2_2^18*b_1_0^64+c_2_2^32*b_1_0^36+c_2_2^34*b_1_0^32+c_2_2^48*b_1_0^4+c_2_2^50, b_1_1^50+b_1_0^50, b_1_0^50

G_map
()¶ Return the underlying homomorphism of group algebras (given by a
Matrix_gfpn_dense
matrix).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: G2 = libgap.DihedralGroup(8) sage: H1 = CohomologyRing(8,3) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H1.make() sage: H2.make()
In order to obtain reproducible doc tests, we switch to permutation groups that are, from the perspective of our programs, equivalent to
G1
andG2
, and provide an explicit group isomorphism:sage: phi = libgap.eval('GroupHomomorphismByImages( Group( [ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ] ), Group( [ (1,5)(2,6)(3,8)(4,7), (1,3,2,4)(5,7,6,8) ] ), [ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ], [ (1,7)(2,8)(3,5)(4,6), (1,6)(2,5)(3,7)(4,8) ] )') sage: H1.group()==phi.Source() True sage: H2.group().canonicalIsomorphism(phi.Range()) != libgap.eval('fail') True sage: phi.IsInjective() true sage: phi.IsSurjective() true sage: phi_star = H2.hom(phi,H1) sage: print(phi_star.G_map()) [1 0 0 0 0 0 0 0] [0 1 1 1 1 1 1 1] [0 1 0 0 1 1 0 0] [0 0 0 1 0 0 1 1] [0 0 0 1 1 0 0 1] [0 0 0 0 0 1 1 0] [0 0 0 0 0 1 0 1] [0 0 0 0 0 0 0 1]

apply_to_chain
(d, C)¶ Apply the underlying chain map of
self
to a \(d\)chain.INPUT:
d
, the degree of the chainC
, a \((r\times G)\)Matrix_gfpn_dense
matrix, where \(r\) is the rank of the \(d\)th term of the resolution, and \(G\) is the group order.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: from sage.matrix.matrix_gfpn_dense import Matrix_gfpn_dense as MTX sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: f = H.2.right_multiplication() sage: print(f.apply_to_chain(1, MTX(MatrixSpace(GF(2),2,8, implementation=MTX), [[0,1,0,1,0,1,0,1],[1,0,1,0,1,0,1,0]]))) [0 1 0 1 0 1 0 1]

deg
()¶ Return the degree of
self
.NOTE:
An induced homomorphism always is of degree zero. We provide this method since
ChMap
in principle also works for more general maps so that the image has a different degree from the source.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, from_scratch=True) sage: H1.make() sage: G2 = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make() sage: phi = G1.IsomorphismGroups(G2) sage: phi_star = H2.hom(phi,H1) sage: phi_star.deg() 0

exportData
(f)¶ Store data describing the induced map into files.
INPUT:
f
 a string, providing the path and the beginning of the name of the files into which the terms ofself
shall be savedOUTPUT:
The matrix
self[i]
is saved to the filef+repr(i)
.NOTE:
This method is internally used, in order to save memory by disposing of data that are currently not needed. So, a user would normally not directly invoke the method.
TESTS:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H1 = CohomologyRing(8,3) sage: H1.make() sage: G = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make() 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,7)(2,8)(3,5)(4,6), (1,6)(2,5)(3,7)(4,8) ] )') sage: phi_star = H2.hom(phi,H1) sage: print(phi_star(H2.1)) 2Cocycle in H^*(D8; GF(2)), represented by [1 0 1] sage: print(phi_star.__getitem_name__(1)) [1 0 0 0 0 0 0 0] [1 1 1 1 1 1 0 0] [1 0 0 0 0 0 0 0] [0 0 1 1 0 0 0 0] sage: f = tmp_dir() sage: phi_star.exportData(f) sage: phi_star.__getitem_name__(1) == f+'1' True

kernel
()¶ Compute the kernel.
TEST:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(81,8) sage: H.make() sage: H.restriction_maps()[2][1].kernel() a_1_1, a_2_1, a_2_2, a_3_2, b_4_2a_4_1, a_5_3+a_5_2, b_6_3a_1_0*a_5_2, a_7_5+b_2_0*a_5_2+c_6_4*a_1_0 sage: H.restriction_maps()[2][1]( H('b_6_3a_1_0*a_5_2') ) (b_6_3((a_1_0)*(a_5_2)))_: 6Cocycle in H^*(SmallGroup(9,2); GF(3)) sage: _.MTX() [0 0 0 0 0 0 0]

knownDeg
()¶ Return the degree out to which
self
was constructed.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, from_scratch=True) sage: H1.make() sage: G2 = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make()
In order to obtain reproducible doc tests, we switch to permutation groups that are, from the perspective of our programs, equivalent to
G1
andG2
, and provide an explicit group isomorphism:sage: phi = libgap.eval('GroupHomomorphismByImages( Group( [ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ] ), Group( [ (1,5)(2,6)(3,8)(4,7), (1,3,2,4)(5,7,6,8) ] ), [ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ], [ (1,7)(2,8)(3,5)(4,6), (1,6)(2,5)(3,7)(4,8) ] )') sage: H1.group()==phi.Source() True sage: H2.group().canonicalIsomorphism(phi.Range()) != libgap.eval('fail') True sage: phi.IsInjective() true sage: phi.IsSurjective() true sage: phi_star = H2.hom(phi,H1) sage: phi_star.knownDeg() 0 sage: print(phi_star(H2.1)) 2Cocycle in H^*(D8; GF(2)), represented by [1 0 1] sage: phi_star.knownDeg() 2

label
()¶ Provide a short description of this chain map, using a name when available.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H1 = CohomologyRing(8,3) sage: H1.make() sage: G = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make() 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,7)(2,8)(3,5)(4,6), (1,6)(2,5)(3,7)(4,8) ] )') sage: phi_star = H2.hom(phi,H1) sage: phi_star.label() 'Map H^*(DihedralGroup_8_; GF(2)) > H^*(8gp3; GF(2))' sage: phi_star.set_name('phi^*') sage: phi_star.label() 'phi^*'

lift
()¶ Compute the next unknown term of
self
.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, from_scratch=True) sage: H1.make() sage: G2 = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make()
In order to obtain reproducible doc tests, we switch to permutation groups that are, from the perspective of our programs, equivalent to
G1
andG2
, and provide an explicit group isomorphism:sage: phi = libgap.eval('GroupHomomorphismByImages( Group( [ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ] ), Group( [ (1,5)(2,6)(3,8)(4,7), (1,3,2,4)(5,7,6,8) ] ), [ (1,2)(3,8)(4,6)(5,7), (1,3)(2,5)(4,7)(6,8) ], [ (1,7)(2,8)(3,5)(4,6), (1,6)(2,5)(3,7)(4,8) ] )') sage: H1.group()==phi.Source() True sage: H2.group().canonicalIsomorphism(phi.Range()) != libgap.eval('fail') True sage: phi.IsInjective() true sage: phi.IsSurjective() true sage: phi_star = H2.hom(phi,H1) sage: phi_star.lift() sage: phi_star.knownDeg() 1 sage: phi_star[1] [1 0 0 0 0 0 0 0] [1 1 1 1 1 1 0 0] [1 0 0 0 0 0 0 0] [0 0 1 1 0 0 0 0]

name
()¶ Return the name of
self
.NOTE:
Since induced homomorphisms are cached, there can not be two equal induced homomorphisms with a different name.
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, from_scratch=True) sage: H1.make() sage: G2 = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make() sage: phi = G1.IsomorphismGroups(G2) sage: phi.SetName('phi') sage: phi_star = H2.hom(phi,H1) sage: phi_star.name() 'phi^*'

poincare_of_image
()¶ Poincaré series of the image of
self
(which is a subring of the codomain ofself
).THEORY:
The kernel of self is computed, using Singular. Together with the relation ideal of the domain of self, it allows to compute the Poincaré series of the quotient of the domain by the kernel, which is isomorphic to the image 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()
We study the restriction to one maximal elementary abelian subgroup:
sage: phi = H.restriction_maps()[2][1] sage: phi Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)) sage: [phi.codomain().element_as_polynomial(phi(X)) for X in H.gens()] [1: 0Cocycle in H^*(SmallGroup(4,2); GF(2)), c_1_0*c_1_1+c_1_0^2: 2Cocycle in H^*(SmallGroup(4,2); GF(2)), c_1_1: 1Cocycle in H^*(SmallGroup(4,2); GF(2)), 0: 1Cocycle in H^*(SmallGroup(4,2); GF(2))]
Apparently, the image has dimension one in degree one (given by
c_1_1
) and dimension two in degree two (given byc_1_1^2
andc_1_0*c_1_1+c_1_0^2
). And this can be verified using the Poincaré series of the image:sage: phi.poincare_of_image() 1/(t^3  t^2  t + 1) sage: R.<t> = PowerSeriesRing(QQ) sage: (1/(t^3  t^2  t + 1))[1] 1 sage: (1/(t^3  t^2  t + 1))[2] 2
SEE ALSO:

preimage
(Item=None, Id=None)¶ ASSUMPTION:
self.codomain()
is completely computed.INPUT:
Item
– (optional) element insingular(self.codomain())
 or element of
self.codomain()
.
Id
– (optional) ideal (given by a list of strings) in the codomain, so that lift ofItem
will be done modulo that ideal. Only available ifItem
is not provided as an element ofself.codomain()
but as element in Singular.
OUTPUT:
Return the preimage of
Item
insingular(self.domain())
, ifself.domain()
is completely known, and in the current basering ofself.domain()
otherwise. If
Item
is not provided, the kernel ofself
resp. the preimage of the ideal given byId
is returned as an ideal insingular(self.codomain())
.  If
Item
is a single element andId
isNone
, a representative of the preimage ofItem
is returned, orNone
if there is no preimage.  If
Item
is a single element andId
defines an ideal, a pair is returned, namely one element of the preimage (orNone
, if there is no preimage) and the preimage of the ideal given byId
).
ALGORITHM:
According to chapter 4.3 of [Green].
EXAMPLE:
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: r = H.restriction_maps()[1][1] sage: r Induced homomorphism of degree 0 from H^*(SmallGroup(16,3); GF(2)) to H^*(SmallGroup(4,2); GF(2)) sage: singular(r.codomain()).set_ring() sage: p = singular((r.codomain().1+r.codomain().2)^2); p c_1_1^2+c_1_0^2 sage: I = singular.maxideal(2); I c_1_1^2, c_1_0*c_1_1, c_1_0^2 sage: singular(H).set_ring() sage: r.preimage() a_1_0, b_1_1, b_2_1 sage: r.preimage(p) (c_2_3+c_2_2, a_1_0, b_1_1, b_2_1) sage: r.preimage(Id=I) a_1_0, b_1_1, c_2_2, c_2_3, b_2_1
If both an element and an ideal are provided, one preimage of the preimage of the coset ‘element + ideal’ is returned, together with the preimage of the ideal. Here, the preimage of
p
found above is contained in the preimage of the idealI
:sage: r.preimage(p,Id=I) (0, a_1_0, b_1_1, c_2_2, c_2_3, b_2_1)
We verify these findings. The kernel:
sage: [r(H(t)).as_polynomial() for t in ['a_1_0','b_1_1','b_2_1']] ['0', '0', '0']
The preimage of
I
:sage: [r(H(t)).as_polynomial() for t in ['a_1_0','b_1_1','c_2_2','c_2_3','b_2_1']] ['0', '0', 'c_1_1^2', 'c_1_0^2', '0']
The preimage of
p
:sage: r(H('c_2_3+c_2_2')).as_polynomial() 'c_1_1^2+c_1_0^2'

rank_of_image
(d)¶ Rank of the image of term number \(d\) of
self
.THEORY:
The rank of the image is computed by applying some linear algebra to the
d
th term 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()
We study the restriction to one maximal elementary abelian subgroup:
sage: phi = H.restriction_maps()[2][1] sage: phi Induced homomorphism of degree 0 from H^*(D8; GF(2)) to H^*(SmallGroup(4,2); GF(2)) sage: [phi.codomain().element_as_polynomial(phi(X)) for X in H.gens()] [1: 0Cocycle in H^*(SmallGroup(4,2); GF(2)), c_1_0*c_1_1+c_1_0^2: 2Cocycle in H^*(SmallGroup(4,2); GF(2)), c_1_1: 1Cocycle in H^*(SmallGroup(4,2); GF(2)), 0: 1Cocycle in H^*(SmallGroup(4,2); GF(2))]
Apparently, the image has dimension one in degree one (given by
c_1_1
) and dimension two in degree two (given byc_1_1^2
andc_1_0*c_1_1+c_1_0^2
). And this can be verified using the Poincaré series of the image:sage: phi.rank_of_image(1) 1 sage: phi.rank_of_image(2) 2
SEE ALSO:

set_name
(s)¶ Give
self
a name.NOTE:
Since induced homomorphisms are cached, there can not be two equal induced homomorphisms with a different name. If the
hom()
method is called, the name will be reset.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, from_scratch=True) sage: H1.make() sage: G2 = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make() sage: phi = G1.IsomorphismGroups(G2) sage: phi.SetName('phi') sage: phi_star = H2.hom(phi,H1) sage: phi_star.name() 'phi^*' sage: phi_star.set_name('foobar') sage: phi_star.name() 'foobar' sage: H2.hom(phi,H1).name() 'phi^*' sage: phi_star.name() 'phi^*'

src
()¶ Return the source of the underlying chain map (type
RESL
).NOTE:
Since cohomology is a contravariant functor, the output of
src()
is the resolution of the codomain.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, from_scratch=True) sage: H1.make() sage: G2 = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make() sage: phi = G1.IsomorphismGroups(G2) sage: phi_star = H2.hom(phi,H1) sage: print(phi_star.src()) Resolution: 0 < GF(2) < GF(2)[D8] < rank 2 < rank 3 < rank 4 sage: phi_star.src() is phi_star.codomain().resolution() True

tgt
()¶ Return the codomain of the underlying chain map (type
RESL
).NOTE:
Since cohomology is a contravariant functor, the output of
tgt()
is the resolution of the domain.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, from_scratch=True) sage: H1.make() sage: G2 = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make() sage: phi = G1.IsomorphismGroups(G2) sage: phi_star = H2.hom(phi,H1) sage: print(phi_star.tgt()) Resolution: 0 < GF(2) < GF(2)[DihedralGroup(8)] < rank 2 < rank 3 < rank 4 sage: phi_star.tgt() is phi_star.domain().resolution() True


class
pGroupCohomology.cochain.
ChMap_unpickle_class
¶ Unpickling an instance of
ChMap
, representing an induced homomorphism.EXAMPLES:
Usually, an induced homomorphism is created by defining two groups and a homomorphism between them, computing the cohomology rings of the groups, and then invoking the
hom()
method of cohomology rings.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, from_scratch=True) sage: H1.make() sage: G2 = libgap.DihedralGroup(8) sage: H2 = CohomologyRing(G2, GroupName = 'DihedralGroup(8)', from_scratch=True) sage: H2.make() sage: phi = G1.IsomorphismGroups(G2)
After ensuring that
phi
is printed nicely, we obtain the induced map and see that it is cached:sage: phi.SetName('phi') sage: phi_star = H2.hom(phi,H1) sage: phi_star is loads(dumps(phi_star)) # indirect doctest True

class
pGroupCohomology.cochain.
CohomologyHomset
(X, Y, category=None)¶ Set of Homomorphisms between Modular Cohomology Rings of Finite \(p\)Groups.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace
We consider the dihedral group of order 8 and will study the restriction maps to representatives for all conjugacy classes of nontrivial subgroups.
sage: G = libgap.DihedralGroup(8) sage: H = CohomologyRing(G,GroupName = 'D8', from_scratch=True) sage: H.make() sage: SubG = [X.RepresentativeSmallest() for X in G.ConjugacyClassesSubgroups()] sage: SubG = [X.MinimalGeneratingSet().Group() for X in SubG if X.Order()>1] sage: for i in range(len(SubG)): ....: SubG[i].SetName('U%d'%(i+1)) sage: HSubG = [CohomologyRing(X, from_scratch=True) for X in SubG] sage: for X in HSubG: ....: X.make() sage: IncG = [X.GroupHomomorphismByImages(G,X.GeneratorsOfGroup(),X.GeneratorsOfGroup()) for X in SubG] sage: for i in range(len(IncG)): ....: IncG[i].SetName('i_%d'%(i+1)) sage: ResG = [H.hom(IncG[i], HSubG[i]) for i in range(len(HSubG))] # indirect doctest
Now, we can apply the maps to elements of
H
:sage: ResG[2](H.2+H.3) i_3^*(b_1_0+b_1_1): 1Cocycle in H^*(SmallGroup(2,1); GF(2))
The image of an element of the base field is mapped to itself, while cochains of degree 0 are properly mapped:
sage: ResG[2](H.0) 1 sage: ResG[2](H(1)) i_3^*(1): 0Cocycle in H^*(SmallGroup(2,1); GF(2))
Finally, we show how the images of nonscalar generators of
H
under the various restrictions maps can be expressed as elements of the cohomology rings of the subgroups:sage: for f in ResG: ....: print([f.codomain().element_as_polynomial(f(X)).name() for X in H.gens()[1:]]) ['c_1_0^2', '0', '0'] ['0', 'c_1_0', '0'] ['c_1_0^2', 'c_1_0', 'c_1_0'] ['c_1_1^2+c_1_0*c_1_1', 'c_1_0', '0'] ['c_2_0', '0', 'c_1_0'] ['c_1_1^2+c_1_0*c_1_1+c_1_0^2', 'c_1_1', 'c_1_1'] ['c_2_2', 'b_1_0', 'b_1_1']

class
pGroupCohomology.cochain.
MODCOCH
(parent, value, deg=None, name=None, S=None, rdeg=None, ydeg=None, is_polyrep=False, is_NF=None)¶ Elements of modular cohomology rings of finite groups.
See
pGroupCohomology
orMODCOHO
for examples of cohomology computations.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=2) sage: H.make() sage: H.2 c_1_0: 1Cocycle in H^*(SmallGroup(720,763); GF(2)) sage: print(H('b_3_3*c_3_2+c_2_1^2*c_1_0^2')) #indirect doctest (b_3_3)*(c_3_2)+(((c_2_1)^2)*((c_1_0)^2)): 6Cocycle in H^*(SmallGroup(720,763); GF(2)) defined by b_1_1^4*c_1_2^2+b_1_0^4*c_1_2^2+c_2_5*b_1_0^3*c_1_2+c_2_5^2*b_1_1^2+c_2_5^2*b_1_0*c_1_2+b_1_1^2*c_1_2^4+c_2_5^2*c_1_2^2

as_cocycle_in_subgroup
()¶ Represent
self
as stable cocycle of the chosen subgroup.OUTPUT:
The element (
MODCOCH
) ofself.parent().subgroup_cohomology()
by whichself
is defined.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') # long time sage: H.make() # long time sage: H.subgroup_cohomology() H^*(SmallGroup(192,1493); GF(2)) sage: H.1.as_cocycle_in_subgroup() (b_1_0)^2+(b_2_2)+(b_2_1): 2Cocycle in H^*(SmallGroup(192,1493); GF(2)) sage: H.subgroup_cohomology()('b_1_0^2+b_2_2+b_2_1')*H.2.as_cocycle_in_subgroup() == (H.1*H.2).as_cocycle_in_subgroup() True

as_cocycle_in_sylow
()¶ Represent
self
as stable cocycle of the Sylow subgroup.OUTPUT:
The element (
MODCOCH
) ofself.parent().sylow_cohomology()
that corresponds toself
.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') # long time sage: H.make() # long time sage: H.1.as_cocycle_in_sylow() b_1_1*b_1_2+b_1_1^2+b_1_0^2+b_2_5+b_2_4: 2Cocycle in H^*(SmallGroup(64,138); GF(2)) sage: H.sylow_cohomology()('b_1_1*b_1_2+b_1_1^2+b_1_0^2+b_2_5+b_2_4')*H.2.as_cocycle_in_sylow() == (H.1*H.2).as_cocycle_in_sylow() True

as_polynomial
()¶ Find a polynomial representation of
self
.OUTPUT: A string that defines a polynomial, expressed in the given generator names of the cohomology ring
NOTE: The name of the cohomology ring element will be changed into the polynomial expression.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=2) sage: H.make() sage: c = H.2 sage: c.setname('charly') sage: c charly: 1Cocycle in H^*(SmallGroup(720,763); GF(2)) sage: c.name() 'charly' sage: c.as_polynomial() 'c_1_0' sage: c c_1_0: 1Cocycle in H^*(SmallGroup(720,763); GF(2))

coef
(m)¶ The coefficient of a monomial.
INPUT:
m
: A monomial of the underlying cohomology ring of a subgroup (String or SingularOUTPUT:
self
can be considered as a stable element of the cohomology of a subgroup. Return the coefficient ofm
in the normal form of that stable element.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(400,206,prime=5) sage: H.make() sage: c = H.2*H.3*H.1 sage: print(c) ((c_8_0)*(c_16_1))*(a_6_0): 30Cocycle in H^*(SmallGroup(400,206); GF(5)) defined by c_2_1^3*c_2_2^11*a_1_0*a_1_1c_2_1^11*c_2_2^3*a_1_0*a_1_1
We can use a monomial in the Singular interface
sage: c.coef(c.lm()) 1
or given by a string:
sage: c.coef('c_2_1^11*c_2_2^3*a_1_0*a_1_1') 1

coef_list
(M)¶ Return the list of coefficients.
INPUT:
A list of standard monomials (represented by strings) of the cohomology ring of the underlying subgroup
OUTPUT:
A list of integers, providing the coefficients of the given monomials in the stable element (normal form) that corresponds to
self
.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(400,206,prime=5) sage: H.make() sage: c = H.2*H.3*H.1 sage: print(c) ((c_8_0)*(c_16_1))*(a_6_0): 30Cocycle in H^*(SmallGroup(400,206); GF(5)) defined by c_2_1^3*c_2_2^11*a_1_0*a_1_1c_2_1^11*c_2_2^3*a_1_0*a_1_1
We wish to get the list of coefficients of
c
for all standard monomials of the underlying subgroup:sage: M = H.subgroup_cohomology().standard_monomials(30); M ['c_2_2^14*a_1_0*a_1_1', 'c_2_1*c_2_2^13*a_1_0*a_1_1', 'c_2_1^2*c_2_2^12*a_1_0*a_1_1', 'c_2_1^3*c_2_2^11*a_1_0*a_1_1', 'c_2_1^4*c_2_2^10*a_1_0*a_1_1', 'c_2_1^5*c_2_2^9*a_1_0*a_1_1', 'c_2_1^6*c_2_2^8*a_1_0*a_1_1', 'c_2_1^7*c_2_2^7*a_1_0*a_1_1', 'c_2_1^8*c_2_2^6*a_1_0*a_1_1', 'c_2_1^9*c_2_2^5*a_1_0*a_1_1', 'c_2_1^10*c_2_2^4*a_1_0*a_1_1', 'c_2_1^11*c_2_2^3*a_1_0*a_1_1', 'c_2_1^12*c_2_2^2*a_1_0*a_1_1', 'c_2_1^13*c_2_2*a_1_0*a_1_1', 'c_2_1^14*a_1_0*a_1_1', 'c_2_2^15', 'c_2_1*c_2_2^14', 'c_2_1^2*c_2_2^13', 'c_2_1^3*c_2_2^12', 'c_2_1^4*c_2_2^11', 'c_2_1^5*c_2_2^10', 'c_2_1^6*c_2_2^9', 'c_2_1^7*c_2_2^8', 'c_2_1^8*c_2_2^7', 'c_2_1^9*c_2_2^6', 'c_2_1^10*c_2_2^5', 'c_2_1^11*c_2_2^4', 'c_2_1^12*c_2_2^3', 'c_2_1^13*c_2_2^2', 'c_2_1^14*c_2_2', 'c_2_1^15'] sage: c.coef_list(M) [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

deg
()¶ Degree of a cohomology element.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=2) sage: H.make() sage: H('c_3_2^2+b_3_3*c_3_2+c_2_1*c_1_0*c_3_2').deg() 6
The degree may be explicitly provided in the definition of the cohomology ring element, even if it is not clear from its given value:
sage: from pGroupCohomology.cochain import MODCOCH sage: c = MODCOCH(H, '0', deg=15) sage: c.deg() 15

is_nilpotent
()¶ Tells whether this cocycle is nilpotent.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(60,3,prime=2) sage: H.make() sage: singular(H).set_ring() sage: H.nil_radical() c_1_0 sage: H.gens() [1, c_2_0: 2Cocycle in H^*(SmallGroup(60,3); GF(2)), c_1_0: 1Cocycle in H^*(SmallGroup(60,3); GF(2))] sage: H.gen(1).is_nilpotent() False sage: H.gen(2).is_nilpotent() True sage: bool(H.gen(2)^2) False
An example in odd characteristic:
sage: H = CohomologyRing(1620, 23, prime=3) sage: H.make() sage: H.1.is_nilpotent() True sage: bool(H.1^2) True sage: bool(H.1^3) False sage: H.2.is_nilpotent() False

lc
()¶ Leading coefficient of
self
(type <int>).OUTPUT:
An element of a modular cohomology ring of a finite group is given by a stable element in the cohomology ring of a suitable subgroup. Expressing the stable element as a polynomial, this method returns its leading coefficient, as an int.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(400,206,prime=5) sage: H.make() sage: singular(H.subgroup_cohomology()).set_ring() sage: (H.6*H.8).lc() 2

lm
()¶ Leading monomial (no coefficient) of
self
.OUTPUT:
An element of a modular cohomology ring of a finite group is given by a stable element in the cohomology ring of a suitable subgroup. Expressing the stable element as a polynomial, this method returns its leading monomial, as an element of the Singular interface.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(72,40,prime=3) sage: H.make() sage: singular(H.subgroup_cohomology()).set_ring() sage: H.4.lm() c_2_1*c_2_2^2*a_1_0

lm_string
()¶ Leading monomial (no coefficient) of
self
(type <string>).OUTPUT:
An element of a modular cohomology ring of a finite group is given by a stable element in the cohomology ring of a suitable subgroup. Expressing the stable element as a polynomial, this method returns its leading monomial, as a string.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(72,40,prime=3) sage: H.make() sage: H.4.lm_string() 'c_2_1*c_2_2^2*a_1_0'

lt
()¶ Leading term of the underlying cohomology element.
OUTPUT:
An element of a modular cohomology ring of a finite group is given by a stable element in the cohomology ring of a suitable subgroup. Expressing the stable element as a polynomial, this method returns its leading term (i.e., the product of coefficient and monomial), as an element in the Singular interface.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(400,206,prime=5) sage: H.make() sage: singular(H.subgroup_cohomology()).set_ring() sage: (H.6*H.8).lt() 2*c_2_1^5*c_2_2^5*a_1_0*a_1_1

massey_power
(i=1)¶ Experimental: Restricted Massey power.
ALGORITHM:
A cocycle
C
is expressed as a (stable) element of the cohomology of the Sylow subgroup. The Massey power is computed there (seemassey_power()
).NOTE:
We did not prove that the result always is a stable element. But if it is, it yields the restricted Massey power of
C
. Therefore, this method is merely experimental.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(432,234,prime=3) sage: H.make() sage: c = H.5; c a_3_0: 3Cocycle in H^*(SmallGroup(432,234); GF(3)) sage: cS = c.as_cocycle_in_sylow(); cS b_2_3*a_1_1+b_2_0*a_1_0: 3Cocycle in H^*(E27; GF(3)) sage: cM = c.massey_power(); cM b_4_0*b_4_1+b_4_0^2: 8Cocycle in H^*(SmallGroup(432,234); GF(3)) sage: cSM = cS.massey_power(); cSM <(b_2_3)*(a_1_1)+(b_2_0)*(a_1_0); 1>: 8Cocycle in H^*(E27; GF(3)) sage: cM.as_cocycle_in_sylow() == cSM True

name
()¶ Return the name of the cohomology ring element.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=2) sage: H.make() sage: c = H.2 sage: c.name() 'c_1_0' sage: c.setname('charly') sage: c charly: 1Cocycle in H^*(SmallGroup(720,763); GF(2)) sage: c.name() 'charly' sage: c.as_polynomial() 'c_1_0' sage: c c_1_0: 1Cocycle in H^*(SmallGroup(720,763); GF(2))

nilpotency_degree
()¶ The smallest exponent by which this cocycle becomes zero.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(60,3,prime=2) sage: H.make() sage: singular(H).set_ring() sage: H.nil_radical() c_1_0 sage: H.gens() [1, c_2_0: 2Cocycle in H^*(SmallGroup(60,3); GF(2)), c_1_0: 1Cocycle in H^*(SmallGroup(60,3); GF(2))] sage: H.1.is_nilpotent() False sage: H.1.nilpotency_degree() +Infinity sage: (H.1*0).nilpotency_degree() 1 sage: H.2.is_nilpotent() True sage: bool(H.2^2) False sage: H.2.nilpotency_degree() 2
An example in odd characteristic:
sage: H = CohomologyRing(1620, 23, prime=3) sage: H.make() sage: for g in H.Gen: ....: if g.nilpotency_degree() == 3: ....: break ....: sage: bool(g^2) True sage: bool(g^3) False sage: H.2.is_nilpotent() False sage: H.2.nilpotency_degree() +Infinity sage: (H.2*0).nilpotency_degree() 1

nilreduce
()¶ Inplace reduction of
self
’s value by the ideal generated by nilpotent generators.OUTPUT:
self
. Before, all nilpotent generators of the cohomology containingself.value()
are killed inself.value()
.EXAMPLES:
Since this test relies on the ring presentation of the cohomology of a certain subgroup, we compute it from scratch, rather than relying on potentially outdated data in the local sources.
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: X = CohomologyRing(81,8, from_scratch=True) sage: X.make() sage: H = CohomologyRing(648,132,prime=3, from_scratch=True) sage: H.make() sage: c = copy(H.5) sage: c c_6_0: 6Cocycle in H^*(SmallGroup(648,132); GF(3))
c
is a regular element (marked by the letter ‘c’ in its name). We took a copy of the generator ofH
sincec
will be changed inplace. Interpreted as an element of the cohomology of the underlying subgroup, it has one nilpotent summand:sage: c.as_cocycle_in_subgroup() b_6_3+a_1_0*a_5_2c_6_4: 6Cocycle in H^*(SmallGroup(81,8); GF(3))
We kill this summand:
sage: c.nilreduce() c_6_0: 6Cocycle in H^*(SmallGroup(648,132); GF(3)) sage: c.as_cocycle_in_subgroup() b_6_3c_6_4: 6Cocycle in H^*(SmallGroup(81,8); GF(3))
Indeed, the value of
c
has changed:sage: c == H.5 False

rdeg
()¶ \(r\)degree.
This is supposed to be 1 for Duflot elements, i.e., for those elements that have a nonzero restrictions to the centre of a Sylow subgroup.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=2) sage: H.make() sage: [t.rdeg() for t in H.Gen] [1, 1, 0, 1]
So, the restriction of all but the third generator to the centre of a Sylow subgroup should be nonzero:
sage: r = H.restriction_maps()[1][1] sage: r Induced homomorphism of degree 0 from H^*(SmallGroup(720,763); GF(2)) to H^*(SmallGroup(4,2); GF(2)) sage: print(r(H.1)._NF_()) c_1_1^2: 2Cocycle in H^*(SmallGroup(4,2); GF(2)) defined by c_1_1^2 sage: print(r(H.2)._NF_()) c_1_0: 1Cocycle in H^*(SmallGroup(4,2); GF(2)) defined by c_1_0 sage: print(r(H.3)._NF_()) 0: 3Cocycle in H^*(SmallGroup(4,2); GF(2)) defined by 0 sage: print(r(H.4)._NF_()) c_1_0*c_1_1^2: 3Cocycle in H^*(SmallGroup(4,2); GF(2)) defined by c_1_0*c_1_1^2

set_latex_name
(s)¶ Declare how self should be typeset in LaTeX.
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: latex(H.2) b_{1,0} sage: (H.2).set_latex_name('H_2') sage: latex(H.2) H_2

setname
(s, is_polyrep=False)¶ Set the name of a cohomology ring element.
INPUT:
s
(string), new namme of the elementis_polyrep
(optional boolean, defaultFalse
): IfTrue
, the user asserts that the new name provides a polynomial representation of the element, expressed in the given generator names of the cohomology ring
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=2) sage: H.make() sage: c = H.2 sage: c.setname('charly') sage: c charly: 1Cocycle in H^*(SmallGroup(720,763); GF(2)) sage: c.name() 'charly' sage: c.as_polynomial() 'c_1_0' sage: c c_1_0: 1Cocycle in H^*(SmallGroup(720,763); GF(2))

val_str
()¶ A polynomial representation as stable element.
OUTPUT:
A string that provides a polynomial representation for the cohomology ring element, expressed as a (stable) cocycle of the underlying subgroup.
NOTE:
In general, the normal form is not computed before returning the result.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=2) sage: H.make() sage: (H.1*H.2)._NF_().val_str() 'b_1_1^2*c_1_2+b_1_0^2*c_1_2+c_2_5*b_1_1+b_1_1*c_1_2^2+c_2_5*c_1_2' sage: H.one().val_str() '1'

value
()¶ The value of self in the Singular interface.
NOTE:
By “value”, we mean its representation in the Singular interface as a stable element in the cohomology ring of the chosen subgroup.
This value is not unique, as the cohomology ring of the subgroup is a quotient ring. Thus, the value is a coset representative, and it is not necessarily in normal form.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=2) sage: H.make() sage: singular(H.subgroup_cohomology()).set_ring() sage: (H.1*H.2+H.3)._NF_().value() b_1_1^2*c_1_2+b_1_0^2*c_1_2+c_2_5*b_1_1+c_2_5*b_1_0+b_1_1*c_1_2^2+c_2_5*c_1_2
Note that if Singular crashed, it is attempted to reconstructed the value. However, this is only possible if
val_str()
was called before.sage: c = (H.1*H.2+H.3)._NF_() sage: c.val_str() 'b_1_1^2*c_1_2+b_1_0^2*c_1_2+c_2_5*b_1_1+c_2_5*b_1_0+b_1_1*c_1_2^2+c_2_5*c_1_2' sage: singular.quit() sage: CohomologyRing.global_options('info') sage: c.value() H^*(D8xC2; GF(2)): Reconstructing data in the Singular interface b_1_1^2*c_1_2+b_1_0^2*c_1_2+c_2_5*b_1_1+c_2_5*b_1_0+b_1_1*c_1_2^2+c_2_5*c_1_2 sage: CohomologyRing.global_options('warn')

ydeg
()¶ \(y\)degree.
This is supposed to be 1 for nilpotent elements.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=3) sage: H.make() sage: [t.ydeg() for t in H.Gen] [0, 0, 1, 1]
Indeed, the last two generators are nilpotent:
sage: print(H.3**2) (a_3_0)^2: 6Cocycle in H^*(SmallGroup(720,763); GF(3)) defined by 0 sage: print(H.4**2) (a_7_1)^2: 14Cocycle in H^*(SmallGroup(720,763); GF(3)) defined by 0


pGroupCohomology.cochain.
MODCOCH_unpickle
(L0, L1, L2, L3, L4, L5, L6=False, L7=None)¶ Auxiliary function for unpickling
MODCOCH
.TESTS:
sage: from pGroupCohomology import CohomologyRing sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(720,763,prime=2) sage: H.make() sage: H.1 == loads(dumps(H.1)) #indirect doctest True sage: H.1 is loads(dumps(H.1)) #indirect doctest False

class
pGroupCohomology.cochain.
YCOCH
¶ Yoneda cochains.
This is an auxiliary class to facilitate the computation of Massey products.
A Yoneda \(i\)cochain is a collection of maps from the \((i+n)\)the term to the \(n\)th term of a resolution of a group algebra, \(n=0,1,2,...\). There is no compatibility condition whatsoever (e.g., the maps are not supposed to commute with the boundary maps of the resolution).
Yoneda cochains form a cocomplex, equipped with the coboundary map \(\partial\) defined by \((\partial \phi^i)_n = \phi_n\circ d_{n+i+1}  (1)^i d_{ni+1}\circ \phi_{n+1}^i\) where
 \(P_\ast\) is a resolution
 \(\phi^i\) is a Yoneda \(i\)cochain, \(\phi^i_n: P_{i+n}\to P_n\) for \(n=0,1,2,...\)
 \(\phi_n\\circ d_{n+i+1}\) means \(d_{n+i+1}\) followed by \(\phi_n\).
If \(Y_1,Y_2\) are two Yoneda cochains, then \(Y_1*Y_2\) is their composition, where we use the convention first \(Y_2\) then \(Y_1\).
INPUT:
R
: a resolution (RESL
)n
: the degree of the Yoneda cochain (nonnegative integer)M_0,M_1,...,M_i,...
: a list ofMatrix_gfpn_dense
matrices defining maps from the \((n+i)\)th to the \(i\)th term ofR
.coboundary=None
(optional): If it is given, it must be a Yoneda cocycle that is the coboundary of selfconstruction=None
(optional): If it is given, it is a list describing its construction. Either:['+',Y1,Y2]
(self is sum of Yoneda cochainsY1, Y2
),['',Y1,Y2]
(self isY1Y2
),['',Y]
(self isY
),['*',Y1,Y2]
(self is the composition of two Yoneda cochains,Y2
followed byY1
), or['D',Y]
(self is the coboundary of the Yoneda cochainY
).
NOTE:
The optional parameters are internally used in
coboundary()
,find_cobounding_yoneda_cochains()
and when adding or composing Yoneda cochains. We however document some of the options here.We did not implement comparisons between Yoneda cochains, simply since they morally have infinitely many terms, and if two Yoneda cochains have a different construction, it would thus hardly be possible to prove equality, in general.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: from pGroupCohomology.cochain import YCOCH sage: from sage.matrix.matrix_gfpn_dense import Matrix_gfpn_dense as MTX sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: R = H.resolution() sage: R Resolution of GF(2)[D8] sage: Y = YCOCH(R,1, MTX(MatrixSpace(GF(2),2,8, implementation=MTX), [[1,0,1,0,1,0,1,0],[1,0,1,0,1,0,1,0]])) sage: len(Y) 1
If higher terms of
Y
are required, they are automatically computed. Since no construction and no coboundary was provided in the definition ofY
, it is lifted so that its coboundary is zero.sage: Y[1] [1 0 0 0 0 0 0 0] [0 1 0 0 0 1 0 0] [0 0 0 0 0 0 0 0] [1 0 0 1 0 0 0 0] [0 0 0 0 1 0 0 0] [0 0 0 1 0 1 0 0] sage: len(Y) 2 sage: Y[0] [1 0 1 0 1 0 1 0] [1 0 1 0 1 0 1 0] sage: Y.coboundary()[0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0]
Next, we provide all terms explicitly, yielding a Yoneda cochain that is not a cocycle:
sage: tmpM1 = MTX(MatrixSpace(GF(2),2,8, implementation=MTX), [[1,0,1,0,1,0,1,0],[1,0,1,0,1,0,1,0]]) sage: tmpM2 = MTX(MatrixSpace(GF(2),6,8, implementation=MTX), [[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0],[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0]]) sage: Y = YCOCH(R,1,tmpM1,tmpM2) sage: Y Yoneda 1cochain on a resolution of GF(2)[D8] sage: Y[0] [1 0 1 0 1 0 1 0] [1 0 1 0 1 0 1 0] sage: Y[1] [0 1 1 0 0 1 1 0] [1 1 0 0 1 1 0 0] [1 0 1 0 1 0 1 0] [0 1 1 0 0 1 1 0] [1 1 0 0 1 1 0 0] [1 0 1 0 1 0 1 0] sage: Y.coboundary()[0] [0 1 1 1 0 0 0 1] [0 1 1 1 1 1 1 0] [0 1 1 0 0 0 1 1] sage: Y.coboundary()[1] [0 0 0 0 1 0 0 0] [0 1 0 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 1 0 1 0 0] [0 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]
Of course, the coboundary of the coboundary vanishes:
sage: Y.coboundary().coboundary()[0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] sage: Y.coboundary().coboundary()[1] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0]
Here is what happens internally when defining the composition of
Y
with itself:sage: YY = YCOCH(R, 2, construction=['*',Y,Y]) sage: YY[0] [1 0 0 0 0 0 1 1] [1 1 1 0 1 1 1 1] [0 1 1 0 1 1 0 0] sage: YY[1] [0 1 0 0 0 0 0 0] [0 1 0 0 1 0 0 1] [1 1 1 1 1 1 1 1] [1 0 0 0 1 0 0 0] [0 1 1 1 1 1 0 1] [1 0 0 0 1 1 1 0] [0 1 0 1 0 0 1 0] [1 1 0 1 0 0 1 0]
However, usually one would define the composition like that:
sage: YY = Y*Y sage: YY[0] [1 0 0 0 0 0 1 1] [1 1 1 0 1 1 1 1] [0 1 1 0 1 1 0 0] sage: YY[1] [0 1 0 0 0 0 0 0] [0 1 0 0 1 0 0 1] [1 1 1 1 1 1 1 1] [1 0 0 0 1 0 0 0] [0 1 1 1 1 1 0 1] [1 0 0 0 1 1 1 0] [0 1 0 1 0 0 1 0] [1 1 0 1 0 0 1 0]
Internally, the coboundary of
YY
would be constructed like that:sage: DYY = YCOCH(YY.resolution(), YY.deg()+1, construction=['D',YY]) sage: DYY[0] [0 1 0 0 1 0 0 1] [0 1 0 0 0 1 1 0] [0 0 1 1 1 1 1 1] [0 0 1 1 1 1 0 1] sage: DYY[1] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 1 1 0 0 1 1] [0 0 1 0 0 0 1 0] [0 0 0 1 1 0 1 0] [0 1 1 0 0 1 1 0] [0 1 0 1 0 0 1 0] [0 0 1 1 1 0 1 1] [0 1 0 1 0 0 1 0] [0 0 1 0 1 0 1 1]
Of course, for the user it is easier to just do
sage: DYY = YY.coboundary() sage: DYY[0] [0 1 0 0 1 0 0 1] [0 1 0 0 0 1 1 0] [0 0 1 1 1 1 1 1] [0 0 1 1 1 1 0 1]

append
(M)¶ append further terms to
self
.INPUT:
M
:Matrix_gfpn_dense
matrix defining the next term of selfNOTE:
Actually an immutable copy of
M
is appended.Warning: It is strongly recommended to not use this method manually, as it is not checked whether the appended term fits to the construction of the Yoneda cochain.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: from sage.matrix.matrix_gfpn_dense import Matrix_gfpn_dense as MTX sage: from pGroupCohomology.cochain import YCOCH sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: tmpM1 = MTX(MatrixSpace(GF(2),2,8, implementation=MTX), [[1,0,1,0,1,0,1,0],[1,0,1,0,1,0,1,0]]) sage: tmpM2 = MTX(MatrixSpace(GF(2),6,8, implementation=MTX), [[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0],[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0]]) sage: Y = YCOCH(H.resolution(), 1, tmpM1, tmpM2) sage: M = MTX(MatrixSpace(GF(2),12,8, implementation=MTX), [[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0],[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0],[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0],[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0]]) sage: Y.append(M) sage: Y[2]==M True

coboundary
()¶ Return the Yoneda coboundary of
self
.THEORY:
If \(d_\ast: P_\ast \to P_{\ast1}\) denotes the boundary maps of \(P_\ast\) and \(\phi^i\) is a Yoneda \(i\)cochain with \(\phi^i_n: P_{i+n}\to P_n\) then \((\partial \phi^i)_n = \phi_n\circ d_{n+i+1}  (1)^i d_{ni+1}\circ \phi_{n+1}^i\), which is a Yoneda \((i+1)\)cocycle.
NOTE:
Coboundary and lifting commute, see
lift()
.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: from sage.matrix.matrix_gfpn_dense import Matrix_gfpn_dense as MTX sage: from pGroupCohomology.cochain import YCOCH sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: tmpM1 = MTX(MatrixSpace(GF(2),2,8, implementation=MTX), [[1,0,1,0,1,0,1,0],[1,0,1,0,1,0,1,0]]) sage: tmpM2 = MTX(MatrixSpace(GF(2),6,8, implementation=MTX), [[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0],[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0]]) sage: Y = YCOCH(H.resolution(),1,tmpM1, tmpM2) sage: YC = Y.coboundary() sage: YC Yoneda 2cochain on a resolution of GF(2)[D8] sage: print(YC[0]) [0 1 1 1 0 0 0 1] [0 1 1 1 1 1 1 0] [0 1 1 0 0 0 1 1] sage: print(YC[1]) [0 0 0 0 1 0 0 0] [0 1 0 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 1 0 1 0 0] [0 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] sage: print(YC[2]) [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 1 1 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 1 1 0 0 0 0 0]
The coboundary of the coboundary vanishes:
sage: YCC = YC.coboundary() sage: print(YCC[0]) [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] sage: print(YCC[1]) [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0]

deg
()¶ Return the degree of
self
.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: from pGroupCohomology.cochain import YCOCH sage: from sage.matrix.matrix_gfpn_dense import Matrix_gfpn_dense as MTX sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: Y = YCOCH(H.resolution(),2,H.resolution().CochainToChainmap(2,H.1.MTX())[2]) sage: Y.deg() 2

find_cobounding_yoneda_cochains
(all=True)¶ Construct Yoneda cochains whose coboundary is
self
.ASSUMPTION:
self
is a Yoneda cocycle. Note that this assumption is not verified.OUTPUT:
A list of Yoneda cochains whose coboundary is
self
.If the optional parameter
all
isTrue
(which is default) then a list of Yoneda cochains is returned that are pairwise not cohomologous (i.e., the pairwise difference is not a coboundary). Otherwise, the list will only contain at most one Yoneda cochain.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.gens() [1, c_2_2: 2Cocycle in H^*(D8; GF(2)), b_1_0: 1Cocycle in H^*(D8; GF(2)), b_1_1: 1Cocycle in H^*(D8; GF(2))] sage: H.rels() ['b_1_0*b_1_1'] sage: Y1 = H.2.yoneda_cocycle() sage: Y2 = H.3.yoneda_cocycle() sage: Y12 = Y1*Y2 sage: Y12.find_cobounding_yoneda_cochains() [Yoneda 1cochain on a resolution of GF(2)[D8], Yoneda 1cochain on a resolution of GF(2)[D8], Yoneda 1cochain on a resolution of GF(2)[D8], Yoneda 1cochain on a resolution of GF(2)[D8]] sage: C1, C2, C3, C4 = _
Indeed, the pairwise differences are no coboundaries:
sage: print(C1[0]) [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] sage: print(C2[0]) [1 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] sage: print(C3[0]) [0 0 0 0 0 0 0 0] [1 0 0 0 0 0 0 0] sage: print(C4[0]) [1 0 0 0 0 0 0 0] [1 0 0 0 0 0 0 0]
But the coboundary of
C1,...,C4
isY12
:sage: print(C1.coboundary()[1]) [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 1 0 0 0 0] sage: Y12[1] == C1.coboundary()[1] True sage: Y12[0] == C1.coboundary()[0] True sage: Y12[1] == C1.coboundary()[1] True sage: Y12[2] == C1.coboundary()[2] True sage: Y12[0] == C2.coboundary()[0] True sage: Y12[1] == C2.coboundary()[1] True sage: Y12[2] == C2.coboundary()[2] True sage: Y12[0] == C3.coboundary()[0] True sage: Y12[1] == C3.coboundary()[1] True sage: Y12[2] == C3.coboundary()[2] True sage: Y12[0] == C4.coboundary()[0] True sage: Y12[1] == C4.coboundary()[1] True sage: Y12[2] == C4.coboundary()[2] True

lift
(check=False)¶ Compute the next term of
self
.THEORY:
If the coboundary of self vanishes, then the next term is chosen so that the coboundary still vanishes. In the general case, since the coboundary of a Yoneda cochain is a cocycle, we can lift the coboundary according to the previously stated property. Then, the next term is chosen such that the lift and the coboundary map commute.
EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: from sage.matrix.matrix_gfpn_dense import Matrix_gfpn_dense as MTX sage: from pGroupCohomology.cochain import YCOCH sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: tmpM1 = MTX(MatrixSpace(GF(2),2,8, implementation=MTX), [[1,0,1,0,1,0,1,0],[1,0,1,0,1,0,1,0]]) sage: tmpM2 = MTX(MatrixSpace(GF(2),6,8, implementation=MTX), [[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0],[0,1,1,0,0,1,1,0],[1,1,0,0,1,1,0,0],[1,0,1,0,1,0,1,0]]) sage: Y = YCOCH(H.resolution(), 1, tmpM1, tmpM2) sage: YC = Y.coboundary() sage: len(YC) 1
We compute the third term of
YC
and verify that this is the same as computing the fourth term ofY
and then taking the third term of the coboundary of the extended version ofY
. Note that when asking for a term that has not been computed yet (e.g.,YC[2]
) then lifting is done automatically.sage: print(YC[2]) [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 1 1 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 1 1 0 0 0 0 0] sage: Y.lift() sage: Y.lift() sage: len(Y) 4
Now, as four terms of
Y
are known, the third term of its coboundary is known even without lifting. But it coincides with the third term obtained by liftingYC
:sage: YC[2] == Y.coboundary()[2] True

resolution
()¶ Return the resolution over which
self
is defined.EXAMPLES:
sage: from pGroupCohomology import CohomologyRing sage: from pGroupCohomology.cochain import YCOCH sage: CohomologyRing.doctest_setup() # reset, block web access, use temporary workspace sage: H = CohomologyRing(8,3) sage: H.make() sage: Y = YCOCH(H.resolution(),2,H.resolution().CochainToChainmap(2,H.1.MTX())[2]) sage: print(Y.resolution()) Resolution: 0 < GF(2) < GF(2)[D8] < rank 2 < rank 3 < rank 4