Elements and maps of cohomology rings

AUTHORS:

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): 2-Cocycle in H^*(D_8; GF(2))
sage: cD2 = HD.1+HD.3^2; cD2
c_2_2+(b_1_1)**2: 2-Cocycle 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): 3-Cocycle in H^*(Sym6; GF(2))
sage: cS2 = HS.1*HS.2+HS.4; cS2
(c_2_1)*(c_1_0)+(b_3_3): 3-Cocycle 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
    1. a \((1 \times d)\) Matrix_gfpn_dense matrix, or

    2. a \(d\)-tuple of integers

    where \(d\) is the projective rank of the \(n\)-th term of the resolution that underlies H

  • ydeg (optional, default None) – y-degree of the cochain

  • rdeg (optional, default None) – r-degree 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: 1-Cocycle in H^*(D8; GF(2))
sage: D
b_1_1: 1-Cocycle in H^*(D8; GF(2))
sage: C+D
b_1_0+b_1_1: 1-Cocycle in H^*(D8; GF(2))
sage: C*D
(b_1_0)*(b_1_1): 2-Cocycle in H^*(D8; GF(2))
sage: print(C^3)
3-Cocycle in H^*(D8; GF(2)),
represented by
[1 0 0 0]
sage: print(D^3)
3-Cocycle in H^*(D8; GF(2)),
represented by
[0 1 0 0]

Next, we show a non-commutative 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: 2-Cocycle  in H^*(E27; GF(3))
sage: print(C)
2-Cocycle 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: 2-Cocycle in H^*(E27; GF(3))
sage: print(C+D)
2-Cocycle in H^*(E27; GF(3)),
represented by
[1 1 1 0]
sage: print(C-D)
2-Cocycle in H^*(E27; GF(3)),
represented by
[1 2 1 1]

Scalar multiplication works as well:

sage: 2*C
2*(first): 2-Cocycle in H^*(E27; GF(3))
sage: print(C*2)
2-Cocycle in H^*(E27; GF(3)),
represented by
[2 0 2 1]

But certainly, in cohomology computations the cup-product is the most interesting:

sage: C*D
(first)*(second): 4-Cocycle 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: 4-Cocycle in H^*(E27; GF(3))
sage: print(E)
4-Cocycle in H^*(E27; GF(3)),
represented by
[2 2 0 1 0 0 2]

Since \(p>2\) in this example, the cohomology ring is non-commutative:

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)
6-Cocycle in H^*(E27; GF(3)),
represented by
[2 1 1 0 0 0 0 0 0]
sage: print(Y*X)
6-Cocycle 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: 4-Cocycle in H^*(E27; GF(3))
MTX(*args, **kwds)

COCH.MTX(self) -> Matrix_gfpn_dense

Return the Matrix_gfpn_dense matrix by which self 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 inplace

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.1*H.2+H.3^3
sage: c
(c_2_2)*(b_1_0)+(b_1_1)**3: 3-Cocycle in H^*(D8; GF(2))
sage: c.setname('foo')
sage: c
foo: 3-Cocycle 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: 3-Cocycle 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 further COCH 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)
3-Cocycle 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, or None 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: 2-Cocycle in H^*(SmallGroup(9,2); GF(3)),
 c_2_2: 2-Cocycle in H^*(SmallGroup(9,2); GF(3)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(9,2); GF(3)),
 a_1_1: 1-Cocycle 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: 2-Cocycle in H^*(SmallGroup(9,2); GF(3))
sage: H.element_as_polynomial(H.4.massey_power())
-c_2_2: 2-Cocycle 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>: 8-Cocycle in H^*(SmallGroup(9,2); GF(3))
sage: H.element_as_polynomial(_)
-c_2_1^4: 8-Cocycle in H^*(SmallGroup(9,2); GF(3))

We now consider a more advanced example, namely the extraspecial 3-group 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 3-fold 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>: 2-Cocycle in H^*(E27; GF(3)),
 <a_1_1; 1>: 2-Cocycle in H^*(E27; GF(3)),
 <a_3_4; 1>: 8-Cocycle in H^*(E27; GF(3)),
 <a_3_5; 1>: 8-Cocycle 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: 2-Cocycle in H^*(E27; GF(3)),
 -b_2_3: 2-Cocycle 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: 8-Cocycle in H^*(E27; GF(3)),
 -b_2_0^3*b_2_2-b_2_0^2*a_1_1*a_3_5-b_2_0^2*a_1_0*a_3_5+b_2_3*c_6_8+b_2_0*c_6_8: 8-Cocycle 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: 3-Cocycle in H^*(E27; GF(3))
sage: U = r1.codomain()
sage: U.element_as_polynomial(r1(C))
0: 3-Cocycle 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: 3-Cocycle 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: 3-Cocycle in H^*(SmallGroup(9,2); GF(3))
sage: U.element_as_polynomial(r4(C))
c_2_2*a_1_1-c_2_2*a_1_0+c_2_1*a_1_1: 3-Cocycle 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: 8-Cocycle in H^*(SmallGroup(9,2); GF(3))
sage: U.element_as_polynomial(r2(CP))
c_2_1*c_2_2^3-c_2_1^3*c_2_2: 8-Cocycle in H^*(SmallGroup(9,2); GF(3))
sage: U.element_as_polynomial(r3(CP))
c_2_1*c_2_2^3-c_2_1^3*c_2_2: 8-Cocycle in H^*(SmallGroup(9,2); GF(3))
sage: U.element_as_polynomial(r4(CP))
-c_2_2^4+c_2_1*c_2_2^3-c_2_1^3*c_2_2: 8-Cocycle 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: 1-Cocycle in H^*(SmallGroup(16,2); GF(2))
sage: d
c_1_1: 1-Cocycle in H^*(SmallGroup(16,2); GF(2))
sage: H.element_as_polynomial(c.massey_power())
0: 2-Cocycle in H^*(SmallGroup(16,2); GF(2))
sage: H.element_as_polynomial(d.massey_power())
0: 2-Cocycle in H^*(SmallGroup(16,2); GF(2))
sage: H.element_as_polynomial(c.massey_power(2))
c_2_1: 2-Cocycle in H^*(SmallGroup(16,2); GF(2))
sage: H.element_as_polynomial(d.massey_power(2))
c_2_2: 2-Cocycle in H^*(SmallGroup(16,2); GF(2))

We verify that the result is consistent with the set-valued non-restricted Massey products:

sage: sorted(list(H.massey_products(c,c,c,c)))
[c_2_1: 2-Cocycle in H^*(SmallGroup(16,2); GF(2)),
 c_2_1+c_1_0*c_1_1: 2-Cocycle in H^*(SmallGroup(16,2); GF(2))]
sage: sorted(list(H.massey_products(d,d,d,d)))
[c_2_2: 2-Cocycle in H^*(SmallGroup(16,2); GF(2)),
 c_2_2+c_1_0*c_1_1: 2-Cocycle 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 further COCH 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)
3-Cocycle 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 non-zero).

OUTPUT:

True if self is a null-cochain, and None otherwise

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: C=2*H.1+H.2
sage: print(C)
2-Cocycle in H^*(E27; GF(3)),
represented by
[2 1 0 0]
sage: C.normalize()
sage: print(C)
2-Cocycle in H^*(E27; GF(3)),
represented by
[1 2 0 0]
sage: C
(2*(b_2_0)+b_2_1)/2: 2-Cocycle in H^*(E27; GF(3))
sage: D = 0*H.2
sage: D.normalize()
True
sage: D
0*(b_2_1): 2-Cocycle in H^*(E27; GF(3))
rdeg()

Return the \(r\)-degree of self.

NOTE:

The r-degree 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 right-multiplication 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: 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]
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): 3-Cocycle in H^*(D8; GF(2))
sage: C.setname('foo')
sage: C
foo: 3-Cocycle in H^*(D8; GF(2))
ydeg()

Return the \(y\)-degree of self.

NOTE:

The y-degree 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: 2-Cocycle in H^*(SmallGroup(16,3); GF(2)),
 c_2_2: 2-Cocycle in H^*(SmallGroup(16,3); GF(2)),
 c_2_3: 2-Cocycle in H^*(SmallGroup(16,3); GF(2)),
 a_1_0: 1-Cocycle in H^*(SmallGroup(16,3); GF(2)),
 b_1_1: 1-Cocycle 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)
1-Cocycle in H^*(D8; GF(2)),
represented by
[1 0]
rdeg = 0
ydeg = 0
sage: print(D)
1-Cocycle in H^*(D8; GF(2)),
represented by
[1 0]
rdeg = 0
ydeg = 0

C and D 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 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,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: 0-Cocycle in H^*(D8; GF(2)), b_1_0^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_0: 1-Cocycle 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: 0-Cocycle in H^*(DihedralGroup(8); GF(2)), b_1_0*b_1_1+c_2_2: 2-Cocycle in H^*(DihedralGroup(8); GF(2)), b_1_1: 1-Cocycle in H^*(DihedralGroup(8); GF(2)), b_1_1+b_1_0: 1-Cocycle 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 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,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 chain

  • C, 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 of self shall be saved

OUTPUT:

The matrix self[i] is saved to the file f+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))
2-Cocycle 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_2-a_4_1,
a_5_3+a_5_2,
b_6_3-a_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_3-a_1_0*a_5_2') )
(b_6_3-((a_1_0)*(a_5_2)))_: 6-Cocycle 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 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,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))
2-Cocycle 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 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,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 sub-ring of the codomain of self).

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: 0-Cocycle in H^*(SmallGroup(4,2); GF(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))]

Apparently, the image has dimension one in degree one (given by c_1_1) and dimension two in degree two (given by c_1_1^2 and c_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:

rank_of_image()

preimage(Item=None, Id=None)

ASSUMPTION:

self.codomain() is completely computed.

INPUT:

  • Item – (optional) element in singular(self.codomain())

    or element of self.codomain().

  • Id – (optional) ideal (given by a list of strings) in the codomain, so that lift of Item will be done modulo that ideal. Only available if Item is not provided as an element of self.codomain() but as element in Singular.

OUTPUT:

Return the preimage of Item in singular(self.domain()), if self.domain() is completely known, and in the current basering of self.domain() otherwise.

  • If Item is not provided, the kernel of self resp. the preimage of the ideal given by Id is returned as an ideal in singular(self.codomain()).

  • If Item is a single element and Id is None, a representative of the preimage of Item is returned, or None if there is no preimage.

  • If Item is a single element and Id defines an ideal, a pair is returned, namely one element of the preimage (or None, if there is no preimage) and the preimage of the ideal given by Id).

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 ideal I:

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: 0-Cocycle in H^*(SmallGroup(4,2); GF(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))]

Apparently, the image has dimension one in degree one (given by c_1_1) and dimension two in degree two (given by c_1_1^2 and c_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:

poincare_of_image()

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 non-trivial 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): 1-Cocycle 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): 0-Cocycle in H^*(SmallGroup(2,1); GF(2))

Finally, we show how the images of non-scalar 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 or MODCOHO 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: 1-Cocycle 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)): 6-Cocycle 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) of self.parent().subgroup_cohomology() by which self 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): 2-Cocycle 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) of self.parent().sylow_cohomology() that corresponds to self.

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: 2-Cocycle 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: 1-Cocycle in H^*(SmallGroup(720,763); GF(2))
sage: c.name()
'charly'
sage: c.as_polynomial()
'c_1_0'
sage: c
c_1_0: 1-Cocycle 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 Singular

OUTPUT:

self can be considered as a stable element of the cohomology of a subgroup. Return the coefficient of m 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): 30-Cocycle in H^*(SmallGroup(400,206); GF(5))
defined by
c_2_1^3*c_2_2^11*a_1_0*a_1_1-c_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): 30-Cocycle in H^*(SmallGroup(400,206); GF(5))
defined by
c_2_1^3*c_2_2^11*a_1_0*a_1_1-c_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: 2-Cocycle in H^*(SmallGroup(60,3); GF(2)),
 c_1_0: 1-Cocycle 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 (see massey_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: 3-Cocycle 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: 3-Cocycle in H^*(E27; GF(3))
sage: cM = c.massey_power(); cM
b_4_0*b_4_1+b_4_0^2: 8-Cocycle 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>: 8-Cocycle 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: 1-Cocycle in H^*(SmallGroup(720,763); GF(2))
sage: c.name()
'charly'
sage: c.as_polynomial()
'c_1_0'
sage: c
c_1_0: 1-Cocycle 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: 2-Cocycle in H^*(SmallGroup(60,3); GF(2)),
 c_1_0: 1-Cocycle 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 containing self.value() are killed in self.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: 6-Cocycle 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 of H since c 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_2-c_6_4: 6-Cocycle in H^*(SmallGroup(81,8); GF(3))

We kill this summand:

sage: c.nilreduce()
c_6_0: 6-Cocycle in H^*(SmallGroup(648,132); GF(3))
sage: c.as_cocycle_in_subgroup()
b_6_3-c_6_4: 6-Cocycle 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 non-zero 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 non-zero:

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: 2-Cocycle in H^*(SmallGroup(4,2); GF(2))
defined by
c_1_1^2
sage: print(r(H.2)._NF_())
c_1_0: 1-Cocycle in H^*(SmallGroup(4,2); GF(2))
defined by
c_1_0
sage: print(r(H.3)._NF_())
0: 3-Cocycle in H^*(SmallGroup(4,2); GF(2))
defined by
0
sage: print(r(H.4)._NF_())
c_1_0*c_1_1^2: 3-Cocycle 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 element

  • is_polyrep (optional boolean, default False): If True, 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: 1-Cocycle in H^*(SmallGroup(720,763); GF(2))
sage: c.name()
'charly'
sage: c.as_polynomial()
'c_1_0'
sage: c
c_1_0: 1-Cocycle 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: 6-Cocycle in H^*(SmallGroup(720,763); GF(3))
defined by
0
sage: print(H.4**2)
(a_7_1)^2: 14-Cocycle 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_{n-i+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 (non-negative integer)

  • M_0,M_1,...,M_i,...: a list of Matrix_gfpn_dense matrices defining maps from the \((n+i)\)-th to the \(i\)-th term of R.

  • coboundary=None (optional): If it is given, it must be a Yoneda cocycle that is the coboundary of self

  • construction=None (optional): If it is given, it is a list describing its construction. Either:

    • ['+',Y1,Y2] (self is sum of Yoneda cochains Y1, Y2),

    • ['-',Y1,Y2] (self is Y1-Y2),

    • ['-',Y] (self is -Y),

    • ['*',Y1,Y2] (self is the composition of two Yoneda cochains, Y2 followed by Y1), or

    • ['D',Y] (self is the coboundary of the Yoneda cochain Y).

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 of Y, 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 1-cochain 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 self

NOTE:

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_{\ast-1}\) 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_{n-i+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 2-cochain 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 is True (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: 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))]
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 1-cochain on a resolution of GF(2)[D8],
 Yoneda 1-cochain on a resolution of GF(2)[D8],
 Yoneda 1-cochain on a resolution of GF(2)[D8],
 Yoneda 1-cochain 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 is Y12:

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 of Y and then taking the third term of the coboundary of the extended version of Y. 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 lifting YC:

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