SharedCubicBraidGroup / cubic_braid.pyOpen in CoCalc
Code directory
# This file was *autogenerated* from the file cubic_braid.sage
from sage.all_cmdline import *   # import sage library
_sage_const_3 = Integer(3); _sage_const_2 = Integer(2); _sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_7 = Integer(7); _sage_const_6 = Integer(6); _sage_const_5 = Integer(5); _sage_const_4 = Integer(4); _sage_const_100 = Integer(100); _sage_const_1024 = Integer(1024); _sage_const_32 = Integer(32); _sage_const_12 = Integer(12); _sage_const_11 = Integer(11); _sage_const_648 = Integer(648); _sage_const_155520 = Integer(155520); _sage_const_25 = Integer(25); _sage_const_24 = Integer(24); _sage_const_48 = Integer(48)
r"""
#####################################################################################################################
# Cubic factor groups of braid groups
#####################################################################################################################




##############################################################################
#       Copyright (C) 2016 Sebastian Oehms <[email protected]>
#
#  Distributed under the terms of the GNU General Public License (GPL)
#
#  The full text of the GPL is available at:
#
#                  http://www.gnu.org/licenses/
##############################################################################



This module is devoted for factor groups of the Artin braid groups, such that the images $s_i$ of the braid generators have order three:

    $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 Candian 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) x C_3$. Today, these 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 dimensional factors of these groups. The additional relations on the braid group generators $\{ s_1, \cdot , s_{m-1}\}$ are


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$ for $m >= 5$ in case $S(m)$ 
U) $t_1 t_3 = 1$                                                for $m >= 5$ in case $U(m)$ 

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 conidered by Coxeter and Assion as finitely presented groups (via the gap interface) together with the classical realizations given by the authors. It also contains the coercion 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 under sage version 7.2 (or later) the reflection groups via the gap3
interface are availlable, too. The methods for all this functionality are:

   - as_classical_group
   - as_matrix_group
   - as_reflection_group    (needs sage version 7.2 up and gap3 + CHEVIE)
   - as_permutation_group

Further methods are:

   - order 
   - pre_image_braid_group
   - cubic_braid_subgroup
   - character_table

For more information and EXAMPLES type 

   sage: print CubicBraidGroup_class.__doc__

AUTHOR:

   Sebastian Oehms, Sept. 2016
"""

from sage.groups.finitely_presented import FinitelyPresentedGroup, FinitelyPresentedGroupElement
from sage.misc.decorators import options, rename_keyword
from sage.groups.braid import *
from lib.utils_sys import *
from lib.utils_gap_interface import *
from lib.local_permgroup import *
from lib.local_braid import *
from lib.local_matrix_group import *

   

##############################################################################
#
#                  Class CubicBraidElement (for elements)
#
##############################################################################
class CubicBraidElement(FinitelyPresentedGroupElement):
    """
    This class models elements of cubic factor groups of the braid group. It is the element class of 
    the CubicBraidGroup_class

    If you don't see this well formatted type 

    sage: print CubicBraidElement.__doc__

    It is realized as a particular case of elements of a finitely presented group (inherited from 
    FinitelyPresentedGroupElement)

    EXAMPLES:

        sage: C4.<c1,c2,c3> = CubicBraidGroup(4)
        sage: C4
        Cubic Braid group on 4 strands
        sage: ele1 = c1*c2*c3^-1*c2^-1; type(ele1)
        <class 'lib.cubic_braid.CubicBraidGroup_class_with_category.element_class'>
        sage: ele2 = C4((1, 2, -3, -2))
        sage: ele1 == ele2
        True

    For more information see the parent class typing

    sage:  print CubicBraidGroup_class.__doc__

    AUTHOR

      - Sebastian Oehms, Sept. 2016

    """



    def braid(self):
        """
        Return the canonical braid preimage of self as Object of the class Braid,

        If you don't see this well formatted type 

        sage: print CubicBraidElement.braid.__doc__

        OUTPUT:

            the preimage of self as instance of the Braid class which is the element class of the BraidGroup_class

        EXAMPLES::

            sage: C3.<c1, c2> = CubicBraidGroup(3)
            sage: c1.parent()
            Cubic Braid group on 3 strands 
            sage: c1.braid().parent()
            Braid group on 3 strands

        For information type

        sage:  print CubicBraidGroup_class.__doc__


        """

        pre_image_braid_grp = self.parent().pre_image_braid_group()
        pre_image_braid = pre_image_braid_grp( self )
        return pre_image_braid



    def cubic_writhe( self ):
        """
        Return the exponent_sum of the preimage braid modulo 3

        If you don't see this well formatted type 

        sage: print CubicBraidElement.cubic_writhe.__doc__

        OUTPUT:

            Integer 0, 1, 2 giving the exponent_sum modulo 3 in a word in the braid generators representig self

        EXAMPLES::

            sage: S4.<s1,s2,s3>=AssionGroupS(4)
            sage: s=s1*s2*s3*s2
            sage: s.cubic_writhe()
            1
            sage: 

        AUTHOR:

          - Sebastian Oehms, Sept. 2016

        """
        exp_sum = self.braid().exponent_sum()
        return exp_sum % _sage_const_3 





    def _burau_matrix_(self, rootBur = None, Domain = None, characteristic = None, reduced=False, version='default'):
        """
        Return the Burau matrix of the cubic braid coset. 

        If you don't see this well formatted type 

        sage: print CubicBraidElement._burau_matrix_.__doc_

        This is the internal version of the "burau_matrix" method which returns more information than the main method

        for more information on the main method "burau_matrix" type

        sage: print CubicBraidElement.burau_matrix.__doc_

        The only difference to that method is this:

        OUTPUT:

            a pair consisting of

            - The Burau matrix of the cubic braid coset with entries in the domain given by the options
 
            - the value of rootBur which is used. If the keyword rootBur has been set, this value is identical to this. 
              Otherwise, the value which has been calculated from the other parameters is returned

        EXAMPLES:

         sage: S3.<s1,s2>=AssionGroupS(3)
         sage: s2.burau_matrix( characteristic=2, version='unitary' )
         [     1      0]
         [rI + 1     rI]
         sage: s2._burau_matrix_( characteristic=2, version='unitary' )
         (
         [     1      0]        
         [rI + 1     rI], rI + 1
         )
         sage: 

        AUTHOR:

          - Sebastian Oehms, Sept. 2016

        """

        pre_image_braid = self.braid( )

        BurauOri = pre_image_braid.burau_matrix( var='tt', reduced = reduced, version=version )
        d = BurauOri.dimensions()

        if Domain != None:
            if isinstance( Domain, UniversalCyclotomicField):
                if rootBur == None:
                    if version == 'unitary':
                        rootBur = Domain.gen(_sage_const_12 )
                    else:
                        rootBur = Domain.gen(_sage_const_6 )

        if rootBur == None:
            tT = var('tT')
            if version == 'unitary':
                minPolRootBur = tT**_sage_const_4  -tT**_sage_const_2  +_sage_const_1 
            else:
                minPolRootBur  = tT**_sage_const_2  -tT +_sage_const_1 

            if Domain == None:
                if (characteristic == None):
                    characteristic = _sage_const_0 

                try:
                    characteristic = Integer( characteristic )
                except:
                    raise ValueError('characteristic must be in integer')

                if  characteristic <> _sage_const_0  and not characteristic.is_prime():
                    raise ValueError('characteristic must be a prime')
                if characteristic == _sage_const_0 :
                    if version == 'unitary':
                        PDomain = CyclotomicField(_sage_const_12 )
                    else:
                        PDomain = CyclotomicField(_sage_const_3 )
                else:
                    PDomain = GF( characteristic )
                minPolRootBur = PDomain[tT]( minPolRootBur )
                rootList = minPolRootBur.roots()
                if len(rootList) == _sage_const_0 :
                    Domain = minPolRootBur.splitting_field(names=('rI',)); (rI,) = Domain._first_ngens(1)
                    minPolRootBur = Domain[tT]( minPolRootBur )
                else:
                    Domain = PDomain
                rootList = minPolRootBur.roots()
                for root in rootList:
                   if root[_sage_const_0 ] == _sage_const_0 :
                        continue
                   rootBur = root[_sage_const_0 ]
                   if root[_sage_const_1 ]  == _sage_const_1 :
                        break

            else: # Domain <> None
                if characteristic == None:
                    characteristic = Domain.characteristic()
                elif characteristic <> Domain.characteristic():
                    raise ValueError('characteristic of Domain does not match given characteristic')
                minPolRootBur = Domain[tT]( minPolRootBur )
                rootList = minPolRootBur.roots()
                if len(rootList) == _sage_const_0 :
                    print "Warning: Domain extended to splitting field of", minPolRootBur
                    Domain = minPolRootBur.splitting_field(names=('rI',)); (rI,) = Domain._first_ngens(1)
                    minPolRootBur = Domain[tT]( minPolRootBur )
                rootList = minPolRootBur.roots()
                for root in rootList:
                    if root[_sage_const_0 ] == _sage_const_0 :
                        continue
                    rootBur = root[_sage_const_0 ]
                    if root[_sage_const_1 ]  == _sage_const_1 :
                        break
        else:  # rootBur <> None
            if Domain == None:
                Domain = rootBur.parent()
            if characteristic == None:
                characteristic = Domain.characteristic()
            elif characteristic <> Domain.characteristic():
                raise ValueError('characteristic of Domain does not match given characteristic')
        
            if _sage_const_1  not in Domain:
                raise ValueError('rootBur must belong to a domain containing 1')
            if version == 'unitary':
                testRootBur = Domain(rootBur**_sage_const_4  -rootBur**_sage_const_2  +_sage_const_1 ) 
                if testRootBur  <> _sage_const_0 :
                    raise ValueError('rootBur must vanish on x**4-x**2+1')        
            else:
                testRootBur = Domain(rootBur**_sage_const_2  -rootBur +_sage_const_1 ) 
                if testRootBur  <> _sage_const_0 :
                    raise ValueError('rootBur must vanish on x**2-x+1')        
       
        def conv2Domain ( LaurPol ):
            PolConst = LaurPol.polynomial_construction()
            R = Domain['tt']; (tt,) = R._first_ngens(1)
            p1 = R( PolConst[_sage_const_0 ] )
            p2 = rootBur**(PolConst[_sage_const_1 ])
            erg = p1.substitute( tt = rootBur ) * p2
            return erg
        
        BurauMat = matrix(d[_sage_const_0 ],d[_sage_const_1 ], lambda i,j:  conv2Domain(BurauOri[i,j] ) )        
        
        return BurauMat, rootBur




    


    def burau_matrix(self, rootBur = None, Domain = None, characteristic = None, reduced=False, version='default'):
        r"""
        Return the Burau matrix of the cubic braid coset. 

        If you don't see this well formatted type 

        sage: print CubicBraidElement.burau_matrix.__doc_

        This method uses the same method belonging to the Braid class, but reduces the parameter to a primitive six 
        root of unity, respectivly an element vanishing on the polynomial $x^2-x+1$

        INPUT: (all parameters are optional by keyword )

        - "rootBur": six root of unity in some field (default six 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)
        - "reduced": boolean (default: False); whether to return the reduced or unreduced Burau representation 
                     (see Braid class )
        - "characteristic": integer giving the characteristic of the domain (default is 0 or the characteristic of 
                     the doamain if given) 
        - "version":  values: 
                      'unitary': gives the unitary form according to Squier (see Braid._unitary_burau_matrix_() )
                      'default': the method behaves like the original one of the Braid -class
                      any value else: gives the reduced form given on wikipedia
     

        OUTPUT:

            The Burau matrix of the cubic braid coset with entries in the domain given by the options
         
            If you need the values of the reconstructed keywords "rootBur", "Domain" or "characteristic" use the internal 
            version _burau_matrix_ of this method

        RAISE:

           - ValueError: 'characteristic must be in integer'

           - ValueError: 'characteristic must be a prime'

           - ValueError: 'characteristic of Domain does not match given characteristic'

           - ValueError: 'rootBur must belong to a domain containing 1'

           - ValueError: 'rootBur must vanish on $x^2-x+1$ default case        

           - ValueError: 'rootBur must vanish on $x^4-x^2+1$ in case of call with version = 'unitary'
        


        EXAMPLES::

            sage: C3.<c1, c2> = CubicBraidGroup(3)
            sage: ele1 = c1*c2*c1
            sage: BurauTest = ele1.burau_matrix(); print BurauTest
            [   -zeta3         1     zeta3]
            [   -zeta3 zeta3 + 1         0]
            [        1         0         0]
            sage: BurauTest.base_ring()
            Cyclotomic Field of order 3 and degree 2
            sage:
            sage: BurauTest = ele1.burau_matrix( characteristic = 0 ); print BurauTest
            [   -zeta3         1     zeta3]
            [   -zeta3 zeta3 + 1         0]
            [        1         0         0]
            sage: BurauTest.base_ring()
            Cyclotomic Field of order 3 and degree 2
            sage:
            sage: BurauTest = ele1.burau_matrix( Domain = QQ ); print BurauTest
            Warning: Domain extended to splitting field of tT^2 - tT + 1
            [-rI + 1       1  rI - 1]
            [-rI + 1      rI       0]
            [      1       0       0]
            sage: BurauTest.base_ring()
            Number Field in rI with defining polynomial tT^2 - tT + 1
            sage:
            sage: BurauTest = ele1.burau_matrix( Domain = QQ[I, sqrt(3)] ); print BurauTest
            [ 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: BurauTest.base_ring()
            Number Field in I with defining polynomial x^2 + 1 over its base field
            sage:
            sage: BurauTest = ele1.burau_matrix( characteristic = 7 ); print BurauTest
            [3 1 4]
            [3 5 0]
            [1 0 0]
            sage: BurauTest.base_ring()
            Finite Field of size 7
            sage:
            sage: BurauTest = ele1.burau_matrix( characteristic = 2 ); print BurauTest
            [rI + 1      1 rI + 1]
            [rI + 1     rI      0]
            [     1      0      0]
            sage: BurauTest.base_ring()
            Finite Field in rI of size 2^2
            sage:
            sage: 
            sage: F4.<r64> = GF(4)
            sage: BurauTest = ele1.burau_matrix( rootBur=r64 ); print BurauTest
            [r64 + 1       1 r64 + 1]
            [r64 + 1     r64       0]
            [      1       0       0]
            sage: BurauTest.base_ring()
            Finite Field in r64 of size 2^2
            sage: 
            sage: BurauTest = ele1.burau_matrix( Domain = GF(5) ); print BurauTest
            Warning: Domain extended to splitting field of tT^2 + 4*tT + 1
            [2*rI + 2        1 3*rI + 3]
            [2*rI + 2 3*rI + 4        0]
            [       1        0        0]
            sage: BurauTest.base_ring()
            Finite Field in rI of size 5^2
            sage:
            sage: BurauTest = ele1.burau_matrix( version = 'unitary' ); print BurauTest
            [        0 -zeta12^3]
            [-zeta12^3         0]
            sage: BurauTest.base_ring()
            Cyclotomic Field of order 12 and degree 4
            sage: 
            sage: BurauTest = ele1.burau_matrix( Domain = QQ[I, sqrt(3)], version = 'unitary' ); print BurauTest
            [ 0 -I]
            [-I  0]
            sage: BurauTest.base_ring()
            Number Field in I with defining polynomial x^2 + 1 over its base field

        AUTHOR:

          - Sebastian Oehms, Sept. 2016


        REFERENCES:

           - :wikipedia: "Burau_representation"


        for more inormation type
        sage: print Braid.burau_matrix.__doc__
        sage: print local_Braid.burau_matrix.__doc__
        sage: print local_Braid.__burau_matrix_wikipedia__.__doc__
        sage: print local_Braid.__burau_matrix_unitary__.__doc__

        """

        res = self._burau_matrix_( rootBur = rootBur, Domain = Domain, characteristic = characteristic, reduced = reduced, 
                                   version = version)[_sage_const_0 ]
        return res





##############################################################################
#
#                  Class CubicBraidGroup_class (for the group itself)
#
##############################################################################
class CubicBraidGroup_class(FinitelyPresentedGroup):
    r"""
    Class to handel cubic factors of braid group on n strands

    If you don't see this well formatted type 

    sage: print CubicBraidGroup_class.__doc__

    This class implements quotient groups of the 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 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 BraidGroup class. 
 
    INPUT (to the constructor):
    
    - "names": (see the BraidGroup_class docomentation)

    - "AdditionalRelation": (keyword, explantaion see below)

    - "verbose": (keyword, explantaion see below)


    RAISE (on init):

      - ValueError: "the number of strands must be an integer larger than one"


    Setting the keyword 'AdditionalRelation' to one on the values 'S' or 'U' the additional relations due to 
    Assion are added:

     '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$ for $m >= 5$  
     'U': $t_1 t_3 = 1$                                                for $m >= 5$  


    where $t_i = (s_i s_{i+1})^3$. If AdditionalRelation='C' (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 AdditionalRelation (as finitely presented groups). But anyway, the classes for 'C', 'S' and 'U' are 
    different, since they have different classical realizations implemented .

    Setting the keyword verbose it is possible to print time stamp messages in order to do a performance or 
    call stack debugging. This keyword uses the timeStampControl class. For more information on this type

                     print setupTimeStamp.__doc__
                     print timeStampControl.__doc__
                     print timeStampControl.print_timestamp.__doc__
                     print print_time_tb.__doc__
    

    The creation of instances of this class can also be done more easy by help of the functions CubicBraidGroup, 
    AssionGroupS and AssionGroupU (similar to the function BraidGroup with respect to the BraidGroup_class)


    EXAMPLES:

        sage: from cubic_braid import *
        sage: U3 = CubicBraidGroup(3, AdditionalRelation = 'U'); U3
        Assion group on 3 strands of type U
        sage: U3.gens()
        (c0, c1)

     alternate possibilities defining U3:

        sage: U3 = AssionGroupU(3); U3
        Assion group on 3 strands of type U
        sage: U3.gens()
        (u0, u1)

        sage: U3.<u1,u2> = 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 )
        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] 
        generated by (
        [    E(3) E(12)^11]
        [       0        1], 
        [       1        0]
        [E(12)^11     E(3)])


    using verbose mode:

        sage: C3.<c1,c2> = CubicBraidGroup(3, verbose=True); C3
        L: StackInfo    Elapse:     0, Total:   0 Ident: C3 In: __init__ Line: 403
        L: StackInfo    Elapse:   197, Total:   0 Begin In: __create_classical_realization__ Line: 910
        L: StackInfo    Elapse:     8, Total:   0 Begin In: as_matrix_group Line: 1031
        L: Body         Elapse:    92, Total:   0 genList prepared In: as_matrix_group Line: 1038
        L: Body         Elapse:    52, Total:   0 MatGroup defined In: as_matrix_group Line: 1054
        L: StackInfo    Elapse:   356, Total:   0 Begin In: gap_hom Line: 143
        L: Debug        Elapse:     8, Total:   0 GroupHomomorphis In: gap_hom Line: 188
        L: Debug        Elapse:    17, Total:   0 checked if groupMap works In: gap_hom Line: 199
        L: StackInfo    Elapse:     8, Total:   0 End In: gap_hom Line: 226
        L: StackInfo    Elapse:    44, Total:   0 Begin In: __check_homomorphism__ Line: 60
        L: StackInfo    Elapse:    52, Total:   0 End In: __check_homomorphism__ Line: 625
        L: Body         Elapse:     3, Total:   0 Hom from self defined In: as_matrix_group Line: 1064
        L: StackInfo    Elapse:    62, Total:   0 Begin In: gap_hom Line: 143
        L: Debug        Elapse:     4, Total:   0 GroupHomomorphis In: gap_hom Line: 188
        L: Debug        Elapse:    20, Total:   0 checked if groupMap works In: gap_hom Line: 199
        L: StackInfo    Elapse:     4, Total:   0 End In: gap_hom Line: 226
        L: Body         Elapse:    35, Total:   0 Section to self defined In: as_matrix_group Line: 1077
        L: StackInfo    Elapse:     3, Total:   0 Ende In: as_matrix_group Line: 1102
        L: StackInfo    Elapse:     3, Total:   0 End In: __create_classical_realization__ Line: 975
        L: StackInfo    Elapse:    12, Total:   0 Ident: C3 In: __init__ Line: 472
        Cubic Braid group on 3 strands
        sage: 
        sage: 
        sage: C3.<c1,c2> = CubicBraidGroup(3, verbose=30); C3
        L: StackInfo    Elapse:    62, Total:   0 (truncated   1) Begin In: __create_classical_realization__ Line: 910
            ---> __init__ In: lib/cubic_braid.py Line: 471
            ---> __classcall__ In: /opt/sage/sage-6.9-i686-Linux/local/lib/python2.7/site-packages/sage/structure
        /unique_representation.py Line: 1021
            ---> CubicBraidGroup In: lib/cubic_braid.py Line: 1231
        L: StackInfo    Elapse:   405, Total:   0 Begin In: as_matrix_group Line: 1031
            ---> __create_classical_realization__ In: lib/cubic_braid.py Line: 968
            ---> __init__ In: lib/cubic_braid.py Line: 471
            ---> __classcall__ In: /opt/sage/sage-6.9-i686-Linux/local/lib/python2.7/site-packages/sage/structure
        /unique_representation.py Line: 1021
        L: Body         Elapse:   145, Total:   0 genList prepared In: as_matrix_group Line: 1038
            ---> __create_classical_realization__ In: lib/cubic_braid.py Line: 968
            ---> __init__ In: lib/cubic_braid.py Line: 471
            ---> __classcall__ In: /opt/sage/sage-6.9-i686-Linux/local/lib/python2.7/site-packages/sage/structure
        /unique_representation.py Line: 1021
        Cubic Braid group on 3 strands
        sage: 
    

    TESTS:

        sage: C4 = CubicBraidGroup(4)
        sage: TestSuite(C4).run()
        sage: C5 = CubicBraidGroup(5)
        sage: TestSuite(C5).run()
        sage: C6 = CubicBraidGroup(6)
        sage: TestSuite(C6).run()
        sage: S3 = AssionGroupS(3)
        sage: TestSuite(S3).run()
        sage: S4 = AssionGroupS(4)
        sage: TestSuite(S5).run()
        sage: U3 = AssionGroupU(3)
        sage: TestSuite(U3).run()
        sage: U4 = AssionGroupU(4)
        sage: TestSuite(U4).run()
        sage: U5 = AssionGroupU(5)
        sage: TestSuite(U5).run()

    METHODS (implemented / overwriten here):

        - as_classical_group(): type 
                   sage: print CubicBraidGroup_class.as_classical_group.__doc__
        - as_matrix_group(): type 
                   sage: print CubicBraidGroup_class.as_matrix_group.__doc__
        - as_refection_group(): type 
                   sage: print CubicBraidGroup_class.as_refection_group.__doc__
        - as_permutation_group(): type 
                   sage: print CubicBraidGroup_class.as_permutation_group.__doc__
        - pre_image_braid_group: type
                   sage: print CubicBraidGroup_class.pre_image_braid_group.__doc__
        - cubic_braid_subgroup(): type 
                   sage: print CubicBraidGroup_class.cubic_braid_subgroup.__doc__
        - centralizing_element(): type 
                   sage: print CubicBraidGroup_class.centralizing_element.__doc__
        - order(): type 
                   sage: print CubicBraidGroup_class.order.__doc__
        - character_table(): type 
                   sage: print CubicBraidGroup_class.character_table.__doc__

    AUTHOR

      - Sebastian Oehms, Sept. 2016

    REFERENCES:

    - Coxeter, H.S.M: "Factor groups of the braid groups, Proceedings of the Fourth Candian Mathematical Congress
      (Vancover      1957), pp. 95-122".
    
    - J. Assion: "Einige endliche Faktorgruppen der Zopfgruppen" (Math. Z., 163 (1978), 291-302) 
    """



    Element = CubicBraidElement

    ###########################################################################################
    # private methods
    ###########################################################################################
    def __init__(self, names, AdditionalRelation = 'C', verbose = False ):
        """
        Python constructor.

        for more information type

        sage: print CubicBraidGroup_class.__doc__ 
    

        AUTHOR

          - Sebastian Oehms, Sept. [email protected][email protected]

        """

        self._AdditionalRelation_ = AdditionalRelation
        self._verbose_            = verbose

        n  = Integer(len(names))
        self._nstrands_ = n+_sage_const_1 
        self._ident_ = self._AdditionalRelation_ + self._nstrands_.str()

        self._TimeStamp_ = setupTimeStamp( verbose = verbose, Offset = _sage_const_2 , ShowDateTime = False )
        self._TimeStampSub_ = setupTimeStamp( verbose = verbose, Offset = _sage_const_1 , ShowDateTime = False )
        self.__print_timestamp__( "Ident: %s" %(self._ident_), TsLevel.StackInfo )


        b  = []
        bi = []
        t  = []
        ti = []
 
        sage.groups.braid.BraidGroup_class = local_BraidGroup_class
        self._pre_image_braid_group_ = BraidGroup( names )


        if n<_sage_const_1 : #n is the number of generators, not the number of strands (see ticket 14081)
            raise ValueError("the number of strands must be an integer larger than one")
        free_group = FreeGroup(names)

        oneHundertMB = _sage_const_100 *_sage_const_1024 **_sage_const_2 
        work_space_needed = {'C5':_sage_const_5 , 'C6':_sage_const_48 , 'U6':_sage_const_24 , 'S6':_sage_const_24  }
        if self._ident_ in work_space_needed.keys(): # need to extend GAP-workspace
            gap_extend_workspace( work_space_needed[self._ident_]*oneHundertMB )
        
       
        # internal naming of elements for convinience
        for i in range(_sage_const_1 , n+_sage_const_1 ):
            b.append(free_group([i]))
            bi.append(free_group([-i]))
            if i < n:
                tt = free_group([i, i+_sage_const_1 ])**_sage_const_3  
                t.append(tt)
                tt = free_group([-i, -i-_sage_const_1 ])**_sage_const_3  
                ti.append(tt)

        # first the braid relation
        rels = list(self._pre_image_braid_group_.relations())

        # then the cubic relation
        for i in range(_sage_const_0 , n):
            rels.append(b[i]**_sage_const_3 )
 
        # then Assions relation Satz 2.2 type='S'  Satz 2.4 type='U'
        if n>_sage_const_3 : 
            for i in range(_sage_const_0 , n-_sage_const_3 ):
                if AdditionalRelation == 'U':
                    rels.append((t[i]*t[i+_sage_const_2 ])**_sage_const_3 )
                elif AdditionalRelation == 'S':
                    rels.append(b[i+_sage_const_2 ]*b[i]*t[i+_sage_const_1 ]*b[i]*ti[i+_sage_const_1 ]*t[i+_sage_const_2 ]*t[i+_sage_const_1 ]*b[i]*ti[i+_sage_const_1 ]*ti[i+_sage_const_2 ])


        FinitelyPresentedGroup.__init__(self, free_group, tuple(rels))
        self._nstrands_ = n+_sage_const_1 
        self._ident_ = self._AdditionalRelation_ + self._nstrands_.str()
        self._b_   = b
        self._bi_  = bi
        self._t_   = t
        self._ti_  = ti
        self._free_group_ = free_group
        self._checked_homomorphism_=[]


        # ------------------------------------------------------------------------------------------------
        # 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_group_gens_        = None   # generators of the former group 
        self._classical_base_group_        = None   # this only differs special cases for AssionGroup from the former
        self._classical_base_group_gens_   = None   # generators of the former group
        self._centralizing_matrix_         = None   # for AssionGroup: element in classical base group commuting self
        self._centralizing_element_        = None   # image under nat. map of the former one in the proj. classical group
        self._classical_embedding_         = None   # as subgroup of classical base group (if different from class. group) 

        self.__create_classical_realization__()
        self.__print_timestamp__( "Ident: %s" %(self._ident_), TsLevel.StackInfo )

        return



    def __reduce__(self):
        """
        Checks or unity

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.__recuce__.__doc__

        TESTS:

            sage: C3=CubicBraidGroup(3)
            sage: C3.__reduce__()
            (<class 'lib.cubic_braid.CubicBraidGroup_class'>, (('c0', 'c1'), 'C', False))
            sage: U3.<u1,u2>=AssionGroupU(3, verbose=100)
            sage: U3.__reduce__()
            (<class 'lib.cubic_braid.CubicBraidGroup_class'>, (('u1', 'u2'), 'U', 100))

        """
        return (CubicBraidGroup_class, (self.variable_names(), self._AdditionalRelation_, self._verbose_,))



    def _repr_(self):
        """
        Return a string representation

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class._repr_.__doc__

        OUTPUT:

        String decribing self

        TESTS:

            sage: C5 = CubicBraidGroup(5)
            sage: C5 # indirect doctest
            CubicBraid group on 5 strands 
        """
        if self._AdditionalRelation_ == 'C':
            return "Cubic Braid group on %s strands"%(self._nstrands_) 
        else:
            return "Assion group on %s strands of type %s"%(self._nstrands_ ,self._AdditionalRelation_) 


    
    # -------------------------------------------------------------------------------
    # Methods for test_suite 
    # -------------------------------------------------------------------------------
    def _test_constructions(self, **options):
        """
        Method called by TestSuite

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class._test_constructions.__doc__

        the following is checked:
           - construction of classical group was faithfull
           - construction of permutation groups attached to self is faithful
           - coercion maps to and from classical group exist and are inverse to each other
           - coercion maps to and from permutatiobn group exist and are inverse to each other
           - existence of some examples of matrix representations and commutativity between coercion maps

        AUTHOR

          - Sebastian Oehms, Sept. 2016

        """
        # ------------------------------------------------------------------------
        # testing existence of classical group and coercion maps to and from self
        # ------------------------------------------------------------------------

        self.__print_timestamp__( "Begin", TsLevel.StackInfo )

        Cl=self.as_classical_group()
        homToClass = Cl.coerce_map_from( self )
        homToClassNotNone = self._tester(**options)
        homToClassNotNone.assert_( homToClass != None )
        homToClassCheck = self._tester(**options)

        self.__print_timestamp__ ("Check hom to classical", TsLevel.Body ) 
        homToClassCheck.assert_( self.__check_homomorphism__( homToClass ) == True )

        self.__print_timestamp__ ("Section from classical", TsLevel.Body ) 
        sectFromClass = self.coerce_map_from( Cl )
        sectFromClassNotNone = self._tester(**options)
        sectFromClassNotNone.assert_( sectFromClass != None )


        # ------------------------------------------------------------------------
        # testing if coercion maps are inverse to each other
        # ------------------------------------------------------------------------
        self.__print_timestamp__ ("Testing inverse", TsLevel.Body ) 
        Clgen1 = Cl.gens()[_sage_const_0 ]
        Clgen1Braid = self(Clgen1)
        Clgen1Back = Cl(Clgen1Braid)
        testClgen1Back = self._tester(**options)
        testClgen1Back.assert_( Clgen1Back == Clgen1 )

        # ------------------------------------------------------------------------
        # testing the order calculation of the group
        # ------------------------------------------------------------------------
        self.__print_timestamp__ ("Testing order", TsLevel.Body )

        orderForm = self.order()
        orderCalc = self.order( by_formula = False ) 
        testOrder = self._tester(**options)
        testOrder.assert_( orderForm == orderCalc )
            
        # ------------------------------------------------------------------------
        # preparing tests of matrix and permutation groups
        # ------------------------------------------------------------------------
        F3 = GF(_sage_const_3 ); r63=F3(_sage_const_2 ); F4 = GF(_sage_const_4 , names=('r64',)); (r64,) = F4._first_ngens(1)

        self.__print_timestamp__ ("Testing permutation and matrix group", TsLevel.Body ) 

        def test_attached_group( AttGroup, EleClass, EleSelf ):
            """
            local function in CubicBraidGroup_class._test_constructions.__doc__

            it tests conversion maps from self and the classical group to the given attached Group which must have 
            been defined using the as_matrix_group or as_ermutation_group methods

            INPUT:

             - "AttGroup": attached group (matrix group or permutation group) to be tested
             - "EleSelf":  element of self used to perform the test
             - "EleClass":  element of the classical group of self used to perform the test

            """
            self.__print_timestamp__("Begin", TsLevel.StackInfo)
            AttEleSelf = AttGroup(EleSelf)
            self.__print_timestamp__ ("rightHandSide", TsLevel.BodySub1) 
            AttEleClass = AttGroup(EleClass)
            self.__print_timestamp__ ("leftHandSide", TsLevel.BodySub1) 
            AttComute = self._tester(**options)
            AttComute.assert_(AttEleSelf == AttEleClass)
            self.__print_timestamp__("End", TsLevel.StackInfo)



        # ---------------------------------------------------------------------------------------------
        # existence of attached reflection group and commutativity between coercion maps
        # ---------------------------------------------------------------------------------------------
        self.__print_timestamp__ ("reflection group", TsLevel.BodySub1) 
        try:
            # ---------------------------------------------------------------------------------------------
            # the reflection group may not be constructable in the following plausible cases:
            #  - sage version is less than 7.2 -> class IrreducibleComplexReflectionGroup is not availlable
            #  - gap3 or CHEVIE is not installed
            #  - self is not of type 'C' or not finite
            # ---------------------------------------------------------------------------------------------
            Refl = self.as_reflection_group()
        except:
            Refl = None

        if Refl != None: 
            test_attached_group(Refl, Clgen1, Clgen1Braid)


        # ---------------------------------------------------------------------------------------------
        # existence of attached permutation groups and commutativity between coercion maps
        # ---------------------------------------------------------------------------------------------
        self.__print_timestamp__ ("permutation group", TsLevel.BodySub1) 
        Perm = self.as_permutation_group()
        test_attached_group(Perm, Clgen1, Clgen1Braid)

        self.__print_timestamp__ ("native permutation group", TsLevel.BodySub1) 
        if self._nstrands_ < _sage_const_4 :
            PermN = self.as_permutation_group(native=True)
            test_attached_group(PermN, Clgen1, Clgen1Braid)

        # ---------------------------------------------------------------------------------------------
        # existence of some examples of matrix representations and commutativity between coercion maps
        # ---------------------------------------------------------------------------------------------
        self.__print_timestamp__ ("Default MatrixGroup", TsLevel.BodySub1) 
        MatDEF = self.as_matrix_group()
        test_attached_group(MatDEF, Clgen1, Clgen1Braid)

        self.__print_timestamp__ ("MatrixGroup over GF(3)", TsLevel.BodySub1) 
        if self._AdditionalRelation_ != 'U' or self._nstrands_ < _sage_const_5 : # not well defined elsewise
            MatF3 = self.as_matrix_group(rootBur=r63)
            test_attached_group(MatF3, Clgen1, Clgen1Braid)

        self.__print_timestamp__ ("MatrixGroup over GF(4)", TsLevel.BodySub1) 
        if self._AdditionalRelation_ != 'S' or self._nstrands_ < _sage_const_5 : # not well defined elsewise
            MatF4 = self.as_matrix_group(rootBur=r64)
            test_attached_group(MatF4, Clgen1, Clgen1Braid)

        self.__print_timestamp__ ("MatrixGroup over GF(5)", TsLevel.BodySub1) 
        if self._nstrands_ < _sage_const_5  or self._AdditionalRelation_ == 'C':
            MatF5 = self.as_matrix_group(characteristic = _sage_const_5 )
            test_attached_group(MatF5, Clgen1, Clgen1Braid)

            self.__print_timestamp__ ("MatrixGroup over GF(7)", TsLevel.BodySub1) 
            MatF7 = self.as_matrix_group(Domain=GF(_sage_const_7 ))
            test_attached_group(MatF7, Clgen1, Clgen1Braid)
        
        self.__print_timestamp__("End", TsLevel.StackInfo)

        return

    # -------------------------------------------------------------------------------
    # -------------------------------------------------------------------------------
    # local utility-methods
    # -------------------------------------------------------------------------------
                                            
    def __print_timestamp__( self, Text, Level ):
        """
        Method to print time stamped logging messages

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.__print_timestamp__.__doc__

        This method uses the timeStampControl class. For more information on this type

        print timeStampControl.__doc__
        print timeStampControl.print_timestamp.__doc__
        print print_time_tb.__doc__

        INPUT:
 
            - "Text":  Text to be printed in the log message
            - "Level": indicates the level (importance) of the message. The following values are posible
               0 TsLevel.Silent    to be pinted independent on any verbose mode
               1 TsLevel.StackInfo classifies messages on entry and exit of subroutines
               2 TsLevel.Body      to be used in the body of a function
               3 TsLevel.BodySub1  subordinary message to TsLevel.Body
               4 TsLevel.BodySub2  subordinary message to TsLevel.Body1
               5 TsLevel.Debug     to print debug information 

        Note, that the higher levels include the for comming lower ones. 

        AUTHOR

          - Sebastian Oehms, Sept. 2016

        """
        self._TimeStamp_.print_timestamp( Text = Text, Level = Level )

 

    # -------------------------------------------------------------------------------
    # Method to check if a map from self to another group vanisches on the relations 
    # of self
    # -------------------------------------------------------------------------------
    def __check_homomorphism__(self, test_map ):
        """
        Method to check if the given map is well defined with respect to the relations of self

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.__check_homomorphism__.__doc__

        INPUT:

            - "test_map": the map from self to another group to be tested

        OUTPUT:

            boolean True if test_map vanishes on all relations of self, else false

        WARNINGS:

            "Warning: homomorphism not well defined for relation %s giving: %s" n case the result is False

        EXAMPLES:
        
           sage: S4.<s1,s2,s3>=AssionGroupS(4);  S4
           Assion group on 4 strands of type S
           sage: S4Cl = S4.as_classical_group()
           sage: f = S4Cl.convert_map_from( S4 )
           sage: S4.__check_homomorphism__(f)
           True

         Note, the following may be an irritation: The generators of S4 and S4Cl are the same as set but in different order

           sage: ClassGens=S4Cl.gens(); ClassGens
           [(5,8,11)(6,9,12)(7,10,13)(23,26,29)(24,27,30)(25,28,31)(32,38,35)(33,39,36)(34,40,37),
            (2,11,8)(3,13,9)(4,12,10)(17,35,26)(18,36,27)(19,37,28)(20,29,38)(21,30,39)(22,31,40),
            (1,25,24)(2,29,26)(3,27,31)(6,16,33)(7,34,15)(8,20,35)(9,36,22)(11,38,17)(13,18,40)]

           sage: S4Cl(s1)
           (2,11,8)(3,13,9)(4,12,10)(17,35,26)(18,36,27)(19,37,28)(20,29,38)(21,30,39)(22,31,40)
           sage: S4Cl(s2)
           (5,8,11)(6,9,12)(7,10,13)(23,26,29)(24,27,30)(25,28,31)(32,38,35)(33,39,36)(34,40,37)

        AUTHOR

          - Sebastian Oehms, Sept. 2016

        """

        self.__print_timestamp__( "Begin", TsLevel.StackInfo ) 
        check_needed = True
        checked_homomorphism = list(self._checked_homomorphism_) 
        if checked_homomorphism != None:
            if test_map in checked_homomorphism:
                check_needed = False


        if (check_needed == False ):
            return True

        self.__print_timestamp__( "check_needed", TsLevel.Body ) 

        for relation in list(self.relations()):
            self.__print_timestamp__( "relation %s"%(relation), TsLevel.Debug ) 
            relVal = test_map(relation)
            self.__print_timestamp__( "relation tested", TsLevel.Debug ) 
            if relVal.is_one() == False:
                print "Warning: homomorphism not well defined for relation %s giving: %s"%(relation, relVal )
                return False

        self.__print_timestamp__( "check_ok", TsLevel.Body ) 

        checked_homomorphism.append( test_map )

        self.__print_timestamp__( "check_registerd", TsLevel.Body ) 

        self._checked_homomorphism_ = checked_homomorphism
        self.__print_timestamp__( "End", TsLevel.StackInfo ) 
        return True 


    def __create_classical_realization__(self):
        """
        internal method to create the classical groups attached to self

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.__create_classical_realization__.__doc__

        INPUT:

           no

        OUTPUT:

           no

        this methods sets the following global parameters of self: 

         - self._classical_group_            This is the classical group returned by as_classical_group method
         - self._classical_group_gens_       generators of the former group 
         - self._classical_base_group_       this only differs in special cases for AssionGroup from the former
         - self._classical_base_group_gens_  generators of the former 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 class. group) 

        AUTHOR

          - Sebastian Oehms, Sept. 2016

        """

        # -------------------------------------------------------------------------------
        # local methods to create maps to and from the classical group
        # -------------------------------------------------------------------------------



        # -------------------------------------------------------------------------------
        # create a map from  self to the classical realization 
        # via transvections using the work of Assion
        # -------------------------------------------------------------------------------
        def create_hom_to_classical( self, Group, ImList ):
            """
            internal method to create the homomorphism from self to classical group

            this is a local function in CubicBraidGroup_class.__create_classical_realization__ using
            gap_hom

            see also:
            sage: print gap_hom.__doc__
           
            INPUT:

              - "Group": target of the map
              - "ImList": list of the images of the braid generators

            OUTPUT:

              the created homomorphism. 

            The created homomorphism is registered as coercion and conversion map for Group

            AUTHOR

              - Sebastian Oehms, Sept. 2016

            """
            self.__print_timestamp__( "Begin", TsLevel.StackInfo )
            if ImList[_sage_const_0 ] in Group:
                homToGroup = gap_hom(  self, Group, GensTo = ImList, verbose = self._TimeStampSub_ )
            else:
                GroupImage = ImList[_sage_const_0 ].parent()
                homToImage = gap_hom(  self, GroupImage, GensTo = ImList, verbose = self._TimeStampSub_ )
                homToGroup = homToImage
                if Group.has_coerce_map_from( GroupImage ):
                    incl = Group.coerce_map_from( GroupImage )
                    homToGroup = incl * homToImage
                    Group.register_coercion( homToGroup )
            self.__print_timestamp__( "End", TsLevel.StackInfo )
            return homToGroup




 
        # -------------------------------------------------------------------------------
        # Set up all incrediences of the classical group (generic part)
        # -------------------------------------------------------------------------------
        def SetUpClassicalGroup( self, m, n, BaseGroup, ProjGroup, centralizing_vector, transvec2mat, transvecList ):
            """
            internal method to create classical group for Assion groups

            this is a local function in CubicBraidGroup_class.__create_classical_realization__ 

            It handels the common part of symplectic and unitary version and creates all conversion map using gap_hom

            see also:
            sage: print gap_hom.__doc__

            INPUT:

             - "BaseGroup": The symplectic or unitary groups Sp(m,3) resp. GU(m,2)
             - "ProjGroup": The projeective imaged of these group
             - "centralizing_vector": The centralizing vector described by Assion
             - "transvec2mat": Function to create the transection map from transvection vector
             - "transvecList": List of transvection vectors

            OUTPUT:
            
            the function sets the global parameters of self decribed under

            sage: print CubicBraidGroup_class.__create_classical_realization__.__doc__

            AUTHOR

              - Sebastian Oehms, Sept. 2016

            """


            self.__print_timestamp__( "Begin", TsLevel.StackInfo )

            centralizing_matrix = BaseGroup(transvec2mat(centralizing_vector, fact=_sage_const_1 ))
            centralizing_element = None

            # ------------------------------------------------------------------------------
            # preparing the projective group realizaton
            # ------------------------------------------------------------------------------
            natHom = gap_hom( BaseGroup, ProjGroup, verbose = self._TimeStampSub_ )


            # ------------------------------------------------------------------------------
            # Setting the List of Braid Images or try to fetch them from library
            # ------------------------------------------------------------------------------
            ClGenList=[]
            centralizing_element = natHom( centralizing_matrix )                

            anz_tv=_sage_const_0 
            BaseClGenList=[]
            for v in transvecList:
                anz_tv=anz_tv+_sage_const_1         
                if anz_tv >= n:
                    break
                transvecMat = transvec2mat( v )
                BaseClGenList.append( BaseGroup(transvecMat) )
                if m == n:  # case of centralizer in projective group
                    projTransvecMat = natHom( transvecMat )
                    ClGenList.append( projTransvecMat )
                else:
                    ClGenList.append( BaseGroup(transvecMat) )


            ClassicalGroup = BaseGroup
            if m == n:  # case of centralizer in projective group
                #  ClassicalGroup = ProjGroup.centralizer( centralizing_element ) # to large set of generators
                ClassicalGroup = ProjGroup.subgroup( ClGenList )
                for gen in ClGenList:    # checking centralizer property
                    if gen * centralizing_element != centralizing_element *gen:
                        print "Internal Error! centralzier property failed for:", gen, centralizing_element 
 
            Embedding = None
            if ClassicalGroup == BaseGroup:
                create_hom_to_classical( self, ClassicalGroup,  ClGenList )
                gap_hom( ClassicalGroup, self, GensFrom = ClGenList, verbose = self._TimeStampSub_ )
            else:
                Embedding = BaseGroup.subgroup( BaseClGenList )
                create_hom_to_classical( self, ClassicalGroup,  ClGenList )
                create_hom_to_classical( self, Embedding,       BaseClGenList )
                try:
                    # --------------------------------------------------------------------------------------
                    # Note: this may fail for large permutation groups such as AssionGroupU( 6 )
                    # gap-Error: Gap terminated unexpectedly while reading in a large line
                    # --------------------------------------------------------------------------------------
                    gap_hom( ClassicalGroup, self, GensFrom = ClGenList, verbose = self._TimeStampSub_ )
                except:
                    print "Warning: no map back from classical group (gap overflow)"

                gap_hom( Embedding,  self, GensFrom = BaseClGenList, verbose = self._TimeStampSub_ )
                


            self._classical_group_             = ClassicalGroup
            self._classical_group_gens_        = ClGenList
            self._classical_base_group_        = BaseGroup
            self._classical_base_group_gens    = BaseClGenList
            self._centralizing_matrix_         = centralizing_matrix
            self._centralizing_element_        = centralizing_element
            self._classical_embedding_         = Embedding

            self.__print_timestamp__( "End", TsLevel.StackInfo )
            return 



        # -------------------------------------------------------------------------------
        # local methods to set up the classical group (spezific part)
        # -------------------------------------------------------------------------------
        # Case for symlectic groups
        # -------------------------------------------------------------------------------
        def create_transvecListSympl( self, m ):
            """
            internal method to create classical group for symplectic Assion groups (type 'S' )

            this is a local function in CubicBraidGroup_class.__create_classical_realization__

            INPUT

             - m  the dimension of the classical groups vectorspace of operation

            The routine calculates the central vector and the transvections as vector as given by Assion and then uses
            SetUpClassicalGroup to complete the construction

            AUTHOR

              - Sebastian Oehms, Sept. 2016

            """
            self.__print_timestamp__( "Begin", TsLevel.StackInfo )

            # -----------------------------------------------------------
            # getting the invariant bilinearform of the group
            # in symplectic case possible by corresponding method
            # and setting constants
            # -----------------------------------------------------------
            BaseGroup = Sp( m, _sage_const_3  )
            ProjGroup = PSp( m, _sage_const_3  )

            bform = BaseGroup.invariant_form()
            n = self._nstrands_ 
            bas =bform.column_space().basis()
            if m % _sage_const_2  == _sage_const_0 :
                mhalf = m/_sage_const_2 
            else:
                mhalf = (m-_sage_const_1 )/_sage_const_2  
                        
            # -----------------------------------------------------------
            # computing a hyperbolic decomposition basis with respect
            # to the invariant bilinear form
            # -----------------------------------------------------------
            xbas =[]
            ybas =[]
            for i in range(mhalf):            
                xbas.append( bas[mhalf -i -_sage_const_1 ] )
                ybas.append( bas[mhalf +i ] )
            
            # -----------------------------------------------------------
            # computing the List of transvection vectors according to
            # Assion paper, page 292
            # -----------------------------------------------------------
            transvecList =[xbas[_sage_const_0 ]]                                   # t_1      = x_1
            for i in range(mhalf-_sage_const_1 ):            
                transvecList.append(ybas[i])                          # t_{2i}   = y_i 
                transvecList.append(xbas[i] + xbas[i+_sage_const_1 ] )             # t_{2i+1} = x_j + x_(j+1)
            transvecList.append(ybas[mhalf-_sage_const_1 ]  )                      # t_n      = y_m 

            # -----------------------------------------------------------
            # Convertion-Map from transvection vector to transvection
            # matrix
            # -----------------------------------------------------------
            def transvec2mat( v, bas=bas, bform=bform, fact=_sage_const_1  ):
                t = []
                for x in bas:
                    t.append( x + fact*(x * bform * v) * v )
                Mt = matrix( bform.base_ring(),  t )
                return Mt

            # ------------------------------------------------------------------------------
            # setting the centralizing matrix for the case of projective group realizaton
            # ------------------------------------------------------------------------------
            central_vector = xbas[mhalf-_sage_const_1 ]

            SetUpClassicalGroup( self, m, n, BaseGroup, ProjGroup, central_vector, transvec2mat, transvecList )

            self.__print_timestamp__( "End", TsLevel.StackInfo )

            return
        


        # -------------------------------------------------------------------------------
        # Case for unitary groups
        # -------------------------------------------------------------------------------
        def create_transvecListUnitar( self, m ):
            """
            internal method to create classical group for unitary Assion groups (type 'U' )

            this is a local function in CubicBraidGroup_class.__create_classical_realization__

            INPUT

             - m  the dimension of the classical groups vectorspace of operation

            The routine calculates the central vector and the transvections as vector as given by Assion and then uses
            SetUpClassicalGroup to complete the construction

            AUTHOR

              - Sebastian Oehms, Sept. 2016

            """

            self.__print_timestamp__( "Begin", TsLevel.StackInfo )

            # ---------------------------------------------------------------------
            # getting the invariant bilinearform of the group and setting constants
            # in unitary case this is not implemented in sage but can 
            # be looked up by the GAP-function InvariantSesquilinearForm
            # for instance:
            # gap> GU3:=GeneralUnitaryGroup( 3, 2 );
            # gap> InvariantSesquilinearForm(GU3);
            # rec( matrix := [ [ 0*Z(2), 0*Z(2), Z(2)^0 ], [ 0*Z(2), Z(2)^0, 0*Z(2) ], [ Z(2)^0, 0*Z(2), 0*Z(2) ] ] )
            # ---------------------------------------------------------------------

            BaseGroup = GU( m, _sage_const_2  )
            ProjGroup = PGU( m, _sage_const_2  )
            oneMat = BaseGroup.one().matrix()
            n = self._nstrands_ 
            bform = matrix( m,m, lambda i,j: oneMat[i, m-_sage_const_1 -j] )
            bas = bform.column_space().basis()
            BasR = bform.base_ring()
            vA = BasR.gen()

            if   m % _sage_const_3  == _sage_const_1 :
                mthird = (m-_sage_const_1 )/_sage_const_3 
            elif m % _sage_const_3  == _sage_const_2 :
                mthird = (m-_sage_const_2 )/_sage_const_3  
            else:
                mthird = m/_sage_const_3  

            # -----------------------------------------------------------
            # computing a orthonormal basis with respect
            # to the invariant bilinear form
            # -----------------------------------------------------------
            xbas =[]
            for i in range(m):
                if _sage_const_2 *i == m-_sage_const_1 :
                    xbas.append(bas[i])
                else:
                    xbas.append( vA*bas[i] + vA.frobenius()*bas[m-_sage_const_1 -i])
            
            # -----------------------------------------------------------
            # computing the List of transvection vectors according to
            # Assion paper, page 293
            # -----------------------------------------------------------
            transvecList =[xbas[_sage_const_0 ]]                                           # t_1 = x_1
            if m > _sage_const_1 :
                transvecList.append(xbas[_sage_const_0 ]+xbas[_sage_const_1 ]+xbas[_sage_const_2 ] )                 # t_2 = x_1 + x_2 + x_3
            for j in range(mthird):
                pos = _sage_const_3 *(j+_sage_const_1 ) -_sage_const_1         # 3i-1, j = i-1: j=0, i=1, pos=2  x_{pos} =xbas[pos-1]
                transvecList.append(xbas[pos-_sage_const_1 ])                              # t_{3i}   = x_{3i-1} 
                if  pos +_sage_const_1  < m:
                    transvecList.append(xbas[pos-_sage_const_1 ]+xbas[pos]+xbas[pos+_sage_const_1 ] )   # t_{3i+1} = x_{3i-1} + x_{3i} + x_{3i+1}
                if  pos +_sage_const_3  < m:
                    transvecList.append(xbas[pos+_sage_const_1 ]+xbas[pos+_sage_const_2 ]+xbas[pos+_sage_const_3 ] ) # t_{3i+2} = x_{3i+1} + x_{3i+2} + x_{3i+3}

            # -----------------------------------------------------------
            # Convertion-Map from transvection vector to transvection
            # matrix
            # -----------------------------------------------------------
            def transvec2mat( v, bas=bas, bform=bform, fact=vA ):

                def conjVec( vec ):
                     erg = list(vec)
                     for i in range(len(vec)):
                        erg[i] = erg[i].frobenius()
                     return vector(erg)

                t = []
                for x in bas:
                    # note x does not change under conjugation, since it belongs to standard basis
                    t.append( x + fact *(x * bform * conjVec(v)) * v )
                Mt = matrix( bform.base_ring(),  t )
                return Mt


            # ------------------------------------------------------------------------------
            # setting the centralizing matrix for the case of projective group realizaton
            # ------------------------------------------------------------------------------
            central_vector = xbas[m-_sage_const_2 ]+xbas[m-_sage_const_1 ]

            SetUpClassicalGroup( self, m, n, BaseGroup, ProjGroup, central_vector, transvec2mat, transvecList )

            self.__print_timestamp__( "End", TsLevel.StackInfo )

            return


        #----------------------------------------------------------------------------------------------------------
        #----------------------------------------------------------------------------------------------------------
        # local functions definition section finishes here
        #----------------------------------------------------------------------------------------------------------
        #----------------------------------------------------------------------------------------------------------

        self.__print_timestamp__( "Begin", TsLevel.StackInfo )
        
        # -------------------------------------------------------------------------------
        # initializatn of constants
        # -------------------------------------------------------------------------------
        n = self._nstrands_ 
        anz_gen = n-_sage_const_1 

        # -------------------------------------------------------------------------------
        # Setting the Classical group
        # -------------------------------------------------------------------------------
        if   n == _sage_const_1 :
            ClassicalGroup = AbelianGroup([_sage_const_1 ])
            self._classical_group_            = ClassicalGroup
            self._classical_group_gens_       = ClassicalGroup.gens()
            self._classical_base_group_       = ClassicalGroup
            self._classical_base_group_gens_  = ClassicalGroup.gens()
        elif n == _sage_const_2  and self._AdditionalRelation_ =='C':
            ClassicalGroup = AbelianGroup([_sage_const_3 ])
            self._classical_group_            = ClassicalGroup
            self._classical_group_gens_       = ClassicalGroup.gens()
            self._classical_base_group_       = ClassicalGroup
            self._classical_base_group_gens_  = ClassicalGroup.gens()
        else:
            dim_sympl_group   = n-_sage_const_1              # for S(n-1) = Sp(n-1, 3)
            dim_unitary_group = n-_sage_const_1              # for U(n-1) = GU(n-1, 2)
            if n % _sage_const_2  == _sage_const_0 :
                dim_sympl_group   = n           # for S(n-1) = Z(PSp(n, 3))
            if n % _sage_const_3  == _sage_const_0 :
                dim_unitary_group = n           # for U(n-1) = Z(PGU( n, 3))


            if   self._AdditionalRelation_ =='S':
                create_transvecListSympl( self,  dim_sympl_group   )
            elif self._AdditionalRelation_ =='U':
                create_transvecListUnitar( self, dim_unitary_group )
            else:
                # -----------------------------------------------------------------------------------------------
                # connection between Coxeter realization and unitary Burau representation according to Squier
                # -----------------------------------------------------------------------------------------------
                # 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 (z12 = gap E(12))
                # i\theta = z12^5
                # unitary Form of Coxeter: f 
                # unitary Form of Squier: J(s) 
                #     Then we have J(z12) = 2 f
                # unitary Burau Matrix Coxeter for b_1: buc_i
                # unitary Burau Matrix Squier  for b_1: bus_i
                #     Then we have buc_i[i,i-1] = buc_[i,i+1]= - z12^5, buc_[i,i] = 1 + 2*cos(\pi/6)*z12^5
                #     Then we have bus_i[i,i-1] = bus_[i,i+1]=   s,     bus_[i,i] = -s^2
                # now - z12^5 = z12^(-1)
                # and 1 + 2*cos(\pi/6)*z12^5 = 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^(-1)
                # -----------------------------------------------------------------------------------------------
                UCF = UniversalCyclotomicField()
                z12inverse = UCF.gen(_sage_const_12 ,_sage_const_11 )
                ClassicalGroup = self.as_matrix_group( rootBur=z12inverse, Domain=UCF, version='unitary', check=False )
                self._classical_group_            = ClassicalGroup
                self._classical_group_gens_       = ClassicalGroup.gens()
                self._classical_base_group_       = ClassicalGroup
                self._classical_base_group_gens_  = ClassicalGroup.gens()
                self._classical_embedding_        = ClassicalGroup

        self.__print_timestamp__( "End", TsLevel.StackInfo )

        return





    # ----------------------------------------------------------------------------------
    # ----------------------------------------------------------------------------------
    # public methods
    # ----------------------------------------------------------------------------------
    # change_debug_options
    # ----------------------------------------------------------------------------------
    def change_debug_options(self, verbose = None, for_subroutine = False, ShowDateTime = False ):
        """
        Changes the options for timestamp debug log messages

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.change_debug_options.__doc__

        The verbose -mode which has been set in the constructor can be modified here. It is possible set the mode
        separately for main routines (this module) and routines from external modules.

        Furthermore the printing of the datetime-string in the messages can be turned on

        INPUT (all optional keywords):

           - "verbose"       (default = unchanged) the new verbose mode to be set. For more informati9on on the possible 
                             values type sage: print CubicBraidGroup_class.__doc__
           - "for_subroutine" boolean (default = False): decides wether to apply the setting to log messages of this module 
                             (False) or to subroutines from external modules (True) such as lib.utils_gap_interface
           - "ShowDateTime"   boolean (default = False): decides wether to print a datetime-string in the msages 

        EXAMPLES:

          sage: from cubic_braid import *
          sage: C3 = CubicBraidGroup(3)
          sage: C3.change_debug_options(verbose=True)
          sage: C5c5= C3.as_matrix_group( characteristic=5)
          L: StackInfo   :  Elapse:  4711, Total:   4 Begin In: as_matrix_group Line: 1789
          L: Body        :  Elapse:   685, Total:   5 genList prepared In: as_matrix_group Line: 1805
          L: Body        :  Elapse:   147, Total:   5 MatGroup defined In: as_matrix_group Line: 1830
          L: StackInfo   :  Elapse:    38, Total:   5 Begin In: __check_homomorphism__ Line: 1058
          L: Body        :  Elapse:     2, Total:   5 check_needed In: __check_homomorphism__ Line: 1069
          L: Debug       :  Elapse:     2, Total:   5 relation c0*c1*c0*c1^-1*c0^-1*c1^-1 In: __check_homomorphism__ Line: 
                                                      1072
          L: Debug       :  Elapse:     6, Total:   5 relation tested In: __check_homomorphism__ Line: 1074
          L: Debug       :  Elapse:     6, Total:   5 relation c0^3 In: __check_homomorphism__ Line: 1072
          L: Debug       :  Elapse:     5, Total:   5 relation tested In: __check_homomorphism__ Line: 1074
          L: Debug       :  Elapse:     6, Total:   5 relation c1^3 In: __check_homomorphism__ Line: 1072
          L: Debug       :  Elapse:     6, Total:   5 relation tested In: __check_homomorphism__ Line: 1074
          L: Body        :  Elapse:     8, Total:   5 check_ok In: __check_homomorphism__ Line: 1079
          L: Body        :  Elapse:     3, Total:   5 check_registerd In: __check_homomorphism__ Line: 1083
          L: StackInfo   :  Elapse:     5, Total:   5 End In: __check_homomorphism__ Line: 1086
          L: Body        :  Elapse:     2, Total:   5 Hom from self defined In: as_matrix_group Line: 1840
          L: Body        :  Elapse:   904, Total:   6 Section to self defined In: as_matrix_group Line: 1853
          L: Body        :  Elapse:     4, Total:   6 section to classical group defined In: as_matrix_group Line: 1873
          L: StackInfo   :  Elapse:   367, Total:   6 Ende In: as_matrix_group Line: 1893
          sage: 
          sage: C3.change_debug_options(ShowDateTime = True)
          sage: C5c5= C3.as_matrix_group( characteristic=5)
          L: StackInfo   : 2017-01-26 18:01:50.782780 Elapse:  2986, Total:   2 Begin In: as_matrix_group Line: 1789
          L: Body        : 2017-01-26 18:01:50.859565 Elapse:    77, Total:   3 genList prepared In: as_matrix_group Line: 
                                                                                1805
          L: Body        : 2017-01-26 18:01:50.889521 Elapse:    29, Total:   3 MatGroup defined In: as_matrix_group Line: 
                                                                                1830
          L: StackInfo   : 2017-01-26 18:01:50.908706 Elapse:    19, Total:   3 Begin In: __check_homomorphism__ Line: 1058
          ..........................................
          L: Body        : 2017-01-26 18:01:51.370860 Elapse:     3, Total:   3 section to classical group defined In: 
                                                                                as_matrix_group Line: 1873
          L: StackInfo   : 2017-01-26 18:01:51.373498 Elapse:     2, Total:   3 Ende In: as_matrix_group Line: 1893
          sage: 

        AUTHOR

          - Sebastian Oehms, Jan. 2017

        """

        if verbose == None:
            verbose = self._verbose_
 
        if for_subroutine == False:
            self._verbose_   = verbose
            self._TimeStamp_ = setupTimeStamp( verbose = verbose, Offset = _sage_const_2 , ShowDateTime = ShowDateTime )
        else:          
            self._TimeStampSub_ = setupTimeStamp( verbose = verbose, Offset = _sage_const_1 , ShowDateTime = ShowDateTime )






    # ----------------------------------------------------------------------------------
    # pre_image_braid_group
    # ----------------------------------------------------------------------------------
    def pre_image_braid_group(self):
        """
        Return an Objekt of the class BraidGroup with identical generators, such that there exists an epimorhism to self

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.pre_image_braid_group.__doc__

        OUTPUT: 

          Instance of the class BraidGroup having conversion maps to and from self (which is just a section in the 
          latter case)

        EXAMPLES:

            sage: from cubic_braid import *
            sage: U5=AssionGroupU(5); U5
            Assion group on 5 strands of type U
            sage: B5=U5.pre_image_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: 
            sage: bU == u
            True
            sage: uB == b
            True

        AUTHOR

          - Sebastian Oehms, Sept. 2016

        """
        return self._pre_image_braid_group_ 




    # ----------------------------------------------------------------------------------
    # as_matrix_group
    # ----------------------------------------------------------------------------------
    def as_matrix_group(self, rootBur=None, Domain=None, characteristic=None, reduced=False, 
                              version='default', section=True, check=True):
        """
        creates an epimorphic image of self as a matrix group by use of the burau representation

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.as_matrix_group.__doc__
 
        INPUT: (all parameters are optional by keyword )

        - "rootBur": six root of unity in some field (default six 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 
                     the doamain if given). If none of the keywords "rootBur", "Domain" and "characteristic" is given
                     the default characteristic is 3 (resp. 2) if self is of Assion type 'S' (resp. 'U')   
        - "reduced": boolean (default: False); whether to return the reduced or unreduced Burau representation (see 
                     Braid class )
        - "version":  values: 
                      'unitary': gives the unitary form according to Squier (see Braid._unitary_burau_matrix_() )
                      'default': the method behaves like the original one of the Braid -class
                      - any value else gives the reduced form given on wikipedia
        - "section"; boolean (default: True) Setting this to False creates a map back to self only in the case of
                     isomorphism. By default the map is created as a section in any case.

               compare the INPUT of
 
               sage: print CubicBraidElement.burau_matrix.__doc_

        OUTPUT:

        an instance of the class FinitelyGeneratedMatrixGroup_gap according to the Input parameters together with a map 
        from an to self and the classical group the map backwards (in both cases) is given if the the matrix group is
        isomorphic to self or if the keyword section = True (default)

        RAISE:

           - ValueError: "matrix group fails to be an epimorphic image of %s" if the burau map does not vanish on the 
                         relation of self see example with U5 below

        EXAMPLES:

            sage: from cubic_braid import *
            sage: C5=CubicBraidGroup(5)
            sage: 
            sage: M5ch5 = C5.as_matrix_group(characteristic=5); M5ch5
            Matrix group over Finite Field in rI of size 5^2 with 4 generators (
            [2*rI + 2 3*rI + 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*rI + 2 3*rI + 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*rI + 2 3*rI + 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*rI + 2 3*rI + 4]
            [       0        0        0        1        0]
            )
            sage: 
            sage: c=C5([3,4,-2,-3,1]); c
            c2*c1^-1*c0*c3*c2^-1
            sage: 
            sage: cM=M5ch5(c); cM
            [2*rI + 2 3*rI + 4        0        0        0]
            [       0        0        0        1        0]
            [2*rI + 1        0 2*rI + 2     3*rI 3*rI + 3]
            [2*rI + 2        0        0 3*rI + 4        0]
            [       0        0 2*rI + 2 3*rI + 4        0]
            sage: 
            sage: mC=C5(cM)
            sage: mC == c
            True

            sage: C5Cl=C5.as_classical_group()
            sage: 
            sage: mCl=C5Cl(cM); mCL
            [                 E(3)              E(12)^11                     0                     0]
            [            -E(12)^11                     1                 -E(4)               -E(3)^2]
            [                 E(3)              E(12)^11                E(3)^2 -2*E(12)^7 - E(12)^11]
            [                    0                     1               E(12)^7               -E(3)^2]
            sage: 
            sage: cCl=C5Cl(c)
            sage: mCl == cCl
            True
            sage: 
            sage: cClM=M5ch5(cCl)
            sage: cClM == cM
            True

            sage: U5=AssionGroupU(5); U5
            Assion group on 5 strands of type U
            sage: M5ch3 = U5.as_matrix_group(characteristic=3)
            Warning: homomorphism not well defined for relation ((u0*u1)^3*(u2*u3)^3)^3 giving: [1 1 2 1 2]
            [2 0 2 1 2]
            [2 1 1 1 2]
            [2 1 2 0 2]
            [2 1 2 1 1]
            ---------------------------------------------------------------------------
            ValueError                                Traceback (most recent call last)
            ......................
            ValueError: matrix group fails to be an epimorphic image of Assion group on 5 strands of type U
            sage: 


        AUTHOR

          - Sebastian Oehms, Sept. 2016

        """

        # -------------------------------------------------------------------------------
        # define matrix group by generotors using the Burau represntation
        # -------------------------------------------------------------------------------
        self.__print_timestamp__("Begin", TsLevel.StackInfo)


        # -------------------------------------------------------------------------------
        # adaption of default options for Assion groups on more then 4 stands
        # (in order to achive the maps beeing well defined) 
        # -------------------------------------------------------------------------------
        if rootBur == None and Domain == None and characteristic == None:
            if   self._AdditionalRelation_ == 'S':
                characteristic = _sage_const_3 
            elif self._AdditionalRelation_ == 'U':
                characteristic = _sage_const_2 
            else: 
                characteristic = _sage_const_0 
            self.__print_timestamp__("default characteristic set to %d" %(characteristic), TsLevel.Debug)


        genList =[]
        for braidGen in list(self.gens()):
            burMat = braidGen._burau_matrix_(rootBur=rootBur, Domain=Domain, characteristic=characteristic, reduced=reduced, 
                                             version=version)
            if rootBur == None:
                rootBur = burMat[_sage_const_1 ]
            if Domain == None:
                Domain = rootBur.parent()
            if characteristic == None:
                characteristic = Domain.characteristic()

            genList.append(burMat[_sage_const_0 ]) 

        self.__print_timestamp__("genList prepared", TsLevel.Body)

        avoid_gap_worspace_error = False
        if self.order() == infinity:
            avoid_gap_worspace_error = True

        if version == 'unitary':
            hermFormBraid = self.pre_image_braid_group().__unitary_form__()
            d = hermFormBraid.dimensions()[_sage_const_0 ]
            s = hermFormBraid.base_ring().gen()
            hermForm = matrix(d,d, lambda i, j: Domain(hermFormBraid[i,j].subs({s:rootBur})))
            if is_FiniteField(Domain):
                if hermForm.determinant() == _sage_const_0 :
                    print "Warning: hermitian form %s is degenerated" %(hermForm)
                BaseGroup = GU(d, Domain, var=Domain.gen(), hermitian_form=hermForm)
            else:
                BaseGroup = GU(d, Domain, hermitian_form=hermForm)

            self.__print_timestamp__("Base Group %s defined" %(BaseGroup), TsLevel.Debug)

            MatGroup = BaseGroup.subgroup(genList)

        else:
            MatGroup = MatrixGroup(genList)

        self.__print_timestamp__("MatGroup defined", TsLevel.Body)

        # -------------------------------------------------------------------------------
        # check if there is a well defined map to MatGroup
        # Register map from self to MatGroup 
        # -------------------------------------------------------------------------------
        homToMat = gap_hom(self, MatGroup, verbose=self._TimeStampSub_)

        if check == True:
            if self.__check_homomorphism__(homToMat) == False: 
                raise ValueError( "matrix group fails to be an epimorphic image of %s"%(self._repr_()) )

        self.__print_timestamp__("Hom from self defined", TsLevel.Body)

        # -------------------------------------------------------------------------------
        # define  a section from MatGroup to self
        # and register 
        # -------------------------------------------------------------------------------
        homFromMat = None
        if avoid_gap_worspace_error == True:
            # workspace of more than 2 GB is not enought to calculate a section
            print "Warning: no section back from matrix group over (gap overflow)", MatGroup.base_ring()
        elif section == True:
            try:
                homFromMat = gap_hom( MatGroup, self, verbose = self._TimeStampSub_)
                self.__print_timestamp__("Section to self defined", TsLevel.Body)
            except:
                print "Warning: no section back from matrix group over", MatGroup.base_ring()
        else:
            try:
                homFromMat = gap_hom(MatGroup, self, check=True, verbose=self._TimeStampSub_)
                self.__print_timestamp__("Homomorphism to self defined", TsLevel.Body)
            except:
                print "Warning: no homomorphism back from matrix group over", MatGroup.base_ring()

        # -------------------------------------------------------------------------------
        # Register section from MatGroup to ClassicalGroup
        # -------------------------------------------------------------------------------
        ClassicalGroup = self._classical_group_

        if ClassicalGroup != None: 
            if homFromMat != None:
                homToClass = ClassicalGroup.coerce_map_from(self)
                if homToClass != None:
                    ClassicalGroup.register_coercion(homToClass * homFromMat)
                    self.__print_timestamp__("section to classical group defined", TsLevel.Body)
                else:
                    print "Warning: no map from matrix group over"
                    print MatGroup.base_ring(), "to classical group", ClassicalGroup

        # -------------------------------------------------------------------------------
        # Register section from MatGroup to ClassicalEmbedding (if exists)
        # -------------------------------------------------------------------------------
        ClassicalEmbedding = self._classical_embedding_

        if ClassicalEmbedding != None and ClassicalEmbedding != ClassicalGroup: 
            if homFromMat != None:
                homToEmb = ClassicalEmbedding.coerce_map_from(self)
                if homToEmb != None:
                    ClassicalEmbedding.register_coercion(homToEmb * homFromMat)
                    self.__print_timestamp__("section to classical embedding defined", TsLevel.Body)
                else:
                    print "Warning: no map from matrix group over"
                    print MatGroup.base_ring(), "to classical embedded roup", ClassicalEmbeding

        self.__print_timestamp__("Ende", TsLevel.StackInfo)
        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, native=False ):
        """
        This method returns the permutation group corresponding to self together with conversion maps to and from
        self and the classical realization of self

        INPUT:

            - "native" boolean as optional keyword, default = False. If you set this True the permutation group is 
                       calculated with repsect to self as finitely presented group. By default the  permutation group is 
                       taken from the classical group realization.

               CAUTION: setting native = True may cause a segmentation fault if you use the sage coercion functionality 
                        afterwards (in other context, even though the coercions for the permutation group work fine).
                        The reason for this is not clear!

        OUTPUT: 

            instance of a subgroup of the symmetric group (PermutationGroup_subgroup) together with conversion maps to
            and from self and the classical groups.

        RAISE:

           - ValueError: "permutation group fails to be an epimorphic image of %s"

        EXAMPLE:

            sage: C3=CubicBraidGroup(3)
            sage: 
            sage: PC3=C3.as_permutation_group(); PC3
            Subgroup of (Symmetric group of order 8! as a permutation group) generated by [(2,3,5)(4,6,8), (1,2,4)(5,7,6)]
            sage: 
            sage: PC3n=C3.as_permutation_group(native=True); PC3n
            Subgroup of (Symmetric group of order 24! as a permutation group) generated by [(1,2,3)(4,10,11)(5,12,13)
            (6,14,15)(7,16,17)(8,18,19)(9,20,21)(22,23,24), 
            (1,4,5)(2,6,7)(3,8,9)(10,14,18)(11,22,20)(12,15,23)(13,17,21)(16,19,24)]
            sage: C3Cl = C3.as_classical_group()
            sage: c=C3([2,1-2]); c
            c1*c0^-1
            sage: lc=C3Cl(c); lc
            [  E(3)^2 -E(12)^7]
            [ E(12)^7  -E(3)^2]
            sage: pc=PC3(c); pc
            (1,5,7,4)(2,8,6,3)
            sage: pcn=PC3n(c); pcn
            (1,11,24,7)(2,15,22,9)(3,19,23,5)(4,13,16,18)(6,17,20,10)(8,21,12,14)
            sage:
            sage: clc  = C3(lc);    clc  == c
            True
            sage: cpc  = C3(pc);    cpc  == c
            True
            sage: cpcn = C3(pcn);   cpcn == c
            True
            sage: lpc  = C3Cl(pc);  lpc  == lc
            True
            sage: lpcn = C3Cl(pcn); lpcn == lc
            True
            sage: plc  = PC3(lc);   plc  == pc
            True
            sage: plcn = PC3n(lc);  plcn == pcn
            True


        AUTHOR

          - Sebastian Oehms, Sept. 2016
           
        """

        # -------------------------------------------------------------------------------
        # define permutation group assiossiated to self
        # -------------------------------------------------------------------------------
        self.__print_timestamp__( "Begin", TsLevel.StackInfo )

        ClassicalGroup = self.as_classical_group()
        Domain = None

        # -------------------------------------------------------------------------------
        # naming and initializing the maps
        # -------------------------------------------------------------------------------
        c2s = self.convert_map_from( ClassicalGroup )
        s2c = ClassicalGroup.convert_map_from( self )
        s2po = None; po2s = None; c2po = None; po2c = None; 
        s2p  = None; p2s  = None; c2p  = None; p2c  = None; 

        # -------------------------------------------------------------------------------
        # setting the original permutation group
        # -------------------------------------------------------------------------------
        if native == True or self._nstrands_ < _sage_const_3 :
            PermGroupOri = gap_as_permutation_group(self, verbose = self._TimeStampSub_ )

            s2po = PermGroupOri.convert_map_from( self )
            po2s = self.convert_map_from( PermGroupOri )

            SortGenList = [ s2po(gen) for gen in self.gens() ]
        else:
            if isinstance( ClassicalGroup, PermutationGroup_generic):
                PermGroupOri = ClassicalGroup

                c2po = Hom( ClassicalGroup, PermGroupOri).identity()
                po2c = Hom( PermGroupOri, ClassicalGroup).identity()

            else:
                PermGroupOri = gap_as_permutation_group( ClassicalGroup, verbose = self._TimeStampSub_ )

                c2po = PermGroupOri.convert_map_from( ClassicalGroup ) 
                po2c = ClassicalGroup.convert_map_from( PermGroupOri )

            SortGenList = [ c2po(ClassicalGroup(gen)) for gen in self.gens() ]

        Domain = SymmetricGroup( len( PermGroupOri.domain() ) )
        PermGroup = Domain.subgroup( SortGenList )

        po2p = PermGroup.convert_map_from( PermGroupOri )
        p2po = PermGroupOri.convert_map_from( PermGroup )


        self.__print_timestamp__( "subgroup of %s"%(Domain), TsLevel.Body )


        # ---------------------------------------------------------------------------------------------------------
        # setting the maps to the permutation group
        # ---------------------------------------------------------------------------------------------------------
        s2p_hom = None
        c2p_hom = None

        if c2p == None and c2po != None and po2p != None:
            c2p = po2p * c2po

        if c2p != None:
            c2p_hom = register_hom( ClassicalGroup, PermGroup, c2p, verbose = self._TimeStampSub_ )
            self.__print_timestamp__( "c2p_hom defined pos 1", TsLevel.Debug )

        if s2p == None and s2po != None and po2p != None:
            s2p = po2p * s2po

        if s2p != None:
            s2p_hom = register_hom( self, PermGroup, s2p, verbose = self._TimeStampSub_ )
            self.__print_timestamp__( "s2p_hom defined pos 1", TsLevel.Debug )

        if c2p == None and s2p_hom != None:
            c2p = s2p_hom * c2s
            if native == True:
                # Note: in this case registering the map is not neccessary, but may cause a segmentation fault later on
                c2p_hom = c2p
            else:
                c2p_hom = register_hom( ClassicalGroup, PermGroup, c2p, verbose = self._TimeStampSub_ )
            self.__print_timestamp__( "c2p_hom defined pos 2", TsLevel.Debug )

        if s2p == None and c2p_hom != None:
            s2p = c2p_hom * s2c
            s2p_hom = register_hom( self, PermGroup, s2p, verbose = self._TimeStampSub_ )
            self.__print_timestamp__( "s2p_hom defined pos 2", TsLevel.Debug )
        

        if s2p_hom == None:
            print "Warning: no map from self to permutation group defined"
             
        if c2p_hom == None:
            print "Warning: no map from classical group to permutation group defined"

        self.__print_timestamp__( "homToPerm defined", TsLevel.Debug )

        # ---------------------------------------------------------------------------------------------------------
        # setting the maps from the permutation group
        # ---------------------------------------------------------------------------------------------------------
        p2s_hom = None
        p2c_hom = None

        if p2c == None and po2c != None and p2po != None:
            p2c = po2c * p2po

        if p2c != None:
            p2c_hom = register_hom( PermGroup, ClassicalGroup, p2c, verbose = self._TimeStampSub_ )
            self.__print_timestamp__( "p2c_hom defined pos 1", TsLevel.Debug )

        if p2s == None and po2s != None and p2po != None:
            p2s = po2s * p2po

        if p2s != None:
            p2s_hom = register_hom( PermGroup, self,  p2s, verbose = self._TimeStampSub_ )
            self.__print_timestamp__( "p2s_hom defined pos 1", TsLevel.Debug )

        if p2c == None and p2s_hom != None:
            p2c = s2c * p2s_hom 
            p2c_hom = register_hom( PermGroup, ClassicalGroup, p2c, verbose = self._TimeStampSub_ )
            self.__print_timestamp__( "p2c_hom defined pos 2", TsLevel.Debug )

        if p2s == None and p2c_hom != None:
            p2s = c2s * p2c_hom
            p2s_hom = register_hom( PermGroup, self, p2s, verbose = self._TimeStampSub_ )
            self.__print_timestamp__( "p2s_hom defined pos 2", TsLevel.Debug )
        

        if p2s_hom == None:
            print "Warning: no map from permutation group to self defined"
             
        if c2p_hom == None:
            print "Warning: no map from permutation group to classical group defined"

        self.__print_timestamp__( "homFromPerm defined", TsLevel.Debug )

             
             




        if s2p_hom != None:
            self.__print_timestamp__( "checking homToPerm", TsLevel.Body )

            if self.__check_homomorphism__( s2p_hom ) == False: 
                raise ValueError( "permutation group fails to be an epimorphic image of %s"%(self._repr_()) )
            self.__print_timestamp__( "check homToPerm finished", TsLevel.Body )


        self.__print_timestamp__( "End", TsLevel.StackInfo )
        
        return PermGroup






    # ----------------------------------------------------------------------------------
    # as_classical_group
    # ----------------------------------------------------------------------------------
    def as_classical_group(self, embedded=False):
        """
        creates an isomorphic image of self as a classical group according to the construction given by Coxeter resp. Assion

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.as_classical_group.__doc__

        INPUT: (optional as keyword)

          - "embedded": boolean (default = False). This boolean does effect the cases of AssionGroups where they are 
                        realized as projective groups, only. More precisely: if self is of type 'S' (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 stand (in this case as subgroup of Sp(n-1,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) (type 'C' ) 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. 

        RAISE:

          - ValueError: "no classical group defined" if the construction was not possible

          - ValueError: "no classical embedding defined" if the construction was not possible

        EXAMPLES:

           sage: from cubic_braid import *
           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: 
           sage: uCle = U3Clemb(u); uCle
           [a + 1 a + 1     1]
           [a + 1     0     a]
           [    1     a     a]
           sage:
           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 with respect to hermitian form [0 0 1]
           [0 1 0]
           [1 0 0]
           sage: uCle in 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] 
           generated by (
           [    E(3) E(12)^11        0]
           [       0        1        0]
           [       0        0        1], 
           [       1        0        0]
           [E(12)^11     E(3) E(12)^11]
           [       0        0        1], 
           [       1        0        0]
           [       0        1        0]
           [       0 E(12)^11     E(3)])
           sage: type(C4Cl)
           <class 'lib.local_matrix_group.MatrixGroup_subgroup_with_category'>



        AUTHOR

          - Sebastian Oehms, Sept. 2016
           

        """
   
        # -------------------------------------------------------------------------------
        # the classical group have already been created in __init__       
        # -------------------------------------------------------------------------------

        if embedded == False or self._classical_embedding_ == None or self._classical_group_ == self._classical_embedding_:
            if self._classical_group_ == None:
                raise ValueError( "no classical group defined") 
            else:
                return self._classical_group_ 
        else:
            # ----------------------------------------------------------------------------------------
            # there is a difference between self._classical_group_ and self._classical_embedding_
            # only in the cases where self._nstrands_ divides by 2 (AssionGroupS) resp. 3 
            # (AssionGroupU). In this case the embedding is the subgroup of the classical group
            # of one strand more (self._nstrands_ +1) generated by the first self._nstrands_ -1
            # generators
            # ----------------------------------------------------------------------------------------
            if self._classical_embedding_ == None:
                raise ValueError( "no classical embedding defined") 
            else:
                return self._classical_embedding_ 
        



        

    # ----------------------------------------------------------------------------------
    # as_refection_group
    # ----------------------------------------------------------------------------------
    def as_reflection_group(self, check=False ):
        """
        creates an isomorphic image of self as irreducible complex reflection group. This is possible only for the finite 
        cubic braid groups of type 'C'

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.as_classical_group.__doc__

        This method uses the sage implementation of reflection group via the gap3 CHEVIE package. To use this methode
        you must have sage from version 7.2 up and gap3 with CHEVIE installed

        INPUT (optional):

          -check :  boolean (default false): can be set to force a check of well definiteness of the morphism from self

        OUTPUT: 

          an object of the class IrreducibleComplexReflectionGroup (from sage.combinat.root_system.reflection_group_complex)
          together with isomorphism to and from self and self.as_classical_group()

        RAISE:

          - ValueError:   "no refection group defined" if the construction was not possible
          - ImportError:  "cannot import name IrreducibleComplexReflectionGroup" means:Sage Version 7.2 up is needed for 
                          this functionality"


        EXAMPLES:

          sage: from lib.cubic_braid import *
          sage: C3.<c1,c2> = CubicBraidGroup(3)
          sage: R3 = C3.as_reflection_group(); R3
          Irreducible complex reflection group of rank 2 and type ST4
          sage: type(R3)
          <class 'lib.local_permgroup.IrreducibleComplexReflectionGroup_with_category'>
          sage: 
          sage: R3.cartan_matrix()
          [-2*E(3) - E(3)^2           E(3)^2]
          [         -E(3)^2 -2*E(3) - E(3)^2]
          sage: R3.simple_roots()
          Finite family {1: (0, -2*E(3) - E(3)^2), 2: (2*E(3)^2, E(3)^2)}
          sage: R3.simple_coroots()
          Finite family {1: (0, 1), 2: (1/3*E(3) - 1/3*E(3)^2, 1/3*E(3) - 1/3*E(3)^2)}
          sage: 

        Conversion maps:

          sage: 
          sage: C3Cl = C3.as_classical_group()
          sage: ele = c1*c2**2; ele
          c1*c2^2
          sage: rele = R3(ele); rele
          (1,14,12,18)(2,15,24,16)(3,22,19,4)(5,6,17,20)(7,10,23,21)(8,11,9,13)
          sage: rele.matrix()
          [-1/3*E(3) + 1/3*E(3)^2  1/3*E(3) + 2/3*E(3)^2]
          [-4/3*E(3) - 2/3*E(3)^2  1/3*E(3) - 1/3*E(3)^2]
          sage: clele = C3Cl(ele); clele
          [ -E(3)^2  E(12)^7]
          [-E(12)^7   E(3)^2]
          sage: clrele = C3Cl(rele); clrele
          [ -E(3)^2  E(12)^7]
          [-E(12)^7   E(3)^2]
          sage: C3(rele)
          c1*c2^-1

       The refelection groups can also be viewed as subgroups of unitary groups over the universal cyclotomic field. This 
       functionality is availlable just in the context of cubic braid groups in addition to the basic functionality of the 
       IrreducibleComplexReflectionGroup_class. Note that the unitary group corresponding to the reflection group is 
       isomorphic but diferent from the classical group due to different hermitian forms for the unitary groups they live in.

         sage: C4=CubicBraidGroup(4)
         sage: R4=C4.as_reflection_group()
         sage: R4Cl=R4.as_unitary_group(); R4Cl
         Subgroup of General Unitary Group of degree 3 over Universal Cyclotomic Field generated by:
         ([   1    0    0]
          [   0    1    0]
          [   0    0 E(3)], 
          [-1/3*E(3) - 2/3*E(3)^2  2/3*E(3) + 1/3*E(3)^2  2/3*E(3) + 1/3*E(3)^2]
          [ 2/3*E(3) + 1/3*E(3)^2 -1/3*E(3) - 2/3*E(3)^2  2/3*E(3) + 1/3*E(3)^2]
          [ 2/3*E(3) + 1/3*E(3)^2  2/3*E(3) + 1/3*E(3)^2 -1/3*E(3) - 2/3*E(3)^2], 
          [   1    0    0]
          [   0 E(3)    0]
          [   0    0    1])
         sage: C4Cl=C4.as_classical_group(); C4Cl
         Subgroup of 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] generated by:
         ([    E(3) E(12)^11        0]
          [       0        1        0]
          [       0        0        1], 
          [       1        0        0]
          [E(12)^11     E(3) E(12)^11]
          [       0        0        1], 
          [       1        0        0]
          [       0        1        0]
          [       0 E(12)^11     E(3)])
          sage: C4ClAmbient = C4Cl.ambient(); C4ClAmbient
          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]
          sage: R4ClAmbient = R4Cl.ambient(); R4ClAmbient
          General Unitary Group of degree 3 over Universal Cyclotomic Field
          sage: C4ClAmbient == R4ClAmbient
          False


        AUTHOR:

          - Sebastian Oehms, Mar. 2017
           

        """
   
        # -------------------------------------------------------------------------------
        # the reflection groups are taken via gap3 -CHEVIE - Interface
        # sage Version 7.2 or later is needed 
        # They are called according to the Shephard-Todd classification:
        #    2 strands -> G(2,1,1)      
        #    3 strands -> G4      
        #    4 strands -> G25      
        #    5 strands -> G32      
        # -------------------------------------------------------------------------------

        if self._AdditionalRelation_  != 'C' or self._nstrands_ > _sage_const_5  or self._nstrands_ < _sage_const_2 :
            raise ValueError( "no reflection group defined") 

        # -------------------------------------------------------------------------------
        # define reflection group assiossiated to self
        # -------------------------------------------------------------------------------
        self.__print_timestamp__( "Begin", TsLevel.StackInfo )

        ReflectGroup = None

        from lib.local_permgroup import IrreducibleComplexReflectionGroup

        def ReflectionGroup( *args,**kwds):
            """
            This local Function overloads the corresponding function of sage.combinat.root_system.reflection_group_real 
            in order to make "call by name conversion" availlable via the local_permgroup module 
            """
            RefGroup = IrreducibleComplexReflectionGroup(tuple(args),
                           index_set=kwds.get('index_set', None),
                           hyperplane_index_set=kwds.get('hyperplane_index_set', None),
                           reflection_index_set=kwds.get('reflection_index_set', None))
            return RefGroup


        if   self._nstrands_ == _sage_const_2 :
            ReflectGroup = ReflectionGroup( [_sage_const_2 ,_sage_const_1 ,_sage_const_1 ] )
        elif self._nstrands_ == _sage_const_3 :
            ReflectGroup = ReflectionGroup( _sage_const_4  )
        elif self._nstrands_ == _sage_const_4 :
            ReflectGroup = ReflectionGroup( _sage_const_25  )
        elif self._nstrands_ == _sage_const_5 :
            ReflectGroup = ReflectionGroup( _sage_const_32  )
            
        self.__print_timestamp__( "ReflectGroup %s defined" %(ReflectGroup), TsLevel.Body )

        # -------------------------------------------------------------------------------
        # check if there is a well defined map to MatGroup
        # Register map from self to MatGroup 
        # -------------------------------------------------------------------------------
        homToRefl = gap_hom( self, ReflectGroup, verbose = self._TimeStampSub_ )

        if check == True:
            if self.__check_homomorphism__( homToRefl ) == False: 
                raise ValueError( "refection group fails to be an epimorphic image of %s"%(self._repr_()) )

        self.__print_timestamp__( "Hom from self defined", TsLevel.Body )

        try:
            homFromRefl = gap_hom( ReflectGroup, self, verbose = self._TimeStampSub_ )
            self.__print_timestamp__( "Hom to self defined", TsLevel.Body )
        except:
            print "Warning: no section back from reflection group"


        # -------------------------------------------------------------------------------
        # maps to and from the classical group
        # -------------------------------------------------------------------------------
        ClassicalGroup = self.as_classical_group()
        c2s = self.convert_map_from( ClassicalGroup )
        s2c = ClassicalGroup.convert_map_from( self )

        r2c = s2c * homFromRefl 
        r2c_hom = register_hom( ReflectGroup, ClassicalGroup, r2c, verbose = self._TimeStampSub_ )
        self.__print_timestamp__( "r2c_hom defined", TsLevel.Debug )

        c2r = homToRefl * c2s 
        c2r_hom = register_hom( ClassicalGroup, ReflectGroup, c2r, verbose = self._TimeStampSub_ )
        self.__print_timestamp__( "c2r_hom defined", TsLevel.Debug )

        self.__print_timestamp__( "End", TsLevel.StackInfo )

        return ReflectGroup
        


    # ----------------------------------------------------------------------------------
    # centralizing element in the classical symplectic resp. unitary group
    # ----------------------------------------------------------------------------------
    def centralizing_element(self, projective=False ):
        """
        returns the centralizing element defined in the work of Assion (Hilfssatz 1.1.3 and 1.2.3)

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.centralizing_element.__doc__

        INPUT: (optional as keyword)

          - "projective": boolean (default = False). This boolean does effect the cases of AssionGroups where they are
                          realized as projective groups, only. More precisely: if self is of type 'S' (for example) and 
                          the number of strands n is even, than its classical group is a subgroup of 
                          PSp(n,3) (being centralized by this element). By default this group will be given.
                          Setting embedded = True the classical realization is given as subgroup of its classical 
                          enlargement with one more stand (in this case as subgroup of Sp(n,3)) 

        OUTPUT:

          depending on the optional keyword a permutation as an element of PSp(n,3) (type S) or PGU(n,2) (type U) if
          projective = True  and 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). 

        RAISE:

          - ValueError: "no centralizing element defined"


        EXAMPLES:

          sage: U3=AssionGroupU(3);  U3
          Assion group on 3 strands of type U
          sage: 
          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: 
          sage: U3Clem = U3.as_classical_group(embedded=True); U3Clem
          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: 
          sage: u3cent = U3.centralizing_element(); u3cent
          [a + 1 a + 1     1]
          [a + 1     0     a]
          [    1     a     a]
          sage: u3cent in U3Cl
          False
          sage: u3centP in U3Cl
          True
          sage: u3cent in U3Clem
          True
          sage: u3centP in U3Clem
          False

        considering u3cent as element in AssionGroupU(4)

          sage: U4=AssionGroupU(4);  U4
          Assion group on 4 strands of type U
          sage: 
          sage: U4Cl = U4.as_classical_group(); U4Cl
          General Unitary Group of degree 3 over Finite Field in a of size 2^2 with respect to hermitian form [0 0 1]
          [0 1 0]
          [1 0 0]
          sage: u3cent in U4Cl
          True
          sage: U4(u3cent)
          (u0*u1^-1)^2
          sage:
          sage: # calculating the centralizer of u3cent in U4Cl via GAP functions in order to
          sage: # check if U3Clem is a subgroup of the centralizer of u3cent in U4Cl
          sage:
          sage: CentU4u3cent = gap_centralizer( U4Cl, u3cent ); CentU4u3cent
          Matrix group over Finite Field in a of size 2^2 with 4 generators (
          [a + 1 a + 1     1]  [a + 1     0     0]  [    1     1 a + 1]  [1 0 1]
          [a + 1     0     a]  [    0 a + 1     0]  [    0     a     a]  [0 a 0]
          [    1     a     a], [    0     0 a + 1], [    0     0     1], [1 0 0]
          )
          sage: 
          sage: CentU4u3cent.gens()[0] in U3Clem
          True
          sage: CentU4u3cent.gens()[1] in U3Clem
          False
          sage: CentU4u3cent.gens()[2] in U3Clem
          True
          sage: CentU4u3cent.gens()[3] in U3Clem
          False
          sage: 
          sage: CentU4u3cent.order()
          72
          sage: U3Clem.order()
          24

        check that U3Clem is a subgroup of index 3 in CentU4u3cent 

          sage: U3Clem.gens()[0] in CentU4u3cent
          True
          sage: U3Clem.gens()[1] in CentU4u3cent
          True


        AUTHOR

          - Sebastian Oehms, Sept. 2016

        """

        # -------------------------------------------------------------------------------
        # the centralizing elements have already been created in __init__
        # -------------------------------------------------------------------------------
        if self._centralizing_matrix_ == None:
            raise ValueError( "no centralizing element defined") 
        else:
            if projective == True:
                return self._centralizing_element_
            else: 
                return self._centralizing_matrix_
                

    # ----------------------------------------------------------------------------------
    # calculating the order by formula
    # ----------------------------------------------------------------------------------
    def order(self, by_formula = True ):
        """
        to avoid long waittime on calculations the order will be obtained by formular resp. direct value

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.order.__doc__

        INPUT:
 
          - "by_formula": (optional keyword) boolean (default = True). In the default case the order is calculated from
             formulas for simple group of Lie typ. If set to false the order is calculated by native function with 
             respect to the classical group (in the cases where this is finite). 

        OUTPUT: 

            size of the group as Integer ore infinity

        EXAMPLES:

          sage: S6=AssionGroupS(6)
          sage: S6.order()
          12597120
          sage: S6.order(by_formula=False)
          12597120
          sage: 
          sage: C6=CubicBraidGroup(6)
          sage: C6.order()
          +Infinity


        AUTHOR

          - Sebastian Oehms, Sept. 2016

        REFERENCES:

         - Carter, R.W.: "Simple groups of Lie type", John Wiley & Sons (London 1989)

        """
 
        n = self._nstrands_

        if by_formula == False:
           if self._AdditionalRelation_ == 'C' and n > _sage_const_5 :
               order = infinity
           else:
               order = self.as_classical_group().order()
           return order

        m = n -_sage_const_1   # dim of classical group

        order = _sage_const_0 
        if n == _sage_const_1 :
            order = _sage_const_1 
        elif n == _sage_const_2 :
            order = _sage_const_3 
        elif n == _sage_const_3 :
            order = _sage_const_24 
        elif n == _sage_const_4 :
            order = _sage_const_648 


        if self._AdditionalRelation_ == 'S':
            q = _sage_const_3   # size of base_ring
            if n % _sage_const_2  != _sage_const_0 :
                l = m/_sage_const_2 
                # -------------------------------------------------------------------------------------------------------
                # using the formula (for example from Carter, R.W., page 4) for self.as_classical_group() isomorphic to
                # PSp(2l,q)
                # PSp(2l,q).order() = 1/(2,q-1) * q^l^2*(q^2-1)*...*(q^(2*l)-1)
                # thus Sp(2l,q).order() = q^l^2*(q^2-1)*...*(q^(2*l)-1)
                # since Sp(2l,q).order() = (q-1)*PSp(2l,q).order()
                # -------------------------------------------------------------------------------------------------------
                order = _sage_const_1 
                for i in range(l):
                    order = order * (q**(_sage_const_2 *(i+_sage_const_1 ))-_sage_const_1 )       
                order = order * q**l**_sage_const_2 

        elif self._AdditionalRelation_ == 'U':
            q = _sage_const_2   # characteristic of base_ring
            if n % _sage_const_3  != _sage_const_0 :
                # -----------------------------------------------------------------------------------------------------
                # using the formula (for example from Carter, R.W.,page 4) for self.as_classical_group() isomorphic to
                # PSU(m,q)
                # PSU(m,q).order() = 1/(m,q+1)*q^(m*(m-1)/2)*(q^2-1)*(q^3+1)...*(q^m - (-1)^m)
                # thus GU(m,q).order() = (q+1)*q^(m*(m-1)/2)*(q^2-1)*(q^3+1)...*(q^m - (-1)^m)
                # since GU(m,q).order() = (q+1)**2*PSU(m,q).order() for m % 3 == 0
                # and   GU(m,q).order() = (q+1)*PSU(m,q).order()    for m % 3 != 0
                # -----------------------------------------------------------------------------------------------------
                order = _sage_const_1 
                for i in range(m-_sage_const_1 ):
                    order = order * (q**(i+_sage_const_2 ) - (-_sage_const_1 )**(i+_sage_const_2 ))
                order = order * (q+_sage_const_1 )*q**(m*(m-_sage_const_1 )/_sage_const_2 )

        elif self._AdditionalRelation_ == 'C':
            if order > _sage_const_0 :
                pass
            elif n == _sage_const_5 :
                order = _sage_const_155520 
            else:
                order = infinity

        if order == _sage_const_0 :
            order = self.as_classical_group().order()
 
        return order


    # ----------------------------------------------------------------------------------
    # creating a CubicBraidGroup as subgroup of self on less strands
    # ----------------------------------------------------------------------------------
    def cubic_braid_subgroup( self, nstrands = None ):
        """
        creates a CubicBraidGroup as subgroup of self on the first "n_strands" strands

        If you don't see this well formatted type 

        sage: print CubicBraidGroup_class.order.__doc__

        INPUT:

          - "nstrands": Integer > 0 and < self._nstrands_ giving the number of strand for the subgroup.
            the default is one strand less than self  

        OUTPUT: 

           an instance of the this class realizing the subgroup

        EXAMPLES:



        AUTHOR

          - Sebastian Oehms, Sept. 2016

        """
 
        if nstrands == None:
            nstrands = self._nstrands_ -_sage_const_1 

        n = self._nstrands_

        try:
            nstrands = Integer( nstrands )
        except:
            raise TypeError( "nstrands must be an integer" )

        if nstrands >= n or nstrands <= _sage_const_0 :
            raise ValueError( "nstrands must be positive and less than %s" %(self._nstrands_) )

        Gens = self.gens()
        GensRed = tuple( [ Gens[i] for i in range(nstrands -_sage_const_1 ) ])

        SGrp = CubicBraidGroup( names = GensRed, AdditionalRelation = self._AdditionalRelation_, verbose = self._verbose_ )

        def embed( ele ):
            return self( ele.Tietze() )

        register_hom( SGrp, self, embed, verbose = self._TimeStampSub_ )

        return SGrp







    # ----------------------------------------------------------------------------------
    # Although GAP can calculate character tables for finitely presentet groups
    # this method is not offered by the sage gap interface
    # we therefore use the permutation group implementation to get it 
    # ----------------------------------------------------------------------------------
    def character_table( self ):
        """
        calculates the character_table of the cubic braid group via the gap interface

        OUTPUT: 
  
           Character table as matrix (instance of sage.matrix.matrix_cyclo_dense.Matrix_cyclo_dense)

        EXAMPLE:

          sage: U3=AssionGroupU(3);  U3
          Assion group on 3 strands of type U
          sage: U3ct=U3.character_table(); U3ct
          [         1          1          1          1          1          1          1]
          [         1 -zeta3 - 1      zeta3          1      zeta3 -zeta3 - 1          1]
          [         1      zeta3 -zeta3 - 1          1 -zeta3 - 1      zeta3          1]
          [         2         -1         -1          0          1          1         -2]
          [         2     -zeta3  zeta3 + 1          0 -zeta3 - 1      zeta3         -2]
          [         2  zeta3 + 1     -zeta3          0      zeta3 -zeta3 - 1         -2]
          [         3          0          0         -1          0          0          3]
  



        AUTHOR

          - Sebastian Oehms, Sept. 2016

        """
        PermGroup = self.as_permutation_group()
        CharTab = PermGroup.character_table()

        return CharTab












        


##############################################################################
#
#   Functions to create Objects                  
#
##############################################################################
def CubicBraidGroup(n=None, names='c', AdditionalRelation = 'C', verbose = False ):
    """
    Constructs cubic quotients of braid groups as instance of the CubicBraidGroup_class 

    If you don't see this well formatted type 

    sage: print CubicBraidGroup.__doc__

    for more information about the CubicBraidGroup_class type

    sage: print CubicBraidGroup_class.__doc__

    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.

           The entry can be either a string with the names of the generators, or the number of generators and the prefix 
           of the names to be given. The default prefix is 'c'

     - "AdditionalRelation":  (optional keyword, default = 'C') is passed to the corresponding keyword parameter of
           the constructor of the CubicBraidGroup_class. For more information type 
           sage: print CubicBraidGroup_class.__doc__

     - "verbose":  (optional keyword, default = False) is passed to the corresponding keyword parameter of
           the constructor of the CubicBraidGroup_class. For more information type 
           sage: print CubicBraidGroup_class.__doc__



    This function is adapted from the BraidGroup function!

    EXAMPLES:

        sage: C3=CubicBraidGroup(3); C3.generators()
        (c0, c1)
        sage: CubicBraidGroup(3, 'g').generators()
        (g0, g1)
        sage: U3.<u1,u2>=CubicBraidGroup(3, AdditionalRelation = 'U'); U3.generators()
        (u1, u2)


        AUTHOR

          - Sebastian Oehms, Sept. 2016

    """
    # Support Freegroup('a,b') syntax
    if n is not None:
        try:
            n = Integer(n)-_sage_const_1 
        except TypeError:
            names = n

            n = None
    # derive n from counting names
    if n is None:
        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, AdditionalRelation, verbose )


# ----------------------------------------------------------------------------------
# Short-Hand-Calls
# ----------------------------------------------------------------------------------


def AssionGroupS(n=None, names='s', verbose = False ):
    """
    Constructs cubic quotients of braid groups as instance of the CubicBraidGroup_class which have been investigated
    by J.Assion under the notation S(m)  

    If you don't see this well formatted type 

    sage: print AssionGroupS.__doc__

    for more information about the CubicBraidGroup_class type

    sage: print CubicBraidGroup_class.__doc__

    This function is a short hand cut for the CubicBraidGroup function setting AdditionalRelation ='S' and 
    default names='s'

    INPUT:

     - "n": integer or None (default). The number of strands. This parameter is passed to the corresponding parameter 
           of the CubicBraidGroup function For more information type 
           sage: print CubicBraidGroup.__doc__

     - "names": string or list/tuple/iterable of strings (default:'s'). This parameter is passed to the corresponding 
           parameter of the CubicBraidGroup function For more information type 
           sage: print CubicBraidGroup.__doc__

     - "verbose":  (optional keyword, default = False) is passed to the corresponding keyword parameter of
           the constructor of the CubicBraidGroup_class. For more information type 
           sage: print CubicBraidGroup_class.__doc__

    EXAMPLES:

        sage: S3=AssionGroupS(3);  S3
        Assion group on 3 strands of type S
        sage: S3x=CubicBraidGroup(3, names='s', AdditionalRelation = 'S'); S3x
        Assion group on 3 strands of type S
        sage: S3 == S3x
        True

        AUTHOR

          - Sebastian Oehms, Sept. 2016

    """

    return CubicBraidGroup(n = n, names = names, AdditionalRelation = 'S', verbose = verbose )

def AssionGroupU(n=None, names='u', verbose = False ):
    """
    Constructs cubic quotients of braid groups as instance of the CubicBraidGroup_class which have been investigated
    by J.Assion under the notation U(m)  

    If you don't see this well formatted type 

    sage: print AssionGroupU.__doc__

    for more information about the CubicBraidGroup_class type

    sage: print CubicBraidGroup_class.__doc__

    This function is a short hand cut for the CubicBraidGroup function setting AdditionalRelation ='U' and 
    default names='u'

    INPUT:

     - "n": integer or None (default). The number of strands. This parameter is passed to the corresponding parameter 
           of the CubicBraidGroup function For more information type 
           sage: print CubicBraidGroup.__doc__

     - "names": string or list/tuple/iterable of strings (default:'u'). This parameter is passed to the corresponding 
           parameter of the CubicBraidGroup function For more information type 
           sage: print CubicBraidGroup.__doc__

     - "verbose":  (optional keyword, default = False) is passed to the corresponding keyword parameter of
           the constructor of the CubicBraidGroup_class. For more information type 
           sage: print CubicBraidGroup_class.__doc__

    EXAMPLES:

        sage: U3=AssionGroupU(3);  U3
        Assion group on 3 strands of type U
        sage: U3x=CubicBraidGroup(3, names='u', AdditionalRelation = 'U'); U3x
        Assion group on 3 strands of type U
        sage: U3 == U3x
        True

        AUTHOR

          - Sebastian Oehms, Sept. 2016

    """

    return CubicBraidGroup(n = n, names = names, AdditionalRelation = 'U', verbose = verbose )