Ticket #3664: trac_3664-1.patch

File trac_3664-1.patch, 205.7 kB (added by mhansen, 4 months ago)
  • a/sage/combinat/crystals/crystals.py

    old new  
    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        """ 
  • a/sage/combinat/root_system/all.py

    old new  
    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 
  • /dev/null

    old new  
     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 
  • a/sage/combinat/root_system/cartan_matrix.py

    old new  
    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 
  • a/sage/combinat/root_system/cartan_type.py

    old new  
    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]