# HG changeset patch
# User Christian Stump <christian.stump at gmail.com>
# Date 1352623639 -3600
# Node ID 79ce1f7cd3129cb2207af0607b4012ea77251484
# Parent 257ad14e3668760e87b5978588eeec0d98da40a7
#12882 Allows a generalized Cartan matrix as input for Dynkin diagrams
diff --git a/sage/combinat/root_system/dynkin_diagram.py b/sage/combinat/root_system/dynkin_diagram.py
a
|
b
|
AUTHORS: |
5 | 5 | |
6 | 6 | - Travis Scrimshaw (2012-04-22): Nicolas M. Thiery moved Cartan matrix creation |
7 | 7 | to here and I cached results for speed. |
8 | | |
| 8 | |
| 9 | - Christian Stump (2012-11-11): Added Cartan matrix as possible input for Dynkin diagrams |
9 | 10 | """ |
10 | 11 | #***************************************************************************** |
11 | | # Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, |
| 12 | # Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, |
12 | 13 | # |
13 | 14 | # Distributed under the terms of the GNU General Public License (GPL) |
14 | 15 | # |
… |
… |
AUTHORS: |
24 | 25 | from sage.misc.cachefunc import cached_method |
25 | 26 | from sage.graphs.digraph import DiGraph |
26 | 27 | from cartan_type import CartanType, CartanType_abstract |
| 28 | from sage.matrix.matrix import is_Matrix |
| 29 | from sage.functions.generalized import sgn |
27 | 30 | |
28 | 31 | def DynkinDiagram(*args): |
29 | 32 | """ |
30 | 33 | INPUT: |
31 | 34 | |
32 | | - ``ct`` - a Cartan Type |
| 35 | The input can be one of the following: |
33 | 36 | |
34 | | Returns a Dynkin diagram for type ct. |
35 | | |
36 | | |
| 37 | - empty to obtain an empty Dynkin diagram |
| 38 | - input for a Cartan type |
| 39 | - Cartan matrix |
| 40 | - Cartan matrix and an indexing set |
| 41 | |
| 42 | Returns a corresponding Dynkin diagram. |
| 43 | |
| 44 | |
37 | 45 | The edge multiplicities are encoded as edge labels. This uses the |
38 | 46 | convention in Kac / Fulton Harris, Representation theory / Wikipedia |
39 | 47 | (http://en.wikipedia.org/wiki/Dynkin_diagram). That is for i != j:: |
40 | 48 | |
41 | | j --k--> i <==> a_ij = -k |
| 49 | j --k--> i <==> a_ij = -k |
42 | 50 | <==> -scalar(coroot[i], root[j]) = k |
43 | | <==> multiple arrows point from the longer root |
| 51 | <==> multiple arrows point from the longer root |
44 | 52 | to the shorter one |
45 | | |
| 53 | |
46 | 54 | EXAMPLES:: |
47 | | |
| 55 | |
48 | 56 | sage: DynkinDiagram(['A', 4]) |
49 | 57 | O---O---O---O |
50 | 58 | 1 2 3 4 |
… |
… |
def DynkinDiagram(*args): |
67 | 75 | 5 6 7 8 |
68 | 76 | A2xB2xF4 |
69 | 77 | |
| 78 | sage: R = RootSystem("A2xB2xF4") |
| 79 | sage: R.cartan_matrix() |
| 80 | [ 2 -1| 0 0| 0 0 0 0] |
| 81 | [-1 2| 0 0| 0 0 0 0] |
| 82 | [-----+-----+-----------] |
| 83 | [ 0 0| 2 -1| 0 0 0 0] |
| 84 | [ 0 0|-2 2| 0 0 0 0] |
| 85 | [-----+-----+-----------] |
| 86 | [ 0 0| 0 0| 2 -1 0 0] |
| 87 | [ 0 0| 0 0|-1 2 -1 0] |
| 88 | [ 0 0| 0 0| 0 -2 2 -1] |
| 89 | [ 0 0| 0 0| 0 0 -1 2] |
| 90 | |
| 91 | sage: DD = DynkinDiagram(R.cartan_matrix()); DD |
| 92 | Dynkin diagram of rank 8 |
| 93 | sage: DD.cartan_matrix() |
| 94 | [ 2 -1 0 0 0 0 0 0] |
| 95 | [-1 2 0 0 0 0 0 0] |
| 96 | [ 0 0 2 -2 0 0 0 0] |
| 97 | [ 0 0 -1 2 0 0 0 0] |
| 98 | [ 0 0 0 0 2 -1 0 0] |
| 99 | [ 0 0 0 0 -1 2 -2 0] |
| 100 | [ 0 0 0 0 0 -1 2 -1] |
| 101 | [ 0 0 0 0 0 0 -1 2] |
| 102 | |
70 | 103 | SEE ALSO: :func:`CartanType` for a general discussion on Cartan |
71 | 104 | types and in particular node labeling conventions. |
72 | 105 | """ |
73 | 106 | if len(args) == 0: |
74 | 107 | return DynkinDiagram_class() |
| 108 | if is_Matrix(args[0]): |
| 109 | M = args[0] |
| 110 | n = M.ncols() |
| 111 | if any( ( M[i,j] > 0 ) if i != j else ( M[i,j] != 2 ) for i in xrange(n) for j in xrange(n) ): |
| 112 | for i in xrange(n): |
| 113 | for j in xrange(n): |
| 114 | print i,j,M[i,j],M[i,j]>0 |
| 115 | raise ValueError, "The input matrix is not a valid Cartan datum." |
| 116 | |
| 117 | if not all( sgn(M[i,j]) == sgn(M[j,i]) for i in xrange(n) for j in xrange(i+1,n) ): |
| 118 | raise ValueError, "The input matrix is not a valid Cartan datum." |
| 119 | |
| 120 | if not M.is_symmetrizable(): |
| 121 | "The input matrix is not a valid Cartan datum." |
| 122 | |
| 123 | if len(args) == 1: |
| 124 | index_set = range(n) |
| 125 | elif len(args) == 2: |
| 126 | index_set = tuple( x for x in args[1] ) |
| 127 | else: |
| 128 | raise ValueError, "You have given a Cartan matrix, but too many additional arguments." |
| 129 | |
| 130 | D = DynkinDiagram_class() |
| 131 | for i in range(n): |
| 132 | for j in range(n): |
| 133 | if i != j: |
| 134 | D.add_edge( index_set[i], index_set[j], -M[i,j] ) |
| 135 | return D |
| 136 | |
75 | 137 | ct = CartanType(*args) |
76 | 138 | if hasattr(ct, "dynkin_diagram"): |
77 | 139 | return ct.dynkin_diagram() |
… |
… |
def DynkinDiagram(*args): |
81 | 143 | def dynkin_diagram(t): |
82 | 144 | """ |
83 | 145 | Returns the Dynkin diagram of type t. |
84 | | |
| 146 | |
85 | 147 | Note that this function is deprecated, and that you should use |
86 | 148 | DynkinDiagram instead as this will be disappearing in the near |
87 | 149 | future. |
88 | | |
| 150 | |
89 | 151 | EXAMPLES:: |
90 | | |
| 152 | |
91 | 153 | sage: dynkin_diagram(["A", 3]) |
92 | 154 | doctest:1: DeprecationWarning: dynkin_diagram is deprecated, use DynkinDiagram instead! |
93 | 155 | See http://trac.sagemath.org/3654 for details. |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
108 | 170 | - ``t`` - a Cartan type or None |
109 | 171 | |
110 | 172 | EXAMPLES:: |
111 | | |
| 173 | |
112 | 174 | sage: d = DynkinDiagram(["A", 3]) |
113 | 175 | sage: d == loads(dumps(d)) |
114 | 176 | True |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
124 | 186 | def __copy__(self): |
125 | 187 | """ |
126 | 188 | EXAMPLES:: |
127 | | |
| 189 | |
128 | 190 | sage: d = DynkinDiagram(["A", 3]) |
129 | 191 | sage: type(copy(d)) |
130 | 192 | <class 'sage.combinat.root_system.dynkin_diagram.DynkinDiagram_class'> |
131 | 193 | """ |
132 | | import copy |
| 194 | import copy |
133 | 195 | # we have to go back to the generic copy method because the DiGraph one returns a DiGraph, not a DynkinDiagram |
134 | 196 | return copy._reconstruct(self,self.__reduce_ex__(2),0) |
135 | 197 | |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
144 | 206 | G2 |
145 | 207 | """ |
146 | 208 | result = self.cartan_type().ascii_art() +"\n" if hasattr(self.cartan_type(), "ascii_art") else "" |
147 | | |
| 209 | |
148 | 210 | if self.cartan_type() is None: |
149 | 211 | return result+"Dynkin diagram of rank %s"%self.rank() |
150 | 212 | else: |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
154 | 216 | def add_edge(self, i, j, label=1): |
155 | 217 | """ |
156 | 218 | EXAMPLES:: |
157 | | |
| 219 | |
158 | 220 | sage: from sage.combinat.root_system.dynkin_diagram import DynkinDiagram_class |
159 | 221 | sage: d = DynkinDiagram_class(CartanType(['A',3])) |
160 | 222 | sage: list(sorted(d.edges())) |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
198 | 260 | [ 2 -1 -1] |
199 | 261 | [-2 2 -1] |
200 | 262 | [-1 -1 2] |
201 | | |
| 263 | |
202 | 264 | """ |
203 | 265 | # hyperbolic Dynkin diagram of Exercise 4.9 p. 57 of Kac Infinite Dimensional Lie Algebras. |
204 | 266 | g = DynkinDiagram() |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
214 | 276 | def index_set(self): |
215 | 277 | """ |
216 | 278 | EXAMPLES:: |
217 | | |
| 279 | |
218 | 280 | sage: DynkinDiagram(['C',3]).index_set() |
219 | 281 | [1, 2, 3] |
220 | 282 | sage: DynkinDiagram("A2","B2","F4").index_set() |
221 | 283 | [1, 2, 3, 4, 5, 6, 7, 8] |
222 | 284 | """ |
223 | 285 | return self.vertices() |
224 | | |
| 286 | |
225 | 287 | def cartan_type(self): |
226 | 288 | """ |
227 | 289 | EXAMPLES:: |
228 | | |
| 290 | |
229 | 291 | sage: DynkinDiagram("A2","B2","F4").cartan_type() |
230 | 292 | A2xB2xF4 |
231 | 293 | """ |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
234 | 296 | def rank(self): |
235 | 297 | r""" |
236 | 298 | Returns the index set for this Dynkin diagram |
237 | | |
| 299 | |
238 | 300 | EXAMPLES:: |
239 | | |
| 301 | |
240 | 302 | sage: DynkinDiagram(['C',3]).rank() |
241 | 303 | 3 |
242 | 304 | sage: DynkinDiagram("A2","B2","F4").rank() |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
247 | 309 | def dynkin_diagram(self): |
248 | 310 | """ |
249 | 311 | EXAMPLES:: |
250 | | |
| 312 | |
251 | 313 | sage: DynkinDiagram(['C',3]).dynkin_diagram() |
252 | 314 | O---O=<=O |
253 | 315 | 1 2 3 |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
280 | 342 | def dual(self): |
281 | 343 | r""" |
282 | 344 | Returns the dual Dynkin diagram, obtained by reversing all edges. |
283 | | |
| 345 | |
284 | 346 | EXAMPLES:: |
285 | | |
| 347 | |
286 | 348 | sage: D = DynkinDiagram(['C',3]) |
287 | 349 | sage: D.edges() |
288 | 350 | [(1, 2, 1), (2, 1, 1), (2, 3, 1), (3, 2, 2)] |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
294 | 356 | [(1, 2, 1), (2, 1, 1), (2, 3, 2), (3, 2, 1)] |
295 | 357 | sage: D.dual() == DynkinDiagram(['B',3]) |
296 | 358 | True |
297 | | |
| 359 | |
298 | 360 | TESTS:: |
299 | | |
| 361 | |
300 | 362 | sage: D = DynkinDiagram(['A',0]); D |
301 | 363 | A0 |
302 | 364 | sage: D.edges() |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
335 | 397 | """ |
336 | 398 | return True |
337 | 399 | |
338 | | |
339 | 400 | def __getitem__(self, i): |
340 | 401 | r""" |
341 | 402 | With a tuple (i,j) as argument, returns the scalar product |
342 | 403 | `\langle |
343 | 404 | \alpha^\vee_i, \alpha_j\rangle`. |
344 | | |
| 405 | |
345 | 406 | Otherwise, behaves as the usual DiGraph.__getitem__ |
346 | | |
| 407 | |
347 | 408 | EXAMPLES: We use the `C_4` dynkin diagram as a cartan |
348 | 409 | matrix:: |
349 | | |
| 410 | |
350 | 411 | sage: g = DynkinDiagram(['C',4]) |
351 | 412 | sage: matrix([[g[i,j] for j in range(1,5)] for i in range(1,5)]) |
352 | 413 | [ 2 -1 0 0] |
353 | 414 | [-1 2 -1 0] |
354 | 415 | [ 0 -1 2 -2] |
355 | 416 | [ 0 0 -1 2] |
356 | | |
| 417 | |
357 | 418 | The neighbors of a node can still be obtained in the usual way:: |
358 | | |
| 419 | |
359 | 420 | sage: [g[i] for i in range(1,5)] |
360 | 421 | [[2], [1, 3], [2, 4], [3]] |
361 | 422 | """ |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
374 | 435 | Returns the `j^{th}` column `(a_{i,j})_i` of the |
375 | 436 | Cartan matrix corresponding to this Dynkin diagram, as a container |
376 | 437 | (or iterator) of tuples `(i, a_{i,j})` |
377 | | |
| 438 | |
378 | 439 | EXAMPLES:: |
379 | | |
| 440 | |
380 | 441 | sage: g = DynkinDiagram(["B",4]) |
381 | 442 | sage: [ (i,a) for (i,a) in g.column(3) ] |
382 | 443 | [(3, 2), (2, -1), (4, -2)] |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
388 | 449 | Returns the `i^{th}` row `(a_{i,j})_j` of the |
389 | 450 | Cartan matrix corresponding to this Dynkin diagram, as a container |
390 | 451 | (or iterator) of tuples `(j, a_{i,j})` |
391 | | |
| 452 | |
392 | 453 | EXAMPLES:: |
393 | | |
| 454 | |
394 | 455 | sage: g = DynkinDiagram(["C",4]) |
395 | 456 | sage: [ (i,a) for (i,a) in g.row(3) ] |
396 | 457 | [(3, 2), (2, -1), (4, -2)] |
397 | 458 | """ |
398 | 459 | return [(i,2)] + [(j,-m) for (j, i1, m) in self.incoming_edges(i)] |
399 | | |
| 460 | |
400 | 461 | def digraph(self): |
401 | 462 | """ |
402 | 463 | Returns the DiGraph associated to self. |
… |
… |
class DynkinDiagram_class(DiGraph, Carta |
417 | 478 | G.set_latex_options(format="dot2tex", edge_labels = True, color_by_label = self.cartan_type()._index_set_coloring, |
418 | 479 | edge_options = lambda (u,v,label): ({"backward":label ==0})) |
419 | 480 | return G |
420 | | |
| 481 | |
421 | 482 | def _latex_(self, **options): |
422 | 483 | r""" |
423 | 484 | Returns the crystal graph as a latex string. This can be exported |
424 | 485 | to a file with self.latex_file('filename'). |
425 | | |
| 486 | |
426 | 487 | EXAMPLES:: |
427 | | |
| 488 | |
428 | 489 | """ |
429 | 490 | if not have_dot2tex(): |
430 | 491 | print "dot2tex not available. Install after running \'sage -sh\'" |
431 | 492 | return |
432 | 493 | G = self.digraph() |
433 | | G.set_latex_options(format="dot2tex", edge_labels = True, |
| 494 | G.set_latex_options(format="dot2tex", edge_labels = True, |
434 | 495 | edge_options = lambda (u,v,label): ({"backward":label ==0}), **options) |
435 | 496 | return G._latex_() |
436 | 497 | |
437 | 498 | def precheck(t, letter=None, length=None, affine=None, n_ge=None, n=None): |
438 | 499 | """ |
439 | 500 | EXAMPLES:: |
440 | | |
| 501 | |
441 | 502 | sage: from sage.combinat.root_system.dynkin_diagram import precheck |
442 | 503 | sage: ct = CartanType(['A',4]) |
443 | 504 | sage: precheck(ct, letter='C') |
… |
… |
def precheck(t, letter=None, length=None |
468 | 529 | if length is not None: |
469 | 530 | if len(t) != length: |
470 | 531 | raise ValueError, "len(t) must be = %s"%length |
471 | | |
| 532 | |
472 | 533 | if affine is not None: |
473 | 534 | try: |
474 | 535 | if t[2] != affine: |