### Navigation

- index
- modules |
- next |
- previous |
- Combinatorics »
- Root Systems »

# Weight lattices and weight spaces

class `sage.combinat.root_system.weight_space.``WeightSpace`(root_system, base_ring, extended)

  Bases: `sage.combinat.free_module.CombinatorialFreeModule`

  INPUT:

  - `root_system` – a root system
  - `base_ring` – a ring \(R\)
  - `extended` – a boolean (default: False)

  The weight space (or lattice if `base_ring` is \(\ZZ\)) of a root system is the formal free module \(\bigoplus_i R \Lambda_i\) generated by the fundamental weights \((\Lambda_i)_{i\in I}\) of the root system.

  This class is also used for coweight spaces (or lattices).

  See also

  - `RootSystem()`
  - `RootSystem.weight_lattice()` and `RootSystem.weight_space()`
  - `WeightLatticeRealizations()`

  EXAMPLES:

      sage: Q = RootSystem(['A', 3]).weight_lattice(); Q
      Weight lattice of the Root system of type ['A', 3]
      sage: Q.simple_roots()
      Finite family {1: 2*Lambda[1] - Lambda[2], 2: -Lambda[1] + 2*Lambda[2] - Lambda[3], 3: -Lambda[2] + 2*Lambda[3]}

      sage: Q = RootSystem(['A', 3, 1]).weight_lattice(); Q
      Weight lattice of the Root system of type ['A', 3, 1]
      sage: Q.simple_roots()
      Finite family {0: 2*Lambda[0] -   Lambda[1]               -   Lambda[3],
                     1:  -Lambda[0] + 2*Lambda[1] -   Lambda[2],
                     2:                -Lambda[1] + 2*Lambda[2] -   Lambda[3],
                     3:  -Lambda[0]               -   Lambda[2] + 2*Lambda[3]}

  For infinite types, the Cartan matrix is singular, and therefore the embedding of the root lattice is not faithful:

      sage: sum(Q.simple_roots())
      0

  In particular, the null root is zero:

      sage: Q.null_root()
      0

  This can be compensated by extending the basis of the weight space and slightly deforming the simple roots to make them linearly independent, without affecting the scalar product with the coroots. This feature is currently only implemented for affine types. In that case, if `extended` is set, then the basis of the weight space is extended by an element \(\delta\):

      sage: Q = RootSystem(['A', 3, 1]).weight_lattice(extended = True); Q
      Extended weight lattice of the Root system of type ['A', 3, 1]
      sage: Q.basis().keys()
      {0, 1, 2, 3, 'delta'}

  And the simple root \(\alpha_0\) associated to the special node is deformed as follows:

      sage: Q.simple_roots()
      Finite family {0: 2*Lambda[0] -   Lambda[1]               -   Lambda[3] + delta,
                     1:  -Lambda[0] + 2*Lambda[1] -   Lambda[2],
                     2:                -Lambda[1] + 2*Lambda[2] -   Lambda[3],
                     3:  -Lambda[0]               -   Lambda[2] + 2*Lambda[3]}

  Now, the null root is nonzero:

      sage: Q.null_root()
      delta

  Warning

  By a slight notational abuse, the extra basis element used to extend the fundamental weights is called `\delta` in the current implementation. However, in the literature, `\delta` usually denotes instead the null root. Most of the time, those two objects coincide, but not for type \(BC\) (aka. \(A_{2n}^{(2)}\)). Therefore we currently have:

      sage: Q = RootSystem(["A",4,2]).weight_lattice(extended=True)
      sage: Q.simple_root(0)
      2*Lambda[0] - Lambda[1] + delta
      sage: Q.null_root()
      2*delta

  whereas, with the standard notations from the literature, one would expect to get respectively \(2\Lambda_0 -\Lambda_1 +1/2 \delta\) and \(\delta\).

  Other than this notational glitch, the implementation remains correct for type \(BC\).

  The notations may get improved in a subsequent version, which might require changing the index of the extra basis element. To guarantee backward compatibility in code not included in Sage, it is recommended to use the following idiom to get that index:

      sage: F = Q.basis_extension(); F
      Finite family {'delta': delta}
      sage: index = F.keys()[0]; index
      'delta'

  Then, for example, the coefficient of an element of the extended weight lattice on that basis element can be recovered with:

      sage: Q.null_root()[index]
      2

  TESTS:

      sage: for ct in CartanType.samples(crystallographic=True)+[CartanType(["A",2],["C",5,1])]:
      ...       TestSuite(ct.root_system().weight_lattice()).run()
      ...       TestSuite(ct.root_system().weight_space()).run()
      sage: for ct in CartanType.samples(affine=True):
      ...       if ct.is_implemented():
      ...           P = ct.root_system().weight_space(extended=True)
      ...           TestSuite(P).run()

  `Element`

    alias of `WeightSpaceElement`

  `basis_extension`()

    Return the basis elements used to extend the fundamental weights

    EXAMPLES:

        sage: Q = RootSystem(["A",3,1]).weight_lattice()
        sage: Q.basis_extension()
        Family ()

        sage: Q = RootSystem(["A",3,1]).weight_lattice(extended=True)
        sage: Q.basis_extension()
        Finite family {'delta': delta}

    This method is irrelevant for finite types:

        sage: Q = RootSystem(["A",3]).weight_lattice()
        sage: Q.basis_extension()
        Family ()

  `fundamental_weight`(i)

    Returns the \(i\)-th fundamental weight

    INPUT:

    - `i` – an element of the index set or `"delta"`

    By a slight notational abuse, for an affine type this method also accepts `"delta"` as input, and returns the image of \(\delta\) of the extended weight lattice in this realization.

    EXAMPLES:

        sage: Q = RootSystem(["A",3]).weight_lattice()
        sage: Q.fundamental_weight(1)
        Lambda[1]

        sage: Q = RootSystem(["A",3,1]).weight_lattice(extended=True)
        sage: Q.fundamental_weight(1)
        Lambda[1]
        sage: Q.fundamental_weight("delta")
        delta

  `is_extended`()

    Returns whether this is an extended weight lattice

    EXAMPLES:

        sage: RootSystem(["A",3,1]).weight_lattice().is_extended()
        False
        sage: RootSystem(["A",3,1]).weight_lattice(extended=True).is_extended()
        True

  `simple_root`(j)

    Returns the \(j^{th}\) simple root

    EXAMPLES:

        sage: L = RootSystem(["C",4]).weight_lattice()
        sage: L.simple_root(3)
        -Lambda[2] + 2*Lambda[3] - Lambda[4]

    Its coefficients are given by the corresponding column of the Cartan matrix:

        sage: L.cartan_type().cartan_matrix()[:,2]
        [ 0]
        [-1]
        [ 2]
        [-1]

    Here are all simple roots:

        sage: L.simple_roots()
        Finite family {1:  2*Lambda[1]   - Lambda[2],
                       2:   -Lambda[1] + 2*Lambda[2]   - Lambda[3],
                       3:   -Lambda[2] + 2*Lambda[3]   - Lambda[4],
                       4:               -2*Lambda[3] + 2*Lambda[4]}

    For the extended weight lattice of an affine type, the simple root associated to the special node is deformed by adding \(\delta\), where \(\delta\) is the null root:

        sage: L = RootSystem(["C",4,1]).weight_lattice(extended=True)
        sage: L.simple_root(0)
        2*Lambda[0] - 2*Lambda[1] + delta

    In fact \(\delta\) is really \(1/a_0\) times the null root (see the discussion in `WeightSpace`) but this only makes a difference in type \(BC\):

        sage: L = RootSystem(CartanType(["BC",4,2])).weight_lattice(extended=True)
        sage: L.simple_root(0)
        2*Lambda[0] - Lambda[1] + delta
        sage: L.null_root()
        2*delta

    See also

    - `simple_root()`
    - `CartanType.col_annihilator()`

class `sage.combinat.root_system.weight_space.``WeightSpaceElement`(M, x)

  Bases: `sage.combinat.free_module.CombinatorialFreeModuleElement`

  Create a combinatorial module element. This should never be called directly, but only through the parent combinatorial free module’s `__call__()` method.

  TESTS:

      sage: F = CombinatorialFreeModule(QQ, ['a','b','c'])
      sage: B = F.basis()
      sage: f = B['a'] + 3*B['c']; f
      B['a'] + 3*B['c']
      sage: f == loads(dumps(f))
      True

  `is_dominant`()

    Checks whether an element in the weight space lies in the positive cone spanned by the basis elements (fundamental weights).

    EXAMPLES:

        sage: W=RootSystem(['A',3]).weight_space()
        sage: Lambda=W.basis()
        sage: w=Lambda[1]+Lambda[3]
        sage: w.is_dominant()
        True
        sage: w=Lambda[1]-Lambda[2]
        sage: w.is_dominant()
        False

  `scalar`(lambdacheck)

    The canonical scalar product between the weight lattice and the coroot lattice.

    Todo

    - merge with_apply_multi_module_morphism
    - allow for any root space / lattice
    - define properly the return type (depends on the base rings of the two spaces)
    - make this robust for extended weight lattices (\(i\) might be “delta”)

    EXAMPLES:

        sage: L = RootSystem(["C",4,1]).weight_lattice()
        sage: Lambda     = L.fundamental_weights()
        sage: alphacheck = L.simple_coroots()
        sage: Lambda[1].scalar(alphacheck[1])
        1
        sage: Lambda[1].scalar(alphacheck[2])
        0

    The fundamental weights and the simple coroots are dual bases:

        sage: matrix([ [ Lambda[i].scalar(alphacheck[j])
        ...              for i in L.index_set() ]
        ...            for j in L.index_set() ])
        [1 0 0 0 0]
        [0 1 0 0 0]
        [0 0 1 0 0]
        [0 0 0 1 0]
        [0 0 0 0 1]

    Note that the scalar product is not yet implemented between the weight space and the coweight space; in any cases, that won’t be the job of this method:

        sage: R = RootSystem(["A",3])
        sage: alpha = R.weight_space().roots()
        sage: alphacheck = R.coweight_space().roots()
        sage: alpha[1].scalar(alphacheck[1])
        Traceback (most recent call last):
        ...
        ValueError: -Lambdacheck[1] + 2*Lambdacheck[2] - Lambdacheck[3] is not in the coroot space

### Navigation

- index
- modules |
- next |
- previous |
- Combinatorics »
- Root Systems »