Source code for bggcohomology.weight_set

"""Module for doing computations with the weights of a weight module and action of Weyl group."""

import numpy as np

from sage.combinat.root_system.weyl_group import WeylGroup
from sage.matrix.constructor import matrix


[docs]class WeightSet: """Class to do simple computations with the weights of a weight module. Parameters ---------- root_system : str String representing the root system (e.g. 'A2') Attributes ---------- root_system : str String representing the root system (e.g. 'A2') W : WeylGroup Object encoding the Weyl group. weyl_dic : dict(str, WeylGroup.element_class) Dictionary mapping strings representing a Weyl group element as reduced word in simple reflections, to the Weyl group element. reduced_words : list[str] Sorted list of all strings representing Weyl group elements as reduced word in simple reflections. simple_roots : list[RootSpace.element_class] List of the simple roots rank : int Rank of root system rho : RootSpace.element_class Half the sum of all positive roots pos_roots : List[RootSpace.element_class] List of all the positive roots action_dic : Dict[str, np.array(np.int32, np.int32)] dictionary mapping each string representing an element of the Weyl group to a matrix expressing the action on the simple roots. rho_action_dic : Dict[str, np.array(np.int32)] dictionary mapping each string representing an element of the Weyl group to a vector representing the image of the dot action on rho. """
[docs] @classmethod def from_bgg(cls, BGG): """Initialize from an instance of BGGComplex. Some data can be reused, and this gives roughly 3x faster initialization. Parameters ---------- BGG : BGGComplex The BGGComplex to initialize from. """ hot_start = {"W": BGG.W, "weyl_dic": BGG.reduced_word_dic} return cls(BGG.root_system, hot_start=hot_start)
def __init__(self, root_system, hot_start=None): self.root_system = root_system if hot_start is None: self.W = WeylGroup(root_system) self.weyl_dic = self._compute_weyl_dictionary() else: self.W = hot_start["W"] self.weyl_dic = hot_start["weyl_dic"] self.domain = self.W.domain() self.reduced_words = sorted(self.weyl_dic.keys(), key=len) self.simple_roots = self.domain.simple_roots().values() self.rank = len(self.simple_roots) self.rho = self.domain.rho() self.pos_roots = self.domain.positive_roots() # Matrix of all simple roots, for faster matrix solving self.simple_root_matrix = matrix( [list(s.to_vector()) for s in self.simple_roots] ).transpose() self.action_dic, self.rho_action_dic = self.get_action_dic() def _compute_weyl_dictionary(self): """Construct a dictionary enumerating all of the elements of the Weyl group. The keys are reduced words of the elements """ reduced_word_dic = { "".join([str(s) for s in g.reduced_word()]): g for g in self.W } return reduced_word_dic
[docs] def weight_to_tuple(self, weight): """Convert element of weight lattice to a sum of simple roots. Parameters ---------- weight : RootSpace.element_class Returns ------- tuple[int] tuple representing root as linear combination of simple roots """ b = weight.to_vector() b = matrix(b).transpose() return tuple(self.simple_root_matrix.solve_right(b).transpose().list())
[docs] def tuple_to_weight(self, t): """Inverse of `weight_to_tuple`. Parameters ---------- t : tuple[int] Returns ------- RootSpace.element_class """ return sum(int(a) * b for a, b in zip(t, self.simple_roots))
[docs] def get_action_dic(self): """Compute weyl group action as well as action on rho. Returns ------- Dict[str, np.array(np.int32, np.int32)] : dictionary mapping each string representing an element of the Weyl group to a matrix expressing the action on the simple roots. Dict[str, np.array(np.int32)] : dictionary mapping each string representing an element of the Weyl group to a vector representing the image of the dot action on rho. """ action_dic = dict() rho_action_dic = dict() for s, w in self.weyl_dic.items(): # s is a string, w is a matrix # Compute action of w on every simple root, decompose result in simple roots, encode result as matrix. action_mat = [] for mu in self.simple_roots: action_mat.append(self.weight_to_tuple(w.action(mu))) action_dic[s] = np.array(action_mat, dtype=np.int32) # Encode the dot action of w on rho. rho_action_dic[s] = np.array( self.weight_to_tuple(w.action(self.rho) - self.rho), dtype=np.int32 ) return action_dic, rho_action_dic
[docs] def dot_action(self, w, mu): r"""Compute the dot action of w on mu. The dot action :math:`w\cdot\mu = w(\mu+\rho)-\rho`, with :math:`\rho` half the sum of all the positive roots. Parameters ---------- w : str string representing the weyl group element mu : iterable(int) the weight Returns ------- np.array[np.int32] vector encoding the new weight """ # The dot action w.mu = w(mu+rho)-rho = w*mu + (w*rho-rho). # The former term is given by action_dic, the latter by rho_action_dic return ( np.matmul(self.action_dic[w].T, np.array(mu, dtype=np.int32)) + self.rho_action_dic[w] )
[docs] def dot_orbit(self, mu): """Compute the orbit of the Weyl group action on a weight. Parameters ---------- mu : iterable(int) A weight Returns ------- dict(str, np.array[np.int32]) Dictionary mapping Weyl group elements to weights encoded as numpy vectors. """ return {w: self.dot_action(w, mu) for w in self.reduced_words}
[docs] def is_dot_regular(self, mu): """Check if mu has a non-trivial stabilizer under the dot action. Parameters ---------- mu : iterable(int) The weight Returns ------- bool `True` if the weight is dot-regular """ for s in self.reduced_words[1:]: if np.all(self.dot_action(s, mu) == mu): return False # no stabilizer found return True
[docs] def compute_weights(self, weights): """Find dot-regular weights and associated dominant weights of a set of weights. Parameters ---------- weights : iterable(iterable(int)) Iterable of weights returns ------- list(tuple[tuple(int), tuple(int), int]) list of triples consisting of dot-regular weight, associated dominant, and the length of the Weyl group element making the weight dominant under the dot action. """ regular_weights = [] for mu in weights: if self.is_dot_regular(mu): mu_prime, w = self.make_dominant(mu) regular_weights.append((mu, tuple(mu_prime), len(w))) return regular_weights
[docs] def is_dominant(self, mu): """Use sagemath built-in function to check if weight is dominant. Parameters ---------- mu : iterable(int) the weight Returns ------- bool `True` if weight is dominant """ return self.tuple_to_weight(mu).is_dominant()
[docs] def make_dominant(self, mu): """For a dot-regular weight mu, w such that if w.mu is dominant. Such a w exists iff mu is dot-regular, in which case it is also unique. Parameters ---------- mu : iterable(int) the dot-regular weight Returns ------- tuple(int) The dominant weight w.mu str the string representing the Weyl group element w. """ for w in self.reduced_words: new_mu = self.dot_action(w, mu) if self.is_dominant(new_mu): return new_mu, w else: raise ValueError( "Could not make weight %s dominant, probably it is not dot-regular." )
[docs] def get_vertex_weights(self, mu): """For a given dot-regular mu, return its orbit under the dot-action. Parameters ---------- mu : iterable(int) Returns ------- list[tuple[int]] list of weights """ vertex_weights = dict() for w in self.reduced_words: vertex_weights[w] = tuple(self.dot_action(w, mu)) return vertex_weights
[docs] def highest_weight_rep_dim(self, mu): """Give dimension of highest weight representation of integral dominant weight. Parameters ---------- mu : tuple(int) A integral dominant weight Returns ------- int dimension of highest weight representation. """ mu_weight = self.tuple_to_weight(mu) numerator = 1 denominator = 1 for alpha in self.pos_roots: numerator *= (mu_weight + self.rho).dot_product(alpha) denominator *= self.rho.dot_product(alpha) return numerator // denominator