Ticket #3664: trac_3664-1.patch

File trac_3664-1.patch, 205.7 KB (added by mhansen, 6 years ago)
  • sage/combinat/crystals/crystals.py

    # HG changeset patch
    # User Nicolas M. Thiery <nthiery@users.sf.net>
    # Date 1218050423 18000
    # Node ID db34e50d9e6c422bbec0f0f666e101d6c0e777b5
    # Parent  29be632ff7bcefcb1b56903c58c550391c41dd6f
    Improvements / refactoring of root system code.
    
    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/crystals/crystals.py
    a b  
    145145        EXAMPLES: 
    146146            sage: C = CrystalOfLetters(['A', 5]) 
    147147            sage: C.weight_lattice_realization() 
    148             Ambient lattice of the root system of type ['A', 5] 
     148            Ambient space for the Root system of type ['A', 5] 
    149149        """ 
    150         return self.cartan_type.root_system().ambient_lattice() 
     150        return self.cartan_type.root_system().ambient_space() 
    151151 
    152152    def Lambda(self): 
    153153        """ 
  • sage/combinat/root_system/all.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/all.py
    a b  
    11from cartan_type import CartanType 
    2 from dynkin_diagram import dynkin_diagram 
     2from dynkin_diagram import DynkinDiagram, dynkin_diagram 
    33from cartan_matrix import cartan_matrix 
    44from coxeter_matrix import coxeter_matrix 
    55from root_system import RootSystem, WeylDim 
  • new file sage/combinat/root_system/ambient_space.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/ambient_space.py
    - +  
     1from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement 
     2from root_lattice_realization import RootLatticeRealizationElement 
     3from weight_lattice_realization import WeightLatticeRealization 
     4from sage.modules.free_module import FreeModule 
     5from sage.rings.all import ZZ, QQ 
     6from sage.modules.free_module_element import vector 
     7 
     8class AmbientSpace(CombinatorialFreeModule, WeightLatticeRealization): 
     9    r""" 
     10    Abstract class for ambient spaces 
     11 
     12    Any implementation of this class should implement a class method 
     13    smallest_base_ring as described below, and a method dimension 
     14    working on a partially initialized instance with just root_system 
     15    as attribute. There is no safe default implementation for the later, 
     16    so none is provided. 
     17    """ 
     18 
     19    # FIXME: attribute or method? 
     20    def dimension(self): 
     21        """ 
     22        Returns the dimension of this ambient space 
     23        """ 
     24        raise NotImplementedError 
     25     
     26    @classmethod 
     27    def smallest_base_ring(cls): 
     28        """ 
     29        Returns the smallest ground ring over which the ambient space can be realized 
     30        """ 
     31        return QQ; 
     32 
     33    def __init__(self, root_system, base_ring): 
     34        """ 
     35        EXAMPLES: 
     36            sage: e = RootSystem(['A',3]).ambient_lattice() 
     37            sage: e == loads(dumps(e)) 
     38            True 
     39        """ 
     40        self.root_system = root_system 
     41        basis_name = "alphacheck" if root_system.dualSide else "alpha" 
     42        CombinatorialFreeModule.__init__(self, base_ring,\ 
     43                                         #range(1,self.dimension()+1),\ 
     44                                         range(0,self.dimension()),\ 
     45                                         element_class = AmbientSpaceElement,\ 
     46                                         prefix='e') 
     47 
     48        # FIXME: here for backward compatibility; 
     49        # Should we use dimension everywhere? 
     50        self.n = self.dimension() 
     51 
     52    def __repr__(self): 
     53        """ 
     54        TEST: 
     55            sage: RootSystem(['A',4]).ambient_lattice() 
     56            Ambient lattice for the Root system of type ['A', 4] 
     57            sage: RootSystem(['B',4]).ambient_space() 
     58            Ambient space for the Root system of type ['B', 4] 
     59 
     60        """ 
     61        if self.base_ring() == ZZ: 
     62            space = "lattice" 
     63        else: 
     64            space = "space" 
     65        return "Ambient "+space+" for the %s"%self.root_system 
     66 
     67    def __call__(self, v): 
     68        """ 
     69        TESTS: 
     70            sage: R = RootSystem(['A',4]).ambient_lattice() 
     71            sage: R([1,2,3,4,5]) 
     72            (1, 2, 3, 4, 5) 
     73        """ 
     74        # This adds coercion from a list 
     75        if isinstance(v, list) or isinstance(v, tuple): 
     76            K = self.base_ring() 
     77            return self._from_dict(dict([(i,K(v[i])) for i in range(len(v))])) 
     78        else: 
     79            return CombinatorialFreeModule.__call__(self, v) 
     80 
     81    # For backward compatibility 
     82    def _term(self, i): 
     83        self.term(i) 
     84 
     85    def __getitem__(self,i): 
     86        """ 
     87        Note that indexing starts at 1. 
     88         
     89        EXAMPLES: 
     90            sage: e = RootSystem(['A',2]).ambient_lattice() 
     91            sage: e[1] 
     92            (1, 0, 0) 
     93        """ 
     94        return self.term(i-1) 
     95 
     96    def coroot_lattice(self): 
     97        return self 
     98 
     99    def simple_coroot(self, i): 
     100        r""" 
     101        Returns the i-th simple coroot, as an element of this space 
     102 
     103        EXAMPLE: 
     104        sage: R = RootSystem(["A",3]) 
     105        sage: L = R.ambient_lattice () 
     106        sage: L.simple_coroot(1) 
     107        (1, -1, 0, 0) 
     108        sage: L.simple_coroot(2) 
     109        (0, 1, -1, 0) 
     110        sage: L.simple_coroot(3) 
     111        (0, 0, 1, -1) 
     112        """         
     113        return self.simple_root(i).associated_coroot() 
     114 
     115    def reflection(self, root, coroot=None): 
     116        # TODO: get rid of this as one can use the generic implementation 
     117        # (i.e. scalar and associated coroot are implemented) 
     118        return lambda v: v-2*root.inner_product(v)/root.inner_product(root)*root 
     119 
     120    def _term(self, i): 
     121        """ 
     122        Note that indexing starts at 0. 
     123 
     124        EXAMPLES: 
     125            sage: e = RootSystem(['A',2]).ambient_lattice() 
     126            sage: e._term(0) 
     127            (1, 0, 0) 
     128        """ 
     129        return self.term(i) 
     130 
     131    def __cmp__(self, other): 
     132        """ 
     133        EXAMPLES: 
     134            sage: e1 = RootSystem(['A',3]).ambient_lattice() 
     135            sage: e2 = RootSystem(['B',3]).ambient_lattice() 
     136            sage: e1 == e1 
     137            True 
     138            sage: e1 == e2 
     139            False 
     140        """ 
     141        if self.__class__ != other.__class__: 
     142            return cmp(self.__class__, other.__class__) 
     143        if self.root_system != other.root_system: 
     144            return cmp(self.root_system, other.root_system) 
     145        return 0 
     146 
     147class AmbientSpaceElement(CombinatorialFreeModuleElement, RootLatticeRealizationElement): 
     148 
     149    # For backward compatibility 
     150    def __repr__(self): 
     151        return str(self.to_vector()) 
     152     
     153    def inner_product(self, lambdacheck): 
     154        """ 
     155        The scalar product with elements of the coroot lattice 
     156        embedded in the ambient space 
     157        """ 
     158        assert(lambdacheck.parent() == self.parent()) 
     159        return sum((c*self[t] for (t,c) in lambdacheck), 
     160                   self.parent().base_ring().zero_element()) 
     161 
     162    scalar = inner_product 
     163    dot_product = inner_product 
     164 
     165    def associated_coroot(self): 
     166        # FIXME: make it work over ZZ! 
     167        return self * (2/self.inner_product(self)) 
     168 
  • sage/combinat/root_system/cartan_matrix.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/cartan_matrix.py
    a b  
    1515# 
    1616#                  http://www.gnu.org/licenses/ 
    1717#***************************************************************************** 
    18 from dynkin_diagram import dynkin_diagram_as_function 
    1918import cartan_type  
    2019from sage.matrix.all import MatrixSpace 
    2120from sage.rings.all import ZZ 
    22  
    23 def cartan_matrix_as_function(t): 
    24     """ 
    25     Returns a function that represents the Cartan matrix 
    26     of type t. 
    27  
    28     EXAMPLES: 
    29         sage: from sage.combinat.root_system.cartan_matrix import cartan_matrix_as_function 
    30         sage: f = cartan_matrix_as_function(['A',4]) 
    31         sage: matrix([[f(i,j) for j in range(1,5)] for i in range(1,5)]) 
    32         [ 2 -1  0  0] 
    33         [-1  2 -1  0] 
    34         [ 0 -1  2 -1] 
    35         [ 0  0 -1  2]     
    36     """ 
    37     ct = cartan_type.CartanType(t)     
    38     f = dynkin_diagram_as_function(ct) 
    39     cmf = lambda i,j: 2 if i == j else -f(j,i) 
    40     return cmf 
    4121 
    4222def cartan_matrix(t): 
    4323    """ 
     
    5434        [-1  2 -1  0  0  0] 
    5535        [ 0 -1  2 -1  0  0] 
    5636        [ 0  0 -1  2 -1  0] 
    57         [ 0  0  0 -1  2 -2] 
    58         [ 0  0  0  0 -1  2] 
     37        [ 0  0  0 -1  2 -1] 
     38        [ 0  0  0  0 -2  2] 
    5939        sage: cartan_matrix(['C', 4]) 
    6040        [ 2 -1  0  0] 
    6141        [-1  2 -1  0] 
    62         [ 0 -1  2 -1] 
    63         [ 0  0 -2  2] 
     42        [ 0 -1  2 -2] 
     43        [ 0  0 -1  2] 
    6444        sage: cartan_matrix(['D', 6]) 
    6545        [ 2 -1  0  0  0  0] 
    6646        [-1  2 -1  0  0  0] 
     
    6848        [ 0  0 -1  2 -1 -1] 
    6949        [ 0  0  0 -1  2  0] 
    7050        [ 0  0  0 -1  0  2] 
     51        sage: cartan_matrix(['E',6]) 
     52        [ 2  0 -1  0  0  0] 
     53        [ 0  2  0 -1  0  0] 
     54        [-1  0  2 -1  0  0] 
     55        [ 0 -1 -1  2 -1  0] 
     56        [ 0  0  0 -1  2 -1] 
     57        [ 0  0  0  0 -1  2] 
     58        sage: cartan_matrix(['E',7]) 
     59        [ 2  0 -1  0  0  0  0] 
     60        [ 0  2  0 -1  0  0  0] 
     61        [-1  0  2 -1  0  0  0] 
     62        [ 0 -1 -1  2 -1  0  0] 
     63        [ 0  0  0 -1  2 -1  0] 
     64        [ 0  0  0  0 -1  2 -1] 
     65        [ 0  0  0  0  0 -1  2] 
    7166        sage: cartan_matrix(['E', 8]) 
    7267        [ 2  0 -1  0  0  0  0  0] 
    7368        [ 0  2  0 -1  0  0  0  0] 
     
    7974        [ 0  0  0  0  0  0 -1  2] 
    8075        sage: cartan_matrix(['F', 4]) 
    8176        [ 2 -1  0  0] 
    82         [-1  2 -2  0] 
     77        [-1  2 -1  0] 
     78        [ 0 -2  2 -1] 
     79        [ 0  0 -1  2] 
     80 
     81      This is different from MuPAD-Combinat, due to different node convention? 
     82 
     83        sage: cartan_matrix(['G', 2]) 
     84        [ 2 -3] 
     85        [-1  2] 
     86        sage: cartan_matrix(['A', 3, 1]) 
     87        [ 2 -1  0 -1] 
     88        [-1  2 -1  0] 
    8389        [ 0 -1  2 -1] 
     90        [-1  0 -1  2] 
     91        sage: cartan_matrix(['B', 3, 1]) 
     92        [ 2  0 -1  0] 
     93        [ 0  2 -1  0] 
     94        [-1 -1  2 -1] 
     95        [ 0  0 -2  2] 
     96        sage: cartan_matrix(['C', 3, 1]) 
     97        [ 2 -1  0  0] 
     98        [-2  2 -1  0] 
     99        [ 0 -1  2 -2] 
    84100        [ 0  0 -1  2] 
    85         sage: cartan_matrix(['G', 2]) 
    86         [ 2 -1] 
    87         [-3  2] 
    88  
     101        sage: cartan_matrix(['D', 4, 1]) 
     102        [ 2  0 -1  0  0] 
     103        [ 0  2 -1  0  0] 
     104        [-1 -1  2 -1 -1] 
     105        [ 0  0 -1  2  0] 
     106        [ 0  0 -1  0  2] 
     107        sage: cartan_matrix(['E', 6, 1]) 
     108        [ 2  0 -1  0  0  0  0] 
     109        [ 0  2  0 -1  0  0  0] 
     110        [-1  0  2  0 -1  0  0] 
     111        [ 0 -1  0  2 -1  0  0] 
     112        [ 0  0 -1 -1  2 -1  0] 
     113        [ 0  0  0  0 -1  2 -1] 
     114        [ 0  0  0  0  0 -1  2] 
     115        sage: cartan_matrix(['E', 7, 1]) 
     116        [ 2 -1  0  0  0  0  0  0] 
     117        [-1  2  0 -1  0  0  0  0] 
     118        [ 0  0  2  0 -1  0  0  0] 
     119        [ 0 -1  0  2 -1  0  0  0] 
     120        [ 0  0 -1 -1  2 -1  0  0] 
     121        [ 0  0  0  0 -1  2 -1  0] 
     122        [ 0  0  0  0  0 -1  2 -1] 
     123        [ 0  0  0  0  0  0 -1  2] 
     124        sage: cartan_matrix(['E', 8, 1]) 
     125        [ 2  0  0  0  0  0  0  0 -1] 
     126        [ 0  2  0 -1  0  0  0  0  0] 
     127        [ 0  0  2  0 -1  0  0  0  0] 
     128        [ 0 -1  0  2 -1  0  0  0  0] 
     129        [ 0  0 -1 -1  2 -1  0  0  0] 
     130        [ 0  0  0  0 -1  2 -1  0  0] 
     131        [ 0  0  0  0  0 -1  2 -1  0] 
     132        [ 0  0  0  0  0  0 -1  2 -1] 
     133        [-1  0  0  0  0  0  0 -1  2] 
     134        sage: cartan_matrix(['F', 4, 1]) 
     135        [ 2 -1  0  0  0] 
     136        [-1  2 -1  0  0] 
     137        [ 0 -1  2 -1  0] 
     138        [ 0  0 -2  2 -1] 
     139        [ 0  0  0 -1  2] 
     140        sage: cartan_matrix(['G', 2, 1]) 
     141        [ 2  0 -1] 
     142        [ 0  2 -3] 
     143        [-1 -1  2] 
    89144    """ 
    90     ct = cartan_type.CartanType(t) 
    91     index_set = ct.index_set() 
    92     cmf = cartan_matrix_as_function(ct) 
     145    t = cartan_type.CartanType(t) 
     146    dynkin_diagram = t.dynkin_diagram() 
     147    index_set = t.index_set() 
    93148    MS = MatrixSpace(ZZ, len(index_set), sparse=True) 
    94149    m = MS(0) 
    95150    for i in range(len(index_set)): 
    96151        for j in range(len(index_set)): 
    97             m[i,j] = cmf(index_set[i],index_set[j]) 
     152            m[i,j] = dynkin_diagram[index_set[i],index_set[j]] 
    98153    return m 
  • sage/combinat/root_system/cartan_type.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/cartan_type.py
    a b  
    1515# 
    1616#                  http://www.gnu.org/licenses/ 
    1717#***************************************************************************** 
    18 import sage.combinat.root_system.root_system as root_system 
     18#import sage.combinat.root_system.root_system as root_system 
     19from sage.combinat import root_system 
    1920from cartan_matrix import cartan_matrix 
     21from sage.rings.all import ZZ 
    2022 
    21 def CartanType(t): 
     23# TODO: 
     24# Get rid of almost all runtype type checking by extending the class hierarchy with: 
     25#  - type_relabel.CartanType (in type_relabel module, together with relabelled AmbientSpace) 
     26#  - CartanType_crystalographic 
     27#  - CartanType_simply_laced 
     28#  - type_A.CartanType (in the type_A module) 
     29#  - ... 
     30#  - CartanType_untwisted_affine 
     31#  - type_A_affine.CartanType 
     32#  - type_BC_affine.CartanType 
     33# ... 
     34# Implement the Kac conventions by relabeling/dual/... of the above 
     35# Implement coxeter diagrams for non crystalographic 
     36# Implement dual ambient space 
     37 
     38 
     39class CartanTypeFactory: 
     40    # Intention: we want simultaneously CartanType to be a factory for 
     41    # the various subtypes of CartanType_abstract, as in: 
     42    #     CartanType(["A",4,1]) 
     43    # and to behaves as a "module" for some extra utilities: 
     44    #     CartanType.samples() 
     45    # 
     46    # Implementation: CartanType is the unique instance of this class 
     47    # CartanTypeFactory. Is there a better/more standard way to do it? 
     48 
     49  def __call__(self, *args): 
    2250    """ 
    2351    Returns an object corresponding to the Cartan type t. 
     52    INPUT: 
     53       [letter, rank] 
     54    where letter is one of 'A','B','C','D','E','F','G' and rank 
     55    is the rank. An alternative string notation is allowed. 
     56    A third optional parameter is permitted for affine 
     57    types. Reducible types may be entered by giving a list of 
     58    irreducible types or by a single string  
    2459 
    2560    EXAMPLES: 
    2661        sage: CartanType(['A',4]) 
    2762        ['A', 4] 
     63        sage: CartanType("A4") 
     64        ['A', 4] 
     65        sage: CartanType(['A',2],['B',2]) 
     66        A2xB2 
     67        sage: CartanType(['A',2],['B',2]).is_reducible() 
     68        True 
     69        sage: CartanType("A2xB2") 
     70        A2xB2 
     71        sage: CartanType("A2","B2") == CartanType("A2xB2") 
     72        True 
     73        sage: CartanType(['A',4,1]) 
     74        ['A', 4, 1] 
     75        sage: CartanType(['A',4,1]).is_affine() 
     76        True 
    2877    """ 
    29     if isinstance(t, CartanType_simple): 
     78    if len(args) == 1: 
     79        t = args[0] 
     80    else: 
     81        t = args 
     82    if isinstance(t, CartanType_abstract): 
    3083        return t 
    31     else: 
    32         return CartanType_simple(t) 
    3384 
    34 class CartanType_simple: 
    35     def __init__(self, t): 
     85    if type(t)==str: 
     86        if "x" in t: 
     87            return root_system.type_reducible.CartanType([CartanType(u) for u in t.split("x")]) 
     88        else: 
     89            return CartanType([t[0], eval(t[1:])]) 
     90 
     91    t = list(t) 
     92         
     93    if type(t[0]) == str and t[1] in ZZ: 
     94        if len(t) == 2: 
     95            return CartanType_simple_finite(t) 
     96        elif len(t) == 3: 
     97            return CartanType_simple_affine(t) 
     98 
     99    return root_system.type_reducible.CartanType([ CartanType(subt) for subt in t ]) 
     100 
     101  def samples(self, finite=False, affine=False, crystalographic=False): 
     102      """ 
     103      Returns a sample of the implemented cartan types 
     104 
     105      With finite=True resp. affine=True, one can restrict to finite 
     106      resp. affine only cartan types 
     107 
     108      EXAMPLES: 
     109          sage: CartanType.samples(finite=True) 
     110          [['A', 1], ['A', 5], ['B', 5], ['C', 5], ['D', 5], ['E', 6], ['E', 7], ['E', 8], ['F', 4], ['G', 2], ['I', 5], ['H', 3], ['H', 4]] 
     111 
     112          sage: CartanType.samples(affine=True) 
     113          [['A', 1, 1], ['A', 5, 1], ['B', 5, 1], ['C', 5, 1], ['D', 5, 1], ['E', 6, 1], ['E', 7, 1], ['E', 8, 1], ['F', 4, 1], ['G', 2, 1], ['A', 2, 2], ['A', 10, 2], ['A', 9, 2], ['D', 5, 2], ['D', 4, 3], ['E', 6, 2]] 
     114 
     115          sage: CartanType.samples() 
     116          [['A', 1], ['A', 5], ['B', 5], ['C', 5], ['D', 5], ['E', 6], ['E', 7], ['E', 8], ['F', 4], ['G', 2], ['I', 5], ['H', 3], ['H', 4], ['A', 1, 1], ['A', 5, 1], ['B', 5, 1], ['C', 5, 1], ['D', 5, 1], ['E', 6, 1], ['E', 7, 1], ['E', 8, 1], ['F', 4, 1], ['G', 2, 1], ['A', 2, 2], ['A', 10, 2], ['A', 9, 2], ['D', 5, 2], ['D', 4, 3], ['E', 6, 2]] 
     117          sage: CartanType.samples(crystalographic=True) 
     118          [['A', 1], ['A', 5], ['B', 5], ['C', 5], ['D', 5], ['E', 6], ['E', 7], ['E', 8], ['F', 4], ['G', 2], ['A', 1, 1], ['A', 5, 1], ['B', 5, 1], ['C', 5, 1], ['D', 5, 1], ['E', 6, 1], ['E', 7, 1], ['E', 8, 1], ['F', 4, 1], ['G', 2, 1], ['A', 2, 2], ['A', 10, 2], ['A', 9, 2], ['D', 5, 2], ['D', 4, 3], ['E', 6, 2]] 
     119      """ 
     120      if crystalographic: 
     121          return [ t for t in CartanType.samples(finite=finite, affine=affine) if t.is_crystalographic() ] 
     122      if finite: 
     123          return([CartanType(t) for t in [["A", 1], ["A", 5], ["B", 5], ["C", 5], ["D", 5], 
     124                                          ["E", 6], ["E", 7], ["E", 8], 
     125                                          ["F", 4], 
     126                                          ["G", 2], 
     127                                          ["I", 5], 
     128                                          ["H", 3], ["H", 4]]]) 
     129      elif affine: 
     130          return([t.affine() for t in CartanType.samples(finite=True, crystalographic=True)] + 
     131                 [CartanType(t) for t in [["A", 2, 2], ["A", 10, 2], ["A", 9, 2], 
     132                                          ["D", 5, 2], 
     133                                          ["D", 4, 3], 
     134                                          ["E", 6, 2]]]); 
     135      else: 
     136          return CartanType.samples(finite=True) + CartanType.samples(affine=True) 
     137 
     138CartanType = CartanTypeFactory() 
     139 
     140class CartanType_abstract: 
     141    r""" 
     142    Abstract class for cartan types 
     143 
     144    Subclasses should implement: 
     145 
     146    type() 
     147    dynkin_diagram() 
     148    cartan_matrix() 
     149    is_finite() 
     150    is_affine() 
     151    is_irreducible() 
     152    """ 
     153 
     154    def type(self): 
     155        r""" 
     156        Returns the type of self, or None if unknown 
    36157        """ 
    37         EXAMPLES: 
    38             sage: ct = CartanType(['A',4]) 
    39             sage: ct == loads(dumps(ct)) 
    40             True 
    41         """ 
    42         self.t = t 
    43          
    44         self.letter = t[0] 
    45         self.n = t[1] 
    46  
    47         if len(t) > 2: 
    48             self.affine = t[2] 
    49         else: 
    50             self.affine = None 
    51  
    52     def __hash__(self): 
    53         """ 
    54         EXAMPLES: 
    55             sage: ct = CartanType(['A',2]) 
    56             sage: hash(ct) #random 
    57             -5684143898951441983 
    58         """ 
    59         return hash( (self.letter,self.n,self.affine) ) 
    60          
    61  
    62     def __repr__(self): 
    63         """ 
    64         TESTS: 
    65             sage: ct = CartanType(['A',3]) 
    66             sage: repr(ct) 
    67             "['A', 3]" 
    68         """ 
    69         if self.affine is None: 
    70             return "['%s', %s]"%(self.letter, self.n) 
    71         else: 
    72             return "['%s', %s, %s]"%(self.letter, self.n, self.affine) 
    73  
    74     def __getitem__(self, x): 
    75         """ 
    76         EXAMPLES: 
    77             sage: t = CartanType(['A', 3, 1]) 
    78             sage: t[0] 
    79             'A' 
    80             sage: t[1] 
    81             3 
    82             sage: t[2] 
    83             1 
    84             sage: t[3] 
    85             Traceback (most recent call last): 
    86             ... 
    87             IndexError: list index out of range 
    88         """ 
    89         return self.t[x] 
    90  
    91     def __cmp__(self, other): 
    92         """ 
    93         EXAMPLES: 
    94             sage: ct1 = CartanType(['A',4]) 
    95             sage: ct2 = CartanType(['A',4]) 
    96             sage: ct3 = CartanType(['A',5]) 
    97             sage: ct1 == ct2 
    98             True 
    99             sage: ct1 != ct3 
    100             True 
    101         """ 
    102         if other.__class__ != self.__class__: 
    103             return cmp(self.__class__, other.__class__) 
    104          
    105         if other.letter != self.letter: 
    106             return cmp(self.letter, other.letter) 
    107         if other.affine != self.affine: 
    108             return cmp(self.affine, other.affine) 
    109         if other.n != self.n: 
    110             return cmp(self.n, other.n) 
    111  
    112         return 0 
    113  
    114  
    115     def __len__(self): 
    116         """ 
    117         EXAMPLES: 
    118             sage: len(CartanType(['A',4])) 
    119             2 
    120             sage: len(CartanType(['A',4,1])) 
    121             3 
    122         """ 
    123         if self.affine: 
    124             return 3 
    125         else: 
    126             return 2 
    127  
    128     def is_finite(self): 
    129         """ 
    130         Returns True if self is finite. 
    131  
    132         EXAMPLES: 
    133             sage: CartanType(['A',4]).is_finite() 
    134             True 
    135             sage: CartanType(['A',4,1]).is_finite() 
    136             False 
    137         """ 
    138         if self.affine is not None: 
    139             return False 
    140  
    141         if self.letter in ['A', 'B', 'C', 'D', 'I']: 
    142             return True 
    143  
    144         if self.letter == 'E': 
    145             return self.n <= 8 
    146  
    147         if self.letter == 'F': 
    148             return self.n <= 4 
    149  
    150         if self.letter == 'G': 
    151             return self.n <= 2 
    152  
    153     def is_affine(self): 
    154         """ 
    155         Returns True if self is affine. 
    156          
    157         EXAMPLES: 
    158             sage: CartanType(['A', 3]).is_affine() 
    159             False 
    160             sage: CartanType(['A', 3, 1]).is_affine() 
    161             True 
    162         """ 
    163         return self.affine is not None 
    164  
     158        return None 
    165159 
    166160    def rank(self): 
    167161        """ 
     
    174168            sage: CartanType(['I', 8]).rank() 
    175169            2 
    176170        """ 
    177         if self.is_affine(): 
    178             if self.affine == 3 and self.letter == 'D': 
    179                 return self.n-1 
    180             elif self.affine == 2 and self.letter == 'A': 
    181                 ## FIXME: check in the literature what should be the 
    182                 ## appropriate definition for rank 
    183                 return int(self.n+1)/2 
    184             else: 
    185                 return self.n 
    186         else: 
    187             if self.letter == "I": 
    188                 return 2 
    189             else: 
    190                 return self.n 
     171        raise notImplementedError 
     172 
     173    def dual(self): 
     174        """ 
     175        Returns the dual cartan type, possibly just as a formal dual 
     176 
     177        EXAMPLES: 
     178            sage: CartanType(['A',3]).dual() 
     179            ['A', 3] 
     180            sage: CartanType(['D',4]).dual() 
     181            ['D', 4] 
     182            sage: CartanType(['E',8]).dual() 
     183            ['E', 8] 
     184            sage: CartanType(['B',3]).dual() 
     185            ['C', 3] 
     186            sage: CartanType(['C',2]).dual() 
     187            ['B', 2] 
     188        """ 
     189        return root_system.type_dual.CartanType(self) 
     190     
     191    def type_string(self): 
     192        r""" 
     193        Returns a string suitable for type-specific code dispatch 
     194 
     195        EXAMPLES: (TODO!) 
     196        """ 
     197        return "type_None" 
     198 
     199    def is_reducible(self): 
     200        """ 
     201        Report whether the root system is reducible (i.e. not simple), 
     202        that is whether it can be factored as a product of root 
     203        systems. 
     204         
     205        EXAMPLES: 
     206          sage: CartanType("A2xB3").is_reducible() 
     207          True 
     208          sage: CartanType(['A',2]).is_reducible() 
     209          False 
     210        """ 
     211        return not self.is_irreducible() 
     212 
     213    def is_irreducible(self): 
     214        """ 
     215        Report whether this Cartan type is irreducible (i.e. simple) 
     216         
     217        """ 
     218        raise NotImplementedError 
     219 
     220    def is_finite(self): 
     221        """ 
     222        Returns whether this Cartan type is finite. 
     223 
     224        EXAMPLES: 
     225            sage: CartanType(['A',4]).is_finite() 
     226            True 
     227            sage: CartanType(['A',4,1]).is_finite() 
     228            False 
     229        """ 
     230        raise NotImplementedError 
     231 
     232    def is_affine(self): 
     233        """ 
     234        Returns whether self is affine. 
     235         
     236        EXAMPLES: 
     237            sage: CartanType(['A', 3]).is_affine() 
     238            False 
     239            sage: CartanType(['A', 3, 1]).is_affine() 
     240            True 
     241        """ 
     242        raise NotImplementedError 
     243 
     244    def is_crystalographic(self): 
     245        """ 
     246        Returns whether this Cartan type is simple laced 
     247 
     248        EXAMPLES: 
     249            sage: [ [t, t.is_crystalographic() ] for t in CartanType.samples(finite=True) ] 
     250            [[['A', 1], True], [['A', 5], True], 
     251            [['B', 5], True], [['C', 5], True], [['D', 5], True], 
     252            [['E', 6], True], [['E', 7], True], [['E', 8], True], 
     253            [['F', 4], True], [['G', 2], True], 
     254            [['I', 5], False], [['H', 3], False], [['H', 4], False]] 
     255 
     256        TESTS: 
     257            sage: all(t.is_crystalographic() for t in CartanType.samples(affine=True)) 
     258            True 
     259        """ 
     260        raise NotImplementedError 
     261 
     262    def is_simple_laced(self): 
     263        """ 
     264        Returns whether this Cartan type is simple laced 
     265 
     266        EXAMPLES: 
     267            sage: [ [t, t.is_simply_laced() ] for t in CartanType.samples() ] 
     268            [[['A', 1], True], [['A', 5], True], 
     269            [['B', 5], False], [['C', 5], False], [['D', 5], True], 
     270            [['E', 6], True], [['E', 7], True], [['E', 8], True], 
     271            [['F', 4], False], [['G', 2], False], [['I', 5], False], [['H', 3], False], [['H', 4], False], 
     272            [['A', 1, 1], False], [['A', 5, 1], True], 
     273            [['B', 5, 1], False], [['C', 5, 1], False], [['D', 5, 1], True], 
     274            [['E', 6, 1], True], [['E', 7, 1], True], [['E', 8, 1], True], 
     275            [['F', 4, 1], False], [['G', 2, 1], False], 
     276            [['A', 2, 2], False], [['A', 10, 2], False], [['A', 9, 2], False], [['D', 5, 2], False], [['D', 4, 3], False], [['E', 6, 2], False]] 
     277        """ 
     278        raise NotImplementedError 
    191279 
    192280    def index_set(self): 
    193281        """ 
     
    213301            sage: CartanType(['A',4]).root_system() 
    214302            Root system of type ['A', 4] 
    215303        """ 
    216         return root_system.RootSystem(self) 
     304        return root_system.root_system.RootSystem(self) 
     305 
     306# Maybe we want a separate class for affine 
     307 
     308class CartanType_simple(CartanType_abstract): 
     309    """ 
     310    TESTS: 
     311            sage: ct1 = CartanType(['A',4]) 
     312            sage: ct2 = CartanType(['A',4]) 
     313            sage: ct3 = CartanType(['A',5]) 
     314            sage: ct1 == ct2 
     315            True 
     316            sage: ct1 != ct3 
     317            True 
     318        """ 
     319 
     320    def __hash__(self): 
     321        """ 
     322        EXAMPLES: 
     323            sage: ct = CartanType(['A',2]) 
     324            sage: hash(ct) #random 
     325            -5684143898951441983 
     326        """ 
     327        return hash(str(self)) 
     328         
     329    def __getitem__(self, x): 
     330        """ 
     331        EXAMPLES: 
     332            sage: t = CartanType(['A', 3, 1]) 
     333            sage: t[0] 
     334            'A' 
     335            sage: t[1] 
     336            3 
     337            sage: t[2] 
     338            1 
     339            sage: t[3] 
     340            Traceback (most recent call last): 
     341            ... 
     342            IndexError: list index out of range 
     343        """ 
     344        return self.t[x] 
     345 
     346    def is_irreducible(self): 
     347        return True 
     348 
     349    def dynkin_diagram(self): 
     350        """ 
     351        Returns the Dynkin diagram associated with self. 
     352 
     353        EXAMPLES: 
     354            sage: CartanType(['A',4]).dynkin_diagram() 
     355            Dynkin diagram of type ['A', 4] 
     356        """ 
     357        return root_system.dynkin_diagram.DynkinDiagram(self) 
    217358 
    218359    def cartan_matrix(self): 
    219360        """ 
     
    227368            [ 0  0 -1  2] 
    228369 
    229370        """ 
    230         return cartan_matrix(self) 
     371        return root_system.cartan_matrix.cartan_matrix(self) 
    231372 
    232373    def type(self): 
    233374        """ 
     
    236377        EXAMPLES: 
    237378            sage: CartanType(['A', 4]).type() 
    238379            'A' 
     380            sage: CartanType(['A', 4, 1]).type() 
     381            'A' 
    239382        """ 
    240383        return self.letter 
     384 
     385    def type_string(self): 
     386        """ 
     387        Returns a string suitable for type-specific code dispatch 
     388 
     389        EXAMPLES: 
     390            sage: CartanType(['A', 4]).type_string() 
     391            'type_A' 
     392            sage: CartanType(['A', 4, 1]).type_string() 
     393            'type_A_affine' 
     394        """ 
     395        if self.is_affine(): 
     396            return "type_%s_affine"%self.letter 
     397        else: 
     398            return "type_%s"%self.letter 
     399 
     400    def dual(self): 
     401        if self.type() in ["A", "D", "E"]: 
     402            return self 
     403        else: 
     404            return CartanType_abstract.dual(self) 
     405 
     406    def is_irreducible(self): 
     407        """ 
     408        Report that this Cartan type is irreducible. 
     409        """ 
     410        return True 
     411 
     412class CartanType_simple_finite(CartanType_simple): 
     413    r""" 
     414    A class for finite simple Cartan types 
     415    """ 
     416 
     417    def __init__(self, t): 
     418        """ 
     419        EXAMPLES: 
     420            sage: ct = CartanType(['A',4]) 
     421            sage: ct == loads(dumps(ct)) 
     422            True 
     423        """ 
     424        assert(len(t) == 2) 
     425        assert(t[0] in ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']) 
     426        assert(t[1] in ZZ and t[1] >= 0) 
     427        if t[0] in ['B', 'C']: 
     428            assert(t[1] >= 2) 
     429        if t[0] == 'D': 
     430            assert(t[1] >= 3) 
     431        if t[0] == 'E': 
     432            assert(t[1] <= 8) 
     433        if t[0] == 'F': 
     434            assert(t[1] <= 4) 
     435        if t[0] == 'G': 
     436            assert(t[1] <= 2) 
     437        if t[0] == 'H': 
     438            assert(t[1] <= 4) 
     439 
     440        self.t = t 
     441        self.letter = t[0] 
     442        self.n = t[1] 
     443 
     444 
     445    def __repr__(self): 
     446        """ 
     447        TESTS: 
     448            sage: ct = CartanType(['A',3]) 
     449            sage: repr(ct) 
     450            "['A', 3]" 
     451        """ 
     452        return "['%s', %s]"%(self.letter, self.n) 
     453 
     454    def __len__(self): 
     455        """ 
     456        EXAMPLES: 
     457            sage: len(CartanType(['A',4])) 
     458            2 
     459        """ 
     460        return 2 
     461 
     462    def __cmp__(self, other): 
     463        if other.__class__ != self.__class__: 
     464            return cmp(self.__class__, other.__class__) 
     465        if other.letter != self.letter: 
     466            return cmp(self.letter, other.letter) 
     467        return cmp(self.n, other.n) 
     468 
     469    def rank(self): 
     470        if self.letter == "I": 
     471            return 2 
     472        else: 
     473            return self.n 
     474    def is_finite(self): 
     475        return True 
     476 
     477    def is_affine(self): 
     478        return False 
     479 
     480    def is_crystalographic(self): 
     481        return self.letter in ["A", "B", "C", "D", "E", "F", "G"] 
     482 
     483    def is_simply_laced(self): 
     484        return self.letter in  ["A", "D", "E"] 
     485 
     486    def affine(self): 
     487        """ 
     488        Returns the corresponding untwisted affine Cartan type 
     489 
     490        EXAMPLES: 
     491            sage: CartanType(['A',3]).affine() 
     492            ['A', 3, 1] 
     493        """ 
     494        return CartanType([self.letter, self.n, 1]) 
     495 
     496    def dual(self): 
     497        if self.type() == "B": 
     498            return CartanType(["C",self.n]) 
     499        elif self.type() == "C": 
     500            return CartanType(["B",self.n]) 
     501        else: 
     502            return CartanType_simple.dual(self) 
     503 
     504########################################################################## 
     505class CartanType_simple_affine(CartanType_simple): 
     506    r""" 
     507    A class for affine simple Cartan types 
     508    """ 
     509 
     510    def __init__(self, t): 
     511        """ 
     512        EXAMPLES: 
     513            sage: ct = CartanType(['A',4]) 
     514            sage: ct == loads(dumps(ct)) 
     515            True 
     516        """ 
     517        assert(len(t) == 3) 
     518        assert(t[0] in ['A', 'B', 'C', 'D', 'E', 'F', 'G']) 
     519        assert(t[1] in ZZ and t[1] >= 1) 
     520        assert(t[2] in [1,2,3]) 
     521        if t[0] in ['B', 'C']: 
     522            assert(t[1] >= 2) 
     523        if t[0] == 'D': 
     524            assert(t[1] >= 4) 
     525        if t[0] == 'E': 
     526            assert(t[1] <= 8) 
     527        if t[0] == 'F': 
     528            assert(t[1] <= 4) 
     529        if t[0] == 'G': 
     530            assert(t[1] <= 2) 
     531        if t[2] == 3: 
     532            assert(t[0] == "D") 
     533            assert(t[1] == 4) 
     534        if t[2] == 2: 
     535            assert(t[0] in ['A', 'D', 'E']) 
     536            if t[0] == 'E': 
     537                assert(t[1] == 6) 
     538 
     539        self.t = t 
     540        self.letter = t[0] 
     541        self.n = t[1] 
     542        self.affine = t[2] 
     543 
     544    def __repr__(self): 
     545        """ 
     546        TESTS: 
     547            sage: ct = CartanType(['A',3, 1]) 
     548            sage: repr(ct) 
     549            "['A', 3, 1]" 
     550        """ 
     551        return "['%s', %s, %s]"%(self.letter, self.n, self.affine) 
     552 
     553    def __cmp__(self, other): 
     554        c = CartanType_simple_finite.cmp(self, other) 
     555        if c != 0: 
     556            return c 
     557        else: 
     558            return cmp(self.affine, other.affine) 
     559 
     560    def __len__(self): 
     561        """ 
     562        EXAMPLES: 
     563            sage: len(CartanType(['A',4,1])) 
     564            3 
     565        """ 
     566        return 3 
     567 
     568    def rank(self): 
     569        if self.affine == 3 and self.letter == 'D': 
     570            return self.n-1 
     571        elif self.affine == 2 and self.letter == 'A': 
     572            ## FIXME: check in the literature what should be the 
     573            ## appropriate definition for rank 
     574            return int(self.n+1)/2 
     575        else: 
     576            return self.n 
     577 
     578    def is_finite(self): 
     579        return False 
     580 
     581    def is_affine(self): 
     582        return True 
     583 
     584    def is_crystalographic(self): 
     585        return True 
     586 
     587    def is_simply_laced(self): 
     588        if self.affine != 1: 
     589            return False 
     590        if self.letter == "A": 
     591            return self.n > 1 
     592        return self.letter in  ["D", "E"] 
     593 
     594    def classical(self): 
     595        r""" 
     596        Returns the classical Cartan type associated with self (which should be affine) 
     597 
     598        Caveat: only implemented for untwisted 
     599 
     600        EXAMPLES: 
     601            sage: CartanType(['A', 3, 1]).classical() 
     602            ['A', 3] 
     603            sage: CartanType(['B', 3, 1]).classical() 
     604            ['B', 3] 
     605        """ 
     606         
     607        if self.affine == 1: 
     608            return CartanType([self.letter,self.n]) 
     609        else: 
     610            raise notImplementedError 
  • sage/combinat/root_system/coxeter_matrix.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/coxeter_matrix.py
    a b  
    1616#                  http://www.gnu.org/licenses/ 
    1717#***************************************************************************** 
    1818from cartan_type import CartanType 
    19 from dynkin_diagram import dynkin_diagram_as_function 
    2019from sage.matrix.all import MatrixSpace 
    2120from sage.rings.all import ZZ 
    2221 
     
    3332        [2 3 1 3] 
    3433        [2 2 3 1] 
    3534    """ 
    36     ct = CartanType(t) 
    37     f = dynkin_diagram_as_function(ct) 
     35    a = CartanType(t).dynkin_diagram() 
     36    scalarproducts_to_order = { 0: 2,  1: 3,  2: 4,  3: 7 
     37                                # 4 should be infinity 
     38                                } 
    3839 
    39     if ct.letter == "G": 
    40         coxeter = lambda i,j: 1 if i == j else max(f(j,i), f(i,j))+4 
    41     else: 
    42         coxeter = lambda i,j: 1 if i == j else max(f(j,i), f(i,j))+2 
    43  
    44     return coxeter 
     40    return lambda i,j: 1 if i == j else scalarproducts_to_order[a[i,j]*a[j,i]] 
    4541     
    4642     
    4743def coxeter_matrix(t): 
  • sage/combinat/root_system/dynkin_diagram.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/dynkin_diagram.py
    a b  
    1616#                  http://www.gnu.org/licenses/ 
    1717#***************************************************************************** 
    1818from sage.graphs.all import DiGraph 
     19from cartan_type import CartanType, CartanType_abstract 
     20from cartan_matrix import cartan_matrix 
     21import cartan_type 
     22from root_system import RootSystem 
    1923 
     24def DynkinDiagram(*args): 
     25    """ 
     26    INPUT: 
     27       ct -- A Cartan Type 
     28    Returns a Dynkin diagram for type ct. 
     29 
     30    The edge multiplicities are encoded as edge labels. This uses the 
     31    convention in Kac / Fulton Harris Representation theory wikipedia 
     32    http://en.wikipedia.org/wiki/Dynkin_diagram, that is for i != j: 
     33  
     34    j -k-> i  <==>  a_ij = -k  <==>  -scalar(coroot[i], root[j]) = k 
     35    <==>  multiple arrows point from the longer root to the shorter one 
     36 
     37    TODO: say something about the node labelling conventions. 
     38 
     39    EXAMPLES: 
     40        sage: DynkinDiagram(['A', 4]) 
     41        Dynkin diagram of type ['A', 4] 
     42        sage: DynkinDiagram(['A',1],['A',1]) 
     43        Dynkin diagram of type A1xA1 
     44        sage: R = RootSystem("A2xB2xF4") 
     45        sage: DynkinDiagram(R) 
     46        Dynkin diagram of type A2xB2xF4 
     47    """ 
     48    if len(args) == 1: 
     49        t = args[0] 
     50    else: 
     51        t = CartanType(args) 
     52 
     53    if isinstance(t, RootSystem): 
     54        ct = t.cartan_type() 
     55    else: 
     56        ct = CartanType(t) 
     57    if ct.is_reducible(): 
     58        function = globals()["type_reducible"] 
     59    else: 
     60        letter = ct[0].lower() 
     61        affine = "" 
     62        ct = CartanType(ct) 
     63        if ct.is_affine(): 
     64            affine = "_affine" 
     65        function = globals()["type_"+letter+affine] 
     66    try: 
     67        return function(ct) 
     68    except KeyError: 
     69        raise TypeError, "Dynkin diagram data not yet hardcoded for type %s"%t 
     70 
     71def dynkin_diagram(t): 
     72    """ 
     73    Deprecated; please use DynkinDiagram 
     74    """ 
     75    return DynkinDiagram(t) 
     76 
     77 
     78class DynkinDiagram_class(DiGraph, CartanType_abstract): 
     79    def __init__(self, t): 
     80        DiGraph.__init__(self) 
     81        self._cartan_type = t 
     82 
     83    def __repr__(self): 
     84        """ 
     85        EXAMPLES: 
     86          sage: DynkinDiagram(['A',3]) 
     87          Dynkin diagram of type ['A', 3] 
     88        """ 
     89        if self._cartan_type is None: 
     90            return "Dynkin diagram of rank %s"%self.rank() 
     91        else: 
     92            return "Dynkin diagram of type %s"%self._cartan_type 
     93 
     94    def add_edge(self, i, j, label=1): 
     95        DiGraph.add_edge(self, i, j, label) 
     96        if not self.has_edge(j,i): 
     97            self.add_edge(j,i,1) 
     98 
     99    def index_set(self): 
     100        """ 
     101        EXAMPLES: 
     102          sage: DynkinDiagram(['C',3]).index_set() 
     103          [1, 2, 3] 
     104          sage: DynkinDiagram("A2","B2","F4").index_set() 
     105          [1, 2, 3, 4, 5, 6, 7, 8] 
     106        """ 
     107        return self.vertices() 
     108         
     109    def cartan_type(self): 
     110        """ 
     111        EXAMPLES: 
     112          sage: DynkinDiagram("A2","B2","F4").cartan_type() 
     113          A2xB2xF4 
     114        """ 
     115        return self._cartan_type 
     116 
     117    def rank(self): 
     118        r""" 
     119        returns the index set for this Dynkin diagram 
     120 
     121        EXAMPLES: 
     122        """ 
     123        return self.num_verts() 
     124 
     125    def dynkin_diagram(self): 
     126        return self 
     127 
     128    def cartan_matrix(self): 
     129        r""" 
     130        returns the Cartan matrix for this Dynkin diagram 
     131 
     132        EXAMPLES: 
     133            sage: DynkinDiagram(['C',3]).cartan_matrix() 
     134            [ 2 -1  0] 
     135            [-1  2 -2] 
     136            [ 0 -1  2] 
     137        """ 
     138        return cartan_matrix(self) 
     139 
     140    def dual(self): 
     141        r""" 
     142        Returns the dual Dynkin diagram, obtained by reversing all edges. 
     143 
     144        EXAMPLES: 
     145            sage: D = DynkinDiagram(['C',3]) 
     146            sage: D.edges() 
     147            [(1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 2)] 
     148            sage: D.dual() 
     149            Dynkin diagram of type ['B', 3] 
     150            sage: D.dual().edges() 
     151            [(1, 2, 1), (2, 1, 1), (2, 3, 2), (3, 2, 1)] 
     152            sage: D.dual() == DynkinDiagram(['B',3]) 
     153            True 
     154 
     155        TESTS: 
     156            sage: D = DynkinDiagram(['A',0]); D 
     157            Dynkin diagram of type ['A', 0] 
     158            sage: D.edges() 
     159            [] 
     160            sage: D.dual() 
     161            Dynkin diagram of type ['A', 0] 
     162            sage: D.dual().edges() 
     163            [] 
     164            sage: D = DynkinDiagram(['A',1]) 
     165            sage: D.edges() 
     166            [] 
     167            sage: D.dual() 
     168            Dynkin diagram of type ['A', 1] 
     169            sage: D.dual().edges() 
     170            [] 
     171 
     172        """ 
     173        result = DynkinDiagram_class(None) 
     174        result.add_vertices(self.vertices()) 
     175        for source, target, label in self.edges(): 
     176            result.add_edge(target, source, label) 
     177        result._cartan_type = self._cartan_type.dual() if not self._cartan_type is None else None 
     178        return result 
     179 
     180    def __getitem__(self, i): 
     181        """ 
     182        With a tuple (i,j) as argument, returns the scalar product $\langle 
     183        \alpha^\vee_i, \alpha_j\rangle$. 
     184 
     185        Otherwise, behaves as the usual DiGraph.__getitem__ 
     186         
     187        EXAMPLES: 
     188        We use the $C_4$ dynkin diagram as a cartan matrix: 
     189            sage: g = DynkinDiagram(['C',4]) 
     190            sage: matrix([[g[i,j] for j in range(1,5)] for i in range(1,5)]) 
     191            [ 2 -1  0  0] 
     192            [-1  2 -1  0] 
     193            [ 0 -1  2 -2] 
     194            [ 0  0 -1  2] 
     195 
     196        The neighbors of a node can still be obtained in the usual way: 
     197            sage: [g[i] for i in range(1,5)] 
     198            [[2], [1, 3], [2, 4], [3]] 
     199        """ 
     200        if not isinstance(i, tuple): 
     201            return DiGraph.__getitem__(self,i) 
     202        [i,j] = i 
     203        if i == j: 
     204            return 2 
     205        elif self.has_edge(j, i): 
     206            return -self.edge_label(j, i) 
     207        else: 
     208            return 0 
     209 
     210    def column(self, j): 
     211        """ 
     212        Returns the $j$-th column $(a_{i,j})_i$ of the Cartan matrix 
     213        corresponding to this Dynkin diagram, as a container (or iterator) 
     214        of tuples (i, a_{i,j}) 
     215 
     216        EXAMPLES: 
     217            sage: g = DynkinDiagram(["B",4]) 
     218            sage: [ (i,a) for (i,a) in g.column(3) ] 
     219            [(3, 2), (2, -1), (4, -2)] 
     220 
     221        Caveat: broken in sage < 3.0.3 
     222        """ 
     223        return [(j,2)] + [(i,-m) for (j1, i, m) in self.outgoing_edges(j)] 
     224 
     225    def row(self, i): 
     226        """ 
     227        Returns the $i$-th row $(a_{i,j})_j$ of the Cartan matrix 
     228        corresponding to this Dynkin diagram, as a container (or iterator) 
     229        of tuples (j, a_{i,j}) 
     230 
     231        EXAMPLES: 
     232            sage: g = DynkinDiagram(["C",4]) 
     233            sage: [ (i,a) for (i,a) in g.row(3) ] 
     234            [(3, 2), (2, -1), (4, -2)] 
     235        """ 
     236        return [(i,2)] + [(j,-m) for (j, i1, m) in self.incoming_edges(i)] 
     237         
    20238def precheck(t, letter=None, length=None, affine=None, n_ge=None, n=None): 
    21239    """ 
    22240    EXAMPLES: 
     
    52270        if len(t) != length: 
    53271            raise ValueError, "len(t) must be = %s"%length 
    54272         
    55  
    56273    if affine is not None: 
    57274        try: 
    58275            if t[2] != affine: 
     
    68285        if t[1] != n: 
    69286            raise ValueError, "t[1] must be = %s"%n 
    70287 
     288############################################################################## 
     289# Everything below is type by type hardcoded data. It probably should be moved 
     290# into the type_... files 
     291############################################################################## 
     292 
     293 
    71294def type_a(t): 
    72295    """ 
    73296    Returns the graph corresponding to the Dynkin diagram 
     
    76299    EXAMPLES: 
    77300        sage: from sage.combinat.root_system.dynkin_diagram import type_a 
    78301        sage: ct = CartanType(['A',3]) 
    79         sage: a = type_a(ct);a 
    80         Multi-digraph on 3 vertices 
     302        sage: a = type_a(ct); a 
     303        Dynkin diagram of type ['A', 3] 
    81304        sage: e = a.edges(); e.sort(); e 
    82         [(1, 2, None), (2, 1, None), (2, 3, None), (3, 2, None)] 
     305        [(1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 1)] 
    83306 
     307    TEST: 
     308        sage: a = DynkinDiagram(['A',1]) 
     309        sage: a 
     310        Dynkin diagram of type ['A', 1] 
     311        sage: a.vertices(), a.edges() 
     312        ([1], []) 
    84313    """ 
    85314    precheck(t, letter="A", length=2) 
    86315    n = t[1] 
    87     g = DiGraph(multiedges=True) 
     316    g = DynkinDiagram_class(t) 
     317    g.add_vertices(t.index_set()) 
    88318    for i in range(1, n): 
    89319        g.add_edge(i, i+1) 
    90         g.add_edge(i+1, i) 
    91  
    92320    return g 
    93321 
    94322def type_a_affine(t): 
    95323    """ 
    96     Returns the DiGraph corresponding to the Dynkin diagram 
    97     of affine type A. 
     324    Returns the extended Dynkin diagram for affine type A. 
    98325 
    99326    EXAMPLES: 
    100327        sage: from sage.combinat.root_system.dynkin_diagram import type_a_affine 
    101328        sage: ct = CartanType(['A',3,1]) 
    102329        sage: a = type_a_affine(ct); a 
    103         Multi-digraph on 4 vertices 
     330        Dynkin diagram of type ['A', 3, 1] 
    104331        sage: e = a.edges(); e.sort(); e 
    105         [(0, 1, None), 
    106          (0, 3, None), 
    107          (1, 0, None), 
    108          (1, 2, None), 
    109          (2, 1, None), 
    110          (2, 3, None), 
    111          (3, 0, None), 
    112          (3, 2, None)] 
     332        [(0, 1, 1), 
     333         (0, 3, 1), 
     334         (1, 0, 1), 
     335         (1, 2, 1), 
     336         (2, 1, 1), 
     337         (2, 3, 1), 
     338         (3, 0, 1), 
     339         (3, 2, 1)] 
    113340    """ 
    114341    precheck(t, letter="A", length=3, affine=1) 
    115342    n = t[1] 
    116     g = type_a(['A', n]) 
    117  
     343    g = DynkinDiagram_class(t) 
     344    g.add_vertices(t.index_set()) 
     345    for i in range(1, n): 
     346        g.add_edge(i, i+1) 
    118347    g.add_edge(0, 1) 
    119     g.add_edge(1, 0) 
    120348    g.add_edge(0, n) 
    121     g.add_edge(n, 0) 
    122349 
    123350    return g 
    124351 
    125352def type_b(t): 
    126353    """ 
    127     Returns the DiGraph corresponding to the Dynkin diagram 
    128     of type B. 
     354    Returns a Dynkin diagram for type B. 
    129355     
    130356    EXAMPLES: 
    131         sage: from sage.combinat.root_system.dynkin_diagram import type_b 
    132         sage: ct = CartanType(['B',3]) 
    133         sage: b = type_b(ct);b 
    134         Multi-digraph on 3 vertices 
    135         sage: e = b.edges(); e.sort(); e 
    136         [(1, 2, None), (2, 1, None), (2, 3, None), (3, 2, None), (3, 2, None)] 
    137  
     357         sage: from sage.combinat.root_system.dynkin_diagram import type_b 
     358         sage: ct = CartanType(['B',3]) 
     359         sage: b = type_b(ct);b 
     360         Dynkin diagram of type ['B', 3] 
     361         sage: e = b.edges(); e.sort(); e 
     362         [(1, 2, 1), (2, 1, 1), (2, 3, 2), (3, 2, 1)] 
    138363 
    139364    """ 
    140365    precheck(t, letter='B', length=2, n_ge=2) 
    141366    n = t[1] 
    142     g = type_a(['A', n]) 
    143     g.add_edge(n, n-1) 
     367    g = DynkinDiagram_class(t) 
     368    g.add_vertices(t.index_set()) 
     369    for i in range(1, n): 
     370        g.add_edge(i, i+1) 
     371    g.set_edge_label(n-1, n, 2) 
    144372    return g 
     373     
     374def type_b_affine(t): 
     375    """ 
     376    Returns the extended Dynkin diagram for affine type B. 
     377     
     378    EXAMPLES: 
     379       sage: DynkinDiagram(['B',3,1]).edges() 
     380       [(0, 2, 1), (1, 2, 1), (2, 0, 1), (2, 1, 1), (2, 3, 2), (3, 2, 1)] 
    145381 
     382    """ 
     383    precheck(t, letter='B', length=3, affine=1) 
     384    n = t[1] 
     385    g = DynkinDiagram_class(t) 
     386    g.add_vertices(t.index_set()) 
     387    for i in range(1, n): 
     388        g.add_edge(i, i+1) 
     389    g.set_edge_label(n-1, n, 2) 
     390    g.add_edge(0,2) 
     391    return g 
    146392     
    147393def type_c(t): 
    148394    """ 
    149     Returns the DiGraph corresponding to the Dynkin diagram 
    150     of type C. 
     395    Returns a Dynkin diagram for type C. 
    151396 
    152397    EXAMPLES: 
    153398        sage: from sage.combinat.root_system.dynkin_diagram import type_c 
    154399        sage: ct = CartanType(['C',3]) 
    155         sage: c = type_c(ct);c 
    156         Multi-digraph on 3 vertices 
     400        sage: c = type_c(ct); c 
     401        Dynkin diagram of type ['C', 3] 
    157402        sage: e = c.edges(); e.sort(); e 
    158         [(1, 2, None), (2, 1, None), (2, 3, None), (2, 3, None), (3, 2, None)] 
     403        [(1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 2)] 
    159404 
    160405    """ 
    161406    precheck(t, letter='C', length=2, n_ge=2) 
    162407    n = t[1] 
    163     g = type_a(['A', n]) 
    164     g.add_edge(n-1,n) 
     408    g = DynkinDiagram_class(t) 
     409    g.add_vertices(t.index_set()) 
     410    for i in range(1, n): 
     411        g.add_edge(i, i+1) 
     412    g.set_edge_label(n,n-1,2) 
    165413    return g     
    166414 
    167415def type_c_affine(t): 
    168416    """ 
    169     Returns the DiGraph corresponding to the Dynkin diagram 
    170     of affine type C. 
     417    Returns the extended Dynkin diagram for affine type C. 
    171418     
    172419    EXAMPLES: 
    173420        sage: from sage.combinat.root_system.dynkin_diagram import type_c_affine 
    174421        sage: ct = CartanType(['C',3,1]) 
    175422        sage: c = type_c_affine(ct);c 
    176         Multi-digraph on 4 vertices 
     423        Dynkin diagram of type ['C', 3, 1] 
    177424        sage: e = c.edges(); e.sort(); e 
    178         [(0, 1, None), 
    179          (0, 1, None), 
    180          (1, 0, None), 
    181          (1, 2, None), 
    182          (2, 1, None), 
    183          (2, 3, None), 
    184          (2, 3, None), 
    185          (3, 2, None)] 
     425        [(0, 1, 2), (1, 0, 1), (1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 2)] 
    186426 
    187427    """ 
    188428    precheck(t, letter='C', length=3, affine=1) 
    189429    n = t[1] 
    190     g = type_c(['C', n]) 
    191     g.add_edge(0,1) 
    192     g.add_edge(0,1) 
    193     g.add_edge(1,0) 
     430    g = DynkinDiagram_class(t) 
     431    g.add_vertices(t.index_set()) 
     432    for i in range(1, n): 
     433        g.add_edge(i, i+1) 
     434    g.set_edge_label(n,n-1,2) 
     435    g.add_edge(0,1,1) 
     436    g.add_edge(0,1,2) 
    194437    return g 
    195438 
    196439def type_d(t): 
    197440    """ 
    198     Returns the DiGraph corresponding to the Dynkin diagram 
    199     of type D. 
     441    Returns a Dynkin diagram for type D. 
    200442         
    201443    EXAMPLES: 
    202444        sage: from sage.combinat.root_system.dynkin_diagram import type_d 
    203         sage: ct = CartanType(['D',3]) 
     445        sage: ct = CartanType(['D',4]) 
    204446        sage: d = type_d(ct);d 
    205         Multi-digraph on 3 vertices 
     447        Dynkin diagram of type ['D', 4] 
    206448        sage: e = d.edges(); e.sort(); e 
    207         [(1, 2, None), (1, 3, None), (2, 1, None), (3, 1, None)] 
     449        [(1, 2, 1), (2, 1, 1), (2, 3, 1), (2, 4, 1), (3, 2, 1), (4, 2, 1)] 
    208450 
    209451    """ 
    210452    precheck(t, letter="D", length=2, n_ge=3) 
    211453    n = t[1] 
    212     g = type_a(['A', n-1]) 
     454 
     455    g = DynkinDiagram_class(t) 
     456    g.add_vertices(t.index_set()) 
     457    for i in range(1, n-1): 
     458        g.add_edge(i, i+1) 
    213459    g.add_edge(n-2,n) 
    214     g.add_edge(n, n-2) 
    215460    return g 
    216461 
    217462def type_d_affine(t): 
    218463    """ 
    219     Returns the DiGraph corresponding to the Dynkin diagram 
    220     of type D. 
     464    Returns the extended Dynkin diagram for affine type D. 
    221465 
    222466    EXAMPLES: 
    223         sage: from sage.combinat.root_system.dynkin_diagram import type_d_affine 
    224         sage: ct = CartanType(['D',3,1]) 
    225         sage: d = type_d_affine(ct);d 
    226         Multi-digraph on 4 vertices 
    227         sage: e = d.edges(); e.sort(); e 
    228         [(0, 2, None), 
    229          (1, 2, None), 
    230          (1, 3, None), 
    231          (2, 0, None), 
    232          (2, 1, None), 
    233          (3, 1, None)] 
     467       sage: DynkinDiagram(CartanType(['D', 4, 1])) 
     468       Dynkin diagram of type ['D', 4, 1] 
     469       sage: DynkinDiagram(CartanType(['D', 4, 1])).edges() 
     470       [(0, 2, 1), 
     471        (1, 2, 1), 
     472        (2, 0, 1), 
     473        (2, 1, 1), 
     474        (2, 3, 1), 
     475        (2, 4, 1), 
     476        (3, 2, 1), 
     477        (4, 2, 1)] 
    234478 
    235479    """ 
    236480    precheck(t, letter="D", length=3, affine=1) 
    237481    n = t[1] 
    238     g = type_d(['D', n]) 
     482    g = DynkinDiagram_class(t) 
     483    g.add_vertices(t.index_set()) 
     484    for i in range(1, n-1): 
     485        g.add_edge(i, i+1) 
     486    g.add_edge(n-2,n) 
    239487    g.add_edge(0,2) 
    240     g.add_edge(2,0) 
    241488    return g 
    242489 
    243490def type_e(t): 
    244491    """ 
    245     Returns the DiGraph corresponding to the Dynkin diagram 
    246     of type E. 
     492    Returns a Dynkin diagram for type E. 
    247493 
    248494    EXAMPLES: 
    249495        sage: from sage.combinat.root_system.dynkin_diagram import type_e 
    250496        sage: ct = CartanType(['E',6]) 
    251497        sage: e = type_e(ct);e 
    252         Multi-digraph on 6 vertices 
     498        Dynkin diagram of type ['E', 6] 
    253499        sage: edges = e.edges(); edges.sort(); edges 
    254         [(1, 3, None), 
    255          (2, 4, None), 
    256          (3, 1, None), 
    257          (3, 4, None), 
    258          (4, 2, None), 
    259          (4, 3, None), 
    260          (4, 5, None), 
    261          (5, 4, None), 
    262          (5, 6, None), 
    263          (6, 5, None)] 
     500        [(1, 3, 1), (2, 4, 1), (3, 1, 1), (3, 4, 1), (4, 2, 1), (4, 3, 1), (4, 5, 1), (5, 4, 1), (5, 6, 1), (6, 5, 1)] 
    264501 
    265502    """ 
    266503    precheck(t, letter="E", length=2, n_ge=3) 
    267504    n = t[1] 
    268     g = DiGraph(multiedges=True) 
     505    g = DynkinDiagram_class(t) 
    269506    g.add_edge(1,3) 
    270     g.add_edge(3,1) 
    271507    g.add_edge(2,4) 
    272     g.add_edge(4,2) 
    273508    for i in range(3,n): 
    274509        g.add_edge(i, i+1) 
    275         g.add_edge(i+1, i) 
     510    return g 
     511 
     512def type_e_affine(t): 
     513    """ 
     514    Returns the extended Dynkin diagram for affine type E. 
     515 
     516    EXAMPLES: 
     517        sage: from sage.combinat.root_system.dynkin_diagram import type_e_affine 
     518        sage: e = DynkinDiagram(['E', 6, 1]) 
     519        sage: edges = e.edges(); edges.sort(); edges 
     520        [(0, 2, 1), 
     521         (1, 3, 1), 
     522         (2, 0, 1), 
     523         (2, 4, 1), 
     524         (3, 1, 1), 
     525         (3, 4, 1), 
     526         (4, 2, 1), 
     527         (4, 3, 1), 
     528         (4, 5, 1), 
     529         (5, 4, 1), 
     530         (5, 6, 1), 
     531         (6, 5, 1)] 
     532 
     533    """ 
     534    precheck(t, letter="E", length=3, affine=1) 
     535    n = t[1] 
     536    g = DynkinDiagram_class(t) 
     537    g.add_edge(1,3) 
     538    g.add_edge(2,4) 
     539    for i in range(3,n): 
     540        g.add_edge(i, i+1) 
     541    if n == 6: 
     542        g.add_edge(0, 2) 
     543    elif n == 7: 
     544        g.add_edge(0, 1) 
     545    elif n == 8: 
     546        g.add_edge(0, 8) 
     547    else: 
     548        raise ValueError, "Invalid Cartan Type for Type E affine" 
    276549    return g 
    277550 
    278551def type_f(t): 
    279552    """ 
    280     Returns the DiGraph corresponding to the Dynkin diagram 
    281     of type F. 
     553    Returns a Dynkin diagram for type F. 
    282554 
    283555    EXAMPLES: 
    284556        sage: from sage.combinat.root_system.dynkin_diagram import type_f 
    285557        sage: ct = CartanType(['F',4]) 
    286558        sage: f = type_f(ct);f 
    287         Multi-digraph on 4 vertices 
     559        Dynkin diagram of type ['F', 4] 
    288560        sage: e = f.edges(); e.sort(); e 
    289         [(1, 2, None), 
    290          (2, 1, None), 
    291          (2, 3, None), 
    292          (3, 2, None), 
    293          (3, 2, None), 
    294          (3, 4, None), 
    295          (4, 3, None)] 
     561        [(1, 2, 1), (2, 1, 1), (2, 3, 2), (3, 2, 1), (3, 4, 1), (4, 3, 1)] 
    296562 
    297563    """ 
    298564    precheck(t, letter='F', length=2, n=4) 
    299     g = DiGraph(multiedges=True) 
     565    g = DynkinDiagram_class(t) 
    300566    for i in range(1, 4): 
    301567        g.add_edge(i, i+1) 
    302         g.add_edge(i+1, i) 
    303     g.add_edge(3,2) 
     568    g.set_edge_label(2,3,2) 
     569    return g 
     570 
     571def type_f_affine(t): 
     572    """ 
     573    Returns the extended Dynkin diagram for affine type F. 
     574 
     575    EXAMPLES: 
     576        sage: f = DynkinDiagram(['F', 4, 1]) 
     577        sage: edges = f.edges(); edges.sort(); edges 
     578        [(0, 1, 1), (1, 0, 1), (1, 2, 1), (2, 1, 1), (2, 3, 2), (3, 2, 1), (3, 4, 1), (4, 3, 1)] 
     579 
     580    """ 
     581    precheck(t, letter="F", length=3, affine=1) 
     582    g = DynkinDiagram_class(t) 
     583    for i in range(1, 4): 
     584        g.add_edge(i, i+1) 
     585    g.set_edge_label(2,3,2) 
     586    g.add_edge(0, 1) 
    304587    return g 
    305588 
    306589def type_g(t): 
    307590    """ 
    308     Returns the DiGraph corresponding to the Dynkin diagram 
    309     of type G. 
     591    Returns a Dynkin diagram for type G. 
    310592 
    311593    EXAMPLES: 
    312594        sage: from sage.combinat.root_system.dynkin_diagram import type_g 
    313595        sage: ct = CartanType(['G',2]) 
    314596        sage: g = type_g(ct);g 
    315         Multi-digraph on 2 vertices 
     597        Dynkin diagram of type ['G', 2] 
    316598        sage: e = g.edges(); e.sort(); e 
    317         [(1, 2, None), (1, 2, None), (1, 2, None), (2, 1, None)] 
     599        [(1, 2, 1), (2, 1, 3)] 
    318600 
    319601    """ 
    320602    precheck(t, letter='G', length=2, n=2) 
    321     g = DiGraph(multiedges=True) 
    322     for _ in range(3): 
    323         g.add_edge(1,2) 
    324     g.add_edge(2,1) 
     603    g = DynkinDiagram_class(t) 
     604    g.add_edge(1,2) 
     605    g.set_edge_label(2,1,3) 
    325606    return g 
    326607 
    327 def dynkin_diagram(t): 
     608def type_g_affine(t): 
    328609    """ 
    329     Returns a DiGraph corresponding to the Dynkin diagram of 
    330     type t. 
     610    Returns the extended Dynkin diagram for type G. 
    331611 
    332612    EXAMPLES: 
    333         sage: from sage.combinat.root_system.dynkin_diagram import dynkin_diagram 
    334         sage: dynkin_diagram(['A', 4]) 
    335         Multi-digraph on 4 vertices 
     613        sage: from sage.combinat.root_system.dynkin_diagram import type_g_affine 
     614        sage: ct = CartanType(['G',2,1]) 
     615        sage: g = type_g_affine(ct); g 
     616        Dynkin diagram of type ['G', 2, 1] 
     617        sage: e = g.edges(); e.sort(); e 
     618        [(0, 2, 1), (1, 2, 1), (2, 0, 1), (2, 1, 3)] 
    336619 
    337620    """ 
    338     import cartan_type 
    339     f = "type_" 
    340     letter = t[0].lower() 
    341     affine = "" 
    342     ct = cartan_type.CartanType(t) 
    343     if ct.is_affine(): 
    344         affine = "_affine" 
     621    precheck(t, letter="G", length=3, affine=1) 
     622    g = DynkinDiagram_class(t) 
     623    g.add_edge(1, 2) 
     624    g.set_edge_label(2,1,3) 
     625    g.add_edge(0, 2) 
     626    return g 
    345627 
    346     function = globals()[f+letter+affine] 
    347     try: 
    348         return function(t) 
    349     except KeyError: 
    350         raise TypeError, "Dynkin diagram data not yet hardcoded for type %s"%t 
     628def type_reducible(t): 
     629    """ 
     630    Returns a Dynkin diagram for type reducible. 
     631    EXAMPLES: 
     632      sage: t = CartanType("A2xB2xF4") 
     633      sage: dd = DynkinDiagram(t); dd 
     634      Dynkin diagram of type A2xB2xF4 
     635      sage: dd.edges() 
     636      [(1, 2, 1), (2, 1, 1), (3, 4, 2), (4, 3, 1), (5, 6, 1), (6, 5, 1), (6, 7, 2), (7, 6, 1), (7, 8, 1), (8, 7, 1)] 
    351637 
    352      
    353  
    354 def dynkin_diagram_as_function(t): 
    355638    """ 
    356     Returns a function corresponding to the Dynkin diagram of 
    357     type t.   
    358  
    359     EXAMPLES: 
    360         sage: from sage.combinat.root_system.dynkin_diagram import dynkin_diagram_as_function 
    361         sage: f = dynkin_diagram_as_function(['A',4]) 
    362         sage: f(1,1) 
    363         -2 
    364     """ 
    365     d = dynkin_diagram(t) 
    366     f = lambda i,j: -2 if i == j else ( len(filter(lambda x: x[1] == j, d.outgoing_edges(i))) if d.has_edge(i,j) else 0) 
    367  
    368     return f 
     639    g = DynkinDiagram_class(t) 
     640    g.add_vertices(t.index_set()) 
     641    for i in range(len(t._types)): 
     642        for [e1, e2, l] in DynkinDiagram(t._types[i]).edges(): 
     643            shift = t._rshifts[i] 
     644            g.add_edge(e1+shift, e2+shift, label=l) 
     645    return g 
     646             
     647             
  • new file sage/combinat/root_system/root_lattice_realization.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/root_lattice_realization.py
    - +  
     1#***************************************************************************** 
     2#       Copyright (C) 2007 Nicolas M. Thiery <nthiery at users.sf.net> 
     3# 
     4#  Distributed under the terms of the GNU General Public License (GPL) 
     5# 
     6#    This code is distributed in the hope that it will be useful, 
     7#    but WITHOUT ANY WARRANTY; without even the implied warranty of 
     8#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     9#    General Public License for more details. 
     10# 
     11#  The full text of the GPL is available at: 
     12# 
     13#                  http://www.gnu.org/licenses/ 
     14#***************************************************************************** 
     15from sage.combinat.family import Family 
     16 
     17class RootLatticeRealization: 
     18 
     19    def index_set(self): 
     20        return self.root_system.index_set() 
     21 
     22    def dynkin_diagram(self): 
     23        return self.root_system.dynkin_diagram() 
     24 
     25    ########################################################################## 
     26    # checks 
     27    ########################################################################## 
     28 
     29    def check(self): 
     30        alpha      = self.simple_roots() 
     31        alphacheck = self.simple_coroots() 
     32        dynkin_diagram = self.dynkin_diagram() 
     33        for i in self.index_set(): 
     34            for j in self.index_set(): 
     35                assert(alpha[j].scalar(alphacheck[i]) == dynkin_diagram[i,j]) 
     36 
     37    ########################################################################## 
     38    # highest root 
     39    ########################################################################## 
     40 
     41    def highest_root(self): 
     42        """ 
     43        Returns the highest root (for an irreducible finite root system) 
     44 
     45        EXAMPLES: 
     46        sage: RootSystem(['A',4]).ambient_space().highest_root() 
     47        (1, 0, 0, 0, -1) 
     48 
     49        sage: RootSystem(['E',6]).weight_space().highest_root() 
     50        Lambda[2] 
     51 
     52        """ 
     53        assert(self.root_system.is_finite()) 
     54        assert(self.root_system.is_irreducible()) 
     55        return self.a_long_simple_root().to_positive_chamber() 
     56 
     57    def a_long_simple_root(self): 
     58        """ 
     59        Returns a long simple root, corresponding to the highest outgoing edge 
     60        in the Dynkin diagram. 
     61 
     62        Caveat: This depends on a direct identification between dynkin diagram 
     63        nodes and the simple roots, which is not yet valid in the ambient space 
     64 
     65        Caveat: this may be break in affine type A_2n^(2) 
     66 
     67        Caveat: meaningful/broken for non irreducible? 
     68 
     69        TODO: implement DynkinDiagram.vertices_by_length as in 
     70        MuPAD-Combinat, and use it here 
     71         
     72        TESTS: 
     73            sage: X=RootSystem(['A',1]).weight_space() 
     74            sage: X.a_long_simple_root() 
     75            2*Lambda[1] 
     76            sage: X=RootSystem(['A',5]).weight_space() 
     77            sage: X.a_long_simple_root() 
     78            2*Lambda[1] - Lambda[2] 
     79        """ 
     80        if self.dynkin_diagram().rank() == 1: 
     81            return self.simple_roots()[self.index_set()[0]] 
     82        longest=self.dynkin_diagram().outgoing_edges()[0] 
     83        for j in self.dynkin_diagram().outgoing_edges(): 
     84            if j[2]>longest[2]: 
     85                longest=j 
     86        return self.simple_roots()[longest[0]] 
     87 
     88 
     89    ########################################################################## 
     90    # simple roots 
     91    ########################################################################## 
     92 
     93    def simple_root(self, i): 
     94        """ 
     95        Returns the $i$-th simple root 
     96        """ 
     97        raise NotImplementedError 
     98 
     99    def simple_roots(self): 
     100        """ 
     101        Returns the family $(\alpha_i)_{i\in I}$ of the simple roots 
     102        """ 
     103        if not hasattr(self,"_simple_roots"): 
     104            self._simple_roots = Family(self.index_set(), self.simple_root, name = "alpha") 
     105        return self._simple_roots 
     106 
     107    def alpha(self): 
     108        """ 
     109        Returns the family $(\alpha_i)_{i\in I}$ of the simple roots, 
     110        with the extra feature that, for simple irreducible root 
     111        systems, $\alpha_0$ yields the opposite of the highest root. 
     112        """ 
     113        if self.root_system.is_finite() and self.root_system.is_irreducible(): 
     114            return Family(self.index_set(), self.simple_root, \ 
     115                          hidden_keys = [0], hidden_function = lambda i: self.highest_root()) 
     116        else: 
     117            return self.simple_roots() 
     118 
     119    ########################################################################## 
     120    # roots 
     121    ########################################################################## 
     122 
     123    def roots(self): 
     124        """ 
     125        Returns the roots of self. 
     126         
     127        EXAMPLES: 
     128            sage: RootSystem(['A',2]).ambient_lattice().roots() 
     129            [(1, -1, 0), (1, 0, -1), (0, 1, -1), (-1, 1, 0), (-1, 0, 1), (0, -1, 1)] 
     130        """ 
     131        return self.positive_roots() + self.negative_roots() 
     132 
     133    ########################################################################## 
     134    # coroots 
     135    ########################################################################## 
     136 
     137    def coroot_lattice(self): 
     138        return self.root_system.coroot_lattice() 
     139 
     140    def simple_coroot(self, i): 
     141        return self.coroot_lattice().simple_root(i) 
     142 
     143    def simple_coroots(self): 
     144        """ 
     145        Returns the family $(\alpha^\vee_i)_{i\in I}$ of the simple coroots 
     146        """ 
     147        if not hasattr(self,"cache_simple_coroots"): 
     148            self.cache_simple_coroots = Family(self.index_set(), self.simple_coroot, name = "alphacheck") 
     149        return self.cache_simple_coroots 
     150 
     151    def alphacheck(self): 
     152        # TODO: remember 
     153        """ 
     154        Returns the family $(\alpha^\vee_i)_{i\in I}$ of the simple 
     155        coroots, with the extra feature that for simple irreducible 
     156        root systems, $\alpha^\vee_0$ yields the coroot associated to 
     157        the opposite of the highest root (caveat: this is usually not 
     158        the highest coroot!) 
     159        """ 
     160        if self.root_system.is_finite() and self.root_system.is_irreducible(): 
     161            return Family(self.index_set(), self.simple_coroot, \ 
     162                          hidden_keys = [0], hidden_function = lambda i: self.cohighest_root()) 
     163        else: 
     164            return self.simple_roots() 
     165 
     166    def cohighest_root(self): 
     167        # TODO: remember AND DOCUMENT 
     168        return self.highest_root.associated_coroot() 
     169 
     170    def associated_coroot(self, root): 
     171        """ 
     172        Returns the coroot associated to this root 
     173        EXAMPLES: 
     174            TODO 
     175        """ 
     176        assert(root in self.roots() != False) 
     177        raise NotImplementedError() 
     178 
     179    ########################################################################## 
     180    # reflections 
     181    ########################################################################## 
     182 
     183    def reflection(self, root, coroot=None): 
     184        """ 
     185        Returns the reflection along the root, and across the 
     186        hyperplane define by coroot, as a function from 
     187        self to self. 
     188         
     189        EXAMPLES: 
     190            sage: space = RootSystem(['A',2]).weight_lattice() 
     191            sage: x=space.simple_roots()[1] 
     192            sage: y=space.simple_coroots()[1] 
     193            sage: s = space.reflection(x,y) 
     194            sage: x 
     195            2*Lambda[1] - Lambda[2] 
     196            sage: s(x) 
     197            -2*Lambda[1] + Lambda[2] 
     198            sage: s(-x) 
     199            2*Lambda[1] - Lambda[2] 
     200        """ 
     201        if coroot is None: 
     202            coroot = root.associated_coroot() 
     203        return lambda v: v - v.scalar(coroot) * root 
     204 
     205    def simple_reflection(self, i): 
     206        # TODO: remember 
     207        """ 
     208        Returns the $i^{th}$ simple reflection, as a function from 
     209        self to self. 
     210         
     211        INPUT: 
     212            i -- i is in self's index set 
     213 
     214        EXAMPLES: 
     215            sage: space = RootSystem(['A',2]).ambient_lattice() 
     216            sage: s = space.simple_reflection(1) 
     217            sage: x = space.simple_roots()[1] 
     218            sage: x 
     219            (1, -1, 0) 
     220            sage: s(x) 
     221            (-1, 1, 0) 
     222        """ 
     223        return self.reflection(self.simple_root(i), self.simple_coroot(i)) 
     224 
     225    def simple_reflections(self): 
     226    # TODO: cache 
     227        """ 
     228        Returns the family $(s_i)_{i\in I}$ of the simple reflections 
     229        of this root system 
     230 
     231        EXAMPLES: 
     232            TODO 
     233        """ 
     234        return self.alpha().zip(self.reflection, self.alphacheck(), name = "s") 
     235 
     236    s = simple_reflections 
     237 
     238    ########################################################################## 
     239    # projections 
     240    ########################################################################## 
     241 
     242    def projection(self, root, coroot=None, to_negative=True): 
     243        """ 
     244        Returns the projection along the root, and across the 
     245        hyperplane define by coroot, as a function $\pi$ from self to 
     246        self. $\pi$ is a half-linear map which stabilizes the negative 
     247        half space, and acts by reflection on the positive half space. 
     248 
     249        If to_negative is False, then this project onto the positive 
     250        half space instead. 
     251 
     252        EXAMPLES: 
     253            sage: space = RootSystem(['A',2]).weight_lattice() 
     254            sage: x=space.simple_roots()[1] 
     255            sage: y=space.simple_coroots()[1] 
     256            sage: pi = space.projection(x,y) 
     257            sage: x 
     258            2*Lambda[1] - Lambda[2] 
     259            sage: pi(x) 
     260            -2*Lambda[1] + Lambda[2] 
     261            sage: pi(-x) 
     262            -2*Lambda[1] + Lambda[2] 
     263            sage: pi = space.projection(x,y,False) 
     264            sage: pi(-x) 
     265            2*Lambda[1] - Lambda[2] 
     266        """ 
     267        if coroot is None: 
     268            coroot = root.associated_coroot() 
     269        def projection(v): 
     270            if ((v.scalar(coroot) > 0) == to_negative): 
     271                return v - v.scalar(coroot) * root  
     272            else: 
     273                return v 
     274        return projection 
     275 
     276    def simple_projection(self, i, to_negative=True): 
     277        # TODO: remember 
     278        """ 
     279        Returns the projection along the $i^{th}$ simple root, and across the 
     280        hyperplane define by the $i^{th}$ simple coroot, as a function from 
     281        self to self. 
     282         
     283        INPUT: 
     284            i -- i is in self's index set 
     285 
     286        EXAMPLES: 
     287            sage: space = RootSystem(['A',2]).weight_lattice() 
     288            sage: x = space.simple_roots()[1] 
     289            sage: pi = space.simple_projection(1) 
     290            sage: x 
     291            2*Lambda[1] - Lambda[2] 
     292            sage: pi(x) 
     293            -2*Lambda[1] + Lambda[2] 
     294            sage: pi(-x) 
     295            -2*Lambda[1] + Lambda[2] 
     296            sage: pi = space.simple_projection(1,False) 
     297            sage: pi(-x) 
     298            2*Lambda[1] - Lambda[2] 
     299        """ 
     300        return self.projection(self.simple_root(i), self.simple_coroot(i), to_negative) 
     301 
     302    def simple_projections(self): 
     303    # TODO: cache 
     304        """ 
     305        Returns the family $(s_i)_{i\in I}$ of the simple projections 
     306        of this root system 
     307 
     308        EXAMPLES: 
     309            TODO 
     310        """ 
     311        return self.alpha().zip(self.projection, self.alphacheck(), name = "pi") 
     312 
     313    pi = simple_projections 
     314 
     315    ########################################################################## 
     316    # Weyl group 
     317    ########################################################################## 
     318 
     319    def weyl_group(self): 
     320        """ 
     321        Returns the Weyl group associated to self. 
     322 
     323        EXAMPLES: 
     324            sage: e = RootSystem(['F',4]).ambient_space() 
     325            sage: e.weyl_group() 
     326            The Weyl Group of type ['F', 4] 
     327        """ 
     328        from sage.combinat.root_system.weyl_group import WeylGroup 
     329        # FIXME: should return the Weyl group acting on that particular 
     330        # root lattice realization 
     331        # return WeylGroup(self) 
     332        return WeylGroup(self.root_system.cartan_type()) 
     333 
     334class RootLatticeRealizationElement: 
     335 
     336    def scalar(self, lambdacheck): 
     337        """ 
     338        The natural pairing between this and the coroot lattice. 
     339        """ 
     340        raise NotImplementedError 
     341 
     342 
     343    def simple_reflection(self, i): 
     344        """ 
     345        The image of self by the $i$-th simple reflection 
     346        """ 
     347        # Subclasses should optimize whenever possible! 
     348        return self.parent().simple_reflections()[i](self) 
     349 
     350    ########################################################################## 
     351    # Descents 
     352    ########################################################################## 
     353 
     354    def has_descent(self, i, positive=False): 
     355        """ 
     356        Test if self has a descent at position $i$, that is if self is 
     357        on the strict negative side of the $i$-th simple reflection 
     358        hyperplane. 
     359 
     360        If positive if True, tests if it is on the strict positive 
     361        side instead. 
     362 
     363        EXAMPLES: 
     364            sage: space=RootSystem(['A',5]).weight_space() 
     365            sage: alpha=RootSystem(['A',5]).weight_space().simple_roots() 
     366            sage: [alpha[i].has_descent(1) for i in space.index_set()] 
     367            [False, True, False, False, False] 
     368            sage: [(-alpha[i]).has_descent(1) for i in space.index_set()] 
     369            [True, False, False, False, False] 
     370            sage: [alpha[i].has_descent(1, True) for i in space.index_set()] 
     371            [True, False, False, False, False] 
     372            sage: [(-alpha[i]).has_descent(1, True) for i in space.index_set()] 
     373            [False, True, False, False, False] 
     374            sage: (alpha[1]+alpha[2]+alpha[4]).has_descent(3) 
     375            True 
     376            sage: (alpha[1]+alpha[2]+alpha[4]).has_descent(1) 
     377            False 
     378            sage: (alpha[1]+alpha[2]+alpha[4]).has_descent(1, True) 
     379            True 
     380        """ 
     381        s = self.scalar(self.parent().simple_coroots()[i]) 
     382        if positive: 
     383            return s > 0 
     384        else: 
     385            return s < 0 
     386 
     387    def first_descent(self, index_set=None, positive=False): 
     388        """ 
     389        Returns the first descent of pt 
     390 
     391        One can use the index_set option to restrict to the parabolic 
     392        subgroup indexed by index_set. 
     393 
     394        EXAMPLES: 
     395            sage: space=RootSystem(['A',5]).weight_space() 
     396            sage: alpha=space.simple_roots() 
     397            sage: (alpha[1]+alpha[2]+alpha[4]).first_descent() 
     398            3 
     399            sage: (alpha[1]+alpha[2]+alpha[4]).first_descent([1,2,5]) 
     400            5 
     401            sage: (alpha[1]+alpha[2]+alpha[4]).first_descent([1,2,5,3,4]) 
     402            5 
     403        """ 
     404        if index_set == None: 
     405            index_set = self.parent().index_set() 
     406        for i in index_set: 
     407            if self.has_descent(i, positive): 
     408                return i 
     409        return None 
     410 
     411    def descents(self, index_set=None, positive=False): 
     412        """ 
     413        Returns the descents of pt 
     414 
     415        EXAMPLES: 
     416            sage: space=RootSystem(['A',5]).weight_space() 
     417            sage: alpha=space.simple_roots() 
     418            sage: (alpha[1]+alpha[2]+alpha[4]).descents() 
     419            [3, 5] 
     420        """ 
     421        if index_set==None: 
     422            index_set=self.parent().index_set() 
     423        return [ i for i in index_set if self.has_descent(i, positive) ] 
     424     
     425    def to_positive_chamber(self, index_set = None, positive = True): 
     426        """ 
     427        Returns the unique element of the orbit of pt in the positive 
     428        chamber. 
     429 
     430        With the index_set optional parameter, this is done with 
     431        respect to the corresponding parbolic subgroup 
     432 
     433        With positive = False, returns the unique element in the 
     434        negative chamber instead 
     435         
     436     
     437        EXAMPLES: 
     438            sage: space=RootSystem(['A',5]).weight_space() 
     439            sage: alpha=RootSystem(['A',5]).weight_space().simple_roots() 
     440            sage: alpha[1].to_positive_chamber() 
     441            Lambda[1] + Lambda[5] 
     442            sage: alpha[1].to_positive_chamber([1,2]) 
     443            Lambda[1] + Lambda[2] - Lambda[3] 
     444        """ 
     445        if index_set==None: 
     446            index_set=self.parent().index_set() 
     447        while True: 
     448            # The first index where it is *not* yet on the positive side 
     449            i = self.first_descent(index_set, positive=not positive) 
     450            if i is None: 
     451                return self 
     452            else: 
     453                self = self.simple_reflection(i) 
     454 
     455    def is_dominant(self, index_set = None, positive = True): 
     456        """ 
     457        Returns whether self is dominant. 
     458 
     459        With positive = False, returns whether self is antidominant 
     460         
     461        INPUT: 
     462            v -- an element of the lattice 
     463 
     464        EXAMPLES: 
     465            sage: L = RootSystem(['A',2]).ambient_lattice() 
     466            sage: Lambda = L.fundamental_weights() 
     467            sage: [x.is_dominant() for x in Lambda] 
     468            [True, True] 
     469            sage: [x.is_dominant(positive=False) for x in Lambda] 
     470            [False, False] 
     471            sage: (Lambda[1]-Lambda[2]).is_dominant() 
     472            False 
     473            sage: (-Lambda[1]+Lambda[2]).is_dominant() 
     474            False 
     475            sage: (Lambda[1]-Lambda[2]).is_dominant([1]) 
     476            True 
     477            sage: (Lambda[1]-Lambda[2]).is_dominant([2]) 
     478            False 
     479            sage: [x.is_dominant() for x in L.roots()] 
     480            [False, True, False, False, False, False] 
     481            sage: [x.is_dominant(positive=False) for x in L.roots()] 
     482            [False, False, False, False, True, False] 
     483        """ 
     484        return self.first_descent(index_set, not positive) is None 
  • new file sage/combinat/root_system/root_space.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/root_space.py
    - +  
     1#***************************************************************************** 
     2#       Copyright (C) 2007 Nicolas M. Thiery <nthiery at users.sf.net> 
     3# 
     4#  Distributed under the terms of the GNU General Public License (GPL) 
     5# 
     6#    This code is distributed in the hope that it will be useful, 
     7#    but WITHOUT ANY WARRANTY; without even the implied warranty of 
     8#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     9#    General Public License for more details. 
     10# 
     11#  The full text of the GPL is available at: 
     12# 
     13#                  http://www.gnu.org/licenses/ 
     14#***************************************************************************** 
     15 
     16from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement 
     17from root_lattice_realization import RootLatticeRealization, RootLatticeRealizationElement 
     18from sage.rings.all import ZZ 
     19 
     20 
     21class RootSpace(CombinatorialFreeModule, RootLatticeRealization): 
     22 
     23    def __init__(self, root_system, base_ring): 
     24        self.root_system = root_system 
     25        basis_name = "alphacheck" if root_system.dualSide else "alpha" 
     26        CombinatorialFreeModule.__init__(self, base_ring,\ 
     27                                         root_system.index_set(),\ 
     28                                         element_class = RootSpaceElement,\ 
     29                                         prefix=basis_name) 
     30        # This would be more efficient, but this is not used intensively, 
     31        # and we would have to be careful with pickling: 
     32        # self.simple_root = self.basis().__getitem__ 
     33 
     34    def simple_root(self, i): 
     35        return self.basis()[i] 
     36 
     37    def __repr__(self): 
     38        """ 
     39        TEST: 
     40            sage: RootSystem(['A',4]).root_lattice() 
     41            The root lattice of the Root system of type ['A', 4] 
     42            sage: RootSystem(['B',4]).root_space() 
     43            The root space over the Rational Field of the Root system of type ['B', 4] 
     44            sage: RootSystem(['A',4]).coroot_lattice() 
     45            The coroot lattice of the Root system of type ['A', 4] 
     46            sage: RootSystem(['B',4]).coroot_space() 
     47            The coroot space over the Rational Field of the Root system of type ['B', 4] 
     48 
     49        """ 
     50        return "The %s"%self.root_system.dualString+\ 
     51               ("root lattice " if self.base_ring() == ZZ else "root space over the %s "%self.base_ring())+\ 
     52               "of the %s"%(self.root_system.dual if self.root_system.dualSide else self.root_system) 
     53 
     54    simple_roots = CombinatorialFreeModule.basis 
     55     
     56 
     57class RootSpaceElement(CombinatorialFreeModuleElement, RootLatticeRealizationElement): 
     58 
     59    def scalar(self, lambdacheck): 
     60        """ 
     61        The scalar product between the root lattice and 
     62        the coroot lattice. 
     63        """ 
     64        zero = self.parent().base_ring().zero_element() 
     65        cartan_matrix = self.parent().dynkin_diagram() 
     66        return sum( (sum( (lambdacheck[i]*s for (i,s) in cartan_matrix.column(j)), zero) * c 
     67                         for (j,c) in self), zero) 
     68 
  • sage/combinat/root_system/root_system.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/root_system.py
    a b  
    44#***************************************************************************** 
    55#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,  
    66#                          Justin Walker <justin at mac.com> 
     7#                          Nicolas M. Thiery <nthiery at users.sf.net> 
    78# 
    89#  Distributed under the terms of the GNU General Public License (GPL) 
    910# 
     
    1617# 
    1718#                  http://www.gnu.org/licenses/ 
    1819#***************************************************************************** 
    19 import cartan_type  
    20 from sage.modules.free_module import FreeModule 
    21 from sage.rings.all import ZZ 
    22 from sage.misc.misc import prod 
     20# Design largely inspired from MuPAD-Combinat 
    2321 
    24 def RootSystem(t): 
    25     """ 
     22from cartan_type import CartanType 
     23from sage.rings.all import ZZ, QQ 
     24from sage import combinat 
     25from root_space import RootSpace 
     26from weight_space import WeightSpace 
     27import type_A 
     28import type_B 
     29import type_C 
     30import type_D 
     31import type_E 
     32import type_F 
     33import type_G 
     34import type_dual 
     35import type_reducible 
     36import type_None 
     37 
     38class RootSystem: 
     39    r""" 
    2640    Returns the root system associated to the Cartan type t. 
    2741     
    2842    EXAMPLES: 
    29         sage: RootSystem(['A',3]) 
    30         Root system of type ['A', 3] 
     43      We construct the root system for type $B_3$ 
     44 
     45        sage: R=RootSystem(['B',3]); R 
     46        Root system of type ['B', 3] 
     47 
     48      R models the root system abstractly. It comes equipped with 
     49      various realizations of the root and weight lattices, where all 
     50      computation take place. Let us play first with the root lattice. 
     51 
     52        sage: space = R.root_lattice() 
     53        sage: space 
     54        The root lattice of the Root system of type ['B', 3] 
     55 
     56      It is the free \ZZ module $\bigoplus_i \ZZ.\alpha_i$ spanned by 
     57      the simple roots: 
     58         
     59        sage: space.base_ring() 
     60        Integer Ring 
     61        sage: list(space.basis())  
     62        [alpha[1], alpha[2], alpha[3]] 
     63         
     64      Let us do some computations with the simple roots: 
     65 
     66        sage: alpha = space.simple_roots() 
     67        sage: alpha[1] + alpha[2] 
     68        alpha[1] + alpha[2] 
     69 
     70      There is a canonical pairing between the root lattice and the 
     71      coroot lattice: 
     72        sage: R.coroot_lattice() 
     73        The coroot lattice of the Root system of type ['B', 3] 
     74 
     75      We construct the simple coroots, and do some computations (see 
     76      comments about duality below for some caveat). 
     77        sage: alphacheck = space.simple_coroots() 
     78        sage: list(alphacheck) 
     79        [alphacheck[1], alphacheck[2], alphacheck[3]] 
     80 
     81 
     82      We can carry over the same computations in any of the other 
     83      realizations of the root lattice, like the root space 
     84      $\bigoplus_i \QQ.\alpha_i$, the weight lattice $\bigoplus_i 
     85      \ZZ.\Lambda_i$, the weight space $\bigoplus_i \QQ.\Lambda_i$. 
     86      For example: 
     87 
     88        sage: space = R.weight_space() 
     89        sage: space 
     90        The weight space over the Rational Field of the Root system of type ['B', 3] 
     91 
     92        sage: space.base_ring() 
     93        Rational Field 
     94        sage: list(space.basis()) 
     95        [Lambda[1], Lambda[2], Lambda[3]] 
     96 
     97        sage: alpha = space.simple_roots() 
     98        sage: alpha[1] + alpha[2] 
     99        Lambda[1] + Lambda[2] - 2*Lambda[3] 
     100 
     101      The fundamental weights are the dual basis of the coroots: 
     102 
     103        sage: Lambda = space.fundamental_weights() 
     104        sage: Lambda[1] 
     105        Lambda[1] 
     106 
     107        sage: alphacheck = space.simple_coroots() 
     108        sage: list(alphacheck) 
     109        [alphacheck[1], alphacheck[2], alphacheck[3]] 
     110 
     111        sage: [Lambda[i].scalar(alphacheck[1]) for i in space.index_set()] 
     112        [1, 0, 0] 
     113        sage: [Lambda[i].scalar(alphacheck[2]) for i in space.index_set()] 
     114        [0, 1, 0] 
     115        sage: [Lambda[i].scalar(alphacheck[3]) for i in space.index_set()] 
     116        [0, 0, 1] 
     117 
     118      Let us us use the simple reflections. In the weight space, they 
     119      work as in the \emph{number game}: firing the node $i$ on an 
     120      element x adds $c$ times the simple root $\alpha_i$, where $c$ 
     121      is the coefficient of $i$ in $x$: 
     122       
     123        sage: s = space.simple_reflections() 
     124        sage: Lambda[1].simple_reflection(1) 
     125        -Lambda[1] + Lambda[2] 
     126        sage: Lambda[2].simple_reflection(1) 
     127        Lambda[2] 
     128        sage: Lambda[3].simple_reflection(1) 
     129        Lambda[3] 
     130        sage: (-2*Lambda[1] + Lambda[2] + Lambda[3]).simple_reflection(1) 
     131        2*Lambda[1] - Lambda[2] + Lambda[3] 
     132 
     133      It can be convenient to manipulate the simple reflections 
     134      themselves: 
     135 
     136        sage: s = space.simple_reflections() 
     137        sage: s[1](Lambda[1]) 
     138        -Lambda[1] + Lambda[2] 
     139        sage: s[1](Lambda[2]) 
     140        Lambda[2] 
     141        sage: s[1](Lambda[3]) 
     142        Lambda[3] 
     143 
     144      The root system may also come equipped with an ambient space, 
     145      that is a simultaneous realization of the weight lattice and the 
     146      coroot lattice in an euclidean vector space. This is implemented 
     147      on a type by type basis, and is not always available. When the 
     148      coefficients permit it, this is also available as an ambient 
     149      lattice. 
     150 
     151      TODO: Demo: signed permutations realization of type B 
     152       
     153 
     154 
     155      The root system is aware of its dual root system: 
     156        sage: R.dual 
     157        Dual of root system of type ['B', 3] 
     158 
     159      R.dual is really the root system of type $C_3$: 
     160        sage: R.dual.cartan_type() 
     161        ['C', 3] 
     162 
     163      And the coroot lattice that we have been manipulating before is 
     164      really implemented as the root lattice of the dual root system: 
     165 
     166        sage: R.dual.root_lattice() 
     167        The coroot lattice of the Root system of type ['B', 3] 
     168 
     169      In particular, the coroots for the root lattice are in fact the 
     170      roots of the coroot lattice: 
     171 
     172        sage: list(R.root_lattice().simple_coroots()) 
     173        [alphacheck[1], alphacheck[2], alphacheck[3]] 
     174        sage: list(R.coroot_lattice().simple_roots()) 
     175        [alphacheck[1], alphacheck[2], alphacheck[3]] 
     176        sage: list(R.dual.root_lattice().simple_roots()) 
     177        [alphacheck[1], alphacheck[2], alphacheck[3]] 
     178 
     179      The coweight lattice and space are defined similarly. Note 
     180      that, to limit confusion, all the output have been tweaked 
     181      appropriately. 
     182 
     183 
     184    TESTS: 
     185 
     186        sage: R = RootSystem(['C',3]) 
     187        sage: R == loads(dumps(R)) 
     188        True 
     189        sage: L = R.ambient_space() 
     190        sage: s = L.simple_reflections() 
     191        sage: s = L.simple_projections() # todo: not implemented 
     192        sage: L == loads(dumps(L)) 
     193        True 
     194        sage: L = R.root_space() 
     195        sage: s = L.simple_reflections() 
     196        sage: L == loads(dumps(L)) 
     197        True 
     198 
     199        sage: for T in CartanType.samples(finite=True,crystalographic=True): 
     200        ...       RootSystem(T).check() 
    31201    """ 
    32     ct = cartan_type.CartanType(t) 
    33     if not ct.affine: 
    34         typ = ct.type() 
    35         if typ == "A": 
    36             return RootSystem_a(ct) 
    37         elif typ == "B": 
    38             return RootSystem_b(ct) 
    39         elif typ == "C": 
    40             return RootSystem_c(ct) 
    41         elif typ == "D": 
    42             return RootSystem_d(ct) 
    43         elif typ == "E": 
    44             return RootSystem_e(ct) 
    45         elif typ == "F": 
    46             return RootSystem_f(ct) 
    47         elif typ == "G": 
    48             return RootSystem_g(ct) 
    49     else: 
    50         return RootSystem_generic(ct) 
     202 
     203    def check(self): 
     204        self.root_lattice().check() 
     205        self.root_space  ().check() 
     206        self.weight_lattice().check() 
     207        self.weight_space().check() 
     208        if not self.ambient_lattice() is None: 
     209            self.ambient_lattice().check() 
     210        if not self.ambient_space() is None: 
     211            self.ambient_space().check() 
    51212     
    52 class RootSystem_generic: 
    53     def __init__(self, ct): 
     213    def __init__(self, cartan_type, asDualOf=None): 
    54214        """ 
    55215        TESTS: 
    56216            sage: R = RootSystem(['A',3]) 
    57             sage: loads(dumps(R)) 
     217            sage: R 
    58218            Root system of type ['A', 3] 
    59219        """ 
    60         self.ct = ct 
     220        self._cartan_type = CartanType(cartan_type) 
     221 
     222        # Get the python module containing type-specific information, 
     223        # if it exists 
     224        self.tools = getattr(combinat.root_system, 
     225                             self._cartan_type.type_string(), 
     226                             combinat.root_system.type_None); 
     227 
     228        # Duality 
     229        # The root system can be defined as dual of another root system. This will 
     230        # only affects the pretty printing 
     231        if asDualOf == None: 
     232            self.dual = RootSystem(self._cartan_type.dual(), asDualOf=self); 
     233            self.dualSide = False 
     234            self.dualString = "" 
     235        else: 
     236            self.dual = asDualOf 
     237            self.dualSide = True 
     238            self.dualString = "co" 
    61239 
    62240    def __repr__(self): 
    63241        """ 
     
    65243            sage: RootSystem(['A',3]) 
    66244            Root system of type ['A', 3] 
    67245        """ 
    68         return "Root system of type %s"%self.ct 
     246        if self.dualSide: 
     247            return "Dual of root system of type %s"%self.dual.cartan_type() 
     248        else: 
     249            return "Root system of type %s"%self.cartan_type() 
    69250 
    70251    def cartan_type(self): 
    71252        """ 
     
    76257            sage: R.cartan_type() 
    77258            ['A', 3] 
    78259        """ 
    79         return self.ct 
     260        return self._cartan_type 
    80261 
     262    # TODO: remember 
     263    def dynkin_diagram(self): 
     264        """ 
     265        Returns the Dynkin diagram of the root system. 
     266         
     267        EXAMPLES: 
     268            sage: R = RootSystem(['A',3]) 
     269            sage: R.dynkin_diagram() 
     270            Dynkin diagram of type ['A', 3] 
     271        """ 
     272        return self.cartan_type().dynkin_diagram() 
     273 
     274    # TODO: remember 
    81275    def cartan_matrix(self): 
    82276        """ 
    83277        EXAMPLES: 
     
    96290        """ 
    97291        return self.cartan_type().index_set() 
    98292 
     293    def is_finite(self): 
     294        # TODO: remember 
     295        return self.cartan_type().is_finite() 
     296 
     297    def is_irreducible(self): 
     298        # TODO: remember 
     299        return self.cartan_type().is_irreducible() 
     300 
    99301    def __cmp__(self, other): 
    100302        """ 
    101303        EXAMPLES: 
     
    108310        """ 
    109311        if self.__class__ != other.__class__: 
    110312            return cmp(self.__class__, other.__class__) 
    111         if self.ct != other.ct: 
    112             return cmp(self.ct, other.ct) 
     313        if self._cartan_type != other._cartan_type: 
     314            return cmp(self._cartan_type, other._cartan_type) 
    113315        return 0 
     316 
     317 
     318    def root_lattice(self): 
     319        return self.root_space(ZZ) 
     320 
     321    def root_space(self, base_ring = QQ): 
     322        return RootSpace(self, base_ring) 
     323 
     324    def coroot_lattice(self): 
     325        return self.dual.root_lattice() 
    114326     
    115 class RootSystem_a(RootSystem_generic): 
     327    def coroot_space(self, base_ring = QQ): 
     328        return self.dual.root_space(base_ring) 
     329 
     330 
     331    def weight_lattice(self): 
     332        return self.weight_space(ZZ) 
     333 
     334    def weight_space(self, base_ring = QQ): 
     335        return WeightSpace(self, base_ring) 
     336 
     337    def coweight_lattice(self): 
     338        return self.dual.weight_lattice() 
     339     
     340    def coweight_space(self, base_ring = QQ): 
     341        return self.dual.weight_space(base_ring) 
     342 
     343 
    116344    def ambient_lattice(self): 
    117         """ 
     345        r""" 
     346        Returns the usual ambient lattice for this root_system, if it 
     347        exists and is implemented, and None otherwise. This is a 
     348        Z-module, endowed with its canonical euclidean scalar product, 
     349        which embeds simultaneously the root lattice and the coroot 
     350        lattice (what about the weight lattice?) 
     351         
    118352        EXAMPLES: 
    119353            sage: RootSystem(['A',4]).ambient_lattice() 
    120             Ambient lattice of the root system of type ['A', 4] 
     354            Ambient lattice for the Root system of type ['A', 4] 
     355 
     356            sage: RootSystem(['B',4]).ambient_lattice() 
     357            sage: RootSystem(['C',4]).ambient_lattice() 
     358            sage: RootSystem(['D',4]).ambient_lattice() 
     359            sage: RootSystem(['E',6]).ambient_lattice() 
     360            sage: RootSystem(['F',4]).ambient_lattice() 
     361            sage: RootSystem(['G',2]).ambient_lattice() 
    121362        """ 
    122         return AmbientLattice_a(self.ct) 
     363        return self.ambient_space(ZZ) 
    123364 
    124 class RootSystem_b(RootSystem_generic): 
    125     def ambient_lattice(self): 
     365    def ambient_space(self, base_ring=QQ): 
    126366        """ 
    127         EXAMPLES: 
    128             sage: RootSystem(['B',4]).ambient_lattice() 
    129             Ambient lattice of the root system of type ['B', 4] 
    130         """ 
    131         return AmbientLattice_b(self.ct) 
    132  
    133 class RootSystem_c(RootSystem_generic): 
    134     def ambient_lattice(self): 
    135         """ 
    136         EXAMPLES: 
    137             sage: RootSystem(['C',4]).ambient_lattice() 
    138             Ambient lattice of the root system of type ['C', 4] 
    139         """ 
    140         return AmbientLattice_c(self.ct) 
    141  
    142 class RootSystem_d(RootSystem_generic): 
    143     def ambient_lattice(self): 
    144         """ 
    145         EXAMPLES: 
    146             sage: RootSystem(['D',4]).ambient_lattice() 
    147             Ambient lattice of the root system of type ['D', 4] 
    148         """ 
    149         return AmbientLattice_d(self.ct) 
    150  
    151 class RootSystem_e(RootSystem_generic): 
    152     def ambient_lattice(self): 
    153         """ 
    154         EXAMPLES: 
    155             sage: RootSystem(['E',6]).ambient_lattice() 
    156             Ambient lattice of the root system of type ['E', 6] 
    157         """ 
    158         return AmbientLattice_e(self.ct) 
    159  
    160 class RootSystem_f(RootSystem_generic): 
    161     def ambient_lattice(self): 
    162         """ 
    163         EXAMPLES: 
    164             sage: RootSystem(['F',4]).ambient_lattice() 
    165             Ambient lattice of the root system of type ['F', 4] 
    166         """         
    167         return AmbientLattice_f(self.ct) 
    168  
    169 class RootSystem_g(RootSystem_generic): 
    170     def ambient_lattice(self): 
    171         """ 
    172         EXAMPLES: 
    173             sage: RootSystem(['G',2]).ambient_lattice() 
    174             Ambient lattice of the root system of type ['G', 2] 
    175         """         
    176         return AmbientLattice_g(self.ct) 
    177  
    178  
    179  
    180 class WeightLatticeRealization_class: 
    181     # Should this be a method or an attribute? 
    182     # same question for the roots, ... 
    183     def rho(self): 
    184         """ 
    185         EXAMPLES: 
    186             sage: RootSystem(['A',3]).ambient_lattice().rho() 
    187             (3, 2, 1, 0) 
    188         """ 
    189         return sum(self.fundamental_weights()) 
    190  
    191     # Should it be a method of highest_weight? 
    192     def weyl_dimension(self, highest_weight): 
    193         """ 
    194         EXAMPLES: 
    195             sage: hwv = vector([2,1,0,0]) 
    196             sage: RootSystem(['A',3]).ambient_lattice().weyl_dimension(hwv) 
    197             20 
    198         """ 
    199         # Should assert(highest_weight.is_dominant()) 
    200         rho = self.rho() 
    201         n = prod([(rho+highest_weight).dot_product(x) for x in self.positive_roots()]) 
    202         d = prod([ rho.dot_product(x) for x in self.positive_roots()]) 
    203         return n/d 
    204  
    205     def highest_root(self): 
    206         """ 
    207         EXAMPLES: 
    208             sage: RootSystem(['E',6]).ambient_lattice().highest_root() 
    209             (1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2, 1/2) 
    210         """ 
    211         for alp in self.positive_roots(): 
    212             if all(not(alp+bet in self.positive_roots()) for bet in self.positive_roots()): 
    213                 return alp 
    214  
    215     def simple_reflection(self, i, v): 
    216         """ 
    217         Returns the $i^{th}$ simple reflection applied to v, an element 
    218         of the lattice. 
    219          
    220         INPUT: 
    221             i -- i is in self's index set 
    222             v -- an element of the lattice 
    223  
    224         EXAMPLES: 
    225             sage: e = RootSystem(['A',2]).ambient_lattice() 
    226             sage: v = e.simple_roots()[0] 
    227             sage: e.simple_reflection(1, v) 
    228             (-1, 1, 0) 
    229         """ 
    230         alpha = self.simple_roots()[i-1] 
    231         return v-2*alpha.inner_product(v)/alpha.inner_product(alpha)*alpha 
    232  
    233     def weyl_group(self): 
    234         """ 
    235         Returns the Weyl group associated to self. 
    236  
    237         EXAMPLES: 
    238             sage: e = RootSystem(['F',4]).ambient_lattice() 
    239             sage: e.weyl_group() 
    240             The Weyl Group of type ['F', 4] 
    241         """ 
    242         from sage.combinat.root_system.weyl_group import WeylGroup 
    243         return WeylGroup(self.ct) 
    244  
    245     def is_dominant(self, v): 
    246         """ 
    247         Returns True if v is dominant. 
    248  
    249         INPUT: 
    250             v -- an element of the lattice 
    251  
    252         EXAMPLES: 
    253             sage: L = RootSystem(['A',2]).ambient_lattice() 
    254             sage: [L.is_dominant(x) for x in L.roots()] 
    255             [False, True, False, False, False, False] 
    256         """ 
    257         for alph in self.positive_roots(): 
    258             if v.inner_product(alph) < 0: 
    259                 return False 
    260         return True 
    261  
    262  
    263 class AmbientLattice_generic(WeightLatticeRealization_class): 
    264     def __init__(self, ct): 
    265         """ 
    266         EXAMPLES: 
    267             sage: e = RootSystem(['A',3]).ambient_lattice() 
    268             sage: e == loads(dumps(e)) 
    269             True 
    270         """ 
    271         if not hasattr(self, 'n'): 
    272             self.n  = ct.rank() 
    273         self.ct = ct 
    274         self._free_module = FreeModule(ZZ, self.n) 
    275  
    276     def __repr__(self): 
    277         """ 
    278         EXAMPLES: 
    279             sage: RootSystem(['B',4]).ambient_lattice() 
    280             Ambient lattice of the root system of type ['B', 4] 
    281  
    282         """ 
    283         return "Ambient lattice of the root system of type %s"%self.ct 
    284  
    285     def __getitem__(self,i): 
    286         """ 
    287         Note that indexing starts at 1. 
     367        Returns the usual ambient space for this root_system, if it is 
     368        implemented, and None otherwise. This is a QQ-module, endowed 
     369        with its canonical euclidean scalar product, which embeds 
     370        simultaneously the root lattice and the coroot lattice (what 
     371        about the weight lattice?). An alternative base ring can be 
     372        provided as an option; it must contain the smallest ring over 
     373        which the ambient space can be defined (ZZ or QQ, depending on 
     374        the type). 
    288375         
    289376        EXAMPLES: 
    290             sage: e = RootSystem(['A',2]).ambient_lattice() 
    291             sage: e[1] 
    292             (1, 0, 0) 
     377            sage: RootSystem(['A',4]).ambient_space() 
     378            Ambient space for the Root system of type ['A', 4] 
     379 
     380            sage: RootSystem(['B',4]).ambient_space() 
     381            Ambient space for the Root system of type ['B', 4] 
     382 
     383            sage: RootSystem(['C',4]).ambient_space() 
     384            Ambient space for the Root system of type ['C', 4] 
     385 
     386            sage: RootSystem(['D',4]).ambient_space() 
     387            Ambient space for the Root system of type ['D', 4] 
     388 
     389            sage: RootSystem(['E',6]).ambient_space() 
     390            Ambient space for the Root system of type ['E', 6] 
     391 
     392            sage: RootSystem(['F',4]).ambient_space() 
     393            Ambient space for the Root system of type ['F', 4] 
     394 
     395            sage: RootSystem(['G',2]).ambient_space() 
     396            Ambient space for the Root system of type ['G', 2] 
    293397        """ 
    294         return self._term(i-1) 
    295  
    296     def roots(self): 
    297         """ 
    298         Returns the roots of self. 
    299          
    300         EXAMPLES: 
    301             sage: RootSystem(['A',2]).ambient_lattice().roots() 
    302             [(1, -1, 0), (1, 0, -1), (0, 1, -1), (-1, 1, 0), (-1, 0, 1), (0, -1, 1)] 
    303         """ 
    304         return self.positive_roots() + self.negative_roots() 
    305  
    306     def _term(self, i): 
    307         """ 
    308         Note that indexing starts at 0. 
    309  
    310         EXAMPLES: 
    311             sage: e = RootSystem(['A',2]).ambient_lattice() 
    312             sage: e._term(0) 
    313             (1, 0, 0) 
    314         """ 
    315         return self._free_module.gen(i) 
    316  
    317     def __cmp__(self, other): 
    318         """ 
    319         EXAMPLES: 
    320             sage: e1 = RootSystem(['A',3]).ambient_lattice() 
    321             sage: e2 = RootSystem(['B',3]).ambient_lattice() 
    322             sage: e1 == e1 
    323             True 
    324             sage: e1 == e2 
    325             False 
    326         """ 
    327         if self.__class__ != other.__class__: 
    328             return cmp(self.__class__, other.__class__) 
    329         if self.ct != other.ct: 
    330             return cmp(self.ct, other.ct) 
    331         return 0 
     398        # Intention: check that the ambient_space is implemented and that 
     399        # base_ring contains the smallest base ring for this ambient space 
     400        if not self.tools.__dict__.has_key("ambient_space") or \ 
     401            (base_ring == ZZ and self.tools.ambient_space.smallest_base_ring() == QQ): 
     402            return None 
     403        else: 
     404            return self.tools.ambient_space(self, base_ring) 
    332405     
    333 class AmbientLattice_a(AmbientLattice_generic): 
    334     def __init__(self, ct): 
    335         """ 
    336         EXAMPLES: 
    337             sage: e = RootSystem(['A',3]).ambient_lattice() 
    338             sage: e.n 
    339             4 
    340         """ 
    341         self.n  = ct.rank()+1 
    342         AmbientLattice_generic.__init__(self, ct) 
    343          
    344     def root(self, i, j): 
    345         """ 
    346         Note that indexing starts at 0. 
    347          
    348         EXAMPLES: 
    349             sage: e = RootSystem(['A',3]).ambient_lattice() 
    350             sage: e.root(0,1) 
    351             (1, -1, 0, 0) 
    352         """ 
    353         return self._term(i) - self._term(j) 
    354  
    355     def simple_roots(self): 
    356         """ 
    357         EXAMPLES: 
    358             sage: e = CartanType(['A',3]).root_system().ambient_lattice() 
    359             sage: e.simple_roots() 
    360             [(1, -1, 0, 0), (0, 1, -1, 0), (0, 0, 1, -1)] 
    361         """ 
    362         return [ self.root(i, i+1) for i in range(self.n-1) ] 
    363  
    364     def negative_roots(self): 
    365         """ 
    366         EXAMPLES: 
    367             sage: e = CartanType(['A',3]).root_system().ambient_lattice() 
    368             sage: e.negative_roots() 
    369             [(-1, 1, 0, 0), 
    370              (-1, 0, 1, 0), 
    371              (-1, 0, 0, 1), 
    372              (0, -1, 1, 0), 
    373              (0, -1, 0, 1), 
    374              (0, 0, -1, 1)] 
    375         """ 
    376         res = [] 
    377         for j in range(self.n-1): 
    378             for i in range(j+1,self.n): 
    379                 res.append(  self.root(i,j) ) 
    380         return res 
    381  
    382     def positive_roots(self): 
    383         """ 
    384         EXAMPLES: 
    385             sage: e = CartanType(['A',3]).root_system().ambient_lattice() 
    386             sage: e.positive_roots() 
    387             [(1, -1, 0, 0), 
    388              (1, 0, -1, 0), 
    389              (0, 1, -1, 0), 
    390              (1, 0, 0, -1), 
    391              (0, 1, 0, -1), 
    392              (0, 0, 1, -1)] 
    393               
    394         """         
    395         res = [] 
    396         for j in range(self.n): 
    397             for i in range(j): 
    398                 res.append(  self.root(i,j) ) 
    399         return res 
    400  
    401     def highest_root(self): 
    402         """ 
    403         EXAMPLE: 
    404            sage: e = CartanType(['A',3]).root_system().ambient_lattice() 
    405            sage: e.highest_root() 
    406            (1, 0, 0, -1) 
    407         """ 
    408         return self.root(0,self.n-1) 
    409  
    410     def fundamental_weights(self): 
    411         """ 
    412         EXAMPLES: 
    413             sage: e = CartanType(['A',3]).root_system().ambient_lattice() 
    414             sage: e.fundamental_weights() 
    415             [(1, 0, 0, 0), (1, 1, 0, 0), (1, 1, 1, 0)] 
    416  
    417         """ 
    418         return [ sum([self._term(j) for j in range(i+1)]) for i in range(self.n-1)] 
    419  
    420 class AmbientLattice_b(AmbientLattice_generic): 
    421     def root(self, i, j): 
    422         """ 
    423         Note that indexing starts at 0. 
    424          
    425         EXAMPLES: 
    426             sage: e = RootSystem(['B',3]).ambient_lattice() 
    427             sage: e.root(0,1) 
    428             (1, -1, 0) 
    429              
    430         """ 
    431         return self._term(i) - self._term(j) 
    432      
    433     def simple_roots(self): 
    434         """ 
    435         EXAMPLES: 
    436             sage: e = RootSystem(['B',4]).ambient_lattice() 
    437             sage: e.simple_roots() 
    438             [(1, -1, 0, 0), (0, 1, -1, 0), (0, 0, 1, -1), (0, 0, 0, 1)] 
    439             sage: e.positive_roots() 
    440             [(1, -1, 0, 0), 
    441             (1, 1, 0, 0), 
    442             (1, 0, -1, 0), 
    443             (1, 0, 1, 0), 
    444             (1, 0, 0, -1), 
    445             (1, 0, 0, 1), 
    446             (0, 1, -1, 0), 
    447             (0, 1, 1, 0), 
    448             (0, 1, 0, -1), 
    449             (0, 1, 0, 1), 
    450             (0, 0, 1, -1), 
    451             (0, 0, 1, 1), 
    452             (1, 0, 0, 0), 
    453             (0, 1, 0, 0), 
    454             (0, 0, 1, 0), 
    455             (0, 0, 0, 1)] 
    456             sage: e.fundamental_weights() 
    457             [(1, 0, 0, 0), (1, 1, 0, 0), (1, 1, 1, 0), (1/2, 1/2, 1/2, 1/2)] 
    458              
    459         """ 
    460         return [ self.root(i,i+1) for i in range(self.n-1) ] + [ self._term(self.n-1) ] 
    461  
    462     def negative_roots(self): 
    463         """ 
    464         EXAMPLES: 
    465             sage: RootSystem(['B',3]).ambient_lattice().negative_roots() 
    466             [(-1, 1, 0), 
    467              (-1, -1, 0), 
    468              (-1, 0, 1), 
    469              (-1, 0, -1), 
    470              (0, -1, 1), 
    471              (0, -1, -1), 
    472              (-1, 0, 0), 
    473              (0, -1, 0), 
    474              (0, 0, -1)] 
    475               
    476         """ 
    477         return [ -a for a in self.positive_roots()] 
    478  
    479  
    480     def positive_roots(self): 
    481         """ 
    482         EXAMPLES: 
    483             sage: RootSystem(['B',3]).ambient_lattice().positive_roots() 
    484             [(1, -1, 0), 
    485              (1, 1, 0), 
    486              (1, 0, -1), 
    487              (1, 0, 1), 
    488              (0, 1, -1), 
    489              (0, 1, 1), 
    490              (1, 0, 0), 
    491              (0, 1, 0), 
    492              (0, 0, 1)] 
    493               
    494         """ 
    495         res = [] 
    496         for i in range(self.n-1): 
    497             for j in range(i+1,self.n): 
    498                 res.append(self._term(i) - self._term(j)) 
    499                 res.append(self._term(i) + self._term(j)) 
    500         for i in range(self.n): 
    501             res.append(self._term(i)) 
    502         return res 
    503  
    504     def fundamental_weights(self): 
    505         """ 
    506         EXAMPLES: 
    507             sage: RootSystem(['B',3]).ambient_lattice().fundamental_weights() 
    508             [(1, 0, 0), (1, 1, 0), (1/2, 1/2, 1/2)] 
    509  
    510         """ 
    511         return [ sum(self._term(j) for j in range(i+1)) for i in range(self.n-1)]\ 
    512                + [ sum( self._term(j) for j in range(self.n) ) / 2 ] 
    513  
    514  
    515 class AmbientLattice_c(AmbientLattice_generic): 
    516     def root(self, i, j, p1, p2): 
    517         """ 
    518         Note that indexing starts at 0. 
    519          
    520         EXAMPLES: 
    521             sage: e = RootSystem(['C',3]).ambient_lattice() 
    522             sage: e.root(0, 1, 1, 1) 
    523             (-1, -1, 0) 
    524         """ 
    525         return (-1)**p1 * self._term(i) + (-1)**p2 * self._term(j) 
    526  
    527     def simple_roots(self): 
    528         """ 
    529         EXAMPLES: 
    530             sage: RootSystem(['C',3]).ambient_lattice().simple_roots() 
    531             [(1, -1, 0), (0, 1, -1), (0, 0, 2)] 
    532  
    533         """ 
    534         return [ self.root(i, i+1,0,1) for i in range(self.n-1) ] + [self.root(self.n-1, self.n-1, 0, 0)] 
    535  
    536     def positive_roots(self): 
    537         """ 
    538         EXAMPLES: 
    539             sage: RootSystem(['C',3]).ambient_lattice().positive_roots() 
    540             [(1, 1, 0), 
    541              (1, 0, 1), 
    542              (0, 1, 1), 
    543              (1, -1, 0), 
    544              (1, 0, -1), 
    545              (0, 1, -1), 
    546              (2, 0, 0), 
    547              (0, 2, 0), 
    548              (0, 0, 2)] 
    549         """ 
    550         res = [] 
    551         for p in [0,1]: 
    552             for j in range(self.n): 
    553                 res.extend([self.root(i,j,0,p) for i in range(j)]) 
    554         res.extend([self.root(i,i,0,0) for i in range(self.n)]) 
    555         return res 
    556      
    557     def negative_roots(self): 
    558         """ 
    559         EXAMPLES: 
    560             sage: RootSystem(['C',3]).ambient_lattice().negative_roots() 
    561             [(-1, 1, 0), 
    562              (-1, 0, 1), 
    563              (0, -1, 1), 
    564              (-1, -1, 0), 
    565              (-1, 0, -1), 
    566              (0, -1, -1), 
    567              (-2, 0, 0), 
    568              (0, -2, 0), 
    569              (0, 0, -2)] 
    570         """ 
    571         res = [] 
    572         for p in [0,1]: 
    573             for j in range(self.n): 
    574                 res.extend( [self.root(i,j,1,p) for i in range(j) ] ) 
    575         res.extend( [ self.root(i,i,1,1) for i in range(self.n) ] ) 
    576         return res 
    577      
    578  
    579     def fundamental_weights(self): 
    580         """ 
    581         EXAMPLES: 
    582             sage: RootSystem(['C',3]).ambient_lattice().fundamental_weights() 
    583             [(1, 0, 0), (1, 1, 0), (1, 1, 1)] 
    584         """ 
    585         return [ sum(self._term(j) for j in range(i+1)) for i in range(self.n)] 
    586                 
    587  
    588 class AmbientLattice_d(AmbientLattice_generic): 
    589     def root(self, i, j, p1, p2): 
    590         """ 
    591         Note that indexing starts at 0. 
    592          
    593         EXAMPLES: 
    594             sage: e = RootSystem(['D',3]).ambient_lattice() 
    595             sage: e.root(0, 1, 1, 1) 
    596             (-1, -1, 0) 
    597             sage: e.root(0, 0, 1, 1) 
    598             (-1, 0, 0) 
    599              
    600         """ 
    601         if i != j: 
    602             return (-1)**p1 * self._term(i) + (-1)**p2 * self._term(j) 
    603         else: 
    604             return (-1)**p1 * self._term(i) 
    605  
    606     def simple_roots(self): 
    607         """ 
    608         EXAMPLES: 
    609             sage: RootSystem(['D',4]).ambient_lattice().simple_roots() 
    610             [(1, -1, 0, 0), (0, 1, -1, 0), (0, 0, 1, -1), (0, 0, 1, 1)] 
    611              
    612         """ 
    613         return [ self.root(i, i+1, 0, 1) for i in range(self.n-1) ] + [self.root(self.n-2, self.n-1, 0, 0)] 
    614  
    615     def positive_roots(self): 
    616         """ 
    617         EXAMPLES: 
    618             sage: RootSystem(['D',4]).ambient_lattice().positive_roots() 
    619             [(1, 1, 0, 0), 
    620              (1, 0, 1, 0), 
    621              (0, 1, 1, 0), 
    622              (1, 0, 0, 1), 
    623              (0, 1, 0, 1), 
    624              (0, 0, 1, 1), 
    625              (1, -1, 0, 0), 
    626              (1, 0, -1, 0), 
    627              (0, 1, -1, 0), 
    628              (1, 0, 0, -1), 
    629              (0, 1, 0, -1), 
    630              (0, 0, 1, -1)] 
    631  
    632         """ 
    633         res = [] 
    634         for p in [0,1]: 
    635             for j in range(self.n): 
    636                 res.extend([self.root(i,j,0,p) for i in range(j)]) 
    637         return res 
    638      
    639     def negative_roots(self): 
    640         """ 
    641         EXAMPLES: 
    642             sage: RootSystem(['D',4]).ambient_lattice().negative_roots()           
    643             [(-1, 1, 0, 0), 
    644              (-1, 0, 1, 0), 
    645              (0, -1, 1, 0), 
    646              (-1, 0, 0, 1), 
    647              (0, -1, 0, 1), 
    648              (0, 0, -1, 1), 
    649              (-1, -1, 0, 0), 
    650              (-1, 0, -1, 0), 
    651              (0, -1, -1, 0), 
    652              (-1, 0, 0, -1), 
    653              (0, -1, 0, -1), 
    654              (0, 0, -1, -1)] 
    655               
    656         """ 
    657         res = [] 
    658         for p in [0,1]: 
    659             for j in range(self.n): 
    660                 res.extend([self.root(i,j,1,p) for i in range(j)]) 
    661         return res 
    662  
    663      
    664     def fundamental_weights(self): 
    665         """ 
    666         EXAMPLES: 
    667             sage: RootSystem(['D',4]).ambient_lattice().fundamental_weights() 
    668             [(1, 0, 0, 0), (1, 1, 0, 0), (1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, 1/2)] 
    669              
    670         """ 
    671         return [ sum(self._term(j) for j in range(i+1)) for i in range(self.n-2)]+\ 
    672                [ sum(self._term(j) for j in range(self.n-1))/2-self._term(self.n-1)/2]+\ 
    673                [ sum(self._term(j) for j in range(self.n))/2 ] 
    674                 
    675  
    676 class AmbientLattice_e(AmbientLattice_generic): 
    677     """ 
    678     The lattice behind E6, E7, or E8.  The computations are based on Bourbaki,  
    679     Groupes et Algebres de Lie, Ch. 4,5,6 (planche V-VII). 
    680     """ 
    681     def __init__(self, ct): 
    682         """ 
    683         Create the ambient lattice for the root system for E6, E7, E8. 
    684         Specify the Base, i.e., the simple roots w.r. to the canonical 
    685         basis for $R^8$. 
    686          
    687         EXAMPLES: 
    688             sage: e = RootSystem(['E',6]).ambient_lattice() 
    689             sage: e == loads(dumps(e)) 
    690             True 
    691             sage: [e.weyl_dimension(v) for v in e.fundamental_weights()] 
    692             [27, 78, 351, 2925, 351, 27] 
    693             sage: e = RootSystem(['E',7]).ambient_lattice() 
    694             sage: [e.weyl_dimension(v) for v in e.fundamental_weights()] 
    695             [133, 912, 8645, 365750, 27664, 1539, 56] 
    696             sage: e = RootSystem(['E',8]).ambient_lattice() 
    697             sage: [e.weyl_dimension(v) for v in e.fundamental_weights()] 
    698             [3875, 147250, 6696000, 6899079264, 146325270, 2450240, 30380, 248] 
    699            """ 
    700         v = ZZ(1)/ZZ(2) 
    701         self.n = 8          # We're always in R^8, but not always the whole space. 
    702         self.rank = ct.n 
    703         AmbientLattice_generic.__init__(self, ct) 
    704         if ct.n == 6: 
    705             self.Base = [v*(self.root(0,7)-self.root(1,2,3,4,5,6)), 
    706                          self.root(0,1), 
    707                          self.root(0,1,p1=1), 
    708                          self.root(1,2,p1=1), 
    709                          self.root(2,3,p1=1), 
    710                          self.root(3,4,p1=1)] 
    711         elif ct.n == 7: 
    712             self.Base = [v*(self.root(0,7)-self.root(1,2,3,4,5,6)), 
    713                          self.root(0,1), 
    714                          self.root(0,1,p1=1), 
    715                          self.root(1,2,p1=1), 
    716                          self.root(2,3,p1=1), 
    717                          self.root(3,4,p1=1), 
    718                          self.root(4,5,p1=1)] 
    719         elif ct.n == 8: 
    720             self.Base = [v*(self.root(0,7)-self.root(1,2,3,4,5,6)), 
    721                          self.root(0,1), 
    722                          self.root(0,1,p1=1), 
    723                          self.root(1,2,p1=1), 
    724                          self.root(2,3,p1=1), 
    725                          self.root(3,4,p1=1), 
    726                          self.root(4,5,p1=1), 
    727                          self.root(5,6,p1=1)] 
    728         else: 
    729             raise NotImplementedError, "Type \'E\' root systems only come in flavors 6, 7, 8.  Please make another choice" 
    730  
    731     def root(self, i1, i2=None, i3=None, i4=None, i5=None, i6=None, i7=None, i8=None, p1=0, p2=0, p3=0, p4=0, p5=0, p6=0, p7=0, p8=0): 
    732         """ 
    733         Compute an element of the underlying lattice, using the specified elements of 
    734         the standard basis, with signs dictated by the corresponding 'pi' arguments. 
    735         We rely on the caller to provide the correct arguments. 
    736         This is typically used to generate roots, although the generated elements 
    737         need not be roots themselves. 
    738         We assume that if one of the indices is not given, the rest are not as well. 
    739         This should work for E6, E7, E8. 
    740          
    741         EXAMPLES: 
    742             sage: E6 = RootSystem(['E',6]) 
    743             sage: LE6 = E6.ambient_lattice() 
    744             sage: [ LE6.root(i,j,p3=1) for i in xrange(LE6.n) for j in xrange(i+1,LE6.n) ] 
    745             [(1, 1, 0, 0, 0, 0, 0, 0), (1, 0, 1, 0, 0, 0, 0, 0), (1, 0, 0, 1, 0, 0, 0, 0), (1, 0, 0, 0, 1, 0, 0, 0), (1, 0, 0, 0, 0, 1, 0, 0), (1, 0, 0, 0, 0, 0, 1, 0), (1, 0, 0, 0, 0, 0, 0, 1), (0, 1, 1, 0, 0, 0, 0, 0), (0, 1, 0, 1, 0, 0, 0, 0), (0, 1, 0, 0, 1, 0, 0, 0), (0, 1, 0, 0, 0, 1, 0, 0), (0, 1, 0, 0, 0, 0, 1, 0), (0, 1, 0, 0, 0, 0, 0, 1), (0, 0, 1, 1, 0, 0, 0, 0), (0, 0, 1, 0, 1, 0, 0, 0), (0, 0, 1, 0, 0, 1, 0, 0), (0, 0, 1, 0, 0, 0, 1, 0), (0, 0, 1, 0, 0, 0, 0, 1), (0, 0, 0, 1, 1, 0, 0, 0), (0, 0, 0, 1, 0, 1, 0, 0), (0, 0, 0, 1, 0, 0, 1, 0), (0, 0, 0, 1, 0, 0, 0, 1), (0, 0, 0, 0, 1, 1, 0, 0), (0, 0, 0, 0, 1, 0, 1, 0), (0, 0, 0, 0, 1, 0, 0, 1), (0, 0, 0, 0, 0, 1, 1, 0), (0, 0, 0, 0, 0, 1, 0, 1), (0, 0, 0, 0, 0, 0, 1, 1)] 
    746         """ 
    747         if i1 == i2 or i2 == None: 
    748             return (-1)**p1*self._term(i1) 
    749         if i3 == None: 
    750             return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2) 
    751         if i4 == None: 
    752             return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3) 
    753         if i5 == None: 
    754             return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3)+(-1)**p4*self._term(i4) 
    755         if i6 == None: 
    756             return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3)+(-1)**p4*self._term(i4)+(-1)**p5*self._term(i5) 
    757         if i7 == None: 
    758             return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3)+(-1)**p4*self._term(i4)+(-1)**p5*self._term(i5)+(-1)**p6*self._term(i6) 
    759         if i8 == None: 
    760             return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3)+(-1)**p4*self._term(i4)+(-1)**p5*self._term(i5)+(-1)**p6*self._term(i6)+(-1)**p7*self._term(i7) 
    761         return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3)+(-1)**p4*self._term(i4)+(-1)**p5*self._term(i5)+(-1)**p6*self._term(i6)+(-1)**p7*self._term(i7)+(-1)**p8*self._term(i8) 
    762  
    763     def simple_roots(self): 
    764         """ 
    765         There are computed as what Bourbaki calls the Base: 
    766             a1 = e2-e3, a2 = e3-e4, a3 = e4, a4 = 1/2*(e1-e2-e3-e4) 
    767         EXAMPLES: 
    768             sage: LE6 = RootSystem(['E',6]).ambient_lattice() 
    769             sage: LE6.simple_roots() 
    770             [(1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2, 1/2), (1, 1, 0, 0, 0, 0, 0, 0), (-1, 1, 0, 0, 0, 0, 0, 0), (0, -1, 1, 0, 0, 0, 0, 0), (0, 0, -1, 1, 0, 0, 0, 0), (0, 0, 0, -1, 1, 0, 0, 0)] 
    771         """ 
    772         return self.Base 
    773  
    774     def negative_roots(self): 
    775         """ 
    776         The negative postive roots. 
    777         EXAMPLES: 
    778             sage: LE6 =  RootSystem(['E',6]).ambient_lattice() 
    779             sage: LE6.negative_roots() 
    780             [(-1, -1, 0, 0, 0, 0, 0, 0), (-1, 0, -1, 0, 0, 0, 0, 0), (-1, 0, 0, -1, 0, 0, 0, 0), (-1, 0, 0, 0, -1, 0, 0, 0), (0, -1, -1, 0, 0, 0, 0, 0), (0, -1, 0, -1, 0, 0, 0, 0), (0, -1, 0, 0, -1, 0, 0, 0), (0, 0, -1, -1, 0, 0, 0, 0), (0, 0, -1, 0, -1, 0, 0, 0), (0, 0, 0, -1, -1, 0, 0, 0), (1, -1, 0, 0, 0, 0, 0, 0), (1, 0, -1, 0, 0, 0, 0, 0), (1, 0, 0, -1, 0, 0, 0, 0), (1, 0, 0, 0, -1, 0, 0, 0), (0, 1, -1, 0, 0, 0, 0, 0), (0, 1, 0, -1, 0, 0, 0, 0), (0, 1, 0, 0, -1, 0, 0, 0), (0, 0, 1, -1, 0, 0, 0, 0), (0, 0, 1, 0, -1, 0, 0, 0), (0, 0, 0, 1, -1, 0, 0, 0), (-1/2, -1/2, -1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, -1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, -1/2, -1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (1/2, -1/2, -1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (1/2, -1/2, 1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (1/2, -1/2, 1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, -1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (1/2, 1/2, -1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, 1/2, -1/2, 1/2, 1/2, -1/2)] 
    781         """ 
    782         return [ -a for a in self.positive_roots()] 
    783  
    784     def positive_roots(self): 
    785         """ 
    786         These are the roots positive w.r. to lexicographic ordering of the 
    787         basis elements (e1<...<e4). 
    788         EXAMPLES: 
    789             sage: LE6 =  RootSystem(['E',6]).ambient_lattice() 
    790             sage: LE6.positive_roots() 
    791             [(1, 1, 0, 0, 0, 0, 0, 0), (1, 0, 1, 0, 0, 0, 0, 0), (1, 0, 0, 1, 0, 0, 0, 0), (1, 0, 0, 0, 1, 0, 0, 0), (0, 1, 1, 0, 0, 0, 0, 0), (0, 1, 0, 1, 0, 0, 0, 0), (0, 1, 0, 0, 1, 0, 0, 0), (0, 0, 1, 1, 0, 0, 0, 0), (0, 0, 1, 0, 1, 0, 0, 0), (0, 0, 0, 1, 1, 0, 0, 0), (-1, 1, 0, 0, 0, 0, 0, 0), (-1, 0, 1, 0, 0, 0, 0, 0), (-1, 0, 0, 1, 0, 0, 0, 0), (-1, 0, 0, 0, 1, 0, 0, 0), (0, -1, 1, 0, 0, 0, 0, 0), (0, -1, 0, 1, 0, 0, 0, 0), (0, -1, 0, 0, 1, 0, 0, 0), (0, 0, -1, 1, 0, 0, 0, 0), (0, 0, -1, 0, 1, 0, 0, 0), (0, 0, 0, -1, 1, 0, 0, 0), (1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2, 1/2), (1/2, 1/2, 1/2, -1/2, -1/2, -1/2, -1/2, 1/2), (1/2, 1/2, -1/2, 1/2, -1/2, -1/2, -1/2, 1/2), (1/2, 1/2, -1/2, -1/2, 1/2, -1/2, -1/2, 1/2), (1/2, -1/2, 1/2, 1/2, -1/2, -1/2, -1/2, 1/2), (1/2, -1/2, 1/2, -1/2, 1/2, -1/2, -1/2, 1/2), (1/2, -1/2, -1/2, 1/2, 1/2, -1/2, -1/2, 1/2), (1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2, 1/2), (-1/2, 1/2, 1/2, 1/2, -1/2, -1/2, -1/2, 1/2), (-1/2, 1/2, 1/2, -1/2, 1/2, -1/2, -1/2, 1/2), (-1/2, 1/2, -1/2, 1/2, 1/2, -1/2, -1/2, 1/2), (-1/2, 1/2, -1/2, -1/2, -1/2, -1/2, -1/2, 1/2), (-1/2, -1/2, 1/2, 1/2, 1/2, -1/2, -1/2, 1/2), (-1/2, -1/2, 1/2, -1/2, -1/2, -1/2, -1/2, 1/2), (-1/2, -1/2, -1/2, 1/2, -1/2, -1/2, -1/2, 1/2), (-1/2, -1/2, -1/2, -1/2, 1/2, -1/2, -1/2, 1/2)] 
    792             sage: LE6.rho() 
    793             (0, 1, 2, 3, 4, -4, -4, 4) 
    794             sage: E8=RootSystem(['E',8]) 
    795             sage: LE8=E8.ambient_lattice() 
    796             sage: LE8.negative_roots()              
    797             [(-1, -1, 0, 0, 0, 0, 0, 0), (-1, 0, -1, 0, 0, 0, 0, 0), (-1, 0, 0, -1, 0, 0, 0, 0), (-1, 0, 0, 0, -1, 0, 0, 0), (-1, 0, 0, 0, 0, -1, 0, 0), (-1, 0, 0, 0, 0, 0, -1, 0), (-1, 0, 0, 0, 0, 0, 0, -1), (0, -1, -1, 0, 0, 0, 0, 0), (0, -1, 0, -1, 0, 0, 0, 0), (0, -1, 0, 0, -1, 0, 0, 0), (0, -1, 0, 0, 0, -1, 0, 0), (0, -1, 0, 0, 0, 0, -1, 0), (0, -1, 0, 0, 0, 0, 0, -1), (0, 0, -1, -1, 0, 0, 0, 0), (0, 0, -1, 0, -1, 0, 0, 0), (0, 0, -1, 0, 0, -1, 0, 0), (0, 0, -1, 0, 0, 0, -1, 0), (0, 0, -1, 0, 0, 0, 0, -1), (0, 0, 0, -1, -1, 0, 0, 0), (0, 0, 0, -1, 0, -1, 0, 0), (0, 0, 0, -1, 0, 0, -1, 0), (0, 0, 0, -1, 0, 0, 0, -1), (0, 0, 0, 0, -1, -1, 0, 0), (0, 0, 0, 0, -1, 0, -1, 0), (0, 0, 0, 0, -1, 0, 0, -1), (0, 0, 0, 0, 0, -1, -1, 0), (0, 0, 0, 0, 0, -1, 0, -1), (0, 0, 0, 0, 0, 0, -1, -1), (1, -1, 0, 0, 0, 0, 0, 0), (1, 0, -1, 0, 0, 0, 0, 0), (1, 0, 0, -1, 0, 0, 0, 0), (1, 0, 0, 0, -1, 0, 0, 0), (1, 0, 0, 0, 0, -1, 0, 0), (1, 0, 0, 0, 0, 0, -1, 0), (1, 0, 0, 0, 0, 0, 0, -1), (0, 1, -1, 0, 0, 0, 0, 0), (0, 1, 0, -1, 0, 0, 0, 0), (0, 1, 0, 0, -1, 0, 0, 0), (0, 1, 0, 0, 0, -1, 0, 0), (0, 1, 0, 0, 0, 0, -1, 0), (0, 1, 0, 0, 0, 0, 0, -1), (0, 0, 1, -1, 0, 0, 0, 0), (0, 0, 1, 0, -1, 0, 0, 0), (0, 0, 1, 0, 0, -1, 0, 0), (0, 0, 1, 0, 0, 0, -1, 0), (0, 0, 1, 0, 0, 0, 0, -1), (0, 0, 0, 1, -1, 0, 0, 0), (0, 0, 0, 1, 0, -1, 0, 0), (0, 0, 0, 1, 0, 0, -1, 0), (0, 0, 0, 1, 0, 0, 0, -1), (0, 0, 0, 0, 1, -1, 0, 0), (0, 0, 0, 0, 1, 0, -1, 0), (0, 0, 0, 0, 1, 0, 0, -1), (0, 0, 0, 0, 0, 1, -1, 0), (0, 0, 0, 0, 0, 1, 0, -1), (0, 0, 0, 0, 0, 0, 1, -1), (-1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2), (-1/2, -1/2, -1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, -1/2, -1/2, 1/2, -1/2, 1/2, -1/2), (-1/2, -1/2, -1/2, -1/2, 1/2, 1/2, -1/2, -1/2), (-1/2, -1/2, -1/2, 1/2, -1/2, -1/2, 1/2, -1/2), (-1/2, -1/2, -1/2, 1/2, -1/2, 1/2, -1/2, -1/2), (-1/2, -1/2, -1/2, 1/2, 1/2, -1/2, -1/2, -1/2), (-1/2, -1/2, -1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, -1/2, -1/2, -1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, -1/2, -1/2, 1/2, -1/2, -1/2), (-1/2, -1/2, 1/2, -1/2, 1/2, -1/2, -1/2, -1/2), (-1/2, -1/2, 1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, 1/2, -1/2, -1/2, -1/2, -1/2), (-1/2, -1/2, 1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, 1/2, 1/2, -1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, -1/2, -1/2, -1/2, -1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, -1/2, -1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, -1/2, -1/2, 1/2, -1/2, -1/2, -1/2), (-1/2, 1/2, -1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, 1/2, -1/2, -1/2, -1/2, -1/2), (-1/2, 1/2, -1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, 1/2, 1/2, -1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, 1/2, 1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, 1/2, -1/2, -1/2, -1/2, -1/2, -1/2), (-1/2, 1/2, 1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, -1/2, 1/2, -1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, -1/2, 1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, 1/2, 1/2, -1/2, -1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, 1/2, -1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2, -1/2), (-1/2, 1/2, 1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, -1/2, -1/2, -1/2, -1/2, -1/2, 1/2, -1/2), (1/2, -1/2, -1/2, -1/2, -1/2, 1/2, -1/2, -1/2), (1/2, -1/2, -1/2, -1/2, 1/2, -1/2, -1/2, -1/2), (1/2, -1/2, -1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (1/2, -1/2, -1/2, 1/2, -1/2, -1/2, -1/2, -1/2), (1/2, -1/2, -1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (1/2, -1/2, -1/2, 1/2, 1/2, -1/2, 1/2, -1/2), (1/2, -1/2, -1/2, 1/2, 1/2, 1/2, -1/2, -1/2), (1/2, -1/2, 1/2, -1/2, -1/2, -1/2, -1/2, -1/2), (1/2, -1/2, 1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (1/2, -1/2, 1/2, -1/2, 1/2, -1/2, 1/2, -1/2), (1/2, -1/2, 1/2, -1/2, 1/2, 1/2, -1/2, -1/2), (1/2, -1/2, 1/2, 1/2, -1/2, -1/2, 1/2, -1/2), (1/2, -1/2, 1/2, 1/2, -1/2, 1/2, -1/2, -1/2), (1/2, -1/2, 1/2, 1/2, 1/2, -1/2, -1/2, -1/2), (1/2, -1/2, 1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2), (1/2, 1/2, -1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (1/2, 1/2, -1/2, -1/2, 1/2, -1/2, 1/2, -1/2), (1/2, 1/2, -1/2, -1/2, 1/2, 1/2, -1/2, -1/2), (1/2, 1/2, -1/2, 1/2, -1/2, -1/2, 1/2, -1/2), (1/2, 1/2, -1/2, 1/2, -1/2, 1/2, -1/2, -1/2), (1/2, 1/2, -1/2, 1/2, 1/2, -1/2, -1/2, -1/2), (1/2, 1/2, -1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, -1/2, -1/2, -1/2, 1/2, -1/2), (1/2, 1/2, 1/2, -1/2, -1/2, 1/2, -1/2, -1/2), (1/2, 1/2, 1/2, -1/2, 1/2, -1/2, -1/2, -1/2), (1/2, 1/2, 1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, 1/2, -1/2, -1/2, -1/2, -1/2), (1/2, 1/2, 1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, 1/2, 1/2, -1/2, 1/2, -1/2), (1/2, 1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2)] 
    798             sage: LE8.rho() 
    799             (0, 1, 2, 3, 4, 5, 6, 23) 
    800         """ 
    801         v = ZZ(1)/ZZ(2) 
    802         # Note that  
    803         if not hasattr(self, 'PosRoots'): 
    804             if self.rank == 6: 
    805                 self.PosRoots = ( [ self.root(i,j) for i in xrange(self.rank-1) for j in xrange(i+1,self.rank-1) ] + 
    806                                   [ self.root(i,j,p1=1) for i in xrange(self.rank-1) for j in xrange(i+1,self.rank-1) ] + 
    807                                   [ v*(self.root(7)-self.root(6)-self.root(5)+self.root(0,1,2,3,4,p1=p1,p2=p2,p3=p3,p4=p4,p5=p5)) 
    808                                     for p1 in [0,1] for p2 in [0,1] for p3 in [0,1] for p4 in [0,1] for p5 in [0,1] if (p1+p2+p3+p4+p5)%2 == 0 ]) 
    809             elif self.rank == 7: 
    810                 self.PosRoots = ( [ self.root(i,j) for i in xrange(self.rank-1) for j in xrange(i+1,self.rank-1) ] + 
    811                                   [ self.root(i,j,p1=1) for i in xrange(self.rank-1) for j in xrange(i+1,self.rank-1) ] + 
    812                                   [ self.root(6,7,p1=1) ] + 
    813                                   [ v*(self.root(7)-self.root(6)+self.root(0,1,2,3,4,5,p1=p1,p2=p2,p3=p3,p4=p4,p5=p5,p6=p6)) 
    814                                     for p1 in [0,1] for p2 in [0,1] for p3 in [0,1] for p4 in [0,1] for p5 in [0,1] for p6 in [0,1] if (p1+p2+p3+p4+p5+p6)%2 == 1 ]) 
    815             elif self.rank == 8: 
    816                 self.PosRoots = ( [ self.root(i,j) for i in xrange(self.rank) for j in xrange(i+1,self.rank) ] + 
    817                                   [ self.root(i,j,p1=1) for i in xrange(self.rank) for j in xrange(i+1,self.rank) ] + 
    818                                   [ v*(self.root(7)+self.root(0,1,2,3,4,5,6,p1=p1,p2=p2,p3=p3,p4=p4,p5=p5,p6=p6,p7=p7)) 
    819                                     for p1 in [0,1] for p2 in [0,1] for p3 in [0,1] for p4 in [0,1] for p5 in [0,1] for p6 in [0,1] for p7 in [0,1] if (p1+p2+p3+p4+p5+p6+p7)%2 == 0 ]) 
    820  
    821         return self.PosRoots 
    822  
    823     def fundamental_weights(self): 
    824         """ 
    825         EXAMPLES: 
    826             sage: LE6 = RootSystem(['E',6]).ambient_lattice() 
    827             sage: LE6.fundamental_weights() 
    828             [(0, 0, 0, 0, 0, -2/3, -2/3, 2/3), (1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2, 1/2), (-1/2, 1/2, 1/2, 1/2, 1/2, -5/6, -5/6, 5/6), (0, 0, 1, 1, 1, -1, -1, 1), (0, 0, 0, 1, 1, -2/3, -2/3, 2/3), (0, 0, 0, 0, 1, -1/3, -1/3, 1/3)] 
    829         """ 
    830         v2 = ZZ(1)/ZZ(2) 
    831         v3 = ZZ(1)/ZZ(3) 
    832         if self.rank == 6: 
    833             return [ 2*v3*self.root(7,6,5,p2=1,p3=1), 
    834                      v2*self.root(0,1,2,3,4,5,6,7,p6=1,p7=1), 
    835                      5*v2*v3*self.root(7,6,5,p2=1,p3=1)+v2*self.root(0,1,2,3,4,p1=1), 
    836                      self.root(2,3,4,5,6,7,p4=1,p5=1), 
    837                      2*v3*self.root(7,6,5,p2=1,p3=1)+self.root(3,4), 
    838                      v3*self.root(7,6,5,p2=1,p3=1)+self.root(4)] 
    839         elif self.rank == 7: 
    840             return [ self.root(7,6,p2=1), 
    841                      v2*self.root(0,1,2,3,4,5)+self.root(6,7,p1=1), 
    842                      v2*(self.root(0,1,2,3,4,5,p1=1)+3*self.root(6,7,p1=1)), 
    843                      self.root(2,3,4,5)+2*self.root(6,7,p1=1), 
    844                      3*v2*self.root(6,7,p1=1)+self.root(3,4,5), 
    845                      self.root(4,5,6,7,p3=1), 
    846                      self.root(5)+v2*self.root(6,7,p1=1)] 
    847         elif self.rank == 8: 
    848             return [ 2*self.root(7), 
    849                      v2*(self.root(0,1,2,3,4,5,6)+5*self.root(7)), 
    850                      v2*(self.root(0,1,2,3,4,5,6,p1=1)+7*self.root(7)), 
    851                      self.root(2,3,4,5,6)+5*self.root(7), 
    852                      self.root(3,4,5,6)+4*self.root(7), 
    853                      self.root(4,5,6)+3*self.root(7), 
    854                      self.root(5,6)+2*self.root(7), 
    855                      self.root(6,7)] 
    856  
    857  
    858 class AmbientLattice_f(AmbientLattice_generic): 
    859     """ 
    860     The lattice behind F4.  The computations are based on Bourbaki, Groupes et Algebres de Lie, 
    861     Ch. 4,5,6 (planche VIII). 
    862     """ 
    863     def __init__(self, ct): 
    864         """ 
    865         Create the ambient lattice for the root system for F4. 
    866         Specify the Base, i.e., the simple roots w.r. to the canonical 
    867         basis for $R^4$. 
    868  
    869         EXAMPLES: 
    870             sage: e = RootSystem(['F',4]).ambient_lattice() 
    871             sage: e == loads(dumps(e)) 
    872             True 
    873         """ 
    874         v = ZZ(1)/ZZ(2) 
    875         AmbientLattice_generic.__init__(self, ct) 
    876         self.Base = [self.root(1,2,p2=1), 
    877                      self.root(2,3,p2=1), 
    878                      self.root(3), 
    879                      v*(self.root(0)-self.root(1)-self.root(2)-self.root(3))] 
    880  
    881     def root(self, i, j=None, k=None, l=None, p1=0, p2=0, p3=0, p4=0): 
    882         """ 
    883         Compute a root from base elements of the underlying lattice. 
    884         The arguments specify the basis elements and the signs. 
    885         Sadly, the base elements are indexed zero-based. 
    886         We assume that if one of the indices is not given, the rest are not as well. 
    887          
    888         EXAMPLES: 
    889             sage: F4 = RootSystem(['F',4]) 
    890             sage: LF4 = F4.ambient_lattice() 
    891             sage: [ LF4.root(i,j,p2=1) for i in xrange(LF4.n) for j in xrange(i+1,LF4.n) ] 
    892             [(1, -1, 0, 0), (1, 0, -1, 0), (1, 0, 0, -1), (0, 1, -1, 0), (0, 1, 0, -1), (0, 0, 1, -1)] 
    893         """ 
    894         if i == j or j == None: 
    895             return (-1)**p1*self._term(i) 
    896         if k == None: 
    897             return (-1)**p1*self._term(i) + (-1)**p2*self._term(j) 
    898         if l == None: 
    899             return (-1)**p1*self._term(i) + (-1)**p2*self._term(j)+(-1)**p3*self._term(k) 
    900         return (-1)**p1*self._term(i) + (-1)**p2*self._term(j)+(-1)**p3*self._term(k)+(-1)**p4*self._term(l) 
    901  
    902     def simple_roots(self): 
    903         """ 
    904         There are computed as what Bourbaki calls the Base: 
    905             a1 = e2-e3, a2 = e3-e4, a3 = e4, a4 = 1/2*(e1-e2-e3-e4) 
    906              
    907         EXAMPLES: 
    908             sage: LF4 = RootSystem(['F',4]).ambient_lattice() 
    909             sage: LF4.simple_roots() 
    910             [(0, 1, -1, 0), (0, 0, 1, -1), (0, 0, 0, 1), (1/2, -1/2, -1/2, -1/2)] 
    911         """ 
    912         return self.Base 
    913  
    914     def negative_roots(self): 
    915         """ 
    916         Returns the negative roots in self. 
    917          
    918         EXAMPLES: 
    919             sage: LF4 =  RootSystem(['F',4]).ambient_lattice() 
    920             sage: LF4.negative_roots() 
    921             [(-1, 0, 0, 0), (0, -1, 0, 0), (0, 0, -1, 0), (0, 0, 0, -1), (-1, -1, 0, 0), (-1, 0, -1, 0), (-1, 0, 0, -1), (0, -1, -1, 0), (0, -1, 0, -1), (0, 0, -1, -1), (-1, 1, 0, 0), (-1, 0, 1, 0), (-1, 0, 0, 1), (0, -1, 1, 0), (0, -1, 0, 1), (0, 0, -1, 1), (-1/2, -1/2, -1/2, -1/2), (-1/2, -1/2, -1/2, 1/2), (-1/2, -1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, 1/2), (-1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, -1/2, 1/2), (-1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, 1/2)] 
    922         """ 
    923         return [ -a for a in self.positive_roots()] 
    924  
    925     def positive_roots(self): 
    926         """ 
    927         These are the roots positive w.r. to lexicographic ordering of the 
    928         basis elements (e1<...<e4). 
    929          
    930         EXAMPLES: 
    931             sage: LF4 = RootSystem(['F',4]).ambient_lattice() 
    932             sage: LF4.positive_roots() 
    933             [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1), (1, 1, 0, 0), (1, 0, 1, 0), (1, 0, 0, 1), (0, 1, 1, 0), (0, 1, 0, 1), (0, 0, 1, 1), (1, -1, 0, 0), (1, 0, -1, 0), (1, 0, 0, -1), (0, 1, -1, 0), (0, 1, 0, -1), (0, 0, 1, -1), (1/2, 1/2, 1/2, 1/2), (1/2, 1/2, 1/2, -1/2), (1/2, 1/2, -1/2, 1/2), (1/2, 1/2, -1/2, -1/2), (1/2, -1/2, 1/2, 1/2), (1/2, -1/2, 1/2, -1/2), (1/2, -1/2, -1/2, 1/2), (1/2, -1/2, -1/2, -1/2)] 
    934             sage: LF4.rho() 
    935             (11/2, 5/2, 3/2, 1/2) 
    936         """ 
    937         v = ZZ(1)/ZZ(2) 
    938         if not hasattr(self, 'PosRoots'): 
    939             self.PosRoots = ([ self._term(i) for i in xrange(self.n) ] + 
    940                             [ self.root(i,j,p2=0) for i in xrange(self.n) for j in xrange(i+1,self.n) ] + 
    941                             [ self.root(i,j,p2=1) for i in xrange(self.n) for j in xrange(i+1,self.n) ] + 
    942                             [ v*self.root(0,1,2,3,0,p2,p3,p4) for p2 in [0,1] for p3 in [0,1] for p4 in [0,1] ]) 
    943         return self.PosRoots 
    944  
    945     def fundamental_weights(self): 
    946         """ 
    947         EXAMPLES: 
    948             sage: LF4 =  RootSystem(['F',4]).ambient_lattice() 
    949             sage: LF4.fundamental_weights() 
    950             [(1, 1, 0, 0), (2, 1, 1, 0), (3/2, 1/2, 1/2, 1/2), (1, 0, 0, 0)] 
    951         """ 
    952         v = ZZ(1)/ZZ(2) 
    953         return [ self._term(0)+self._term(1), 2*self._term(0)+self._term(1)+self._term(2), v*(3*self._term(0)+self._term(1)+self._term(2)+self._term(3)), self._term(0)] 
    954  
    955  
    956 class AmbientLattice_g(AmbientLattice_generic): 
    957     """ 
    958     TESTS: 
    959         sage: [WeylDim(['G',2],[a,b]) for a,b in [[0,0], [1,0], [0,1], [1,1]]] 
    960         [1, 7, 14, 64] 
    961     """ 
    962     def __init__(self, ct): 
    963         """ 
    964         EXAMPLES: 
    965             sage: e = RootSystem(['G',2]).ambient_lattice() 
    966             sage: e == loads(dumps(e)) 
    967             True 
    968         """ 
    969         self.n = 3 
    970         AmbientLattice_generic.__init__(self, ct) 
    971  
    972     def simple_roots(self): 
    973         """ 
    974         EXAMPLES: 
    975             sage: CartanType(['G',2]).root_system().ambient_lattice().simple_roots() 
    976             [(0, 1, -1), (1, -2, 1)] 
    977          """ 
    978         return [ self._term(1)-self._term(2),\ 
    979                  self._term(0)-2*self._term(1)+self._term(2)] 
    980  
    981     def positive_roots(self): 
    982         """ 
    983         EXAMPLES: 
    984             sage: CartanType(['G',2]).root_system().ambient_lattice().positive_roots() 
    985             [(0, 1, -1), (1, -2, 1), (1, -1, 0), (1, 0, -1), (1, 1, -2), (2, -1, -1)] 
    986         """ 
    987         return [ c0*self._term(0)+c1*self._term(1)+c2*self._term(2) \ 
    988                  for [c0,c1,c2] in 
    989                  [[0,1,-1],[1,-2,1],[1,-1,0],[1,0,-1],[1,1,-2],[2,-1,-1]]] 
    990  
    991     def negative_roots(self): 
    992         """ 
    993         EXAMPLES: 
    994             sage: CartanType(['G',2]).root_system().ambient_lattice().negative_roots() 
    995             [(0, -1, 1), (-1, 2, -1), (-1, 1, 0), (-1, 0, 1), (-1, -1, 2), (-2, 1, 1)] 
    996         """ 
    997         return [ c0*self._term(0)+c1*self._term(1)+c2*self._term(2) \ 
    998                  for [c0,c1,c2] in 
    999                  [[0,-1,1],[-1,2,-1],[-1,1,0],[-1,0,1],[-1,-1,2],[-2,1,1]]] 
    1000  
    1001     def fundamental_weights(self): 
    1002         """ 
    1003         EXAMPLES: 
    1004             sage: CartanType(['G',2]).root_system().ambient_lattice().fundamental_weights() 
    1005             [(1, 0, -1), (2, -1, -1)] 
    1006         """ 
    1007         return [ c0*self._term(0)+c1*self._term(1)+c2*self._term(2) \ 
    1008                  for [c0,c1,c2] in 
    1009                  [[1,0,-1],[2,-1,-1]]] 
    1010  
    1011406 
    1012407def WeylDim(ct, coeffs): 
    1013408    """ 
     
    1038433        sage: [WeylDim(['E', 6], x) for x in [0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 2], [0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0], [1, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 1], [2, 0, 0, 0, 0, 0]] 
    1039434        [1, 78, 27, 351, 351, 351, 27, 650, 351] 
    1040435    """ 
    1041     lattice = RootSystem(ct).ambient_lattice() 
    1042     rank = ct[1] 
     436    ct = CartanType(ct) 
     437    lattice = RootSystem(ct).ambient_space() 
     438    rank = ct.rank() 
    1043439    fw = lattice.fundamental_weights() 
    1044     hwv = sum(coeffs[i]*fw[i] for i in range(min(rank, len(coeffs)))) 
     440    hwv = lattice.sum(coeffs[i]*fw[i+1] for i in range(min(rank, len(coeffs)))) 
    1045441    return lattice.weyl_dimension(hwv) 
  • new file sage/combinat/root_system/type_A.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/type_A.py
    - +  
     1from ambient_space import AmbientSpace 
     2from sage.rings.all import ZZ 
     3from sage.combinat.family import Family 
     4 
     5class ambient_space(AmbientSpace): 
     6    r""" 
     7        sage: R = RootSystem(["A",3]) 
     8        sage: R.ambient_space () 
     9        Ambient space for the Root system of type ['A', 3] 
     10    """ 
     11     
     12    @classmethod 
     13    def smallest_base_ring(cls): 
     14        return ZZ; 
     15 
     16    def dimension(self): 
     17        return self.root_system.cartan_type().rank()+1 
     18 
     19    def root(self, i, j): 
     20        """ 
     21        Note that indexing starts at 0. 
     22         
     23        EXAMPLES: 
     24            sage: e = RootSystem(['A',3]).ambient_lattice() 
     25            sage: e.root(0,1) 
     26            (1, -1, 0, 0) 
     27        """ 
     28        return self._term(i) - self._term(j) 
     29 
     30    def simple_root(self, i): 
     31        """ 
     32        EXAMPLES: 
     33            sage: e = CartanType(['A',3]).root_system().ambient_lattice() 
     34            sage: e.simple_roots() 
     35            Finite family {1: (1, -1, 0, 0), 2: (0, 1, -1, 0), 3: (0, 0, 1, -1)} 
     36        """ 
     37        return self.root(i-1, i) 
     38 
     39    def negative_roots(self): 
     40        """ 
     41        EXAMPLES: 
     42            sage: e = CartanType(['A',3]).root_system().ambient_lattice() 
     43            sage: e.negative_roots() 
     44            [(-1, 1, 0, 0), 
     45             (-1, 0, 1, 0), 
     46             (-1, 0, 0, 1), 
     47             (0, -1, 1, 0), 
     48             (0, -1, 0, 1), 
     49             (0, 0, -1, 1)] 
     50        """ 
     51        res = [] 
     52        for j in range(self.n-1): 
     53            for i in range(j+1,self.n): 
     54                res.append(  self.root(i,j) ) 
     55        return res 
     56 
     57    def positive_roots(self): 
     58        """ 
     59        EXAMPLES: 
     60            sage: e = CartanType(['A',3]).root_system().ambient_lattice() 
     61            sage: e.positive_roots() 
     62            [(1, -1, 0, 0), 
     63             (1, 0, -1, 0), 
     64             (0, 1, -1, 0), 
     65             (1, 0, 0, -1), 
     66             (0, 1, 0, -1), 
     67             (0, 0, 1, -1)] 
     68              
     69        """         
     70        res = [] 
     71        for j in range(self.n): 
     72            for i in range(j): 
     73                res.append(  self.root(i,j) ) 
     74        return res 
     75 
     76    def highest_root(self): 
     77        """ 
     78        EXAMPLE: 
     79           sage: e = CartanType(['A',3]).root_system().ambient_lattice() 
     80           sage: e.highest_root() 
     81           (1, 0, 0, -1) 
     82        """ 
     83        return self.root(0,self.n-1) 
     84 
     85    def fundamental_weight(self, i): 
     86        """ 
     87        EXAMPLES: 
     88            sage: e = CartanType(['A',3]).root_system().ambient_lattice() 
     89            sage: e.fundamental_weights() 
     90            Finite family {1: (1, 0, 0, 0), 2: (1, 1, 0, 0), 3: (1, 1, 1, 0)} 
     91 
     92        """ 
     93        return self.sum(self.term(j) for j in range(i)) 
  • new file sage/combinat/root_system/type_B.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/type_B.py
    - +  
     1from ambient_space import AmbientSpace 
     2 
     3class ambient_space(AmbientSpace): 
     4    def dimension(self): 
     5        return self.root_system.cartan_type().rank() 
     6 
     7    def root(self, i, j): 
     8        """ 
     9        Note that indexing starts at 0. 
     10         
     11        EXAMPLES: 
     12            sage: e = RootSystem(['B',3]).ambient_space() 
     13            sage: e.root(0,1) 
     14            (1, -1, 0) 
     15             
     16        """ 
     17        return self._term(i) - self._term(j) 
     18     
     19    def simple_root(self, i): 
     20        """ 
     21        EXAMPLES: 
     22            sage: e = RootSystem(['B',4]).ambient_space() 
     23            sage: e.simple_roots() 
     24            Finite family {1: (1, -1, 0, 0), 2: (0, 1, -1, 0), 3: (0, 0, 1, -1), 4: (0, 0, 0, 1)} 
     25            sage: e.positive_roots() 
     26            [(1, -1, 0, 0), 
     27            (1, 1, 0, 0), 
     28            (1, 0, -1, 0), 
     29            (1, 0, 1, 0), 
     30            (1, 0, 0, -1), 
     31            (1, 0, 0, 1), 
     32            (0, 1, -1, 0), 
     33            (0, 1, 1, 0), 
     34            (0, 1, 0, -1), 
     35            (0, 1, 0, 1), 
     36            (0, 0, 1, -1), 
     37            (0, 0, 1, 1), 
     38            (1, 0, 0, 0), 
     39            (0, 1, 0, 0), 
     40            (0, 0, 1, 0), 
     41            (0, 0, 0, 1)] 
     42            sage: e.fundamental_weights() 
     43            Finite family {1: (1, 0, 0, 0), 2: (1, 1, 0, 0), 3: (1, 1, 1, 0), 4: (1/2, 1/2, 1/2, 1/2)} 
     44        """ 
     45        assert(i in self.index_set()) 
     46        return self.root(i-1,i) if i < self.n else self._term(self.n-1) 
     47 
     48    def negative_roots(self): 
     49        """ 
     50        EXAMPLES: 
     51            sage: RootSystem(['B',3]).ambient_space().negative_roots() 
     52            [(-1, 1, 0), 
     53             (-1, -1, 0), 
     54             (-1, 0, 1), 
     55             (-1, 0, -1), 
     56             (0, -1, 1), 
     57             (0, -1, -1), 
     58             (-1, 0, 0), 
     59             (0, -1, 0), 
     60             (0, 0, -1)] 
     61              
     62        """ 
     63        return [ -a for a in self.positive_roots()] 
     64 
     65 
     66    def positive_roots(self): 
     67        """ 
     68        EXAMPLES: 
     69            sage: RootSystem(['B',3]).ambient_space().positive_roots() 
     70            [(1, -1, 0), 
     71             (1, 1, 0), 
     72             (1, 0, -1), 
     73             (1, 0, 1), 
     74             (0, 1, -1), 
     75             (0, 1, 1), 
     76             (1, 0, 0), 
     77             (0, 1, 0), 
     78             (0, 0, 1)] 
     79              
     80        """ 
     81        res = [] 
     82        for i in range(self.n-1): 
     83            for j in range(i+1,self.n): 
     84                res.append(self._term(i) - self._term(j)) 
     85                res.append(self._term(i) + self._term(j)) 
     86        for i in range(self.n): 
     87            res.append(self._term(i)) 
     88        return res 
     89 
     90    def fundamental_weight(self, i): 
     91        """ 
     92        EXAMPLES: 
     93            sage: RootSystem(['B',3]).ambient_space().fundamental_weights() 
     94            Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1/2, 1/2, 1/2)} 
     95        """ 
     96        assert(i in self.index_set()) 
     97        n = self.dimension() 
     98        if i == n: 
     99            return self.sum( self.term(j) for j in range(n) ) / 2 
     100        else: 
     101            return self.sum(self.term(j) for j in range(i)) 
  • new file sage/combinat/root_system/type_C.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/type_C.py
    - +  
     1from ambient_space import AmbientSpace 
     2from sage.rings.all import ZZ 
     3 
     4class ambient_space(AmbientSpace): 
     5 
     6# The coroots can't be defined with integer coefficients! 
     7#    @classmethod 
     8#    def smallest_base_ring(cls): 
     9#        return ZZ; 
     10 
     11    def dimension(self): 
     12        return self.root_system.cartan_type().rank() 
     13 
     14    def root(self, i, j, p1, p2): 
     15        """ 
     16        Note that indexing starts at 0. 
     17         
     18        EXAMPLES: 
     19            sage: e = RootSystem(['C',3]).ambient_space() 
     20            sage: e.root(0, 1, 1, 1) 
     21            (-1, -1, 0) 
     22        """ 
     23        return (-1)**p1 * self._term(i) + (-1)**p2 * self._term(j) 
     24 
     25    def simple_root(self, i): 
     26        """ 
     27        EXAMPLES: 
     28            sage: RootSystem(['C',3]).ambient_space().simple_roots() 
     29            Finite family {1: (1, -1, 0), 2: (0, 1, -1), 3: (0, 0, 2)} 
     30        """ 
     31        assert(i in self.index_set()) 
     32        return self.root(i-1, i,0,1) if i < self.n else self.root(self.n-1, self.n-1, 0, 0) 
     33 
     34    def positive_roots(self): 
     35        """ 
     36        EXAMPLES: 
     37            sage: RootSystem(['C',3]).ambient_space().positive_roots() 
     38            [(1, 1, 0), 
     39             (1, 0, 1), 
     40             (0, 1, 1), 
     41             (1, -1, 0), 
     42             (1, 0, -1), 
     43             (0, 1, -1), 
     44             (2, 0, 0), 
     45             (0, 2, 0), 
     46             (0, 0, 2)] 
     47        """ 
     48        res = [] 
     49        for p in [0,1]: 
     50            for j in range(self.n): 
     51                res.extend([self.root(i,j,0,p) for i in range(j)]) 
     52        res.extend([self.root(i,i,0,0) for i in range(self.n)]) 
     53        return res 
     54     
     55    def negative_roots(self): 
     56        """ 
     57        EXAMPLES: 
     58            sage: RootSystem(['C',3]).ambient_space().negative_roots() 
     59            [(-1, 1, 0), 
     60             (-1, 0, 1), 
     61             (0, -1, 1), 
     62             (-1, -1, 0), 
     63             (-1, 0, -1), 
     64             (0, -1, -1), 
     65             (-2, 0, 0), 
     66             (0, -2, 0), 
     67             (0, 0, -2)] 
     68        """ 
     69        res = [] 
     70        for p in [0,1]: 
     71            for j in range(self.n): 
     72                res.extend( [self.root(i,j,1,p) for i in range(j) ] ) 
     73        res.extend( [ self.root(i,i,1,1) for i in range(self.n) ] ) 
     74        return res 
     75     
     76 
     77    def fundamental_weight(self, i): 
     78        """ 
     79        EXAMPLES: 
     80            sage: RootSystem(['C',3]).ambient_space().fundamental_weights() 
     81            Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1, 1, 1)} 
     82        """ 
     83        return self.sum(self._term(j) for j in range(i)) 
  • new file sage/combinat/root_system/type_D.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/type_D.py
    - +  
     1from ambient_space import AmbientSpace 
     2 
     3class ambient_space(AmbientSpace): 
     4    def dimension(self): 
     5        return self.root_system.cartan_type().rank() 
     6 
     7    def root(self, i, j, p1, p2): 
     8        """ 
     9        Note that indexing starts at 0. 
     10         
     11        EXAMPLES: 
     12            sage: e = RootSystem(['D',3]).ambient_space() 
     13            sage: e.root(0, 1, 1, 1) 
     14            (-1, -1, 0) 
     15            sage: e.root(0, 0, 1, 1) 
     16            (-1, 0, 0) 
     17             
     18        """ 
     19        if i != j: 
     20            return (-1)**p1 * self._term(i) + (-1)**p2 * self._term(j) 
     21        else: 
     22            return (-1)**p1 * self._term(i) 
     23 
     24    def simple_root(self, i): 
     25        """ 
     26        EXAMPLES: 
     27            sage: RootSystem(['D',4]).ambient_space().simple_roots() 
     28            Finite family {1: (1, -1, 0, 0), 2: (0, 1, -1, 0), 3: (0, 0, 1, -1), 4: (0, 0, 1, 1)} 
     29             
     30        """ 
     31        assert(i in self.index_set()) 
     32        return self.root(i-1, i, 0, 1) if i < self.n else self.root(self.n-2, self.n-1, 0, 0) 
     33 
     34    def positive_roots(self): 
     35        """ 
     36        EXAMPLES: 
     37            sage: RootSystem(['D',4]).ambient_space().positive_roots() 
     38            [(1, 1, 0, 0), 
     39             (1, 0, 1, 0), 
     40             (0, 1, 1, 0), 
     41             (1, 0, 0, 1), 
     42             (0, 1, 0, 1), 
     43             (0, 0, 1, 1), 
     44             (1, -1, 0, 0), 
     45             (1, 0, -1, 0), 
     46             (0, 1, -1, 0), 
     47             (1, 0, 0, -1), 
     48             (0, 1, 0, -1), 
     49             (0, 0, 1, -1)] 
     50 
     51        """ 
     52        res = [] 
     53        for p in [0,1]: 
     54            for j in range(self.n): 
     55                res.extend([self.root(i,j,0,p) for i in range(j)]) 
     56        return res 
     57     
     58    def negative_roots(self): 
     59        """ 
     60        EXAMPLES: 
     61            sage: RootSystem(['D',4]).ambient_space().negative_roots()           
     62            [(-1, 1, 0, 0), 
     63             (-1, 0, 1, 0), 
     64             (0, -1, 1, 0), 
     65             (-1, 0, 0, 1), 
     66             (0, -1, 0, 1), 
     67             (0, 0, -1, 1), 
     68             (-1, -1, 0, 0), 
     69             (-1, 0, -1, 0), 
     70             (0, -1, -1, 0), 
     71             (-1, 0, 0, -1), 
     72             (0, -1, 0, -1), 
     73             (0, 0, -1, -1)] 
     74              
     75        """ 
     76        res = [] 
     77        for p in [0,1]: 
     78            for j in range(self.n): 
     79                res.extend([self.root(i,j,1,p) for i in range(j)]) 
     80        return res 
     81 
     82     
     83    def fundamental_weight(self, i): 
     84        """ 
     85        EXAMPLES: 
     86            sage: RootSystem(['D',4]).ambient_space().fundamental_weights() 
     87            Finite family {1: (1, 0, 0, 0), 2: (1, 1, 0, 0), 3: (1/2, 1/2, 1/2, -1/2), 4: (1/2, 1/2, 1/2, 1/2)} 
     88        """ 
     89        assert(i in self.index_set()) 
     90        n = self.dimension() 
     91        if i == n: 
     92            return  self.sum(self.term(j) for j in range(n)) / 2 
     93        elif i == n-1: 
     94            return (self.sum(self.term(j) for j in range(n-1)) - self._term(n-1)) / 2 
     95        else: 
     96            return  self.sum(self.term(j) for j in range(i)) 
  • new file sage/combinat/root_system/type_E.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/type_E.py
    - +  
     1from ambient_space import AmbientSpace 
     2from sage.rings.all import ZZ 
     3from sage.combinat.family import Family 
     4 
     5class ambient_space(AmbientSpace): 
     6    """ 
     7    The lattice behind E6, E7, or E8.  The computations are based on Bourbaki,  
     8    Groupes et Algebres de Lie, Ch. 4,5,6 (planche V-VII). 
     9    """ 
     10    def dimension(self): 
     11        return 8; 
     12 
     13    def __init__(self, root_system, baseRing): 
     14        """ 
     15        Create the ambient space for the root system for E6, E7, E8. 
     16        Specify the Base, i.e., the simple roots w.r. to the canonical 
     17        basis for R^8. 
     18         
     19        EXAMPLES: 
     20            sage: e = RootSystem(['E',6]).ambient_space() 
     21            sage: e == loads(dumps(e)) 
     22            True 
     23            sage: [e.weyl_dimension(v) for v in e.fundamental_weights()] 
     24            [27, 78, 351, 2925, 351, 27] 
     25            sage: e = RootSystem(['E',7]).ambient_space() 
     26            sage: [e.weyl_dimension(v) for v in e.fundamental_weights()] 
     27            [133, 912, 8645, 365750, 27664, 1539, 56] 
     28            sage: e = RootSystem(['E',8]).ambient_space() 
     29            sage: [e.weyl_dimension(v) for v in e.fundamental_weights()] 
     30            [3875, 147250, 6696000, 6899079264, 146325270, 2450240, 30380, 248] 
     31           """ 
     32        v = ZZ(1)/ZZ(2) 
     33        self.rank = root_system.cartan_type().rank() 
     34        AmbientSpace.__init__(self, root_system, baseRing) 
     35        if self.rank == 6: 
     36            self.Base = [v*(self.root(0,7)-self.root(1,2,3,4,5,6)), 
     37                         self.root(0,1), 
     38                         self.root(0,1,p1=1), 
     39                         self.root(1,2,p1=1), 
     40                         self.root(2,3,p1=1), 
     41                         self.root(3,4,p1=1)] 
     42        elif self.rank == 7: 
     43            self.Base = [v*(self.root(0,7)-self.root(1,2,3,4,5,6)), 
     44                         self.root(0,1), 
     45                         self.root(0,1,p1=1), 
     46                         self.root(1,2,p1=1), 
     47                         self.root(2,3,p1=1), 
     48                         self.root(3,4,p1=1), 
     49                         self.root(4,5,p1=1)] 
     50        elif self.rank == 8: 
     51            self.Base = [v*(self.root(0,7)-self.root(1,2,3,4,5,6)), 
     52                         self.root(0,1), 
     53                         self.root(0,1,p1=1), 
     54                         self.root(1,2,p1=1), 
     55                         self.root(2,3,p1=1), 
     56                         self.root(3,4,p1=1), 
     57                         self.root(4,5,p1=1), 
     58                         self.root(5,6,p1=1)] 
     59        else: 
     60            raise NotImplementedError, "Type \'E\' root systems only come in flavors 6, 7, 8.  Please make another choice" 
     61 
     62    def root(self, i1, i2=None, i3=None, i4=None, i5=None, i6=None, i7=None, i8=None, p1=0, p2=0, p3=0, p4=0, p5=0, p6=0, p7=0, p8=0): 
     63        """ 
     64        Compute an element of the underlying lattice, using the specified elements of 
     65        the standard basis, with signs dictated by the corresponding 'pi' arguments. 
     66        We rely on the caller to provide the correct arguments. 
     67        This is typically used to generate roots, although the generated elements 
     68        need not be roots themselves. 
     69        We assume that if one of the indices is not given, the rest are not as well. 
     70        This should work for E6, E7, E8. 
     71         
     72        EXAMPLES: 
     73            sage: E6 = RootSystem(['E',6]) 
     74            sage: LE6 = E6.ambient_space() 
     75            sage: [ LE6.root(i,j,p3=1) for i in xrange(LE6.n) for j in xrange(i+1,LE6.n) ] 
     76            [(1, 1, 0, 0, 0, 0, 0, 0), (1, 0, 1, 0, 0, 0, 0, 0), (1, 0, 0, 1, 0, 0, 0, 0), (1, 0, 0, 0, 1, 0, 0, 0), (1, 0, 0, 0, 0, 1, 0, 0), (1, 0, 0, 0, 0, 0, 1, 0), (1, 0, 0, 0, 0, 0, 0, 1), (0, 1, 1, 0, 0, 0, 0, 0), (0, 1, 0, 1, 0, 0, 0, 0), (0, 1, 0, 0, 1, 0, 0, 0), (0, 1, 0, 0, 0, 1, 0, 0), (0, 1, 0, 0, 0, 0, 1, 0), (0, 1, 0, 0, 0, 0, 0, 1), (0, 0, 1, 1, 0, 0, 0, 0), (0, 0, 1, 0, 1, 0, 0, 0), (0, 0, 1, 0, 0, 1, 0, 0), (0, 0, 1, 0, 0, 0, 1, 0), (0, 0, 1, 0, 0, 0, 0, 1), (0, 0, 0, 1, 1, 0, 0, 0), (0, 0, 0, 1, 0, 1, 0, 0), (0, 0, 0, 1, 0, 0, 1, 0), (0, 0, 0, 1, 0, 0, 0, 1), (0, 0, 0, 0, 1, 1, 0, 0), (0, 0, 0, 0, 1, 0, 1, 0), (0, 0, 0, 0, 1, 0, 0, 1), (0, 0, 0, 0, 0, 1, 1, 0), (0, 0, 0, 0, 0, 1, 0, 1), (0, 0, 0, 0, 0, 0, 1, 1)] 
     77        """ 
     78        if i1 == i2 or i2 == None: 
     79            return (-1)**p1*self._term(i1) 
     80        if i3 == None: 
     81            return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2) 
     82        if i4 == None: 
     83            return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3) 
     84        if i5 == None: 
     85            return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3)+(-1)**p4*self._term(i4) 
     86        if i6 == None: 
     87            return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3)+(-1)**p4*self._term(i4)+(-1)**p5*self._term(i5) 
     88        if i7 == None: 
     89            return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3)+(-1)**p4*self._term(i4)+(-1)**p5*self._term(i5)+(-1)**p6*self._term(i6) 
     90        if i8 == None: 
     91            return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3)+(-1)**p4*self._term(i4)+(-1)**p5*self._term(i5)+(-1)**p6*self._term(i6)+(-1)**p7*self._term(i7) 
     92        return (-1)**p1*self._term(i1) + (-1)**p2*self._term(i2)+(-1)**p3*self._term(i3)+(-1)**p4*self._term(i4)+(-1)**p5*self._term(i5)+(-1)**p6*self._term(i6)+(-1)**p7*self._term(i7)+(-1)**p8*self._term(i8) 
     93 
     94    def simple_root(self, i): 
     95        """ 
     96        There are computed as what Bourbaki calls the Base: 
     97            a1 = e2-e3, a2 = e3-e4, a3 = e4, a4 = 1/2*(e1-e2-e3-e4) 
     98        EXAMPLES: 
     99            sage: LE6 = RootSystem(['E',6]).ambient_space() 
     100            sage: LE6.simple_roots() 
     101            Finite family {1: (1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2, 1/2), 2: (1, 1, 0, 0, 0, 0, 0, 0), 3: (-1, 1, 0, 0, 0, 0, 0, 0), 4: (0, -1, 1, 0, 0, 0, 0, 0), 5: (0, 0, -1, 1, 0, 0, 0, 0), 6: (0, 0, 0, -1, 1, 0, 0, 0)} 
     102        """ 
     103        assert(i in self.index_set()) 
     104        return self.Base[i-1] 
     105 
     106    def negative_roots(self): 
     107        """ 
     108        The negative postive roots. 
     109        EXAMPLES: 
     110            sage: LE6 =  RootSystem(['E',6]).ambient_space() 
     111            sage: LE6.negative_roots() 
     112            [(-1, -1, 0, 0, 0, 0, 0, 0), (-1, 0, -1, 0, 0, 0, 0, 0), (-1, 0, 0, -1, 0, 0, 0, 0), (-1, 0, 0, 0, -1, 0, 0, 0), (0, -1, -1, 0, 0, 0, 0, 0), (0, -1, 0, -1, 0, 0, 0, 0), (0, -1, 0, 0, -1, 0, 0, 0), (0, 0, -1, -1, 0, 0, 0, 0), (0, 0, -1, 0, -1, 0, 0, 0), (0, 0, 0, -1, -1, 0, 0, 0), (1, -1, 0, 0, 0, 0, 0, 0), (1, 0, -1, 0, 0, 0, 0, 0), (1, 0, 0, -1, 0, 0, 0, 0), (1, 0, 0, 0, -1, 0, 0, 0), (0, 1, -1, 0, 0, 0, 0, 0), (0, 1, 0, -1, 0, 0, 0, 0), (0, 1, 0, 0, -1, 0, 0, 0), (0, 0, 1, -1, 0, 0, 0, 0), (0, 0, 1, 0, -1, 0, 0, 0), (0, 0, 0, 1, -1, 0, 0, 0), (-1/2, -1/2, -1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, -1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, -1/2, -1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (1/2, -1/2, -1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (1/2, -1/2, 1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (1/2, -1/2, 1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, -1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (1/2, 1/2, -1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, 1/2, -1/2, 1/2, 1/2, -1/2)] 
     113        """ 
     114        return [ -a for a in self.positive_roots()] 
     115 
     116    def positive_roots(self): 
     117        """ 
     118        These are the roots positive w.r. to lexicographic ordering of the 
     119        basis elements (e1<...<e4). 
     120        EXAMPLES: 
     121            sage: LE6 =  RootSystem(['E',6]).ambient_space() 
     122            sage: LE6.positive_roots() 
     123            [(1, 1, 0, 0, 0, 0, 0, 0), (1, 0, 1, 0, 0, 0, 0, 0), (1, 0, 0, 1, 0, 0, 0, 0), (1, 0, 0, 0, 1, 0, 0, 0), (0, 1, 1, 0, 0, 0, 0, 0), (0, 1, 0, 1, 0, 0, 0, 0), (0, 1, 0, 0, 1, 0, 0, 0), (0, 0, 1, 1, 0, 0, 0, 0), (0, 0, 1, 0, 1, 0, 0, 0), (0, 0, 0, 1, 1, 0, 0, 0), (-1, 1, 0, 0, 0, 0, 0, 0), (-1, 0, 1, 0, 0, 0, 0, 0), (-1, 0, 0, 1, 0, 0, 0, 0), (-1, 0, 0, 0, 1, 0, 0, 0), (0, -1, 1, 0, 0, 0, 0, 0), (0, -1, 0, 1, 0, 0, 0, 0), (0, -1, 0, 0, 1, 0, 0, 0), (0, 0, -1, 1, 0, 0, 0, 0), (0, 0, -1, 0, 1, 0, 0, 0), (0, 0, 0, -1, 1, 0, 0, 0), (1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2, 1/2), (1/2, 1/2, 1/2, -1/2, -1/2, -1/2, -1/2, 1/2), (1/2, 1/2, -1/2, 1/2, -1/2, -1/2, -1/2, 1/2), (1/2, 1/2, -1/2, -1/2, 1/2, -1/2, -1/2, 1/2), (1/2, -1/2, 1/2, 1/2, -1/2, -1/2, -1/2, 1/2), (1/2, -1/2, 1/2, -1/2, 1/2, -1/2, -1/2, 1/2), (1/2, -1/2, -1/2, 1/2, 1/2, -1/2, -1/2, 1/2), (1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2, 1/2), (-1/2, 1/2, 1/2, 1/2, -1/2, -1/2, -1/2, 1/2), (-1/2, 1/2, 1/2, -1/2, 1/2, -1/2, -1/2, 1/2), (-1/2, 1/2, -1/2, 1/2, 1/2, -1/2, -1/2, 1/2), (-1/2, 1/2, -1/2, -1/2, -1/2, -1/2, -1/2, 1/2), (-1/2, -1/2, 1/2, 1/2, 1/2, -1/2, -1/2, 1/2), (-1/2, -1/2, 1/2, -1/2, -1/2, -1/2, -1/2, 1/2), (-1/2, -1/2, -1/2, 1/2, -1/2, -1/2, -1/2, 1/2), (-1/2, -1/2, -1/2, -1/2, 1/2, -1/2, -1/2, 1/2)] 
     124            sage: LE6.rho() 
     125            (0, 1, 2, 3, 4, -4, -4, 4) 
     126            sage: E8=RootSystem(['E',8]) 
     127            sage: LE8=E8.ambient_space() 
     128            sage: LE8.negative_roots()              
     129            [(-1, -1, 0, 0, 0, 0, 0, 0), (-1, 0, -1, 0, 0, 0, 0, 0), (-1, 0, 0, -1, 0, 0, 0, 0), (-1, 0, 0, 0, -1, 0, 0, 0), (-1, 0, 0, 0, 0, -1, 0, 0), (-1, 0, 0, 0, 0, 0, -1, 0), (-1, 0, 0, 0, 0, 0, 0, -1), (0, -1, -1, 0, 0, 0, 0, 0), (0, -1, 0, -1, 0, 0, 0, 0), (0, -1, 0, 0, -1, 0, 0, 0), (0, -1, 0, 0, 0, -1, 0, 0), (0, -1, 0, 0, 0, 0, -1, 0), (0, -1, 0, 0, 0, 0, 0, -1), (0, 0, -1, -1, 0, 0, 0, 0), (0, 0, -1, 0, -1, 0, 0, 0), (0, 0, -1, 0, 0, -1, 0, 0), (0, 0, -1, 0, 0, 0, -1, 0), (0, 0, -1, 0, 0, 0, 0, -1), (0, 0, 0, -1, -1, 0, 0, 0), (0, 0, 0, -1, 0, -1, 0, 0), (0, 0, 0, -1, 0, 0, -1, 0), (0, 0, 0, -1, 0, 0, 0, -1), (0, 0, 0, 0, -1, -1, 0, 0), (0, 0, 0, 0, -1, 0, -1, 0), (0, 0, 0, 0, -1, 0, 0, -1), (0, 0, 0, 0, 0, -1, -1, 0), (0, 0, 0, 0, 0, -1, 0, -1), (0, 0, 0, 0, 0, 0, -1, -1), (1, -1, 0, 0, 0, 0, 0, 0), (1, 0, -1, 0, 0, 0, 0, 0), (1, 0, 0, -1, 0, 0, 0, 0), (1, 0, 0, 0, -1, 0, 0, 0), (1, 0, 0, 0, 0, -1, 0, 0), (1, 0, 0, 0, 0, 0, -1, 0), (1, 0, 0, 0, 0, 0, 0, -1), (0, 1, -1, 0, 0, 0, 0, 0), (0, 1, 0, -1, 0, 0, 0, 0), (0, 1, 0, 0, -1, 0, 0, 0), (0, 1, 0, 0, 0, -1, 0, 0), (0, 1, 0, 0, 0, 0, -1, 0), (0, 1, 0, 0, 0, 0, 0, -1), (0, 0, 1, -1, 0, 0, 0, 0), (0, 0, 1, 0, -1, 0, 0, 0), (0, 0, 1, 0, 0, -1, 0, 0), (0, 0, 1, 0, 0, 0, -1, 0), (0, 0, 1, 0, 0, 0, 0, -1), (0, 0, 0, 1, -1, 0, 0, 0), (0, 0, 0, 1, 0, -1, 0, 0), (0, 0, 0, 1, 0, 0, -1, 0), (0, 0, 0, 1, 0, 0, 0, -1), (0, 0, 0, 0, 1, -1, 0, 0), (0, 0, 0, 0, 1, 0, -1, 0), (0, 0, 0, 0, 1, 0, 0, -1), (0, 0, 0, 0, 0, 1, -1, 0), (0, 0, 0, 0, 0, 1, 0, -1), (0, 0, 0, 0, 0, 0, 1, -1), (-1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2), (-1/2, -1/2, -1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, -1/2, -1/2, 1/2, -1/2, 1/2, -1/2), (-1/2, -1/2, -1/2, -1/2, 1/2, 1/2, -1/2, -1/2), (-1/2, -1/2, -1/2, 1/2, -1/2, -1/2, 1/2, -1/2), (-1/2, -1/2, -1/2, 1/2, -1/2, 1/2, -1/2, -1/2), (-1/2, -1/2, -1/2, 1/2, 1/2, -1/2, -1/2, -1/2), (-1/2, -1/2, -1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, -1/2, -1/2, -1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, -1/2, -1/2, 1/2, -1/2, -1/2), (-1/2, -1/2, 1/2, -1/2, 1/2, -1/2, -1/2, -1/2), (-1/2, -1/2, 1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, 1/2, -1/2, -1/2, -1/2, -1/2), (-1/2, -1/2, 1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, 1/2, 1/2, -1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, -1/2, -1/2, -1/2, -1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, -1/2, -1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, -1/2, -1/2, 1/2, -1/2, -1/2, -1/2), (-1/2, 1/2, -1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, 1/2, -1/2, -1/2, -1/2, -1/2), (-1/2, 1/2, -1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, 1/2, 1/2, -1/2, 1/2, -1/2), (-1/2, 1/2, -1/2, 1/2, 1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, 1/2, -1/2, -1/2, -1/2, -1/2, -1/2), (-1/2, 1/2, 1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, -1/2, 1/2, -1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, -1/2, 1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, 1/2, 1/2, -1/2, -1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, 1/2, -1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2, -1/2), (-1/2, 1/2, 1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, -1/2, -1/2, -1/2, -1/2, -1/2, 1/2, -1/2), (1/2, -1/2, -1/2, -1/2, -1/2, 1/2, -1/2, -1/2), (1/2, -1/2, -1/2, -1/2, 1/2, -1/2, -1/2, -1/2), (1/2, -1/2, -1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (1/2, -1/2, -1/2, 1/2, -1/2, -1/2, -1/2, -1/2), (1/2, -1/2, -1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (1/2, -1/2, -1/2, 1/2, 1/2, -1/2, 1/2, -1/2), (1/2, -1/2, -1/2, 1/2, 1/2, 1/2, -1/2, -1/2), (1/2, -1/2, 1/2, -1/2, -1/2, -1/2, -1/2, -1/2), (1/2, -1/2, 1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (1/2, -1/2, 1/2, -1/2, 1/2, -1/2, 1/2, -1/2), (1/2, -1/2, 1/2, -1/2, 1/2, 1/2, -1/2, -1/2), (1/2, -1/2, 1/2, 1/2, -1/2, -1/2, 1/2, -1/2), (1/2, -1/2, 1/2, 1/2, -1/2, 1/2, -1/2, -1/2), (1/2, -1/2, 1/2, 1/2, 1/2, -1/2, -1/2, -1/2), (1/2, -1/2, 1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, -1/2, -1/2, -1/2, -1/2, -1/2, -1/2), (1/2, 1/2, -1/2, -1/2, -1/2, 1/2, 1/2, -1/2), (1/2, 1/2, -1/2, -1/2, 1/2, -1/2, 1/2, -1/2), (1/2, 1/2, -1/2, -1/2, 1/2, 1/2, -1/2, -1/2), (1/2, 1/2, -1/2, 1/2, -1/2, -1/2, 1/2, -1/2), (1/2, 1/2, -1/2, 1/2, -1/2, 1/2, -1/2, -1/2), (1/2, 1/2, -1/2, 1/2, 1/2, -1/2, -1/2, -1/2), (1/2, 1/2, -1/2, 1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, -1/2, -1/2, -1/2, 1/2, -1/2), (1/2, 1/2, 1/2, -1/2, -1/2, 1/2, -1/2, -1/2), (1/2, 1/2, 1/2, -1/2, 1/2, -1/2, -1/2, -1/2), (1/2, 1/2, 1/2, -1/2, 1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, 1/2, -1/2, -1/2, -1/2, -1/2), (1/2, 1/2, 1/2, 1/2, -1/2, 1/2, 1/2, -1/2), (1/2, 1/2, 1/2, 1/2, 1/2, -1/2, 1/2, -1/2), (1/2, 1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2)] 
     130            sage: LE8.rho() 
     131            (0, 1, 2, 3, 4, 5, 6, 23) 
     132        """ 
     133        v = ZZ(1)/ZZ(2) 
     134        # Note that  
     135        if not hasattr(self, 'PosRoots'): 
     136            if self.rank == 6: 
     137                self.PosRoots = ( [ self.root(i,j) for i in xrange(self.rank-1) for j in xrange(i+1,self.rank-1) ] + 
     138                                  [ self.root(i,j,p1=1) for i in xrange(self.rank-1) for j in xrange(i+1,self.rank-1) ] + 
     139                                  [ v*(self.root(7)-self.root(6)-self.root(5)+self.root(0,1,2,3,4,p1=p1,p2=p2,p3=p3,p4=p4,p5=p5)) 
     140                                    for p1 in [0,1] for p2 in [0,1] for p3 in [0,1] for p4 in [0,1] for p5 in [0,1] if (p1+p2+p3+p4+p5)%2 == 0 ]) 
     141            elif self.rank == 7: 
     142                self.PosRoots = ( [ self.root(i,j) for i in xrange(self.rank-1) for j in xrange(i+1,self.rank-1) ] + 
     143                                  [ self.root(i,j,p1=1) for i in xrange(self.rank-1) for j in xrange(i+1,self.rank-1) ] + 
     144                                  [ self.root(6,7,p1=1) ] + 
     145                                  [ v*(self.root(7)-self.root(6)+self.root(0,1,2,3,4,5,p1=p1,p2=p2,p3=p3,p4=p4,p5=p5,p6=p6)) 
     146                                    for p1 in [0,1] for p2 in [0,1] for p3 in [0,1] for p4 in [0,1] for p5 in [0,1] for p6 in [0,1] if (p1+p2+p3+p4+p5+p6)%2 == 1 ]) 
     147            elif self.rank == 8: 
     148                self.PosRoots = ( [ self.root(i,j) for i in xrange(self.rank) for j in xrange(i+1,self.rank) ] + 
     149                                  [ self.root(i,j,p1=1) for i in xrange(self.rank) for j in xrange(i+1,self.rank) ] + 
     150                                  [ v*(self.root(7)+self.root(0,1,2,3,4,5,6,p1=p1,p2=p2,p3=p3,p4=p4,p5=p5,p6=p6,p7=p7)) 
     151                                    for p1 in [0,1] for p2 in [0,1] for p3 in [0,1] for p4 in [0,1] for p5 in [0,1] for p6 in [0,1] for p7 in [0,1] if (p1+p2+p3+p4+p5+p6+p7)%2 == 0 ]) 
     152 
     153        return self.PosRoots 
     154 
     155    def fundamental_weights(self): 
     156        """ 
     157        EXAMPLES: 
     158            sage: LE6 = RootSystem(['E',6]).ambient_space() 
     159            sage: LE6.fundamental_weights() 
     160            Finite family {1: (0, 0, 0, 0, 0, -2/3, -2/3, 2/3), 2: (1/2, 1/2, 1/2, 1/2, 1/2, -1/2, -1/2, 1/2), 3: (-1/2, 1/2, 1/2, 1/2, 1/2, -5/6, -5/6, 5/6), 4: (0, 0, 1, 1, 1, -1, -1, 1), 5: (0, 0, 0, 1, 1, -2/3, -2/3, 2/3), 6: (0, 0, 0, 0, 1, -1/3, -1/3, 1/3)} 
     161        """ 
     162        v2 = ZZ(1)/ZZ(2) 
     163        v3 = ZZ(1)/ZZ(3) 
     164        if self.rank == 6: 
     165            return Family({ 1: 2*v3*self.root(7,6,5,p2=1,p3=1), 
     166                            2: v2*self.root(0,1,2,3,4,5,6,7,p6=1,p7=1), 
     167                            3: 5*v2*v3*self.root(7,6,5,p2=1,p3=1)+v2*self.root(0,1,2,3,4,p1=1), 
     168                            4: self.root(2,3,4,5,6,7,p4=1,p5=1), 
     169                            5: 2*v3*self.root(7,6,5,p2=1,p3=1)+self.root(3,4), 
     170                            6: v3*self.root(7,6,5,p2=1,p3=1)+self.root(4)}) 
     171        elif self.rank == 7: 
     172            return Family({ 1: self.root(7,6,p2=1), 
     173                            2: v2*self.root(0,1,2,3,4,5)+self.root(6,7,p1=1), 
     174                            3: v2*(self.root(0,1,2,3,4,5,p1=1)+3*self.root(6,7,p1=1)), 
     175                            4: self.root(2,3,4,5)+2*self.root(6,7,p1=1), 
     176                            5: 3*v2*self.root(6,7,p1=1)+self.root(3,4,5), 
     177                            6: self.root(4,5,6,7,p3=1), 
     178                            7: self.root(5)+v2*self.root(6,7,p1=1)}) 
     179        elif self.rank == 8: 
     180            return Family({ 1: 2*self.root(7), 
     181                            2: v2*(self.root(0,1,2,3,4,5,6)+5*self.root(7)), 
     182                            3: v2*(self.root(0,1,2,3,4,5,6,p1=1)+7*self.root(7)), 
     183                            4: self.root(2,3,4,5,6)+5*self.root(7), 
     184                            5: self.root(3,4,5,6)+4*self.root(7), 
     185                            6: self.root(4,5,6)+3*self.root(7), 
     186                            7: self.root(5,6)+2*self.root(7), 
     187                            8: self.root(6,7)}) 
  • new file sage/combinat/root_system/type_F.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/type_F.py
    - +  
     1from ambient_space import AmbientSpace 
     2from sage.rings.all import ZZ 
     3from sage.combinat.family import Family 
     4 
     5# TODO: double check that this can't be defined over ZZ 
     6 
     7class ambient_space(AmbientSpace): 
     8    """ 
     9    The lattice behind F4.  The computations are based on Bourbaki, Groupes et Algebres de Lie, 
     10    Ch. 4,5,6 (planche VIII). 
     11    """ 
     12 
     13    def dimension(self): 
     14        return self.root_system.cartan_type().rank() 
     15 
     16    def __init__(self, root_system, base_ring): 
     17        """ 
     18        Create the ambient lattice for the root system for F4. 
     19        Specify the Base, i.e., the simple roots w.r. to the canonical 
     20        basis for R^4. 
     21 
     22        EXAMPLES: 
     23            sage: e = RootSystem(['F',4]).ambient_space() 
     24            sage: e == loads(dumps(e)) 
     25            True 
     26        """ 
     27        AmbientSpace.__init__(self, root_system, base_ring) 
     28        v = ZZ(1)/ZZ(2) 
     29        self.Base = [self.root(1,2,p2=1), 
     30                     self.root(2,3,p2=1), 
     31                     self.root(3), 
     32                     v*(self.root(0)-self.root(1)-self.root(2)-self.root(3))] 
     33 
     34    def root(self, i, j=None, k=None, l=None, p1=0, p2=0, p3=0, p4=0): 
     35        """ 
     36        Compute a root from base elements of the underlying lattice. 
     37        The arguments specify the basis elements and the signs. 
     38        Sadly, the base elements are indexed zero-based. 
     39        We assume that if one of the indices is not given, the rest are not as well. 
     40         
     41        EXAMPLES: 
     42            sage: F4 = RootSystem(['F',4]) 
     43            sage: LF4 = F4.ambient_space() 
     44            sage: [ LF4.root(i,j,p2=1) for i in xrange(LF4.n) for j in xrange(i+1,LF4.n) ] 
     45            [(1, -1, 0, 0), (1, 0, -1, 0), (1, 0, 0, -1), (0, 1, -1, 0), (0, 1, 0, -1), (0, 0, 1, -1)] 
     46        """ 
     47        if i == j or j == None: 
     48            return (-1)**p1*self._term(i) 
     49        if k == None: 
     50            return (-1)**p1*self._term(i) + (-1)**p2*self._term(j) 
     51        if l == None: 
     52            return (-1)**p1*self._term(i) + (-1)**p2*self._term(j)+(-1)**p3*self._term(k) 
     53        return (-1)**p1*self._term(i) + (-1)**p2*self._term(j)+(-1)**p3*self._term(k)+(-1)**p4*self._term(l) 
     54 
     55    def simple_root(self, i): 
     56        """ 
     57        There are computed as what Bourbaki calls the Base: 
     58            a1 = e2-e3, a2 = e3-e4, a3 = e4, a4 = 1/2*(e1-e2-e3-e4) 
     59             
     60        EXAMPLES: 
     61            sage: LF4 = RootSystem(['F',4]).ambient_space() 
     62            sage: LF4.simple_roots() 
     63            Finite family {1: (0, 1, -1, 0), 2: (0, 0, 1, -1), 3: (0, 0, 0, 1), 4: (1/2, -1/2, -1/2, -1/2)} 
     64        """ 
     65        return self.Base[i-1] 
     66 
     67    def negative_roots(self): 
     68        """ 
     69        Returns the negative roots in self. 
     70         
     71        EXAMPLES: 
     72            sage: LF4 =  RootSystem(['F',4]).ambient_space() 
     73            sage: LF4.negative_roots() 
     74            [(-1, 0, 0, 0), (0, -1, 0, 0), (0, 0, -1, 0), (0, 0, 0, -1), (-1, -1, 0, 0), (-1, 0, -1, 0), (-1, 0, 0, -1), (0, -1, -1, 0), (0, -1, 0, -1), (0, 0, -1, -1), (-1, 1, 0, 0), (-1, 0, 1, 0), (-1, 0, 0, 1), (0, -1, 1, 0), (0, -1, 0, 1), (0, 0, -1, 1), (-1/2, -1/2, -1/2, -1/2), (-1/2, -1/2, -1/2, 1/2), (-1/2, -1/2, 1/2, -1/2), (-1/2, -1/2, 1/2, 1/2), (-1/2, 1/2, -1/2, -1/2), (-1/2, 1/2, -1/2, 1/2), (-1/2, 1/2, 1/2, -1/2), (-1/2, 1/2, 1/2, 1/2)] 
     75        """ 
     76        return [ -a for a in self.positive_roots()] 
     77 
     78    def positive_roots(self): 
     79        """ 
     80        These are the roots positive w.r. to lexicographic ordering of the 
     81        basis elements (e1<...<e4). 
     82         
     83        EXAMPLES: 
     84            sage: LF4 = RootSystem(['F',4]).ambient_space() 
     85            sage: LF4.positive_roots() 
     86            [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1), (1, 1, 0, 0), (1, 0, 1, 0), (1, 0, 0, 1), (0, 1, 1, 0), (0, 1, 0, 1), (0, 0, 1, 1), (1, -1, 0, 0), (1, 0, -1, 0), (1, 0, 0, -1), (0, 1, -1, 0), (0, 1, 0, -1), (0, 0, 1, -1), (1/2, 1/2, 1/2, 1/2), (1/2, 1/2, 1/2, -1/2), (1/2, 1/2, -1/2, 1/2), (1/2, 1/2, -1/2, -1/2), (1/2, -1/2, 1/2, 1/2), (1/2, -1/2, 1/2, -1/2), (1/2, -1/2, -1/2, 1/2), (1/2, -1/2, -1/2, -1/2)] 
     87            sage: LF4.rho() 
     88            (11/2, 5/2, 3/2, 1/2) 
     89        """ 
     90        v = ZZ(1)/ZZ(2) 
     91        if not hasattr(self, 'PosRoots'): 
     92            self.PosRoots = ([ self._term(i) for i in xrange(self.n) ] + 
     93                            [ self.root(i,j,p2=0) for i in xrange(self.n) for j in xrange(i+1,self.n) ] + 
     94                            [ self.root(i,j,p2=1) for i in xrange(self.n) for j in xrange(i+1,self.n) ] + 
     95                            [ v*self.root(0,1,2,3,0,p2,p3,p4) for p2 in [0,1] for p3 in [0,1] for p4 in [0,1] ]) 
     96        return self.PosRoots 
     97 
     98    def fundamental_weights(self): 
     99        """ 
     100        EXAMPLES: 
     101            sage: LF4 =  RootSystem(['F',4]).ambient_space() 
     102            sage: LF4.fundamental_weights() 
     103            Finite family {1: (1, 1, 0, 0), 2: (2, 1, 1, 0), 3: (3/2, 1/2, 1/2, 1/2), 4: (1, 0, 0, 0)} 
     104        """ 
     105        v = ZZ(1)/ZZ(2) 
     106        return Family({ 1: self._term(0)+self._term(1), 
     107                        2: 2*self._term(0)+self._term(1)+self._term(2), 
     108                        3: v*(3*self._term(0)+self._term(1)+self._term(2)+self._term(3)), 
     109                        4: self._term(0)}) 
  • new file sage/combinat/root_system/type_G.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/type_G.py
    - +  
     1from ambient_space import AmbientSpace 
     2from sage.combinat.family import Family 
     3 
     4# TODO: check whether this can be defined over ZZ 
     5 
     6class ambient_space(AmbientSpace): 
     7    """ 
     8    TESTS: 
     9        sage: [WeylDim(['G',2],[a,b]) for a,b in [[0,0], [1,0], [0,1], [1,1]]] 
     10        [1, 7, 14, 64] 
     11 
     12    EXAMPLES: 
     13        sage: e = RootSystem(['G',2]).ambient_space() 
     14        sage: e == loads(dumps(e)) 
     15        True 
     16    """ 
     17 
     18    def dimension(self): 
     19        return 3 
     20 
     21    def simple_root(self, i): 
     22        """ 
     23        EXAMPLES: 
     24            sage: CartanType(['G',2]).root_system().ambient_space().simple_roots() 
     25            Finite family {1: (0, 1, -1), 2: (1, -2, 1)} 
     26         """ 
     27        return self._term(1)-self._term(2) if i == 1 else self._term(0)-2*self._term(1)+self._term(2) 
     28 
     29    def positive_roots(self): 
     30        """ 
     31        EXAMPLES: 
     32            sage: CartanType(['G',2]).root_system().ambient_space().positive_roots() 
     33            [(0, 1, -1), (1, -2, 1), (1, -1, 0), (1, 0, -1), (1, 1, -2), (2, -1, -1)] 
     34        """ 
     35        return [ self(v) for v in 
     36                 [[0,1,-1],[1,-2,1],[1,-1,0],[1,0,-1],[1,1,-2],[2,-1,-1]]] 
     37 
     38    def negative_roots(self): 
     39        """ 
     40        EXAMPLES: 
     41            sage: CartanType(['G',2]).root_system().ambient_space().negative_roots() 
     42            [(0, -1, 1), (-1, 2, -1), (-1, 1, 0), (-1, 0, 1), (-1, -1, 2), (-2, 1, 1)] 
     43        """ 
     44        return [ self(v) for v in 
     45                 [[0,-1,1],[-1,2,-1],[-1,1,0],[-1,0,1],[-1,-1,2],[-2,1,1]]] 
     46 
     47    def fundamental_weights(self): 
     48        """ 
     49        EXAMPLES: 
     50            sage: CartanType(['G',2]).root_system().ambient_space().fundamental_weights() 
     51            Finite family {1: (1, 0, -1), 2: (2, -1, -1)} 
     52        """ 
     53        return Family({ 1: self([1,0,-1]), 
     54                        2: self([2,-1,-1])}) 
  • new file sage/combinat/root_system/type_None.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/type_None.py
    - +  
     1  
  • new file sage/combinat/root_system/type_dual.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/type_dual.py
    - +  
     1from sage.combinat.root_system.cartan_type import CartanType_abstract 
     2 
     3class CartanType(CartanType_abstract): 
     4    r""" 
     5    A class for dual Cartan types 
     6 
     7    The dual of a cartan type is a cartan type with the same index 
     8    set, but all arrows reversed in the Dynkin diagram (otherwise 
     9    said, the Cartan matrix is transposed). It shares a lot of 
     10    properties in common with its dual. In particular, the Weyl group 
     11    is isomorphic to that of the dual as a Coxeter group. 
     12    """ 
     13 
     14    def __init__(self, type): 
     15        """ 
     16        INPUT: 
     17           type -- a Cartan type 
     18         
     19        EXAMPLES: 
     20           sage: ct = CartanType(['F',4]).dual() 
     21           sage: ct == loads(dumps(ct)) 
     22           True 
     23        """ 
     24        self._dual = type 
     25 
     26    def __repr__(self): 
     27        """ 
     28        EXAMPLES: 
     29           sage: ct = CartanType(['F', 4]).dual() 
     30           sage: ct 
     31           ['F', 4]^* 
     32        """ 
     33        return self.dual().__repr__()+"^*" 
     34 
     35    def __cmp__(self, other): 
     36        """ 
     37        EXAMPLES: 
     38            sage: ct1 = CartanType(['A',1],['B',2]) 
     39            sage: ct2 = CartanType(['B',2],['A',1]) 
     40            sage: ct3 = CartanType(['A',4]) 
     41            sage: ct = [ct1, ct2, ct3] 
     42            sage: [[x.__cmp__(y) for x in ct] for y in ct] 
     43            [[0, 1, -1], [-1, 0, -1], [1, 1, 0]] 
     44            sage: sorted(ct) 
     45            [['A', 4], A1xB2, B2xA1] 
     46        """ 
     47        if other.__class__ != self.__class__: 
     48            return cmp(self.__class__, other.__class__) 
     49        return cmp(self._dual, other._dual) 
     50 
     51    def dual(self): 
     52        return self._dual 
     53 
     54    def is_irreducible(self): 
     55        return self._dual.is_irreducible() 
     56         
     57    def is_finite(self): 
     58        return self._dual.is_finite() 
     59 
     60    def is_crystalographic(self): 
     61        return self._dual.is_crystalographic 
     62 
     63    def is_affine(self): 
     64        return self._dual.is_affine() 
     65 
     66    def rank(self): 
     67        return self._dual.rank() 
     68 
     69    def index_set(self): 
     70        return self._dual.index_set() 
     71 
     72    def dynkin_diagram(self): 
     73        return self._dual.dynkin_diagram().dual() 
     74 
     75#class ambient_space(AmbientSpace): 
     76# todo? 
  • new file sage/combinat/root_system/type_reducible.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/type_reducible.py
    - +  
     1from sage.combinat.root_system.cartan_type import CartanType_abstract, CartanType_simple 
     2from sage.misc.flatten import flatten 
     3from sage.matrix.constructor import block_diagonal_matrix 
     4from ambient_space import AmbientSpace 
     5 
     6class CartanType(CartanType_abstract): 
     7    r""" 
     8    A class for reducible Cartan types 
     9    """ 
     10 
     11    def __init__(self, types): 
     12        """ 
     13        INPUT: 
     14           types -- a list of simple Cartan types 
     15        Reducible root systems are ones that can be factored as 
     16        direct products. Strictly speaking type D2 (corresponding 
     17        to orthogonal groups of degree 4) are reducible since they 
     18        are isomorphic to A1xA1. However type D2 is considered 
     19        irreducible for our purposes. 
     20        EXAMPLES: 
     21           sage: [t1,t2]=[CartanType(x) for x in ['A',1],['B',2]] 
     22           sage: CartanType([t1,t2]) 
     23           A1xB2 
     24           sage: t = CartanType("A2xB2") 
     25           sage: t == loads(dumps(t)) 
     26           True 
     27        """ 
     28        self._types = types 
     29        self.affine = False 
     30        self._spaces = [t.root_system().ambient_space() for t in types] 
     31        self._shifts = [sum(l.n for l in self._spaces[:k]) for k in range(len(types))] 
     32        self._rshifts = [sum(l[1] for l in types[:k]) for k in range(len(types))] 
     33 
     34    def __repr__(self): 
     35        """ 
     36        EXAMPLES: 
     37           sage: ct = CartanType("A2","B2") 
     38           sage: repr(ct) 
     39           'A2xB2' 
     40        """ 
     41        names = [t[0]+str(t[1]) for t in self._types] 
     42        return  names[0]+"".join(flatten([["x",t] for t in names[1:]])) 
     43 
     44    def __cmp__(self, other): 
     45        """ 
     46        EXAMPLES: 
     47            sage: ct1 = CartanType(['A',1],['B',2]) 
     48            sage: ct2 = CartanType(['B',2],['A',1]) 
     49            sage: ct3 = CartanType(['A',4]) 
     50            sage: ct = [ct1, ct2, ct3] 
     51            sage: [[x.__cmp__(y) for x in ct] for y in ct] 
     52            [[0, 1, -1], [-1, 0, -1], [1, 1, 0]] 
     53            sage: sorted(ct) 
     54            [['A', 4], A1xB2, B2xA1] 
     55        """ 
     56        if isinstance(other, CartanType_simple): 
     57            return 1 
     58        if len(self._types) < len(other._types): 
     59            return -1 
     60        if len(self._types) > len(other._types): 
     61            return 1 
     62        for i in range(len(self._types)): 
     63            if self._types[i] != other._types[i]: 
     64                return self._types[i].__cmp__(other._types[i]) 
     65        return 0 
     66 
     67    def component_types(self): 
     68        """ 
     69        A list of Cartan types making up the reducible type 
     70        EXAMPLES: 
     71          sage: CartanType(['A',2],['B',2]).component_types() 
     72          [['A', 2], ['B', 2]] 
     73        """ 
     74        return self._types 
     75 
     76    def type(self): 
     77        """ 
     78        Returns "reducible" since the type is reducible 
     79        """ 
     80        return "reducible" 
     81 
     82    def is_finite(self): 
     83        return all(t.is_finite() for t in self.component_types()) 
     84 
     85    def rank(self): 
     86        """ 
     87        Returns the rank of self. 
     88        EXAMPLES: 
     89           sage: CartanType("A2","A1").rank() 
     90           3 
     91        """ 
     92        return sum(t.rank() for t in self._types) 
     93 
     94    def root_system(self): 
     95        """ 
     96        Returns the root system associated to self. 
     97 
     98        EXAMPLES: 
     99            sage: CartanType(['A',4]).root_system() 
     100            Root system of type ['A', 4] 
     101        """ 
     102        return root_system.RootSystem(self) 
     103 
     104    def cartan_matrix(self, subdivide=True): 
     105        """ 
     106        Returns the Cartan matrix associated with self. By default 
     107        the Cartan matrix is a subdivided block matrix showing the 
     108        reducibility but the subdivision can be suppressed with 
     109        the option subdivide=False. 
     110 
     111        EXAMPLES: 
     112           sage: ct = CartanType("A2","B2") 
     113           sage: ct.cartan_matrix() 
     114           [ 2 -1| 0  0] 
     115           [-1  2| 0  0] 
     116           [-----+-----] 
     117           [ 0  0| 2 -1] 
     118           [ 0  0|-2  2] 
     119           sage: ct.cartan_matrix(subdivide=False) 
     120           [ 2 -1  0  0] 
     121           [-1  2  0  0] 
     122           [ 0  0  2 -1] 
     123           [ 0  0 -2  2] 
     124        """ 
     125        return block_diagonal_matrix([t.cartan_matrix() for t in self._types], subdivide=subdivide) 
     126 
     127    def is_irreducible(self): 
     128        """ 
     129        Report that this Cartan type is not irreducible 
     130        """ 
     131        return False 
     132 
     133    def dual(self): 
     134        """ 
     135        EXAMPLE: 
     136          sage: CartanType("A2xB2").dual() 
     137          A2xC2 
     138        """ 
     139        return CartanType([t.dual() for t in self._types]) 
     140 
     141    def type_string(self): 
     142        """ 
     143        EXAMPLE: 
     144          sage: CartanType(['A',2],['B',2]).type_string() 
     145          'type_reducible' 
     146        """ 
     147        return "type_reducible" 
     148     
     149    def is_affine(self): 
     150        """ 
     151        Report that this reducible Cartan type is not affine 
     152        """ 
     153        return False 
     154 
     155 
     156class ambient_space(AmbientSpace): 
     157    """ 
     158    EXAMPLES: 
     159      sage: RootSystem("A2xB2").ambient_space() 
     160      Ambient space for the Root system of type A2xB2 
     161    """ 
     162    def cartan_type(self): 
     163        """ 
     164        EXAMPLES: 
     165           sage: RootSystem("A2xB2").ambient_space().cartan_type() 
     166           A2xB2 
     167        """ 
     168        return self.root_system.cartan_type() 
     169 
     170    def component_types(self): 
     171        """ 
     172        EXAMPLES: 
     173          sage: RootSystem("A2xB2").ambient_space().component_types() 
     174          [['A', 2], ['B', 2]] 
     175        """ 
     176        return self.root_system.cartan_type().component_types() 
     177 
     178    def dimension(self): 
     179        """ 
     180        EXAMPLES: 
     181          sage: RootSystem("A2xB2").ambient_space().dimension() 
     182          5 
     183        """ 
     184        return sum(v.dimension() for v in self.ambient_spaces()) 
     185     
     186    def ambient_spaces(self): 
     187        """ 
     188        Returns a list of the irreducible Cartan types of which the 
     189        given reducible Cartan type is a product. 
     190 
     191        EXAMPLES: 
     192          sage: RootSystem("A2xB2").ambient_space().ambient_spaces() 
     193          [Ambient space for the Root system of type ['A', 2], 
     194           Ambient space for the Root system of type ['B', 2]] 
     195        """ 
     196        return [t.root_system().ambient_space() for t in self.component_types()] 
     197 
     198    def inject_weights(self, i, v): 
     199        """ 
     200        INPUT: 
     201          i -- an integer in range(self.components) 
     202          v -- a vector in the i-th component weight lattice 
     203        Produces the corresponding element of the lattice. 
     204        EXAMPLES: 
     205          sage: V = RootSystem("A2xB2").ambient_space() 
     206          sage: [V.inject_weights(i,V.ambient_spaces()[i].fundamental_weights()[1]) for i in range(2)] 
     207          [(1, 0, 0, 0, 0), (0, 0, 0, 1, 0)] 
     208          sage: [V.inject_weights(i,V.ambient_spaces()[i].fundamental_weights()[2]) for i in range(2)] 
     209          [(1, 1, 0, 0, 0), (0, 0, 0, 1/2, 1/2)] 
     210        """ 
     211        shift = self.root_system.cartan_type()._shifts[i] 
     212        return self._from_dict( dict([(shift+k, c) for (k,c) in v ])) 
     213         
     214    def simple_roots(self): 
     215        """ 
     216        EXAMPLES: 
     217          sage: RootSystem("A1xA2").ambient_space().simple_roots() 
     218          [(1, -1, 0, 0, 0), (0, 0, 1, -1, 0), (0, 0, 0, 1, -1)] 
     219        """ 
     220        ret = [] 
     221        for i in range(len(self.component_types())): 
     222            ret.extend(self.inject_weights(i, v) for v in self.ambient_spaces()[i].simple_roots()) 
     223        return ret 
     224 
     225    def positive_roots(self): 
     226        """ 
     227        EXAMPLE: 
     228           sage: RootSystem("A1xA2").ambient_space().positive_roots() 
     229           [(1, -1, 0, 0, 0), (0, 0, 1, -1, 0), (0, 0, 1, 0, -1), (0, 0, 0, 1, -1)] 
     230        """ 
     231        ret = [] 
     232        for i in range(len(self.component_types())): 
     233            ret.extend(self.inject_weights(i, v) for v in self.ambient_spaces()[i].positive_roots()) 
     234        return ret 
     235 
     236    def negative_roots(self): 
     237        """ 
     238        EXAMPLE: 
     239           sage: RootSystem("A1xA2").ambient_space().negative_roots() 
     240           [(-1, 1, 0, 0, 0), (0, 0, -1, 1, 0), (0, 0, -1, 0, 1), (0, 0, 0, -1, 1)] 
     241        """ 
     242        ret = [] 
     243        for i in range(len(self.component_types())): 
     244            ret.extend(self.inject_weights(i, v) for v in self.ambient_spaces()[i].negative_roots()) 
     245        return ret 
     246 
     247    def fundamental_weights(self): 
     248        """ 
     249        EXAMPLE: 
     250           sage: RootSystem("A2xB2").ambient_space().fundamental_weights() 
     251           [(1, 0, 0, 0, 0), (1, 1, 0, 0, 0), (0, 0, 0, 1, 0), (0, 0, 0, 1/2, 1/2)] 
     252        """ 
     253        ret = [] 
     254        for i in range(len(self.component_types())): 
     255            ret.extend(self.inject_weights(i, v) for v in self.ambient_spaces()[i].fundamental_weights()) 
     256        return ret 
  • new file sage/combinat/root_system/weight_lattice_realization.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/weight_lattice_realization.py
    - +  
     1from sage.misc.misc import prod 
     2from sage.combinat.family import Family 
     3from root_lattice_realization import RootLatticeRealization 
     4 
     5class WeightLatticeRealization (RootLatticeRealization): 
     6 
     7    def check(self): 
     8        RootLatticeRealization.check(self) 
     9        Lambda     = self.fundamental_weights() 
     10        alphacheck = self.simple_coroots() 
     11 
     12        for i in self.index_set(): 
     13            assert(Lambda[i].is_dominant()) 
     14            for j in self.index_set(): 
     15                assert(Lambda[j].scalar(alphacheck[i]) == (1 if i==j else 0)) 
     16 
     17        assert(self.rho().is_dominant()) 
     18        assert(self.highest_root().is_dominant()) 
     19 
     20    # Should this be a method or an attribute? 
     21    # same question for the roots, ... 
     22    def fundamental_weights(self): 
     23        """ 
     24        Returns the family $(\Lambda_i)_{i\in I}$ of the fundamental weights 
     25        """ 
     26        if not hasattr(self,"_fundamental_weights"): 
     27            self._fundamental_weights = Family(self.index_set(), 
     28                                               self.fundamental_weight, 
     29                                               name = "Lambda") 
     30        return self._fundamental_weights 
     31 
     32    def rho(self): 
     33        """ 
     34        EXAMPLES: 
     35            sage: RootSystem(['A',3]).ambient_lattice().rho() 
     36            (3, 2, 1, 0) 
     37        """ 
     38        return sum(self.fundamental_weights()) 
     39 
     40    # Should it be a method of highest_weight? 
     41    def weyl_dimension(self, highest_weight): 
     42        """ 
     43        EXAMPLES: 
     44            sage: RootSystem(['A',3]).ambient_lattice().weyl_dimension([2,1,0,0]) 
     45            20 
     46        """ 
     47        highest_weight = self(highest_weight) 
     48        assert(highest_weight.is_dominant()) 
     49        rho = self.rho() 
     50        n = prod([(rho+highest_weight).dot_product(x) for x in self.positive_roots()]) 
     51        d = prod([ rho.dot_product(x) for x in self.positive_roots()]) 
     52        return n/d 
     53 
  • new file sage/combinat/root_system/weight_space.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/weight_space.py
    - +  
     1#***************************************************************************** 
     2#       Copyright (C) 2007 Nicolas M. Thiery <nthiery at users.sf.net> 
     3# 
     4#  Distributed under the terms of the GNU General Public License (GPL) 
     5# 
     6#    This code is distributed in the hope that it will be useful, 
     7#    but WITHOUT ANY WARRANTY; without even the implied warranty of 
     8#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     9#    General Public License for more details. 
     10# 
     11#  The full text of the GPL is available at: 
     12# 
     13#                  http://www.gnu.org/licenses/ 
     14#***************************************************************************** 
     15 
     16from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement 
     17from sage.combinat.family import Family 
     18from root_lattice_realization import RootLatticeRealizationElement 
     19from weight_lattice_realization import WeightLatticeRealization 
     20from sage.rings.all import ZZ 
     21 
     22 
     23class WeightSpace(CombinatorialFreeModule, WeightLatticeRealization): 
     24 
     25    def __init__(self, root_system, base_ring): 
     26        self.root_system = root_system 
     27        basis_name = "Lambdacheck" if root_system.dualSide else "Lambda" 
     28        CombinatorialFreeModule.__init__(self, base_ring,\ 
     29                                         root_system.index_set(),\ 
     30                                         element_class = WeightSpaceElement,\ 
     31                                         prefix=basis_name) 
     32 
     33    def __repr__(self): 
     34        """ 
     35        TEST: 
     36            sage: RootSystem(['A',4]).weight_lattice() 
     37            The weight lattice of the Root system of type ['A', 4] 
     38            sage: RootSystem(['B',4]).weight_space() 
     39            The weight space over the Rational Field of the Root system of type ['B', 4] 
     40            sage: RootSystem(['A',4]).coweight_lattice() 
     41            The coweight lattice of the Root system of type ['A', 4] 
     42            sage: RootSystem(['B',4]).coweight_space() 
     43            The coweight space over the Rational Field of the Root system of type ['B', 4] 
     44 
     45        """ 
     46        return "The %s"%self.root_system.dualString+\ 
     47               ("weight lattice " if self.base_ring() == ZZ else "weight space over the %s "%self.base_ring())+\ 
     48               "of the %s"%(self.root_system.dual if self.root_system.dualSide else self.root_system) 
     49 
     50    fundamental_weights = CombinatorialFreeModule.basis 
     51 
     52    def simple_root(self, j): 
     53        """ 
     54        Returns the $j$-th simple root 
     55         
     56        TESTS: 
     57            sage: R = RootSystem(["C",4]) 
     58            sage: R.weight_lattice().simple_root(3) 
     59            -Lambda[2] + 2*Lambda[3] - Lambda[4] 
     60 
     61            sage: R.weight_lattice().simple_roots() 
     62            Finite family {1: 2*Lambda[1] - Lambda[2], 2: -Lambda[1] + 2*Lambda[2] - Lambda[3], 3: -Lambda[2] + 2*Lambda[3] - Lambda[4], 4: -2*Lambda[3] + 2*Lambda[4]} 
     63 
     64        """ 
     65        assert(j in self.index_set()) 
     66        return self._from_dict(dict([(i,c) for (i,c) in self.root_system.dynkin_diagram().column(j)])) 
     67 
     68 
     69class WeightSpaceElement(CombinatorialFreeModuleElement, RootLatticeRealizationElement): 
     70 
     71    def scalar(self, lambdacheck): 
     72        """ 
     73        The canonical scalar product between the weight lattice and 
     74        the coroot lattice. 
     75 
     76        TODO: merge with_apply_multi_module_morphism 
     77        """ 
     78        zero = self.parent().base_ring().zero_element() 
     79        if len(self) < len(lambdacheck): 
     80            return sum( (lambdacheck[i]*c for (i,c) in self), zero) 
     81        else: 
     82            return sum( (self[i]*c for (i,c) in lambdacheck), zero) 
  • sage/combinat/root_system/weyl_characters.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/weyl_characters.py
    a b  
    5656    weight vector. 
    5757 
    5858    EXAMPLES: 
    59         sage: L = RootSystem(['A',2]).ambient_lattice() 
     59        sage: L = RootSystem(['A',2]).ambient_space() 
    6060        sage: [fw1,fw2] = L.fundamental_weights() 
    6161        sage: R = WeylCharacterRing(['A',2], prefix="R") 
    6262        sage: [R(1),R(fw1),R(fw2)] 
     
    112112        if self._hdict == {}: 
    113113            return "0" 
    114114        v = self._hdict.keys() 
    115         v.sort() 
     115        # Just a workaround to keep the same sorting as before when 
     116        # the dictionary was indexed by tuples 
     117        v.sort(key = lambda v: tuple(v.to_vector())) 
    116118        return repr_lincomb([self._parent.irr_repr(k) for k in v], [self._hdict[k] for k in v]) 
    117119 
    118120    def __cmp__(self, right): 
     
    207209            sage: [F4(x).check(verbose = true) for x in F4.lattice().fundamental_weights()] 
    208210            [[52, 52], [1274, 1274], [273, 273], [26, 26]] 
    209211        """ 
    210         theoretical = sum(self._hdict[k]*self._lattice.weyl_dimension(self._parent.VS(k)) for k in self._hdict) 
     212        theoretical = sum(self._hdict[k]*self._lattice.weyl_dimension(k) for k in self._hdict) 
    211213        practical = sum(self._mdict[k] for k in self._mdict) 
    212214        if verbose: 
    213215            return [theoretical, practical] 
     
    228230        mdict = {} 
    229231        for k in self._mdict: 
    230232            for l in y._mdict: 
    231                 m = tuple(self._parent.VS(k)+self._parent.VS(l)) 
     233                m = k+l 
    232234                if m in mdict: 
    233235                    mdict[m] += self._mdict[k]*y._mdict[l] 
    234236                else: 
     
    300302           sage: B3(1/2,1/2,1/2).hlist() 
    301303           [[(1/2, 1/2, 1/2), 1]] 
    302304        """ 
    303         return [[self._parent.VS(k),m] for k,m in self._hdict.iteritems()] 
     305        return [[k,m] for k,m in self._hdict.iteritems()] 
    304306 
    305307    def mlist(self): 
    306308        """ 
     
    309311        EXAMPLES: 
    310312            sage: B3 = WeylCharacterRing(['B',3]) 
    311313            sage: B3(1/2,1/2,1/2).mlist() 
    312             [[(1/2, 1/2, 1/2), 1], 
    313              [(-1/2, 1/2, -1/2), 1], 
    314              [(-1/2, -1/2, -1/2), 1], 
    315              [(1/2, -1/2, 1/2), 1], 
    316              [(-1/2, 1/2, 1/2), 1], 
    317              [(1/2, -1/2, -1/2), 1], 
    318              [(-1/2, -1/2, 1/2), 1], 
    319              [(1/2, 1/2, -1/2), 1]] 
     314            [[(1/2, -1/2, -1/2), 1], [(-1/2, 1/2, -1/2), 1], [(1/2, 1/2, 1/2), 1], [(1/2, 1/2, -1/2), 1], [(-1/2, -1/2, 1/2), 1], [(-1/2, -1/2, -1/2), 1], [(1/2, -1/2, 1/2), 1], [(-1/2, 1/2, 1/2), 1]] 
     315 
     316# Why did the test not pass with the following indentation? 
     317#             [[( 1/2, -1/2, -1/2), 1], 
     318#              [(-1/2,  1/2, -1/2), 1], 
     319#              [( 1/2,  1/2,  1/2), 1], 
     320#              [( 1/2,  1/2, -1/2), 1], 
     321#              [(-1/2, -1/2,  1/2), 1], 
     322#              [(-1/2, -1/2, -1/2), 1], 
     323#              [( 1/2, -1/2,  1/2), 1], 
     324#              [(-1/2,  1/2,  1/2), 1]] 
    320325        """ 
    321         return [[self._parent.VS(k),m] for k,m in self._mdict.iteritems()] 
     326        return [[k,m] for k,m in self._mdict.iteritems()] 
    322327 
    323328    def parent(self): 
    324329        """ 
     
    369374 
    370375    EXAMPLES: 
    371376        sage: R = WeylCharacterRing(['B',3], prefix='R') 
    372         sage: chi = R(R.lattice().fundamental_weights()[2]); chi 
     377        sage: chi = R(R.lattice().fundamental_weights()[3]); chi 
    373378        R(1/2,1/2,1/2) 
    374379        sage: R(1/2,1/2,1/2) == chi 
    375380        True 
     
    407412    EXAMPLES: 
    408413        sage: R = WeylCharacterRing(['A',2], prefix = R) 
    409414        sage: R([2,1,0]).mlist() 
    410         [[(2, 1, 0), 1], 
    411           [(0, 1, 2), 1], 
    412           [(1, 1, 1), 2], 
    413           [(0, 2, 1), 1], 
    414           [(2, 0, 1), 1], 
    415           [(1, 2, 0), 1], 
    416           [(1, 0, 2), 1]] 
     415        [[(1, 0, 2), 1], 
     416         [(1, 1, 1), 2], 
     417         [(2, 1, 0), 1], 
     418         [(1, 2, 0), 1], 
     419         [(2, 0, 1), 1], 
     420         [(0, 1, 2), 1], 
     421         [(0, 2, 1), 1]] 
    417422 
    418423 
    419424    """ 
    420425    ct = cartan_type.CartanType(ct) 
    421426    return cache_wcr(ct, base_ring=base_ring, prefix=prefix, cache=cache) 
     427 
     428# TODO: inherit all the data structure from CombinatorialFreeModule(base_ring, self._lattice) 
    422429 
    423430class WeylCharacterRing_class(Algebra): 
    424431    def __init__(self, ct, base_ring, prefix, cache): 
     
    432439 
    433440        self.cartan_type = ct 
    434441        self._base_ring = base_ring 
    435         self._lattice = RootSystem(self.cartan_type).ambient_lattice() 
    436         self._origin = tuple(self._lattice._free_module(0)) 
    437         self.VS = VectorSpace(QQ, self._lattice.n) 
     442        self._lattice = RootSystem(self.cartan_type).ambient_space() 
     443        self._origin = self._lattice.zero() 
    438444        if prefix == None: 
    439445            prefix = ct[0]+str(ct[1]) 
    440446        self._prefix = prefix 
    441         self._ip = [self._lattice.fundamental_weights()[i].inner_product(self._lattice.simple_roots()[i]) 
    442                                                                            for i in range(ct[1])] 
     447        alpha = self._lattice.simple_roots() 
     448        Lambda = self._lattice.fundamental_weights() 
     449        # FIXME: indexing of fundamental weights 
     450        self._ip = [Lambda[i].inner_product(alpha[i]) 
     451                    for i in ct.index_set()] 
    443452        self._cache = cache 
    444453        if cache: 
    445454            self._irreducibles={} 
     
    495504            elif x in self.base_ring(): 
    496505                hdict = {self._origin: x} 
    497506                return WeylCharacter(self, hdict, hdict) 
     507 
     508        x = self._lattice(x) 
    498509     
    499         x = self.VS(x) 
    500         vp = [QQ(x.inner_product(self._lattice.simple_roots()[i]))/QQ(self._ip[i]) 
    501               for i in range(self.cartan_type[1])] 
     510        alphacheck = self._lattice.simple_coroots() 
     511        vp = [x.inner_product(alphacheck[i]) 
     512              for i in self.cartan_type.index_set()] 
    502513        if not all(v in ZZ for v in vp): 
    503514            raise ValueError, "not in weight lattice" 
    504515        if not all(v >= 0 for v in vp): 
    505516            raise ValueError, "the weight%s is not dominant"%x.__repr__() 
    506         if self._cache and tuple(x) in self._irreducibles: 
    507             return self._irreducibles[tuple(x)] 
    508         hdict = {tuple(x): 1} 
     517        if self._cache and x in self._irreducibles: 
     518            return self._irreducibles[x] 
     519        hdict = {x: 1} 
    509520        mdict = irreducible_character_freudenthal(x, self._lattice) 
    510521        ret = WeylCharacter(self, hdict, mdict) 
    511522        if self._cache: 
    512             self._irreducibles[tuple(x)] = ret 
     523            self._irreducibles[x] = ret 
    513524        return ret 
    514525 
    515526    def __repr__(self): 
     
    557568            return self.__call__(x) 
    558569        raise TypeError, "no canonical coercion of x" 
    559570 
     571    # FIXME: should be something like weight_lattice_realization? 
    560572    def lattice(self): 
    561573        """ 
    562574        Returns the weight lattice associated to self. 
    563575         
    564576        EXAMPLES: 
    565577            sage: WeylCharacterRing(['E',8]).lattice() 
    566             Ambient lattice of the root system of type ['E', 8] 
     578            Ambient space for the Root system of type ['E', 8] 
    567579        """ 
    568580        return self._lattice 
    569581 
     
    583595        hdict = {} 
    584596        ddict = mdict.copy() 
    585597        while not ddict == {}: 
    586             highest = max((self.VS(x).inner_product(self._lattice.rho()),x) for x in ddict)[1] 
    587             hvect = self.VS(highest) 
    588             if not self._lattice.is_dominant(hvect): 
     598            highest = max((x.inner_product(self._lattice.rho()),x) for x in ddict)[1] 
     599            if not highest.is_dominant(): 
    589600                raise ValueError, "multiplicity dictionary may not be Weyl group invariant" 
    590601            if self._cache and highest in self._irreducibles: 
    591602                sdict = self._irreducibles[highest]._mdict 
    592603            else: 
    593                 sdict = irreducible_character_freudenthal(hvect, self._lattice) 
     604                sdict = irreducible_character_freudenthal(highest, self._lattice) 
    594605            if self._cache and not highest in self._irreducibles: 
    595606                self._irreducibles[highest] = WeylCharacter(self, {highest:1}, sdict) 
    596607            c = ddict[highest] 
     
    643654        L - the ambient lattice 
    644655 
    645656    """ 
    646     VS = VectorSpace(QQ, L.n) 
     657 
    647658    rho = L.rho() 
    648659    mdict = {} 
    649     current_layer = {tuple(hwv):1} 
     660    current_layer = {hwv:1} 
    650661    while len(current_layer) > 0: 
    651662        next_layer = {} 
    652663        for mu in current_layer: 
    653664            if not current_layer[mu] == 0: 
    654665                mdict[mu] = current_layer[mu] 
    655666                for alpha in L.simple_roots(): 
    656                     next_layer[tuple(VS(mu)-alpha)] = None 
     667                    next_layer[mu-alpha] = None 
    657668        if debug: 
    658669            print next_layer 
    659670        for mu in next_layer: 
    660             vmu = VS(mu) 
    661671            if next_layer[mu] == None: 
    662672                if debug: 
    663673                    print "  mu:", mu 
    664674                accum = 0 
    665675                for alpha in L.positive_roots(): 
    666676                    i = 1 
    667                     while tuple(vmu+i*alpha) in mdict: 
     677                    while mu+i*alpha in mdict: 
    668678                        if debug: 
    669                             print "    ", vmu+i*alpha, 
    670                             print mdict[tuple(vmu + i*alpha)]*(vmu + i*alpha).inner_product(alpha) 
    671                         accum += mdict[tuple(vmu + i*alpha)]*(vmu + i*alpha).inner_product(alpha) 
     679                            print "    ", mu+i*alpha, 
     680                            print mdict[mu + i*alpha]*(mu + i*alpha).inner_product(alpha) 
     681                        accum += mdict[mu + i*alpha]*(mu + i*alpha).inner_product(alpha) 
    672682                        i += 1 
    673683                if accum == 0: 
    674684                    next_layer[mu] = 0 
    675685                else: 
    676                     next_layer[mu] = QQ(2*accum)/QQ((hwv+rho).inner_product(hwv+rho)-(vmu+rho).inner_product(vmu+rho)) 
     686                    next_layer[mu] = QQ(2*accum)/QQ((hwv+rho).inner_product(hwv+rho)-(mu+rho).inner_product(mu+rho)) 
    677687        current_layer = next_layer 
    678688    return mdict 
    679689 
     
    897907    """ 
    898908    r = R.cartan_type[1] 
    899909    s = S.cartan_type[1] 
     910    # Each rule takes a tuple or list and returns a list 
    900911    if rule == "levi": 
    901912        if not s == r-1: 
    902913            raise ValueError, "Rank is wrong" 
     
    928939        elif R.cartan_type[0] == 'A': 
    929940            def rule(x) : y = [-i for i in x]; y.reverse(); return y 
    930941        elif R.cartan_type[0] == 'D': 
    931             def rule(x) : y = R.VS(x); y[len(y)-1] = -y[len(y)-1]; return y 
     942            def rule(x) : x[len(x)-1] = -x[len(x)-1]; return x 
    932943        elif R.cartan_type[0] == 'E' and R.cartan_type[1] == 6: 
    933944            raise NotImplementedError, "Exceptional branching rules are yet to be implemented" 
    934945        else: 
     
    9911002 
    9921003    mdict = {} 
    9931004    for k in chi._mdict: 
    994         h = tuple(S.VS(rule(k))) 
     1005        h = S._lattice(rule(list(k.to_vector()))) 
    9951006        if h in mdict: 
    9961007            mdict[h] += chi._mdict[k] 
    9971008        else: 
     
    10451056            sage: B3 = WeylCharacterRing(['B',3]) 
    10461057            sage: b3 = WeightRing(B3) 
    10471058            sage: fw = b3.lattice().fundamental_weights() 
    1048             sage: b3(fw[2]) 
     1059            sage: b3(fw[3]) 
    10491060            b3(1/2,1/2,1/2) 
    1050             sage: b3(B3(fw[2])) 
     1061            sage: b3(B3(fw[3])) 
    10511062            b3(-1/2,-1/2,-1/2) + b3(-1/2,-1/2,1/2) + b3(-1/2,1/2,-1/2) + b3(-1/2,1/2,1/2) + b3(1/2,-1/2,-1/2) + b3(1/2,-1/2,1/2) + b3(1/2,1/2,-1/2) + b3(1/2,1/2,1/2) 
    10521063        """ 
    10531064 
    10541065        if self._mdict == {}: 
    10551066            return "0" 
    10561067        v = self._mdict.keys() 
    1057         v.sort() 
     1068        # Just a workaround to keep the same sorting as before when 
     1069        # the dictionary was indexed by tuples 
     1070        v.sort(key = lambda v: tuple(v.to_vector())) 
    10581071        return repr_lincomb([self._wt_repr(k) for k in v], [self._mdict[k] for k in v]) 
    10591072 
    10601073    def __cmp__(left, right): 
     
    11311144        mdict = {} 
    11321145        for k in self._mdict: 
    11331146            for l in y._mdict: 
    1134                 m = tuple(self._parent.VS(k)+self._parent.VS(l)) 
     1147                m = k+l 
    11351148                if m in mdict: 
    11361149                    mdict[m] += self._mdict[k]*y._mdict[l] 
    11371150                else: 
     
    11731186            sage: g2 = WeightRing(G2) 
    11741187            sage: pr = sum(g2(a) for a in g2.lattice().positive_roots()) 
    11751188            sage: pr.mlist() 
    1176             [[(1, 1, -2), 1], 
    1177              [(1, -1, 0), 1], 
    1178              [(1, 0, -1), 1], 
    1179              [(1, -2, 1), 1], 
     1189            [[(1, -2,  1), 1], 
     1190             [(1, -1,  0), 1], 
     1191             [(1,  0, -1), 1], 
    11801192             [(2, -1, -1), 1], 
    1181              [(0, 1, -1), 1]] 
     1193             [(0,  1, -1), 1], 
     1194             [(1,  1, -2), 1]] 
    11821195        """ 
    1183         return [[self._parent.VS(k),m] for k,m in self._mdict.iteritems()] 
     1196        return [[k,m] for k,m in self._mdict.iteritems()] 
    11841197 
    11851198    def weyl_group_action(self, w): 
    11861199        """ 
     
    11941207            sage: sum(g2(fw2).weyl_group_action(w) for w in L.weyl_group()) 
    11951208            2*g2(-2,1,1) + 2*g2(-1,-1,2) + 2*g2(-1,2,-1) + 2*g2(1,-2,1) + 2*g2(1,1,-2) + 2*g2(2,-1,-1) 
    11961209        """ 
    1197         return WeightRingElement(self._parent, dict([[tuple(w.action(self._parent.VS(x))),self._mdict[x]] for x in self._mdict.keys()])) 
     1210        return WeightRingElement(self._parent, dict([[w.action(x),self._mdict[x]] for x in self._mdict.keys()])) 
    11981211 
    11991212    def character(self): 
    12001213        """ 
     
    12921305        self._base_ring = self._parent._base_ring 
    12931306        self._lattice = self._parent._lattice 
    12941307        self._origin = self._parent._origin 
    1295         self.VS = self._parent.VS 
    12961308        self._prefix = prefix 
    12971309        self._ip = self._parent._ip 
    12981310 
     
    13291341                return WeightRingElement(self, x._mdict) 
    13301342        except AttributeError: 
    13311343            pass 
    1332         x = self.VS(x) 
    1333         mdict = {tuple(x): 1} 
     1344        x = self._lattice(x) 
     1345        mdict = {x: 1} 
    13341346        return WeightRingElement(self, mdict) 
    13351347 
    13361348    def __repr__(self): 
     
    13831395 
    13841396    def lattice(self): 
    13851397        """ 
    1386         Returns the weight lattice associated to self. 
     1398        Returns the weight lattice realization associated to self. 
    13871399        . 
    13881400        EXAMPLES: 
    13891401            sage: E8 = WeylCharacterRing(['E',8]) 
    13901402            sage: e8 = WeightRing(E8) 
    13911403            sage: e8.lattice() 
    1392             Ambient lattice of the root system of type ['E', 8] 
     1404            Ambient space for the Root system of type ['E', 8] 
    13931405        """ 
    13941406        return self._lattice 
    13951407 
  • sage/combinat/root_system/weyl_group.py

    diff -r 29be632ff7bc -r db34e50d9e6c sage/combinat/root_system/weyl_group.py
    a b  
    4141 
    4242      or alternatively and equivalently: 
    4343 
    44         sage: L = RootSystem(['F',4]).ambient_lattice() 
     44        sage: L = RootSystem(['F',4]).ambient_space() 
    4545        sage: G = L.weyl_group() 
    4646 
    4747      Either produces a weight lattice, with access to its 
     
    6565 
    6666        sage: L = G.lattice() 
    6767        sage: fw = L.fundamental_weights(); fw 
    68         [(1, 1, 0, 0), (2, 1, 1, 0), (3/2, 1/2, 1/2, 1/2), (1, 0, 0, 0)] 
     68        Finite family {1: (1, 1, 0, 0), 2: (2, 1, 1, 0), 3: (3/2, 1/2, 1/2, 1/2), 4: (1, 0, 0, 0)} 
    6969        sage: rho = sum(fw); rho 
    7070        (11/2, 5/2, 3/2, 1/2) 
    7171        sage: w.action(rho) # action of G on weight lattice 
     
    8585        The Weyl Group of type ['A', 2] 
    8686    """ 
    8787    from sage.combinat.root_system.root_system import RootSystem 
    88     e = RootSystem(ct).ambient_lattice() 
     88    e = RootSystem(ct).ambient_space() 
    8989    n = e.n 
    90     rank = e.ct[1] 
    91     basis = e._free_module.basis() 
     90    rank = ct.rank() 
     91    basis = e.basis() 
    9292    gens = [] 
     93    s = e.simple_reflections() 
    9394    for k in range(rank): 
    9495        m = [] 
    9596        for i in range(n): 
    9697            for j in range(n): 
    97                 m.append(e.simple_reflection(k+1,basis[j]).inner_product(basis[i])) 
     98                m.append(s[k+1](basis[j]).inner_product(basis[i])) 
    9899        gens.append(matrix(QQ,n,m)) 
    99100    return WeylGroup_gens(gens,e) 
    100101 
     
    111112            True 
    112113        """ 
    113114        MatrixGroup_gens.__init__(self, gens) 
    114         self.ambient_lattice = L 
     115        self.ambient_space = L 
    115116        self.reflections = [WeylGroupElement(g, self) for g in gens] 
    116117        self.n = L.n 
    117118 
     
    121122            sage: WeylGroup(['A',1]).__repr__() 
    122123            "The Weyl Group of type ['A', 1]" 
    123124        """ 
    124         return "The Weyl Group of type %s"%repr(self.ambient_lattice.ct) 
     125        # FIXME: do we want to say Weyl Group of the AmbientSpace of ...? 
     126        return "The Weyl Group of type %s"%repr(self.cartan_type()) 
    125127 
    126128    def __call__(self, x): 
    127129        """ 
     
    189191        EXAMPLES: 
    190192            sage: G = WeylGroup(['F',4]) 
    191193            sage: G.lattice() 
    192             Ambient lattice of the root system of type ['F', 4] 
     194            Ambient space for the Root system of type ['F', 4] 
    193195        """ 
    194         return self.ambient_lattice 
     196        return self.ambient_space 
    195197 
    196198    def simple_reflections(self): 
    197199        """ 
     
    224226            [0 1 0 0] 
    225227            [0 0 0 1] 
    226228        """ 
    227         if i not in self.ambient_lattice.ct.index_set(): 
     229        if i not in self.cartan_type().index_set(): 
    228230            raise ValueError, "i must be in the index set" 
    229231        return self.reflections[i-1] 
    230232 
     
    235237          sage: [WeylGroup(t).long_element().length() for t in ['A',5],['B',3],['C',3],['D',4],['G',2],['F',4],['E',6]] 
    236238          [15, 9, 9, 12, 6, 24, 36] 
    237239        """ 
    238         type = self.ambient_lattice.ct 
     240        type = self.cartan_type() 
    239241        if type[0] == 'D' and type[1]%2 == 1: 
    240242            l = [-1 for i in range(self.n-1)] 
    241243            l.append(1) 
     
    280282            ['F', 4] 
    281283 
    282284        """ 
    283         return self.ambient_lattice.ct 
     285        return self.ambient_space.root_system.cartan_type() 
    284286 
    285287    def __cmp__(self, other): 
    286288        """ 
     
    293295        """ 
    294296        if self.__class__ != other.__class__: 
    295297            return cmp(self.__class__, other.__class__) 
    296         if self.ambient_lattice.ct != other.ambient_lattice.ct: 
    297             return cmp(self.ambient_lattice.ct, other.ambient_lattice.ct) 
     298        if self.cartan_type() != other.cartan_type(): 
     299            return cmp(self.cartan_type(), other.cartan_type()) 
    298300        return 0 
    299301 
    300302class WeylGroupElement(MatrixGroupElement): 
     
    321323            sage: w = WeylGroup(['A',2]) 
    322324            sage: s1 = w.simple_reflection(1) 
    323325            sage: s1.lattice() 
    324             Ambient lattice of the root system of type ['A', 2] 
     326            Ambient space for the Root system of type ['A', 2] 
    325327        """ 
    326328        return self._parent.lattice() 
    327329 
     
    342344 
    343345        """ 
    344346        ret = 0 
    345         for alph in self.lattice().positive_roots(): 
    346             walph = self.__matrix*alph 
     347        for alpha in self.lattice().positive_roots(): 
     348            walph = self.action(alpha) 
    347349            for v in self.lattice().fundamental_weights(): 
    348350                if walph.inner_product(v) < 0: 
    349351                    ret += 1 
     
    415417        EXAMPLES: 
    416418            sage: w = WeylGroup(['A',2]) 
    417419            sage: s1 = w.simple_reflection(1) 
    418             sage: v = vector(QQ,[1,0,0]) 
     420            sage: v = w.lattice()([1,0,0]) 
    419421            sage: s1.action(v) 
    420422            (0, 1, 0) 
    421423        """ 
    422         return (self.__matrix*transpose(v)).columns()[0] 
     424        return (self.lattice()(list(self.__matrix*transpose(v.to_vector()).columns()[0])))