From 756a7bbdf4d86553a99b298cfa11933c0ca8f423 Mon Sep 17 00:00:00 2001 From: Sebastian Oehms Date: Sat, 16 Feb 2019 09:27:50 +0100 Subject: [PATCH 01/10] 27302: initial version --- src/doc/en/reference/groups/index.rst | 1 + src/doc/en/reference/references/index.rst | 6 + src/sage/groups/all.py | 3 + src/sage/groups/cubic_braid.py | 1867 +++++++++++++++++++++ 4 files changed, 1877 insertions(+) create mode 100644 src/sage/groups/cubic_braid.py diff --git a/src/doc/en/reference/groups/index.rst b/src/doc/en/reference/groups/index.rst index f9ff8ba9d09..29dc5ef8ff0 100644 --- a/src/doc/en/reference/groups/index.rst +++ b/src/doc/en/reference/groups/index.rst @@ -17,6 +17,7 @@ Groups sage/groups/finitely_presented sage/groups/finitely_presented_named sage/groups/braid + sage/groups/cubic_braid sage/groups/indexed_free_group sage/groups/raag sage/groups/group_exp diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 08bbff33178..219d21ff2c9 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -160,6 +160,9 @@ REFERENCES: multipartitions*. Osaka J. Math. **38** (2001), 827–837. :mathscinet:`MR1864465` +.. [Ass1978] \J. Assion: *Einige endliche Faktorgruppen der Zopfgruppen*, Math. Z., 163 + (1978), 291-302. + .. [AS-Bessel] \F. W. J. Olver: 9. Bessel Functions of Integer Order, in Abramowitz and Stegun: Handbook of Mathematical Functions. http://people.math.sfu.ca/~cbm/aands/page_355.htm @@ -890,6 +893,9 @@ REFERENCES: .. [Con2015] Keith Conrad: *Tensor products*, `http://www.math.uconn.edu/~kconrad/blurbs/ `_ +.. [Cox1957] \H. S. M. Coxeter: *Factor groups of the braid groups*, Proceedings of the Fourth Candian + Mathematical Congress (Vancover 1957), pp. 95-122. + .. [CP2001] John Crisp and Luis Paris. *The solution to a conjecture of Tits on the subgroup generated by the squares of the generators of an Artin group*. Invent. Math. **145** diff --git a/src/sage/groups/all.py b/src/sage/groups/all.py index 8ac4072e670..350305ab8b0 100644 --- a/src/sage/groups/all.py +++ b/src/sage/groups/all.py @@ -27,6 +27,9 @@ lazy_import('sage.groups.free_group', 'FreeGroup') lazy_import('sage.groups.braid', 'BraidGroup') +lazy_import('sage.groups.cubic_braid', 'CubicBraidGroup') +lazy_import('sage.groups.cubic_braid', 'AssionGroupU') +lazy_import('sage.groups.cubic_braid', 'AssionGroupS') lazy_import('sage.groups.affine_gps.affine_group', 'AffineGroup') lazy_import('sage.groups.affine_gps.euclidean_group', 'EuclideanGroup') diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py new file mode 100644 index 00000000000..d9249958644 --- /dev/null +++ b/src/sage/groups/cubic_braid.py @@ -0,0 +1,1867 @@ +# -*- coding: utf-8 -*- +r""" +Cubic Braid Groups + +This module is devoted to factor groups of the Artin braid groups, such +that the images `s_i` of the braid generators have order three: + +.. MATH:: + + s_i^3 = 1 + +In general these groups have firstly been investigated by Coxeter, H.S.M. +in: "Factor groups of the braid groups, Proceedings of the Fourth Canadian +Mathematical Congress (Vancover 1957), pp. 95-122". + +Coxeter showed, that these groups are finite as long as the number of +strands is less than 6 and infinite elsewise. More explicitely the factor +group on three strand braids is isomorphic to `SL(2,3)`, on four strand +braids to `GU(3,2)` and on five strand braids to `Sp(4,3) \times C_3`. +Today, these finite groups are known as irreducible complex reflection groups +enumerated in the Shephard-Todd classification as `G_{4}`, `G_{25}` and +`G_{32}`. + +Coxeter realized these groups as subgroups of unitary groups with respect +to a certain hermitian form over the complex numbers (in fact over `\QQ` +adjoined with a primitive 12-th root of unity). + +In "Einige endliche Faktorgruppen der Zopfgruppen" (Math. Z., 163 (1978), +291-302) J. Assion considered two series `S(m)` and `U(m)` of finite +factors of these groups. The additional relations on the braid group +generators `\{ s_1, \cdot , s_{m-1}\}` are + +.. MATH:: + + \begin{array}{lll} + \mbox{S:} & s_3 s_1 t_2 s_1 t_2^{-1} t_3 t_2 s_1 t_2^{-1} t_3^{-1} = 1 + & \mbox{ for } m >= 5 \mbox{ in case } S(m)\\ + \mbox{U:} & t_1 t_3 = 1 + & \mbox{ for } m >= 5 \mbox{ in case } U(m) + \end{array} + +where `t_i = (s_i s_{i+1})^3`. He showed that each series of finite cubic +braid group factors must be an epimorphic image of one of his two series, +as long as the groups with less than 5 strands are the full cubic braid +groups, whereas the group on 5 strands is not. He realized the groups `S(m)` +as symplectic groups over `GF(3)` (resp. subgroups therein) and `U(m)` as +general unitary groups over `GF(4)` (resp. subgroups therein). + +This class implements all the groups considered by Coxeter and Assion as +finitely presented groups together with the classical realizations given +by the authors. It also contains the conversion maps between the two ways +of realization. In addition the user can construct other realizations and +maps to matrix groups with help of the burau representation. In case gap3 +and CHEVIE are installed the reflection groups (via the gap3 interface) +are availlable, too. The methods for all this functionality are +:meth:`as_classical_group`, :meth:`as_matrix_group`, :meth:`as_permutatopn_group` +and :meth:`as_reflection_group`. + + +REFERENCES: + +- [Cox1957]_ +- [Ass1978]_ + +AUTHORS: + +- Sebastian Oehms 2019-02-16, initial version. +""" + + + + + + + + + +# **************************************************************************** +# Copyright (C) 2019 Sebastian Oehms +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +# **************************************************************************** + + + +from sage.rings.integer import Integer +from sage.groups.free_group import FreeGroup +from sage.groups.finitely_presented import FinitelyPresentedGroup, FinitelyPresentedGroupElement +from sage.groups.braid import BraidGroup +from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField +from sage.rings.number_field.number_field import CyclotomicField +from sage.rings.finite_rings.finite_field_constructor import GF +from enum import Enum + + +############################################################################## +# +# Enum for the type of the group +# +############################################################################## + +class CubicBraidGroupType(Enum): + r""" + Enum class to select the type of the group: + + - ``Coxeter`` -- 'C' the full cubic braid group. + - ``AssionS`` -- 'S' finite factor group of type S considered by Assion. + - ``AssionU`` -- 'U' finite factor group of type U considered by Assion. + """ + Coxeter = 'C' + AssionS = 'S' + AssionU = 'U' + + + + +############################################################################## +# +# Functions to create Instances of the CubicBraidGroup_class +# +############################################################################## +def CubicBraidGroup(n=None, names='c', cbg_type=CubicBraidGroupType.Coxeter): + r""" + Constructs cubic braid groups as instance of :class:`CubicBraidGroup_class`. + + INPUT: + + - ``n`` -- integer or ``None`` (default). The number of + strands. If not specified the ``names`` are counted and the + group is assumed to have one more strand than generators. + + - ``names`` -- string or list/tuple/iterable of strings (default: + ``'c'``). The generator names or name prefix. + + - ``cbg_type`` -- (optional keyword, default = CubicBraidGroupType.Coxeter) + is passed to the corresponding keyword argument of the constructor of + :class:`CubicBraidGroup_class`. + + EXAMPLES:: + + sage: C3 = CubicBraidGroup(3); C3.generators() + (c0, c1) + sage: CubicBraidGroup(3, 'g').generators() + (g0, g1) + sage: from sage.groups.cubic_braid import CubicBraidGroupType + sage: U3.=CubicBraidGroup(3, cbg_type=CubicBraidGroupType.AssionU); U3.generators() + (u1, u2) + """ + # this code is adapted from :func:`BraidGroup` + # Support Freegroup('a,b') syntax + if n is not None: + try: + n = Integer(n)-1 + except TypeError: + names = n + + n = None + # derive n from counting names + if n is None: + import six + if isinstance(names, six.string_types): + n = len(names.split(',')) + else: + names = list(names) + n = len(names) + try: + from sage.structure.category_object import normalize_names + except: + from sage.structure.parent import normalize_names + names = tuple(normalize_names(n, names)) + return CubicBraidGroup_class(names, cbg_type=cbg_type) + + +# ---------------------------------------------------------------------------------- +# Short-Hands for AssionsGroups: +# ---------------------------------------------------------------------------------- + +def AssionGroupS(n=None, names='s'): + r""" + Constructs cubic braid groups as instance of :class:`CubicBraidGroup_class` which + have been investigated by J.Assion using the notation S(m). This function is a short + hand cut for :func:`CubicBraidGroup` setting ``cbg_type=CubicBraidGroupType.AssionS`` + and default ``names='s'``. + + For more information type ``CubicBraidGroup_class?`` + + INPUT: + + - ``n`` -- integer or None (default). The number of strands. This argument is passed + to the corresponding argument of :func:`CubicBraidGroup`. + + - ``names`` -- string or list/tuple/iterable of strings (default:'s'). This argument is + passed to the corresponding argument of :func:`CubicBraidGroup`. + + EXAMPLES:: + + sage: S3 = AssionGroupS(3); S3 + Assion group on 3 strands of type S + sage: from sage.groups.cubic_braid import CubicBraidGroupType + sage: S3x = CubicBraidGroup(3, names='s', cbg_type=CubicBraidGroupType.AssionS); S3x + Assion group on 3 strands of type S + sage: S3 == S3x + True + """ + return CubicBraidGroup(n = n, names = names, cbg_type=CubicBraidGroupType.AssionS) + + +def AssionGroupU(n=None, names='u'): + r""" + Constructs cubic braid groups as instance of :class:`CubicBraidGroup_class` which + have been investigated by J.Assion using the notation U(m). This function is a short + hand cut for :func:`CubicBraidGroup` setting ``cbg_type=CubicBraidGroupType.AssionU`` + and default ``names='u'``. + + For more information type ``CubicBraidGroup_class?`` + + INPUT: + + - ``n`` -- integer or None (default). The number of strands. This argument is passed + to the corresponding argument of :func:`CubicBraidGroup`. + + - ``names`` -- string or list/tuple/iterable of strings (default:'u'). This argument is + passed to the corresponding argument of :func:`CubicBraidGroup`. + + EXAMPLES:: + + sage: U3 = AssionGroupU(3); U3 + Assion group on 3 strands of type U + sage: from sage.groups.cubic_braid import CubicBraidGroupType + sage: U3x = CubicBraidGroup(3, names='u', cbg_type=CubicBraidGroupType.AssionU); U3x + Assion group on 3 strands of type U + sage: U3 == U3x + True + + """ + return CubicBraidGroup(n = n, names = names, cbg_type=CubicBraidGroupType.AssionU) + + + + + + + +############################################################################## +# +# Class CubicBraidElement (for elements) +# +############################################################################## + +class CubicBraidElement(FinitelyPresentedGroupElement): + r""" + This class models elements of cubic factor groups of the braid group. + It is the element class of the CubicBraidGroup_class. + + For more information see the documentation of the parent + :class:`CubicBraidGroup_class`. + + EXAMPLES:: + + sage: C4. = CubicBraidGroup(4); C4 + Cubic Braid group on 4 strands + sage: ele1 = c1*c2*c3^-1*c2^-1 + sage: ele2 = C4((1, 2, -3, -2)) + sage: ele1 == ele2 + True + """ + + + + def braid(self): + r""" + Return the canonical braid preimage of ``self`` as Object of the + class :class:`Braid`. + + OUTPUT: + + The preimage of ``self`` as instance of :class:`Braid`. + + EXAMPLES:: + + sage: C3. = CubicBraidGroup(3) + sage: c1.parent() + Cubic Braid group on 3 strands + sage: c1.braid().parent() + Braid group on 3 strands + """ + + braid_group = self.parent().braid_group() + return braid_group(self) + + + + def burau_matrix(self, rootBur = None, Domain = None, characteristic = None, var='t', reduced=False): + r""" + Return the Burau matrix of the cubic braid coset. + + This method uses the same method belonging to :class:`Braid`, but + reduces the indeterminant to a primitive sixth (resp. twelfth in case + reduced='unitary') root of unity. + + INPUT (all arguments are optional keywords): + + - ``rootBur`` -- six (resp. twelfth) root of unity in some field + (default root of unity over `\QQ`). + - ``Domain`` -- base_ring for the burau matrix (default is Cyclotomic + Field of order 3 and degree 2, resp. the domain of `rootBur` if given). + - ``characteristic`` - integer giving the characteristic of the + domain (default is 0 or the characteristic of `Domain` if given). + - ``var`` -- string used for the indeterminant name in case rootBur + must be constructed in a splitting field. + - ``reduced`` -- boolean (default: ``False``) or string; for more + information see the documentation of :meth:`burau_matrix` of + :class:`Braid`. + + OUTPUT: + + The Burau matrix of the cubic braid coset with entries in the + domain given by the options. In case the option `reduced='unitary'` + is given a triple consisting of the burau matrix, its adjoined and + the hermitain form is returned. + + EXAMPLES:: + + sage: C3. = CubicBraidGroup(3) + sage: ele = c1*c2*c1 + sage: BuMa = ele.burau_matrix(); BuMa + [ -zeta3 1 zeta3] + [ -zeta3 zeta3 + 1 0] + [ 1 0 0] + sage: BuMa.base_ring() + Cyclotomic Field of order 3 and degree 2 + sage: BuMa == ele.burau_matrix(characteristic = 0) + True + sage: BuMa = ele.burau_matrix(Domain=QQ); BuMa + [-t + 1 1 t - 1] + [-t + 1 t 0] + [ 1 0 0] + sage: BuMa.base_ring() + Number Field in t with defining polynomial t^2 - t + 1 + sage: BuMa = ele.burau_matrix(Domain = QQ[I, sqrt(3)]); BuMa + [ 1/2*sqrt3*I + 1/2 1 -1/2*sqrt3*I - 1/2] + [ 1/2*sqrt3*I + 1/2 -1/2*sqrt3*I + 1/2 0] + [ 1 0 0] + sage: BuMa.base_ring() + Number Field in I with defining polynomial x^2 + 1 over its base field + sage: BuMa = ele.burau_matrix(characteristic=7); BuMa + [3 1 4] + [3 5 0] + [1 0 0] + sage: BuMa.base_ring() + Finite Field of size 7 + sage: BuMa = ele.burau_matrix(characteristic=2); BuMa + [t + 1 1 t + 1] + [t + 1 t 0] + [ 1 0 0] + sage: BuMa.base_ring() + Finite Field in t of size 2^2 + sage: F4. = GF(4) + sage: BuMa = ele.burau_matrix(rootBur=r64); BuMa + [r64 + 1 1 r64 + 1] + [r64 + 1 r64 0] + [ 1 0 0] + sage: BuMa.base_ring() + Finite Field in r64 of size 2^2 + sage: BuMa = ele.burau_matrix(Domain=GF(5)); BuMa + [2*t + 2 1 3*t + 3] + [2*t + 2 3*t + 4 0] + [ 1 0 0] + sage: BuMa.base_ring() + Finite Field in t of size 5^2 + sage: BuMa, BuMaAd, H = ele.burau_matrix(reduced='unitary'); BuMa + [ 0 zeta12^3] + [zeta12^3 0] + sage: BuMa * H * BuMaAd == H + True + sage: BuMa.base_ring() + Cyclotomic Field of order 12 and degree 4 + sage: BuMa, BuMaAd, H = ele.burau_matrix(Domain = QQ[I, sqrt(3)], reduced='unitary'); BuMa + [0 I] + [I 0] + sage: BuMa.base_ring() + Number Field in I with defining polynomial x^2 + 1 over its base field + """ + braid = self.braid() + + unitary = False + minPolRootBurCf = [1 , -1 , 1] # minimal polynomial of sixth root of unity + if type(reduced) == str: + if reduced == 'unitary': + unitary = True + minPolRootBurCf = [1 , 0 , -1 , 0 , 1] # minimal polynomial of twelfth root of unity + + BurauOri = braid.burau_matrix(reduced=reduced) + + if unitary: + BurauOri, BurauOriAdj, HermFormOri = BurauOri + + if Domain != None: + if isinstance(Domain, UniversalCyclotomicField): + if rootBur is None: + if unitary: + rootBur = Domain.gen(12) + else: + rootBur = Domain.gen(6) + + if rootBur is None: + def find_root(domain): + minPolRootBur = domain[var](minPolRootBurCf) + rootList = minPolRootBur.roots() + if len(rootList) == 0: + Domain = minPolRootBur.splitting_field(minPolRootBur.variable_name()) + minPolRootBur = Domain[var](minPolRootBurCf) + else: + Domain = domain + rootList = minPolRootBur.roots() + for root in rootList: + if root[0] == 0: + continue + rootBur = root[0] + if root[1] == 1: + break + return rootBur + + if Domain is None: + if (characteristic is None): + characteristic = 0 + try: + characteristic = Integer(characteristic) + except ValueError: + raise ValueError('characteristic must be in integer') + + if characteristic <> 0 and not characteristic.is_prime(): + raise ValueError('characteristic must be a prime') + if characteristic == 0: + if unitary: + domain = CyclotomicField(12) + else: + domain = CyclotomicField(3) + else: + domain = GF(characteristic) + rootBur = find_root(domain) + Domain = rootBur.parent() + + else: # Domain <> None + if characteristic is None: + characteristic = Domain.characteristic() + elif characteristic <> Domain.characteristic(): + raise ValueError('characteristic of Domain does not match given characteristic') + rootBur = find_root(Domain) + + else: # rootBur <> None + if Domain is None: + Domain = rootBur.parent() + if characteristic is None: + characteristic = Domain.characteristic() + elif characteristic <> Domain.characteristic(): + raise ValueError('characteristic of Domain does not match given characteristic') + + if 1 not in Domain: + raise ValueError('rootBur must belong to a domain containing 1') + if unitary: + if Domain(rootBur**4 -rootBur**2 +1) != 0: + raise ValueError('rootBur must vanish on x**4-x**2+1') + else: + if Domain(rootBur**2 -rootBur +1) != 0: + raise ValueError('rootBur must vanish on x**2-x+1') + + def conv2Domain (LaurPol): + l1, l2 = LaurPol.polynomial_construction() + R = Domain['tt']; (tt,) = R._first_ngens(1) + p1 = R(l1) + p2 = rootBur**(l2) + res = p1.substitute(tt=rootBur) * p2 + return res + + from sage.matrix.constructor import matrix + + d1, d2 = BurauOri.dimensions() + BurauMat = matrix(d1, d2, lambda i,j: conv2Domain(BurauOri[i,j])) + + if unitary: + BurauMatAdj = matrix(d1, d2, lambda i,j: conv2Domain(BurauOriAdj[i,j])) + HermForm = matrix(d1, d2, lambda i,j: conv2Domain(HermFormOri[i,j])) + return BurauMat, BurauMatAdj, HermForm + + return BurauMat + + + + + +############################################################################## +# +# Class CubicBraidGroup_class +# +############################################################################## +class CubicBraidGroup_class(FinitelyPresentedGroup): + r""" + This class implements factor groups of the Artin braid group mapping + their generators to elements of order 3 (see the module header for more + informations on these groups). + + These groups are implemented as a particular case of finitely presented + groups similar to the :class:`BraidGroup_class`. + + A cubic braid group can be created by giving the number of strands, and + the name of the generators in a similar way as it works for the + :class:`BraidGroup_class`. + + INPUT (to the constructor): + + - ``names`` -- (see the documentation of :class:`BraidGroup_class`). + + - ``cbg_type`` -- (keyword, explanation see below). + + + Setting the keyword ``cbg_type`` to one on the values ``CubicBraidGroupType.AssionS`` + or ``CubicBraidGroupType.AssionU`` the additional relations due to Assion are added: + + .. MATH:: + + \begin{array}{lll} + \mbox{S:} & s_3 s_1 t_2 s_1 t_2^{-1} t_3 t_2 s_1 t_2^{-1} t_3^{-1} = 1 + & \mbox{ for } m >= 5 \mbox{ in case } S(m)\\ + \mbox{U:} & t_1 t_3 = 1 + & \mbox{ for } m >= 5 \mbox{ in case } U(m) + \end{array} + + where `t_i = (s_i s_{i+1})^3`. If ``cbg_type == CubicBraidGroupType.Coxeter`` (default) + only the cubic relation on the generators is active (Coxeters case of investigation). + Note that for `n = 2, 3, 4` the groups do not differ between the three possible + values of cbg_type (as finitely presented groups). But anyway, the instances for + ``CubicBraidGroupType.Coxeter, CubicBraidGroupType.AssionS`` and ``CubicBraidGroupType.AssionU`` + are different, since they have different classical realizations implemented. + + The creation of instances of this class can also be done more easily by help + of :func:`CubicBraidGroup`, :func:`AssionGroupS` and :func:`AssionGroupU` + (similar to :func:`BraidGroup` with respect to :class:`BraidGroup_class`). + + + EXAMPLES:: + + sage: from sage.groups.cubic_braid import CubicBraidGroupType + sage: U3 = CubicBraidGroup(3, cbg_type=CubicBraidGroupType.AssionU); U3 + Assion group on 3 strands of type U + sage: U3.gens() + (c0, c1) + + alternative possibilities defining U3:: + + sage: U3 = AssionGroupU(3); U3 + Assion group on 3 strands of type U + sage: U3.gens() + (u0, u1) + sage: U3. = AssionGroupU(3); U3 + Assion group on 3 strands of type U + sage: U3.gens() + (u1, u2) + + alternates naming the generators:: + + sage: U3 = AssionGroupU(3, 'a, b'); U3 + Assion group on 3 strands of type U + sage: U3.gens() + (a, b) + sage: C3 = CubicBraidGroup(3, 't'); C3 + Cubic Braid group on 3 strands + sage: C3.gens() + (t0, t1) + sage: U3.is_isomorphic(C3) + #I Forcing finiteness test + True + sage: U3.as_classical_group() + Subgroup of (The projective general unitary group of degree 3 over Finite Field of size 2) generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] + sage: C3.as_classical_group() + Subgroup of General Unitary Group of degree 2 over Universal Cyclotomic Field with respect to hermitian form + [-E(12)^7 + E(12)^11 -1] + [ -1 -E(12)^7 + E(12)^11] with 2 generators ( + [ E(3)^2 0] [ 1 -E(12)^7] + [-E(12)^7 1], [ 0 E(3)^2] + ) + + TESTS: + + sage: C3 = CubicBraidGroup(3) + sage: TestSuite(C3).run() + sage: C4 = CubicBraidGroup(4) + sage: TestSuite(C4).run() # long time + sage: C6 = CubicBraidGroup(6) + sage: TestSuite(C6).run() # long time + sage: S3 = AssionGroupS(3) + sage: TestSuite(S3).run() + sage: S5 = AssionGroupS(5) + sage: TestSuite(S5).run() # long time + sage: U3 = AssionGroupU(3) + sage: TestSuite(U3).run() + sage: U4 = AssionGroupU(4) + sage: TestSuite(U4).run() # long time + sage: U5 = AssionGroupU(5) + sage: TestSuite(U5).run() # long time + + + REFERENCES: + + - [Cox1957]_ + - [Ass1978]_ + """ + + + + Element = CubicBraidElement + + ########################################################################################### + # private methods + ########################################################################################### + def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): + """ + Python constructor. + """ + n = Integer(len(names)) + if n < 1: + raise ValueError("the number of strands must be an integer larger than one") + + free_group = FreeGroup(names) + self._cbg_type = cbg_type + self._nstrands = n+1 + self._ident = self._cbg_type.value + self._nstrands.str() + self._braid_group = BraidGroup(names) + + # internal naming of elements for convinience + b = [free_group([i]) for i in range(1 , n+1)] + t = [free_group([i, i+1])**3 for i in range(1 , n)] + ti = [free_group([-i, -i-1])**3 for i in range(1 , n)] + + # first the braid relation + rels = list(self._braid_group.relations()) + + # than the cubic relation + for i in range(0, n): + rels.append(b[i]**3) + + # than Assions relation Satz 2.2 for cbg_type=CubicBraidGroupType.AssionS + # and Satz 2.4 for cbg_type=CubicBraidGroupType.AssionU + if n > 3: + for i in range(0, n-3): + if cbg_type == CubicBraidGroupType.AssionU: + rels.append((t[i]*t[i+2])**3) + elif cbg_type == CubicBraidGroupType.AssionS: + rels.append(b[i+2]*b[i]*t[i+1]*b[i]*ti[i+1]*t[i+2]*t[i+1]*b[i]*ti[i+1]*ti[i+2]) + + + FinitelyPresentedGroup.__init__(self, free_group, tuple(rels)) + self._free_group = free_group + + # ------------------------------------------------------------------------------------------------ + # the following global pointers to classical group realizations will be set in the private method + # _create_classical_realization + # ------------------------------------------------------------------------------------------------ + self._classical_group = None # This is the classical Group returned by as_classical_group + self._classical_base_group = None # this only differs for special cases for AssionGroup from the former + self._classical_invariant_form = None # invariant form of the classical base group + self._classical_embedding = None # if self._classical_group different from self._classical_base_group + self._centralizing_matrix = None # for AssionGroup: element in classical base group commuting with self + self._centralizing_element = None # image under nat. map of the former one in the proj. classical group + return + + + + + + + + def _repr_(self): + r""" + Return a string representation. + + OUTPUT: + + String describing ``self``. + """ + if self._cbg_type == CubicBraidGroupType.Coxeter: + return "Cubic Braid group on %s strands"%(self.strands()) + else: + return "Assion group on %s strands of type %s"%(self.strands() ,self._cbg_type.value) + + + + # ------------------------------------------------------------------------------- + # Methods for test_suite + # ------------------------------------------------------------------------------- + def _internal_test_attached_group(self, AttGroup, tester): + r""" + It tests conversion maps from ``self`` to the given attached Group + which must have been defined using the :meth:`as_classical_group`, + :meth:`as_matrix_group`, meth:`as_permutation_group` or + :meth:`as_reflection_group`. + + INPUT: + + - ``AttGroup`` -- attached group to be tested as specified above. + """ + elem = self.an_element() + AttElem = AttGroup(elem) + if self.is_finite() and self.strands() <= 7: # not realistic for larger number of strands + AttElemBack= self(AttElem) + tester.assert_(AttElemBack == elem) + return + + + def _test_classical_group(self, **options): + r""" + Method called by TestSuite. + + The following is checked: + - construction of classical group was faithfull. + - coercion maps to and from classical group exist and are inverse to each other. + """ + tester = self._tester(**options) + Cl = self.as_classical_group() + if self.is_finite(): + self._internal_test_attached_group(Cl, tester) + return + + + def _test_permutation_group(self, **options): + r""" + Method called by TestSuite. + + The following is checked: + - construction of permutation group was faithfull. + - coercion maps to and from permutation group exist and are inverse to each other. + """ + if self.is_finite(): + tester = self._tester(**options) + Perm = self.as_permutation_group() + self._internal_test_attached_group(Perm, tester) + return + + + def _test_matrix_group(self, **options): + r""" + Method called by TestSuite. + + The following is checked: + - construction of matrix group was faithfull in several cases. + - coercion maps to and from matrix group exist. + """ + tester = self._tester(**options) + F3 = GF(3); r63 = F3(2); F4 = GF(4); r64 = F4.gen() + MatDEF = self.as_matrix_group() + self._internal_test_attached_group(MatDEF, tester) + + if self._cbg_type != CubicBraidGroupType.AssionU or self.strands() < 5 : # not well defined elsewise + MatF3 = self.as_matrix_group(rootBur=r63) + self._internal_test_attached_group(MatF3, tester) + + if self._cbg_type != CubicBraidGroupType.AssionS or self.strands() < 5 : # not well defined elsewise + MatF4 = self.as_matrix_group(rootBur=r64) + self._internal_test_attached_group(MatF4, tester) + + if self.strands() < 5 or self._cbg_type == CubicBraidGroupType.Coxeter: + MatF5 = self.as_matrix_group(characteristic=5) + self._internal_test_attached_group(MatF5, tester) + + MatF7 = self.as_matrix_group(Domain=GF(7)) + self._internal_test_attached_group(MatF7, tester) + return + + + def _test_reflection_group(self, **options): + r""" + Method called by TestSuite. + + The following is checked: + - construction of reflection group was faithfull. + - coercion maps to and from reflection group exist and are inverse to each other. + """ + if self._cbg_type == CubicBraidGroupType.Coxeter and self.is_finite() and self.strands() > 2: + from sage.combinat.root_system.reflection_group_real import is_chevie_available + if is_chevie_available(): + tester = self._tester(**options) + Refl = self.as_reflection_group() + self._internal_test_attached_group(Refl, tester) + return + + + # ------------------------------------------------------------------------------- + # ------------------------------------------------------------------------------- + # local utility-methods + # ------------------------------------------------------------------------------- + # ------------------------------------------------------------------------------- + + def _create_classical_realization(self, just_embedded=False): + r""" + Internal method to create the classical groups attached to ``self``. + + This methods sets the following attributes of ``self``: + + - self._classical_group This is the classical group returned by as_classical_group method. + - self._classical_base_group this only differs in special cases for AssionGroup from the former. + - self._classical_invariant_form invariant form of the classical base group. + - self._centralizing_matrix for AssionGroup: element in classical base group commuting with self. + - self._centralizing_element image under natural map of the former one in the projective classical group. + - self._classical_embedding as subgroup of classical base group (if different from classical group). + """ + + # ------------------------------------------------------------------------------- + # Set up all incrediences of the classical Assion group (generic part) + # ------------------------------------------------------------------------------- + def set_classical_realization(self, BaseGroup, ProjGroup, centralizing_matrix, transvec_matrices): + r""" + Internal method to create classical group for Assion groups. + + This is a local function of :meth:`_create_classical_realization`. + + It handels the common part of symplectic and unitary version and creates conversion maps. + + INPUT: + + - ``BaseGroup`` -- The symplectic or unitary groups Sp(m,3) resp. GU(m,2). + - ``ProjGroup`` -- The corresponding projeective group of BaseGroup. + - ``centralizing_matrix`` -- The centralizing matrix according to Assion. + - ``transvec_matrices`` -- List of transvection matrices according to Assion. + + OUTPUT: + + No output, but the function sets the attributes of ``self`` decribed above. + """ + centralizing_element = None + + # ------------------------------------------------------------------------------ + # Setting the List of Braid Images + # ------------------------------------------------------------------------------ + im_gens = [BaseGroup(m) for m in transvec_matrices] + + # ------------------------------------------------------------------------------ + # By the work of Assion no check on the group homomorphism is needed, at all. + # But to take care of software bugs they are perfomed in cases where they are + # not really expansive. + # ------------------------------------------------------------------------------ + check = False + if self.strands() < 7: + check = True + + # ------------------------------------------------------------------------------ + # Do the projective group realization if needed + # ------------------------------------------------------------------------------ + Embedding = self._classical_embedding + ClassicalGroup = None + if ProjGroup is None: + ClassicalGroup = BaseGroup + homToClassic = self.hom(im_gens, check=check) + ClassicalGroup.register_conversion(homToClassic) + else: + if Embedding is None: + im_gens.pop() + Embedding = BaseGroup.subgroup(im_gens, check=check) + Embedding.register_conversion(self.hom(Embedding.gens(), check=check)) + homToBase = self.hom(im_gens, check=check, codomain=BaseGroup) + BaseGroup.register_conversion(homToBase) + + if not just_embedded: + transvec_matrices.pop() + natHom = BaseGroup.hom(ProjGroup.gens(), check=check) + centralizing_element = natHom(centralizing_matrix) + ClassicalGroupGens = [natHom(m) for m in transvec_matrices] + ClassicalGroup = ProjGroup.subgroup(ClassicalGroupGens, canonicalize=False) + homToClassic = self.hom(ClassicalGroup.gens(), check=check) + ClassicalGroup.register_conversion(homToClassic) + + # ------------------------------------------------------------------------------ + # register constructed items + # ------------------------------------------------------------------------------ + self._classical_group = ClassicalGroup + self._classical_base_group = BaseGroup + self._classical_invariant_form = BaseGroup.invariant_form() + self._centralizing_matrix = centralizing_matrix + self._centralizing_element = centralizing_element + self._classical_embedding = Embedding + return + + + + # ------------------------------------------------------------------------------- + # local methods to set up the classical group (spezific part) + # ------------------------------------------------------------------------------- + # Case for symlectic groups + # ------------------------------------------------------------------------------- + def create_sympl_realization(self, m): + r""" + Internal method to create classical group for symplectic + Assion groups (`cbg_type CubicBraidGroupType.AssionS`). + + INPUT: + + - ``m`` -- Integer, the dimension of the classical groups vectorspace of operation. + + The function calculates the centralizing matrix and the transvections as given by Assion + and then uses set_classical_realization to complete the construction. + """ + + # ----------------------------------------------------------- + # getting the invariant bilinearform of the group + # and setting constants. + # ----------------------------------------------------------- + n = self.strands() + + from sage.groups.matrix_gps.symplectic import Sp + BaseGroup = Sp(m, 3) + ProjGroup = None + if m == n: + from sage.groups.perm_gps.permgroup_named import PSp + ProjGroup = PSp(m, 3) + + bform = BaseGroup.invariant_form() + bas = bform.column_space().basis() + if m % 2 == 0: + mhalf = m/2 + else: + mhalf = (m-1)/2 + + # ----------------------------------------------------------- + # computing a hyperbolic decomposition basis with respect + # to the invariant bilinear form. + # ----------------------------------------------------------- + xbas =[bas[mhalf -i -1] for i in range(mhalf)] + ybas =[bas[mhalf +i] for i in range(mhalf)] + + # ----------------------------------------------------------- + # computing the List of transvection vectors according to + # the Assion paper, page 292. + # ----------------------------------------------------------- + transvections =[xbas[0]] # t_1 = x_1 + for i in range(mhalf-1): + transvections.append(ybas[i]) # t_{2i} = y_i + transvections.append(xbas[i] + xbas[i+1]) # t_{2i+1} = x_j + x_(j+1) + transvections.append(ybas[mhalf-1]) # t_n = y_m + + # ----------------------------------------------------------- + # Conversion-Map from transvection vector to transvection + # matrix. + # ----------------------------------------------------------- + from sage.matrix.constructor import matrix + def transvec2mat(v, bas=bas, bform=bform, fact=1): + t = [x + fact*(x * bform * v) * v for x in bas] + return matrix(bform.base_ring(), t) + + # ------------------------------------------------------------------------------ + # setting the centralizing matrix for the case of projective group realizaton + # ------------------------------------------------------------------------------ + centralizing_vector = xbas[mhalf-1] + centralizing_matrix = BaseGroup(transvec2mat(centralizing_vector, fact=1)) + transvec_matrices = [transvec2mat(v) for v in transvections] + + set_classical_realization(self, BaseGroup, ProjGroup, centralizing_matrix, transvec_matrices) + return + + + + # ------------------------------------------------------------------------------- + # Case for unitary groups + # ------------------------------------------------------------------------------- + def create_unitary_realization(self, m): + """ + Internal method to create classical group for + unitary Assion groups (`cbg_type CubicBraidGroupType.AssionU`). + + INPUT: + + - ``m`` -- Integer, the dimension of the classical groups vectorspace of operation. + + The function calculates the centralizing_matrix and the transvections as given by Assion + and then uses set_classical_realization to complete the construction. + """ + + # --------------------------------------------------------------------- + # getting the invariant bilinearform of the group + # and setting constants + # --------------------------------------------------------------------- + n = self.strands() + + from sage.groups.matrix_gps.unitary import GU + BaseGroup = GU(m, 2) + ProjGroup = None + if m == n: + from sage.groups.perm_gps.permgroup_named import PGU + ProjGroup = PGU(m, 2) + + bform = BaseGroup.invariant_form() + bas = bform.column_space().basis() + BasR = bform.base_ring() + vA = BasR.gen() + + if m % 3 == 1: + mthird = (m-1)/3 + elif m % 3 == 2: + mthird = (m-2)/3 + else: + mthird = m/3 + + # ----------------------------------------------------------- + # computing a orthonormal basis with respect + # to the invariant bilinear form. + # ----------------------------------------------------------- + xbas =[] + for i in range(m): + if 2*i == m-1: + xbas.append(bas[i]) + else: + xbas.append(vA*bas[i] + vA.frobenius()*bas[m-1 -i]) + + # ----------------------------------------------------------- + # computing the List of transvection vectors according to + # Assion paper, page 293. + # ----------------------------------------------------------- + transvections =[xbas[0]] # t_1 = x_1 + if m > 1: + transvections.append(xbas[0]+xbas[1]+xbas[2]) # t_2 = x_1 + x_2 + x_3 + for j in range(mthird): + pos = 3*(j+1)-1 + transvections.append(xbas[pos-1]) # t_{3i} = x_{3i-1} + if pos +1 < m: + transvections.append(xbas[pos-1]+xbas[pos]+xbas[pos+1]) # t_{3i+1} = x_{3i-1} + x_{3i} + x_{3i+1} + if pos +3 < m: + transvections.append(xbas[pos+1]+xbas[pos+2]+xbas[pos+3]) # t_{3i+2} = x_{3i+1} + x_{3i+2} + x_{3i+3} + + # ----------------------------------------------------------- + # Conversion-Map from transvection vector to transvection + # matrix. + # ----------------------------------------------------------- + from sage.matrix.constructor import matrix + def transvec2mat(v, bas=bas, bform=bform, fact=vA): + # note x does not change under conjugation, since it belongs to standard basis + t = [x + fact *(x * bform * v.conjugate()) * v for x in bas] + return matrix(bform.base_ring(), t) + + + # ------------------------------------------------------------------------------ + # setting the centralizing matrix for the case of projective group realizaton. + # ------------------------------------------------------------------------------ + centralizing_vector = xbas[m-2]+xbas[m-1] + centralizing_matrix = BaseGroup(transvec2mat(centralizing_vector, fact=1)) + transvec_matrices = [transvec2mat(v) for v in transvections] + + set_classical_realization(self, BaseGroup, ProjGroup, centralizing_matrix, transvec_matrices) + return + + + #---------------------------------------------------------------------------------------------------------- + #---------------------------------------------------------------------------------------------------------- + # local functions declaration section finishes here + #---------------------------------------------------------------------------------------------------------- + #---------------------------------------------------------------------------------------------------------- + + + # ------------------------------------------------------------------------------- + # initialization of constants + # ------------------------------------------------------------------------------- + n = self.strands() + + # ------------------------------------------------------------------------------- + # Setting the Classical group + # ------------------------------------------------------------------------------- + if self._cbg_type == CubicBraidGroupType.AssionS: + dim_sympl_group = n-1 # S(n-1) = Sp(n-1, 3) + if n % 2 == 0: + dim_sympl_group = n # S(n-1) = subgroup of PSp(n, 3) + create_sympl_realization(self, dim_sympl_group) + elif self._cbg_type == CubicBraidGroupType.AssionU: + dim_unitary_group = n-1 # U(n-1) = GU(n-1, 2) + if n % 3 == 0: + dim_unitary_group = n # U(n-1) = subgroup PGU(n, 3) + create_unitary_realization(self, dim_unitary_group) + else: + # ----------------------------------------------------------------------------------------------- + # connection between Coxeter realization and unitary Burau representation according to Squier: + # ----------------------------------------------------------------------------------------------- + # Notation of Coxeter: p = 3, \theta =\pi/3 = primitive 6th root of unity + # i\theta = \pi/3+\pi/2 = 5\pi/6 = 5th power of primitive 12th root of unity + # i\theta = z12^5 = - ~z12 where z12 = UCF.gen(12) + # Let f be the unitary Form of Coxeter and J(s) the one of Squier. Then we have + # J(z12) = 2 f + # Let `buc` be the unitary Burau Matrix of Coxeter for the first braid generator and `bus` + # the corresponding one according to Squier. Then we have: + # buc_[i,i-1] = buc_[i,i+1]= - i\theta, buc_[i,i] = 1 + 2*cos(\pi/6)*i\theta + # bus_[i,i-1] = bus_[i,i+1]= s, bus_[i,i] = -s^2 + # now 1 + 2*cos(\pi/6)*i\theta = 1 + sqrt(3)*(-sqrt(3)/2 + I/2) = 1- 3/2 + sqrt(3)I/2 = z12^4 = - ~z12^2 + # finally: Coxeters Realization is the unitary Burau representation of Squier for s = ~z12 + # ----------------------------------------------------------------------------------------------- + UCF = UniversalCyclotomicField(); z12 = UCF.gen(12) + ClassicalGroup = self.as_matrix_group(rootBur=~z12, Domain=UCF, reduced='unitary') + self._classical_group = ClassicalGroup + self._classical_base_group = ClassicalGroup + self._classical_embedding = ClassicalGroup + if self._classical_invariant_form is None: + self._classical_invariant_form = ClassicalGroup.ambient().invariant_form() + return + + + + def _element_constructor_(self, x, **kwds): + r""" + Extensions to the _element constructor of :class:`FinitelyPresentedGroup`: + new functionalities are: + + -- constructing element from an element of the attached classical group + (embedded and not embedded) + -- constructing element from an element of the attached permutation group + -- constructing element from an element of the attached refelction group + + INPUT:: + + - ``x`` -- can be one of the following: + -- an instance of the element class of ``self`` (but possible to a different parent). + -- an instance of the element class of the braid group. + -- a tuple representing a braid in Tietze form. + -- an instance of an element class of a parent P such that there is a map from ``self`` to P + having :meth:`lift`, for example an element of an alternative realization of ``self``, such + as the classical realization. + -- any other object which works for the element constructor of :class:`FinitelyPresentedGroup`. + + OUTPUT: + + instance of the element class of ``self`` + + EXAMPLES:: + + sage: S3 = AssionGroupS(3) + sage: S3Cl = S3.as_classical_group() + sage: g = mul(S3Cl.gens()) + sage: S3(g) # indirect doctest + s0*s1*s0^-1 + """ + if hasattr(x, 'parent'): + parent = x.parent() + map_to = parent.convert_map_from(self) + if map_to is not None: + if hasattr(map_to, 'lift'): + return map_to.lift(x) + return super(CubicBraidGroup_class, self)._element_constructor_(x) + + + + + + ####################################################################################################################### + # ---------------------------------------------------------------------------------- + # public methods + # ---------------------------------------------------------------------------------- + ####################################################################################################################### + + + + # --------------------------------------------------------------------------------------------------------------------- + # strands + # --------------------------------------------------------------------------------------------------------------------- + def strands(self): + r""" + Return the number of strands of the braid group whose image is ``self``. + + OUTPUT: Integer. + + EXAMPLES:: + + sage: C4 = CubicBraidGroup(4) + sage: C4.strands() + 4 + """ + return self._nstrands + + + + + # ---------------------------------------------------------------------------------- + # braid_group + # ---------------------------------------------------------------------------------- + def braid_group(self): + r""" + Return an Instance of :class:`BraidGroup` with identical generators, such that + there exists an epimorhism to ``self``. + + OUTPUT: + + Instance of :class:`BraidGroup` having conversion maps to and from ``self`` + (which is just a section in the latter case). + + EXAMPLES:: + + sage: U5 = AssionGroupU(5); U5 + Assion group on 5 strands of type U + sage: B5 = U5.braid_group(); B5 + Braid group on 5 strands + sage: b = B5([4,3,2,-4,1]) + sage: u = U5([4,3,2,-4,1]) + sage: u == b + False + sage: b.burau_matrix() + [ 1 - t t 0 0 0] + [ 1 - t 0 t 0 0] + [ 1 - t 0 0 0 t] + [ 1 - t 0 0 1 -1 + t] + [ 1 0 0 0 0] + sage: u.burau_matrix() + [ -zeta3 zeta3 + 1 0 0 0] + [ -zeta3 0 zeta3 + 1 0 0] + [ -zeta3 0 0 0 zeta3 + 1] + [ -zeta3 0 0 1 zeta3] + [ 1 0 0 0 0] + sage: bU = U5(b) + sage: uB = B5(u) + sage: bU == u + True + sage: uB == b + True + """ + return self._braid_group + + + + + + + + + + + + # ---------------------------------------------------------------------------------- + # as_matrix_group + # ---------------------------------------------------------------------------------- + def as_matrix_group(self, rootBur=None, Domain=None, characteristic=None, var='t', reduced=False): + r""" + Creates an epimorphic image of ``self`` as a matrix group by use of the burau representation. + + INPUT (all arguments are optional by keyword): + + - ``rootBur`` -- six (resp. twelfth) root of unity in some field + (default root of unity over `\QQ`). + - ``Domain`` -- base_ring for the burau matrix (default is Cyclotomic + Field of order 3 and degree 2, resp. the domain of `rootBur` if given). + - ``characteristic`` - integer giving the characteristic of the + domain (default is 0 or the characteristic of `Domain` if given) + If none of the keywords `rootBur`, `Domain` and `characteristic` is + given the default characteristic is 3 (resp. 2) if ``self`` is of ``cbg_type + CubicBraidGroupType.AssionS`` (resp. ``CubicBraidGroupType.AssionU``). + - ``var`` -- string used for the indeterminant name in case `rootBur` + must be constructed in a splitting field. + - ``reduced`` -- boolean (default: ``False``); for more information + see the documentation of :meth:`burau_matrix` of :class:`Braid`. + + OUTPUT: + + An instance of the class :class:`FinitelyGeneratedMatrixGroup_gap` according to the + input arguments together with a group homomorphism registerd as a conversion + from ``self`` to it. + + EXAMPLES:: + + sage: C5 = CubicBraidGroup(5) + sage: C5Mch5 = C5.as_matrix_group(characteristic=5); C5Mch5 + Matrix group over Finite Field in t of size 5^2 with 4 generators ( + [2*t + 2 3*t + 4 0 0 0] + [ 1 0 0 0 0] + [ 0 0 1 0 0] + [ 0 0 0 1 0] + [ 0 0 0 0 1], + + [ 1 0 0 0 0] + [ 0 2*t + 2 3*t + 4 0 0] + [ 0 1 0 0 0] + [ 0 0 0 1 0] + [ 0 0 0 0 1], + + [ 1 0 0 0 0] + [ 0 1 0 0 0] + [ 0 0 2*t + 2 3*t + 4 0] + [ 0 0 1 0 0] + [ 0 0 0 0 1], + + [ 1 0 0 0 0] + [ 0 1 0 0 0] + [ 0 0 1 0 0] + [ 0 0 0 2*t + 2 3*t + 4] + [ 0 0 0 1 0] + ) + sage: c = C5([3,4,-2,-3,1]); c + c2*c3*c1^-1*c2^-1*c0 + sage: m = C5Mch5(c); m + [2*t + 2 3*t + 4 0 0 0] + [ 0 0 0 1 0] + [2*t + 1 0 2*t + 2 3*t 3*t + 3] + [2*t + 2 0 0 3*t + 4 0] + [ 0 0 2*t + 2 3*t + 4 0] + sage: m_back = C5(m) + sage: m_back == c + True + sage: U5 = AssionGroupU(5); U5 + Assion group on 5 strands of type U + sage: U5Mch3 = U5.as_matrix_group(characteristic=3) + Traceback (most recent call last): + ... + ValueError: Burau representation does not factor through the relations + """ + # ------------------------------------------------------------------------------- + # define matrix group by generators using the Burau representation + # ------------------------------------------------------------------------------- + + # ------------------------------------------------------------------------------- + # adaption of default options for Assion groups on more then 4 stands + # (in order to achive the maps beeing well defined) + # ------------------------------------------------------------------------------- + if rootBur is None and Domain is None and characteristic is None: + if self._cbg_type == CubicBraidGroupType.AssionS: + characteristic = 3 + elif self._cbg_type == CubicBraidGroupType.AssionU: + characteristic = 2 + else: + characteristic = 0 + + unitary = False + if type(reduced) == str: + if reduced == 'unitary': + unitary = True + + genList =[] + for braidGen in self.gens(): + burMat = braidGen.burau_matrix(rootBur=rootBur, Domain=Domain, characteristic=characteristic, + var=var, reduced=reduced) + if unitary: + burMat, burMatAd, hermForm = burMat + + if Domain is None: + Domain = burMat.base_ring() + + genList.append(burMat) + + if unitary and hermForm.is_singular(): + unitary = False # since a degenertated hermitian form doesn't define a unitary group + if self._classical_invariant_form is None: + self._classical_invariant_form = hermForm + + if unitary: + from sage.rings.finite_rings.finite_field_base import is_FiniteField + from sage.groups.matrix_gps.unitary import GU + d, d = hermForm.dimensions() + if is_FiniteField(Domain): + BaseGroup = GU(d, Domain, var=Domain.gen(), invariant_form=hermForm) + else: + BaseGroup = GU(d, Domain, invariant_form=hermForm) + + MatGroup = BaseGroup.subgroup(genList) + else: + from sage.groups.matrix_gps.finitely_generated import MatrixGroup + MatGroup = MatrixGroup(genList) + + # ------------------------------------------------------------------------------- + # check if there is a well defined group homomorphism to MatGroup + # Register map from ``self`` to MatGroup. + # Since GAP' check is very expansive (on time and memory), the check is performed + # here. + # ------------------------------------------------------------------------------- + homToMat = self.hom(MatGroup.gens(), check=False) + if not all( homToMat(rel).is_one() for rel in self.relations()): + raise ValueError("Burau representation does not factor through the relations") + MatGroup.register_conversion(homToMat) + return MatGroup + + + + + + + # ---------------------------------------------------------------------------------- + # Although this method is availlable for finitely presented group + # we use the classical group implementation (by performace reason) to get + # the permutation_group. + # ---------------------------------------------------------------------------------- + def as_permutation_group(self, use_classical=True): + r""" + This method returns a permutation group isomporhic to ``self`` together + with group isomorphism from ``self`` as a conversion. + + INPUT (all arguments are optional by keyword): + + - ``use_classical`` -- (boolean, default True) by default the permutation + group is calculated via the attached classical matrix group, since this + results in a smaller degree. If set to False the permutation group will + be calculated using ``self`` (as finitely presented group). + + OUTPUT: + + An instance of class :class:`PermutationGroup_generic` together with a group homomorphism + from ``self`` registerd as a conversion. + + EXAMPLES:: + + sage: C3 = CubicBraidGroup(3) + sage: PC3 = C3.as_permutation_group() + sage: C3.is_isomorphic(PC3) + #I Forcing finiteness test + True + sage: PC3.degree() + 8 + sage: c = C3([2,1-2]) + sage: C3(PC3(c)) == c + True + """ + if not self.is_finite(): + raise ValueError('Cubic braid group is infinite!') + + if use_classical: + CG = self.as_classical_group() + from sage.groups.perm_gps.permgroup import PermutationGroup_generic + if isinstance(CG, PermutationGroup_generic): + return CG + CGM = CG.as_matrix_group() + PG = CGM.as_permutation_group() + img_gens = [PG(CGM(CG(gen))) for gen in self.gens()] + else: + PG = super(CubicBraidGroup_class, self).as_permutation_group() + img_gens = PG.gens() + + img_gens = [PG(gen) for gen in img_gens] + homToPerm = self.hom(img_gens) + PG.register_conversion(homToPerm) + return PG + + + + + + + # ---------------------------------------------------------------------------------- + # as_classical_group + # ---------------------------------------------------------------------------------- + def as_classical_group(self, embedded=False): + r""" + Creates an isomorphic image of ``self`` as a classical group according + to the construction given by Coxeter resp. Assion. + + INPUT (optional keyword): + + - ``embedded`` -- boolean (default = False). This boolean does effect the + cases of Assion groups when they are realized as projective groups, only. + More precisely: if ``self`` is of ``cbg_type CubicBraidGroupType.AssionS`` + (for example) and the number of strands ``n`` is even, than its classical group + is a subgroup of ``PSp(n,3)`` (being centralized by the element + ``self.centralizing_element(projective=True))``. By default this group will be + given. Setting ``embedded = True`` the classical realization is given as + subgroup of its classical enlargement with one more strand (in this + case as subgroup of ``Sp(n,3))``. + + OUTPUT: + + Depending on the type of ``self`` and the number of strands an instance of ``Sp(n-1,3)``, + ``GU(n-1,2)``, subgroup of ``PSp(n,3), PGU(n,2)`` or a subgroup of ``GU(n-1, UCF)`` + (``cbg_type CubicBraidGroupType.Coxeter``) with respect to a certain hermitian form + attached to the burau representation (used by Coxeter and Squier). Here ``UCF`` stands + for the universal cyclotomic field. + + EXAMPLES:: + + sage: U3 = AssionGroupU(3) + sage: U3Cl = U3.as_classical_group(); U3Cl + Subgroup of (The projective general unitary group of degree 3 over Finite Field of size 2) generated by + [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), + (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] + sage: U3Clemb = U3.as_classical_group(embedded=True); U3Clemb + Matrix group over Finite Field in a of size 2^2 with 2 generators ( + [0 0 a] [a + 1 a a] + [0 1 0] [ a a + 1 a] + [a 0 a], [ a a a + 1] + ) + sage: u = U3([-2,1,-2,1]); u + (u1^-1*u0)^2 + sage: uCl = U3Cl(u); uCl + (1,16)(2,9)(3,10)(4,19)(6,12)(7,20)(13,21)(14,15) + sage: uCle = U3Clemb(u); uCle + [a + 1 a + 1 1] + [a + 1 0 a] + [ 1 a a] + sage: U3(uCl) == u + True + sage: U3(uCle) == u + True + sage: U4 = AssionGroupU(4) + sage: U4Cl = U4.as_classical_group(); U4Cl + General Unitary Group of degree 3 over Finite Field in a of size 2^2 + sage: U3Clemb.ambient() == U4Cl + True + sage: C4 = CubicBraidGroup(4) + sage: C4Cl = C4.as_classical_group(); C4Cl + Subgroup of General Unitary Group of degree 3 over Universal Cyclotomic Field with respect to hermitian form + [-E(12)^7 + E(12)^11 -1 0] + [ -1 -E(12)^7 + E(12)^11 -1] + [ 0 -1 -E(12)^7 + E(12)^11] with 3 generators ( + [ E(3)^2 0 0] [ 1 -E(12)^7 0] + [-E(12)^7 1 0] [ 0 E(3)^2 0] + [ 0 0 1], [ 0 -E(12)^7 1], + + [ 1 0 0] + [ 0 1 -E(12)^7] + [ 0 0 E(3)^2] + ) + """ + + # ------------------------------------------------------------------------------- + # create the classical group if not already done + # ------------------------------------------------------------------------------- + if self._classical_group is None: + if embedded and self._classical_embedding is None: + # this is separated to avoid unneccessary (for larger group exhaustive) calculations + self._create_classical_realization(just_embedded=True) + else: + self._create_classical_realization() + + if embedded and self._classical_embedding is not None: + # ---------------------------------------------------------------------------------------- + # there is a difference between self._classical_group and self._classical_embedding + # only in the cases where self.strands() divides by 2 (AssionGroupS) resp. 3 + # (AssionGroupU). In this case the embedding is the subgroup of the classical group + # of one strand more (self.strands() +1) generated by the first self.strands() -1 + # generators + # ---------------------------------------------------------------------------------------- + return self._classical_embedding + elif self._classical_group is not None: + return self._classical_group + else: + raise ValueError("no classical embedding defined") + + + + + + + # ---------------------------------------------------------------------------------- + # as_refection_group + # ---------------------------------------------------------------------------------- + def as_reflection_group(self): + r""" + Creates an isomorphic image of ``self`` as irreducible complex reflection group. + This is possible only for the finite cubic braid groups of ``cbg_type + CubicBraidGroupType.Coxeter``. + + This method uses the sage implementation of reflection group via the gap3 CHEVIE + package. To use this method you must have gap3 together with CHEVIE installed! + + OUTPUT: + + An instance of the class :class:`IrreducibleComplexReflectionGroup` together with + a group isomorphism from ``self`` registered as a conversion. + + + EXAMPLES:: + + sage: C3. = CubicBraidGroup(3) # optional - gap3 + sage: R3 = C3.as_reflection_group(); R3 # optional - gap3 + Irreducible complex reflection group of rank 2 and type ST4 + sage: R3.cartan_matrix() # optional - gap3 + [-2*E(3) - E(3)^2 E(3)^2] + [ -E(3)^2 -2*E(3) - E(3)^2] + sage: R3.simple_roots() # optional - gap3 + Finite family {1: (0, -2*E(3) - E(3)^2), 2: (2*E(3)^2, E(3)^2)} + sage: R3.simple_coroots() # optional - gap3 + Finite family {1: (0, 1), 2: (1/3*E(3) - 1/3*E(3)^2, 1/3*E(3) - 1/3*E(3)^2)} + + Conversion maps:: + + sage: r = R3.an_element() # optional - gap3 + sage: cr = C3(r); cr # optional - gap3 + c1*c2 + sage: mr = r.matrix(); mr # optional - gap3 + [ 1/3*E(3) - 1/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2] + [-2/3*E(3) + 2/3*E(3)^2 2/3*E(3) + 1/3*E(3)^2] + sage: C3Cl = C3.as_classical_group() # optional - gap3 + sage: C3Cl(cr) # optional - gap3 + [ E(3)^2 -E(4)] + [-E(12)^7 0] + + The refelection groups can also be viewed as subgroups of unitary groups + over the universal cyclotomic field. Note that the unitary group corresponding + to the reflection group is isomorphic but different from the classical group due + to different hermitian forms for the unitary groups they live in:: + + sage: C4 = CubicBraidGroup(4) # optional - gap3 + sage: R4 = C4.as_reflection_group() # optional - gap3 + sage: R4.invariant_form() # optional - gap3 + [1 0 0] + [0 1 0] + [0 0 1] + sage: _ == C4.classical_invariant_form() # optional - gap3 + False + """ + + # ------------------------------------------------------------------------------- + # the reflection groups are called according to the Shephard-Todd classification: + # 2 strands -> G(2,1,1) + # 3 strands -> G4 + # 4 strands -> G25 + # 5 strands -> G32 + # ------------------------------------------------------------------------------- + + from sage.combinat.root_system.reflection_group_real import is_chevie_available + if not is_chevie_available(): + raise ImportError("the GAP3 package 'chevie' is needed to obtain the corresponding reflection groups") + + if self._cbg_type != CubicBraidGroupType.Coxeter or self.strands() > 5 or self.strands() < 2: + raise ValueError("no reflection group defined") + + # ------------------------------------------------------------------------------- + # define reflection group assiossiated to self + # ------------------------------------------------------------------------------- + ReflectGroup = None + + from sage.combinat.root_system.reflection_group_real import ReflectionGroup + + if self.strands() == 2: + ReflectGroup = ReflectionGroup([2 ,1 ,1]) + elif self.strands() == 3: + ReflectGroup = ReflectionGroup(4) + elif self.strands() == 4: + ReflectGroup = ReflectionGroup(25) + elif self.strands() == 5: + ReflectGroup = ReflectionGroup(32) + + homToRefl = self.hom(ReflectGroup.gens()) + ReflectGroup.register_conversion(homToRefl) + return ReflectGroup + + + + # ---------------------------------------------------------------------------------- + # classical invariant form returns the invariant form of the classical realization + # ---------------------------------------------------------------------------------- + def classical_invariant_form(self): + r""" + Returns the invariant form of the classical realization of ``self``. + + OUTPUT: + + A square matrix of dimension according to the space the classical realization is + operating on. In the case of the full cubic braid groups and of the assion groups + of ``cbg_type CubicBraidGroupType.AssionU`` the matrix is hermitian. In the case of + the Assion groups of ``cbg_type CubicBraidGroupType.AssionS`` it is alternating. + Note that the invariant form of the full cubic braid group on more than 5 strands + is degenerated (causing the group to be infinite). + + In the case of Assion groups having projective classical groups the invariant form + corresponds to the ambient group of its classical embedding. + + EXAMPLES:: + + sage: S3 = AssionGroupS(3) + sage: S3.classical_invariant_form() + [0 1] + [2 0] + sage: S4 = AssionGroupS(4) + sage: S4.classical_invariant_form() + [0 0 0 1] + [0 0 1 0] + [0 2 0 0] + [2 0 0 0] + sage: S5 = AssionGroupS(5) + sage: S4.classical_invariant_form() == S5.classical_invariant_form() + True + sage: U4 = AssionGroupU(4) + sage: U4.classical_invariant_form() + [0 0 1] + [0 1 0] + [1 0 0] + sage: C5 = CubicBraidGroup(5) + sage: C5.classical_invariant_form() + [-E(12)^7 + E(12)^11 -1 0 0] + [ -1 -E(12)^7 + E(12)^11 -1 0] + [ 0 -1 -E(12)^7 + E(12)^11 -1] + [ 0 0 -1 -E(12)^7 + E(12)^11] + sage: _.is_singular() + False + sage: C6 = CubicBraidGroup(6) + sage: C6.classical_invariant_form().is_singular() + True + """ + # ------------------------------------------------------------------------------- + # create the classical_invariant_form if not already done + # ------------------------------------------------------------------------------- + if self._classical_invariant_form is None: + self._create_classical_realization() + + if self._classical_invariant_form is None: + raise ValueError("no classical invariant form defined!") + + return self._classical_invariant_form + + + + + # ---------------------------------------------------------------------------------- + # centralizing element in the classical symplectic resp. unitary group + # ---------------------------------------------------------------------------------- + def centralizing_element(self, embedded=False): + r""" + Returns the centralizing element defined by the work of Assion + (Hilfssatz 1.1.3 and 1.2.3). + + INPUT (optional): + + - ``embedded`` -- boolean (default = False). This boolean just effects + the cases of Assion groups when they are realized as projective groups. + More precisely: if ``self`` is of ``cbg_type CubicBraidGroupType.AssionS`` + (for example) and the number of strands ``n`` is even, than its classical + group is a subgroup of ``PSp(n,3)`` being centralized by the element return + for option ``embedded=False``. Otherwise the image of this element inside + the embedded classical group will be returned (see option embedded of + :meth:`classical_group`)! + + OUTPUT: + + Depending on the optional keyword a permutation as an element of ``PSp(n,3)`` + (type S) or ``PGU(n,2)`` (type U) for ``n = 0 mod 2`` (type S) reps. ``n = 0 mod 3`` + (type U) is returned. Elsewise, the centralizing element is a matrix + belonging to ``Sp(n,3)`` reps. ``GU(n,2)``. + + EXAMPLES:: + + sage: U3 = AssionGroupU(3); U3 + Assion group on 3 strands of type U + sage: U3Cl = U3.as_classical_group(); U3Cl + Subgroup of (The projective general unitary group of degree 3 over Finite Field of size 2) generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] + sage: c = U3.centralizing_element(); c + (1,16)(2,9)(3,10)(4,19)(6,12)(7,20)(13,21)(14,15) + sage: c in U3Cl + True + sage: P = U3Cl.ambient_group() + sage: P.centralizer(c) == U3Cl + True + + embedded Version:: + + sage: cm = U3.centralizing_element(embedded=True); cm + [a + 1 a + 1 1] + [a + 1 0 a] + [ 1 a a] + sage: U4 = AssionGroupU(4) + sage: U4Cl = U4.as_classical_group() + sage: cm in U4Cl + True + sage: [cm * U4Cl(g) == U4Cl(g) * cm for g in U4.gens()] + [True, True, False] + """ + + # ------------------------------------------------------------------------------- + # create the centralizing elements if not already done + # ------------------------------------------------------------------------------- + if self._centralizing_matrix is None: + self._create_classical_realization() + + if self._centralizing_matrix is None: + raise ValueError("no centralizing element defined") + else: + if embedded == True or self._centralizing_element is None: + return self._centralizing_matrix + else: + return self._centralizing_element + + + # ---------------------------------------------------------------------------------- + # calculating the order by formula + # ---------------------------------------------------------------------------------- + def order(self): + r""" + To avoid long waittime on calculations the order will be obtained + using the classical realization. + + OUTPUT: + + Cardinality of the group as Integer or infinity. + + EXAMPLES:: + + sage: S15 = AssionGroupS(15) + sage: S15.order() + 109777561863482259035023554842176139436811616256000 + sage: C6 = CubicBraidGroup(6) + sage: C6.order() + +Infinity + """ + from sage.rings.infinity import infinity + n = self.strands() + + if self._cbg_type == CubicBraidGroupType.Coxeter and n > 5: + order = infinity + else: + order = self.as_classical_group(embedded=True).order() + + return order + + + cardinality = order + + + def is_finite(self): + r""" + Method from :class:`GroupMixinLibGAP` overwriten because of performance reason. + """ + from sage.rings.infinity import infinity + return not self.order() is infinity + + + # ---------------------------------------------------------------------------------- + # creating a CubicBraidGroup as subgroup of self on less strands + # ---------------------------------------------------------------------------------- + def cubic_braid_subgroup(self, nstrands = None): + r""" + Creates a cubic braid group as subgroup of ``self`` on the first ``nstrands`` strands. + + INPUT: + + - ``nstrands`` -- integer > 0 and < ``self.strands()`` giving the number of strands + for the subgroup. The default is one strand less than ``self`` has. + + OUTPUT: + + An instance of this class realizing the subgroup. + + .. NOTE:: + + Since ``self`` is inherited from :class:`UniqueRepresentation` the obtained instance + is identical to other instances created with the same arguments (see example + below). The ambient group corresponds to the last call of this method. + + EXAMPLES:: + + sage: U5 = AssionGroupU(5) + sage: U3s = U5.cubic_braid_subgroup(3) + sage: u1, u2 = U3s.gens() + sage: u1 in U5 + False + sage: U5(u1) in U5.gens() + True + sage: U3s is AssionGroupU(3) + True + sage: U3s.ambient() == U5 + True + """ + + if nstrands is None: + nstrands = self.strands() -1 + + n = self.strands() + + try: + nstrands = Integer(nstrands) + except: + raise TypeError("nstrands must be an integer") + + if nstrands >= n or nstrands <= 0: + raise ValueError("nstrands must be positive and less than %s" %(self.strands())) + + Gens = self.gens() + GensRed = tuple([Gens[i] for i in range(nstrands -1)]) + subgrp = CubicBraidGroup(names=GensRed, cbg_type=self._cbg_type) + subgrp._ambient = self + return subgrp From 623e14b4f5d9cbfb852ac1702c028db80f291ef5 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 9 Mar 2019 18:23:07 +0100 Subject: [PATCH 02/10] PEP8 adaptions --- src/sage/groups/cubic_braid.py | 486 ++++++++++++++------------------- 1 file changed, 203 insertions(+), 283 deletions(-) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index d9249958644..e8e878eaa08 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -68,13 +68,6 @@ """ - - - - - - - # **************************************************************************** # Copyright (C) 2019 Sebastian Oehms # @@ -86,7 +79,6 @@ # **************************************************************************** - from sage.rings.integer import Integer from sage.groups.free_group import FreeGroup from sage.groups.finitely_presented import FinitelyPresentedGroup, FinitelyPresentedGroupElement @@ -102,7 +94,6 @@ # Enum for the type of the group # ############################################################################## - class CubicBraidGroupType(Enum): r""" Enum class to select the type of the group: @@ -116,8 +107,6 @@ class CubicBraidGroupType(Enum): AssionU = 'U' - - ############################################################################## # # Functions to create Instances of the CubicBraidGroup_class @@ -167,10 +156,8 @@ def CubicBraidGroup(n=None, names='c', cbg_type=CubicBraidGroupType.Coxeter): else: names = list(names) n = len(names) - try: - from sage.structure.category_object import normalize_names - except: - from sage.structure.parent import normalize_names + + from sage.structure.category_object import normalize_names names = tuple(normalize_names(n, names)) return CubicBraidGroup_class(names, cbg_type=cbg_type) @@ -178,7 +165,6 @@ def CubicBraidGroup(n=None, names='c', cbg_type=CubicBraidGroupType.Coxeter): # ---------------------------------------------------------------------------------- # Short-Hands for AssionsGroups: # ---------------------------------------------------------------------------------- - def AssionGroupS(n=None, names='s'): r""" Constructs cubic braid groups as instance of :class:`CubicBraidGroup_class` which @@ -241,16 +227,11 @@ def AssionGroupU(n=None, names='u'): - - - - ############################################################################## # # Class CubicBraidElement (for elements) # ############################################################################## - class CubicBraidElement(FinitelyPresentedGroupElement): r""" This class models elements of cubic factor groups of the braid group. @@ -269,8 +250,6 @@ class CubicBraidElement(FinitelyPresentedGroupElement): True """ - - def braid(self): r""" Return the canonical braid preimage of ``self`` as Object of the @@ -293,8 +272,7 @@ class :class:`Braid`. return braid_group(self) - - def burau_matrix(self, rootBur = None, Domain = None, characteristic = None, var='t', reduced=False): + def burau_matrix(self, root_bur = None, domain = None, characteristic = None, var='t', reduced=False): r""" Return the Burau matrix of the cubic braid coset. @@ -304,13 +282,13 @@ def burau_matrix(self, rootBur = None, Domain = None, characteristic = None, var INPUT (all arguments are optional keywords): - - ``rootBur`` -- six (resp. twelfth) root of unity in some field + - ``root_bur`` -- six (resp. twelfth) root of unity in some field (default root of unity over `\QQ`). - - ``Domain`` -- base_ring for the burau matrix (default is Cyclotomic - Field of order 3 and degree 2, resp. the domain of `rootBur` if given). + - ``domain`` -- base_ring for the burau matrix (default is Cyclotomic + Field of order 3 and degree 2, resp. the domain of `root_bur` if given). - ``characteristic`` - integer giving the characteristic of the - domain (default is 0 or the characteristic of `Domain` if given). - - ``var`` -- string used for the indeterminant name in case rootBur + domain (default is 0 or the characteristic of `domain` if given). + - ``var`` -- string used for the indeterminant name in case root_bur must be constructed in a splitting field. - ``reduced`` -- boolean (default: ``False``) or string; for more information see the documentation of :meth:`burau_matrix` of @@ -335,13 +313,13 @@ def burau_matrix(self, rootBur = None, Domain = None, characteristic = None, var Cyclotomic Field of order 3 and degree 2 sage: BuMa == ele.burau_matrix(characteristic = 0) True - sage: BuMa = ele.burau_matrix(Domain=QQ); BuMa + sage: BuMa = ele.burau_matrix(domain=QQ); BuMa [-t + 1 1 t - 1] [-t + 1 t 0] [ 1 0 0] sage: BuMa.base_ring() Number Field in t with defining polynomial t^2 - t + 1 - sage: BuMa = ele.burau_matrix(Domain = QQ[I, sqrt(3)]); BuMa + sage: BuMa = ele.burau_matrix(domain = QQ[I, sqrt(3)]); BuMa [ 1/2*sqrt3*I + 1/2 1 -1/2*sqrt3*I - 1/2] [ 1/2*sqrt3*I + 1/2 -1/2*sqrt3*I + 1/2 0] [ 1 0 0] @@ -360,13 +338,13 @@ def burau_matrix(self, rootBur = None, Domain = None, characteristic = None, var sage: BuMa.base_ring() Finite Field in t of size 2^2 sage: F4. = GF(4) - sage: BuMa = ele.burau_matrix(rootBur=r64); BuMa + sage: BuMa = ele.burau_matrix(root_bur=r64); BuMa [r64 + 1 1 r64 + 1] [r64 + 1 r64 0] [ 1 0 0] sage: BuMa.base_ring() Finite Field in r64 of size 2^2 - sage: BuMa = ele.burau_matrix(Domain=GF(5)); BuMa + sage: BuMa = ele.burau_matrix(domain=GF(5)); BuMa [2*t + 2 1 3*t + 3] [2*t + 2 3*t + 4 0] [ 1 0 0] @@ -379,7 +357,7 @@ def burau_matrix(self, rootBur = None, Domain = None, characteristic = None, var True sage: BuMa.base_ring() Cyclotomic Field of order 12 and degree 4 - sage: BuMa, BuMaAd, H = ele.burau_matrix(Domain = QQ[I, sqrt(3)], reduced='unitary'); BuMa + sage: BuMa, BuMaAd, H = ele.burau_matrix(domain = QQ[I, sqrt(3)], reduced='unitary'); BuMa [0 I] [I 0] sage: BuMa.base_ring() @@ -388,44 +366,44 @@ def burau_matrix(self, rootBur = None, Domain = None, characteristic = None, var braid = self.braid() unitary = False - minPolRootBurCf = [1 , -1 , 1] # minimal polynomial of sixth root of unity + min_pol_root_bur_cf = [1 , -1 , 1] # minimal polynomial of sixth root of unity if type(reduced) == str: if reduced == 'unitary': unitary = True - minPolRootBurCf = [1 , 0 , -1 , 0 , 1] # minimal polynomial of twelfth root of unity + min_pol_root_bur_cf = [1 , 0 , -1 , 0 , 1] # minimal polynomial of twelfth root of unity - BurauOri = braid.burau_matrix(reduced=reduced) + burau_ori = braid.burau_matrix(reduced=reduced) if unitary: - BurauOri, BurauOriAdj, HermFormOri = BurauOri + burau_ori, burau_ori_adj, herm_form_ori = burau_ori - if Domain != None: - if isinstance(Domain, UniversalCyclotomicField): - if rootBur is None: + if domain is not None: + if isinstance(domain, UniversalCyclotomicField): + if root_bur is None: if unitary: - rootBur = Domain.gen(12) + root_bur = domain.gen(12) else: - rootBur = Domain.gen(6) + root_bur = domain.gen(6) - if rootBur is None: + if root_bur is None: def find_root(domain): - minPolRootBur = domain[var](minPolRootBurCf) - rootList = minPolRootBur.roots() - if len(rootList) == 0: - Domain = minPolRootBur.splitting_field(minPolRootBur.variable_name()) - minPolRootBur = Domain[var](minPolRootBurCf) + min_pol_root_bur = domain[var](min_pol_root_bur_cf) + root_list = min_pol_root_bur.roots() + if len(root_list) == 0: + domain = min_pol_root_bur.splitting_field(min_pol_root_bur.variable_name()) + min_pol_root_bur = domain[var](min_pol_root_bur_cf) else: - Domain = domain - rootList = minPolRootBur.roots() - for root in rootList: + domain = domain + root_list = min_pol_root_bur.roots() + for root in root_list: if root[0] == 0: continue - rootBur = root[0] + root_bur = root[0] if root[1] == 1: break - return rootBur + return root_bur - if Domain is None: + if domain is None: if (characteristic is None): characteristic = 0 try: @@ -442,54 +420,52 @@ def find_root(domain): domain = CyclotomicField(3) else: domain = GF(characteristic) - rootBur = find_root(domain) - Domain = rootBur.parent() + root_bur = find_root(domain) + domain = root_bur.parent() - else: # Domain <> None + else: # domain <> None if characteristic is None: - characteristic = Domain.characteristic() - elif characteristic <> Domain.characteristic(): - raise ValueError('characteristic of Domain does not match given characteristic') - rootBur = find_root(Domain) - - else: # rootBur <> None - if Domain is None: - Domain = rootBur.parent() + characteristic = domain.characteristic() + elif characteristic <> domain.characteristic(): + raise ValueError('characteristic of domain does not match given characteristic') + root_bur = find_root(domain) + + else: # root_bur <> None + if domain is None: + domain = root_bur.parent() if characteristic is None: - characteristic = Domain.characteristic() - elif characteristic <> Domain.characteristic(): - raise ValueError('characteristic of Domain does not match given characteristic') + characteristic = domain.characteristic() + elif characteristic <> domain.characteristic(): + raise ValueError('characteristic of domain does not match given characteristic') - if 1 not in Domain: - raise ValueError('rootBur must belong to a domain containing 1') + if 1 not in domain: + raise ValueError('root_bur must belong to a domain containing 1') if unitary: - if Domain(rootBur**4 -rootBur**2 +1) != 0: - raise ValueError('rootBur must vanish on x**4-x**2+1') + if domain(root_bur**4 -root_bur**2 +1) != 0: + raise ValueError('root_bur must vanish on x**4-x**2+1') else: - if Domain(rootBur**2 -rootBur +1) != 0: - raise ValueError('rootBur must vanish on x**2-x+1') + if domain(root_bur**2 -root_bur +1) != 0: + raise ValueError('root_bur must vanish on x**2-x+1') - def conv2Domain (LaurPol): - l1, l2 = LaurPol.polynomial_construction() - R = Domain['tt']; (tt,) = R._first_ngens(1) + def conv2domain (laur_pol): + l1, l2 = laur_pol.polynomial_construction() + R = domain['tt']; (tt,) = R._first_ngens(1) p1 = R(l1) - p2 = rootBur**(l2) - res = p1.substitute(tt=rootBur) * p2 + p2 = root_bur**(l2) + res = p1.substitute(tt=root_bur) * p2 return res from sage.matrix.constructor import matrix - d1, d2 = BurauOri.dimensions() - BurauMat = matrix(d1, d2, lambda i,j: conv2Domain(BurauOri[i,j])) + d1, d2 = burau_ori.dimensions() + burau_mat = matrix(d1, d2, lambda i,j: conv2domain(burau_ori[i,j])) if unitary: - BurauMatAdj = matrix(d1, d2, lambda i,j: conv2Domain(BurauOriAdj[i,j])) - HermForm = matrix(d1, d2, lambda i,j: conv2Domain(HermFormOri[i,j])) - return BurauMat, BurauMatAdj, HermForm - - return BurauMat - + burau_mat_adj = matrix(d1, d2, lambda i,j: conv2domain(burau_ori_adj[i,j])) + herm_form = matrix(d1, d2, lambda i,j: conv2domain(herm_form_ori[i,j])) + return burau_mat, burau_mat_adj, herm_form + return burau_mat @@ -575,14 +551,14 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): #I Forcing finiteness test True sage: U3.as_classical_group() - Subgroup of (The projective general unitary group of degree 3 over Finite Field of size 2) generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] + Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] of (The projective general unitary group of degree 3 over Finite Field of size 2) sage: C3.as_classical_group() - Subgroup of General Unitary Group of degree 2 over Universal Cyclotomic Field with respect to hermitian form + Subgroup with 2 generators ( + [ E(3)^2 0] [ 1 -E(12)^7] + [-E(12)^7 1], [ 0 E(3)^2] + ) of General Unitary Group of degree 2 over Universal Cyclotomic Field with respect to hermitian form [-E(12)^7 + E(12)^11 -1] - [ -1 -E(12)^7 + E(12)^11] with 2 generators ( - [ E(3)^2 0] [ 1 -E(12)^7] - [-E(12)^7 1], [ 0 E(3)^2] - ) + [ -1 -E(12)^7 + E(12)^11] TESTS: @@ -610,8 +586,6 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): - [Ass1978]_ """ - - Element = CubicBraidElement ########################################################################################### @@ -652,7 +626,6 @@ def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): elif cbg_type == CubicBraidGroupType.AssionS: rels.append(b[i+2]*b[i]*t[i+1]*b[i]*ti[i+1]*t[i+2]*t[i+1]*b[i]*ti[i+1]*ti[i+2]) - FinitelyPresentedGroup.__init__(self, free_group, tuple(rels)) self._free_group = free_group @@ -669,11 +642,6 @@ def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): return - - - - - def _repr_(self): r""" Return a string representation. @@ -688,11 +656,10 @@ def _repr_(self): return "Assion group on %s strands of type %s"%(self.strands() ,self._cbg_type.value) - # ------------------------------------------------------------------------------- # Methods for test_suite # ------------------------------------------------------------------------------- - def _internal_test_attached_group(self, AttGroup, tester): + def _internal_test_attached_group(self, attached_group, tester): r""" It tests conversion maps from ``self`` to the given attached Group which must have been defined using the :meth:`as_classical_group`, @@ -701,13 +668,13 @@ def _internal_test_attached_group(self, AttGroup, tester): INPUT: - - ``AttGroup`` -- attached group to be tested as specified above. + - ``attached_group`` -- attached group to be tested as specified above. """ elem = self.an_element() - AttElem = AttGroup(elem) + att_grp_elem = attached_group(elem) if self.is_finite() and self.strands() <= 7: # not realistic for larger number of strands - AttElemBack= self(AttElem) - tester.assert_(AttElemBack == elem) + att_grp_elem_back= self(att_grp_elem) + tester.assert_(att_grp_elem_back == elem) return @@ -720,9 +687,9 @@ def _test_classical_group(self, **options): - coercion maps to and from classical group exist and are inverse to each other. """ tester = self._tester(**options) - Cl = self.as_classical_group() + classic_grp = self.as_classical_group() if self.is_finite(): - self._internal_test_attached_group(Cl, tester) + self._internal_test_attached_group(classic_grp, tester) return @@ -736,8 +703,8 @@ def _test_permutation_group(self, **options): """ if self.is_finite(): tester = self._tester(**options) - Perm = self.as_permutation_group() - self._internal_test_attached_group(Perm, tester) + permgrp = self.as_permutation_group() + self._internal_test_attached_group(permgrp, tester) return @@ -755,19 +722,19 @@ def _test_matrix_group(self, **options): self._internal_test_attached_group(MatDEF, tester) if self._cbg_type != CubicBraidGroupType.AssionU or self.strands() < 5 : # not well defined elsewise - MatF3 = self.as_matrix_group(rootBur=r63) - self._internal_test_attached_group(MatF3, tester) + matrix_grpF3 = self.as_matrix_group(root_bur=r63) + self._internal_test_attached_group(matrix_grpF3, tester) if self._cbg_type != CubicBraidGroupType.AssionS or self.strands() < 5 : # not well defined elsewise - MatF4 = self.as_matrix_group(rootBur=r64) - self._internal_test_attached_group(MatF4, tester) + matrix_grpF4 = self.as_matrix_group(root_bur=r64) + self._internal_test_attached_group(matrix_grpF4, tester) if self.strands() < 5 or self._cbg_type == CubicBraidGroupType.Coxeter: - MatF5 = self.as_matrix_group(characteristic=5) - self._internal_test_attached_group(MatF5, tester) + matrix_grpF5 = self.as_matrix_group(characteristic=5) + self._internal_test_attached_group(matrix_grpF5, tester) - MatF7 = self.as_matrix_group(Domain=GF(7)) - self._internal_test_attached_group(MatF7, tester) + matrix_grpF7 = self.as_matrix_group(domain=GF(7)) + self._internal_test_attached_group(matrix_grpF7, tester) return @@ -783,8 +750,8 @@ def _test_reflection_group(self, **options): from sage.combinat.root_system.reflection_group_real import is_chevie_available if is_chevie_available(): tester = self._tester(**options) - Refl = self.as_reflection_group() - self._internal_test_attached_group(Refl, tester) + reflgrp = self.as_reflection_group() + self._internal_test_attached_group(reflgrp, tester) return @@ -793,7 +760,6 @@ def _test_reflection_group(self, **options): # local utility-methods # ------------------------------------------------------------------------------- # ------------------------------------------------------------------------------- - def _create_classical_realization(self, just_embedded=False): r""" Internal method to create the classical groups attached to ``self``. @@ -811,7 +777,7 @@ def _create_classical_realization(self, just_embedded=False): # ------------------------------------------------------------------------------- # Set up all incrediences of the classical Assion group (generic part) # ------------------------------------------------------------------------------- - def set_classical_realization(self, BaseGroup, ProjGroup, centralizing_matrix, transvec_matrices): + def set_classical_realization(self, base_group, proj_group, centralizing_matrix, transvec_matrices): r""" Internal method to create classical group for Assion groups. @@ -821,8 +787,8 @@ def set_classical_realization(self, BaseGroup, ProjGroup, centralizing_matrix, t INPUT: - - ``BaseGroup`` -- The symplectic or unitary groups Sp(m,3) resp. GU(m,2). - - ``ProjGroup`` -- The corresponding projeective group of BaseGroup. + - ``base_group`` -- The symplectic or unitary groups Sp(m,3) resp. GU(m,2). + - ``proj_group`` -- The corresponding projeective group of base_group. - ``centralizing_matrix`` -- The centralizing matrix according to Assion. - ``transvec_matrices`` -- List of transvection matrices according to Assion. @@ -835,7 +801,7 @@ def set_classical_realization(self, BaseGroup, ProjGroup, centralizing_matrix, t # ------------------------------------------------------------------------------ # Setting the List of Braid Images # ------------------------------------------------------------------------------ - im_gens = [BaseGroup(m) for m in transvec_matrices] + im_gens = [base_group(m) for m in transvec_matrices] # ------------------------------------------------------------------------------ # By the work of Assion no check on the group homomorphism is needed, at all. @@ -849,42 +815,39 @@ def set_classical_realization(self, BaseGroup, ProjGroup, centralizing_matrix, t # ------------------------------------------------------------------------------ # Do the projective group realization if needed # ------------------------------------------------------------------------------ - Embedding = self._classical_embedding - ClassicalGroup = None - if ProjGroup is None: - ClassicalGroup = BaseGroup - homToClassic = self.hom(im_gens, check=check) - ClassicalGroup.register_conversion(homToClassic) + embedding = self._classical_embedding + classical_group = None + if proj_group is None: + classical_group = base_group + hom_to_classic = self.hom(im_gens, check=check) + classical_group.register_conversion(hom_to_classic) else: - if Embedding is None: + if embedding is None: im_gens.pop() - Embedding = BaseGroup.subgroup(im_gens, check=check) - Embedding.register_conversion(self.hom(Embedding.gens(), check=check)) - homToBase = self.hom(im_gens, check=check, codomain=BaseGroup) - BaseGroup.register_conversion(homToBase) - + embedding = base_group.subgroup(im_gens, check=check) + embedding.register_conversion(self.hom(embedding.gens(), check=check)) + hom_to_base = self.hom(im_gens, check=check, codomain=base_group) + base_group.register_conversion(hom_to_base) if not just_embedded: transvec_matrices.pop() - natHom = BaseGroup.hom(ProjGroup.gens(), check=check) - centralizing_element = natHom(centralizing_matrix) - ClassicalGroupGens = [natHom(m) for m in transvec_matrices] - ClassicalGroup = ProjGroup.subgroup(ClassicalGroupGens, canonicalize=False) - homToClassic = self.hom(ClassicalGroup.gens(), check=check) - ClassicalGroup.register_conversion(homToClassic) + nat_hom = base_group.hom(proj_group.gens(), check=check) + centralizing_element = nat_hom(centralizing_matrix) + classical_group_gens = [nat_hom(m) for m in transvec_matrices] + classical_group = proj_group.subgroup(classical_group_gens, canonicalize=False) + hom_to_classic = self.hom(classical_group.gens(), check=check) + classical_group.register_conversion(hom_to_classic) # ------------------------------------------------------------------------------ # register constructed items # ------------------------------------------------------------------------------ - self._classical_group = ClassicalGroup - self._classical_base_group = BaseGroup - self._classical_invariant_form = BaseGroup.invariant_form() + self._classical_group = classical_group + self._classical_base_group = base_group + self._classical_invariant_form = base_group.invariant_form() self._centralizing_matrix = centralizing_matrix self._centralizing_element = centralizing_element - self._classical_embedding = Embedding + self._classical_embedding = embedding return - - # ------------------------------------------------------------------------------- # local methods to set up the classical group (spezific part) # ------------------------------------------------------------------------------- @@ -910,14 +873,16 @@ def create_sympl_realization(self, m): n = self.strands() from sage.groups.matrix_gps.symplectic import Sp - BaseGroup = Sp(m, 3) - ProjGroup = None + base_group = Sp(m, 3) + proj_group = None if m == n: from sage.groups.perm_gps.permgroup_named import PSp - ProjGroup = PSp(m, 3) + proj_group = PSp(m, 3) - bform = BaseGroup.invariant_form() + bform = base_group.invariant_form() bas = bform.column_space().basis() + F = bform.base_ring() + if m % 2 == 0: mhalf = m/2 else: @@ -953,14 +918,12 @@ def transvec2mat(v, bas=bas, bform=bform, fact=1): # setting the centralizing matrix for the case of projective group realizaton # ------------------------------------------------------------------------------ centralizing_vector = xbas[mhalf-1] - centralizing_matrix = BaseGroup(transvec2mat(centralizing_vector, fact=1)) + centralizing_matrix = base_group(transvec2mat(centralizing_vector, fact=1)) transvec_matrices = [transvec2mat(v) for v in transvections] - set_classical_realization(self, BaseGroup, ProjGroup, centralizing_matrix, transvec_matrices) + set_classical_realization(self, base_group, proj_group, centralizing_matrix, transvec_matrices) return - - # ------------------------------------------------------------------------------- # Case for unitary groups # ------------------------------------------------------------------------------- @@ -984,16 +947,16 @@ def create_unitary_realization(self, m): n = self.strands() from sage.groups.matrix_gps.unitary import GU - BaseGroup = GU(m, 2) - ProjGroup = None + base_group = GU(m, 2) + proj_group = None if m == n: from sage.groups.perm_gps.permgroup_named import PGU - ProjGroup = PGU(m, 2) + proj_group = PGU(m, 2) - bform = BaseGroup.invariant_form() + bform = base_group.invariant_form() bas = bform.column_space().basis() - BasR = bform.base_ring() - vA = BasR.gen() + F = bform.base_ring() + a = F.gen() if m % 3 == 1: mthird = (m-1)/3 @@ -1011,7 +974,7 @@ def create_unitary_realization(self, m): if 2*i == m-1: xbas.append(bas[i]) else: - xbas.append(vA*bas[i] + vA.frobenius()*bas[m-1 -i]) + xbas.append(a*bas[i] + a.frobenius()*bas[m-1 -i]) # ----------------------------------------------------------- # computing the List of transvection vectors according to @@ -1033,30 +996,28 @@ def create_unitary_realization(self, m): # matrix. # ----------------------------------------------------------- from sage.matrix.constructor import matrix - def transvec2mat(v, bas=bas, bform=bform, fact=vA): + def transvec2mat(v, bas=bas, bform=bform, fact=a): # note x does not change under conjugation, since it belongs to standard basis t = [x + fact *(x * bform * v.conjugate()) * v for x in bas] - return matrix(bform.base_ring(), t) + return matrix(F, t) # ------------------------------------------------------------------------------ # setting the centralizing matrix for the case of projective group realizaton. # ------------------------------------------------------------------------------ centralizing_vector = xbas[m-2]+xbas[m-1] - centralizing_matrix = BaseGroup(transvec2mat(centralizing_vector, fact=1)) + centralizing_matrix = base_group(transvec2mat(centralizing_vector, fact=1)) transvec_matrices = [transvec2mat(v) for v in transvections] - set_classical_realization(self, BaseGroup, ProjGroup, centralizing_matrix, transvec_matrices) + set_classical_realization(self, base_group, proj_group, centralizing_matrix, transvec_matrices) return - #---------------------------------------------------------------------------------------------------------- #---------------------------------------------------------------------------------------------------------- # local functions declaration section finishes here #---------------------------------------------------------------------------------------------------------- #---------------------------------------------------------------------------------------------------------- - # ------------------------------------------------------------------------------- # initialization of constants # ------------------------------------------------------------------------------- @@ -1092,16 +1053,14 @@ def transvec2mat(v, bas=bas, bform=bform, fact=vA): # finally: Coxeters Realization is the unitary Burau representation of Squier for s = ~z12 # ----------------------------------------------------------------------------------------------- UCF = UniversalCyclotomicField(); z12 = UCF.gen(12) - ClassicalGroup = self.as_matrix_group(rootBur=~z12, Domain=UCF, reduced='unitary') - self._classical_group = ClassicalGroup - self._classical_base_group = ClassicalGroup - self._classical_embedding = ClassicalGroup + classical_group = self.as_matrix_group(root_bur=~z12, domain=UCF, reduced='unitary') + self._classical_group = classical_group + self._classical_base_group = classical_group + self._classical_embedding = classical_group if self._classical_invariant_form is None: - self._classical_invariant_form = ClassicalGroup.ambient().invariant_form() + self._classical_invariant_form = classical_group.ambient().invariant_form() return - - def _element_constructor_(self, x, **kwds): r""" Extensions to the _element constructor of :class:`FinitelyPresentedGroup`: @@ -1144,17 +1103,12 @@ def _element_constructor_(self, x, **kwds): return super(CubicBraidGroup_class, self)._element_constructor_(x) - - - ####################################################################################################################### # ---------------------------------------------------------------------------------- # public methods # ---------------------------------------------------------------------------------- ####################################################################################################################### - - # --------------------------------------------------------------------------------------------------------------------- # strands # --------------------------------------------------------------------------------------------------------------------- @@ -1173,8 +1127,6 @@ def strands(self): return self._nstrands - - # ---------------------------------------------------------------------------------- # braid_group # ---------------------------------------------------------------------------------- @@ -1220,34 +1172,25 @@ def braid_group(self): return self._braid_group - - - - - - - - - # ---------------------------------------------------------------------------------- # as_matrix_group # ---------------------------------------------------------------------------------- - def as_matrix_group(self, rootBur=None, Domain=None, characteristic=None, var='t', reduced=False): + def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var='t', reduced=False): r""" Creates an epimorphic image of ``self`` as a matrix group by use of the burau representation. INPUT (all arguments are optional by keyword): - - ``rootBur`` -- six (resp. twelfth) root of unity in some field + - ``root_bur`` -- six (resp. twelfth) root of unity in some field (default root of unity over `\QQ`). - - ``Domain`` -- base_ring for the burau matrix (default is Cyclotomic - Field of order 3 and degree 2, resp. the domain of `rootBur` if given). + - ``domain`` -- base_ring for the burau matrix (default is Cyclotomic + Field of order 3 and degree 2, resp. the domain of `root_bur` if given). - ``characteristic`` - integer giving the characteristic of the - domain (default is 0 or the characteristic of `Domain` if given) - If none of the keywords `rootBur`, `Domain` and `characteristic` is + domain (default is 0 or the characteristic of `domain` if given) + If none of the keywords `root_bur`, `domain` and `characteristic` is given the default characteristic is 3 (resp. 2) if ``self`` is of ``cbg_type CubicBraidGroupType.AssionS`` (resp. ``CubicBraidGroupType.AssionU``). - - ``var`` -- string used for the indeterminant name in case `rootBur` + - ``var`` -- string used for the indeterminant name in case `root_bur` must be constructed in a splitting field. - ``reduced`` -- boolean (default: ``False``); for more information see the documentation of :meth:`burau_matrix` of :class:`Braid`. @@ -1303,7 +1246,7 @@ def as_matrix_group(self, rootBur=None, Domain=None, characteristic=None, var='t sage: U5Mch3 = U5.as_matrix_group(characteristic=3) Traceback (most recent call last): ... - ValueError: Burau representation does not factor through the relations + ValueError: burau representation does not factor through the relations """ # ------------------------------------------------------------------------------- # define matrix group by generators using the Burau representation @@ -1311,9 +1254,9 @@ def as_matrix_group(self, rootBur=None, Domain=None, characteristic=None, var='t # ------------------------------------------------------------------------------- # adaption of default options for Assion groups on more then 4 stands - # (in order to achive the maps beeing well defined) + # (in order to achieve the maps beeing well defined) # ------------------------------------------------------------------------------- - if rootBur is None and Domain is None and characteristic is None: + if root_bur is None and domain is None and characteristic is None: if self._cbg_type == CubicBraidGroupType.AssionS: characteristic = 3 elif self._cbg_type == CubicBraidGroupType.AssionU: @@ -1326,52 +1269,48 @@ def as_matrix_group(self, rootBur=None, Domain=None, characteristic=None, var='t if reduced == 'unitary': unitary = True - genList =[] - for braidGen in self.gens(): - burMat = braidGen.burau_matrix(rootBur=rootBur, Domain=Domain, characteristic=characteristic, + gen_list =[] + for braid_gen in self.gens(): + bur_mat = braid_gen.burau_matrix(root_bur=root_bur, domain=domain, characteristic=characteristic, var=var, reduced=reduced) if unitary: - burMat, burMatAd, hermForm = burMat + bur_mat, bur_mat_ad, herm_form = bur_mat - if Domain is None: - Domain = burMat.base_ring() + if domain is None: + domain = bur_mat.base_ring() - genList.append(burMat) + gen_list.append(bur_mat) - if unitary and hermForm.is_singular(): + if unitary and herm_form.is_singular(): unitary = False # since a degenertated hermitian form doesn't define a unitary group if self._classical_invariant_form is None: - self._classical_invariant_form = hermForm + self._classical_invariant_form = herm_form if unitary: from sage.rings.finite_rings.finite_field_base import is_FiniteField from sage.groups.matrix_gps.unitary import GU - d, d = hermForm.dimensions() - if is_FiniteField(Domain): - BaseGroup = GU(d, Domain, var=Domain.gen(), invariant_form=hermForm) + d, d = herm_form.dimensions() + if is_FiniteField(domain): + base_group = GU(d, domain, var=domain.gen(), invariant_form=herm_form) else: - BaseGroup = GU(d, Domain, invariant_form=hermForm) + base_group = GU(d, domain, invariant_form=herm_form) - MatGroup = BaseGroup.subgroup(genList) + matrix_group = base_group.subgroup(gen_list) else: from sage.groups.matrix_gps.finitely_generated import MatrixGroup - MatGroup = MatrixGroup(genList) + matrix_group = MatrixGroup(gen_list) # ------------------------------------------------------------------------------- - # check if there is a well defined group homomorphism to MatGroup - # Register map from ``self`` to MatGroup. + # check if there is a well defined group homomorphism to matrix_group + # Register map from ``self`` to matrix_group. # Since GAP' check is very expansive (on time and memory), the check is performed # here. # ------------------------------------------------------------------------------- - homToMat = self.hom(MatGroup.gens(), check=False) - if not all( homToMat(rel).is_one() for rel in self.relations()): - raise ValueError("Burau representation does not factor through the relations") - MatGroup.register_conversion(homToMat) - return MatGroup - - - - + hom_to_mat = self.hom(matrix_group.gens(), check=False) + if not all( hom_to_mat(rel).is_one() for rel in self.relations()): + raise ValueError("burau representation does not factor through the relations") + matrix_group.register_conversion(hom_to_mat) + return matrix_group # ---------------------------------------------------------------------------------- @@ -1410,7 +1349,7 @@ def as_permutation_group(self, use_classical=True): True """ if not self.is_finite(): - raise ValueError('Cubic braid group is infinite!') + raise ValueError('cubic braid group is infinite!') if use_classical: CG = self.as_classical_group() @@ -1425,15 +1364,11 @@ def as_permutation_group(self, use_classical=True): img_gens = PG.gens() img_gens = [PG(gen) for gen in img_gens] - homToPerm = self.hom(img_gens) - PG.register_conversion(homToPerm) + hom_to_perm = self.hom(img_gens) + PG.register_conversion(hom_to_perm) return PG - - - - # ---------------------------------------------------------------------------------- # as_classical_group # ---------------------------------------------------------------------------------- @@ -1466,15 +1401,13 @@ def as_classical_group(self, embedded=False): sage: U3 = AssionGroupU(3) sage: U3Cl = U3.as_classical_group(); U3Cl - Subgroup of (The projective general unitary group of degree 3 over Finite Field of size 2) generated by - [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), - (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] + Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] of (The projective general unitary group of degree 3 over Finite Field of size 2) sage: U3Clemb = U3.as_classical_group(embedded=True); U3Clemb - Matrix group over Finite Field in a of size 2^2 with 2 generators ( + Subgroup with 2 generators ( [0 0 a] [a + 1 a a] - [0 1 0] [ a a + 1 a] - [a 0 a], [ a a a + 1] - ) + [0 1 0] [ a a + 1 a] + [a 0 a], [ a a a + 1] + ) of General Unitary Group of degree 3 over Finite Field in a of size 2^2 sage: u = U3([-2,1,-2,1]); u (u1^-1*u0)^2 sage: uCl = U3Cl(u); uCl @@ -1494,20 +1427,19 @@ def as_classical_group(self, embedded=False): True sage: C4 = CubicBraidGroup(4) sage: C4Cl = C4.as_classical_group(); C4Cl - Subgroup of General Unitary Group of degree 3 over Universal Cyclotomic Field with respect to hermitian form - [-E(12)^7 + E(12)^11 -1 0] - [ -1 -E(12)^7 + E(12)^11 -1] - [ 0 -1 -E(12)^7 + E(12)^11] with 3 generators ( - [ E(3)^2 0 0] [ 1 -E(12)^7 0] - [-E(12)^7 1 0] [ 0 E(3)^2 0] - [ 0 0 1], [ 0 -E(12)^7 1], + Subgroup with 3 generators ( + [ E(3)^2 0 0] [ 1 -E(12)^7 0] + [-E(12)^7 1 0] [ 0 E(3)^2 0] + [ 0 0 1], [ 0 -E(12)^7 1], - [ 1 0 0] - [ 0 1 -E(12)^7] - [ 0 0 E(3)^2] - ) + [ 1 0 0] + [ 0 1 -E(12)^7] + [ 0 0 E(3)^2] + ) of General Unitary Group of degree 3 over Universal Cyclotomic Field with respect to hermitian form + [-E(12)^7 + E(12)^11 -1 0] + [ -1 -E(12)^7 + E(12)^11 -1] + [ 0 -1 -E(12)^7 + E(12)^11] """ - # ------------------------------------------------------------------------------- # create the classical group if not already done # ------------------------------------------------------------------------------- @@ -1533,10 +1465,6 @@ def as_classical_group(self, embedded=False): raise ValueError("no classical embedding defined") - - - - # ---------------------------------------------------------------------------------- # as_refection_group # ---------------------------------------------------------------------------------- @@ -1603,7 +1531,6 @@ def as_reflection_group(self): # 4 strands -> G25 # 5 strands -> G32 # ------------------------------------------------------------------------------- - from sage.combinat.root_system.reflection_group_real import is_chevie_available if not is_chevie_available(): raise ImportError("the GAP3 package 'chevie' is needed to obtain the corresponding reflection groups") @@ -1614,23 +1541,22 @@ def as_reflection_group(self): # ------------------------------------------------------------------------------- # define reflection group assiossiated to self # ------------------------------------------------------------------------------- - ReflectGroup = None + reflection_group = None from sage.combinat.root_system.reflection_group_real import ReflectionGroup if self.strands() == 2: - ReflectGroup = ReflectionGroup([2 ,1 ,1]) + reflection_group = ReflectionGroup([2 ,1 ,1]) elif self.strands() == 3: - ReflectGroup = ReflectionGroup(4) + reflection_group = ReflectionGroup(4) elif self.strands() == 4: - ReflectGroup = ReflectionGroup(25) + reflection_group = ReflectionGroup(25) elif self.strands() == 5: - ReflectGroup = ReflectionGroup(32) - - homToRefl = self.hom(ReflectGroup.gens()) - ReflectGroup.register_conversion(homToRefl) - return ReflectGroup + reflection_group = ReflectionGroup(32) + hom_to_refl = self.hom(reflection_group.gens()) + reflection_group.register_conversion(hom_to_refl) + return reflection_group # ---------------------------------------------------------------------------------- @@ -1696,8 +1622,6 @@ def classical_invariant_form(self): return self._classical_invariant_form - - # ---------------------------------------------------------------------------------- # centralizing element in the classical symplectic resp. unitary group # ---------------------------------------------------------------------------------- @@ -1729,7 +1653,7 @@ def centralizing_element(self, embedded=False): sage: U3 = AssionGroupU(3); U3 Assion group on 3 strands of type U sage: U3Cl = U3.as_classical_group(); U3Cl - Subgroup of (The projective general unitary group of degree 3 over Finite Field of size 2) generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] + Subgroup generated by [(1,7,6)(3,19,14)(4,15,10)(5,11,18)(12,16,20), (1,12,13)(2,15,19)(4,9,14)(5,18,8)(6,21,16)] of (The projective general unitary group of degree 3 over Finite Field of size 2) sage: c = U3.centralizing_element(); c (1,16)(2,9)(3,10)(4,19)(6,12)(7,20)(13,21)(14,15) sage: c in U3Cl @@ -1846,22 +1770,18 @@ def cubic_braid_subgroup(self, nstrands = None): sage: U3s.ambient() == U5 True """ - if nstrands is None: nstrands = self.strands() -1 n = self.strands() - try: - nstrands = Integer(nstrands) - except: - raise TypeError("nstrands must be an integer") + nstrands = Integer(nstrands) if nstrands >= n or nstrands <= 0: raise ValueError("nstrands must be positive and less than %s" %(self.strands())) - Gens = self.gens() - GensRed = tuple([Gens[i] for i in range(nstrands -1)]) - subgrp = CubicBraidGroup(names=GensRed, cbg_type=self._cbg_type) + gens = self.gens() + gens_red = tuple([gens[i] for i in range(nstrands -1)]) + subgrp = CubicBraidGroup(names=gens_red, cbg_type=self._cbg_type) subgrp._ambient = self return subgrp From 76a845e05e5ffe45b2f0203a6076691640e8b8bf Mon Sep 17 00:00:00 2001 From: Sebastian Oehms Date: Sat, 30 Mar 2019 08:29:45 +0100 Subject: [PATCH 03/10] 27302: fixed doctests --- src/sage/groups/cubic_braid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index e8e878eaa08..c5369fee536 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -556,7 +556,7 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): Subgroup with 2 generators ( [ E(3)^2 0] [ 1 -E(12)^7] [-E(12)^7 1], [ 0 E(3)^2] - ) of General Unitary Group of degree 2 over Universal Cyclotomic Field with respect to hermitian form + ) of General Unitary Group of degree 2 over Universal Cyclotomic Field with respect to positive definite hermitian form [-E(12)^7 + E(12)^11 -1] [ -1 -E(12)^7 + E(12)^11] @@ -1435,7 +1435,7 @@ def as_classical_group(self, embedded=False): [ 1 0 0] [ 0 1 -E(12)^7] [ 0 0 E(3)^2] - ) of General Unitary Group of degree 3 over Universal Cyclotomic Field with respect to hermitian form + ) of General Unitary Group of degree 3 over Universal Cyclotomic Field with respect to positive definite hermitian form [-E(12)^7 + E(12)^11 -1 0] [ -1 -E(12)^7 + E(12)^11 -1] [ 0 -1 -E(12)^7 + E(12)^11] From 3402ba75d5159fb4f8b1c4f94a6d7ac25bee99ed Mon Sep 17 00:00:00 2001 From: Sebastian Oehms Date: Sat, 30 Mar 2019 18:01:44 +0100 Subject: [PATCH 04/10] 27302: python3 fixes --- src/sage/groups/cubic_braid.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index c5369fee536..975ce44ebf7 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -411,7 +411,7 @@ def find_root(domain): except ValueError: raise ValueError('characteristic must be in integer') - if characteristic <> 0 and not characteristic.is_prime(): + if characteristic != 0 and not characteristic.is_prime(): raise ValueError('characteristic must be a prime') if characteristic == 0: if unitary: @@ -423,19 +423,19 @@ def find_root(domain): root_bur = find_root(domain) domain = root_bur.parent() - else: # domain <> None + else: # domain != None if characteristic is None: characteristic = domain.characteristic() - elif characteristic <> domain.characteristic(): + elif characteristic != domain.characteristic(): raise ValueError('characteristic of domain does not match given characteristic') root_bur = find_root(domain) - else: # root_bur <> None + else: # root_bur != None if domain is None: domain = root_bur.parent() if characteristic is None: characteristic = domain.characteristic() - elif characteristic <> domain.characteristic(): + elif characteristic != domain.characteristic(): raise ValueError('characteristic of domain does not match given characteristic') if 1 not in domain: From 4b967409c6e7be2871f355ce370c19cb0211a815 Mon Sep 17 00:00:00 2001 From: Sebastian Oehms Date: Mon, 1 Apr 2019 21:04:22 +0200 Subject: [PATCH 05/10] 27302: further corrections according to patchbot hints --- src/sage/groups/cubic_braid.py | 66 +++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 975ce44ebf7..33eeb8904a4 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -423,14 +423,14 @@ def find_root(domain): root_bur = find_root(domain) domain = root_bur.parent() - else: # domain != None + else: # domain is not None if characteristic is None: characteristic = domain.characteristic() elif characteristic != domain.characteristic(): raise ValueError('characteristic of domain does not match given characteristic') root_bur = find_root(domain) - else: # root_bur != None + else: # root_bur is not!= None if domain is None: domain = root_bur.parent() if characteristic is None: @@ -649,6 +649,13 @@ def _repr_(self): OUTPUT: String describing ``self``. + + EXAMPLES:: + + sage: CubicBraidGroup(2) + Cubic Braid group on 2 strands + sage: AssionGroupU(2) + Assion group on 2 strands of type U """ if self._cbg_type == CubicBraidGroupType.Coxeter: return "Cubic Braid group on %s strands"%(self.strands()) @@ -669,6 +676,13 @@ def _internal_test_attached_group(self, attached_group, tester): INPUT: - ``attached_group`` -- attached group to be tested as specified above. + + EXAMPLES:: + + sage: CBG2 = CubicBraidGroup(2) + sage: tester = CBG2._tester() + sage: CBG2M = CBG2.as_matrix_group() + sage: CBG2._internal_test_attached_group(CBG2M, tester) """ elem = self.an_element() att_grp_elem = attached_group(elem) @@ -685,6 +699,11 @@ def _test_classical_group(self, **options): The following is checked: - construction of classical group was faithfull. - coercion maps to and from classical group exist and are inverse to each other. + + EXAMPLES:: + + sage: CBG2 = CubicBraidGroup(2) + sage: CBG2._test_classical_group() """ tester = self._tester(**options) classic_grp = self.as_classical_group() @@ -700,6 +719,11 @@ def _test_permutation_group(self, **options): The following is checked: - construction of permutation group was faithfull. - coercion maps to and from permutation group exist and are inverse to each other. + + EXAMPLES:: + + sage: CBG2 = CubicBraidGroup(2) + sage: CBG2._test_permutation_group() """ if self.is_finite(): tester = self._tester(**options) @@ -715,6 +739,11 @@ def _test_matrix_group(self, **options): The following is checked: - construction of matrix group was faithfull in several cases. - coercion maps to and from matrix group exist. + + EXAMPLES:: + + sage: CBG2 = CubicBraidGroup(2) + sage: CBG2._test_matrix_group() """ tester = self._tester(**options) F3 = GF(3); r63 = F3(2); F4 = GF(4); r64 = F4.gen() @@ -745,6 +774,11 @@ def _test_reflection_group(self, **options): The following is checked: - construction of reflection group was faithfull. - coercion maps to and from reflection group exist and are inverse to each other. + + EXAMPLES:: + + sage: CBG2 = CubicBraidGroup(2) + sage: CBG2._test_reflection_group() """ if self._cbg_type == CubicBraidGroupType.Coxeter and self.is_finite() and self.strands() > 2: from sage.combinat.root_system.reflection_group_real import is_chevie_available @@ -772,6 +806,23 @@ def _create_classical_realization(self, just_embedded=False): - self._centralizing_matrix for AssionGroup: element in classical base group commuting with self. - self._centralizing_element image under natural map of the former one in the projective classical group. - self._classical_embedding as subgroup of classical base group (if different from classical group). + + EXAMPLES:: + + sage: AU2 = AssionGroupU(2) + sage: AU2._classical_group is None + True + sage: AU2._classical_embedding is None + True + sage: AU2._classical_invariant_form is None + True + sage: AU2._create_classical_realization() + sage: AU2._classical_group + General Unitary Group of degree 1 over Finite Field in a of size 2^2 + sage: AU2._classical_embedding is AU2._classical_group + True + sage: AU2._classical_invariant_form + [1] """ # ------------------------------------------------------------------------------- @@ -821,6 +872,7 @@ def set_classical_realization(self, base_group, proj_group, centralizing_matrix, classical_group = base_group hom_to_classic = self.hom(im_gens, check=check) classical_group.register_conversion(hom_to_classic) + embedding = classical_group else: if embedding is None: im_gens.pop() @@ -881,7 +933,6 @@ def create_sympl_realization(self, m): bform = base_group.invariant_form() bas = bform.column_space().basis() - F = bform.base_ring() if m % 2 == 0: mhalf = m/2 @@ -1071,7 +1122,7 @@ def _element_constructor_(self, x, **kwds): -- constructing element from an element of the attached permutation group -- constructing element from an element of the attached refelction group - INPUT:: + INPUT: - ``x`` -- can be one of the following: -- an instance of the element class of ``self`` (but possible to a different parent). @@ -1729,6 +1780,13 @@ def order(self): def is_finite(self): r""" Method from :class:`GroupMixinLibGAP` overwriten because of performance reason. + + EXAMPLES:: + + sage: CubicBraidGroup(6).is_finite() + False + sage: AssionGroupS(6).is_finite() + True """ from sage.rings.infinity import infinity return not self.order() is infinity From 1164156b48655b2ef30ec2ef877757a4ee211740 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 2 Apr 2019 21:02:19 +0200 Subject: [PATCH 06/10] 27302: typo and style fixes --- src/doc/en/reference/references/index.rst | 2 +- src/sage/groups/cubic_braid.py | 109 +++++++++++----------- 2 files changed, 54 insertions(+), 57 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index d5c902c2929..2b7a24ed76e 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -976,7 +976,7 @@ REFERENCES: `http://www.math.uconn.edu/~kconrad/blurbs/ `_ .. [Cox1957] \H. S. M. Coxeter: *Factor groups of the braid groups*, Proceedings of the Fourth Candian - Mathematical Congress (Vancover 1957), pp. 95-122. + Mathematical Congress (Vancouver 1957), pp. 95-122. .. [CP2001] John Crisp and Luis Paris. *The solution to a conjecture of Tits on the subgroup generated by the squares of the diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 33eeb8904a4..0c9e45863f4 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -11,7 +11,7 @@ In general these groups have firstly been investigated by Coxeter, H.S.M. in: "Factor groups of the braid groups, Proceedings of the Fourth Canadian -Mathematical Congress (Vancover 1957), pp. 95-122". +Mathematical Congress (Vancouver 1957), pp. 95-122". Coxeter showed, that these groups are finite as long as the number of strands is less than 6 and infinite elsewise. More explicitely the factor @@ -50,10 +50,10 @@ finitely presented groups together with the classical realizations given by the authors. It also contains the conversion maps between the two ways of realization. In addition the user can construct other realizations and -maps to matrix groups with help of the burau representation. In case gap3 +maps to matrix groups with help of the Burau representation. In case gap3 and CHEVIE are installed the reflection groups (via the gap3 interface) -are availlable, too. The methods for all this functionality are -:meth:`as_classical_group`, :meth:`as_matrix_group`, :meth:`as_permutatopn_group` +are available, too. The methods for all this functionality are +:meth:`as_classical_group`, :meth:`as_matrix_group`, :meth:`as_permutation_group` and :meth:`as_reflection_group`. @@ -114,7 +114,7 @@ class CubicBraidGroupType(Enum): ############################################################################## def CubicBraidGroup(n=None, names='c', cbg_type=CubicBraidGroupType.Coxeter): r""" - Constructs cubic braid groups as instance of :class:`CubicBraidGroup_class`. + Construct cubic braid groups as instance of :class:`CubicBraidGroup_class`. INPUT: @@ -126,8 +126,8 @@ def CubicBraidGroup(n=None, names='c', cbg_type=CubicBraidGroupType.Coxeter): ``'c'``). The generator names or name prefix. - ``cbg_type`` -- (optional keyword, default = CubicBraidGroupType.Coxeter) - is passed to the corresponding keyword argument of the constructor of - :class:`CubicBraidGroup_class`. + of enum type :class:`CubicBraidGroupType` is passed to the corresponding + keyword argument of the constructor of :class:`CubicBraidGroup_class`. EXAMPLES:: @@ -167,7 +167,7 @@ def CubicBraidGroup(n=None, names='c', cbg_type=CubicBraidGroupType.Coxeter): # ---------------------------------------------------------------------------------- def AssionGroupS(n=None, names='s'): r""" - Constructs cubic braid groups as instance of :class:`CubicBraidGroup_class` which + Construct cubic braid groups as instance of :class:`CubicBraidGroup_class` which have been investigated by J.Assion using the notation S(m). This function is a short hand cut for :func:`CubicBraidGroup` setting ``cbg_type=CubicBraidGroupType.AssionS`` and default ``names='s'``. @@ -197,7 +197,7 @@ def AssionGroupS(n=None, names='s'): def AssionGroupU(n=None, names='u'): r""" - Constructs cubic braid groups as instance of :class:`CubicBraidGroup_class` which + Construct cubic braid groups as instance of :class:`CubicBraidGroup_class` which have been investigated by J.Assion using the notation U(m). This function is a short hand cut for :func:`CubicBraidGroup` setting ``cbg_type=CubicBraidGroupType.AssionU`` and default ``names='u'``. @@ -284,7 +284,7 @@ def burau_matrix(self, root_bur = None, domain = None, characteristic = None, va - ``root_bur`` -- six (resp. twelfth) root of unity in some field (default root of unity over `\QQ`). - - ``domain`` -- base_ring for the burau matrix (default is Cyclotomic + - ``domain`` -- base_ring for the Burau matrix (default is Cyclotomic Field of order 3 and degree 2, resp. the domain of `root_bur` if given). - ``characteristic`` - integer giving the characteristic of the domain (default is 0 or the characteristic of `domain` if given). @@ -298,7 +298,7 @@ def burau_matrix(self, root_bur = None, domain = None, characteristic = None, va The Burau matrix of the cubic braid coset with entries in the domain given by the options. In case the option `reduced='unitary'` - is given a triple consisting of the burau matrix, its adjoined and + is given a triple consisting of the Burau matrix, its adjoined and the hermitain form is returned. EXAMPLES:: @@ -389,7 +389,7 @@ def burau_matrix(self, root_bur = None, domain = None, characteristic = None, va def find_root(domain): min_pol_root_bur = domain[var](min_pol_root_bur_cf) root_list = min_pol_root_bur.roots() - if len(root_list) == 0: + if not(root_list): domain = min_pol_root_bur.splitting_field(min_pol_root_bur.variable_name()) min_pol_root_bur = domain[var](min_pol_root_bur_cf) else: @@ -489,10 +489,10 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): INPUT (to the constructor): - - ``names`` -- (see the documentation of :class:`BraidGroup_class`). - - - ``cbg_type`` -- (keyword, explanation see below). + - ``names`` -- see the corresponding documentation of :class:`BraidGroup_class`. + - ``cbg_type`` -- (optional keyword, default = CubicBraidGroupType.Coxeter, + see explanation below) of enum type :class:`CubicBraidGroupType`. Setting the keyword ``cbg_type`` to one on the values ``CubicBraidGroupType.AssionS`` or ``CubicBraidGroupType.AssionU`` the additional relations due to Assion are added: @@ -517,7 +517,6 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): of :func:`CubicBraidGroup`, :func:`AssionGroupS` and :func:`AssionGroupU` (similar to :func:`BraidGroup` with respect to :class:`BraidGroup_class`). - EXAMPLES:: sage: from sage.groups.cubic_braid import CubicBraidGroupType @@ -560,26 +559,6 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): [-E(12)^7 + E(12)^11 -1] [ -1 -E(12)^7 + E(12)^11] - TESTS: - - sage: C3 = CubicBraidGroup(3) - sage: TestSuite(C3).run() - sage: C4 = CubicBraidGroup(4) - sage: TestSuite(C4).run() # long time - sage: C6 = CubicBraidGroup(6) - sage: TestSuite(C6).run() # long time - sage: S3 = AssionGroupS(3) - sage: TestSuite(S3).run() - sage: S5 = AssionGroupS(5) - sage: TestSuite(S5).run() # long time - sage: U3 = AssionGroupU(3) - sage: TestSuite(U3).run() - sage: U4 = AssionGroupU(4) - sage: TestSuite(U4).run() # long time - sage: U5 = AssionGroupU(5) - sage: TestSuite(U5).run() # long time - - REFERENCES: - [Cox1957]_ @@ -594,6 +573,32 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): """ Python constructor. + + INPUT: + + - ``names`` -- see the corresponding documentation of :class:`BraidGroup_class`. + + - ``cbg_type`` -- (optional keyword, default = CubicBraidGroupType.Coxeter) of enum type + :class:`CubicBraidGroupType` to select the type of the group. + + TESTS:: + + sage: C3 = CubicBraidGroup(3) # indirect doctest + sage: TestSuite(C3).run() + sage: C4 = CubicBraidGroup(4) # indirect doctest + sage: TestSuite(C4).run() # long time + sage: C6 = CubicBraidGroup(6) # indirect doctest + sage: TestSuite(C6).run() # long time + sage: S3 = AssionGroupS(3) # indirect doctest + sage: TestSuite(S3).run() + sage: S5 = AssionGroupS(5) # indirect doctest + sage: TestSuite(S5).run() # long time + sage: U3 = AssionGroupU(3) # indirect doctest + sage: TestSuite(U3).run() + sage: U4 = AssionGroupU(4) # indirect doctest + sage: TestSuite(U4).run() # long time + sage: U5 = AssionGroupU(5) # indirect doctest + sage: TestSuite(U5).run() # long time """ n = Integer(len(names)) if n < 1: @@ -614,13 +619,13 @@ def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): rels = list(self._braid_group.relations()) # than the cubic relation - for i in range(0, n): + for i in range(n): rels.append(b[i]**3) # than Assions relation Satz 2.2 for cbg_type=CubicBraidGroupType.AssionS # and Satz 2.4 for cbg_type=CubicBraidGroupType.AssionU if n > 3: - for i in range(0, n-3): + for i in range(n-3): if cbg_type == CubicBraidGroupType.AssionU: rels.append((t[i]*t[i+2])**3) elif cbg_type == CubicBraidGroupType.AssionS: @@ -934,10 +939,7 @@ def create_sympl_realization(self, m): bform = base_group.invariant_form() bas = bform.column_space().basis() - if m % 2 == 0: - mhalf = m/2 - else: - mhalf = (m-1)/2 + mhalf = m // 2 # ----------------------------------------------------------- # computing a hyperbolic decomposition basis with respect @@ -1009,12 +1011,7 @@ def create_unitary_realization(self, m): F = bform.base_ring() a = F.gen() - if m % 3 == 1: - mthird = (m-1)/3 - elif m % 3 == 2: - mthird = (m-2)/3 - else: - mthird = m/3 + mthird = m // 3 # ----------------------------------------------------------- # computing a orthonormal basis with respect @@ -1234,7 +1231,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' - ``root_bur`` -- six (resp. twelfth) root of unity in some field (default root of unity over `\QQ`). - - ``domain`` -- base_ring for the burau matrix (default is Cyclotomic + - ``domain`` -- base_ring for the Burau matrix (default is Cyclotomic Field of order 3 and degree 2, resp. the domain of `root_bur` if given). - ``characteristic`` - integer giving the characteristic of the domain (default is 0 or the characteristic of `domain` if given) @@ -1297,7 +1294,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' sage: U5Mch3 = U5.as_matrix_group(characteristic=3) Traceback (most recent call last): ... - ValueError: burau representation does not factor through the relations + ValueError: Burau representation does not factor through the relations """ # ------------------------------------------------------------------------------- # define matrix group by generators using the Burau representation @@ -1359,13 +1356,13 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' # ------------------------------------------------------------------------------- hom_to_mat = self.hom(matrix_group.gens(), check=False) if not all( hom_to_mat(rel).is_one() for rel in self.relations()): - raise ValueError("burau representation does not factor through the relations") + raise ValueError("Burau representation does not factor through the relations") matrix_group.register_conversion(hom_to_mat) return matrix_group # ---------------------------------------------------------------------------------- - # Although this method is availlable for finitely presented group + # Although this method is available for finitely presented group # we use the classical group implementation (by performace reason) to get # the permutation_group. # ---------------------------------------------------------------------------------- @@ -1445,7 +1442,7 @@ def as_classical_group(self, embedded=False): Depending on the type of ``self`` and the number of strands an instance of ``Sp(n-1,3)``, ``GU(n-1,2)``, subgroup of ``PSp(n,3), PGU(n,2)`` or a subgroup of ``GU(n-1, UCF)`` (``cbg_type CubicBraidGroupType.Coxeter``) with respect to a certain hermitian form - attached to the burau representation (used by Coxeter and Squier). Here ``UCF`` stands + attached to the Burau representation (used by Coxeter and Squier). Here ``UCF`` stands for the universal cyclotomic field. EXAMPLES:: @@ -1560,7 +1557,7 @@ def as_reflection_group(self): [ E(3)^2 -E(4)] [-E(12)^7 0] - The refelection groups can also be viewed as subgroups of unitary groups + The reflection groups can also be viewed as subgroups of unitary groups over the universal cyclotomic field. Note that the unitary group corresponding to the reflection group is isomorphic but different from the classical group due to different hermitian forms for the unitary groups they live in:: @@ -1615,7 +1612,7 @@ def as_reflection_group(self): # ---------------------------------------------------------------------------------- def classical_invariant_form(self): r""" - Returns the invariant form of the classical realization of ``self``. + Return the invariant form of the classical realization of ``self``. OUTPUT: @@ -1678,7 +1675,7 @@ def classical_invariant_form(self): # ---------------------------------------------------------------------------------- def centralizing_element(self, embedded=False): r""" - Returns the centralizing element defined by the work of Assion + Return the centralizing element defined by the work of Assion (Hilfssatz 1.1.3 and 1.2.3). INPUT (optional): From 46a0134f143615c55c2e436567950517252f960c Mon Sep 17 00:00:00 2001 From: Sebastian Oehms Date: Thu, 4 Apr 2019 22:32:08 +0200 Subject: [PATCH 07/10] 27302: spell-check performed --- src/sage/groups/cubic_braid.py | 94 +++++++++++++++++----------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 0c9e45863f4..c1f477450cd 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -14,7 +14,7 @@ Mathematical Congress (Vancouver 1957), pp. 95-122". Coxeter showed, that these groups are finite as long as the number of -strands is less than 6 and infinite elsewise. More explicitely the factor +strands is less than 6 and infinite else-wise. More explicitly the factor group on three strand braids is isomorphic to `SL(2,3)`, on four strand braids to `GU(3,2)` and on five strand braids to `Sp(4,3) \times C_3`. Today, these finite groups are known as irreducible complex reflection groups @@ -277,7 +277,7 @@ def burau_matrix(self, root_bur = None, domain = None, characteristic = None, va Return the Burau matrix of the cubic braid coset. This method uses the same method belonging to :class:`Braid`, but - reduces the indeterminant to a primitive sixth (resp. twelfth in case + reduces the indeterminate to a primitive sixth (resp. twelfth in case reduced='unitary') root of unity. INPUT (all arguments are optional keywords): @@ -288,7 +288,7 @@ def burau_matrix(self, root_bur = None, domain = None, characteristic = None, va Field of order 3 and degree 2, resp. the domain of `root_bur` if given). - ``characteristic`` - integer giving the characteristic of the domain (default is 0 or the characteristic of `domain` if given). - - ``var`` -- string used for the indeterminant name in case root_bur + - ``var`` -- string used for the indeterminate name in case root_bur must be constructed in a splitting field. - ``reduced`` -- boolean (default: ``False``) or string; for more information see the documentation of :meth:`burau_matrix` of @@ -299,7 +299,7 @@ def burau_matrix(self, root_bur = None, domain = None, characteristic = None, va The Burau matrix of the cubic braid coset with entries in the domain given by the options. In case the option `reduced='unitary'` is given a triple consisting of the Burau matrix, its adjoined and - the hermitain form is returned. + the hermitian form is returned. EXAMPLES:: @@ -478,7 +478,7 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): r""" This class implements factor groups of the Artin braid group mapping their generators to elements of order 3 (see the module header for more - informations on these groups). + information on these groups). These groups are implemented as a particular case of finitely presented groups similar to the :class:`BraidGroup_class`. @@ -507,7 +507,7 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): \end{array} where `t_i = (s_i s_{i+1})^3`. If ``cbg_type == CubicBraidGroupType.Coxeter`` (default) - only the cubic relation on the generators is active (Coxeters case of investigation). + only the cubic relation on the generators is active (Coxeter's case of investigation). Note that for `n = 2, 3, 4` the groups do not differ between the three possible values of cbg_type (as finitely presented groups). But anyway, the instances for ``CubicBraidGroupType.Coxeter, CubicBraidGroupType.AssionS`` and ``CubicBraidGroupType.AssionU`` @@ -610,7 +610,7 @@ def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): self._ident = self._cbg_type.value + self._nstrands.str() self._braid_group = BraidGroup(names) - # internal naming of elements for convinience + # internal naming of elements for convenience b = [free_group([i]) for i in range(1 , n+1)] t = [free_group([i, i+1])**3 for i in range(1 , n)] ti = [free_group([-i, -i-1])**3 for i in range(1 , n)] @@ -622,7 +622,7 @@ def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): for i in range(n): rels.append(b[i]**3) - # than Assions relation Satz 2.2 for cbg_type=CubicBraidGroupType.AssionS + # than Assion's relation Satz 2.2 for cbg_type=CubicBraidGroupType.AssionS # and Satz 2.4 for cbg_type=CubicBraidGroupType.AssionU if n > 3: for i in range(n-3): @@ -639,10 +639,10 @@ def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): # _create_classical_realization # ------------------------------------------------------------------------------------------------ self._classical_group = None # This is the classical Group returned by as_classical_group - self._classical_base_group = None # this only differs for special cases for AssionGroup from the former + self._classical_base_group = None # this only differs for special cases for Assion groups from the former self._classical_invariant_form = None # invariant form of the classical base group self._classical_embedding = None # if self._classical_group different from self._classical_base_group - self._centralizing_matrix = None # for AssionGroup: element in classical base group commuting with self + self._centralizing_matrix = None # for Assion groups: element in classical base group commuting with self self._centralizing_element = None # image under nat. map of the former one in the proj. classical group return @@ -702,7 +702,7 @@ def _test_classical_group(self, **options): Method called by TestSuite. The following is checked: - - construction of classical group was faithfull. + - construction of classical group was faithful. - coercion maps to and from classical group exist and are inverse to each other. EXAMPLES:: @@ -722,7 +722,7 @@ def _test_permutation_group(self, **options): Method called by TestSuite. The following is checked: - - construction of permutation group was faithfull. + - construction of permutation group was faithful. - coercion maps to and from permutation group exist and are inverse to each other. EXAMPLES:: @@ -742,7 +742,7 @@ def _test_matrix_group(self, **options): Method called by TestSuite. The following is checked: - - construction of matrix group was faithfull in several cases. + - construction of matrix group was faithful in several cases. - coercion maps to and from matrix group exist. EXAMPLES:: @@ -755,11 +755,11 @@ def _test_matrix_group(self, **options): MatDEF = self.as_matrix_group() self._internal_test_attached_group(MatDEF, tester) - if self._cbg_type != CubicBraidGroupType.AssionU or self.strands() < 5 : # not well defined elsewise + if self._cbg_type != CubicBraidGroupType.AssionU or self.strands() < 5 : # not well defined else-wise matrix_grpF3 = self.as_matrix_group(root_bur=r63) self._internal_test_attached_group(matrix_grpF3, tester) - if self._cbg_type != CubicBraidGroupType.AssionS or self.strands() < 5 : # not well defined elsewise + if self._cbg_type != CubicBraidGroupType.AssionS or self.strands() < 5 : # not well defined else-wise matrix_grpF4 = self.as_matrix_group(root_bur=r64) self._internal_test_attached_group(matrix_grpF4, tester) @@ -777,7 +777,7 @@ def _test_reflection_group(self, **options): Method called by TestSuite. The following is checked: - - construction of reflection group was faithfull. + - construction of reflection group was faithful. - coercion maps to and from reflection group exist and are inverse to each other. EXAMPLES:: @@ -806,9 +806,9 @@ def _create_classical_realization(self, just_embedded=False): This methods sets the following attributes of ``self``: - self._classical_group This is the classical group returned by as_classical_group method. - - self._classical_base_group this only differs in special cases for AssionGroup from the former. + - self._classical_base_group this only differs in special cases for Assion groups from the former. - self._classical_invariant_form invariant form of the classical base group. - - self._centralizing_matrix for AssionGroup: element in classical base group commuting with self. + - self._centralizing_matrix for Assion groups: element in classical base group commuting with self. - self._centralizing_element image under natural map of the former one in the projective classical group. - self._classical_embedding as subgroup of classical base group (if different from classical group). @@ -831,7 +831,7 @@ def _create_classical_realization(self, just_embedded=False): """ # ------------------------------------------------------------------------------- - # Set up all incrediences of the classical Assion group (generic part) + # Set up data of the classical Assion group (generic part) # ------------------------------------------------------------------------------- def set_classical_realization(self, base_group, proj_group, centralizing_matrix, transvec_matrices): r""" @@ -839,18 +839,18 @@ def set_classical_realization(self, base_group, proj_group, centralizing_matrix, This is a local function of :meth:`_create_classical_realization`. - It handels the common part of symplectic and unitary version and creates conversion maps. + It handles the common part of symplectic and unitary version and creates conversion maps. INPUT: - ``base_group`` -- The symplectic or unitary groups Sp(m,3) resp. GU(m,2). - - ``proj_group`` -- The corresponding projeective group of base_group. + - ``proj_group`` -- The corresponding projective group of base_group. - ``centralizing_matrix`` -- The centralizing matrix according to Assion. - ``transvec_matrices`` -- List of transvection matrices according to Assion. OUTPUT: - No output, but the function sets the attributes of ``self`` decribed above. + No output, but the function sets the attributes of ``self`` described above. """ centralizing_element = None @@ -861,7 +861,7 @@ def set_classical_realization(self, base_group, proj_group, centralizing_matrix, # ------------------------------------------------------------------------------ # By the work of Assion no check on the group homomorphism is needed, at all. - # But to take care of software bugs they are perfomed in cases where they are + # But to take care of software bugs they are performed in cases where they are # not really expansive. # ------------------------------------------------------------------------------ check = False @@ -906,7 +906,7 @@ def set_classical_realization(self, base_group, proj_group, centralizing_matrix, return # ------------------------------------------------------------------------------- - # local methods to set up the classical group (spezific part) + # local methods to set up the classical group (specific part) # ------------------------------------------------------------------------------- # Case for symlectic groups # ------------------------------------------------------------------------------- @@ -917,14 +917,14 @@ def create_sympl_realization(self, m): INPUT: - - ``m`` -- Integer, the dimension of the classical groups vectorspace of operation. + - ``m`` -- Integer, the dimension of the classical groups vector-space of operation. The function calculates the centralizing matrix and the transvections as given by Assion and then uses set_classical_realization to complete the construction. """ # ----------------------------------------------------------- - # getting the invariant bilinearform of the group + # getting the invariant bilinear form of the group # and setting constants. # ----------------------------------------------------------- n = self.strands() @@ -968,7 +968,7 @@ def transvec2mat(v, bas=bas, bform=bform, fact=1): return matrix(bform.base_ring(), t) # ------------------------------------------------------------------------------ - # setting the centralizing matrix for the case of projective group realizaton + # setting the centralizing matrix for the case of projective group realization # ------------------------------------------------------------------------------ centralizing_vector = xbas[mhalf-1] centralizing_matrix = base_group(transvec2mat(centralizing_vector, fact=1)) @@ -987,14 +987,14 @@ def create_unitary_realization(self, m): INPUT: - - ``m`` -- Integer, the dimension of the classical groups vectorspace of operation. + - ``m`` -- Integer, the dimension of the classical groups vector-space of operation. The function calculates the centralizing_matrix and the transvections as given by Assion and then uses set_classical_realization to complete the construction. """ # --------------------------------------------------------------------- - # getting the invariant bilinearform of the group + # getting the invariant bilinear form of the group # and setting constants # --------------------------------------------------------------------- n = self.strands() @@ -1051,7 +1051,7 @@ def transvec2mat(v, bas=bas, bform=bform, fact=a): # ------------------------------------------------------------------------------ - # setting the centralizing matrix for the case of projective group realizaton. + # setting the centralizing matrix for the case of projective group realization. # ------------------------------------------------------------------------------ centralizing_vector = xbas[m-2]+xbas[m-1] centralizing_matrix = base_group(transvec2mat(centralizing_vector, fact=1)) @@ -1098,7 +1098,7 @@ def transvec2mat(v, bas=bas, bform=bform, fact=a): # buc_[i,i-1] = buc_[i,i+1]= - i\theta, buc_[i,i] = 1 + 2*cos(\pi/6)*i\theta # bus_[i,i-1] = bus_[i,i+1]= s, bus_[i,i] = -s^2 # now 1 + 2*cos(\pi/6)*i\theta = 1 + sqrt(3)*(-sqrt(3)/2 + I/2) = 1- 3/2 + sqrt(3)I/2 = z12^4 = - ~z12^2 - # finally: Coxeters Realization is the unitary Burau representation of Squier for s = ~z12 + # finally: Coxeter's Realization is the unitary Burau representation of Squier for s = ~z12 # ----------------------------------------------------------------------------------------------- UCF = UniversalCyclotomicField(); z12 = UCF.gen(12) classical_group = self.as_matrix_group(root_bur=~z12, domain=UCF, reduced='unitary') @@ -1117,7 +1117,7 @@ def _element_constructor_(self, x, **kwds): -- constructing element from an element of the attached classical group (embedded and not embedded) -- constructing element from an element of the attached permutation group - -- constructing element from an element of the attached refelction group + -- constructing element from an element of the attached reflection group INPUT: @@ -1181,7 +1181,7 @@ def strands(self): def braid_group(self): r""" Return an Instance of :class:`BraidGroup` with identical generators, such that - there exists an epimorhism to ``self``. + there exists an epimorphism to ``self``. OUTPUT: @@ -1238,7 +1238,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' If none of the keywords `root_bur`, `domain` and `characteristic` is given the default characteristic is 3 (resp. 2) if ``self`` is of ``cbg_type CubicBraidGroupType.AssionS`` (resp. ``CubicBraidGroupType.AssionU``). - - ``var`` -- string used for the indeterminant name in case `root_bur` + - ``var`` -- string used for the indeterminate name in case `root_bur` must be constructed in a splitting field. - ``reduced`` -- boolean (default: ``False``); for more information see the documentation of :meth:`burau_matrix` of :class:`Braid`. @@ -1246,7 +1246,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' OUTPUT: An instance of the class :class:`FinitelyGeneratedMatrixGroup_gap` according to the - input arguments together with a group homomorphism registerd as a conversion + input arguments together with a group homomorphism registered as a conversion from ``self`` to it. EXAMPLES:: @@ -1302,7 +1302,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' # ------------------------------------------------------------------------------- # adaption of default options for Assion groups on more then 4 stands - # (in order to achieve the maps beeing well defined) + # (in order to achieve the maps being well defined) # ------------------------------------------------------------------------------- if root_bur is None and domain is None and characteristic is None: if self._cbg_type == CubicBraidGroupType.AssionS: @@ -1330,7 +1330,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' gen_list.append(bur_mat) if unitary and herm_form.is_singular(): - unitary = False # since a degenertated hermitian form doesn't define a unitary group + unitary = False # since a degenerated hermitian form doesn't define a unitary group if self._classical_invariant_form is None: self._classical_invariant_form = herm_form @@ -1363,12 +1363,12 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' # ---------------------------------------------------------------------------------- # Although this method is available for finitely presented group - # we use the classical group implementation (by performace reason) to get + # we use the classical group implementation (by performance reason) to get # the permutation_group. # ---------------------------------------------------------------------------------- def as_permutation_group(self, use_classical=True): r""" - This method returns a permutation group isomporhic to ``self`` together + This method returns a permutation group isomorphic to ``self`` together with group isomorphism from ``self`` as a conversion. INPUT (all arguments are optional by keyword): @@ -1381,7 +1381,7 @@ def as_permutation_group(self, use_classical=True): OUTPUT: An instance of class :class:`PermutationGroup_generic` together with a group homomorphism - from ``self`` registerd as a conversion. + from ``self`` registered as a conversion. EXAMPLES:: @@ -1493,7 +1493,7 @@ def as_classical_group(self, embedded=False): # ------------------------------------------------------------------------------- if self._classical_group is None: if embedded and self._classical_embedding is None: - # this is separated to avoid unneccessary (for larger group exhaustive) calculations + # this is separated to avoid unnecessary (for larger group exhaustive) calculations self._create_classical_realization(just_embedded=True) else: self._create_classical_realization() @@ -1581,13 +1581,13 @@ def as_reflection_group(self): # ------------------------------------------------------------------------------- from sage.combinat.root_system.reflection_group_real import is_chevie_available if not is_chevie_available(): - raise ImportError("the GAP3 package 'chevie' is needed to obtain the corresponding reflection groups") + raise ImportError("the GAP3 package 'CHEVIE' is needed to obtain the corresponding reflection groups") if self._cbg_type != CubicBraidGroupType.Coxeter or self.strands() > 5 or self.strands() < 2: raise ValueError("no reflection group defined") # ------------------------------------------------------------------------------- - # define reflection group assiossiated to self + # define reflection group associated to self # ------------------------------------------------------------------------------- reflection_group = None @@ -1617,7 +1617,7 @@ def classical_invariant_form(self): OUTPUT: A square matrix of dimension according to the space the classical realization is - operating on. In the case of the full cubic braid groups and of the assion groups + operating on. In the case of the full cubic braid groups and of the Assion groups of ``cbg_type CubicBraidGroupType.AssionU`` the matrix is hermitian. In the case of the Assion groups of ``cbg_type CubicBraidGroupType.AssionS`` it is alternating. Note that the invariant form of the full cubic braid group on more than 5 strands @@ -1693,7 +1693,7 @@ def centralizing_element(self, embedded=False): Depending on the optional keyword a permutation as an element of ``PSp(n,3)`` (type S) or ``PGU(n,2)`` (type U) for ``n = 0 mod 2`` (type S) reps. ``n = 0 mod 3`` - (type U) is returned. Elsewise, the centralizing element is a matrix + (type U) is returned. Else-wise, the centralizing element is a matrix belonging to ``Sp(n,3)`` reps. ``GU(n,2)``. EXAMPLES:: @@ -1744,7 +1744,7 @@ def centralizing_element(self, embedded=False): # ---------------------------------------------------------------------------------- def order(self): r""" - To avoid long waittime on calculations the order will be obtained + To avoid long wait-time on calculations the order will be obtained using the classical realization. OUTPUT: @@ -1776,7 +1776,7 @@ def order(self): def is_finite(self): r""" - Method from :class:`GroupMixinLibGAP` overwriten because of performance reason. + Method from :class:`GroupMixinLibGAP` overwritten because of performance reason. EXAMPLES:: From 46840491603debc1785300287cbb6933c144fdf7 Mon Sep 17 00:00:00 2001 From: Sebastian Oehms Date: Fri, 12 Apr 2019 12:00:17 +0200 Subject: [PATCH 08/10] 27302: implement __classcall_private__ and move Enum into the class --- src/sage/groups/cubic_braid.py | 263 +++++++++++++++++---------------- 1 file changed, 138 insertions(+), 125 deletions(-) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index c1f477450cd..356c9f98c15 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -89,141 +89,75 @@ from enum import Enum -############################################################################## -# -# Enum for the type of the group -# -############################################################################## -class CubicBraidGroupType(Enum): - r""" - Enum class to select the type of the group: - - - ``Coxeter`` -- 'C' the full cubic braid group. - - ``AssionS`` -- 'S' finite factor group of type S considered by Assion. - - ``AssionU`` -- 'U' finite factor group of type U considered by Assion. - """ - Coxeter = 'C' - AssionS = 'S' - AssionU = 'U' ############################################################################## # -# Functions to create Instances of the CubicBraidGroup_class +# Functions to create Instances of the CubicBraidGroup # ############################################################################## -def CubicBraidGroup(n=None, names='c', cbg_type=CubicBraidGroupType.Coxeter): - r""" - Construct cubic braid groups as instance of :class:`CubicBraidGroup_class`. - - INPUT: - - - ``n`` -- integer or ``None`` (default). The number of - strands. If not specified the ``names`` are counted and the - group is assumed to have one more strand than generators. - - - ``names`` -- string or list/tuple/iterable of strings (default: - ``'c'``). The generator names or name prefix. - - - ``cbg_type`` -- (optional keyword, default = CubicBraidGroupType.Coxeter) - of enum type :class:`CubicBraidGroupType` is passed to the corresponding - keyword argument of the constructor of :class:`CubicBraidGroup_class`. - - EXAMPLES:: - - sage: C3 = CubicBraidGroup(3); C3.generators() - (c0, c1) - sage: CubicBraidGroup(3, 'g').generators() - (g0, g1) - sage: from sage.groups.cubic_braid import CubicBraidGroupType - sage: U3.=CubicBraidGroup(3, cbg_type=CubicBraidGroupType.AssionU); U3.generators() - (u1, u2) - """ - # this code is adapted from :func:`BraidGroup` - # Support Freegroup('a,b') syntax - if n is not None: - try: - n = Integer(n)-1 - except TypeError: - names = n - - n = None - # derive n from counting names - if n is None: - import six - if isinstance(names, six.string_types): - n = len(names.split(',')) - else: - names = list(names) - n = len(names) - - from sage.structure.category_object import normalize_names - names = tuple(normalize_names(n, names)) - return CubicBraidGroup_class(names, cbg_type=cbg_type) # ---------------------------------------------------------------------------------- -# Short-Hands for AssionsGroups: +# Short-Hands for Assions groups: # ---------------------------------------------------------------------------------- def AssionGroupS(n=None, names='s'): r""" - Construct cubic braid groups as instance of :class:`CubicBraidGroup_class` which - have been investigated by J.Assion using the notation S(m). This function is a short - hand cut for :func:`CubicBraidGroup` setting ``cbg_type=CubicBraidGroupType.AssionS`` + Construct cubic braid groups as instance of :class:`CubicBraidGroup` which have been + investigated by J.Assion using the notation S(m). This function is a short hand cut + for setting the construction arguments ``cbg_type=CubicBraidGroup.type.AssionS`` and default ``names='s'``. - For more information type ``CubicBraidGroup_class?`` + For more information type ``CubicBraidGroup?`` INPUT: - ``n`` -- integer or None (default). The number of strands. This argument is passed - to the corresponding argument of :func:`CubicBraidGroup`. + to the corresponding argument of the classcall of :class:`CubicBraidGroup`. - ``names`` -- string or list/tuple/iterable of strings (default:'s'). This argument is - passed to the corresponding argument of :func:`CubicBraidGroup`. + passed to the corresponding argument of the classcall of :class:`CubicBraidGroup`. EXAMPLES:: sage: S3 = AssionGroupS(3); S3 Assion group on 3 strands of type S - sage: from sage.groups.cubic_braid import CubicBraidGroupType - sage: S3x = CubicBraidGroup(3, names='s', cbg_type=CubicBraidGroupType.AssionS); S3x + sage: S3x = CubicBraidGroup(3, names='s', cbg_type=CubicBraidGroup.type.AssionS); S3x Assion group on 3 strands of type S sage: S3 == S3x True """ - return CubicBraidGroup(n = n, names = names, cbg_type=CubicBraidGroupType.AssionS) + return CubicBraidGroup(n = n, names = names, cbg_type=CubicBraidGroup.type.AssionS) def AssionGroupU(n=None, names='u'): r""" - Construct cubic braid groups as instance of :class:`CubicBraidGroup_class` which - have been investigated by J.Assion using the notation U(m). This function is a short - hand cut for :func:`CubicBraidGroup` setting ``cbg_type=CubicBraidGroupType.AssionU`` + Construct cubic braid groups as instance of :class:`CubicBraidGroup` which have been + investigated by J.Assion using the notation U(m). This function is a short hand cut + for setting the construction arguments ``cbg_type=CubicBraidGroup.type.AssionU`` and default ``names='u'``. - For more information type ``CubicBraidGroup_class?`` + For more information type ``CubicBraidGroup?`` INPUT: - ``n`` -- integer or None (default). The number of strands. This argument is passed - to the corresponding argument of :func:`CubicBraidGroup`. + to the corresponding argument of the classcall of :class:`CubicBraidGroup`. - ``names`` -- string or list/tuple/iterable of strings (default:'u'). This argument is - passed to the corresponding argument of :func:`CubicBraidGroup`. + passed to the corresponding argument of the classcall of :class:`CubicBraidGroup`. EXAMPLES:: sage: U3 = AssionGroupU(3); U3 Assion group on 3 strands of type U - sage: from sage.groups.cubic_braid import CubicBraidGroupType - sage: U3x = CubicBraidGroup(3, names='u', cbg_type=CubicBraidGroupType.AssionU); U3x + sage: U3x = CubicBraidGroup(3, names='u', cbg_type=CubicBraidGroup.type.AssionU); U3x Assion group on 3 strands of type U sage: U3 == U3x True """ - return CubicBraidGroup(n = n, names = names, cbg_type=CubicBraidGroupType.AssionU) + return CubicBraidGroup(n = n, names = names, cbg_type=CubicBraidGroup.type.AssionU) @@ -235,10 +169,10 @@ def AssionGroupU(n=None, names='u'): class CubicBraidElement(FinitelyPresentedGroupElement): r""" This class models elements of cubic factor groups of the braid group. - It is the element class of the CubicBraidGroup_class. + It is the element class of the CubicBraidGroup. For more information see the documentation of the parent - :class:`CubicBraidGroup_class`. + :class:`CubicBraidGroup`. EXAMPLES:: @@ -471,10 +405,10 @@ def conv2domain (laur_pol): ############################################################################## # -# Class CubicBraidGroup_class +# Class CubicBraidGroup # ############################################################################## -class CubicBraidGroup_class(FinitelyPresentedGroup): +class CubicBraidGroup(FinitelyPresentedGroup): r""" This class implements factor groups of the Artin braid group mapping their generators to elements of order 3 (see the module header for more @@ -491,11 +425,11 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): - ``names`` -- see the corresponding documentation of :class:`BraidGroup_class`. - - ``cbg_type`` -- (optional keyword, default = CubicBraidGroupType.Coxeter, - see explanation below) of enum type :class:`CubicBraidGroupType`. + - ``cbg_type`` -- (optional keyword, default = CubicBraidGroup.type.Coxeter, + see explanation below) of enum type :class:`CubicBraidGroup.type`. - Setting the keyword ``cbg_type`` to one on the values ``CubicBraidGroupType.AssionS`` - or ``CubicBraidGroupType.AssionU`` the additional relations due to Assion are added: + Setting the keyword ``cbg_type`` to one on the values ``CubicBraidGroup.type.AssionS`` + or ``CubicBraidGroup.type.AssionU`` the additional relations due to Assion are added: .. MATH:: @@ -506,11 +440,11 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): & \mbox{ for } m >= 5 \mbox{ in case } U(m) \end{array} - where `t_i = (s_i s_{i+1})^3`. If ``cbg_type == CubicBraidGroupType.Coxeter`` (default) + where `t_i = (s_i s_{i+1})^3`. If ``cbg_type == CubicBraidGroup.type.Coxeter`` (default) only the cubic relation on the generators is active (Coxeter's case of investigation). Note that for `n = 2, 3, 4` the groups do not differ between the three possible values of cbg_type (as finitely presented groups). But anyway, the instances for - ``CubicBraidGroupType.Coxeter, CubicBraidGroupType.AssionS`` and ``CubicBraidGroupType.AssionU`` + ``CubicBraidGroup.type.Coxeter, CubicBraidGroup.type.AssionS`` and ``CubicBraidGroup.type.AssionU`` are different, since they have different classical realizations implemented. The creation of instances of this class can also be done more easily by help @@ -519,8 +453,7 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): EXAMPLES:: - sage: from sage.groups.cubic_braid import CubicBraidGroupType - sage: U3 = CubicBraidGroup(3, cbg_type=CubicBraidGroupType.AssionU); U3 + sage: U3 = CubicBraidGroup(3, cbg_type=CubicBraidGroup.type.AssionU); U3 Assion group on 3 strands of type U sage: U3.gens() (c0, c1) @@ -567,10 +500,85 @@ class CubicBraidGroup_class(FinitelyPresentedGroup): Element = CubicBraidElement + ############################################################################## + # Enum for the type of the group + ############################################################################## + class type(Enum): + r""" + Enum class to select the type of the group: + + - ``Coxeter`` -- 'C' the full cubic braid group. + - ``AssionS`` -- 'S' finite factor group of type S considered by Assion. + - ``AssionU`` -- 'U' finite factor group of type U considered by Assion. + + EXAMPLES:: + + sage: S2 = CubicBraidGroup(2, cbg_type=CubicBraidGroup.type.AssionS); S2 + Assion group on 2 strands of type S + sage: U3 = CubicBraidGroup(2, cbg_type='U') + Traceback (most recent call last): + ... + TypeError: the cbg_type must be an instance of + """ + Coxeter = 'C' + AssionS = 'S' + AssionU = 'U' + + ########################################################################################### # private methods ########################################################################################### - def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): + @staticmethod + def __classcall_private__(cls, n=None, names='c', cbg_type=None): + r""" + Normalize input to ensure a unique representation. + + INPUT: + + - ``n`` -- integer or ``None`` (default). The number of + strands. If not specified the ``names`` are counted and the + group is assumed to have one more strand than generators. + + - ``names`` -- string or list/tuple/iterable of strings (default: + ``'c'``). The generator names or name prefix. + + - ``cbg_type`` -- (optional keyword, default = CubicBraidGroup.type.Coxeter) + of enum type :class:`CubicBraidGroup.type` is passed to the corresponding + keyword argument of the constructor of :class:`CubicBraidGroup`. + + EXAMPLES:: + + sage: C3 = CubicBraidGroup(3); C3.generators() + (c0, c1) + sage: CubicBraidGroup(3, 'g').generators() + (g0, g1) + sage: U3.=CubicBraidGroup(3, cbg_type=CubicBraidGroup.type.AssionU); U3.generators() + (u1, u2) + """ + # this code is adapted from :func:`BraidGroup` + # Support Freegroup('a,b') syntax + if n is not None: + try: + n = Integer(n)-1 + except TypeError: + names = n + + n = None + # derive n from counting names + if n is None: + import six + if isinstance(names, six.string_types): + n = len(names.split(',')) + else: + names = list(names) + n = len(names) + + from sage.structure.category_object import normalize_names + names = tuple(normalize_names(n, names)) + return super(CubicBraidGroup, cls).__classcall__(cls, names, cbg_type=cbg_type) + + + def __init__(self, names, cbg_type=None): """ Python constructor. @@ -578,8 +586,8 @@ def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): - ``names`` -- see the corresponding documentation of :class:`BraidGroup_class`. - - ``cbg_type`` -- (optional keyword, default = CubicBraidGroupType.Coxeter) of enum type - :class:`CubicBraidGroupType` to select the type of the group. + - ``cbg_type`` -- (optional keyword, default = CubicBraidGroup.type.Coxeter) of enum type + :class:`CubicBraidGroup.type` to select the type of the group. TESTS:: @@ -604,6 +612,11 @@ def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): 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): + raise TypeError("the cbg_type must be an instance of %s" %(CubicBraidGroup.type)) + free_group = FreeGroup(names) self._cbg_type = cbg_type self._nstrands = n+1 @@ -622,13 +635,13 @@ def __init__(self, names, cbg_type=CubicBraidGroupType.Coxeter): for i in range(n): rels.append(b[i]**3) - # than Assion's relation Satz 2.2 for cbg_type=CubicBraidGroupType.AssionS - # and Satz 2.4 for cbg_type=CubicBraidGroupType.AssionU + # than Assion's relation Satz 2.2 for cbg_type=CubicBraidGroup.type.AssionS + # and Satz 2.4 for cbg_type=CubicBraidGroup.type.AssionU if n > 3: for i in range(n-3): - if cbg_type == CubicBraidGroupType.AssionU: + if cbg_type == CubicBraidGroup.type.AssionU: rels.append((t[i]*t[i+2])**3) - elif cbg_type == CubicBraidGroupType.AssionS: + elif cbg_type == CubicBraidGroup.type.AssionS: rels.append(b[i+2]*b[i]*t[i+1]*b[i]*ti[i+1]*t[i+2]*t[i+1]*b[i]*ti[i+1]*ti[i+2]) FinitelyPresentedGroup.__init__(self, free_group, tuple(rels)) @@ -662,7 +675,7 @@ def _repr_(self): sage: AssionGroupU(2) Assion group on 2 strands of type U """ - if self._cbg_type == CubicBraidGroupType.Coxeter: + if self._cbg_type == CubicBraidGroup.type.Coxeter: return "Cubic Braid group on %s strands"%(self.strands()) else: return "Assion group on %s strands of type %s"%(self.strands() ,self._cbg_type.value) @@ -755,15 +768,15 @@ def _test_matrix_group(self, **options): MatDEF = self.as_matrix_group() self._internal_test_attached_group(MatDEF, tester) - if self._cbg_type != CubicBraidGroupType.AssionU or self.strands() < 5 : # not well defined else-wise + if self._cbg_type != CubicBraidGroup.type.AssionU or self.strands() < 5: # not well defined else-wise matrix_grpF3 = self.as_matrix_group(root_bur=r63) self._internal_test_attached_group(matrix_grpF3, tester) - if self._cbg_type != CubicBraidGroupType.AssionS or self.strands() < 5 : # not well defined else-wise + if self._cbg_type != CubicBraidGroup.type.AssionS or self.strands() < 5: # not well defined else-wise matrix_grpF4 = self.as_matrix_group(root_bur=r64) self._internal_test_attached_group(matrix_grpF4, tester) - if self.strands() < 5 or self._cbg_type == CubicBraidGroupType.Coxeter: + if self.strands() < 5 or self._cbg_type == CubicBraidGroup.type.Coxeter: matrix_grpF5 = self.as_matrix_group(characteristic=5) self._internal_test_attached_group(matrix_grpF5, tester) @@ -785,7 +798,7 @@ def _test_reflection_group(self, **options): sage: CBG2 = CubicBraidGroup(2) sage: CBG2._test_reflection_group() """ - if self._cbg_type == CubicBraidGroupType.Coxeter and self.is_finite() and self.strands() > 2: + if self._cbg_type == CubicBraidGroup.type.Coxeter and self.is_finite() and self.strands() > 2: from sage.combinat.root_system.reflection_group_real import is_chevie_available if is_chevie_available(): tester = self._tester(**options) @@ -913,7 +926,7 @@ def set_classical_realization(self, base_group, proj_group, centralizing_matrix, def create_sympl_realization(self, m): r""" Internal method to create classical group for symplectic - Assion groups (`cbg_type CubicBraidGroupType.AssionS`). + Assion groups (`cbg_type == CubicBraidGroup.type.AssionS`). INPUT: @@ -983,7 +996,7 @@ def transvec2mat(v, bas=bas, bform=bform, fact=1): def create_unitary_realization(self, m): """ Internal method to create classical group for - unitary Assion groups (`cbg_type CubicBraidGroupType.AssionU`). + unitary Assion groups (`cbg_type == CubicBraidGroup.type.AssionU`). INPUT: @@ -1074,12 +1087,12 @@ def transvec2mat(v, bas=bas, bform=bform, fact=a): # ------------------------------------------------------------------------------- # Setting the Classical group # ------------------------------------------------------------------------------- - if self._cbg_type == CubicBraidGroupType.AssionS: + if self._cbg_type == CubicBraidGroup.type.AssionS: dim_sympl_group = n-1 # S(n-1) = Sp(n-1, 3) if n % 2 == 0: dim_sympl_group = n # S(n-1) = subgroup of PSp(n, 3) create_sympl_realization(self, dim_sympl_group) - elif self._cbg_type == CubicBraidGroupType.AssionU: + elif self._cbg_type == CubicBraidGroup.type.AssionU: dim_unitary_group = n-1 # U(n-1) = GU(n-1, 2) if n % 3 == 0: dim_unitary_group = n # U(n-1) = subgroup PGU(n, 3) @@ -1148,7 +1161,7 @@ def _element_constructor_(self, x, **kwds): if map_to is not None: if hasattr(map_to, 'lift'): return map_to.lift(x) - return super(CubicBraidGroup_class, self)._element_constructor_(x) + return super(CubicBraidGroup, self)._element_constructor_(x) ####################################################################################################################### @@ -1237,7 +1250,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' domain (default is 0 or the characteristic of `domain` if given) If none of the keywords `root_bur`, `domain` and `characteristic` is given the default characteristic is 3 (resp. 2) if ``self`` is of ``cbg_type - CubicBraidGroupType.AssionS`` (resp. ``CubicBraidGroupType.AssionU``). + CubicBraidGroup.type.AssionS`` (resp. ``CubicBraidGroup.type.AssionU``). - ``var`` -- string used for the indeterminate name in case `root_bur` must be constructed in a splitting field. - ``reduced`` -- boolean (default: ``False``); for more information @@ -1305,9 +1318,9 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' # (in order to achieve the maps being well defined) # ------------------------------------------------------------------------------- if root_bur is None and domain is None and characteristic is None: - if self._cbg_type == CubicBraidGroupType.AssionS: + if self._cbg_type == CubicBraidGroup.type.AssionS: characteristic = 3 - elif self._cbg_type == CubicBraidGroupType.AssionU: + elif self._cbg_type == CubicBraidGroup.type.AssionU: characteristic = 2 else: characteristic = 0 @@ -1408,7 +1421,7 @@ def as_permutation_group(self, use_classical=True): PG = CGM.as_permutation_group() img_gens = [PG(CGM(CG(gen))) for gen in self.gens()] else: - PG = super(CubicBraidGroup_class, self).as_permutation_group() + PG = super(CubicBraidGroup, self).as_permutation_group() img_gens = PG.gens() img_gens = [PG(gen) for gen in img_gens] @@ -1429,7 +1442,7 @@ def as_classical_group(self, embedded=False): - ``embedded`` -- boolean (default = False). This boolean does effect the cases of Assion groups when they are realized as projective groups, only. - More precisely: if ``self`` is of ``cbg_type CubicBraidGroupType.AssionS`` + More precisely: if ``self`` is of ``cbg_type CubicBraidGroup.type.AssionS`` (for example) and the number of strands ``n`` is even, than its classical group is a subgroup of ``PSp(n,3)`` (being centralized by the element ``self.centralizing_element(projective=True))``. By default this group will be @@ -1441,7 +1454,7 @@ def as_classical_group(self, embedded=False): Depending on the type of ``self`` and the number of strands an instance of ``Sp(n-1,3)``, ``GU(n-1,2)``, subgroup of ``PSp(n,3), PGU(n,2)`` or a subgroup of ``GU(n-1, UCF)`` - (``cbg_type CubicBraidGroupType.Coxeter``) with respect to a certain hermitian form + (``cbg_type == CubicBraidGroup.type.Coxeter``) with respect to a certain hermitian form attached to the Burau representation (used by Coxeter and Squier). Here ``UCF`` stands for the universal cyclotomic field. @@ -1520,7 +1533,7 @@ def as_reflection_group(self): r""" Creates an isomorphic image of ``self`` as irreducible complex reflection group. This is possible only for the finite cubic braid groups of ``cbg_type - CubicBraidGroupType.Coxeter``. + CubicBraidGroup.type.Coxeter``. This method uses the sage implementation of reflection group via the gap3 CHEVIE package. To use this method you must have gap3 together with CHEVIE installed! @@ -1583,7 +1596,7 @@ def as_reflection_group(self): if not is_chevie_available(): raise ImportError("the GAP3 package 'CHEVIE' is needed to obtain the corresponding reflection groups") - if self._cbg_type != CubicBraidGroupType.Coxeter or self.strands() > 5 or self.strands() < 2: + if self._cbg_type != CubicBraidGroup.type.Coxeter or self.strands() > 5 or self.strands() < 2: raise ValueError("no reflection group defined") # ------------------------------------------------------------------------------- @@ -1618,8 +1631,8 @@ def classical_invariant_form(self): A square matrix of dimension according to the space the classical realization is operating on. In the case of the full cubic braid groups and of the Assion groups - of ``cbg_type CubicBraidGroupType.AssionU`` the matrix is hermitian. In the case of - the Assion groups of ``cbg_type CubicBraidGroupType.AssionS`` it is alternating. + of ``cbg_type CubicBraidGroup.type.AssionU`` the matrix is hermitian. In the case of + the Assion groups of ``cbg_type CubicBraidGroup.type.AssionS`` it is alternating. Note that the invariant form of the full cubic braid group on more than 5 strands is degenerated (causing the group to be infinite). @@ -1682,7 +1695,7 @@ def centralizing_element(self, embedded=False): - ``embedded`` -- boolean (default = False). This boolean just effects the cases of Assion groups when they are realized as projective groups. - More precisely: if ``self`` is of ``cbg_type CubicBraidGroupType.AssionS`` + More precisely: if ``self`` is of ``cbg_type CubicBraidGroup.type.AssionS`` (for example) and the number of strands ``n`` is even, than its classical group is a subgroup of ``PSp(n,3)`` being centralized by the element return for option ``embedded=False``. Otherwise the image of this element inside @@ -1763,7 +1776,7 @@ def order(self): from sage.rings.infinity import infinity n = self.strands() - if self._cbg_type == CubicBraidGroupType.Coxeter and n > 5: + if self._cbg_type == CubicBraidGroup.type.Coxeter and n > 5: order = infinity else: order = self.as_classical_group(embedded=True).order() From 24c1d068c530ec9b8ebd9fd1283a02a1906d7463 Mon Sep 17 00:00:00 2001 From: Sebastian Oehms Date: Thu, 30 May 2019 10:13:29 +0200 Subject: [PATCH 09/10] 27302: merge conflict fixed again and assert_ -> assertTrue --- src/sage/groups/cubic_braid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 356c9f98c15..1a1e0744693 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -706,7 +706,7 @@ def _internal_test_attached_group(self, attached_group, tester): att_grp_elem = attached_group(elem) if self.is_finite() and self.strands() <= 7: # not realistic for larger number of strands att_grp_elem_back= self(att_grp_elem) - tester.assert_(att_grp_elem_back == elem) + tester.assertTrue(att_grp_elem_back == elem) return From fe4adff9d357284a8cf57ad8aaace92488a6a475 Mon Sep 17 00:00:00 2001 From: Sebastian Oehms Date: Sun, 11 Aug 2019 10:45:45 +0200 Subject: [PATCH 10/10] 27302: comparison for larger groups fixed --- src/sage/groups/cubic_braid.py | 99 +++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 19 deletions(-) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 1a1e0744693..31a952167f8 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -79,6 +79,9 @@ # **************************************************************************** + +from sage.misc.cachefunc import cached_method +from sage.structure.richcmp import richcmp, richcmp_not_equal, rich_to_bool from sage.rings.integer import Integer from sage.groups.free_group import FreeGroup from sage.groups.finitely_presented import FinitelyPresentedGroup, FinitelyPresentedGroupElement @@ -86,6 +89,7 @@ from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField from sage.rings.number_field.number_field import CyclotomicField from sage.rings.finite_rings.finite_field_constructor import GF + from enum import Enum @@ -176,7 +180,7 @@ class CubicBraidElement(FinitelyPresentedGroupElement): EXAMPLES:: - sage: C4. = CubicBraidGroup(4); C4 + sage: C4. = CubicBraidGroup(4); C4 Cubic Braid group on 4 strands sage: ele1 = c1*c2*c3^-1*c2^-1 sage: ele2 = C4((1, 2, -3, -2)) @@ -184,6 +188,64 @@ class CubicBraidElement(FinitelyPresentedGroupElement): True """ + @cached_method + def _richcmp_braid_burau(self, other, op): + """ + helper method to compare self with an other cubic braid using + the comparision of the braid preimage and the Burau matrix. + + EXAMPLES:: + + sage: C6. = CubicBraidGroup(6) + sage: ele1 = c1*c2*c3^2*c4*c5 + sage: ele2 = c1*c2*~c3*c4*c5 + sage: ele1 == ele2 # indirect doctest + True + + TESTS:: + + sage: S7 = AssionGroupS(7) + sage: all(S7(rel).is_one() for rel in S7.relations()) + True + """ + sbraid = self.braid() + obraid = other.braid() + if sbraid == obraid: + return rich_to_bool(op, 0) + smat = self.burau_matrix() + omat = other.burau_matrix() + skeys = smat.dict().keys() + okeys = omat.dict().keys() + if skeys != okeys: + # certainly different: compare braid preimages + return richcmp(sbraid, obraid, op) + if smat == omat: + return rich_to_bool(op, 0) + # certainly different: compare braid preimages + return richcmp(sbraid, obraid, op) + + + def _richcmp_(self, other, op): + """ + overwrite comparison since the inherited one from FinitelyPresentedGroupElement + does not terminate in the case of more than 5 strands (not only infinite cases). + The comparison is done via the Burau representation + + EXAMPLES:: + + sage: C6. = CubicBraidGroup(6) + sage: ele1 = c1*c2*c3*c4*c5 + sage: ele2 = c1*c2*c4*c5 + sage: ele1 == ele2 # indirect doctest + False + sage: ele1 < ele2 # indirect doctest + True + """ + if self.parent().strands() < 6: + return super(CubicBraidElement, self)._richcmp_(other, op) + return self._richcmp_braid_burau(other, op) + + def braid(self): r""" Return the canonical braid preimage of ``self`` as Object of the @@ -206,6 +268,7 @@ class :class:`Braid`. return braid_group(self) + @cached_method def burau_matrix(self, root_bur = None, domain = None, characteristic = None, var='t', reduced=False): r""" Return the Burau matrix of the cubic braid coset. @@ -339,7 +402,17 @@ def find_root(domain): if domain is None: if (characteristic is None): - characteristic = 0 + # -------------------------------------------------------------------- + # setting the default characteristic in order to achieve the according + # representations being well defined + # -------------------------------------------------------------------- + cbg_type = self.parent()._cbg_type + if cbg_type == CubicBraidGroup.type.AssionS: + characteristic = 3 # making Assion type S relations vanish + elif cbg_type == CubicBraidGroup.type.AssionU: + characteristic = 2 # making Assion type U relations vanish + else: + characteristic = 0 try: characteristic = Integer(characteristic) except ValueError: @@ -1218,11 +1291,11 @@ def braid_group(self): [ 1 - t 0 0 1 -1 + t] [ 1 0 0 0 0] sage: u.burau_matrix() - [ -zeta3 zeta3 + 1 0 0 0] - [ -zeta3 0 zeta3 + 1 0 0] - [ -zeta3 0 0 0 zeta3 + 1] - [ -zeta3 0 0 1 zeta3] - [ 1 0 0 0 0] + [t + 1 t 0 0 0] + [t + 1 0 t 0 0] + [t + 1 0 0 0 t] + [t + 1 0 0 1 t + 1] + [ 1 0 0 0 0] sage: bU = U5(b) sage: uB = B5(u) sage: bU == u @@ -1313,18 +1386,6 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' # define matrix group by generators using the Burau representation # ------------------------------------------------------------------------------- - # ------------------------------------------------------------------------------- - # adaption of default options for Assion groups on more then 4 stands - # (in order to achieve the maps being well defined) - # ------------------------------------------------------------------------------- - if root_bur is None and domain is None and characteristic is None: - if self._cbg_type == CubicBraidGroup.type.AssionS: - characteristic = 3 - elif self._cbg_type == CubicBraidGroup.type.AssionU: - characteristic = 2 - else: - characteristic = 0 - unitary = False if type(reduced) == str: if reduced == 'unitary':