n environment to decompose the i-th Hochschild cohomology on some homogeneous varieties X=G/P by Hoschild-Kostant-Rosenberg.
Hochschild-Kostant-Rosenberg_decomposition / src / HochschildKostantRosenberg_decomposition / base_space.sage
383 viewsLicense: GPL3
ubuntu2204
from typing import Iterator1234class irreducible_Cartan_group ( object ) :567ADMISSIBLE_CARTAN_FAMILIES = { 'A' : ( 1 , +infinity ) ,8'B' : ( 2 , +infinity ) ,9'C' : ( 2 , +infinity ) ,10'D' : ( 3 , +infinity ) ,11'E' : ( 6 , 8 ) ,12'F' : ( 4 , 4 ) ,13'G' : ( 2 , 2 )14}151617def __eq__ ( self , other ) -> bool :18"""Tests if ``self`` coincides with ``other``."""19assert isinstance( other , irreducible_Cartan_group ) , \20'The input for ``other`` needs to be an irreducible Cartan group.'21return self.__repr__() == other.__repr__()22232425def __init__ ( self , Cartan_family:str , Cartan_degree:sage.rings.integer.Integer ) -> None :26"""Initialise ``self``."""27assert Cartan_family in self.ADMISSIBLE_CARTAN_FAMILIES.keys() , \28ValueError('The input for ``Cartan_family`` needs to be a letter from the alphabet '+str(self.ADMISSIBLE_CARTAN_FAMILIES.keys())+'.')29self._Cartan_family = Cartan_family3031assert Cartan_degree in ZZ , \32ValueError('The input for ``Cartan_degree`` needs to be an integer.')33lower_bound , upper_bound = self.ADMISSIBLE_CARTAN_FAMILIES[Cartan_family]34assert lower_bound <= Cartan_degree and Cartan_degree <= upper_bound , \35ValueError('If the Cartan family is '+str(Cartan_family)+', then the input for ``Cartan_degree`` needs to between '+str(lower_bound)+' and '+str(upper_bound)+'.')36self._Cartan_degree = Cartan_degree373839def __neq__ ( self , other ) -> bool :40"""Tests if ``self`` does NOT coincides with ``other``."""41return not self == other424344def __repr__ ( self ) -> tuple[ str , sage.rings.integer.Integer ] :45"""Returns a developers adjusted description."""46return self._Cartan_family , self._Cartan_degree474849def __str__ ( self ) -> str :50"""Returns a human-readable description."""51return self._Cartan_family+'_'+str(self._Cartan_degree)525354def __truediv__ ( self , other:'maximal_parabolic_subgroup' ) -> 'minimal_irreducible_homogeneous_variety' :55"""Returns the minimal irreducible homogeneous variety X=G/P."""56assert isinstance( other , maximal_parabolic_subgroup ) , \57'The input for ``other`` needs to be a minimal parabolic subgroup.'5859assert self == other._parent_group , \60'The parent group of ``other`` needs to be self.'6162return minimal_irreducible_homogeneous_variety( parabolic_subgroup=other )636465def Cartan_string ( self ) -> str :66"""Returns the Cartan string ``_Cartan_family``+``_Cartan_degree``."""67return self._Cartan_family+str(self._Cartan_degree)686970def Cartan_type ( self ) -> 'sage.combinat.root_system.type_A.CartanType' \71or 'sage.combinat.root_system.type_B.CartanType' \72or 'sage.combinat.root_system.type_D.CartanType' \73or 'sage.combinat.root_system.type_E.CartanType' \74or 'sage.combinat.root_system.type_E.CartanType' \75or 'sage.combinat.root_system.type_F.CartanType' \76or 'sage.combinat.root_system.type_G.CartanType' :77"""Returns the associated Cartan type."""78return CartanType( self.Cartan_string() )798081def dimension ( self ) -> sage.rings.integer.Integer :82"""83Return the dimension of ``self`.8485INPUT:86- ``self`` -- minimal_irreducible_homogeneous_variety; base space X=G/P.8788OUTPUT:89- ``Output`` -- Integer; the dimension of X=G/P9091ALGORITHM:92Thanks to the post by Pieter Belmans concerning the dimension of partial flag varieties93from Jun 14th, 2017 on his blog (cf. to [Blog_PieterBelmans]_). The link is94https://pbelmans.ncag.info/blog/2017/06/14/dimensions-of-partial-flag-varieties/95(Date: Apr 21st, 2021).9697For the Borel group B ⊂ G: dim B = # of positive roots + rank (which accounts for the center)98For G: dim G = # of roots in the root system + rank (which accounts for the center)99i.e. # of roots in the root system = # of positive roots + # negative roots100and # of positive roots = # negative roots101so # of roots in the root system = 2 * # of positive roots102103REFERENCE:104[Blog_PieterBelmans] https://pbelmans.ncag.info/blog/105"""106rank = self.Cartan_type().dynkin_diagram().rank()107number_of_positive_roots = len( list( self.Cartan_type().root_system().root_lattice().positive_roots() ) )108return rank + 2*number_of_positive_roots109110111def parabolic_subgroup ( self , excluded_node:sage.rings.integer.Integer ) -> 'maximal_parabolic_subgroup' :112"""Returns a maximal parabolic subgroup associated to a given excluded node."""113return maximal_parabolic_subgroup( parent_group=self , excluded_node=excluded_node )114115116def Weyl_character_ring( self ) -> 'sage.combinat.root_system.weyl_characters.WeylCharacterRing_with_category' :117"""Returns the associated Weyl character ring."""118return WeylCharacterRing( self.Cartan_type() , style='coroots' )119120121def Weyl_group( self ) -> 'sage.combinat.root_system.weyl_group.WeylGroup_gens_with_category' :122"""Returns the associated Weyl group."""123return WeylGroup( self.Cartan_type() )124125126127class maximal_parabolic_subgroup ( object ) :128129130def __eq__ ( self , other ) -> bool :131"""Tests if ``self`` coincides with ``other``."""132assert isinstance( other , maximal_parabolic_subgroup ) , \133'The input for ``other`` needs to be an irreducible Cartan group.'134return self.__repr__() == other.__repr__()135136137def __init__ ( self , parent_group:irreducible_Cartan_group , excluded_node:sage.rings.integer.Integer ) :138"""Initialise ``self``."""139assert isinstance( parent_group , irreducible_Cartan_group ) , \140ValueError('The input for ``parent_group`` needs to be an irreducible Cartan group.')141self._parent_group = parent_group142143assert excluded_node in ZZ , \144ValueError('The input for ``excluded_node`` needs to be an integer.')145assert excluded_node in [ 1 .. self._parent_group._Cartan_degree ] , \146ValueError('The input for ``excluded_node`` needs to be in the range from 1 to '+str(self._Cartan_degree)+'.')147self._excluded_node = excluded_node148149150def __neq__ ( self , other ) -> bool :151"""Tests if ``self`` does NOT coincides with ``other``."""152return not self == other153154155def __repr__ ( self ) -> tuple[ irreducible_Cartan_group , sage.rings.integer.Integer ] :156"""Returns a developers adjusted description."""157return self._parent_group , self._excluded_node158159160def __str__ ( self ) -> str :161"""Returns a human-readable description."""162return 'P_'+str(self._excluded_node)163164165def dimension ( self ) -> sage.rings.integer.Integer :166"""167Return the dimension of ``self`.168169INPUT:170- ``self`` -- minimal_irreducible_homogeneous_variety; base space X=G/P.171172OUTPUT:173- ``Output`` -- Integer; the dimension of X=G/P174175ALGORITHM:176Thanks to the post by Pieter Belmans concerning the dimension of partial flag varieties177from Jun 14th, 2017 on his blog (cf. to [Blog_PieterBelmans]_). The link is178https://pbelmans.ncag.info/blog/2017/06/14/dimensions-of-partial-flag-varieties/179(Date: Apr 21st, 2021).180181For the Borel group B ⊂ G: dim B = # of positive roots + rank (which accounts for the center)182For P: dim P = dim B + # of negative roots which are added to construct P183184REFERENCE:185[Blog_PieterBelmans] https://pbelmans.ncag.info/blog/186"""187rank = self._parent_group.Cartan_type().dynkin_diagram().rank()188number_of_positive_roots = len( list( self._parent_group.Cartan_type().root_system().root_lattice().positive_roots() ) )189negative_roots = [ negative_root for negative_root in list( self._parent_group.Cartan_type().root_system().root_lattice().negative_roots() )190if not False in [ node != self._excluded_node for node , coefficient in negative_root ]191]192number_of_available_negative_roots = len( negative_roots )193return rank + number_of_positive_roots + number_of_available_negative_roots194195196def included_nodes ( self ) -> list[ sage.rings.integer.Integer ] :197"""Returns list of included nodes."""198return [ node for node in [ 1 .. self._parent_group._Cartan_degree ] if node != self._excluded_node ]199200201202class minimal_irreducible_homogeneous_variety ( object ) :203204def __eq__ ( self , other ) -> bool :205"""Tests if ``self`` coincides with ``other``."""206assert isinstance( other , minimal_irreducible_homogeneous_variety ) , \207'The input for ``other`` needs to be an irreducible Cartan group.'208return self.__repr__() == other.__repr__()209210211def __init__ ( self , parabolic_subgroup:maximal_parabolic_subgroup ) -> None :212"""Initialise ``self``."""213assert isinstance( parabolic_subgroup , maximal_parabolic_subgroup ) , \214ValueError('The input for ``parabolic_subgroup`` needs to be a maximal parabolic subgroup.')215self._parabolic_subgroup = parabolic_subgroup216217218def __neq__ ( self , other ) -> bool :219"""Tests if ``self`` does NOT coincides with ``other``."""220return not self == other221222223def __repr__ ( self ) -> maximal_parabolic_subgroup :224"""Returns a developers adjusted description."""225return self._parabolic_subgroup226227228def __str__ ( self ) -> str :229"""Returns a human-readable description."""230return str(self._parabolic_subgroup._parent_group)+'/'+str(self._parabolic_subgroup)231232233def dimension ( self ) -> sage.rings.integer.Integer :234"""235Return the dimension of ``self`.236237INPUT:238- ``self`` -- minimal_irreducible_homogeneous_variety; base space X=G/P.239240OUTPUT:241- ``Output`` -- Integer; the dimension of X=G/P242243ALGORITHM:244For X=G/P, dim X = dim G - dim P245"""246return self._parabolic_subgroup._parent_group.dimension() - self._parabolic_subgroup.dimension()247248249def Fano_index ( self ) -> sage.rings.integer.Integer :250"""251Returns the Fano index of ``self``.252253INPUT:254- ``self`` -- minimal_irreducible_homogeneous_variety; base space X=G/P.255256OUTPUT:257- ``Fano_index`` -- integer; index associated to X = G/P.258259ALGORITHM:260Thanks to the post by Pieter Belmans concerning the index of partial flag varieties261from Aug 23rd, 2018 on his blog (cf. to [Blog_PieterBelmans]_). The link is262https://pbelmans.ncag.info/blog/2018/08/23/index-partial-flag-varieties/263(Date: Apr 26th, 2021).264265The index, i.e. for X=G/P (P maximal), we have Pic(X) ≅ ZZ⋅O_X(1) and therefore define the index as the integer i266such that ω∨_X ≅ O_X(1) ⊗ i.267268To compute it, we use lemma 2.19 and remark 2.20 of [KP2016]. Combined they say the following:269Let β be the simple root corresponding to the chosen maximal parabolic subgroup P, and ξ the associated270fundamental weight. Let ¯β be the maximal root of the same length as β such that the coefficient of β271in the expression of ¯β is 1.272Then the index of G/P equals i_G/P = (ρ,β+¯β)/(ξ,β).273274REFERENCE:275[Blog_PieterBelmans] https://pbelmans.ncag.info/blog/276[KP2016] Kuznetsov, Alexander; Polishchuk, Alexander Exceptional collections on isotropic Grassmannians.277J. Eur. Math. Soc. (JEMS) 18 (2016), no. 3, 507–574.278"""279root_lattice = self._parabolic_subgroup._parent_group.Cartan_type().root_system().root_lattice()280ambient_space = self._parabolic_subgroup._parent_group.Cartan_type().root_system().ambient_space()281beta = root_lattice.simple_root(self._parabolic_subgroup._excluded_node).to_ambient() # The simple root associated to ``excluded_node``282xi = ambient_space.fundamental_weight(self._parabolic_subgroup._excluded_node) # The fundamental weight associated to ``excluded_node``283rho = ambient_space.rho() # Sum of fundamental weights284length = beta.dot_product(beta)285beta_bar = [ alpha for alpha in root_lattice.roots()286if alpha.coefficient(self._parabolic_subgroup._excluded_node) == 1 and alpha.to_ambient().dot_product(alpha.to_ambient()) == length287][-1].to_ambient()288# The maximal root of the same length as ``beta`` such that the coefficient of ``beta`` in the expression of ``beta_bar`` is 1.289Fano_index = rho.dot_product(beta + beta_bar) / xi.dot_product(beta)290return Fano_index291292293def Kostant_space ( self , i:sage.rings.integer.Integer , j:sage.rings.integer.Integer , restriction:str or None =None ) -> Iterator[ 'sage.combinat.root_system.weight_space.WeightSpace_with_category.element_class' ] :294"""295Returns the K(G,P,i,j) as introduced in [BS2023].296297INPUT:298- ``self`` -- minimal_irreducible_homogeneous_variety, base space X=G/P.299- ``i`` -- integer.300- ``j`` -- integer.301- ``restriction`` -- string.302303OUTPUT:304- ``Weight`` -- sage.combinat.root_system.weight_space.WeightSpace_with_category.element_class; highest weight corresponding to irreducible summand in K(G,P,i,j).305306307REFERENCE:308[BS2023] Belmans, Pieter; Smirnov, Maxim. Hochschild cohomology of generalised Grassmannians.309"""310# basis311fw = dict( self._parabolic_subgroup._parent_group.Cartan_type().root_system().weight_space().fundamental_weights() )312rho = sum(list(fw.values())) # sum of fundamental weights313ambt = { node : vector( QQ , (node-1)*[ 0 ] + [ 1 ] + (self._parabolic_subgroup._parent_group._Cartan_degree-node)*[ 0 ] )314for node in [ 1 .. self._parabolic_subgroup._parent_group._Cartan_degree ]315}316base_change = matrix( QQ , [ sum([ omega.to_ambient()[node-1]*e for node , e in ambt.items() ])317for omega in fw.values()318]319).transpose().inverse() # Cartan matrix describing base change from ambt to fw320# Weyl group321WG = self._parabolic_subgroup._parent_group.Weyl_group()322sr = WG.simple_reflections()323# Weyl character ring324WCR = self._parabolic_subgroup._parent_group.Weyl_character_ring()325326# integer invariants327dimension = self.dimension() # dimension328Fano_index = self.Fano_index() # Fano index329330for Weyl_element , reduced_description in self.Weyl_group_coset_representatives_of_minimal_length() :331if len(reduced_description) == dimension-i :332# See (1.7): Weight = WeylElement \cdot 0 + ( FanoIndex + j ) * fw[k]333result = Weyl_element.action(rho.to_ambient()) - rho.to_ambient() + (Fano_index+j)*fw[self._parabolic_subgroup._excluded_node].to_ambient()334vector_with_respect_to_ambt_basis = vector( QQ , [ result.coefficient(node) for node in range(self._parabolic_subgroup._parent_group._Cartan_degree) ] )335vector_with_respect_to_fw_basis = base_change*vector_with_respect_to_ambt_basis336weight = sum([ coefficient*fw[node] for node , coefficient in enumerate( vector_with_respect_to_fw_basis , start=1 ) ])337338if restriction in [ None , 'None' , 'none' , '' ] :339yield weight340elif restriction in [ 'Regular' , 'regular' , 'Reg' , 'reg' , 'Non-Singular' , 'non-singular' , 'Non-Sing' , 'non-sing' ] :341if self.is_regular( weight+rho ) : yield weight342else :343raise ValueError('The input for ``restriction`` is anppropriate.')344345346def is_adjoint ( self ) -> bool :347"""Tests if ``self`` is adjoint (cf. grassmannian.info)"""348if self._parabolic_subgroup._parent_group._Cartan_family == 'B' : return self._parabolic_subgroup._excluded_node == 2349elif self._parabolic_subgroup._parent_group._Cartan_family == 'C' : return self._parabolic_subgroup._excluded_node == 1350elif self._parabolic_subgroup._parent_group._Cartan_family == 'D' : return self._parabolic_subgroup._excluded_node == 2 and 4 <= self._parabolic_subgroup._parent_group._Cartan_degree351elif self._parabolic_subgroup._parent_group._Cartan_family == 'E' : return ( self._parabolic_subgroup._excluded_node == 2 and self._parabolic_subgroup._parent_group._Cartan_degree == 6 ) or \352( self._parabolic_subgroup._excluded_node == 1 and self._parabolic_subgroup._parent_group._Cartan_degree == 7 ) or \353( self._parabolic_subgroup._excluded_node == 8 and self._parabolic_subgroup._parent_group._Cartan_degree == 8 )354elif self._parabolic_subgroup._parent_group._Cartan_family == 'F' : return self._parabolic_subgroup._excluded_node == 1 and self._parabolic_subgroup._parent_group._Cartan_degree == 4355elif self._parabolic_subgroup._parent_group._Cartan_family == 'G' : return self._parabolic_subgroup._excluded_node == 2 and self._parabolic_subgroup._parent_group._Cartan_degree == 2356else : return False357358359def is_exceptional ( self ) -> bool :360"""Test if the Cartan family of ``self`` is out of [ E , F , G ]."""361return self._parabolic_subgroup._parent_group.ADMISSIBLE_CARTAN_FAMILIES[self._parabolic_subgroup._parent_group._Cartan_family][1] < +infinity362363364def is_ordinary ( self ) -> bool :365"""Test if the Cartan family of ``self`` is out of [ A , B , C , D ]."""366return not self.is_exceptional()367368369def is_regular ( self , weight:'sage.combinat.root_system.weight_space.WeightSpace_with_category.element_class' ) -> bool :370"""Tests if a given weight on ``self`` is G-regular (i.e. does not ly on a wall of a Weyl chamber)."""371return not self.is_singular( weight )372373374def is_singular ( self , weight:'sage.combinat.root_system.weight_space.WeightSpace_with_category.element_class' ) -> bool :375"""Tests if a given weight on ``self`` is G-singular (i.e. lies on a wall of a Weyl chamber)."""376assert weight in self._parabolic_subgroup._parent_group.Cartan_type().root_system().weight_space() , \377ValueError('The weight must be an element of the weight space: '+str(self._parabolic_subgroup._parent_group.Cartan_type().root_system().weight_space()))378# Move ``Weight`` to dominant chamber379weight_in_dominant_chamber = weight.to_dominant_chamber()380# Consider list of reflections of ``weight`` and check whether ``weight`` is invariant under some reflection381reflections = [ weight_in_dominant_chamber.simple_reflection( index ) for index in self._parabolic_subgroup._parent_group.Cartan_type().index_set() ]382return weight_in_dominant_chamber in reflections383384385def Weyl_group_coset_representatives_of_minimal_length ( self ) -> Iterator[ tuple[ 'sage.combinat.root_system.weyl_group.WeylGroup_gens_with_category.element_class' , list ] ] :386"""Returns the Weyl group coset representatives of minimal length"""387WG = self._parabolic_subgroup._parent_group.Weyl_group()388sr = WG.simple_reflections()389identity = sr[1]*(sr[1].inverse())390391stock = [ [ i+1 for i in w._reduced_word ] for w in WeylGroup( self._parabolic_subgroup._parent_group.Cartan_type() , implementation='permutation' ).iteration('breadth',True) ]392stock = [ ( prod([ identity ] + [ sr[node] for node in reduced_description ]) , reduced_description ) for reduced_description in stock ]393394for Weyl_element_0 , reduced_description_0 in stock :395length_0 = len(reduced_description_0)396397Weyl_element_0_is_coset_representaion_of_minimal_length = True398for node in self._parabolic_subgroup.included_nodes() :399Weyl_element_1 = sr[node]*Weyl_element_0400401for Weyl_element , reduced_description in stock :402if Weyl_element_1 == Weyl_element :403reduced_description_1 = reduced_description404length_1 = len(reduced_description_1)405break406407if length_1 != length_0+1 :408Weyl_element_0_is_coset_representaion_of_minimal_length = False409break410411if Weyl_element_0_is_coset_representaion_of_minimal_length :412yield Weyl_element_0 , reduced_description_0413414415