# Root lattice realizations¶

class sage.combinat.root_system.root_lattice_realizations.RootLatticeRealizations(base, name=None)

The category of root lattice realizations over a given base ring

A root lattice realization $$L$$ over a base ring $$R$$ is a free module (or vector space if $$R$$ is a field) endowed with an embedding of the root lattice of some root system.

Typical root lattice realizations over $$\ZZ$$ include the root lattice, weight lattice, and ambient lattice. Typical root lattice realizations over $$\QQ$$ include the root space, weight space, and ambient space.

To describe the embedding, a root lattice realization must implement a method simple_root() (i) returning for each $$i$$ in the index set the image of the simple root $$\alpha_i$$ under the embedding.

A root lattice realization must further implement a method on elements scalar(), computing the scalar product with elements of the coroot lattice or coroot space.

Using those, this category provides tools for reflections, roots, the Weyl group and its action, ...

EXAMPLES:

Here, we consider the root system of type $$A_7$$, and embed the root lattice element $$x = \alpha_2 + 2 \alpha_6$$ in several root lattice realizations:

sage: R = RootSystem(["A",7])
sage: alpha = R.root_lattice().simple_roots()
sage: x = alpha[2] + 2 * alpha[5]

sage: L = R.root_space()
sage: L(x)
alpha[2] + 2*alpha[5]

sage: L = R.weight_lattice()
sage: L(x)
-Lambda[1] + 2*Lambda[2] - Lambda[3] - 2*Lambda[4] + 4*Lambda[5] - 2*Lambda[6]

sage: L = R.ambient_space()
sage: L(x)
(0, 1, -1, 0, 2, -2, 0, 0)


We embed the root space element $$x = \alpha_2 + 1/2 \alpha_6$$ in several root lattice realizations:

sage: alpha = R.root_space().simple_roots()
sage: x = alpha[2] + 1/2 * alpha[5]

sage: L = R.weight_space()
sage: L(x)
-Lambda[1] + 2*Lambda[2] - Lambda[3] - 1/2*Lambda[4] + Lambda[5] - 1/2*Lambda[6]

sage: L = R.ambient_space()
sage: L(x)
(0, 1, -1, 0, 1/2, -1/2, 0, 0)


Of course, one can’t embed the root space in the weight lattice:

sage: L = R.weight_lattice()
sage: L(x)
Traceback (most recent call last):
...
TypeError: do not know how to make x (= alpha[2] + 1/2*alpha[5]) an element of self (=Weight lattice of the Root system of type ['A', 7])


If $$K_1$$ is a subring of $$K_2$$, then one could in theory have an embedding from the root space over $$K_1$$ to any root lattice realization over $$K_2$$; this is not implemented:

sage: K1 = QQ
sage: K2 = QQ['q']
sage: L = R.weight_space(K2)

sage: alpha = R.root_space(K2).simple_roots()
sage: L(alpha[1])
2*Lambda[1] - Lambda[2]

sage: alpha = R.root_space(K1).simple_roots()
sage: L(alpha[1])
Traceback (most recent call last):
...
TypeError: do not know how to make x (= alpha[1]) an element of self (=Weight space over the Univariate Polynomial Ring in q over Rational Field of the Root system of type ['A', 7])


By a slight abuse, the embedding of the root lattice is not actually required to be faithful. Typically for an affine root system, the null root of the root lattice is killed in the non extended weight lattice:

sage: R = RootSystem(["A", 3, 1])
sage: delta = R.root_lattice().null_root()
sage: L = R.weight_lattice()
sage: L(delta)
0


TESTS:

sage: TestSuite(L).run()

class ElementMethods
associated_coroot()

Returns the coroot associated to this root

EXAMPLES:

sage: alpha = RootSystem(["A", 3]).root_space().simple_roots()
sage: alpha[1].associated_coroot()
alphacheck[1]

associated_reflection()

Given a positive root self, returns a reduced word for the reflection orthogonal to self.

Since the answer is cached, it is a tuple instead of a list.

EXAMPLES:

sage: RootSystem(['C',3]).root_lattice().simple_root(3).weyl_action([1,2]).associated_reflection()
(1, 2, 3, 2, 1)
sage: RootSystem(['C',3]).root_lattice().simple_root(2).associated_reflection()
(2,)

descents(index_set=None, positive=False)

Returns the descents of pt

EXAMPLES:

sage: space=RootSystem(['A',5]).weight_space()
sage: alpha=space.simple_roots()
sage: (alpha[1]+alpha[2]+alpha[4]).descents()
[3, 5]

first_descent(index_set=None, positive=False)

Returns the first descent of pt

One can use the index_set option to restrict to the parabolic subgroup indexed by index_set.

EXAMPLES:

sage: space=RootSystem(['A',5]).weight_space()
sage: alpha=space.simple_roots()
sage: (alpha[1]+alpha[2]+alpha[4]).first_descent()
3
sage: (alpha[1]+alpha[2]+alpha[4]).first_descent([1,2,5])
5
sage: (alpha[1]+alpha[2]+alpha[4]).first_descent([1,2,5,3,4])
5

greater()

Returns the elements in the orbit of self which are greater than self in the weak order.

EXAMPLES:

sage: L = RootSystem(['A',3]).ambient_lattice()
sage: e = L.basis()
sage: e[2].greater()
[(0, 0, 1, 0), (0, 0, 0, 1)]
sage: len(L.rho().greater())
24
sage: len((-L.rho()).greater())
1
sage: sorted([len(x.greater()) for x in L.rho().orbit()])
[1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 8, 8, 8, 8, 12, 12, 12, 24]

has_descent(i, positive=False)

Test if self has a descent at position $$i$$, that is if self is on the strict negative side of the $$i^{th}$$ simple reflection hyperplane.

If positive if True, tests if it is on the strict positive side instead.

EXAMPLES:

sage: space=RootSystem(['A',5]).weight_space()
sage: alpha=RootSystem(['A',5]).weight_space().simple_roots()
sage: [alpha[i].has_descent(1) for i in space.index_set()]
[False, True, False, False, False]
sage: [(-alpha[i]).has_descent(1) for i in space.index_set()]
[True, False, False, False, False]
sage: [alpha[i].has_descent(1, True) for i in space.index_set()]
[True, False, False, False, False]
sage: [(-alpha[i]).has_descent(1, True) for i in space.index_set()]
[False, True, False, False, False]
sage: (alpha[1]+alpha[2]+alpha[4]).has_descent(3)
True
sage: (alpha[1]+alpha[2]+alpha[4]).has_descent(1)
False
sage: (alpha[1]+alpha[2]+alpha[4]).has_descent(1, True)
True

is_dominant(index_set=None, positive=True)

Returns whether self is dominant.

This is done with respect to the subrootsystem indicated by the subset of Dynkin nodes index_set. If index_set is None then the entire Dynkin node set is used. If positive is False then the dominance condition is replaced by antidominance.

EXAMPLES:

sage: L = RootSystem(['A',2]).ambient_lattice()
sage: Lambda = L.fundamental_weights()
sage: [x.is_dominant() for x in Lambda]
[True, True]
sage: [x.is_dominant(positive=False) for x in Lambda]
[False, False]
sage: (Lambda[1]-Lambda[2]).is_dominant()
False
sage: (-Lambda[1]+Lambda[2]).is_dominant()
False
sage: (Lambda[1]-Lambda[2]).is_dominant([1])
True
sage: (Lambda[1]-Lambda[2]).is_dominant([2])
False
sage: [x.is_dominant() for x in L.roots()]
[False, True, False, False, False, False]
sage: [x.is_dominant(positive=False) for x in L.roots()]
[False, False, False, False, True, False]

is_dominant_weight()

Tests whether self is a dominant element of the weight lattice

EXAMPLES:

sage: L = RootSystem(['A',2]).ambient_lattice()
sage: Lambda = L.fundamental_weights()
sage: [x.is_dominant() for x in Lambda]
[True, True]
sage: (3*Lambda[1]+Lambda[2]).is_dominant()
True
sage: (Lambda[1]-Lambda[2]).is_dominant()
False
sage: (-Lambda[1]+Lambda[2]).is_dominant()
False


Warning

The current implementation tests that the scalar products with the coroots are all non negative integers, which is not sufficient. For example, if $$x$$ is the sum of a dominant element of the weight lattice plus some other element orthogonal to all coroots, then the current implementation erroneously reports $$x$$ to be a dominant weight:

sage: x = Lambda[1] + L([-1,-1,-1])
sage: x.is_dominant_weight()
True

is_parabolic_root(index_set)

Supposing that self is a root, is it in the parabolic subsystem with Dynkin nodes index_set?

INPUT:

• index_set – the Dynkin node set of the parabolic subsystem.

Todo

This implementation is only valid in the root or weight lattice

EXAMPLES:

sage: alpha = RootSystem(['A',3]).root_lattice().from_vector(vector([1,1,0]))
sage: alpha.is_parabolic_root([1,3])
False
sage: alpha.is_parabolic_root([1,2])
True
sage: alpha.is_parabolic_root([2])
False

level()

EXAMPLES:

sage: L = RootSystem(['A',2,1]).weight_lattice()
sage: L.rho().level()
3

orbit()

The orbit of self under the action of the Weyl group

EXAMPLES:

$$\rho$$ is a regular element whose orbit is in bijection with the Weyl group. In particular, it as 6 elements for the symmetric group $$S_3$$:

sage: L = RootSystem(["A", 2]).ambient_lattice()
sage: sorted(L.rho().orbit())               # the output order is not specified
[(1, 2, 0), (1, 0, 2), (2, 1, 0), (2, 0, 1), (0, 1, 2), (0, 2, 1)]

sage: L = RootSystem(["A", 3]).weight_lattice()
sage: len(L.rho().orbit())
24
sage: len(L.fundamental_weights()[1].orbit())
4
sage: len(L.fundamental_weights()[2].orbit())
6

pred()

Returns the immediate predecessors of self for the weak order

EXAMPLES:

sage: L = RootSystem(['A',3]).weight_lattice()
sage: Lambda = L.fundamental_weights()
sage: Lambda[1].pred()
[]
sage: L.rho().pred()
[]
sage: (-L.rho()).pred()
[Lambda[1] - 2*Lambda[2] - Lambda[3], -2*Lambda[1] + Lambda[2] - 2*Lambda[3], -Lambda[1] - 2*Lambda[2] + Lambda[3]]

reduced_word(index_set=None, positive=True)

Returns a reduced word for the inverse of the shortest Weyl group element that sends the vector self into the dominant chamber.

With the index_set optional parameter, this is done with respect to the corresponding parabolic subgroup.

If positive is False, use the antidominant chamber instead.

EXAMPLES:

sage: space=RootSystem(['A',5]).weight_space()
sage: alpha=RootSystem(['A',5]).weight_space().simple_roots()
sage: alpha[1].reduced_word()
[2, 3, 4, 5]
sage: alpha[1].reduced_word([1,2])
[2]

reflection(root, use_coroot=False)

Reflects self across the hyperplane orthogonal to root.

If use_coroot is True, root is interpreted as a coroot.

EXAMPLES:

sage: R = RootSystem(['C',4])
sage: weight_lattice = R.weight_lattice()
sage: mu = weight_lattice.from_vector(vector([0,0,1,2]))
sage: coroot_lattice = R.coroot_lattice()
sage: alphavee = coroot_lattice.from_vector(vector([0,0,1,1]))
sage: mu.reflection(alphavee, use_coroot=True)
6*Lambda[2] - 5*Lambda[3] + 2*Lambda[4]
sage: root_lattice = R.root_lattice()
sage: beta = root_lattice.from_vector(vector([0,1,1,0]))
sage: mu.reflection(beta)
Lambda[1] - Lambda[2] + 3*Lambda[4]

scalar(lambdacheck)

Implement the natural pairing with the coroot lattice.

INPUT:

• self – an element of a root lattice realization
• lambdacheck – an element of the coroot lattice or coroot space

OUTPUT: the scalar product of self and lambdacheck

EXAMPLES:

sage: L = RootSystem(['A',4]).root_lattice()
sage: alpha      = L.simple_roots()
sage: alphacheck = L.simple_coroots()
sage: alpha[1].scalar(alphacheck[1])
2
sage: alpha[1].scalar(alphacheck[2])
-1
sage: matrix([ [ alpha[i].scalar(alphacheck[j])
...              for i in L.index_set() ]
...            for j in L.index_set() ])
[ 2 -1  0  0]
[-1  2 -1  0]
[ 0 -1  2 -1]
[ 0  0 -1  2]


TESTS:

sage: super(sage.combinat.root_system.root_space.RootSpaceElement,alpha[1]).scalar(alphacheck[1])
Traceback (most recent call last):
...
NotImplementedError: <abstract method scalar at ...>

simple_reflection(i)

Returns the image of self by the $$i$$-th simple reflection.

EXAMPLES:

sage: alpha = RootSystem(["A", 3]).root_lattice().alpha()
sage: alpha[1].simple_reflection(2)
alpha[1] + alpha[2]

sage: Q = RootSystem(['A', 3, 1]).weight_lattice(extended = True)
sage: Lambda = Q.fundamental_weights()
sage: L = Lambda[0] + Q.null_root()
sage: L.simple_reflection(0)
-Lambda[0] + Lambda[1] + Lambda[3]

simple_reflections()

The images of self by all the simple reflections

EXAMPLES:

sage: alpha = RootSystem(["A", 3]).root_lattice().alpha()
sage: alpha[1].simple_reflections()
[-alpha[1], alpha[1] + alpha[2], alpha[1]]

smaller()

Returns the elements in the orbit of self which are smaller than self in the weak order.

EXAMPLES:

sage: L = RootSystem(['A',3]).ambient_lattice()
sage: e = L.basis()
sage: e[2].smaller()
[(0, 0, 1, 0), (0, 1, 0, 0), (1, 0, 0, 0)]
sage: len(L.rho().smaller())
1
sage: len((-L.rho()).smaller())
24
sage: sorted([len(x.smaller()) for x in L.rho().orbit()])
[1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 8, 8, 8, 8, 12, 12, 12, 24]

succ()

Returns the immediate successors of self for the weak order

EXAMPLES:

sage: L = RootSystem(['A',3]).weight_lattice()
sage: Lambda = L.fundamental_weights()
sage: Lambda[1].succ()
[-Lambda[1] + Lambda[2]]
sage: L.rho().succ()
[-Lambda[1] + 2*Lambda[2] + Lambda[3], 2*Lambda[1] - Lambda[2] + 2*Lambda[3], Lambda[1] + 2*Lambda[2] - Lambda[3]]
sage: (-L.rho()).succ()
[]

to_dominant_chamber(index_set=None, positive=True, reduced_word=False)

Returns the unique dominant element in the Weyl group orbit of the vector self.

If positive is False, returns the antidominant orbit element.

With the index_set optional parameter, this is done with respect to the corresponding parabolic subgroup.

If reduced_word is True, returns the 2-tuple (weight, direction) where weight is the (anti)dominant orbit element and direction is a reduced word for the Weyl group element sending weight to self.

Warning

In infinite type, an orbit may not contain a dominant element. In this case the function may go into an infinite loop.

For affine root systems, errors are generated if the orbit does not contain the requested kind of representative. If the input vector is of positive (resp. negative) level, then there is a dominant (resp. antidominant) element in its orbit but not an antidominant (resp. dominant) one. If the vector is of level zero, then there are neither dominant nor antidominant orbit representatives, except for multiples of the null root, which are themselves both dominant and antidominant orbit representatives.

EXAMPLES:

sage: space=RootSystem(['A',5]).weight_space()
sage: alpha=RootSystem(['A',5]).weight_space().simple_roots()
sage: alpha[1].to_dominant_chamber()
Lambda[1] + Lambda[5]
sage: alpha[1].to_dominant_chamber([1,2])
Lambda[1] + Lambda[2] - Lambda[3]
sage: wl=RootSystem(['A',2,1]).weight_lattice(extended=True)
sage: mu=wl.from_vector(vector([1,-3,0]))
sage: mu.to_dominant_chamber(positive=False, reduced_word = True)
(-Lambda[1] - Lambda[2] - delta, [0, 2])

sage: R = RootSystem(['A',1,1])
sage: rl = R.root_lattice()
sage: nu = rl.zero()
sage: nu.to_dominant_chamber()
0
sage: nu.to_dominant_chamber(positive=False)
0
sage: mu = rl.from_vector(vector([0,1]))
sage: mu.to_dominant_chamber()
Traceback (most recent call last):
...
ValueError: alpha[1] is not in the orbit of the fundamental chamber
sage: mu.to_dominant_chamber(positive=False)
Traceback (most recent call last):
...
ValueError: alpha[1] is not in the orbit of the negative of the fundamental chamber

to_positive_chamber(*args, **kwds)

Deprecated: Use to_dominant_chamber() instead. See trac ticket #12667 for details.

to_simple_root(reduced_word=False)

Return (the index of) a simple root in the orbit of the positive root self.

INPUT:

• self – a positive root
• reduced_word – a boolean (default: False)

OUTPUT:

• The index $$i$$ of a simple root $$\alpha_i$$. If reduced_word is True, this returns instead a pair (i, word), where word is a sequence of reflections mapping $$\alpha_i$$ up the root poset to self.

EXAMPLES:

sage: L = RootSystem(["A",3]).root_lattice()
sage: for alpha in L.positive_roots():
...       print alpha, alpha.to_simple_root()
alpha[1] 1
alpha[2] 2
alpha[3] 3
alpha[1] + alpha[2] 2
alpha[2] + alpha[3] 3
alpha[1] + alpha[2] + alpha[3] 3
sage: for alpha in L.positive_roots():
...        print alpha, alpha.to_simple_root(reduced_word=True)
alpha[1] (1, ())
alpha[2] (2, ())
alpha[3] (3, ())
alpha[1] + alpha[2] (2, (1,))
alpha[2] + alpha[3] (3, (2,))
alpha[1] + alpha[2] + alpha[3] (3, (1, 2))


ALGORITHM:

This method walks from self down to the antidominant chamber by applying successively the simple reflection given by the first descent. Since self is a positive root, each step goes down the root poset, and one must eventually cross a simple root $$\alpha_i$$.

See also

Warning

The behavior is not specified if the input is not a positive root. For a finite root system, this is currently caught (albeit with a not perfect message):

sage: alpha = L.simple_roots()
sage: (2*alpha[1]).to_simple_root()
Traceback (most recent call last):
...
ValueError: -2*alpha[1] - 2*alpha[2] - 2*alpha[3] is not a positive root


For an infinite root systems, this method may run into an infinite reccursion if the input is not a positive root.

translation(x)
INPUT:
• self - an element $$t$$ at level $$0$$
• x - an element of the same space

Returns $$x$$ translated by $$t$$, that is $$x+level(x) t$$

EXAMPLES:

sage: L = RootSystem(['A',2,1]).weight_lattice()
sage: alpha = L.simple_roots()
sage: Lambda = L.fundamental_weights()
sage: t = alpha[2]


Let us look at the translation of an element of level $$1$$:

sage: Lambda[1].level()
1
sage: t.translation(Lambda[1])
-Lambda[0] + 2*Lambda[2]
sage: Lambda[1] + t
-Lambda[0] + 2*Lambda[2]


and of an element of level $$0$$:

sage: alpha [1].level()
0
sage: t.translation(alpha [1])
-Lambda[0] + 2*Lambda[1] - Lambda[2]
sage: alpha[1] + 0*t
-Lambda[0] + 2*Lambda[1] - Lambda[2]


The arguments are given in this seemingly unnatural order to make it easy to construct the translation function:

sage: f = t.translation
sage: f(Lambda[1])
-Lambda[0] + 2*Lambda[2]

weyl_action(element, inverse=False)

Acts on self by an element of the Coxeter or Weyl group.

INPUT:

• element – an element of a Coxeter or Weyl group of the same Cartan type, or a tuple or a list (such as a reduced word) of elements from the index set.
• inverse – a boolean (default: False); whether to act by the inverse element.

EXAMPLES:

sage: wl = RootSystem(['A',3]).weight_lattice()
sage: mu = wl.from_vector(vector([1,0,-2]))
sage: mu
Lambda[1] - 2*Lambda[3]
sage: mudom, rw = mu.to_dominant_chamber(positive=False, reduced_word = True)
sage: mudom, rw
(-Lambda[2] - Lambda[3], [1, 2])


Acting by a (reduced) word:

sage: mudom.weyl_action(rw)
Lambda[1] - 2*Lambda[3]
sage: mu.weyl_action(rw, inverse = True)
-Lambda[2] - Lambda[3]


Acting by an element of the Coxeter or Weyl group on a vector in its own lattice of definition (implemented by matrix multiplication on a vector):

sage: w = wl.weyl_group().from_reduced_word([1, 2])
sage: mudom.weyl_action(w)
Lambda[1] - 2*Lambda[3]


Acting by an element of an isomorphic Coxeter or Weyl group (implemented by the action of a corresponding reduced word):

sage: W = WeylGroup(['A',3], prefix="s")
sage: w = W.from_reduced_word([1, 2])
sage: wl.weyl_group() == W
False
sage: mudom.weyl_action(w)
Lambda[1] - 2*Lambda[3]

weyl_stabilizer(index_set=None)

Returns the subset of Dynkin nodes whose reflections fix self.

If index_set is not None, only consider nodes in this set. Note that if self is dominant or antidominant, then its stabilizer is the parabolic subgroup defined by the returned node set.

EXAMPLES:

sage: wl = RootSystem(['A',2,1]).weight_lattice(extended = True)
sage: al = wl.null_root()
sage: al.weyl_stabilizer()
[0, 1, 2]
sage: wl = RootSystem(['A',4]).weight_lattice()
sage: mu = wl.from_vector(vector([1,1,0,0]))
sage: mu.weyl_stabilizer()
[3, 4]
sage: mu.weyl_stabilizer(index_set = [1,2,3])
[3]

class RootLatticeRealizations.ParentMethods
a_long_simple_root()

Returns a long simple root, corresponding to the highest outgoing edge in the Dynkin diagram.

Caveat: this may be break in affine type $$A_{2n}^{(2)}$$

Caveat: meaningful/broken for non irreducible?

TODO: implement CartanType.nodes_by_length as in MuPAD-Combinat (using CartanType.symmetrizer), and use it here.

TESTS:

sage: X=RootSystem(['A',1]).weight_space()
sage: X.a_long_simple_root()
2*Lambda[1]
sage: X=RootSystem(['A',5]).weight_space()
sage: X.a_long_simple_root()
2*Lambda[1] - Lambda[2]

almost_positive_roots()

Returns the almost positive roots of self

These are the positive roots together with the simple negative roots.

See also

almost_positive_root_decomposition(), tau_plus_minus()

EXAMPLES:

sage: L = RootSystem(['A',2]).root_lattice()
sage: L.almost_positive_roots()
[-alpha[1], alpha[1], alpha[1] + alpha[2], -alpha[2], alpha[2]]

almost_positive_roots_decomposition()

Returns the decomposition of the almost positive roots of self

This is the list of the orbits of the almost positive roots under the action of the dihedral group generated by the operators $$\tau_+$$ and $$\tau_-$$.

See also

EXAMPLES:

sage: RootSystem(['A',2]).root_lattice().almost_positive_roots_decomposition()
[[-alpha[1], alpha[1], alpha[1] + alpha[2], alpha[2], -alpha[2]]]

sage: RootSystem(['B',2]).root_lattice().almost_positive_roots_decomposition()
[[-alpha[1], alpha[1], alpha[1] + 2*alpha[2]], [-alpha[2], alpha[2], alpha[1] + alpha[2]]]

sage: RootSystem(['D',4]).root_lattice().almost_positive_roots_decomposition()
[[-alpha[1], alpha[1], alpha[1] + alpha[2], alpha[2] + alpha[3] + alpha[4]],
[-alpha[2], alpha[2], alpha[1] + alpha[2] + alpha[3] + alpha[4], alpha[1] + 2*alpha[2] + alpha[3] + alpha[4]],
[-alpha[3], alpha[3], alpha[2] + alpha[3], alpha[1] + alpha[2] + alpha[4]],
[-alpha[4], alpha[4], alpha[2] + alpha[4], alpha[1] + alpha[2] + alpha[3]]]


REFERENCES:

 [CFZ2] Chapoton, Fomin, Zelevinsky - Polytopal realizations of generalized associahedra
alpha()

Returns the family $$(\alpha_i)_{i\in I}$$ of the simple roots, with the extra feature that, for simple irreducible root systems, $$\alpha_0$$ yields the opposite of the highest root.

EXAMPLES:

sage: alpha = RootSystem(["A",2]).root_lattice().alpha()
sage: alpha[1]
alpha[1]
sage: alpha[0]
-alpha[1] - alpha[2]

alphacheck()

Returns the family $$( \alpha^\vee_i)_{i\in I}$$ of the simple coroots, with the extra feature that, for simple irreducible root systems, $$\alpha^\vee_0$$ yields the coroot associated to the opposite of the highest root (caveat: for non simply laced root systems, this is not the opposite of the highest coroot!)

EXAMPLES:

sage: alphacheck = RootSystem(["A",2]).ambient_space().alphacheck()
sage: alphacheck
Finite family {1: (1, -1, 0), 2: (0, 1, -1)}


Here is now $$\alpha^\vee_0$$:

(-1, 0, 1)

Todo

add a non simply laced example

Finaly, here is an affine example:

sage: RootSystem(["A",2,1]).weight_space().alphacheck()
Finite family {0: alphacheck[0], 1: alphacheck[1], 2: alphacheck[2]}

sage: RootSystem(["A",3]).ambient_space().alphacheck()
Finite family {1: (1, -1, 0, 0), 2: (0, 1, -1, 0), 3: (0, 0, 1, -1)}

cartan_type()

EXAMPLES:

sage: r = RootSystem(['A',4]).root_space()
sage: r.cartan_type()
['A', 4]

classical()

Return the corresponding root/weight/ambient lattice/space.

EXAMPLES:

sage: RootSystem(["A",4,1]).root_lattice().classical()
Root lattice of the Root system of type ['A', 4]
sage: RootSystem(["A",4,1]).weight_lattice().classical()
Weight lattice of the Root system of type ['A', 4]
sage: RootSystem(["A",4,1]).ambient_space().classical()
Ambient space of the Root system of type ['A', 4]

cohighest_root()

Returns the associated coroot of the highest root.

Note

this is usually not the highest coroot.

EXAMPLES:

sage: RootSystem(['A', 3]).ambient_space().cohighest_root()
(1, 0, 0, -1)

coroot_lattice()

Returns the coroot lattice.

EXAMPLES:

sage: RootSystem(['A',2]).root_lattice().coroot_lattice()
Coroot lattice of the Root system of type ['A', 2]

coroot_space(base_ring=Rational Field)

Returns the coroot space over base_ring

INPUT:

• base_ring – a ring (default: $$\QQ$$)

EXAMPLES:

sage: RootSystem(['A',2]).root_lattice().coroot_space()
Coroot space over the Rational Field of the Root system of type ['A', 2]

sage: RootSystem(['A',2]).root_lattice().coroot_space(QQ['q'])
Coroot space over the Univariate Polynomial Ring in q over Rational Field of the Root system of type ['A', 2]

dynkin_diagram()

EXAMPLES:

sage: r = RootSystem(['A',4]).root_space()
sage: r.dynkin_diagram()
O---O---O---O
1   2   3   4
A4

fundamental_weights_from_simple_roots()

Return the fundamental weights.

This is computed from the simple roots by using the inverse of the Cartan matrix. This method is therefore only valid for finite types and if this realization of the root lattice is large enough to contain them.

EXAMPLES:

In the root space, we retrieve the inverse of the Cartan matrix:

sage: L = RootSystem(["B",3]).root_space()
sage: L.fundamental_weights_from_simple_roots()
Finite family {1:     alpha[1] +   alpha[2] +     alpha[3],
2:     alpha[1] + 2*alpha[2] +   2*alpha[3],
3: 1/2*alpha[1] +   alpha[2] + 3/2*alpha[3]}
sage: ~L.cartan_type().cartan_matrix()
[  1   1 1/2]
[  1   2   1]
[  1   2 3/2]


In the weight lattice and the ambient space, we retrieve the fundamental weights:

sage: L = RootSystem(["B",3]).weight_lattice()
sage: L.fundamental_weights_from_simple_roots()
Finite family {1: Lambda[1], 2: Lambda[2], 3: Lambda[3]}

sage: L = RootSystem(["B",3]).ambient_space()
sage: L.fundamental_weights()
Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1/2, 1/2, 1/2)}
sage: L.fundamental_weights_from_simple_roots()
Finite family {1: (1, 0, 0), 2: (1, 1, 0), 3: (1/2, 1/2, 1/2)}


However the fundamental weights do not belong to the root lattice:

sage: L = RootSystem(["B",3]).root_lattice()
sage: L.fundamental_weights_from_simple_roots()
Traceback (most recent call last):
...
ValueError: The fundamental weights do not live in this realization of the root lattice


Beware of the usual $$GL_n$$ vs $$SL_n$$ catch in type $$A$$:

sage: L = RootSystem(["A",3]).ambient_space()
sage: L.fundamental_weights()
Finite family {1: (1, 0, 0, 0), 2: (1, 1, 0, 0), 3: (1, 1, 1, 0)}
sage: L.fundamental_weights_from_simple_roots()
Finite family {1: (3/4, -1/4, -1/4, -1/4), 2: (1/2, 1/2, -1/2, -1/2), 3: (1/4, 1/4, 1/4, -3/4)}

sage: L = RootSystem(["A",3]).ambient_lattice()
sage: L.fundamental_weights_from_simple_roots()
Traceback (most recent call last):
...
ValueError: The fundamental weights do not live in this realization of the root lattice

highest_root()

Returns the highest root (for an irreducible finite root system)

EXAMPLES:

sage: RootSystem(['A',4]).ambient_space().highest_root()
(1, 0, 0, 0, -1)

sage: RootSystem(['E',6]).weight_space().highest_root()
Lambda[2]

index_set()

EXAMPLES:

sage: r = RootSystem(['A',4]).root_space()
sage: r.index_set()
[1, 2, 3, 4]

negative_roots()

Returns the negative roots of self.

EXAMPLES:

sage: L = RootSystem(['A', 2]).weight_lattice()
sage: sorted(L.negative_roots())
[-2*Lambda[1] + Lambda[2], -Lambda[1] - Lambda[2], Lambda[1] - 2*Lambda[2]]


Algorithm: negate the positive roots

null_coroot()

Returns the null coroot of self.

The null coroot is the smallest non trivial positive coroot which is orthogonal to all simple roots. It exists for any affine root system.

EXAMPLES:

sage: RootSystem(['C',2,1]).root_lattice().null_coroot()
alphacheck[0] + alphacheck[1] + alphacheck[2]
sage: RootSystem(['D',4,1]).root_lattice().null_coroot()
alphacheck[0] + alphacheck[1] + 2*alphacheck[2] + alphacheck[3] + alphacheck[4]
sage: RootSystem(['F',4,1]).root_lattice().null_coroot()
alphacheck[0] + 2*alphacheck[1] + 3*alphacheck[2] + 2*alphacheck[3] + alphacheck[4]

null_root()

Returns the null root of self. The null root is the smallest non trivial positive root which is orthogonal to all simple coroots. It exists for any affine root system.

EXAMPLES:

sage: RootSystem(['C',2,1]).root_lattice().null_root()
alpha[0] + 2*alpha[1] + alpha[2]
sage: RootSystem(['D',4,1]).root_lattice().null_root()
alpha[0] + alpha[1] + 2*alpha[2] + alpha[3] + alpha[4]
sage: RootSystem(['F',4,1]).root_lattice().null_root()
alpha[0] + 2*alpha[1] + 3*alpha[2] + 4*alpha[3] + 2*alpha[4]

pi()

The simple projections of self

Warning

this shortcut is deprecated

EXAMPLES:

sage: space = RootSystem(['A',2]).weight_lattice()
sage: pi = space.pi
sage: x = space.simple_roots()
sage: pi[1](x[2])
-Lambda[1] + 2*Lambda[2]

positive_roots()

Returns the positive roots of self.

EXAMPLES:

sage: L = RootSystem(['A',3]).root_lattice()
sage: sorted(L.positive_roots())
[alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3], alpha[2], alpha[2] + alpha[3], alpha[3]]


Algorithm: generate them from the simple roots by applying successive reflections toward the positive chamber.

positive_roots_by_height(increasing=True)

Returns a list of positive roots in increasing order by height.

If increasing is False, returns them in decreasing order.

Warning

Returns an error unless the Cartan type is finite.

EXAMPLES:

sage: RootSystem(['C',2]).root_lattice().positive_roots_by_height()
[alpha[1], alpha[2], alpha[1] + alpha[2], 2*alpha[1] + alpha[2]]
sage: RootSystem(['C',2]).root_lattice().positive_roots_by_height(increasing = False)
[2*alpha[1] + alpha[2], alpha[1] + alpha[2], alpha[1], alpha[2]]
sage: RootSystem(['A',2,1]).root_lattice().positive_roots_by_height()
Traceback (most recent call last):
...
NotImplementedError: Only implemented for finite Cartan type

positive_roots_nonparabolic(index_set=None)

Returns the set of positive roots outside the parabolic subsystem with Dynkin node set index_set.

INPUT:

• index_set – (default:None) the Dynkin node set of the parabolic subsystem. It should be a tuple. The default value implies the entire Dynkin node set

EXAMPLES:

sage: lattice =  RootSystem(['A',3]).root_lattice()
sage: lattice.positive_roots_nonparabolic((1,3))
[alpha[2], alpha[1] + alpha[2], alpha[2] + alpha[3], alpha[1] + alpha[2] + alpha[3]]
sage: lattice.positive_roots_nonparabolic((2,3))
[alpha[1], alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3]]
sage: lattice.positive_roots_nonparabolic()
[]
sage: lattice.positive_roots_nonparabolic((1,2,3))
[]


warning:

This returns an error if the cartan type is not finite.
positive_roots_nonparabolic_sum(index_set=None)

Returns the sum of positive roots outside the parabolic subsystem with Dynkin node set index_set.

INPUT:

• index_set – (default:None) the Dynkin node set of the parabolic subsystem. It should be a tuple. The default value implies the entire Dynkin node set

EXAMPLES:

sage: lattice =  RootSystem(['A',3]).root_lattice()
sage: lattice.positive_roots_nonparabolic_sum((1,3))
2*alpha[1] + 4*alpha[2] + 2*alpha[3]
sage: lattice.positive_roots_nonparabolic_sum((2,3))
3*alpha[1] + 2*alpha[2] + alpha[3]
sage: lattice.positive_roots_nonparabolic_sum(())
3*alpha[1] + 4*alpha[2] + 3*alpha[3]
sage: lattice.positive_roots_nonparabolic_sum()
0
sage: lattice.positive_roots_nonparabolic_sum((1,2,3))
0


warning:

This returns an error if the cartan type is not finite.
positive_roots_parabolic(index_set=None)

Returns the set of positive roots for the parabolic subsystem with Dynkin node set index_set.

INPUT:

• index_set – (default:None) the Dynkin node set of the parabolic subsystem. It should be a tuple. The default value implies the entire Dynkin node set

EXAMPLES:

sage: lattice =  RootSystem(['A',3]).root_lattice()
sage: PhiP = lattice.positive_roots_parabolic((1,3))
sage: [x for x in PhiP]
[alpha[1], alpha[3]]
sage: PhiP = lattice.positive_roots_parabolic((2,3))
sage: [x for x in PhiP]
[alpha[2], alpha[3], alpha[2] + alpha[3]]
sage: PhiP = lattice.positive_roots_parabolic()
sage: [x for x in PhiP]
[alpha[1], alpha[2], alpha[3], alpha[1] + alpha[2], alpha[2] + alpha[3], alpha[1] + alpha[2] + alpha[3]]


warning:

This returns an error if the cartan type is not finite.
projection(root, coroot=None, to_negative=True)

Returns the projection along the root, and across the hyperplane define by coroot, as a function $$\pi$$ from self to self. $$\pi$$ is a half-linear map which stabilizes the negative half space, and acts by reflection on the positive half space.

If to_negative is False, then this project onto the positive half space instead.

EXAMPLES:

sage: space = RootSystem(['A',2]).weight_lattice()
sage: x=space.simple_roots()[1]
sage: y=space.simple_coroots()[1]
sage: pi = space.projection(x,y)
sage: x
2*Lambda[1] - Lambda[2]
sage: pi(x)
-2*Lambda[1] + Lambda[2]
sage: pi(-x)
-2*Lambda[1] + Lambda[2]
sage: pi = space.projection(x,y,False)
sage: pi(-x)
2*Lambda[1] - Lambda[2]

reflection(root, coroot=None)

Returns the reflection along the root, and across the hyperplane define by coroot, as a function from self to self.

EXAMPLES:

sage: space = RootSystem(['A',2]).weight_lattice()
sage: x=space.simple_roots()[1]
sage: y=space.simple_coroots()[1]
sage: s = space.reflection(x,y)
sage: x
2*Lambda[1] - Lambda[2]
sage: s(x)
-2*Lambda[1] + Lambda[2]
sage: s(-x)
2*Lambda[1] - Lambda[2]

root_poset(restricted=False, facade=False)

Returns the (restricted) root poset associated to self.

The elements are given by the positive roots (resp. non-simple, positive roots), and $$\alpha \leq \beta$$ iff $$\beta - \alpha$$ is a non-negative linear combination of simple roots.

INPUT:

• restricted – (default:False) if True, only non-simple roots are considered.
• facade – (default:False) passes facade option to the poset generator.

EXAMPLES:

sage: Phi = RootSystem(['A',1]).root_poset(); Phi
Finite poset containing 1 elements
sage: Phi.cover_relations()
[]

sage: Phi = RootSystem(['A',2]).root_poset(); Phi
Finite poset containing 3 elements
sage: Phi.cover_relations()
[[alpha[1], alpha[1] + alpha[2]], [alpha[2], alpha[1] + alpha[2]]]

sage: Phi = RootSystem(['A',3]).root_poset(restricted=True); Phi
Finite poset containing 3 elements
sage: Phi.cover_relations()
[[alpha[1] + alpha[2], alpha[1] + alpha[2] + alpha[3]], [alpha[2] + alpha[3], alpha[1] + alpha[2] + alpha[3]]]

sage: Phi = RootSystem(['B',2]).root_poset(); Phi
Finite poset containing 4 elements
sage: Phi.cover_relations()
[[alpha[1], alpha[1] + alpha[2]], [alpha[2], alpha[1] + alpha[2]], [alpha[1] + alpha[2], alpha[1] + 2*alpha[2]]]

roots()

Returns the roots of self.

EXAMPLES:

sage: RootSystem(['A',2]).ambient_lattice().roots()
[(1, -1, 0), (1, 0, -1), (0, 1, -1), (-1, 1, 0), (-1, 0, 1), (0, -1, 1)]


This matches with http://en.wikipedia.org/wiki/Root_systems:

sage: for T in CartanType.samples(finite = True, crystalographic = True):
...       print "%s %3s %3s"%(T, len(RootSystem(T).root_lattice().roots()), len(RootSystem(T).weight_lattice().roots()))
['A', 1]   2   2
['A', 5]  30  30
['B', 1]   2   2
['B', 5]  50  50
['C', 1]   2   2
['C', 5]  50  50
['D', 2]   4   4
['D', 3]  12  12
['D', 5]  40  40
['E', 6]  72  72
['E', 7] 126 126
['E', 8] 240 240
['F', 4]  48  48
['G', 2]  12  12


Todo

the result should be an enumerated set, and handle infinite root systems

s()

Returns the family $$(s_i)_{i\in I}$$ of the simple reflections of this root system.

EXAMPLES:

sage: r = RootSystem(["A", 2]).root_lattice()
sage: s = r.simple_reflections()
sage: s[1]( r.simple_root(1) )
-alpha[1]


TEST:

sage: s
simple reflections

simple_coroot(i)

Returns the $$i^{th}$$ simple coroot.

EXAMPLES:

sage: RootSystem(['A',2]).root_lattice().simple_coroot(1)
alphacheck[1]

simple_coroots()

Returns the family $$( \alpha^\vee_i)_{i\in I}$$ of the simple coroots.

EXAMPLES:

sage: alphacheck = RootSystem(['A',3]).root_lattice().simple_coroots()
sage: [alphacheck[i] for i in [1, 2, 3]]
[alphacheck[1], alphacheck[2], alphacheck[3]]

simple_projection(i, to_negative=True)

Returns the projection along the $$i^{th}$$ simple root, and across the hyperplane define by the $$i^{th}$$ simple coroot, as a function from self to self.

INPUT:

• i - i is in self’s index set

EXAMPLES:

sage: space = RootSystem(['A',2]).weight_lattice()
sage: x = space.simple_roots()[1]
sage: pi = space.simple_projection(1)
sage: x
2*Lambda[1] - Lambda[2]
sage: pi(x)
-2*Lambda[1] + Lambda[2]
sage: pi(-x)
-2*Lambda[1] + Lambda[2]
sage: pi = space.simple_projection(1,False)
sage: pi(-x)
2*Lambda[1] - Lambda[2]

simple_projections(to_negative=True)

Returns the family $$(s_i)_{i\in I}$$ of the simple projections of this root system

EXAMPLES:

sage: space = RootSystem(['A',2]).weight_lattice()
sage: pi = space.simple_projections()
sage: x = space.simple_roots()
sage: pi[1](x[2])
-Lambda[1] + 2*Lambda[2]

TESTS:
sage: pi pi
simple_reflection(i)

Returns the $$i^{th}$$ simple reflection, as a function from self to self.

INPUT:

• i - i is in self’s index set

EXAMPLES:

sage: space = RootSystem(['A',2]).ambient_lattice()
sage: s = space.simple_reflection(1)
sage: x = space.simple_roots()[1]
sage: x
(1, -1, 0)
sage: s(x)
(-1, 1, 0)

simple_reflections()

Returns the family $$(s_i)_{i\in I}$$ of the simple reflections of this root system.

EXAMPLES:

sage: r = RootSystem(["A", 2]).root_lattice()
sage: s = r.simple_reflections()
sage: s[1]( r.simple_root(1) )
-alpha[1]


TEST:

sage: s
simple reflections

simple_root(i)

Returns the $$i^{th}$$ simple root.

This should be overridden by any subclass, and typically implemented as a cached method for efficiency.

EXAMPLES:

sage: r = RootSystem(["A",3]).root_lattice()
sage: r.simple_root(1)
alpha[1]


TESTS:

sage: super(sage.combinat.root_system.root_space.RootSpace, r).simple_root(1)
Traceback (most recent call last):
...
NotImplementedError: <abstract method simple_root at ...>

simple_roots()

Returns the family $$(\alpha_i)_{i\in I}$$ of the simple roots.

EXAMPLES:

sage: alpha = RootSystem(["A",3]).root_lattice().simple_roots()
sage: [alpha[i] for i in [1,2,3]]
[alpha[1], alpha[2], alpha[3]]

tau_epsilon_operator_on_almost_positive_roots(J)

The $$\tau_\epsilon$$ operator on almost positive roots

Given a subset $$J$$ of non adjacent vertices of the Dynkin diagram, this constructs the operator on the almost positive roots which fixes the negative simple roots $$\alpha_i$$ for $$i$$ not in $$J$$, and acts otherwise by:

$\tau_+( \beta ) = (\prod_{i \in J} s_i) (\beta)$

See Equation (1.2) of [CFZ].

EXAMPLES:

sage: L = RootSystem(['A',4]).root_lattice()
sage: tau = L.tau_epsilon_operator_on_almost_positive_roots([1,3])
sage: alpha = L.simple_roots()


The action on a negative simple root not in $$J$$:

sage: tau(-alpha[2])
-alpha[2]


The action on a negative simple root in $$J$$:

sage: tau(-alpha[1])
alpha[1]


The action on all almost positive roots:

sage: for root in L.almost_positive_roots():
...      print 'tau({:<41}) ='.format(root), tau(root)
tau(-alpha[1]                                ) = alpha[1]
tau(alpha[1]                                 ) = -alpha[1]
tau(alpha[1] + alpha[2]                      ) = alpha[2] + alpha[3]
tau(alpha[1] + alpha[2] + alpha[3]           ) = alpha[2]
tau(alpha[1] + alpha[2] + alpha[3] + alpha[4]) = alpha[2] + alpha[3] + alpha[4]
tau(-alpha[2]                                ) = -alpha[2]
tau(alpha[2]                                 ) = alpha[1] + alpha[2] + alpha[3]
tau(alpha[2] + alpha[3]                      ) = alpha[1] + alpha[2]
tau(alpha[2] + alpha[3] + alpha[4]           ) = alpha[1] + alpha[2] + alpha[3] + alpha[4]
tau(-alpha[3]                                ) = alpha[3]
tau(alpha[3]                                 ) = -alpha[3]
tau(alpha[3] + alpha[4]                      ) = alpha[4]
tau(-alpha[4]                                ) = -alpha[4]
tau(alpha[4]                                 ) = alpha[3] + alpha[4]


This method works on any root lattice realization:

sage: L = RootSystem(['B',3]).ambient_space()
sage: tau = L.tau_epsilon_operator_on_almost_positive_roots([1,3])
sage: for root in L.almost_positive_roots():
...      print 'tau({:<41}) ='.format(root), tau(root)
tau((-1, 1, 0)                               ) = (1, -1, 0)
tau((1, 0, 0)                                ) = (0, 1, 0)
tau((1, -1, 0)                               ) = (-1, 1, 0)
tau((1, 1, 0)                                ) = (1, 1, 0)
tau((1, 0, -1)                               ) = (0, 1, 1)
tau((1, 0, 1)                                ) = (0, 1, -1)
tau((0, -1, 1)                               ) = (0, -1, 1)
tau((0, 1, 0)                                ) = (1, 0, 0)
tau((0, 1, -1)                               ) = (1, 0, 1)
tau((0, 1, 1)                                ) = (1, 0, -1)
tau((0, 0, -1)                               ) = (0, 0, 1)
tau((0, 0, 1)                                ) = (0, 0, -1)


See also

tau_plus_minus()

REFERENCES:

 [CFZ] Chapoton, Fomin, Zelevinsky - Polytopal realizations of generalized associahedra
tau_plus_minus()

Returns the $$\tau^+$$ and $$\tau^-$$ piecewise linear operators on self

Those operators are induced by the bipartition $$\{L,R\}$$ of the simple roots of self, and stabilize the almost positive roots. Namely, $$\tau_+$$ fixes the negative simple roots $$\alpha_i$$ for $$i$$ in $$R$$, and acts otherwise by:

$\tau_+( \beta ) = (\prod_{i \in L} s_i) (\beta)$

$$\tau_-$$ acts analogously, with $$L$$ and $$R$$ interchanged.

Those operators are used to construct the associahedron, a polytopal realization of the cluster complex (see Associahedron).

EXAMPLES:

We explore the example of [CFZ1] Eq.(1.3):

sage: S = RootSystem(['A',2]).root_lattice()
sage: taup, taum = S.tau_plus_minus()
sage: for beta in S.almost_positive_roots(): print beta, ",", taup(beta), ",", taum(beta)
-alpha[1] , alpha[1] , -alpha[1]
alpha[1] , -alpha[1] , alpha[1] + alpha[2]
alpha[1] + alpha[2] , alpha[2] , alpha[1]
-alpha[2] , -alpha[2] , alpha[2]
alpha[2] , alpha[1] + alpha[2] , -alpha[2]


REFERENCES:

 [CFZ1] Chapoton, Fomin, Zelevinsky - Polytopal realizations of generalized associahedra
weyl_group(prefix=None)

Returns the Weyl group associated to self.

EXAMPLES:

sage: RootSystem(['F',4]).ambient_space().weyl_group()
Weyl Group of type ['F', 4] (as a matrix group acting on the ambient space)
sage: RootSystem(['F',4]).root_space().weyl_group()
Weyl Group of type ['F', 4] (as a matrix group acting on the root space)

RootLatticeRealizations.super_categories()

EXAMPLES:

sage: from sage.combinat.root_system.root_lattice_realizations import RootLatticeRealizations
sage: RootLatticeRealizations(QQ).super_categories()
[Category of modules with basis over Rational Field]


Root systems

#### Next topic

Weight lattice realizations