Ticket #3664: trac_3664-1.patch

File trac_3664-1.patch, 205.7 KB (added by mhansen, 8 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])))