Ticket #12912: trac_12912-coxeter3-mh.patch

File trac_12912-coxeter3-mh.patch, 100.2 KB (added by nthiery, 8 years ago)
  • module_list.py

    # HG changeset patch
    # User Mike Hansen
    # Date 1360041577 28800
    # Node ID 202da0ae0bfaee38cc59b4a12595d884aeba0cfa
    # Parent  031f4605a497858f4bddbe4a4babf1f00a6b92f4
    #12912: Interface to Fokko Ducloux's Coxeter 3 and implementation of parabolic Kazhdan-Lusztig polynomials
    
    diff --git a/module_list.py b/module_list.py
    a b if (os.path.isfile(SAGE_INC + "gurobi_c. 
    19991999        )
    20002000
    20012001
     2002if is_package_installed('coxeter3'):
     2003    ext_modules.append(
     2004        Extension('sage.libs.coxeter3.coxeter',
     2005                  sources = ['sage/libs/coxeter3/coxeter.pyx'],
     2006                  include_dirs = [os.path.join(SAGE_LOCAL, 'include', 'coxeter')],
     2007                  language="c++",
     2008                  libraries = ['csage', 'coxeter3', 'stdc++'])
     2009        )
     2010
     2011
    20022012if (os.path.isfile(SAGE_INC + "cplex.h") and                                                                                                                                                                                   
    20032013    os.path.isfile(SAGE_LOCAL + "/lib/libcplex.a")):
    20042014    ext_modules.append(
  • sage/combinat/kazhdan_lusztig.py

    diff --git a/sage/combinat/kazhdan_lusztig.py b/sage/combinat/kazhdan_lusztig.py
    a b class KazhdanLusztigPolynomial(SageObjec 
    4343            sage: KL.P(s2,s3*s2*s3*s1*s2)
    4444            q + 1
    4545
     46        A faster implementation (using the optional package Coxeter 3) is given by::
     47
     48            sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3
     49            sage: W.kazhdan_lusztig_polynomial([2], [3,2,3,1,2])        # optional - coxeter3
     50            q + 1
    4651        """
    4752        self._coxeter_group = W
    4853        self._q = q
    class KazhdanLusztigPolynomial(SageObjec 
    6166        """
    6267        Returns the Kazhdan-Lusztig R polynomial.
    6368
     69        INPUT:
     70
     71        - ``x``, ``y`` -- elements of the underlying Coxeter group
     72
    6473        EXAMPLES ::
    6574
    6675           sage: R.<q>=QQ[]
    class KazhdanLusztigPolynomial(SageObjec 
    99108    @cached_method
    100109    def P(self, x, y):
    101110        """
    102         Returns the Kazhdan-Lusztig P polynomial. If the rank is large,
    103         this runs slowly at first but speeds up as you do repeated calculations
    104         due to the caching.
     111        Returns the Kazhdan-Lusztig P polynomial.
     112
     113        If the rank is large, this runs slowly at first but speeds up
     114        as you do repeated calculations due to the caching.
     115
     116        INPUT:
     117
     118        - ``x``, ``y`` -- elements of the underlying Coxeter group
     119
     120        .. SEEALSO::
     121
     122            :mod:`~sage.libs.coxeter3.coxeter_group.CoxeterGroup.kazhdan_lusztig_polynomial`
     123            for a faster implementation using Fokko Ducloux's Coxeter3 C++ library.
    105124
    106125        EXAMPLES ::
    107126
    class KazhdanLusztigPolynomial(SageObjec 
    134153        if self._trace:
    135154            print "    P(%s,%s)=%s"%(x, y, ret)
    136155        return ret
    137        
     156
    138157def laurent_polynomial_truncate(p, n):
    139158    """
    140159    Truncates the Laurent polynomial p, returning only terms
    def laurent_polynomial_truncate(p, n): 
    153172        if k[0] < n:
    154173            dict[k] = pdict[k]
    155174    return p.parent()(dict)
    156 
    157    
    158    
  • sage/combinat/root_system/cartan_type.py

    diff --git a/sage/combinat/root_system/cartan_type.py b/sage/combinat/root_system/cartan_type.py
    a b Non-crystallographic Cartan types are al 
    8484    [['I', 5], ['H', 3], ['H', 4]]
    8585
    8686In Sage, a Cartan type is used as a database of type-specific
    87 information and algorithms (see e.g. :mod:`sage.combinat.root_system.type_A`). 
     87information and algorithms (see e.g. :mod:`sage.combinat.root_system.type_A`).
    8888This database includes how to construct the Dynkin diagram, the ambient space for the root
    8989system (see http://en.wikipedia.org/wiki/Root_system), and further
    9090mathematical properties::
    It will eventually include Coxeter numbe 
    9696
    9797In particular, a Sage Cartan type is endowed with a fixed choice of
    9898labels for the nodes of the Dynkin diagram. This choice follows the
    99 conventions of Nicolas Bourbaki, Lie Groups and Lie Algebras: Chapter 4-6, Elements of Mathematics, 
     99conventions of Nicolas Bourbaki, Lie Groups and Lie Algebras: Chapter 4-6, Elements of Mathematics,
    100100Springer (2002). ISBN 978-3540426509. For example::
    101101
    102102    sage: T = CartanType(['D', 4])
    automatically translated into the previo 
    320320    F4~*
    321321"""
    322322#*****************************************************************************
    323 #       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
    324 #       Copyright (C) 2008-2009 Nicolas M. Thiery <nthiery at users.sf.net>, 
     323#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
     324#       Copyright (C) 2008-2009 Nicolas M. Thiery <nthiery at users.sf.net>,
    325325#
    326326#  Distributed under the terms of the GNU General Public License (GPL)
    327327#                  http://www.gnu.org/licenses/
    class CartanTypeFactory(SageObject): 
    355355    def __call__(self, *args):
    356356        """
    357357        Constructs a Cartan type object.
    358        
     358
    359359        INPUT:
    360360         - ``[letter, rank]``: letter is one of 'A','B','C','D','E','F','G' and rank is an integer
    361361         - ``[letter, rank, twist]``: letter is one of 'A','B','C','D','E','F','G', 'BC', and rank and twist are integers
    362362         - ``str``: a string
    363363         - ``object``: a cartan type, or an object with a cartan type method
    364        
     364
    365365        EXAMPLES:
    366366
    367367        We construct the Cartan type `D_4`::
    368        
     368
    369369            sage: d4 = CartanType(['D',4])
    370370            sage: d4
    371371            ['D', 4]
    class CartanTypeFactory(SageObject): 
    395395                return CartanType([t[0], eval(t[1:])])
    396396
    397397        t = list(t)
    398            
     398
    399399        if type(t[0]) == str and t[1] in ZZ and t[1] >= 0:
    400400            letter, n = t[0], t[1]
    401401            if len(t) == 2:
    class CartanType_abstract(object): 
    735735            [(1, 2, 6)]
    736736            sage: CartanType(['F',4]).coxeter_diagram().edges()
    737737            [(1, 2, 3), (2, 3, 4), (3, 4, 3)]
    738 
    739         This is currently implemented only for crystallographic types::
    740 
    741             sage: CartanType(['H',3]).coxeter_diagram
    742             NotImplemented
    743738        """
    744739
    745740    @cached_method
    class CartanType_abstract(object): 
    976971            sage: CartanType(["A",4,1]).is_implemented()
    977972            True
    978973            sage: CartanType(['H',3]).is_implemented()
    979             False
    980 
    981         .. todo::
    982 
    983             Implemente Cartan datum for non crystallographic types,
    984             and update the implementation of this method accordingly,
    985             say by testing the coxeter diagram instead.
     974            True
    986975        """
    987976        try:
    988             self.dynkin_diagram()
     977            self.coxeter_diagram()
    989978            return True
    990979        except StandardError:
    991980            return False
  • sage/combinat/root_system/coxeter_group.py

    diff --git a/sage/combinat/root_system/coxeter_group.py b/sage/combinat/root_system/coxeter_group.py
    a b def CoxeterGroup(cartan_type, implementa 
    2525    INPUT:
    2626
    2727     - ``cartan_type`` -- a cartan type (or coercible into; see :class:`CartanType`)
    28      - ``implementation`` -- "permutation", "matrix", or None (default: None)
     28     - ``implementation`` -- "permutation", "matrix", "coxeter3", or None (default: None)
    2929
    3030    Returns an implementation of the Coxeter group of type
    3131    ``cartan_type``.
    def CoxeterGroup(cartan_type, implementa 
    6969        NotImplementedError: Coxeter group of type ['A', 4, 1] as permutation group not implemented
    7070
    7171    """
    72     assert implementation in ["permutation", "matrix", None]
     72    assert implementation in ["permutation", "matrix", "coxeter3", None]
    7373    cartan_type = CartanType(cartan_type)
    7474
    7575    if implementation is None:
    def CoxeterGroup(cartan_type, implementa 
    7878        else:
    7979            implementation = "matrix"
    8080
     81    if implementation == "coxeter3":
     82        try:
     83            from sage.libs.coxeter3.coxeter_group import CoxeterGroup
     84        except ImportError:
     85            raise RuntimeError, "coxeter3 must be installed"
     86        else:
     87            return CoxeterGroup(cartan_type)
    8188    if implementation == "permutation" and is_chevie_available() and \
    8289       cartan_type.is_finite() and cartan_type.is_irreducible():
    8390        return CoxeterGroupAsPermutationGroup(cartan_type)
  • sage/combinat/root_system/root_space.py

    diff --git a/sage/combinat/root_system/root_space.py b/sage/combinat/root_system/root_space.py
    a b class RootSpace(ClearCacheOnPickle, Comb 
    4242
    4343    TESTS::
    4444
    45         sage: for ct in CartanType.samples()+[CartanType(["A",2],["C",5,1])]:
    46         ...       if ct.is_implemented():
    47         ...           P = ct.root_system().root_space()
    48         ...           TestSuite(P).run()
    49         ...
     45        sage: for ct in CartanType.samples(crystalographic=True)+[CartanType(["A",2],["C",5,1])]:
     46        ...       TestSuite(ct.root_system().root_lattice()).run()
     47        ...       TestSuite(ct.root_system().root_space()).run()
    5048        sage: r = RootSystem(['A',4]).root_lattice()
    5149        sage: r.simple_root(1)
    5250        alpha[1]
  • sage/combinat/root_system/type_H.py

    diff --git a/sage/combinat/root_system/type_H.py b/sage/combinat/root_system/type_H.py
    a b class CartanType(CartanType_standard_fin 
    1313    def __init__(self, n):
    1414        """
    1515        EXAMPLES::
    16        
     16
    1717            sage: ct = CartanType(['H',3])
    1818            sage: ct
    1919            ['H', 3]
    class CartanType(CartanType_standard_fin 
    3939        """
    4040        assert n in [3, 4]
    4141        CartanType_standard_finite.__init__(self, "H", n)
     42
     43    def coxeter_diagram(self):
     44        """
     45        Returns a Coxeter diagram for type H.
     46
     47        EXAMPLES::
     48
     49             sage: ct = CartanType(['H',3])
     50             sage: ct.coxeter_diagram()
     51             Graph on 3 vertices
     52             sage: sorted(ct.coxeter_diagram().edges())
     53             [(1, 2, 3), (2, 3, 5)]
     54             sage: ct.coxeter_matrix()
     55             [1 3 2]
     56             [3 1 5]
     57             [2 5 1]
     58
     59             sage: ct = CartanType(['H',4])
     60             sage: ct.coxeter_diagram()
     61             Graph on 4 vertices
     62             sage: sorted(ct.coxeter_diagram().edges())
     63             [(1, 2, 3), (2, 3, 3), (3, 4, 5)]
     64             sage: ct.coxeter_matrix()
     65             [1 3 2 2]
     66             [3 1 3 2]
     67             [2 3 1 5]
     68             [2 2 5 1]
     69        """
     70        from sage.graphs.graph import Graph
     71        n = self.n
     72        g = Graph(multiedges=False)
     73        for i in range(1, n):
     74            g.add_edge(i, i+1, 3)
     75        g.set_edge_label(n-1, n, 5)
     76        return g
     77
     78    def coxeter_matrix(self):
     79        """
     80        Returns the Coxeter matrix for this type.
     81
     82        EXAMPLES::
     83
     84            sage: h = CartanType(['H', 3])
     85
     86            sage: h = CartanType(['H', 4])
     87        """
     88        from sage.all import ZZ, matrix
     89        if self.rank() == 3:
     90            entries = [[1,3,2],[3,1,5],[2,5,1]]
     91        else:
     92            entries = [[1,3,2,2],[3,1,3,2],[2,3,1,5],[2,2,5,1]]
     93        return matrix(ZZ, entries)
  • sage/combinat/root_system/type_I.py

    diff --git a/sage/combinat/root_system/type_I.py b/sage/combinat/root_system/type_I.py
    a b  
    22Root system data for type I
    33"""
    44#*****************************************************************************
    5 #       Copyright (C) 2008-2009 Nicolas M. Thiery <nthiery at users.sf.net>, 
     5#       Copyright (C) 2008-2009 Nicolas M. Thiery <nthiery at users.sf.net>,
    66#
    77#  Distributed under the terms of the GNU General Public License (GPL)
    88#                  http://www.gnu.org/licenses/
    class CartanType(CartanType_standard_fin 
    1313    def __init__(self, n):
    1414        """
    1515        EXAMPLES::
    16        
     16
    1717            sage: ct = CartanType(['I',5])
    1818            sage: ct
    1919            ['I', 5]
    class CartanType(CartanType_standard_fin 
    6262            [1, 2]
    6363        """
    6464        return [1, 2]
     65
     66    def coxeter_diagram(self):
     67        """
     68        Returns the Coxeter matrix for this type.
     69
     70        EXAMPLES::
     71
     72            sage: ct = CartanType(['I', 4])
     73            sage: ct.coxeter_diagram()
     74            Graph on 2 vertices
     75            sage: ct.coxeter_diagram().edges()
     76            [(1, 2, 4)]
     77            sage: ct.coxeter_matrix()
     78            [1 4]
     79            [4 1]
     80        """
     81        from sage.graphs.graph import Graph
     82        return Graph([[1,2,self.n]], multiedges=False)
  • sage/combinat/root_system/weight_space.py

    diff --git a/sage/combinat/root_system/weight_space.py b/sage/combinat/root_system/weight_space.py
    a b class WeightSpace(CombinatorialFreeModul 
    128128
    129129    TESTS::
    130130
    131         sage: for ct in CartanType.samples():
    132         ...       if ct.is_implemented():
    133         ...           P = ct.root_system().weight_space()
    134         ...           TestSuite(P).run()
    135         ...
     131        sage: for ct in CartanType.samples(crystalographic=True)+[CartanType(["A",2],["C",5,1])]:
     132        ...       TestSuite(ct.root_system().weight_lattice()).run()
     133        ...       TestSuite(ct.root_system().weight_space()).run()
    136134        sage: for ct in CartanType.samples(affine=True):
    137135        ...       if ct.is_implemented():
    138136        ...           P = ct.root_system().weight_space(extended=True)
  • new file sage/libs/coxeter3/__init__.py

    diff --git a/sage/libs/coxeter3/__init__.py b/sage/libs/coxeter3/__init__.py
    new file mode 100644
    - +  
     1 
  • new file sage/libs/coxeter3/coxeter.pxd

    diff --git a/sage/libs/coxeter3/coxeter.pxd b/sage/libs/coxeter3/coxeter.pxd
    new file mode 100644
    - +  
     1#*****************************************************************************
     2#       Copyright (C) 2009-2013 Mike Hansen <mhansen@gmail.com>
     3#
     4#  Distributed under the terms of the GNU General Public License (GPL)
     5#                  http://www.gnu.org/licenses/
     6#*****************************************************************************
     7
     8from sage.structure.sage_object cimport SageObject
     9include "decl.pxi"
     10
     11cdef class String:
     12    cdef c_String x
     13
     14cdef class Type:
     15    cdef c_Type x
     16
     17cdef class CoxGroup(SageObject):
     18    cdef c_CoxGroup* x
     19    cdef object cartan_type
     20    cdef dict in_ordering
     21    cdef dict out_ordering
     22    cpdef object full_context(self)
     23
     24cdef class CoxGroupElement:
     25    cdef c_CoxWord word
     26    cdef c_CoxGroup* group
     27    cdef CoxGroup _parent
     28    cdef CoxGroupElement _new(self)
     29    cpdef CoxGroup parent(self)
     30
     31cdef class CoxGraph:
     32    cdef c_CoxGraph x
  • new file sage/libs/coxeter3/coxeter.pyx

    diff --git a/sage/libs/coxeter3/coxeter.pyx b/sage/libs/coxeter3/coxeter.pyx
    new file mode 100644
    - +  
     1"""
     2Low level part of the interface to Fokko Ducloux's Coxeter 3 library
     3
     4.. TODO::
     5
     6    - Write a more efficient method for converting polynomials in
     7      Coxeter to Sage polynomials.
     8"""
     9#*****************************************************************************
     10#       Copyright (C) 2009-2013 Mike Hansen <mhansen@gmail.com>
     11#
     12#  Distributed under the terms of the GNU General Public License (GPL)
     13#                  http://www.gnu.org/licenses/
     14#*****************************************************************************
     15
     16include "../../ext/interrupt.pxi"
     17include "../../ext/stdsage.pxi"
     18include "../../ext/cdefs.pxi"
     19include "decl.pxi"
     20
     21initConstants()
     22
     23from sage.rings.all import Integer, ZZ
     24
     25cdef class String:
     26    def __cinit__(self, s=""):
     27        """
     28        Construct a Coxeter string from a Python string.
     29
     30        EXAMPLES::
     31
     32            sage: from sage.libs.coxeter3.coxeter import String       # optional - coxeter3
     33            sage: s = String("hello"); s                              # optional - coxeter3
     34            hello
     35        """
     36        String_construct_str(&self.x, s)
     37
     38    def __dealloc__(self):
     39        """
     40        Deallocate the memory for this string.
     41
     42        EXAMPLES::
     43
     44            sage: from sage.libs.coxeter3.coxeter import String       # optional - coxeter3
     45            sage: s = String("hello")                                 # optional - coxeter3
     46            sage: del s                                               # optional - coxeter3
     47        """
     48        String_destruct(&self.x)
     49
     50    def __repr__(self):
     51        """
     52        EXAMPLES::
     53
     54            sage: from sage.libs.coxeter3.coxeter import String       # optional - coxeter3
     55            sage: s = String('Hi')                                    # optional - coxeter3
     56            sage: s                                                   # optional - coxeter3
     57            Hi
     58        """
     59        return self.x.ptr()
     60
     61    def __hash__(self):
     62        """
     63        Return the hash of this String
     64
     65        This is the hash of the tuple consisting of the class name and
     66        the name of this type.
     67
     68        EXAMPLES::
     69
     70            sage: from sage.libs.coxeter3.coxeter import String        # optional - coxeter3
     71            sage: s = String('hello')                                  # optional - coxeter3
     72            sage: hash(s) == hash('hello')                             # optional - coxeter3
     73            True
     74        """
     75        return hash(repr(self))
     76
     77    def __richcmp__(String self, other, int op):
     78        """
     79        EXAMPLES::
     80
     81            sage: from sage.libs.coxeter3.coxeter import String        # optional - coxeter3
     82            sage: ta1 = String('A')                                    # optional - coxeter3
     83            sage: ta2 = String('A')                                    # optional - coxeter3
     84            sage: tb = String('b')                                     # optional - coxeter3
     85            sage: ta1 == ta2                                           # optional - coxeter3
     86            True
     87            sage: tb != ta1                                            # optional - coxeter3
     88            True
     89            sage: all([ta1 < tb, ta1 <= tb, ta1 <= ta1])               # optional - coxeter3
     90            True
     91            sage: all([tb > ta1, tb >= ta1, tb >= tb])                 # optional - coxeter3
     92            True
     93        """
     94        if type(other) != type(self):
     95            return False
     96
     97        s = repr(self)
     98        o = repr(other)
     99
     100        if op == 2: # ==
     101            return s == o
     102        elif op == 3: # !=
     103            return s != o
     104        elif op == 0: # <
     105            return s < o
     106        elif op == 1: # <=
     107            return s <= o
     108        elif op == 4: # >
     109            return s > o
     110        elif op == 5: # >=
     111            return s >= o
     112
     113    def __len__(self):
     114        """
     115        Return the length of this string.
     116
     117        EXAMPLES::
     118
     119            sage: from sage.libs.coxeter3.coxeter import String       # optional - coxeter3
     120            sage: s = String('Hi')                                    # optional - coxeter3
     121            sage: len(s)                                              # optional - coxeter3
     122            2
     123        """
     124        return self.x.length()
     125
     126    def __reduce__(self):
     127        """
     128        EXAMPLES::
     129
     130            sage: from sage.libs.coxeter3.coxeter import String       # optional - coxeter3
     131            sage: s = String('Hi')                                    # optional - coxeter3
     132            sage: TestSuite(s).run()                                  # optional - coxeter3
     133        """
     134        return (String, (repr(self),) )
     135
     136cdef class Type:
     137    def __cinit__(self, s):
     138        """
     139        Construct a Coxeter Type from a Python string.
     140
     141        EXAMPLES::
     142
     143            sage: from sage.libs.coxeter3.coxeter import Type         # optional - coxeter3
     144            sage: t = Type('A'); t                                    # optional - coxeter3
     145            A
     146        """
     147        Type_construct_str(&self.x, s)
     148
     149    def __dealloc__(self):
     150        """
     151        Deallocate the memory for this Type.
     152
     153        EXAMPLES::
     154
     155            sage: from sage.libs.coxeter3.coxeter import Type         # optional - coxeter3
     156            sage: t = Type('A')                                       # optional - coxeter3
     157            sage: del t                                               # optional - coxeter3
     158        """
     159        Type_destruct(&self.x)
     160
     161    def __repr__(self):
     162        """
     163        EXAMPLES::
     164
     165            sage: from sage.libs.coxeter3.coxeter import Type         # optional - coxeter3
     166            sage: t = Type('A'); t                                    # optional - coxeter3
     167            A
     168        """
     169        return self.x.name().ptr()
     170
     171    def name(self):
     172        """
     173        EXAMPLES::
     174
     175            sage: from sage.libs.coxeter3.coxeter import Type         # optional - coxeter3
     176            sage: t = Type('A')                                       # optional - coxeter3
     177            sage: t.name()                                            # optional - coxeter3
     178            A
     179        """
     180        return String(self.x.name().ptr())
     181
     182    def __hash__(self):
     183        """
     184        Return the hash of this Type.
     185
     186        This is the hash of the tuple consisting of the class name and
     187        the name of this type.
     188
     189        EXAMPLES::
     190
     191            sage: from sage.libs.coxeter3.coxeter import Type          # optional - coxeter3
     192            sage: a = Type('A')                                        # optional - coxeter3
     193            sage: b = Type('B')                                        # optional - coxeter3
     194            sage: hash(a) == hash(b)                                   # optional - coxeter3
     195            False
     196            sage: d = {a: 1, b: 2}                                     # optional - coxeter3
     197        """
     198        return hash((self.__class__.__name__, self.name()))
     199
     200    def __richcmp__(Type self, other, int op):
     201        """
     202        EXAMPLES::
     203
     204            sage: from sage.libs.coxeter3.coxeter import Type          # optional - coxeter3
     205            sage: ta1 = Type('A')                                      # optional - coxeter3
     206            sage: ta2 = Type('A')                                      # optional - coxeter3
     207            sage: tb = Type('b')                                       # optional - coxeter3
     208            sage: ta1 == ta2                                           # optional - coxeter3
     209            True
     210            sage: tb != ta1                                            # optional - coxeter3
     211            True
     212            sage: all([ta1 < tb, ta1 <= tb, ta1 <= ta1])               # optional - coxeter3
     213            True
     214            sage: all([tb > ta1, tb >= ta1, tb >= tb])                 # optional - coxeter3
     215            True
     216        """
     217        if type(other) != type(self):
     218            return False
     219
     220        s = repr(self)
     221        o = repr(other)
     222
     223        if op == 2: # ==
     224            return s == o
     225        elif op == 3: # !=
     226            return s != o
     227        elif op == 0: # <
     228            return s < o
     229        elif op == 1: # <=
     230            return s <= o
     231        elif op == 4: # >
     232            return s > o
     233        elif op == 5: # >=
     234            return s >= o
     235
     236    def __reduce__(self):
     237        """
     238        EXAMPLES::
     239
     240            sage: from sage.libs.coxeter3.coxeter import Type           # optional - coxeter3
     241            sage: t = Type('A')                                         # optional - coxeter3
     242            sage: TestSuite(t).run()                                    # optional - coxeter3
     243        """
     244        return (Type, (repr(self), ))
     245
     246cdef class CoxGroup(SageObject):
     247    def __cinit__(self, cartan_type):
     248        """
     249        EXAMPLES::
     250
     251            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup   # optional - coxeter3
     252            sage: W = CoxGroup(['A', 5]); W                                         # optional - coxeter3
     253            Coxeter group of type A and rank 5
     254
     255        Coxeter 3 segfault's on the trivial Coxeter group; so we catch
     256        this and raise a not implemented error::
     257
     258            sage: W = CoxGroup(['A', 0]); W                                         # optional - coxeter3
     259            Traceback (most recent call last):
     260            ...
     261            NotImplementedError: Coxeter group of type ['A',0] using Coxeter 3 not yet implemented
     262        """
     263        from sage.combinat.root_system.all import CartanType, coxeter_matrix
     264        self.cartan_type = CartanType(cartan_type)
     265        ordering = self._ordering_from_cartan_type(self.cartan_type)
     266
     267        if len(cartan_type) == 2:
     268            type, rank = cartan_type
     269        else:
     270            type, rank, affine = cartan_type
     271            if affine != 1:
     272                raise NotImplementedError
     273
     274            type = type.lower()
     275            rank = rank + 1
     276
     277        type = 'B' if type == 'C' else type
     278
     279        if rank == 0:
     280            raise NotImplementedError("Coxeter group of type ['A',0] using Coxeter 3 not yet implemented")
     281        cdef Type t = Type(type)
     282        cdef c_CoxGroup* c_W = coxeterGroup(t.x, rank)
     283        self.x = c_W
     284        self.out_ordering = dict(zip(range(1, rank+1), ordering))
     285        self.in_ordering = dict([(b,a) for a,b in self.out_ordering.items()])
     286
     287        # Check that the coxeter matrices match up.
     288        if self.coxeter_matrix() != coxeter_matrix(self.cartan_type):
     289            print "Warning, differing coxeter matrices"
     290
     291    @classmethod
     292    def _ordering_from_cartan_type(cls, cartan_type):
     293        """
     294        Return an ordering of the index set associated to the Cartan type.
     295
     296        EXAMPLES::
     297
     298            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup       # optional - coxeter3
     299            sage: W = CoxGroup(['A', 5])                                                # optional - coxeter3
     300            sage: W._ordering_from_cartan_type(CartanType(['A',5]))                     # optional - coxeter3
     301            [1, 2, 3, 4, 5]
     302        """
     303        from sage.misc.all import srange
     304        from sage.rings.all import Integer
     305        t = cartan_type.type()
     306        r = cartan_type.rank()
     307        is_affine = cartan_type.is_affine()
     308
     309        if t in ['B', 'C', 'D', 'F', 'H']:
     310            return srange(r-1 if is_affine else r,
     311                          -1 if is_affine else 0, -1)
     312        elif t in ['A', 'I']:
     313            return srange(0 if is_affine else 1, r+1)
     314        elif t in ['G']:
     315            if is_affine:
     316                raise NotImplementedError
     317            else:
     318                return map(Integer, [1, 2])
     319        elif t in ['E']:
     320            if is_affine:
     321                return srange(1, r) + [Integer(0)]
     322            else:
     323                return srange(1, r+1)
     324        else:
     325            raise NotImplementedError
     326
     327    def __hash__(self):
     328        """
     329        Return the hash of this CoxGroup.
     330
     331        This is the hash of the tuple of the class's name, the type,
     332        and the rank.
     333
     334        EXAMPLES::
     335
     336            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup       # optional - coxeter3
     337            sage: A4 = CoxGroup(['A', 4])                                               # optional - coxeter3
     338            sage: d = {A4: True}                                                        # optional - coxeter3
     339        """
     340        return hash((self.__class__.__name__, self.type(), self.rank()))
     341
     342    def __richcmp__(CoxGroup self, other, int op):
     343        """
     344        EXAMPLES::
     345
     346            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup       # optional - coxeter3
     347            sage: A4 = CoxGroup(['A', 4])                                               # optional - coxeter3
     348            sage: A5 = CoxGroup(['A', 5])                                               # optional - coxeter3
     349            sage: B4 = CoxGroup(['B', 4])                                               # optional - coxeter3
     350            sage: A4 == A4                                                              # optional - coxeter3
     351            True
     352            sage: A4 != B4                                                              # optional - coxeter3
     353            True
     354            sage: A4 < B4                                                               # optional - coxeter3
     355            True
     356            sage: A5 > A4                                                               # optional - coxeter3
     357            True
     358            sage: A4 >= A4                                                              # optional - coxeter3
     359            True
     360            sage: B4 >= A5                                                              # optional - coxeter3
     361            True
     362        """
     363        if type(other) != type(self):
     364            return False
     365
     366        s_t = self.type()
     367        o_t = other.type()
     368        s_r = self.rank()
     369        o_r = other.rank()
     370
     371        if op == 2: # ==
     372            return s_t == o_t and s_r == o_r
     373        elif op == 3: # !=
     374            return s_t != o_t or s_r != o_r
     375        elif op == 0: # <
     376            return s_t < o_t or (s_t == o_t and s_r < o_r)
     377        elif op == 1: # <=
     378            return s_t < o_t or (s_t == o_t and s_r <= o_r)
     379        elif op == 4: # >
     380            return s_t > o_t or (s_t == o_t and s_r > o_r)
     381        elif op == 5: # >=
     382            return s_t > o_t or (s_t == o_t and s_r >= o_r)
     383
     384    def __reduce__(self):
     385        """
     386        EXAMPLES::
     387
     388            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup      # optional - coxeter3
     389            sage: W = CoxGroup(['A', 5])                                               # optional - coxeter3
     390            sage: TestSuite((W)).run()                                                 # optional - coxeter3
     391        """
     392        return (CoxGroup, (self.cartan_type,))
     393
     394    def __dealloc__(self):
     395        """
     396        Deallocate the memory for this CoxGroup.
     397
     398        EXAMPLES::
     399
     400            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup      # optional - coxeter3
     401            sage: W = CoxGroup(['A', 5])                                               # optional - coxeter3
     402            sage: del W                                                                # optional - coxeter3
     403        """
     404        CoxGroup_delete(self.x)
     405
     406    def __repr__(self):
     407        """
     408        Return a string representation of this Coxeter group.
     409
     410        EXAMPLES::
     411
     412            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup      # optional - coxeter3
     413            sage: W = CoxGroup(['A', 5]); W                                            # optional - coxeter3
     414            Coxeter group of type A and rank 5
     415        """
     416        return "Coxeter group of type %s and rank %s"%(self.type(), self.rank())
     417
     418    def __iter__(self):
     419        """
     420        EXAMPLES::
     421
     422            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup      # optional - coxeter3
     423            sage: W = CoxGroup(['A', 2])                                               # optional - coxeter3
     424            sage: list(iter(W))                                                        # optional - coxeter3
     425            [[], [1], [2], [1, 2], [2, 1], [1, 2, 1]]
     426        """
     427        return CoxGroupIterator(self)
     428
     429    def bruhat_interval(self, w, v):
     430        """
     431        Return the list of the elements in the Bruhat interval between `w` and `v`.
     432
     433        EXAMPLES::
     434
     435            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup      # optional - coxeter3
     436            sage: W = CoxGroup(['A', 2])                                               # optional - coxeter3
     437            sage: W.bruhat_interval([], [1,2])                                         # optional - coxeter3
     438            [[], [1], [2], [1, 2]]
     439        """
     440        cdef CoxGroupElement ww = CoxGroupElement(self, w)
     441        cdef CoxGroupElement vv = CoxGroupElement(self, v)
     442        cdef c_List_CoxWord l = c_List_CoxWord_factory(0)
     443        interval(l, self.x[0], ww.word, vv.word)
     444        bruhat_interval = []
     445        cdef int j = 0
     446        cdef CoxGroupElement u
     447        cdef CoxGroupElement gg = CoxGroupElement(self, [])
     448        for j from 0 <= j < l.size():
     449            u = gg._new()
     450            u.word = l.get_index(j)
     451            bruhat_interval.append(u)
     452
     453        # This destruction most likely does not be belong there, and
     454        # it causes a segfault. See discussion on #12912.
     455        # List_CoxWord_destruct(&l)
     456
     457        return bruhat_interval
     458
     459    def orderings(self):
     460        """
     461        Return two dictionaries specifying the mapping of the labels
     462        of the Dynkin diagram between Sage and Coxeter3 and the its
     463        inverse.
     464
     465        EXAMPLES::
     466
     467            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup       # optional - coxeter3
     468            sage: W = CoxGroup(['A', 5])                                                # optional - coxeter3
     469            sage: W.orderings()                                                         # optional - coxeter3
     470            ({1: 1, 2: 2, 3: 3, 4: 4, 5: 5}, {1: 1, 2: 2, 3: 3, 4: 4, 5: 5})
     471        """
     472        return self.in_ordering, self.out_ordering
     473
     474    def type(self):
     475        """
     476        Return the type of this Coxeter group.
     477
     478        Note that the type does not include the rank.
     479
     480        EXAMPLES::
     481
     482            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup       # optional - coxeter3
     483            sage: W = CoxGroup(['A', 5])                                                # optional - coxeter3
     484            sage: W.type()                                                              # optional - coxeter3
     485            A
     486        """
     487        return Type(self.x.type().name().ptr())
     488
     489    def rank(self):
     490        """
     491        Return the rank of this Coxeter group.
     492
     493        EXAMPLES::
     494
     495            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup       # optional - coxeter3
     496            sage: W = CoxGroup(['A', 5])                                                # optional - coxeter3
     497            sage: W.rank()                                                              # optional - coxeter3
     498            5
     499        """
     500        return self.x.rank()
     501
     502    def order(self):
     503        """
     504        Return the order of this Coxeter group.
     505
     506        EXAMPLES::
     507
     508            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup       # optional - coxeter3
     509            sage: W = CoxGroup(['A', 5])                                                # optional - coxeter3
     510            sage: W.order()                                                             # optional - coxeter3
     511            720
     512            sage: W = CoxGroup(['A', 3, 1])                                             # optional - coxeter3
     513            sage: W.order()                                                             # optional - coxeter3
     514            +Infinity
     515        """
     516        if self.is_finite():
     517            return Integer(self.x.order())
     518        else:
     519            from sage.all import infinity
     520            return infinity
     521
     522    def is_finite(self):
     523        """
     524        Return whether this Coxeter group is finite.
     525
     526        EXAMPLES::
     527
     528            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup       # optional - coxeter3
     529            sage: W = CoxGroup(['A', 5])                                                # optional - coxeter3
     530            sage: W.is_finite()                                                         # optional - coxeter3
     531            True
     532            sage: W = CoxGroup(['A', 3, 1])                                             # optional - coxeter3
     533            sage: W.is_finite()                                                         # optional - coxeter3
     534            False
     535        """
     536        return isFiniteType(self.x)
     537
     538    cpdef full_context(self):
     539        """
     540        Make all of the elements of a finite Coxeter group available.
     541
     542        Raises an error if W is not finite
     543
     544        EXAMPLES::
     545
     546            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup       # optional - coxeter3
     547            sage: W = CoxGroup(['A', 2])                                                # optional - coxeter3
     548            sage: W.full_context()                                                      # optional - coxeter3
     549            sage: W = CoxGroup(['A', 2,1])                                              # optional - coxeter3
     550            sage: W.full_context()                                                      # optional - coxeter3
     551            Traceback (most recent call last):
     552            ...
     553            TypeError: Group needs to be finite.
     554        """
     555        if not self.is_finite():
     556            raise TypeError, "Group needs to be finite."
     557        cdef c_FiniteCoxGroup* fcoxgroup = <c_FiniteCoxGroup*>(self.x)
     558        if not fcoxgroup.isFullContext():
     559            fcoxgroup.fullContext()
     560
     561
     562    def long_element(self):
     563        """
     564        Return the longest word in a finite Coxeter group.
     565
     566        EXAMPLES::
     567
     568            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup       # optional - coxeter3
     569            sage: W = CoxGroup(['A', 5])                                                # optional - coxeter3
     570            sage: W.long_element()                                                      # optional - coxeter3
     571            [1, 2, 1, 3, 2, 1, 4, 3, 2, 1, 5, 4, 3, 2, 1]
     572
     573            sage: W = CoxGroup(['A', 3, 1])                                             # optional - coxeter3
     574            sage: W.long_element()                                                      # optional - coxeter3
     575            Traceback (most recent call last):
     576            ...
     577            TypeError: Group needs to be finite.
     578        """
     579        self.full_context()
     580        cdef c_FiniteCoxGroup* fcoxgroup = <c_FiniteCoxGroup*>(self.x)
     581        cdef CoxGroupElement w0 = CoxGroupElement(self, [])
     582        w0.word = fcoxgroup.longest_coxword()
     583        return w0
     584
     585    def __call__(self, w):
     586        """
     587        Return a reduced expression for `w`.
     588
     589        INPUT:
     590
     591        - ``w`` -- a word for an element of ``self``, not necessarily reduced
     592
     593        OUTPUT:
     594
     595        - a reduced expression for ``w``
     596
     597        EXAMPLES::
     598
     599            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup      # optional - coxeter3
     600            sage: W = CoxGroup(['A', 5])                                               # optional - coxeter3
     601            sage: w = [1,1,3,5,4,5,4]                                                  # optional - coxeter3
     602            sage: W.__call__(w)                                                        # optional - coxeter3
     603            [3, 4, 5]
     604        """
     605        return CoxGroupElement(self, w).reduced()
     606
     607    def coxeter_matrix(self):
     608        """
     609        Return the Coxeter matrix for this Coxeter group.
     610
     611        EXAMPLES::
     612
     613            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup      # optional - coxeter3
     614            sage: W = CoxGroup(['A', 5])                                               # optional - coxeter3
     615            sage: W.coxeter_matrix()                                                   # optional - coxeter3
     616            [1 3 2 2 2]
     617            [3 1 3 2 2]
     618            [2 3 1 3 2]
     619            [2 2 3 1 3]
     620            [2 2 2 3 1]
     621
     622        """
     623        from sage.all import matrix, ZZ
     624        rank = self.rank()
     625        m = matrix(ZZ, rank, rank)
     626        for i, ii in enumerate(self.cartan_type.index_set()):
     627            ii = self.in_ordering[ii]-1
     628            for j, jj in enumerate(self.cartan_type.index_set()):
     629                jj = self.in_ordering[jj]-1
     630                m[i,j] = self.x.M(ii, jj)
     631        return m
     632
     633    def coxeter_graph(self):
     634        """
     635        Return the Coxeter graph for this Coxeter group.
     636
     637        OUTPUT:: a Sage graph
     638
     639        .. NOTE::
     640
     641           This uses the labels native to Coxeter3. This is useful
     642           when trying to obtain the mapping between the labels of
     643           Sage and Coxeter3.
     644
     645        EXAMPLES::
     646
     647            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup# optional - coxeter3
     648            sage: W = CoxGroup(['A', 5])                                         # optional - coxeter3
     649            sage: W.coxeter_graph()                                              # optional - coxeter3
     650            Graph on 5 vertices
     651            sage: sorted(W.coxeter_graph().edges())                              # optional - coxeter3
     652            [(1, 2, None), (2, 3, None), (3, 4, None), (4, 5, None)]
     653        """
     654        from sage.all import Graph
     655        g = Graph()
     656        m = self.coxeter_matrix()
     657        rank = self.rank()
     658        for i, row in enumerate(m.rows()):
     659            for j in range(i+1,rank):
     660                if row[j] == 3:
     661                    g.add_edge(i+1, j+1)
     662                elif row[j] > 4:
     663                    g.add_edge(i+1, j+1, row[j])
     664        return g
     665
     666
     667
     668cdef class CoxGroupElement:
     669    def __init__(self, CoxGroup group, w, normal_form=True):
     670        """
     671        TESTS::
     672
     673            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement  # optional - coxeter3
     674            sage: W = CoxGroup(['A', 5])                                                            # optional - coxeter3
     675            sage: w = CoxGroupElement(W, [2,1,2,1,1], normal_form=False); w                         # optional - coxeter3
     676            [2, 1, 2, 1, 1]
     677            sage: w = CoxGroupElement(W, [1,1,4,5,4], normal_form=False); w                         # optional - coxeter3
     678            [1, 1, 4, 5, 4]
     679            sage: w = CoxGroupElement(W, [1,1,4,5,4]); w                                            # optional - coxeter3
     680            [4, 5, 4]
     681        """
     682        self.group = (<CoxGroup>group).x
     683        self._parent = group
     684        self.word.reset()
     685        for i in w:
     686            self.word.append_letter(self._parent.in_ordering[i])
     687
     688        if normal_form:
     689            self.group.normalForm(self.word)
     690
     691
     692    def __cinit__(self):
     693        """
     694        TESTS::
     695
     696            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement  # optional - coxeter3
     697            sage: W = CoxGroup(['A', 4])                                                            # optional - coxeter3
     698            sage: CoxGroupElement(W, [1,2,3,2,3])                                                   # optional - coxeter3
     699            [1, 3, 2]
     700        """
     701        CoxWord_construct(&self.word)
     702
     703    def __dealloc__(self):
     704        """
     705        TESTS::
     706
     707            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement  # optional - coxeter3
     708            sage: W = CoxGroup(['A', 4])                                                            # optional - coxeter3
     709            sage: w = CoxGroupElement(W, [1,2,3,2,3])                                               # optional - coxeter3
     710            sage: del w                                                                             # optional - coxeter3
     711        """
     712        CoxWord_destruct(&self.word)
     713
     714    def _coxnumber(self):
     715        """
     716        Return the internal integer used by Coxeter3 to represent this element.
     717
     718        TESTS::
     719
     720            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement  # optional - coxeter3
     721            sage: W = CoxGroup(['A', 4])                                                            # optional - coxeter3
     722            sage: w = CoxGroupElement(W, [1,2,3,2,3])                                               # optional - coxeter3
     723            sage: w._coxnumber()                                                                    # optional - coxeter3
     724            7L
     725        """
     726        return self.group.extendContext(self.word)
     727
     728    def __reduce__(self):
     729        """
     730        EXAMPLES::
     731
     732            sage: from sage.libs.coxeter3.coxeter import *                                          # optional - coxeter3
     733            sage: W = CoxGroup(['A',5])                                                             # optional - coxeter3
     734            sage: w = W([1,2,3])                                                                    # optional - coxeter3
     735            sage: TestSuite(w).run()                                                                # optional - coxeter3
     736        """
     737        return (CoxGroupElement, (self._parent, list(self)))
     738
     739    def __invert__(self):
     740        """
     741        Return the inverse of this element.
     742
     743        EXAMPLES::
     744
     745
     746            sage: from sage.libs.coxeter3.coxeter import *                                          # optional - coxeter3
     747            sage: W = CoxGroup(['A',5])                                                             # optional - coxeter3
     748            sage: w = W([1,2,3])                                                                    # optional - coxeter3
     749            sage: ~w                                                                                # optional - coxeter3
     750            [3, 2, 1]
     751        """
     752        return CoxGroupElement(self._parent, reversed(self))
     753
     754    inverse = __invert__
     755
     756    cpdef CoxGroup parent(self):
     757        """
     758        Return the parent Coxeter group for this element.
     759
     760        EXAMPLES::
     761
     762            sage: from sage.libs.coxeter3.coxeter import *                                          # optional - coxeter3
     763            sage: W = CoxGroup(['A',5])                                                             # optional - coxeter3
     764            sage: w = W([1,2,3])                                                                    # optional - coxeter3
     765            sage: w.parent()                                                                        # optional - coxeter3
     766            Coxeter group of type A and rank 5
     767
     768        """
     769        return self._parent
     770
     771    def __getitem__(self, i):
     772        """
     773        Return the `i^{th}` entry of this element.
     774
     775        EXAMPLES::
     776
     777            sage: from sage.libs.coxeter3.coxeter import *                                          # optional - coxeter3
     778            sage: W = CoxGroup(['A',5])                                                             # optional - coxeter3
     779            sage: w = W([1,2,3])                                                                    # optional - coxeter3
     780            sage: w[0]                                                                              # optional - coxeter3
     781            1
     782            sage: w[2]                                                                              # optional - coxeter3
     783            3
     784            sage: w[:-2]                                                                            # optional - coxeter3
     785            [1]
     786            sage: w[-2:]                                                                            # optional - coxeter3
     787            [2, 3]
     788            sage: w[3:0:-1]                                                                         # optional - coxeter3
     789            [3, 2]
     790            sage: w[4]                                                                              # optional - coxeter3
     791            Traceback (most recent call last):
     792            ...
     793            IndexError: The index (4) is out of range.
     794        """
     795        if isinstance(i, slice):
     796            #Get the start, stop, and step from the slice
     797            return [self[ii] for ii in xrange(*i.indices(len(self)))]
     798        if i < 0:
     799            i += len(self)
     800        if i >= len(self):
     801            raise IndexError, "The index (%d) is out of range."%i
     802
     803        return self._parent.out_ordering[self.word.get_index(i)]
     804
     805    def __repr__(self):
     806        """
     807        Return a string representation of this CoxGroupElement as a list of generators.
     808
     809        EXAMPLES::
     810
     811            sage: from sage.libs.coxeter3.coxeter import *          # optional - coxeter3
     812            sage: W = CoxGroup(['A',5])                             # optional - coxeter3
     813            sage: w = W([1,2,3]); w                                 # optional - coxeter3
     814            [1, 2, 3]
     815
     816        """
     817        return repr(list(self))
     818
     819    def __hash__(self):
     820        """
     821        Return the hash of this element.
     822
     823        This is a hash of the tuple of the class name, the parent, and
     824        a tuple of the reduced word.
     825
     826        EXAMPLES::
     827
     828            sage: from sage.libs.coxeter3.coxeter import *         # optional - coxeter3
     829            sage: W = CoxGroup(['A', 5])                           # optional - coxeter3
     830            sage: w = W([1,2,3])                                   # optional - coxeter3
     831            sage: v = W([2,3,4])                                   # optional - coxeter3
     832            sage: hash(w) == hash(v)                               # optional - coxeter3
     833            False
     834        """
     835        return hash((self.__class__.__name__, self.parent(), tuple(self)))
     836
     837    def __richcmp__(CoxGroupElement self, other, int op):
     838        """
     839        EXAMPLES:
     840
     841            sage: from sage.libs.coxeter3.coxeter import *        # optional - coxeter3
     842            sage: W = CoxGroup(['A', 5])                          # optional - coxeter3
     843            sage: V = CoxGroup(['A', 6])                          # optional - coxeter3
     844            sage: w1 = W([1,2,3])                                 # optional - coxeter3
     845            sage: w2 = W([2,3,4])                                 # optional - coxeter3
     846            sage: v1 = V([1,2,3])                                 # optional - coxeter3
     847            sage: w1 == w1                                        # optional - coxeter3
     848            True
     849            sage: w1 != w2                                        # optional - coxeter3
     850            True
     851            sage: all([w1 < w2, w1 <= w2, w1 <= w1])              # optional - coxeter3
     852            True
     853            sage: all([w2 > w1, w2 >= w1, w2 >= w2])              # optional - coxeter3
     854            True
     855            sage: w1 == v1                                        # optional - coxeter3
     856            False
     857            sage: w1 != v1                                        # optional - coxeter3
     858            True
     859        """
     860        if type(other) != type(self):
     861            return False
     862
     863        s_p = self.parent()
     864        o_p = other.parent()
     865        s_l = list(self)
     866        o_l = list(other)
     867
     868        if op == 2: # ==
     869            return s_p == o_p and s_l == o_l
     870        elif op == 3: # !=
     871            return s_p != o_p or s_l != o_l
     872        elif op == 0: # <
     873            return s_p < o_p or (s_p == o_p and s_l < o_l)
     874        elif op == 1: # <=
     875            return s_p < o_p or (s_p == o_p and s_l <= o_l)
     876        elif op == 4: # >
     877            return s_p > o_p or (s_p == o_p and s_l > o_l)
     878        elif op == 5: # >=
     879            return s_p > o_p or (s_p == o_p and s_l >= o_l)
     880
     881
     882    def __iter__(self):
     883        """
     884        Return an iterator for the letters in the reduced word for this element.
     885
     886        EXAMPLES::
     887
     888            sage: from sage.libs.coxeter3.coxeter import *      # optional - coxeter3
     889            sage: W = CoxGroup(['A',5])                         # optional - coxeter3
     890            sage: w = W([1,2,3])                                # optional - coxeter3
     891            sage: [a for a in w]                                # optional - coxeter3
     892            [1, 2, 3]
     893        """
     894        return (self[i] for i in xrange(len(self)))
     895
     896    def __len__(self):
     897        """
     898        Return the length of this element.
     899
     900        EXAMPLES::
     901
     902            sage: from sage.libs.coxeter3.coxeter import *       # optional - coxeter3
     903            sage: W = CoxGroup(['A',5])                          # optional - coxeter3
     904            sage: w = W([1,2,3])                                 # optional - coxeter3
     905            sage: len(w)                                         # optional - coxeter3
     906            3
     907        """
     908        return self.word.length()
     909
     910    def left_descents(self):
     911        """
     912        Return the left descent set of this element.
     913
     914        EXAMPLES::
     915
     916            sage: from sage.libs.coxeter3.coxeter import *      # optional - coxeter3
     917            sage: W = CoxGroup(['A',5])                         # optional - coxeter3
     918            sage: w = W([1,2,1])                                # optional - coxeter3
     919            sage: w.left_descents()                             # optional - coxeter3
     920            [1, 2]
     921        """
     922        return LFlags_to_list(self._parent, self.group.ldescent(self.word))
     923
     924    def right_descents(self):
     925        """
     926        Return the right descent set of this element.
     927
     928        EXAMPLES::
     929
     930            sage: from sage.libs.coxeter3.coxeter import *      # optional - coxeter3
     931            sage: W = CoxGroup(['A',5])                         # optional - coxeter3
     932            sage: w = W([1,2,1])                                # optional - coxeter3
     933            sage: w.right_descents()                            # optional - coxeter3
     934            [1, 2]
     935        """
     936        return LFlags_to_list(self._parent, self.group.rdescent(self.word))
     937
     938    def bruhat_le(self, w):
     939        """
     940        Return whether u = (self) is less than w in Bruhat order.
     941
     942        EXAMPLES::
     943
     944            sage: from sage.libs.coxeter3.coxeter import *       # optional - coxeter3
     945            sage: W = CoxGroup(['A',5])                          # optional - coxeter3
     946            sage: w = W([1,2,3,4,5,4])                           # optional - coxeter3
     947            sage: v = W([1,2,4,5,4])                             # optional - coxeter3
     948            sage: v.bruhat_le(w)                                 # optional - coxeter3
     949            True
     950            sage: w.bruhat_le(w)                                 # optional - coxeter3
     951            True
     952            sage: w.bruhat_le(v)                                 # optional - coxeter3
     953            False
     954        """
     955        cdef CoxGroupElement ww = CoxGroupElement(self._parent, w)
     956        return self.group.inOrder_word(self.word, ww.word)
     957
     958    def is_two_sided_descent(self, s):
     959        """
     960        Return whether ``s`` is a two sided descent of ``self``.
     961
     962        EXAMPLES::
     963
     964            sage: from sage.libs.coxeter3.coxeter import *       # optional - coxeter3
     965            sage: W = CoxGroup(['A',2])                          # optional - coxeter3
     966            sage: x = W([1,2,1])                                 # optional - coxeter3
     967            sage: x.is_two_sided_descent(1)                      # optional - coxeter3
     968            True
     969        """
     970        cdef Generator ss = self._parent.in_ordering[s]
     971        return self.group.isDescent(self.word, s)
     972
     973    cdef CoxGroupElement _new(self):
     974        """
     975        Return a new copy of this element.
     976        """
     977        cdef CoxGroupElement res = CoxGroupElement(self.parent(), [])
     978        res.word.set(self.word)
     979        return res
     980
     981    def coatoms(self):
     982        """
     983        Return the coatoms of this element in Bruhat order.
     984
     985        EXAMPLES::
     986
     987            sage: from sage.libs.coxeter3.coxeter import *          # optional - coxeter3
     988            sage: W = CoxGroup(['A',2])                             # optional - coxeter3
     989            sage: W([1,2,1]).coatoms()                              # optional - coxeter3
     990            [[2, 1], [1, 2]]
     991            sage: W([]).coatoms()                                   # optional - coxeter3
     992            []
     993        """
     994        cdef c_List_CoxWord list = c_List_CoxWord_factory(0)
     995        self.group.coatoms(list, self.word)
     996
     997        coatoms = []
     998
     999        cdef Length i = 0
     1000        cdef CoxGroupElement res
     1001        for i from 0 <= i < list.size():
     1002            res = self._new()
     1003            res.word = list.get_index(i)
     1004            coatoms.append(res)
     1005        return coatoms
     1006
     1007    def normal_form(self):
     1008        """
     1009        Return ``self`` in normal form.
     1010
     1011        This is the lexicographically minimal reduced word for
     1012        ``self``.
     1013
     1014        EXAMPLES::
     1015
     1016            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement  # optional - coxeter3
     1017            sage: W = CoxGroup(['A', 5])                                                            # optional - coxeter3
     1018            sage: w = CoxGroupElement(W, [2,1,2], normal_form=False); w                             # optional - coxeter3
     1019            [2, 1, 2]
     1020            sage: w.normal_form()                                                                   # optional - coxeter3
     1021            [1, 2, 1]
     1022
     1023        """
     1024        cdef CoxGroupElement res = self._new()
     1025        self.group.normalForm(res.word)
     1026        return res
     1027
     1028    def reduced(self):
     1029        """
     1030        Return a reduced word for this element.
     1031
     1032        EXAMPLES::
     1033
     1034            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupElement  # optional - coxeter3
     1035            sage: W = CoxGroup(['A', 5])                                                            # optional - coxeter3
     1036            sage: w = CoxGroupElement(W, [2,1,2,1,1], normal_form=False); w                         # optional - coxeter3
     1037            [2, 1, 2, 1, 1]
     1038            sage: w.reduced()                                                                       # optional - coxeter3
     1039            [1, 2, 1]
     1040        """
     1041        cdef CoxGroupElement res = self._new()
     1042        self.group.reduced(res.word, self.word)
     1043        return res
     1044
     1045    def __mul__(CoxGroupElement self, CoxGroupElement y):
     1046        """
     1047        EXAMPLES::
     1048
     1049            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup                    # optional - coxeter3
     1050            sage: W = CoxGroup(['A', 5])                                                             # optional - coxeter3
     1051            sage: W([1]) * W([1])                                                                    # optional - coxeter3
     1052            []
     1053            sage: W([1,2]) * W([1])                                                                  # optional - coxeter3
     1054            [1, 2, 1]
     1055        """
     1056        cdef CoxGroupElement res = self._new()
     1057        self.group.prod(res.word, y.word)
     1058        return res
     1059
     1060    def poincare_polynomial(self):
     1061        """
     1062        Return the Poincare polynomial associated with the Bruhat
     1063        interval between the identity element and this one.
     1064
     1065        EXAMPLES::
     1066
     1067            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup                    # optional - coxeter3
     1068            sage: W = CoxGroup(['A', 5])                                                             # optional - coxeter3
     1069            sage: W([]).poincare_polynomial()                                                        # optional - coxeter3
     1070            1
     1071            sage: W([1,2,1]).poincare_polynomial()                                                   # optional - coxeter3
     1072            t^3 + 2*t^2 + 2*t + 1
     1073        """
     1074        cdef CoxGroup W = self.parent()
     1075        cdef c_List_CoxWord result = c_List_CoxWord_factory(0)
     1076        cdef CoxGroupElement id = CoxGroupElement(W, [])
     1077        cdef CoxGroupElement ww = CoxGroupElement(W, self)
     1078        interval(result, W.x[0], id.word, ww.word)
     1079
     1080        cdef int j = 0
     1081        cdef list coefficients = [0]*(len(ww)+1)
     1082        for j from 0 <= j < result.size():
     1083            coefficients[result.get_index(j).length()] += 1
     1084        return ZZ['t'](coefficients)
     1085
     1086
     1087    def kazhdan_lusztig_polynomial(self, v):
     1088        """
     1089        Return the Kazhdan-Lusztig polynomial `P_{u,v}` where `u` is this element.
     1090
     1091        Currently this is a bit inefficient as it constructs the
     1092        polynomial from its string representation.
     1093
     1094        EXAMPLES::
     1095
     1096            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup                    # optional - coxeter3
     1097            sage: W = CoxGroup(['A', 2])                                                             # optional - coxeter3
     1098            sage: W([]).kazhdan_lusztig_polynomial([1,2,1])                                          # optional - coxeter3
     1099            1
     1100            sage: W([1,2,1]).kazhdan_lusztig_polynomial([])                                          # optional - coxeter3
     1101            0
     1102        """
     1103        from sage.all import ZZ
     1104        cdef CoxGroupElement vv
     1105        if not isinstance(v, CoxGroupElement):
     1106            vv = CoxGroupElement(self._parent, v)
     1107        else:
     1108            vv = v
     1109
     1110        ZZq = ZZ['q']
     1111        if not self.group.inOrder_word(self.word, vv.word):
     1112            return ZZq(0)
     1113
     1114        cdef CoxNbr x = self.group.extendContext(self.word)
     1115        cdef CoxNbr y = self.group.extendContext(vv.word)
     1116        cdef c_KLPol kl_poly = self.group.klPol(x, y)
     1117
     1118        cdef String s = String()
     1119        klpoly_append(s.x, kl_poly, "q")
     1120        return ZZq(str(s))
     1121
     1122    def mu_coefficient(self, v):
     1123        r"""
     1124        Return the mu coefficient `\mu(u,v)` where `u` is this element.
     1125
     1126        EXAMPLES::
     1127
     1128            sage: from sage.libs.coxeter3.coxeter import *          # optional - coxeter3
     1129            sage: W = CoxGroup(['A',5])                             # optional - coxeter3
     1130            sage: w = W([1,2,3,4,5,4])                              # optional - coxeter3
     1131            sage: v = W([1,2,4,5,4])                                # optional - coxeter3
     1132            sage: w.mu_coefficient(v)                               # optional - coxeter3
     1133            0
     1134            sage: w.mu_coefficient(w)                               # optional - coxeter3
     1135            0
     1136            sage: v.mu_coefficient(w)                               # optional - coxeter3
     1137            1
     1138        """
     1139        from sage.all import ZZ
     1140        cdef CoxGroupElement vv = CoxGroupElement(self._parent, v)
     1141        cdef CoxNbr x = self.group.extendContext(self.word)
     1142        cdef CoxNbr y = self.group.extendContext(vv.word)
     1143        return ZZ(self.group.mu(x,y))
     1144
     1145cdef LFlags_to_list(CoxGroup parent, LFlags f):
     1146    """
     1147    Return the right descent set of this element.
     1148
     1149    EXAMPLES::
     1150
     1151        sage: from sage.libs.coxeter3.coxeter import *         # optional - coxeter3
     1152        sage: W = CoxGroup(['A',5])                            # optional - coxeter3
     1153        sage: w = W([1,2,1])                                   # optional - coxeter3
     1154        sage: w.right_descents()                               # optional - coxeter3
     1155        [1, 2]
     1156    """
     1157    cdef Generator s
     1158    cdef LFlags f1 = f
     1159    l = []
     1160    while f1:
     1161        s = firstBit(f1)
     1162        l.append(parent.out_ordering[s+1])
     1163        f1 = f1 & (f1-1)
     1164    return l
     1165
     1166class CoxGroupIterator(object):
     1167    def __init__(self, group):
     1168        """
     1169        A class used to iterate over all of the elements of a Coxeter group.
     1170
     1171        .. note::
     1172
     1173           This will construct all of the elements of the group within
     1174           Coxeter3.  For some groups, this may be too large to fit
     1175           into memory.
     1176
     1177        EXAMPLES::
     1178
     1179            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator # optional - coxeter3
     1180            sage: W = CoxGroup(['A', 2])                                                            # optional - coxeter3
     1181            sage: it = CoxGroupIterator(W)                                                          # optional - coxeter3
     1182            sage: [it.next() for i in range(W.order())]                                             # optional - coxeter3
     1183            [[], [1], [2], [1, 2], [2, 1], [1, 2, 1]]
     1184        """
     1185        self.group = group
     1186        self.order = group.order()
     1187        self.n = 0
     1188        self.group.full_context()
     1189
     1190    def __iter__(self):
     1191        """
     1192        Return self, as per the iterator protocol.
     1193
     1194        EXAMPLES::
     1195
     1196            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator # optional - coxeter3
     1197            sage: W = CoxGroup(['A', 2])                                                            # optional - coxeter3
     1198            sage: it = iter(W)                                                                      # optional - coxeter3
     1199            sage: it is iter(it)                                                                    # optional - coxeter3
     1200            True
     1201        """
     1202        return self
     1203
     1204    def next(self):
     1205        """
     1206        Return the next element in the associated Coxeter group.
     1207
     1208        EXAMPLES::
     1209
     1210            sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator # optional - coxeter3
     1211            sage: W = CoxGroup(['A', 2])                                                            # optional - coxeter3
     1212            sage: it = CoxGroupIterator(W)                                                          # optional - coxeter3
     1213            sage: it.next()                                                                         # optional - coxeter3
     1214            []
     1215        """
     1216        if self.n >= self.order:
     1217            raise StopIteration
     1218        cdef CoxGroupElement w = self.group([])
     1219
     1220        (<CoxGroup>self.group).x.prod_nbr(w.word, self.n)
     1221        self.n += 1
     1222        return w
     1223
     1224CoxGroup_cache = {}
     1225def get_CoxGroup(cartan_type):
     1226    """
     1227    TESTS::
     1228
     1229        sage: from sage.libs.coxeter3.coxeter import get_CoxGroup as CoxGroup, CoxGroupIterator  # optional - coxeter3
     1230        sage: W = CoxGroup(['A', 2])                                                             # optional - coxeter3
     1231    """
     1232    from sage.all import CartanType
     1233    cartan_type = CartanType(cartan_type)
     1234    if cartan_type not in CoxGroup_cache:
     1235        CoxGroup_cache[cartan_type] = CoxGroup(cartan_type)
     1236    return CoxGroup_cache[cartan_type]
  • new file sage/libs/coxeter3/coxeter_group.py

    diff --git a/sage/libs/coxeter3/coxeter_group.py b/sage/libs/coxeter3/coxeter_group.py
    new file mode 100644
    - +  
     1"""
     2Coxeter Groups implemented with Coxeter3
     3"""
     4#*****************************************************************************
     5#       Copyright (C) 2009-2013 Mike Hansen <mhansen@gmail.com>
     6#
     7#  Distributed under the terms of the GNU General Public License (GPL)
     8#                  http://www.gnu.org/licenses/
     9#*****************************************************************************
     10from sage.groups.group import Group
     11from sage.libs.coxeter3.coxeter import get_CoxGroup, CoxGroupElement
     12from sage.structure.element import MultiplicativeGroupElement
     13from sage.misc.cachefunc import cached_method
     14
     15from sage.structure.unique_representation import UniqueRepresentation
     16from sage.structure.element_wrapper import ElementWrapper
     17from sage.categories.all import CoxeterGroups, FiniteCoxeterGroups
     18from sage.structure.parent import Parent
     19
     20class CoxeterGroup(UniqueRepresentation, Parent):
     21    @staticmethod
     22    def __classcall__(cls, cartan_type, *args, **options):
     23        """
     24        TESTS::
     25
     26            sage: from sage.libs.coxeter3.coxeter_group import CoxeterGroup # optional - coxeter3
     27            sage: CoxeterGroup(['B',2])                                     # optional - coxeter3
     28            Coxeter group of type ['B', 2] implemented by Coxeter3
     29
     30        """
     31        from sage.combinat.all import CartanType
     32        ct = CartanType(cartan_type)
     33        return super(CoxeterGroup, cls).__classcall__(cls, ct, *args, **options)
     34
     35    def __init__(self, cartan_type):
     36        """
     37        TESTS::
     38
     39            sage: from sage.libs.coxeter3.coxeter_group import CoxeterGroup  # optional - coxeter3
     40            sage: CoxeterGroup(['A',2])                                     # optional - coxeter3
     41            Coxeter group of type ['A', 2] implemented by Coxeter3
     42            sage: TestSuite(CoxeterGroup(['A',2])).run()                    # optional - coxeter3
     43        """
     44        Parent.__init__(self, category=(FiniteCoxeterGroups() if cartan_type.is_finite() else CoxeterGroups()))
     45        self._coxgroup = get_CoxGroup(cartan_type)
     46        self._cartan_type = cartan_type
     47
     48    def _repr_(self):
     49        """
     50        EXAMPLES::
     51
     52            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3'); W      # optional - coxeter3 # indirect doctest
     53            Coxeter group of type ['A', 3] implemented by Coxeter3
     54            sage: W = CoxeterGroup(['A', 3, 1], implementation='coxeter3'); W   # optional - coxeter3
     55            Coxeter group of type ['A', 3, 1] implemented by Coxeter3
     56        """
     57        return "Coxeter group of type %s implemented by Coxeter3"%(self.cartan_type())
     58
     59    def __iter__(self):
     60        """
     61        EXAMPLES::
     62
     63            sage: W = CoxeterGroup(['A', 2], implementation='coxeter3')    # optional - coxeter3
     64            sage: list(W)                                                  # optional - coxeter3
     65            [[], [1], [2], [1, 2], [2, 1], [1, 2, 1]]
     66        """
     67        for x in self._coxgroup:
     68            yield CoxeterGroup.Element(x, self)
     69
     70    def cartan_type(self):
     71        """
     72        Return the Cartan type for this Coxeter group.
     73
     74        EXAMPLES::
     75
     76            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     77            sage: W.cartan_type()                                         # optional - coxeter3
     78            ['A', 3]
     79        """
     80        return self._cartan_type
     81
     82    def index_set(self):
     83        """
     84        Return the index set for the generators of this Coxeter group.
     85
     86        EXAMPLES::
     87
     88            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')  # optional - coxeter3
     89            sage: W.index_set()                                          # optional - coxeter3
     90            [1, 2, 3]
     91            sage: C = CoxeterGroup(['A', 3,1], implementation='coxeter3') # optional - coxeter3
     92            sage: C.index_set()                                           # optional - coxeter3
     93            [0, 1, 2, 3]
     94        """
     95        return self.cartan_type().index_set()
     96        #return range(1, self.rank()+1)
     97
     98    def bruhat_interval(self, u, v):
     99        """
     100        Return the Bruhat interval between ``u`` and ``v``.
     101
     102        EXAMPLES::
     103
     104            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')    # optional - coxeter3
     105            sage: W.bruhat_interval([1],[3,1,2,3])                         # optional - coxeter3
     106            [[1], [1, 2], [1, 3], [1, 2, 3], [1, 3, 2], [1, 2, 3, 2]]
     107        """
     108        u, v = self(u), self(v)
     109        return self._coxgroup.bruhat_interval(u.value, v.value)
     110
     111    def cardinality(self):
     112        """
     113        Return the cardinality of this Coxeter group.
     114
     115        EXAMPLES::
     116
     117            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')    # optional - coxeter3
     118            sage: W.cardinality()                                          # optional - coxeter3
     119            24
     120        """
     121        return self._coxgroup.order()
     122
     123    def one(self):
     124        """
     125        Return the identity element of this Coxeter group.
     126
     127        EXAMPLES::
     128
     129            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     130            sage: W.one()                                                 # optional - coxeter3
     131            []
     132
     133        """
     134        return self([])
     135
     136    def simple_reflections(self):
     137        """
     138        Return the family of generators for this Coxeter group.
     139
     140        EXAMPLES::
     141
     142            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     143            sage: s = W.simple_reflections()                                            # optional - coxeter3
     144            sage: s[2]*s[1]*s[2]                                          # optional - coxeter3
     145            [2, 1, 2]
     146        """
     147        from sage.combinat.family import Family
     148        return Family(self.index_set(), lambda i: self([i]))
     149
     150    gens = simple_reflections
     151
     152    def rank(self):
     153        """
     154        Return the rank of this coxeter group, that is, the number of generators.
     155
     156        EXAMPLES::
     157
     158            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     159            sage: W.rank()                                                # optional - coxeter3
     160            3
     161        """
     162        return self._coxgroup.rank()
     163
     164    def is_finite(self):
     165        """
     166        Return True if this is a finite Coxeter group.
     167
     168        EXAMPLES::
     169
     170            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     171            sage: W.is_finite()                                           # optional - coxeter3
     172            True
     173        """
     174        return self._coxgroup.is_finite()
     175
     176    def length(self, x):
     177        """
     178        Return the length of an element ``x`` in this Coxeter group.
     179        This is just the length of a reduced word for ``x``.
     180
     181        EXAMPLES::
     182
     183            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     184            sage: W.length(W([1,2]))                                      # optional - coxeter3
     185            2
     186            sage: W.length(W([1,1]))                                      # optional - coxeter3
     187            0
     188
     189        """
     190        return len(x.value)
     191
     192    @cached_method
     193    def coxeter_matrix(self):
     194        """
     195        Return the Coxeter matrix for this Coxeter group.
     196
     197        The columns and rows are ordered according to the result of
     198        :meth:`index_set`.
     199
     200        EXAMPLES::
     201
     202            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')    # optional - coxeter3
     203            sage: W.coxeter_matrix()                                       # optional - coxeter3
     204            [1 3 2]
     205            [3 1 3]
     206            [2 3 1]
     207
     208        """
     209        return self._coxgroup.coxeter_matrix()
     210
     211    def root_system(self):
     212        """
     213        Return the root system associated with this Coxeter group.
     214
     215        EXAMPLES::
     216
     217            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     218            sage: R = W.root_system(); R                                  # optional - coxeter3
     219            Root system of type ['A', 3]
     220            sage: alpha = R.root_space().basis()                          # optional - coxeter3
     221            sage: alpha[2] + alpha[3]                                     # optional - coxeter3
     222            alpha[2] + alpha[3]
     223        """
     224        return self.cartan_type().root_system()
     225
     226    def _an_element_(self):
     227        """
     228        Return an element of this Coxeter group.
     229
     230        EXAMPLES::
     231
     232            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     233            sage: W._an_element_()                                        # optional - coxeter3
     234            []
     235
     236        """
     237        return self([])
     238
     239    def m(self, i, j):
     240        """
     241        Return the entry in the Coxeter matrix between the generator
     242        with label ``i`` and the generator with label ``j``.
     243
     244        EXAMPLES::
     245
     246            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     247            sage: W.m(1,1)                                                # optional - coxeter3
     248            1
     249            sage: W.m(1,0)                                                # optional - coxeter3
     250            2
     251        """
     252        return self.coxeter_matrix()[i-1,j-1]
     253
     254    def kazhdan_lusztig_polynomial(self, u, v, constant_term_one=True):
     255        r"""
     256        Return the Kazhdan-Lusztig polynomial `P_{u,v}`.
     257
     258        INPUT:
     259
     260        - ``u``, ``v`` -- elements of the underlying Coxeter group
     261        - ``constant_term_one`` -- (default: True) True uses the constant equals one convention,
     262           False uses the Leclerc-Thibon convention
     263
     264        .. SEEALSO::
     265
     266            - :class:`~sage.combinat.kazhdan_lusztig.KazhdanLusztigPolynomial`
     267            - :meth:`parabolic_kazhdan_lusztig_polynomial`
     268
     269        EXAMPLES::
     270
     271            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     272            sage: W.kazhdan_lusztig_polynomial([], [1,2, 1])              # optional - coxeter3
     273            1
     274            sage: W.kazhdan_lusztig_polynomial([1],[3,2])                 # optional - coxeter3
     275            0
     276            sage: W = CoxeterGroup(['A',3],implementation='coxeter3')     # optional - coxeter3
     277            sage: W.kazhdan_lusztig_polynomial([2],[2,1,3,2])             # optional - coxeter3
     278            q + 1
     279
     280        .. NOTE::
     281
     282            Coxeter3, as well as Sage's native implementation in
     283            :class:`~sage.combinat.kazhdan_lusztig.KazhdanLusztigPolynomial`
     284            use the convention under which Kazhdan-Lusztig
     285            polynomials give the change of basis from the `(C_w)_{w\in W}`
     286            basis to the `(T_w)_{w\in W}` of the Hecke algebra of `W` with
     287            parameters `q` and `q^{-1}`:
     288
     289                .. MATH:: C_w = \sum_u  P_{u,w} T_w
     290
     291            In particular, `P_{u,u}=1`::
     292
     293                sage: all(W.kazhdan_lusztig_polynomial(u,u) == 1 for u in W) # optional - coxeter3
     294                True
     295
     296            This convention differs from Theorem 2.7 in [LeclercThibon1998]_ by:
     297
     298            .. MATH::
     299
     300                {}^{LT} P_{y,w}(q) = q^{\ell(w)-\ell(y)} P_{y,w}(q^{-2})
     301
     302            To access the Leclerc-Thibon convention use::
     303
     304                sage: W = CoxeterGroup(['A',3],implementation='coxeter3')                         # optional - coxeter3
     305                sage: W.kazhdan_lusztig_polynomial([2],[2,1,3,2],constant_term_one=False)         # optional - coxeter3
     306                q^3 + q
     307
     308        TESTS:
     309
     310         We check that Coxeter3 and Sage's implementation give the same results::
     311
     312            sage: C = CoxeterGroup(['B', 3], implementation='coxeter3')                           # optional - coxeter3
     313            sage: W = WeylGroup("B3",prefix="s")
     314            sage: [s1,s2,s3]=W.simple_reflections()
     315            sage: R.<q>=LaurentPolynomialRing(QQ)
     316            sage: KL=KazhdanLusztigPolynomial(W,q)
     317            sage: all(KL.P(1,w) == C.kazhdan_lusztig_polynomial([],w.reduced_word()) for w in W)  # optional - coxeter3  # long (15s)
     318            True
     319        """
     320        u, v = self(u), self(v)
     321        p = u.value.kazhdan_lusztig_polynomial(v.value)
     322        if constant_term_one:
     323            return u.value.kazhdan_lusztig_polynomial(v.value)
     324        q = p.parent().gen()
     325        return q**(v.length()-u.length())*p.substitute(q=q**(-2))
     326
     327    def parabolic_kazhdan_lusztig_polynomial(self, u, v, J, constant_term_one=True):
     328        """
     329        Return the parabolic Kazhdan-Lusztig polynomial `P_{u,v}^{-,J}`.
     330
     331        INPUT:
     332
     333        - ``u``, ``v`` -- minimal length coset representatives of `W/W_J` for this Coxeter group `W`
     334        - ``J`` -- a subset of the index set of ``self`` specifying the parabolic subgroup
     335
     336        This method implements the parabolic Kazhdan-Lusztig polynomials
     337        `P^{-,J}_{u,v}` of [Deodhar1987]_, which are defined as
     338        `P^{-,J}_{u,v} = \sum_{z\in W_J} (-1)^{\ell(z)} P_{yz,w}(q)`
     339        with the conventions in Sage.
     340        As for :meth:`kazhdan_lusztig_polynomial` the convention
     341        differs from Theorem 2.7 in [LeclercThibon1998]_ by:
     342
     343        .. MATH::
     344
     345            {}^{LT} P_{y,w}^{-,J}(q) = q^{\ell(w)-\ell(y)} P_{y,w}^{-,J}(q^{-2})
     346
     347        REFERENCES:
     348
     349            .. [Deodhar1987] V.V. Deodhar, On some geometric aspects of Bruhat orderings II. The parabolic analogue of Kazhdan-Lusztig polynomials, J. Alg. 111 (1987) 483-506.
     350
     351            .. [LeclercThibon1998] B. Leclerc, J.-Y. Thibon, Littlewood-Richardson coefficients and Kazhdan-Lusztig polynomials, http://front.math.ucdavis.edu/9809.5122
     352
     353        EXAMPLES::
     354
     355            sage: W = CoxeterGroup(['A',3], implementation='coxeter3')                      # optional - coxeter3
     356            sage: W.parabolic_kazhdan_lusztig_polynomial([],[3,2],[1,3])                    # optional - coxeter3
     357            0
     358            sage: W.parabolic_kazhdan_lusztig_polynomial([2],[2,1,3,2],[1,3])               # optional - coxeter3
     359            q
     360
     361            sage: C = CoxeterGroup(['A',3,1], implementation='coxeter3')                    # optional - coxeter3
     362            sage: C.parabolic_kazhdan_lusztig_polynomial([],[1],[0])                        # optional - coxeter3
     363            1
     364            sage: C.parabolic_kazhdan_lusztig_polynomial([],[1,2,1],[0])                    # optional - coxeter3
     365            1
     366            sage: C.parabolic_kazhdan_lusztig_polynomial([],[0,1,0,1,2,1],[0])              # optional - coxeter3
     367            q
     368            sage: w=[1, 2, 1, 3, 0, 2, 1, 0, 3, 0, 2]
     369            sage: v=[1, 2, 1, 3, 0, 1, 2, 1, 0, 3, 0, 2, 1, 0, 3, 0, 2]
     370            sage: C.parabolic_kazhdan_lusztig_polynomial(w,v,[1,3])                         # optional - coxeter3
     371            q^2 + q
     372            sage: C.parabolic_kazhdan_lusztig_polynomial(w,v,[1,3],constant_term_one=False) # optional - coxeter3
     373            q^4 + q^2
     374
     375        TESTS::
     376
     377            sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')                     # optional - coxeter3
     378            sage: type(W.parabolic_kazhdan_lusztig_polynomial([2],[],[1]))                  # optional - coxeter3
     379            <type 'sage.rings.polynomial.polynomial_integer_dense_flint.Polynomial_integer_dense_flint'>
     380        """
     381        from sage.rings.all import ZZ
     382        u = self(u)
     383        v = self(v)
     384        if any(d in J for d in u.descents()) or any(d in J for d in v.descents()):
     385            raise ValueError, "u and v have to be minimal coset representatives"
     386        P = ZZ['q']
     387        q = P.gen()
     388        subgroup = [ z for z in self.weak_order_ideal(lambda x: set(x.descents()).issubset(set(J))) if (u*z).bruhat_le(v) ]
     389        if constant_term_one:
     390            return P.sum((-1)**(z.length())*self.kazhdan_lusztig_polynomial(u*z,v) for z in subgroup)
     391        return P.sum((-q)**(z.length())*self.kazhdan_lusztig_polynomial(u*z,v, constant_term_one=False) for z in subgroup)
     392
     393
     394    class Element(ElementWrapper):
     395        wrapped_class = CoxGroupElement
     396
     397        def __init__(self, x, parent):
     398            """
     399            TESTS::
     400
     401                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')    # optional - coxeter3
     402                sage: W([2,1,2])                                               # optional - coxeter3
     403                [1, 2, 1]
     404            """
     405            if not isinstance(x, CoxGroupElement):
     406                x = CoxGroupElement(parent._coxgroup, x).reduced()
     407            ElementWrapper.__init__(self, x, parent)
     408
     409        def _repr_(self):
     410            """
     411            TESTS::
     412
     413                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     414                sage: W([1,2,1])              # indirect doctest              # optional - coxeter3
     415                [1, 2, 1]
     416            """
     417            return repr(self.value)
     418
     419        def __iter__(self):
     420            """
     421            Return an iterator for the elements in the reduced word.
     422
     423            EXAMPLES::
     424
     425                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     426                sage: w = W([1,2,1])                                          # optional - coxeter3
     427                sage: list(iter(w))                                           # optional - coxeter3
     428                [1, 2, 1]
     429            """
     430            return iter(self.value)
     431
     432        def coatoms(self):
     433            """
     434            Return the coatoms (or co-covers) of this element in the Bruhat order.
     435
     436            EXAMPLES::
     437
     438                sage: W = CoxeterGroup(['B', 3], implementation='coxeter3')  # optional - coxeter3
     439                sage: w = W([1,2,3])                                         # optional - coxeter3
     440                sage: w.coatoms()                                            # optional - coxeter3
     441                [[2, 3], [1, 3], [1, 2]]
     442            """
     443            W = self.parent()
     444            return [W(w) for w in self.value.coatoms()]
     445
     446        def __cmp__(self, other):
     447            """
     448            Return lexicographic comparison of ``self`` and ``other``.
     449
     450            EXAMPLES::
     451
     452                sage: W = CoxeterGroup(['B', 3], implementation='coxeter3')   # optional - coxeter3
     453                sage: w = W([1,2,3])                                          # optional - coxeter3
     454                sage: v = W([3,1,2])                                          # optional - coxeter3
     455                sage: w.__cmp__(v)                                            # optional - coxeter3
     456                -1
     457                sage: v.__cmp__(w)                                            # optional - coxeter3
     458                1
     459            """
     460            if type(self) is not type(other):
     461                return cmp(type(self), type(other))
     462            return cmp(list(self), list(other))
     463
     464        def reduced_word(self):
     465            """
     466            Return the reduced word of ``self``.
     467
     468            EXAMPLES::
     469
     470                sage: W = CoxeterGroup(['B', 3], implementation='coxeter3')  # optional - coxeter3
     471                sage: w = W([1,2,3])                                         # optional - coxeter3
     472                sage: w.reduced_word()                                       # optional - coxeter3
     473                [1, 2, 3]
     474            """
     475            return list(self)
     476
     477        def __invert__(self):
     478            """
     479            Return the inverse of this Coxeter group element.
     480
     481            EXAMPLES::
     482
     483                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     484                sage: w = W([1,2,3])                                          # optional - coxeter3
     485                sage: ~w                                                      # optional - coxeter3
     486                [3, 2, 1]
     487            """
     488            return self.parent()(~self.value)
     489
     490        inverse = __invert__
     491
     492        def __getitem__(self, i):
     493            """
     494            EXAMPLES::
     495
     496                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     497                sage: w0 = W([1,2,1])                                         # optional - coxeter3
     498                sage: w0[0]                                                   # optional - coxeter3
     499                1
     500                sage: w0[1]                                                   # optional - coxeter3
     501                2
     502
     503            """
     504            if i >= len(self):
     505                raise IndexError
     506            return self.value[i]
     507
     508        def _mul_(self, y):
     509            """
     510            EXAMPLES::
     511
     512                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     513                sage: s = W.gens()                                            # optional - coxeter3
     514                sage: s[1]._mul_(s[1])                                        # optional - coxeter3
     515                []
     516                sage: s[1]*s[2]*s[1]                                          # optional - coxeter3
     517                [1, 2, 1]
     518            """
     519            result = self.value * y.value
     520            return self.parent()(result)
     521
     522        def __eq__(self, y):
     523            """
     524            Return whether this Coxeter group element is equal to ``y``.
     525
     526            This is computed by computing the normal form of both elements.
     527
     528            EXAMPLES::
     529
     530                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')    # optional - coxeter3
     531                sage: W([1,2,1]) == W([2,1,2])                                 # optional - coxeter3
     532                True
     533                sage: W([1,2,1]) == W([2,1])                                   # optional - coxeter3
     534                False
     535
     536            """
     537            if not isinstance(y, self.parent().element_class):
     538                return False
     539
     540            return list(self) == list(y)
     541
     542        def __len__(self):
     543            """
     544            EXAMPLES::
     545
     546                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')    # optional - coxeter3
     547                sage: len(W([1,2,1]))                                          # optional - coxeter3
     548                3
     549            """
     550            return self.parent().length(self)
     551
     552
     553        def bruhat_le(self, v):
     554            """
     555            Return whether ``self`` `\le` ``v`` in Bruhat order.
     556
     557            EXAMPLES::
     558
     559                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     560                sage: W([]).bruhat_le([1,2,1])                                # optional - coxeter3
     561                True
     562            """
     563            v = self.parent()(v)
     564            return self.value.bruhat_le(v.value)
     565
     566        def poincare_polynomial(self):
     567            """
     568            Return the Poincare polynomial associated with this element.
     569
     570            EXAMPLES::
     571
     572                sage: W = CoxeterGroup(['A', 2], implementation='coxeter3')      # optional - coxeter3
     573                sage: W.long_element().poincare_polynomial()                     # optional - coxeter3
     574                t^3 + 2*t^2 + 2*t + 1
     575                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')      # optional - coxeter3
     576                sage: W([2,1,3,2]).poincare_polynomial()                         # optional - coxeter3
     577                t^4 + 4*t^3 + 5*t^2 + 3*t + 1
     578                sage: W([1,2,3,2,1]).poincare_polynomial()                       # optional - coxeter3
     579                t^5 + 4*t^4 + 6*t^3 + 5*t^2 + 3*t + 1
     580
     581                sage: rw = sage.combinat.permutation.from_reduced_word           # optional - coxeter3
     582                sage: p = map(attrcall('poincare_polynomial'), W)                # optional - coxeter3
     583                sage: [rw(w.reduced_word()) for i,w in enumerate(W) if p[i] != p[i].reverse()] # optional - coxeter3
     584                [[3, 4, 1, 2], [4, 2, 3, 1]]
     585            """
     586            return self.value.poincare_polynomial()
     587
     588        def has_right_descent(self, i):
     589            """
     590            Return whether ``i`` is a right descent of this element.
     591
     592            EXAMPLES::
     593
     594                sage: W = CoxeterGroup(['A', 4], implementation='coxeter3')   # optional - coxeter3
     595                sage: W([1,2]).has_right_descent(1)                           # optional - coxeter3
     596                False
     597                sage: W([1,2]).has_right_descent(2)                           # optional - coxeter3
     598                True
     599            """
     600            return i in self.value.right_descents()
     601
     602        def has_left_descent(self, i):
     603            """
     604            Return True if ``i`` is a left descent of this element.
     605
     606            EXAMPLES::
     607
     608                sage: W = CoxeterGroup(['A', 4], implementation='coxeter3')   # optional - coxeter3
     609                sage: W([1,2]).has_left_descent(1)                            # optional - coxeter3
     610                True
     611                sage: W([1,2]).has_left_descent(2)                            # optional - coxeter3
     612                False
     613            """
     614            return i in self.value.left_descents()
     615
     616        def action(self, v):
     617            """
     618            Return the action of of this Coxeter group element on the root space.
     619
     620            INPUT:
     621
     622            - ``v`` -- an element of the root space associated with the Coxeter group for ``self``
     623
     624            EXAMPLES::
     625
     626                sage: W = CoxeterGroup(['B', 3], implementation='coxeter3')   # optional - coxeter3
     627                sage: R = W.root_system().root_space()                        # optional - coxeter3
     628                sage: v = R.an_element(); v                                   # optional - coxeter3
     629                2*alpha[1] + 2*alpha[2] + 3*alpha[3]
     630                sage: w = W([1,2,3])                                          # optional - coxeter3
     631                sage: w.action(v)                                             # optional - coxeter3
     632                -alpha[1] + alpha[2] + alpha[3]
     633            """
     634            #TODO: Find a better way to do this
     635            W = self.parent().root_system().root_space().weyl_group()
     636            w = W.from_reduced_word(list(self))
     637            return w.action(v)
     638
     639        def action_on_rational_function(self, f):
     640            r"""
     641            Return the natural action of this Coxeter group element on a
     642            polynomial considered as an element of `S(\mathfrak{h}^*)`.
     643
     644            .. NOTE::
     645
     646               Note that the number of variables in the polynomial
     647               ring must correspond to the rank of this Coxeter
     648               group. The ordering of the variables is assumed to
     649               coincide with the result of :meth:`index_set`.
     650
     651            EXAMPLES::
     652
     653                sage: W = CoxeterGroup(['A', 3], implementation='coxeter3')   # optional - coxeter3
     654                sage: S = PolynomialRing(QQ, 'x,y,z').fraction_field()        # optional - coxeter3
     655                sage: x,y,z = S.gens()                                        # optional - coxeter3
     656                sage: W([1]).action_on_rational_function(x+y+z)               # optional - coxeter3
     657                (x^2*y + x*z + 1)/x
     658                sage: W([2]).action_on_rational_function(x+y+z)               # optional - coxeter3
     659                (x*y^2 + y^2*z + 1)/y
     660                sage: W([3]).action_on_rational_function(x+y+z)               # optional - coxeter3
     661                (y*z^2 + x*z + 1)/z
     662            """
     663            Q = f.parent()
     664            Q_gens = Q.gens()
     665            W = self.parent()
     666            R = W.root_system().root_space()
     667            alpha = R.basis()
     668            n = W.rank()
     669
     670            if Q.ngens() != n:
     671                raise ValueError, "the number of generators for the polynomial ring must be the same as the rank of the root system"
     672
     673            basis_elements = [alpha[i] for i in W.index_set()]
     674            basis_to_order = dict([(s, i) for i, s in enumerate(W.index_set())])
     675
     676            results = []
     677            for poly in [f.numerator(), f.denominator()]:
     678                result = 0
     679                exponents = poly.exponents()
     680
     681                for exponent in exponents:
     682                    #Construct something in the root lattice from the exponent vector
     683                    exponent = sum([e*b for e, b in zip(exponent, basis_elements)])
     684                    exponent = self.action(exponent)
     685
     686                    monomial = 1
     687                    for s, c in exponent.monomial_coefficients().iteritems():
     688                        monomial *= Q_gens[basis_to_order[s]]**int(c)
     689
     690                    result += monomial
     691
     692                results.append(result)
     693
     694            numerator, denominator = results
     695            return numerator / denominator
  • new file sage/libs/coxeter3/decl.pxi

    diff --git a/sage/libs/coxeter3/decl.pxi b/sage/libs/coxeter3/decl.pxi
    new file mode 100644
    - +  
     1#*****************************************************************************
     2#       Copyright (C) 2009-2013 Mike Hansen <mhansen@gmail.com>
     3#
     4#  Distributed under the terms of the GNU General Public License (GPL)
     5#                  http://www.gnu.org/licenses/
     6#*****************************************************************************
     7
     8include "../../ext/stdsage.pxi"
     9include "../../ext/cdefs.pxi"
     10
     11cdef extern from "ccobject.h":
     12    #We do this to get access to Construct_p, etc.
     13    pass
     14
     15cdef extern from "globals.h":
     16    ctypedef unsigned long Ulong
     17
     18#cdef extern from "klsupport.h":
     19#ctypedef unsigned short KLCoeff
     20
     21########
     22# Bits #
     23########
     24cdef extern from "bits.h":
     25    ctypedef Ulong LFlags
     26
     27cdef extern from "coxtypes.h":
     28    ctypedef unsigned short Rank
     29    ctypedef Ulong CoxSize         # should hold at least 32 bits */
     30    ctypedef Ulong BettiNbr        # should hold at least 32 bits */
     31    ctypedef unsigned CoxNbr         # should fit into a CoxSize */
     32    ctypedef CoxNbr ParSize          # this should not be changed */
     33    ctypedef unsigned short ParNbr   # should fit into a CoxNbr */
     34    ctypedef ParNbr *CoxArr
     35    ctypedef unsigned char CoxLetter # for string representations */
     36    ctypedef CoxLetter Generator     # internal representation of generators*/
     37    ctypedef unsigned short Length
     38    ctypedef Ulong StarOp          # for numbering star operations */
     39
     40
     41    #################
     42    #    CoxWord    #
     43    #################
     44    ctypedef struct c_CoxWord "coxtypes::CoxWord":
     45        CoxLetter get_index "operator[]"(Length j)
     46        Length length()
     47        void setLength(Length n)
     48        c_CoxWord append_letter "append" (CoxLetter a)
     49        c_CoxWord reset()
     50        c_CoxWord set "operator="(c_CoxWord w)
     51
     52    void CoxWord_destruct "Destruct<coxtypes::CoxWord>"(c_CoxWord *mem)
     53    c_CoxWord* CoxWord_construct "Construct<coxtypes::CoxWord>" (void *mem)
     54
     55
     56################
     57#    String    #
     58################
     59cdef extern from "io.h":
     60    ctypedef struct c_String "io::String":
     61        void setLength(Ulong n)
     62        Ulong length()
     63        char* ptr()
     64        void setData(char* source, Ulong r)
     65
     66    c_String* String_new "New<io::String>"()
     67    c_String* String_construct_str "Construct_p<io::String, char*>"(void *mem, char* s)
     68    void String_destruct "Destruct<io::String>"(c_String *mem)
     69
     70
     71##############
     72#    Type    #
     73##############
     74cdef extern from "type.h":
     75    ctypedef struct c_Type "type::Type":
     76        c_String name()
     77    void Type_destruct "Destruct<type::Type>"(c_Type *mem)
     78    c_Type* Type_construct "Construct_p<type::Type, char*>" (void *mem, char* s)
     79    c_Type* Type_construct_str "Construct_p<type::Type, char*>" (void *mem, char* s)
     80
     81##############
     82#    Bits    #
     83##############
     84cdef extern from "bits.h":
     85    Generator firstBit "bits::firstBit"(Ulong n)
     86
     87##################
     88#    CoxGraph    #
     89##################
     90cdef extern from "graph.h":
     91    ctypedef unsigned short CoxEntry
     92    ctypedef struct c_CoxGraph "graph::CoxGraph":
     93        pass
     94
     95###############
     96#    KLPol    #
     97###############
     98cdef extern from "kl.h":
     99    ctypedef struct c_KLPol "kl::KLPol":
     100        pass
     101
     102cdef extern from "polynomials.h":
     103    c_String klpoly_append "polynomials::append"(c_String str, c_KLPol, char* x)
     104
     105##################
     106#    List    #
     107##################
     108cdef extern from "list.h":
     109    ctypedef struct c_List_CoxWord "list::List<coxtypes::CoxWord>":
     110        c_CoxWord get_index "operator[]"(Length j)
     111        Ulong size()
     112    c_List_CoxWord  c_List_CoxWord_factory "list::List<coxtypes::CoxWord>"(Ulong len)
     113    void List_CoxWord_destruct "Destruct< list::List<coxtypes::CoxWord> >"(c_List_CoxWord *mem)
     114
     115
     116###################
     117#     CoxGroup    #
     118###################
     119cdef extern from "coxgroup.h":
     120    ctypedef struct c_CoxGroup "coxgroup::CoxGroup":
     121        Rank rank()
     122        c_Type type()
     123        CoxSize order()
     124        c_CoxWord reduced(c_CoxWord res, c_CoxWord w)
     125        c_CoxWord normalForm(c_CoxWord w)
     126        c_CoxWord prod(c_CoxWord g, c_CoxWord h)
     127        int prod_nbr "prod"(c_CoxWord g, CoxNbr x)
     128
     129        c_CoxGraph graph()
     130        CoxEntry M(Generator s, Generator t)
     131        CoxNbr extendContext(c_CoxWord w)
     132        c_KLPol klPol(CoxNbr x, CoxNbr y)
     133        bint inOrder_word "inOrder"(c_CoxWord u, c_CoxWord w)
     134        bint inOrder_nbr "inOrder"(CoxNbr x, CoxNbr y)
     135
     136        LFlags descent(c_CoxWord w)
     137        LFlags ldescent(c_CoxWord w)
     138        LFlags rdescent(c_CoxWord w)
     139        bint isDescent(c_CoxWord w, Generator s)
     140
     141        void coatoms(c_List_CoxWord, c_CoxWord u)
     142
     143        unsigned short mu(CoxNbr x, CoxNbr y) #KLCoeff
     144
     145    c_CoxGroup* CoxGroup_construct_type_rank "Construct_pp<coxgroup::CoxGroup, type::Type, Rank>" (void *mem, c_Type t, Rank r)
     146    void CoxGroup_delete "Delete<coxgroup::CoxGroup>"(c_CoxGroup *mem)
     147
     148
     149#####################
     150#    Interactive    #
     151#####################
     152cdef extern from "interactive.h":
     153    c_CoxGroup* coxeterGroup "interactive::coxeterGroup"(c_Type x, Rank l)
     154
     155cdef extern from "constants.h":
     156    void initConstants()
     157
     158###############################
     159#    Finite Coxeter groups    #
     160###############################
     161cdef extern from "fcoxgroup.h":
     162    ctypedef struct c_FiniteCoxGroup "fcoxgroup::FiniteCoxGroup":
     163        void fullContext()
     164        bint isFullContext()
     165        Length maxLength()
     166        c_CoxWord longest_coxword()
     167
     168    bint isFiniteType "fcoxgroup::isFiniteType"(c_CoxGroup *W)
     169
     170
     171######################
     172#    Sage specific   #
     173######################
     174cdef extern from "sage.h":
     175    void interval "sage::interval"(c_List_CoxWord, c_CoxGroup W, c_CoxWord g, c_CoxWord h)
  • setup.py

    diff --git a/setup.py b/setup.py
    a b code = setup(name = 'sage', 
    944944                     'sage.libs.singular',
    945945                     'sage.libs.symmetrica',
    946946                     'sage.libs.cremona',
     947                     'sage.libs.coxeter3',
    947948                     'sage.libs.mpmath',
    948949                     'sage.libs.lcalc',
    949950