Detecting ring isomorphisms

class pGroupCohomology.isomorphism_test.IsomorphismTest(D, C, use_annihilator=True, use_radical=False, cutoff=15)

An engine to detect graded isomorphisms between cohomology rings by enumeration.

NOTE:

Usually, the isomorphism test engine is only called via is_isomorphic(). However, the direct use of the test engine allows further options.

EXAMPLES:

We give an example of two non-isomorphic groups that have isomorphic cohomology rings:

sage: from pGroupCohomology import CohomologyRing
sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: CohomologyRing.doctest_setup()
sage: H173 = CohomologyRing(64, 173)
sage: H176 = CohomologyRing(64, 176)
sage: H173.make()
sage: H176.make()
sage: CohomologyRing.global_options('info')

We choose a test engine with a cutoff that is too small to detect isomorphy:

sage: T = IsomorphismTest(H176, H173, cutoff=60)
sage: T.explore_isomorphisms()        # long time
IsomorphismTest(H^*(SmallGroup(64,176); GF(2)), H^*(SmallGroup(64,173); GF(2))):
    Trying to find an isomorphism
...
    gen(4) is rigid: b_1_0 --> 1*b_1_0
H^*(SmallGroup(64,173); GF(2)):
    Determine degree 1 standard monomials
    Determine degree 3 standard monomials
    Determine degree 1 standard monomials
IsomorphismTest(H^*(SmallGroup(64,176); GF(2)), H^*(SmallGroup(64,173); GF(2))):
    gen(3) is rigid: a_1_1 --> 1*a_1_1
    1 potential assignments for ['gen(4)', 'gen(3)']
    4 potential assignments for ['gen(4)', 'gen(3)', 'gen(5)']
...
H^*(SmallGroup(64,173); GF(2)):
    Determine degree 2 standard monomials
...
IsomorphismTest(H^*(SmallGroup(64,176); GF(2)), H^*(SmallGroup(64,173); GF(2))):
    Verify if we found an isomorphism
    ... Not a homomorphism
    Verify if we found an isomorphism
...
    0 potential assignments for ['gen(4)', 'gen(3)', 'gen(5)', 'gen(6)', 'gen(1)', 'gen(2)']
    No conclusion on the existence of an isomorphism.

The statistic of criteria used in the process is as follows (sorted in order to have a reproducible test):

sage: sorted(T.statistic.items(), key=repr)
[('Hilbert series of ideals do not match', 129),
 ('isomorphism test', 43200),
 ('nil-deg', 10),
 ('not homomorphism', 43200),
 (('potential isomorphism', 1), 347),
 (('potential isomorphism', 2), 28),
 (('potential isomorphism', 3), 224),
 (('potential isomorphism', 4), 64),
 (('potential isomorphism', 5), 240),
 (('potential isomorphism', 6), 43200)]

So, 43200 possibilites to map the 6 generators have been tested, but none of them resulted in a homomorphism (so, it wasn’t needed to test bijectivity). It would be possible to find an isomorphism using a higher cut-off. However, we show that using an additional criterion (that in some examples would be very difficult to compute) yields the result more easily, as it drastically cuts down the number of generator mappings that potentially could extend to an isomorphism:

sage: T = IsomorphismTest(H176, H173, cutoff=60, use_radical=True)
sage: T.explore_isomorphisms()              # long time
IsomorphismTest(H^*(SmallGroup(64,176); GF(2)), H^*(SmallGroup(64,173); GF(2))):
    Trying to find an isomorphism
H^*(SmallGroup(64,173); GF(2)):
    Determine degree 1 standard monomials
IsomorphismTest(H^*(SmallGroup(64,176); GF(2)), H^*(SmallGroup(64,173); GF(2))):
    gen(4) is rigid: b_1_0 --> 1*b_1_0
H^*(SmallGroup(64,173); GF(2)):
    Determine degree 1 standard monomials
    Determine degree 3 standard monomials
    Determine degree 1 standard monomials
IsomorphismTest(H^*(SmallGroup(64,176); GF(2)), H^*(SmallGroup(64,173); GF(2))):
    gen(3) is rigid: a_1_1 --> 1*a_1_1
    1 potential assignments for ['gen(4)', 'gen(3)']
    4 potential assignments for ['gen(4)', 'gen(3)', 'gen(5)']
    64 potential assignments for ['gen(4)', 'gen(3)', 'gen(5)', 'gen(6)']
...
    240 potential assignments for ['gen(4)', 'gen(3)', 'gen(5)', 'gen(6)', 'gen(1)']
H^*(SmallGroup(64,173); GF(2)):
    Determine degree 4 standard monomials
IsomorphismTest(H^*(SmallGroup(64,176); GF(2)), H^*(SmallGroup(64,173); GF(2))):
    Verify if we found an isomorphism
    ... Not a homomorphism
    Verify if we found an isomorphism
...
    ... Not a homomorphism
    Verify if we found an isomorphism
    Isomorphism found!
('1*c_2_4',
 '1*b_1_2*b_3_6+1*c_4_9+1*c_2_4*b_1_0*b_1_2',
 '1*a_1_1',
 '1*b_1_0',
 '1*b_1_2',
 '1*b_3_6')
sage: sorted(T.statistic.items(), key=repr)
[('Hilbert series of ideals do not match', 171),
 ('Hilbert series of radicals do not match', 286),
 ('isomorphism test', 169),
 ('nil-deg', 10),
 ('not homomorphism', 168),
 (('potential isomorphism', 1), 675),
 (('potential isomorphism', 2), 22),
 (('potential isomorphism', 3), 316),
 (('potential isomorphism', 4), 64),
 (('potential isomorphism', 5), 240),
 (('potential isomorphism', 6), 169)]
candidates_of_gens(Gens, number_of_rigids, allow_cutoff=True)

Return a list of partial mappings of generators of the domain that could potentially extend to an isomorphism.

NOTE:

This method is merely of internal use in explore_isomorphisms().

INPUT:

  • A tuple of numbers, denoting the generators being mapped. Below, we refer to them as “active” generators.
  • The number of generators with a unnique image that have been found so far
  • optional: Whether to allow the list of potential images being cut.

OUTPUT:

A list of tuples defining mappings of the active generators possibly extending to an isomorphism. The length of each tuple coincide with the total number of generators, where in the position of the active generators the possible image is given as string; all other tuple entries are zero.

NOTE:

The number of generators with a unique image is only used for caching. If later more generators with a unique image have been found, it makes sense to revisit the lists of partial assignments, because their length might be drastically reduced when knowing the the unique images of more generators.

EXAMPLES:

sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: from pGroupCohomology import CohomologyRing
sage: CohomologyRing.doctest_setup()
sage: H85 = CohomologyRing(64, 85)
sage: H173 = CohomologyRing(64, 173)
sage: H85.make()
sage: H173.make()
sage: T = IsomorphismTest(H85, H173, cutoff = 10)
sage: T.exhaustive = True
sage: T.not_exhausted_generators = set([])
sage: T.candidates_of_gens((1,),0)
[('1*c_2_4', 0, 0, 0, 0, 0),
 ('1*a_1_1^2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*a_1_1*b_1_2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*a_1_1*b_1_2+1*a_1_1^2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0^2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0^2+1*a_1_1^2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0^2+1*a_1_1*b_1_2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0^2+1*a_1_1*b_1_2+1*a_1_1^2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0*b_1_2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0*b_1_2+1*a_1_1^2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0*b_1_2+1*a_1_1*b_1_2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0*b_1_2+1*a_1_1*b_1_2+1*a_1_1^2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0*b_1_2+1*b_1_0^2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0*b_1_2+1*b_1_0^2+1*a_1_1^2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0*b_1_2+1*b_1_0^2+1*a_1_1*b_1_2+1*c_2_4', 0, 0, 0, 0, 0),
 ('1*b_1_0*b_1_2+1*b_1_0^2+1*a_1_1*b_1_2+1*a_1_1^2+1*c_2_4', 0, 0, 0, 0, 0)]

If too many potential candidates of generator images arise, the list will be cut:

sage: CohomologyRing.global_options('debug')
sage: T.candidates_of_gens((1,2),0)
...
IsomorphismTest(H^*(SmallGroup(64,85); GF(2)), H^*(SmallGroup(64,173); GF(2))):
          cutting list of nonzero elements
          cutting list of candidates
          20 potential assignments for ['gen(1)', 'gen(2)']
[('1*c_2_4', '1*c_4_9', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4^2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*a_1_1^2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*a_1_1^2+1*c_2_4^2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*a_1_1*b_1_2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*a_1_1*b_1_2+1*c_2_4^2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*a_1_1*b_1_2+1*c_2_4*a_1_1^2', 0, 0, 0, 0),
 ('1*c_2_4',
  '1*c_4_9+1*c_2_4*a_1_1*b_1_2+1*c_2_4*a_1_1^2+1*c_2_4^2',
  0,
  0,
  0,
  0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*b_1_0^2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*b_1_0^2+1*c_2_4^2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*b_1_0^2+1*c_2_4*a_1_1^2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*b_1_0^2+1*c_2_4*a_1_1^2+1*c_2_4^2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*b_1_0^2+1*c_2_4*a_1_1*b_1_2', 0, 0, 0, 0),
 ('1*c_2_4',
  '1*c_4_9+1*c_2_4*b_1_0^2+1*c_2_4*a_1_1*b_1_2+1*c_2_4^2',
  0,
  0,
  0,
  0),
 ('1*c_2_4',
  '1*c_4_9+1*c_2_4*b_1_0^2+1*c_2_4*a_1_1*b_1_2+1*c_2_4*a_1_1^2',
  0,
  0,
  0,
  0),
 ('1*c_2_4',
  '1*c_4_9+1*c_2_4*b_1_0^2+1*c_2_4*a_1_1*b_1_2+1*c_2_4*a_1_1^2+1*c_2_4^2',
  0,
  0,
  0,
  0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*b_1_0*b_1_2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*b_1_0*b_1_2+1*c_2_4^2', 0, 0, 0, 0),
 ('1*c_2_4', '1*c_4_9+1*c_2_4*b_1_0*b_1_2+1*c_2_4*a_1_1^2', 0, 0, 0, 0),
 ('1*c_2_4',
  '1*c_4_9+1*c_2_4*b_1_0*b_1_2+1*c_2_4*a_1_1^2+1*c_2_4^2',
  0,
  0,
  0,
  0)]

It can happen that one generator (or a list of generators) cannot be mapped in a way that extends to an isomorphism. This happens, for example, if a generator of the domain in degree \(d\) has a nilpotency degree that doesn’t match the nilpotency degree of any degree-\(d\) element of to codomain. In that case, there cannot be an isomorphism:

sage: T.candidates_of_gens((3,),0)
...
IsomorphismTest(H^*(SmallGroup(64,85); GF(2)), H^*(SmallGroup(64,173); GF(2))):
          test up to 2^3 = 8 elements
          nilpotency degree of '1*a_1_1' doesn't match generator 3
          nilpotency degree of '1*b_1_0' doesn't match generator 3
          nilpotency degree of '1*b_1_0+1*a_1_1' doesn't match generator 3
          nilpotency degree of '1*b_1_2' doesn't match generator 3
          nilpotency degree of '1*b_1_2+1*a_1_1' doesn't match generator 3
          nilpotency degree of '1*b_1_2+1*b_1_0' doesn't match generator 3
          nilpotency degree of '1*b_1_2+1*b_1_0+1*a_1_1' doesn't match generator 3
[]

If one now tries to map another generator, we already know that there cannot be an isomorphism, thus, the answer is immediate:

sage: T.candidates_of_gens((4,),0)
          There cannot be a homomorphism, (gen(3)) cannot be mapped
[]
elements(d)

Iterate over non-zero indecomposable degree-\(d\) elements of the codomain.

INPUT:

\(d\) – the degree

OUTPUT:

Iterator over strings determining indecomposable elements of degree \(d\) of the codomain.

EXAMPLES:

sage: from pGroupCohomology import CohomologyRing
sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: CohomologyRing.doctest_setup()
sage: H1 = CohomologyRing(64,1)
sage: H2 = CohomologyRing(64,2)
sage: T = IsomorphismTest(H1,H2)
sage: list(T.elements(1))
['1*c_1_0', '1*c_1_1', '1*c_1_1+1*c_1_0']
sage: list(T.elements(2))
['1*c_2_1',
 '1*c_2_1+1*c_1_0*c_1_1',
 '1*c_2_2',
 '1*c_2_2+1*c_1_0*c_1_1',
 '1*c_2_2+1*c_2_1',
 '1*c_2_2+1*c_2_1+1*c_1_0*c_1_1']
sage: list(T.elements(3))
[]
explore_isomorphisms()

Enumerate and test potential isomophims.

OUTPUT:

  • A list of generator images (given as strings) of an isomorphism, if an isomorphism was found.
  • None, if no isomorphism was found, but non-isomorphy couldn’t be asserted.
  • False, if the cohomology rings are not isomorphic.

EXAMPLES:

sage: from pGroupCohomology import CohomologyRing
sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: CohomologyRing.doctest_setup()
sage: H156 = CohomologyRing(64,156)
sage: H156.make()
sage: H158 = CohomologyRing(64,158)
sage: H158.make()
sage: T = IsomorphismTest(H156, H158, cutoff = 2)
sage: T.explore_isomorphisms()
('1*a_1_1*a_3_2+1*c_4_4',
 '1*c_4_5+1*c_4_4',
 '1*a_1_0',
 '1*a_1_1',
 '1*a_1_2',
 '1*a_3_2',
 '1*a_3_3')
sage: T = IsomorphismTest(H156, H158, cutoff = 1)
sage: T.explore_isomorphisms()
sage: H85 = CohomologyRing(64, 85)
sage: H173 = CohomologyRing(64, 173)
sage: H85.make()
sage: H173.make()
sage: H85.degvec == H173.degvec
True
sage: H85.poincare_series() == H173.poincare_series()
True
sage: T = IsomorphismTest(H85, H173, cutoff = 10, use_radical = True)
sage: T.explore_isomorphisms()
False
hilbert_of_image()

Hilbert series of the ideal generated by the candidate images.

EXAMPLES:

sage: from pGroupCohomology import CohomologyRing
sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: CohomologyRing.doctest_setup()
sage: H1 = CohomologyRing(27,3)
sage: H1.make()
sage: H2 = CohomologyRing(81,9)
sage: H2.make()
sage: X = IsomorphismTest(H1,H2)
sage: X.set_images(("2*b_2_1+1*b_2_0","2*b_2_3+1*b_2_1",0,0,0,0,0,0,0))
sage: X.hilbert_of_image()
t^20 - 5*t^18 - 2*t^17 + 9*t^16 + 10*t^15 - 4*t^14 - 18*t^13 - 10*t^12 + 10*t^11 + 18*t^10 + 10*t^9 - 10*t^8 - 18*t^7 - 4*t^6 + 10*t^5 + 9*t^4 - 2*t^3 - 5*t^2 + 1
hilbert_of_image_annihilator()

Hilbert series of the annihilator of the ideal generated by the candidate images.

EXAMPLES:

sage: from pGroupCohomology import CohomologyRing
sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: CohomologyRing.doctest_setup()
sage: H1 = CohomologyRing(27,3)
sage: H1.make()
sage: H2 = CohomologyRing(81,9)
sage: H2.make()
sage: X = IsomorphismTest(H1,H2)
sage: X.set_images(("2*b_2_1+1*b_2_0","2*b_2_3+1*b_2_1",0,0,0,0,0,0,0))
sage: X.hilbert_of_image_annihilator()
-t^20 + 3*t^18 + 2*t^17 - t^16 - 6*t^15 - 6*t^14 + 2*t^13 + 8*t^12 + 10*t^11 - 10*t^9 - 8*t^8 - 2*t^7 + 6*t^6 + 6*t^5 + t^4 - 2*t^3 - 3*t^2 + 1
hilbert_of_image_radical()

Hilbert series of the radical of the ideal generated by the candidate images.

EXAMPLES:

sage: from pGroupCohomology import CohomologyRing
sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: CohomologyRing.doctest_setup()
sage: H1 = CohomologyRing(27,3)
sage: H1.make()
sage: H2 = CohomologyRing(81,9)
sage: H2.make()
sage: X = IsomorphismTest(H1,H2)
sage: X.set_images(("2*b_2_1+1*b_2_0","2*b_2_3+1*b_2_1",0,0,0,0,0,0,0))
sage: X.hilbert_of_image_radical()
t^16 - 2*t^15 - 3*t^14 + 6*t^13 + 6*t^12 - 6*t^11 - 13*t^10 + 2*t^9 + 18*t^8 + 2*t^7 - 13*t^6 - 6*t^5 + 6*t^4 + 6*t^3 - 3*t^2 - 2*t + 1
hilbert_of_preimage(Gens)

Hilbert series of the ideal generated by a subset of the ring generators.

INPUT:

A tumple of numbers denoting the generators being chosen.

EXAMPLES:

sage: from pGroupCohomology import CohomologyRing
sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: CohomologyRing.doctest_setup()
sage: H1 = CohomologyRing(27,3)
sage: H1.make()
sage: H2 = CohomologyRing(81,9)
sage: H2.make()
sage: X = IsomorphismTest(H1,H2)
sage: X.hilbert_of_preimage((1,2))
t^19 - 2*t^18 - 3*t^17 + 5*t^16 + 6*t^15 - t^14 - 11*t^13 - 8*t^12 + 8*t^11 + 11*t^10 + 7*t^9 - 6*t^8 - 14*t^7 - 3*t^6 + 7*t^5 + 8*t^4 - t^3 - 5*t^2 + 1

Note that using the Hilbert series of the ideal generated by the second ring generator, one can prove that the two cohomology rings are not isomorphic, although their Poincaré series and generator degrees are equal:

sage: H1.poincare_series() == H2.poincare_series()
True
sage: H1.degvec == H2.degvec
True
sage: for c in X.elements(2):
....:     T = (0,c)+(0,)*7
....:     X.set_images(T)
....:     if X.hilbert_of_preimage((2,)) == X.hilbert_of_image():
....:         print(c)

The point is that no degree-\(2\) element of the codomain generates an ideal with the same Hilbert series as the sedond generator (which also is in degree \(2\)) of the domain.

hilbert_of_preimage_annihilator(Gens)

Hilbert series of the annihilator of the ideal generated by some ring generators of the domain.

EXAMPLES:

sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: from pGroupCohomology import CohomologyRing
sage: CohomologyRing.doctest_setup()
sage: H176 = CohomologyRing(64, 176)
sage: H173 = CohomologyRing(64, 173)
sage: H176.make()
sage: H173.make()
sage: T = IsomorphismTest(H176, H173)
sage: T.set_images((0,0,'a_1_1','b_1_0',0,0))
sage: T.hilbert_of_image_annihilator() == T.hilbert_of_preimage_annihilator((3,4))
True
sage: T.hilbert_of_preimage_annihilator((3,4))
-t^9 + 2*t^8 - t^7 - t^6 + t^5 + t^4 + t^3 - 3*t^2 + 1
hilbert_of_preimage_radical(Gens)

Hilbert series of the radical of the ideal generated by some ring generators of the domain.

EXAMPLES:

sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: from pGroupCohomology import CohomologyRing
sage: CohomologyRing.doctest_setup()
sage: H176 = CohomologyRing(64, 176)
sage: H173 = CohomologyRing(64, 173)
sage: H176.make()
sage: H173.make()
sage: T = IsomorphismTest(H176, H173)
sage: T.set_images((0,0,'a_1_1','b_1_0',0,0))
sage: T.hilbert_of_image_radical() == T.hilbert_of_preimage_radical((3,4))
True
sage: T.set_images(('a_1_1*b_1_2','c_2_4**2','a_1_1','b_1_0',0,0))
sage: T.hilbert_of_image_radical() == T.hilbert_of_preimage_radical((1,2,3,4))
False
is_homomorphism()

Test if the given generator images define a homomorphism.

EXAMPLES:

sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: from pGroupCohomology import CohomologyRing
sage: CohomologyRing.doctest_setup()
sage: H176 = CohomologyRing(64, 176)
sage: H173 = CohomologyRing(64, 173)
sage: H176.make()
sage: H173.make()
sage: T = IsomorphismTest(H176, H173)
sage: T.set_images(('c_2_4', 'b_1_2*b_3_6+1*c_4_9+1*c_2_4*b_1_0*b_1_2', 'a_1_1', 'b_1_0', 'b_1_2', 'b_3_6'))
sage: T.is_homomorphism()
True
sage: T.set_images(('c_2_4', 'b_1_2*b_3_6+1*c_4_9+1*c_2_4*b_1_0*b_1_2', 'a_1_1', 'b_1_2', 'b_1_0', 'b_3_6'))
sage: T.is_homomorphism()
False
is_isomorphism()

Test if the current assignment of generator images gives rise to an isomorphism.

NOTE:

The method uses elimination and may thus be costly. When explore_isomorphisms() is called, it is tried to recognise non-isomorphisms without elimination.

EXAMPLES:

sage: from pGroupCohomology import CohomologyRing
sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: CohomologyRing.doctest_setup()
sage: H156 = CohomologyRing(64,156)
sage: H156.make()
sage: H158 = CohomologyRing(64,158)
sage: H158.make()
sage: T = IsomorphismTest(H156, H158)
sage: T.set_images(('a_1_1*a_3_2+c_4_4', 'c_4_5+c_4_4', 'a_1_0', 'a_1_1', 'a_1_2', 'a_3_2', 'a_3_3'))
sage: CohomologyRing.global_options('debug')
sage: T.is_isomorphism()
...
IsomorphismTest(H^*(SmallGroup(64,156); GF(2)), H^*(SmallGroup(64,158); GF(2))):
          Verify if we found an isomorphism
          ... need elimination...
True
sage: T.set_images(('c_4_4', 'c_4_5+c_4_4', 'a_1_0', 'a_1_1', 'a_1_2', 'a_3_2', 'a_3_3'))
sage: T.is_isomorphism()
          Verify if we found an isomorphism
          ... Not a homomorphism
False
partial_relations(T)

Algebraic relations for a subset of the generators of the domain.

INPUT:

A tuple whose length is the number of generators in positive degree of the domain. The entries are either true or false.

OUTPUT:

An ideal that defines the subring spanned by the denoted generators as a quotient ring.

EXAMPLES:

sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: from pGroupCohomology import CohomologyRing
sage: CohomologyRing.doctest_setup()
sage: H85 = CohomologyRing(64, 85)
sage: H173 = CohomologyRing(64, 173)
sage: H85.make()
sage: H173.make()
sage: T = IsomorphismTest(H85, H173)
sage: T.partial_relations((True,False,True,False,True,False))
a_1_0^2,
a_1_0*b_1_2^2
sage: T._domain.rels()
['a_1_0^2', 'a_1_1^2', 'a_1_0*b_1_2^2', 'a_1_0*a_3_6', 'a_3_6^2']

Note that the computation can be costly, as elimination is involved.

potential_partial_isomorphism(im_gens)

Test if a partial assignment of generator images may extend to an isomorphism.

INPUT:

A list or tuple of generator images, some of them may be zero.

OUTPUT:

The result of some tests telling whether it seems possible to replace the zero assignments to something that yields a ring isomorphism. The specific tests depend on the parameters used to create the test engine.

EXAMPLES:

sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: from pGroupCohomology import CohomologyRing
sage: CohomologyRing.doctest_setup()
sage: H176 = CohomologyRing(64, 176)
sage: H173 = CohomologyRing(64, 173)
sage: H176.make()
sage: H173.make()
sage: T = IsomorphismTest(H176, H173)
sage: T.potential_partial_isomorphism(('c_2_4', 'b_1_2*b_3_6+1*c_4_9+1*c_2_4*b_1_0*b_1_2',0,0,0,0))
True
sage: T.potential_partial_isomorphism(('b_1_2*b_1_0', 'b_1_2*b_3_6+1*c_4_9+1*c_2_4*b_1_0*b_1_2',0,0,0,0))
False

The test engine keeps a statistic on the usage of the method. We see that the method was called twice with potential images of two generators, and see that in one case the Hilbert series of the ideals generated by the generators respectively their images do not match:

sage: sorted(T.statistic.items(), key=repr)
[('Hilbert series of ideals do not match', 1),
 (('potential isomorphism', 2), 2)]
set_images(im_gens)

Map some generators, aiming to test whether that may extend to an isomorphism.

INPUT:

A list of strings or 0, such that the \(i\)-th entry defines the image in the codomain of the \(i\)-th generator of the domain.

OUTPUT:

There is no output, but various attributes of the test engine are redefined.

EXAMPLES:

sage: from pGroupCohomology import CohomologyRing
sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: CohomologyRing.doctest_setup()
sage: H1 = CohomologyRing(27,3)
sage: H1.make()
sage: H2 = CohomologyRing(81,9)
sage: H2.make()
sage: X = IsomorphismTest(H1,H2)
sage: X.set_images(("2*b_2_3+1*b_2_1",0,0,0,0,0,0,0,0))
sage: X.hilbert_of_image()
t^20 - 2*t^19 - 2*t^18 + 2*t^17 + 6*t^16 + 4*t^15 - 10*t^14 - 10*t^13 - t^12 + 12*t^11 + 14*t^10 - 2*t^9 - 11*t^8 - 12*t^7 + 2*t^6 + 10*t^5 + 4*t^4 - 2*t^3 - 4*t^2 + 1
sage: X.set_images(("2*b_2_1+1*b_2_0",0,0,0,0,0,0,0,0))
sage: X.hilbert_of_image()
-t^18 + 4*t^16 + 2*t^15 - 5*t^14 - 8*t^13 - t^12 + 10*t^11 + 9*t^10 - 9*t^8 - 10*t^7 + t^6 + 8*t^5 + 5*t^4 - 2*t^3 - 4*t^2 + 1
unquotiented_domain()

A representation of the domain in Singular, without its quotient relations.

EXAMPLES:

sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: from pGroupCohomology import CohomologyRing
sage: CohomologyRing.doctest_setup()
sage: H85 = CohomologyRing(64, 85)
sage: H173 = CohomologyRing(64, 173)
sage: H85.make()
sage: H173.make()
sage: T = IsomorphismTest(H85, H173)
sage: T.unquotiented_domain
polynomial ring, over a field, global ordering
// coefficients: ZZ/2
// number of vars : 6
//        block   1 : ordering M
//                  : names    c_2_4 c_4_9 a_1_0 a_1_1 b_1_2 a_3_6
//                  : weights      2     4     1     1     1     3
//                  : weights     -1    -1     0     0     0     0
//                  : weights      0     0    -1    -1     0    -1
//                  : weights     -1     0     0     0     0     0
//                  : weights      0     0    -1     0     0     0
//                  : weights      0     0     0    -1     0     0
//        block   2 : ordering C
urbild_GB()

An ideal that allows the computation of preimages of a ring homomorphism.

NOTE:

It requires elimination, thus, can be costly.

EXAMPLES:

sage: from pGroupCohomology.isomorphism_test import IsomorphismTest
sage: from pGroupCohomology import CohomologyRing
sage: CohomologyRing.doctest_setup()
sage: H176 = CohomologyRing(64, 176)
sage: H173 = CohomologyRing(64, 173)
sage: H176.make()
sage: H173.make()
sage: T = IsomorphismTest(H176, H173)
sage: T.set_images(('c_2_4', 'b_1_2*b_3_6+1*c_4_9+1*c_2_4*b_1_0*b_1_2',
....:     'a_1_1', 'b_1_0', 'b_1_2', 'b_3_6'))
sage: T.urbild_GB
@a_1_1+a_1_1,
@b_1_0+b_1_0,
@b_1_2+b_1_2,
@c_2_4+c_2_4,
@b_3_6+b_3_6,
@c_4_9+b_1_2*b_3_6+c_4_9+c_2_4*b_1_0*b_1_2

Since all generators of the codomain occur as leading monomials (with name prepended by “@”), the result shows that we have a surjection.