Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
ee89fe6
wrap_FreeGroup
enriqueartal Jan 16, 2024
5a4dba0
wrap_FpGroup
enriqueartal Jan 20, 2024
11093b4
restore
enriqueartal Jan 20, 2024
8abc7bf
new __reduce__ for free groups
enriqueartal Jan 20, 2024
e041db7
new reduce
enriqueartal Jan 20, 2024
18360f8
doctesting __reduce__
enriqueartal Jan 21, 2024
d08581b
undoing strange changes
enriqueartal Jan 21, 2024
83c7424
lint
enriqueartal Jan 21, 2024
b207835
Merge branch 'sagemath:develop' into groups
enriqueartal Jan 22, 2024
d045124
eliminate wrap_FreeGroup
enriqueartal Jan 26, 2024
d50472c
give up special __reduce__
enriqueartal Jan 26, 2024
7db0b78
sage method for gap f.p. groups
enriqueartal Jan 26, 2024
0999429
less wrap_FpGroup
enriqueartal Jan 26, 2024
566c9e1
no more wrap_FpGroup
enriqueartal Jan 26, 2024
d8c4324
trying...
enriqueartal Jan 28, 2024
1bea861
changing sage method for gap f.p. groups and hom
enriqueartal Jan 28, 2024
d2ffc5c
Update free_group.py
enriqueartal Jan 29, 2024
70f5ea3
Update finitely_presented.py
enriqueartal Jan 29, 2024
2c71529
Update free_group.py
enriqueartal Jan 29, 2024
e9222c4
Added gap groups for free and f.p groups, added __reduce__ methods
enriqueartal Jan 29, 2024
8652315
lint
enriqueartal Jan 29, 2024
2cf0c6b
merge
enriqueartal Jan 29, 2024
b840c35
if the sage and gap generators are permuted, hom are correct
enriqueartal Jan 29, 2024
58f2430
restore
enriqueartal Jan 29, 2024
dcd2113
change order of generators in Alternating groups to match the order i…
enriqueartal Jan 29, 2024
c8fc6c1
private
enriqueartal Jan 31, 2024
47a7f30
.
enriqueartal Jan 31, 2024
eef69e3
.
enriqueartal Jan 31, 2024
d68a8b2
CachedRepresentation
enriqueartal Jan 31, 2024
32dac97
hash
enriqueartal Jan 31, 2024
81f63a1
doctests
enriqueartal Jan 31, 2024
d87dffc
change test in element.pyx
enriqueartal Feb 1, 2024
07517c8
change test in element.pyx
enriqueartal Feb 1, 2024
58c2bc2
add blank line
enriqueartal Feb 1, 2024
7eeba06
first attempt for richcmp
enriqueartal Feb 2, 2024
1cec784
Merge branch 'homgroups' into groups
enriqueartal Feb 2, 2024
eb941f4
Merge branch 'sagemath:develop' into groups
enriqueartal Feb 3, 2024
98f1307
Merge branch 'sagemath:develop' into homgroups
enriqueartal Feb 3, 2024
bc989b3
Merge branch 'groups' into homgroups
enriqueartal Feb 6, 2024
bb26a7b
sage method for free groups and first attempt to richcmp_method
enriqueartal Feb 6, 2024
8d05aa1
change reduce
enriqueartal Feb 6, 2024
336865b
forget richcmp
enriqueartal Feb 6, 2024
f9cd366
traling spaces
enriqueartal Feb 6, 2024
4f4eb8e
delete commented code
enriqueartal Feb 6, 2024
4599efb
warning in doc
enriqueartal Feb 6, 2024
a83319e
delete more commented code
enriqueartal Feb 6, 2024
d300d5f
Merge branch 'sagemath:develop' into groups
enriqueartal Feb 14, 2024
d5ce3df
merge develop
enriqueartal Feb 25, 2024
3cedd7b
Merge branch 'sagemath:develop' into groups
enriqueartal Mar 1, 2024
70b287d
Merge branch 'sagemath:develop' into groups
enriqueartal Mar 5, 2024
f834992
merge
enriqueartal Mar 10, 2024
edffae3
-Change in unique representation to get a better mro
enriqueartal Mar 11, 2024
65ffc52
take out reduce and add UniqueRepresentation
enriqueartal Mar 11, 2024
6562488
lint
enriqueartal Mar 11, 2024
2dfc7e6
more doctests
enriqueartal Mar 13, 2024
c26f2d5
lint
enriqueartal Mar 13, 2024
c5773fd
minor change in one test
enriqueartal Mar 13, 2024
12ea143
Merge branch 'sagemath:develop' into groups
enriqueartal Mar 17, 2024
e16d70d
Merge branch 'sagemath:develop' into groups
enriqueartal Mar 26, 2024
aac514d
merge
enriqueartal Apr 1, 2024
5c39c4e
Merge branch 'sagemath:develop' into groups
enriqueartal Apr 9, 2024
5c3763b
Merge branch 'sagemath:develop' into groups
enriqueartal Apr 13, 2024
435a129
merge 10.4beta4
enriqueartal Apr 27, 2024
4724b6d
deleting problematic backward tests
enriqueartal Apr 29, 2024
ad3cacd
merge
enriqueartal May 3, 2024
15e242a
Merge branch 'sagemath:develop' into groups
enriqueartal May 12, 2024
ccd18ef
Merge branch 'sagemath:develop' into groups
enriqueartal May 25, 2024
da05981
Merge branch 'sagemath:develop' into groups
enriqueartal Jun 2, 2024
962ce4b
Merge branch 'sagemath:develop' into groups
enriqueartal Jun 9, 2024
79b86c3
small changes
enriqueartal Jun 10, 2024
b6d9f7f
tests in richcmp
enriqueartal Jun 10, 2024
8189b8d
merge minor conflicts
enriqueartal Jun 22, 2024
3636ffe
typo
enriqueartal Jun 22, 2024
9f0c918
Merge branch 'sagemath:develop' into groups
enriqueartal Jun 28, 2024
4fae23c
Merge branch 'sagemath:develop' into groups
enriqueartal Jul 5, 2024
7f74a17
change tests due to unique representation change
enriqueartal Jul 10, 2024
cd50bba
Merge branch 'sagemath:develop' into groups
enriqueartal Jul 13, 2024
a48c87c
Merge branch 'sagemath:develop' into groups
enriqueartal Jul 17, 2024
5fdc3a0
Merge branch 'sagemath:develop' into groups
enriqueartal Jul 20, 2024
bb16012
Merge branch 'sagemath:develop' into groups
enriqueartal Jul 25, 2024
3b6fbf0
Merge branch 'sagemath:develop' into groups
enriqueartal Aug 3, 2024
4e0d3b4
Merge branch 'sagemath:develop' into groups
enriqueartal Aug 11, 2024
a0e9a06
Merge branch 'sagemath:develop' into groups
enriqueartal Sep 4, 2024
456c885
Merge branch 'sagemath:develop' into groups
enriqueartal Sep 15, 2024
e7d12f6
Merge branch 'sagemath:develop' into groups
enriqueartal Sep 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/sage/groups/artin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@
# http://www.gnu.org/licenses/
# *****************************************************************************

from sage.misc.cachefunc import cached_method
from sage.groups.free_group import FreeGroup
from sage.groups.finitely_presented import FinitelyPresentedGroup, FinitelyPresentedGroupElement
from sage.combinat.root_system.coxeter_matrix import CoxeterMatrix
from sage.combinat.root_system.coxeter_group import CoxeterGroup
from sage.groups.free_group import FreeGroup
from sage.groups.finitely_presented import FinitelyPresentedGroup, FinitelyPresentedGroupElement
from sage.misc.cachefunc import cached_method
from sage.rings.infinity import Infinity
from sage.structure.richcmp import richcmp, rich_to_bool
from sage.structure.unique_representation import UniqueRepresentation


class ArtinGroupElement(FinitelyPresentedGroupElement):
Expand Down Expand Up @@ -329,7 +330,7 @@ def _left_normal_form_coxeter(self):
return tuple([-delta] + form)


class ArtinGroup(FinitelyPresentedGroup):
class ArtinGroup(UniqueRepresentation, FinitelyPresentedGroup):
r"""
An Artin group.

Expand Down
5 changes: 3 additions & 2 deletions src/sage/groups/cubic_braid.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@
from sage.groups.braid import BraidGroup
from sage.misc.cachefunc import cached_method
from sage.rings.integer import Integer
from sage.structure.unique_representation import UniqueRepresentation


try:
from sage.libs.gap.element import GapElement
Expand Down Expand Up @@ -565,7 +567,7 @@ def conv2domain(laur_pol):
# Class CubicBraidGroup
#
##############################################################################
class CubicBraidGroup(FinitelyPresentedGroup):
class CubicBraidGroup(UniqueRepresentation, FinitelyPresentedGroup):
r"""
Factor groups of the Artin braid group mapping their generators to elements
of order 3.
Expand Down Expand Up @@ -750,7 +752,6 @@ def __init__(self, names, cbg_type=None):
n = Integer(len(names))
if n < 1:
raise ValueError("the number of strands must be an integer larger than one")

if cbg_type is None:
cbg_type = CubicBraidGroup.type.Coxeter
if not isinstance(cbg_type, CubicBraidGroup.type):
Expand Down
206 changes: 109 additions & 97 deletions src/sage/groups/finitely_presented.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@

from sage.arith.misc import GCD as gcd
from sage.categories.morphism import SetMorphism
from sage.functions.generalized import sign
from sage.groups.free_group import FreeGroup
from sage.groups.free_group import FreeGroupElement
from sage.groups.group import Group
Expand All @@ -143,7 +142,8 @@
from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing
from sage.rings.rational_field import QQ
from sage.sets.set import Set
from sage.structure.unique_representation import UniqueRepresentation
from sage.structure.richcmp import richcmp, richcmp_method
from sage.structure.unique_representation import CachedRepresentation


class GroupMorphismWithGensImages(SetMorphism):
Expand Down Expand Up @@ -362,51 +362,7 @@ def __call__(self, *values, **kwds):
return super().__call__(values)


def wrap_FpGroup(libgap_fpgroup):
"""
Wrap a GAP finitely presented group.

This function changes the comparison method of
``libgap_free_group`` to comparison by Python ``id``. If you want
to put the LibGAP free group into a container ``(set, dict)`` then you
should understand the implications of
:meth:`~sage.libs.gap.element.GapElement._set_compare_by_id`. To
be safe, it is recommended that you just work with the resulting
Sage :class:`FinitelyPresentedGroup`.

INPUT:

- ``libgap_fpgroup`` -- a LibGAP finitely presented group

OUTPUT: a Sage :class:`FinitelyPresentedGroup`

EXAMPLES:

First construct a LibGAP finitely presented group::

sage: F = libgap.FreeGroup(['a', 'b'])
sage: a_cubed = F.GeneratorsOfGroup()[0] ^ 3
sage: P = F / libgap([ a_cubed ]); P
<fp group of size infinity on the generators [ a, b ]>
sage: type(P)
<class 'sage.libs.gap.element.GapElement'>

Now wrap it::

sage: from sage.groups.finitely_presented import wrap_FpGroup
sage: wrap_FpGroup(P)
Finitely presented group < a, b | a^3 >
"""
assert libgap_fpgroup.IsFpGroup()
libgap_fpgroup._set_compare_by_id()
from sage.groups.free_group import wrap_FreeGroup
free_group = wrap_FreeGroup(libgap_fpgroup.FreeGroupOfFpGroup())
relations = tuple(free_group(rel.UnderlyingElement())
for rel in libgap_fpgroup.RelatorsOfFpGroup())
return FinitelyPresentedGroup(free_group, relations)


class RewritingSystem:
class RewritingSystem():
"""
A class that wraps GAP's rewriting systems.

Expand Down Expand Up @@ -730,7 +686,8 @@ def make_confluent(self):
raise ValueError('could not make the system confluent')


class FinitelyPresentedGroup(GroupMixinLibGAP, UniqueRepresentation, Group, ParentLibGAP):
@richcmp_method
class FinitelyPresentedGroup(GroupMixinLibGAP, CachedRepresentation, Group, ParentLibGAP):
"""
A class that wraps GAP's Finitely Presented Groups.

Expand All @@ -739,7 +696,9 @@ class FinitelyPresentedGroup(GroupMixinLibGAP, UniqueRepresentation, Group, Pare
You should use
:meth:`~sage.groups.free_group.FreeGroup_class.quotient` to
construct finitely presented groups as quotients of free
groups.
groups. Any class inheriting this one should define
``__reduce__ = CachedRepresentation.__reduce__``
after importing ``CachedRepresentation``.

EXAMPLES::

Expand Down Expand Up @@ -770,7 +729,7 @@ class FinitelyPresentedGroup(GroupMixinLibGAP, UniqueRepresentation, Group, Pare
"""
Element = FinitelyPresentedGroupElement

def __init__(self, free_group, relations, category=None):
def __init__(self, free_group, relations, category=None, libgap_fpgroup=None):
"""
The Python constructor.

Expand All @@ -786,6 +745,25 @@ def __init__(self, free_group, relations, category=None):
sage: J is H
True

sage: A5 = libgap(AlternatingGroup(5))
sage: A5gapfp = A5.IsomorphismFpGroup().Range()
sage: A5gapfp
<fp group of size 60 on the generators [ A_5.1, A_5.2 ]>
sage: A5sage = A5gapfp.sage(); A5sage;
Finitely presented group < A_5.1, A_5.2 | A_5.1^5*A_5.2^-5, A_5.1^5*(A_5.2^-1*A_5.1^-1)^2, (A_5.1^-2*A_5.2^2)^2 >
sage: A5sage.inject_variables()
Traceback (most recent call last):
...
ValueError: variable names have not yet been set using self._assign_names(...)

Check that pickling works::

sage: G = FreeGroup(2) / [2 * (1, 2, -1, -2)]
sage: loads(dumps(G))
Finitely presented group < x0, x1 | (x0*x1*x0^-1*x1^-1)^2 >
sage: G.__reduce__()[1][1]
(Free Group on generators {x0, x1}, ((x0*x1*x0^-1*x1^-1)^2,))

sage: TestSuite(H).run()
sage: TestSuite(J).run()
"""
Expand All @@ -794,11 +772,47 @@ def __init__(self, free_group, relations, category=None):
assert isinstance(relations, tuple)
self._free_group = free_group
self._relations = relations
self._assign_names(free_group.variable_names())
parent_gap = free_group.gap() / libgap([rel.gap() for rel in relations])
ParentLibGAP.__init__(self, parent_gap)
try:
self._assign_names(free_group.variable_names())
except ValueError:
pass
if libgap_fpgroup is None:
libgap_fpgroup = free_group.gap() / libgap([rel.gap() for rel in relations])
ParentLibGAP.__init__(self, libgap_fpgroup)
Group.__init__(self, category=category)

def __hash__(self):
"""
Make hashable.

EXAMPLES::

sage: G = FreeGroup(2) / [(1, 2, 2, 1)]
sage: G.__hash__() == hash((G.free_group(), G.relations()))
True
"""
return hash((self._free_group, self._relations))

def __richcmp__(self, other, op):
"""
Rich comparison of ``self`` and ``other``.

EXAMPLES::

sage: G1 = FreeGroup(2) / [(1, 2, 2, 1, 2, 1)]
sage: G2 = libgap(G1).sage()
sage: G1 == G2
True
sage: G1 is G2
False
"""
if not isinstance(other, self.__class__):
from sage.structure.richcmp import op_NE
return (op == op_NE)
self_data = (self._free_group, self._relations)
other_data = (other._free_group, other._relations)
return richcmp(self_data, other_data, op)

def _repr_(self) -> str:
"""
Return a string representation.
Expand All @@ -812,7 +826,7 @@ def _repr_(self) -> str:
sage: H._repr_()
'Finitely presented group < a, b | a, b^3 >'
"""
gens = ', '.join(self.variable_names())
gens = ', '.join(self._free_group._gen_names)
rels = ', '.join(str(r) for r in self.relations())
return 'Finitely presented group ' + '< ' + gens + ' | ' + rels + ' >'

Expand Down Expand Up @@ -1357,15 +1371,15 @@ def abelianization_map(self):
hom_ab_fp = ab_libgap.IsomorphismFpGroup()
ab_libgap_fp = hom_ab_fp.Range()
hom_simply = ab_libgap_fp.IsomorphismSimplifiedFpGroup()
ab = wrap_FpGroup(hom_simply.Range())
ab = hom_simply.Range().sage()
images = []
for f in self.gens():
f0 = hom_ab_libgap.Image(f)
f1 = hom_ab_fp.Image(f0)
f2 = hom_simply.Image(f1)
L = f2.UnderlyingElement().LetterRepAssocWord()
images.append(ab([int(j) for j in L]))
return self.hom(codomain=ab, im_gens=images)
return self.hom(codomain=ab, im_gens=images, check=False)

@cached_method
def abelianization_to_algebra(self, ring=QQ):
Expand Down Expand Up @@ -1438,12 +1452,9 @@ def simplification_isomorphism(self):
sage: H = G / [a*b*c, a*b^2, c*b/c^2]
sage: I = H.simplification_isomorphism()
sage: I
Generic morphism:
Group morphism:
From: Finitely presented group < a, b, c | a*b*c, a*b^2, c*b*c^-2 >
To: Finitely presented group < b | >
Defn: a |--> b^-2
b |--> b
c |--> b
sage: I(a)
b^-2
sage: I(b)
Expand All @@ -1455,21 +1466,26 @@ def simplification_isomorphism(self):

sage: F = FreeGroup(1)
sage: G = F.quotient([F.0])
sage: G.simplification_isomorphism()
Generic morphism:
sage: h = G.simplification_isomorphism(); h
Group morphism:
From: Finitely presented group < x | x >
To: Finitely presented group < | >
Defn: x |--> 1
sage: h(G.gen(0))
1

ALGORITHM:

Uses GAP.
"""
II = self.gap().IsomorphismSimplifiedFpGroup()
codomain = wrap_FpGroup(II.Range())
phi = lambda x: codomain(II.ImageElm(x.gap()))
HS = self.Hom(codomain)
return GroupMorphismWithGensImages(HS, phi)
cod = II.Range().sage()
phi = [cod(II.ImageElm(x)) for x in self.gap().GeneratorsOfGroup()]
return self.hom(codomain=cod, im_gens=phi, check=False)
# II = self.gap().IsomorphismSimplifiedFpGroup()
# codomain = II.Range().sage()
# phi = lambda x: codomain(II.ImageElm(x.gap()))
# HS = self.Hom(codomain)
# return GroupMorphismWithGensImages(HS, phi)

def simplified(self):
"""
Expand Down Expand Up @@ -1543,48 +1559,44 @@ def epimorphisms(self, H):
sage: F = FreeGroup(3)
sage: G = F / [F([1, 2, 3, 1, 2, 3]), F([1, 1, 1])]
sage: H = AlternatingGroup(3)
sage: G.epimorphisms(H)
[Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >
To: Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> ()
x1 |--> (1,3,2)
x2 |--> (1,2,3),
Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >
To: Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> (1,3,2)
x1 |--> ()
x2 |--> (1,2,3),
Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >
To: Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> (1,3,2)
x1 |--> (1,2,3)
x2 |--> (),
Generic morphism:
From: Finitely presented group < x0, x1, x2 | x0*x1*x2*x0*x1*x2, x0^3 >
To: Alternating group of order 3!/2 as a permutation group
Defn: x0 |--> (1,2,3)
x1 |--> (1,2,3)
x2 |--> (1,2,3)]
sage: for quo in G.epimorphisms(H):
....: for a in G.gens():
....: print(a, "|-->", quo(a))
....: print("-----")
x0 |--> ()
x1 |--> (1,3,2)
x2 |--> (1,2,3)
-----
x0 |--> (1,3,2)
x1 |--> ()
x2 |--> (1,2,3)
-----
x0 |--> (1,3,2)
x1 |--> (1,2,3)
x2 |--> ()
-----
x0 |--> (1,2,3)
x1 |--> (1,2,3)
x2 |--> (1,2,3)
-----

ALGORITHM:

Uses libgap's GQuotients function.
"""
from sage.misc.misc_c import prod
HomSpace = self.Hom(H)
# from sage.misc.misc_c import prod
# HomSpace = self.Hom(H)
Gg = libgap(self)
Hg = libgap(H)
gquotients = Gg.GQuotients(Hg)
res = []
# the following closure is needed to attach a specific value of quo to
# each function in the different morphisms
fmap = lambda tup: (lambda a: H(prod(tup[abs(i)-1]**sign(i) for i in a.Tietze())))
# fmap = lambda tup: (lambda a: H(prod(tup[abs(i)-1]**sign(i) for i in a.Tietze())))
for quo in gquotients:
tup = tuple(H(quo.ImageElm(i.gap()).sage()) for i in self.gens())
fhom = GroupMorphismWithGensImages(HomSpace, fmap(tup))
# tup = tuple(H(quo.ImageElm(i.gap()).sage()) for i in self.gens())
# fhom = GroupMorphismWithGensImages(HomSpace, fmap(tup))
fhom = self.hom(codomain=H, im_gens=[H(quo.ImageElm(a.gap())) for a in self.gens()])
res.append(fhom)
return res

Expand Down
Loading
Loading