Environment to perform calculations of equivariant vector bundles on homogeneous varieties
Equivariant_Vector_Bundles_On_Homogeneous_Varieties__0-2 / src / Equivariant_Vector_Bundles_On_Homogeneous_Varieties / Base_Space / Homogeneous_Variety.sage
1842 viewsLicense: GPL3
ubuntu2204
from typing import Iterator1from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Foundation.Structure import Structure , Irreducible_Structure , Direct_Sum_Of_Structures2from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Base_Space.Cartan_Group import Irreducible_Cartan_Group3from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Base_Space.Parabolic_Subgroup import Parabolic_Subgroup_In_Irreducible_Cartan_Group4567class Homogeneous_Variety ( Structure ) :89BASIS_LABELLING = { 'sr' : [ 'sr' , 'simple roots' , 'alphas' , 'A' ] ,10'mx' : [ 'mx' , 'mixed' , 'simple roots for included nodes and fundamental weights for excluded nodes' , 'B' ] ,11'fw' : [ 'fw' , 'fundamental weights' , 'omegas' , 'C' ] ,12'ambt' : [ 'ambt' , 'ambient' , 'e_i`s' , 'D' ]13}14151617class Irreducible_Homogeneous_Variety ( Irreducible_Structure , Homogeneous_Variety ) :1819def __init__( self , Parabolic_Subgroup:Parabolic_Subgroup_In_Irreducible_Cartan_Group ) -> None :20"""21Initialize a homogeneous variety X=G/P.2223INPUT:24- ``Parabolic_Subgroup`` -- Parabolic_Subgroup_In_Irreducible_Cartan_Group ;2526OUTPUT: None.27"""28assert isinstance( Parabolic_Subgroup , Parabolic_Subgroup_In_Irreducible_Cartan_Group ) , \29TypeError('The input must be a parabolic subgroup in an irreducible Cartan group.')30self._Parabolic_Subgroup = Parabolic_Subgroup313233def __repr__ ( self ) -> Parabolic_Subgroup_In_Irreducible_Cartan_Group :34"""Returns all attributes which are necessary to initialize the object."""35return self.Parent_Group()363738def __str__ ( self , Output_Style='Long' ) -> str :39"""Returns a one-line string as short description."""40if Output_Style == 'Short' : return self.Parent_Group().Cartan_String() + '/P(' + str( self.Included_Nodes() ) + ')'41elif Output_Style == 'Long' : return 'Smooth projective variety ' + self.__str__( Output_Style='Short' ) + '.'42else : raise ValueError('The input for ``Output_Style`` is inappropriate.')434445def Available_Negative_Roots ( self ) -> "Root" :46"""Returns all available negative roots."""47for Root in self.Parent_Group().Cartan_Type().root_system().root_lattice().negative_roots() :48if not Root in self.Parabolic_Subgroup().Negative_Roots() :49yield Root505152def Available_Positive_Roots ( self ) -> "Root" :53"""Returns all available positive roots."""54for Root in self.Parent_Group().Cartan_Type().root_system().root_lattice().positive_roots() :55if not Root in self.Parabolic_Subgroup().Negative_Roots() :56yield Root575859def Available_Roots ( self ) -> "Root" :60"""Returns all available roots."""61for Root in self.Parent_Group().Cartan_Type().root_system().root_lattice().roots() :62if not Root in self.Parabolic_Subgroup().Negative_Roots() :63yield Root646566def Basis ( self , Label:str='mx' ) -> dict :67"""68Returns the basis in terms of simple roots and fundamental weights.6970INPUT:71- ``self`` -- Parabolic_Subgroup; the parabolic subgroup P of a Cartan group G.72- ``Label`` -- str (default: 'mx');7374OUTPUT:75- ``Output`` -- Dictionary.7677ALGORITHM:78- alpha_i : the simple root associated to the i-th node.79- omega_i : the fundamental weight associated to the i-th node.8081- sr = { alpha_i }82- mx_{ i : i excluded } = { alpha_i : i included } cup { omega_i : i excluded }.83Note: mx_{} = sr and mx_{ all i's } = fw84- fw = { omega_i }85- ambt = { standard basis e_i }86"""87if Label in self.BASIS_LABELLING['sr'] :88return dict( self.Parent_Group().Cartan_Type().root_system().weight_space().simple_roots() )8990elif Label in self.BASIS_LABELLING['mx'] :91MixedBasis = {}92for Node in self.Parent_Group().Cartan_Type().index_set() :93if Node in self.Parabolic_Subgroup().Included_Nodes() : Element = self.Parent_Group().Cartan_Type().root_system().weight_space().simple_root(Node)94elif Node in self.Parabolic_Subgroup().Excluded_Nodes() : Element = self.Parent_Group().Cartan_Type().root_system().weight_space().fundamental_weight(Node)95else : raise ValueError('Plausibility? The set of nodes subdivides into the disjoint union of marked ones and excluded ones.')96MixedBasis.update( { Node : Element } )97return MixedBasis9899elif Label in self.BASIS_LABELLING['fw'] :100return dict( self.Parent_Group().Cartan_Type().root_system().weight_space().fundamental_weights() )101102elif Label in self.BASIS_LABELLING['ambt'] :103n = self.Parent_Group().Cartan_Degree()104return { Node : vector( QQ , (Node-1)*[ 0 ] + [ 1 ] + (n-Node)*[ 0 ] ) for Node in [ 1 .. n ] }105106else : raise ValueError('The input of ``Label`` is inappropriate.')107108109# Synonym for the method ``Tautological_Subbundle``110def calO ( self , *Twists:tuple[int] ) -> "Irreducible_Equivariant_Vector_Bundle" :111"""Returns the structure sheaf or a twist of it."""112return self.Structure_Sheaf( *Twists )113114115# Snynoms for different methods depending on the input116def calU ( self , *Input ) -> "Irreducible_Equivaraint_Vector_Bundle" :117"""Returns the tautological subbundle (if there no input) or the irreequivariant vector bundle associated to a highest weight (if there is some input otherwise)."""118if len(Input) == 0 : # Synonym for the method ``Tautological_Subbundle``119return self.Tautological_Subbundle()120121else : # Synonym for the method ``Equivariant_Vector_Bundles``122return self.Equivariant_Vector_Bundle( *Input )123124125# Synonym for the method ``Trivial_Vector_Bundle``126def calV ( self ) -> "Direct_Sum_Of_Equivariant_Vector_Bundles" :127"""Returns the trivial vector bundle ."""128return self.Trivial_Vector_Bundle()129130131def Cartan_Degree ( self ) -> int :132"""Returns the Cartan degree of the parent Group G."""133return self.Parent_Group().Cartan_Degree()134135136def Cartan_Family ( self ) -> str :137"""Returns the Cartan family of the parent Group G."""138return self.Parent_Group().Cartan_Family()139140141def Cartan_Matrix ( self , From:str='fw' , To:str='mx' ) -> Matrix :142"""143Returns the base change between the bases sr, mx or fw.144145INPUT:146- ``self`` -- Parabolic_Subgroup; the parabolic subgroup P of a Cartan group G.147148OUTPUT:149- ``Output`` -- Matrix.150151ALGORITHM:152- alpha_i : the simple root associated to the i-th node.153- omega_i : the fundamental weight associated to the i-th node.154155- sr >> fw : Cartan matrix156- fw >> sr : Inverse of Cartan matrix (sr >> fw)157- mx >> fw : For each excluded node i, replace the i-th column by a standard vector e_i.158- fw >> mx : Inverse of mx >> fw159- sr >> mx : Composition of sr >> fw >> mx160- mx >> sr : Inverse of sr >> mx161"""162if From in self.BASIS_LABELLING['sr'] : From = 'sr'163elif From in self.BASIS_LABELLING['mx'] : From = 'mx'164elif From in self.BASIS_LABELLING['fw'] : From = 'fw'165elif From in self.BASIS_LABELLING['ambt'] : From = 'ambt'166else : raise ValueError('The input for ``From`` is inappropriate.')167if To in self.BASIS_LABELLING['sr'] : To = 'sr'168elif To in self.BASIS_LABELLING['mx'] : To = 'mx'169elif To in self.BASIS_LABELLING['fw'] : To = 'fw'170elif To in self.BASIS_LABELLING['ambt'] : To = 'ambt'171else : raise ValueError('The input for ``To`` is inappropriate.')172173if From == To : return matrix.identity( self.Parent_Group().Cartan_Degree() )174175elif From == 'sr' :176if To == 'mx' : return self.Cartan_Matrix( From = 'fw' , To = 'mx') * self.Cartan_Matrix( From = 'sr' , To = 'fw')177elif To == 'fw' : return self.Parent_Group().Cartan_Type().cartan_matrix()178elif To == 'ambt' :179sr = self.Basis('sr')180ambt = self.Basis('ambt')181return matrix( QQ , [ sum([ alpha.to_ambient()[Node-1]*e for Node , e in ambt.items() ]) for Node , alpha in sr.items() ] ).transpose()182183elif From == 'mx' :184if To == 'sr' : return self.Cartan_Matrix( From = 'sr' , To = 'mx' ).inverse()185elif To == 'fw' :186Matrix = copy( self.Cartan_Matrix( From = 'sr' , To = 'fw' ) )187for Node in self.Parabolic_Subgroup().Excluded_Nodes() :188Matrix[:,Node-1] = vector([ kronecker_delta( I , Node ) for I in [ 1 .. self.Parent_Group().Cartan_Degree() ] ])189return Matrix190elif To == 'ambt' : return self.Cartan_Matrix( From = 'fw' , To = 'ambt') * self.Cartan_Matrix( From = 'mx' , To = 'fw')191192elif From == 'fw' :193if To == 'sr' : return self.Cartan_Matrix( From = 'sr' , To = 'fw' ).inverse()194elif To == 'mx' : return self.Cartan_Matrix( From = 'mx' , To = 'fw' ).inverse()195elif To == 'ambt' :196fw = self.Basis('fw')197ambt = self.Basis('ambt')198return matrix( QQ , [ sum([ omega.to_ambient()[Node-1]*e for Node , e in ambt.items() ]) for Node , omega in fw.items() ] ).transpose()199200elif From == 'ambt' :201if To == 'sr' : return self.Cartan_Matrix( From = 'sr' , To = 'ambt' ).inverse()202elif To == 'fw' : return self.Cartan_Matrix( From = 'fw' , To = 'ambt' ).inverse()203elif To == 'mx' : return self.Cartan_Matrix( From = 'mx' , To = 'ambt' ).inverse()204205206def Cartan_String ( self ) -> str :207"""Returns the Cartan string of the parent Group G."""208return self.Parent_Group().Cartan_String()209210211def Cartan_Type ( self ) -> CartanType :212"""Returns the attribute ``Cartan_Type`` of the parent Group G."""213return self.Parent_Group().Cartan_Type()214215216def Compare_Roots ( self , Root1 , Root2 ) -> str or None :217"""Returns None if the two roots are not comparable and a result '<', '==', or '>' otherwise."""218219RL = self.Parent_Group().Cartan_Type().root_system().root_lattice()220assert Root1 in RL , \221ValueError('The input for ``Root1`` is not a root.')222assert Root2 in RL , \223ValueError('The input for ``Root2`` is not a root.')224225if Root1 == Root2 :226return '=='227228else :229Difference_In_srBasis = Root1-Root2230if Difference_In_srBasis.is_positive_root() : return '>'231elif (-1*Difference_In_srBasis).is_positive_root() : return '<'232else : return None233234235def Compare_Weights ( self , Weight1 , Weight2 ) -> str or None :236"""Returns None if the two weights are not comparable and a result '<', '==', or '>' otherwise."""237238WS = self.Parent_Group().Cartan_Type().root_system().weight_space()239assert Weight1 in WS , \240ValueError('The input for ``Weight1`` is not a weight.')241assert Weight2 in WS , \242ValueError('The input for ``Weight2`` is not a weight.')243244if Weight1 == Weight2 :245return '=='246247else :248RL = self.Parent_Group().Cartan_Type().root_system().root_space()249scr = RL.simple_coroots()250sr = RL.simple_roots()251Coefficients_For_fwBasis = [ (Weight1-Weight2).scalar(coroot) for coroot in scr ]252Coefficients_For_srBasis = vector( QQ , Coefficients_For_fwBasis ) * self.Cartan_Matrix( From='fw' , To='sr' )253Difference_In_srBasis = sum([ QQ(Coefficient)*sr[Node] for Node , Coefficient in enumerate( list( Coefficients_For_srBasis ) , start = 1 ) ])254255if Difference_In_srBasis.is_positive_root() : return '>'256elif (-1*Difference_In_srBasis).is_positive_root() : return '<'257else : return None258259260def Complex ( self , Objects ) -> "Complex_Over_Irreducible_Homogeneous_Variety" :261"""Returns a complex of equivariant vector bundles over ``self``."""262from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Overlying_Structure.Complex_Of_Equivariant_Vector_Bundles import Complex_Of_Coherent_Sheaves263return Complex_Of_Coherent_Sheaves( Base_Space=self , Objects=Objects )264265266# ..ToDo: For PP^n, it is only correct up to sign.267def Complex_Defining_Exterior_Power_Of_Tautological_Quotient_Bundle ( self , p :int =1 ) -> "Complex_Over_Irreducible_Homogeneous_Variety" :268"""Returns the complex defining the p-th exterior power of the tautological quotient bundle on ``self``."""269assert isinstance( p , Integer ) , \270'The input for `p` need to be an integer.'271272G = self.Parent_Group()273fw = self.Basis('fw')274Terms = dict({})275for i in [ 0 .. p+1 ] :276if i == 0 : Terms.update({ 0 : 'Cokernel' })277else : Terms.update({ -1*i : self.Tautological_Subbundle().Symmetric_Power( i-1 ).Multiply_By( G.rmV( fw[1] ).exterior_power( p-i+1 ) ) })278return self.Complex( Terms )279280281def Dimension ( self ) -> int :282"""Returns the dimension dim X = dim G - dim P."""283return self.Parent_Group().Dimension() - self.Parabolic_Subgroup().Dimension()284285286def Equivariant_Vector_Bundle ( self , *Inputs:tuple ) -> "Equivariant_Vector_Bundles" :287"""Returns the direct sum of equivariant vector bundles induced by the given highest weights."""288Constituent_Parts = list(Inputs)289from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Overlying_Structure.Equivariant_Vector_Bundle import Equivariant_Vector_Bundle290return Equivariant_Vector_Bundle.Constructor( Base_Space=self , Constituent_Parts=Constituent_Parts )291292293def Excluded_Nodes ( self ) -> set :294"""Returns the attribute ``Excluded_Nodes`` of the parabolic subgroup P."""295return self.Parabolic_Subgroup().Excluded_Nodes()296297298def Expected_Support_Partition_For_Minimal_Full_Lefschetz_Collection ( self ) -> tuple[ int ] :299"""Returns the expected support partition for a minimal Lefschetz collection on ``self``."""300assert self.Parabolic_Subgroup().Is_Maximal() , \301ValueError('The method is only implemented for those homogeneous varieties where the parabolic subgroup is maximal.')302303Collection__Expected_Length = self.K0().rank()304Node , Fano_Index = next(self.Fano_Index())305306Rectangular_Part__Expected_Height = Fano_Index307Rectangular_Part__Expected_Width = floor( Collection__Expected_Length / Rectangular_Part__Expected_Height )308Residual_Part__Expected_Height = Collection__Expected_Length - Rectangular_Part__Expected_Height * Rectangular_Part__Expected_Width309if Residual_Part__Expected_Height == 0 : Residual_Part__Expected_Width = 0310else : Residual_Part__Expected_Width = 1311312return tuple( Residual_Part__Expected_Height * [ Rectangular_Part__Expected_Width+1 ] + \313(Rectangular_Part__Expected_Height-Residual_Part__Expected_Height) * [ Rectangular_Part__Expected_Width ] \314)315316317def Fano_Index ( self ) -> Iterator[ tuple[ int , int ] ]:318"""319Returns the Fano index of ``self``.320321INPUT:322- ``self`` -- Parabolic_Subgroup; the parabolic subgroup P of a Cartan group G.323324OUTPUT:325- ``Node`` -- Excluded node326- ``Fano_Index`` -- Index associated to X = G/P(Excluded_Nodes={Node})327328ALGORITHM:329Thanks to the post by Pieter Belmans concerning the index of partial flag varieties330from Aug 23rd, 2018 on his blog (cf. to [Blog_PieterBelmans]_). The link is331https://pbelmans.ncag.info/blog/2018/08/23/index-partial-flag-varieties/332(Date: Apr 26th, 2021).333334The 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 i335such that ω∨_X ≅ O_X(1) ⊗ i.336337To compute it, we use lemma 2.19 and remark 2.20 of [KP2016]. Combined they say the following:338Let β be the simple root corresponding to the chosen maximal parabolic subgroup P, and ξ the associated339fundamental weight. Let ¯β be the maximal root of the same length as β such that the coefficient of β340in the expression of ¯β is 1.341Then the index of G/P equals i_G/P = (ρ,β+¯β)/(ξ,β).342343REFERENCE:344[Blog_PieterBelmans] https://pbelmans.ncag.info/blog/345[KP2016] Kuznetsov, Alexander; Polishchuk, Alexander Exceptional collections on isotropic Grassmannians.346J. Eur. Math. Soc. (JEMS) 18 (2016), no. 3, 507–574.347"""348Root_Lattice = self.Parent_Group().Cartan_Type().root_system().root_lattice()349Ambient_Space = self.Parent_Group().Cartan_Type().root_system().ambient_space()350351for Node in self.Parabolic_Subgroup().Excluded_Nodes() :352Beta = Root_Lattice.simple_root(Node).to_ambient() # The simple root associated to ``Node``353Xi = Ambient_Space.fundamental_weight(Node) # The fundamental weight associated to ``Node``354Rho = Ambient_Space.rho() # Sum of fundamental weights355Length = Beta.dot_product(Beta)356Beta_Bar = [Alpha for Alpha in Root_Lattice.roots() if Alpha.coefficient(Node) == 1 and Alpha.to_ambient().dot_product(Alpha.to_ambient()) == Length][-1].to_ambient()357# The maximal root of the same length as ``Beta`` such that the coefficient of ``Beta`` in the expression of ``Beta_Bar`` is 1.358Fano_Index = Rho.dot_product(Beta + Beta_Bar) / Xi.dot_product(Beta)359yield Node , Fano_Index360361362def Grothendieck_Group ( self ) -> FreeModule :363"""364Returns the Grothendieck Group of X=G/P.365366INPUT:367- ``self`` -- Homogeneous Variety.368369OUTPUT:370- ``Output`` -- Integer; The rank of the Grothendieck group of X=G/P.371372ALGORITHM:373Thanks to the post by Pieter Belmans concerning the index of partial flag varieties374from Aug 22nd, 2018 on his blog (cf. to [Blog_PieterBelmans]_). The link is375https://pbelmans.ncag.info/blog/2018/08/22/rank-flag-varieties/376(Date: Apr 26th, 2021).377378It can be computed as the rank of the homology of X=G/P using the Bruhat cell decomposition,379and is equal to #WG/#WL, where WG (resp. WL) denotes the Weyl group of G (resp. L).380L is the Levi subgroup inside the maximal parabolic P.381382.. TODO:383- Check if the rank of the Grothendieck group is always be given by the Euler characteristic.384- Fix Rank_Of_GrothendieckGroup for Borel subgroups.385386REFERENCE:387[Blog_PieterBelmans] https://pbelmans.ncag.info/blog/388[KP2016] Kuznetsov, Alexander; Polishchuk, Alexander Exceptional collections on isotropic Grassmannians.389J. Eur. Math. Soc. (JEMS) 18 (2016), no. 3, 507–574.390"""391Cartan_Type_of_Parent_Group = self.Parent_Group().Cartan_Type()392Weyl_Group_of_Parent_Group = Cartan_Type_of_Parent_Group.root_system().root_lattice().weyl_group()393394if self.Parabolic_Subgroup().Is_Borel() :395# Question: Because WeylGroup_of_Levi_Part.cardinality() == 1?396return Integers()^( Weyl_Group_of_Parent_Group.cardinality() )397398else :399Cartan_Type_of_Levi_Part = self.Parent_Group().Cartan_Type().dynkin_diagram().subtype( self.Parabolic_Subgroup().Included_Nodes() )400Weyl_Group_of_Levi_Part = Cartan_Type_of_Levi_Part.root_system().root_lattice().weyl_group()401return Integers()^( Weyl_Group_of_Parent_Group.cardinality() / Weyl_Group_of_Levi_Part.cardinality() )402403404def Kostant_Space ( self , i:int , j:int , Restriction:str or None =None ) -> Iterator[ "Weight" ] :405"""406Returns the K(G,P,i,j) as introduced in [BS2023].407408INPUT:409- ``self`` -- Homogeneous variety.410- ``i`` -- integer.411- ``j`` -- integer.412413OUTPUT:414- ``Weight`` -- highest weight corresponding to irreducible summand in K(G,P,i,j).415416417REFERENCE:418[BS2023] Belmans, Pieter; Smirnov, Maxim. Hochschild cohomology of generalised Grassmannians.419"""420G = self.Parent_Group()421P = self.Parabolic_Subgroup()422assert P.Is_Maximal() , \423'The homogeneous variety ``self`` needs to be minimal; or equivalently, its associaed parabolic subgroup needs to be maximal.'424k = self.k()425426# Weyl Group427WG = WeylGroup( G.Cartan_Type() )428sr = WG.simple_reflections()429fw = self.Basis('fw')430# Weyl Character Ring431WCR = G.Weyl_Character_Ring()432# Sum of fundamental weights433Rho = sum(list(fw.values()))434# Fano index435Fano_Indices = { Node : Value for ( Node , Value ) in (G/P).Fano_Index() }436assert len(Fano_Indices.keys()) == 1 and k in Fano_Indices.keys() , \437'For minimal homogeneous variety, the Fano index needs to be a unique value associated to the excluded node k='+str(k)+'.'438FanoIndex = Fano_Indices[k]439# Dimension440Dimension = self.Dimension()441442CM = self.Cartan_Matrix( From='ambt' , To='fw' )443444for WeylElement , ReducedDescription in self.Weyl_Group_Coset_Representatives_Of_Minimal_Length() :445if len(ReducedDescription) == Dimension-i :446# See (1.7): Weight = WeylElement \cdot 0 + ( FanoIndex + j ) * fw[k]447Result = WeylElement.action(Rho.to_ambient()) - Rho.to_ambient() + (FanoIndex+j)*fw[k].to_ambient()448ambt_Description = vector( QQ , [ Result.coefficient(i) for i in range(G.Cartan_Degree()) ] )449fw_Description = CM*ambt_Description450Weight = sum([ Coefficient*fw[Node] for Node , Coefficient in enumerate( fw_Description , start=1 ) ])451452if Restriction in [ None , 'None' , 'none' , '' ] :453yield Weight454elif Restriction in [ 'Regular' , 'regular' , 'Reg' , 'reg' , 'Non-Singular' , 'non-singular' , 'Non-Sing' , 'non-sing' ] :455if self.Is_Regular( Weight+Rho ) : yield Weight456else :457raise ValueError('The input for ``Restriction`` is anppropriate.')458459460def Kuznetsov_Polishchuk_Collection ( self ) -> Iterator[ tuple[ int , int , int , "weight" , str ] ] :461"""462Returns the collection of Kuznetsov and Polishchuk on X=G/P.463464INPUT:465- ``self`` -- Homogeneous variety.466467OUTPUT:468- ``TotalCounter`` -- Counter running over all objects of the collection.469- ``BlockCounter`` -- Counter running over all objects of the current block.470- ``t`` -- Integer; block index.471- ``Lambda`` -- highest weight of object.472- ``cE`` -- string description of cE(Lambda).473474.. TODO:475- Implement collection for exceptional cases.476477REFERENCE:478[KP2016] Kuznetsov, Alexander; Polishchuk, Alexander Exceptional collections on isotropic Grassmannians.479J. Eur. Math. Soc. (JEMS) 18 (2016), no. 3, 507–574.480"""481482G = self.Parent_Group()483assert G.Is_Irreducible() , \484'The parent group of ``self`` need to be irreducible.'485Cartan_Family = G.Cartan_Family()486n = self.Cartan_Degree()487488P = self.Parabolic_Subgroup()489assert P.Is_Maximal() , \490'The parabolic subgroup of ``self`` need to be maximal.'491k = self.k()492493Blocks = dict({})494# Conjecture 9.8. on page 49495if Cartan_Family in [ 'A' ] :496l = n+1-k497# Collect all intersection points between a line segment from (0,0) to (k,l) and a grid { (x,y) : x \in ZZ or y \in ZZ }498Slope = l/k499Q = []500for xRunner1 in [ 0 .. k ] :501yRunner1 = Slope*xRunner1502Q += [ ( xRunner1 , yRunner1 ) ]503if xRunner1 < k: # Notice: 0 < Slope = (n+1)/k - 1 if and only if k < n+1504for yRunner2 in [ ceil(yRunner1) .. floor(yRunner1+Slope) ] :505xRunner2 = 1/Slope*yRunner2506if yRunner1 < yRunner2 and yRunner2 < yRunner1+Slope : Q += [ ( xRunner2 , yRunner2 ) ]507for t , (x,y) in enumerate(Q) :508a = floor(x)509b = floor(y)510c = k - ceil(x)511d = l - ceil(y)512Block = []513for p1 in IntegerListsLex( length=a , min_part=t , max_part=d+t , max_slope=0 ) :514p1 = list(p1)515p2 = [ t for Node in [ a+1 .. k ] ]516p3 = [ 0 for Node in [ k+1 .. n+1-b ] ]517for p4 in IntegerListsLex( length=b , min_part=0 , max_part=c , max_slope=0 ) :518p4 = [ Entry-c for Entry in p4 ]519Highest_Weight = p1+p2+p3+p4520Block += [ Highest_Weight ]521Block.reverse()522Blocks.update({ t : Block })523524elif Cartan_Family in [ 'B' , 'D' ] :525# Equation 56 on page 39526if Cartan_Family == 'B' : e = 1/2527elif Cartan_Family == 'D' : e = 0528529# k <= n-1 if Cartan family is B or k <= n-2 if Cartan family is D530# Theorem 9.1. on page 42531if k in [ 1 .. n+2*e-2 ] :532for t in [ 0 .. k-1 ] :533Block = []534for p1 in IntegerListsLex ( length=t , min_part=t , max_part=2*n+2*e-k-2 , max_slope=0 ) :535p1 = list(p1)536p2 = [ t for Node in [ t+1 .. k ] ]537for p3 in IntegerListsLex ( length=n-k , min_part=(2*e-1)*t , max_part=floor((k-t)/2) , max_slope=0 ) :538p3 = list(p3)539Highest_Weight = p1+p2+p3540if Highest_Weight[n-1] >= (2*e-1)*Highest_Weight[n-2] : Block += [ Highest_Weight ]541Block.reverse()542Blocks.update({ t : Block })543Block = []544for p1 in IntegerListsLex ( length=t , min_part=t , max_part=2*n+2*e-k-2 , max_slope=0 ) :545p1 = [ Entry+1/2 for Entry in p1 ]546p2 = [ t+1/2 for Node in [ t+1 .. k ] ]547for p3 in IntegerListsLex ( length=n-k , min_part=ceil((2*e-1)*t-1/2) , max_part=floor((k-t)/2-1/2) , max_slope=0 ) :548p3 = [ Entry+1/2 for Entry in p3 ]549Highest_Weight = p1+p2+p3550if Highest_Weight[n-1] >= (2*e-1)*Highest_Weight[n-2] : Block += [ Highest_Weight ]551Block.reverse()552Blocks.update({ t+1/2 : Block })553for t in [ k .. 2*n+2*e-k-2 ] :554Block = []555for p1 in IntegerListsLex ( length=k-1 , min_part=t , max_part=2*n+2*e-k-2 , max_slope=0 ) :556p1 = list(p1)557p2 = [ t ]558p3 = [ 0 for Node in [ k+1 .. n ] ]559Highest_Weight = p1+p2+p3560Block += [ Highest_Weight ]561Block.reverse()562Blocks.update({ t : Block })563564# k == n if Cartan family is B or k from { n-1 , n } if Cartan family is D565# Theorem 9.3. on page 43566elif k in [ n+2*e-1 .. n ] :567# D_n/P_n-1 and D_n/P_n are both isomorphic to B_n-1/P_n-1568if Cartan_Family == 'D' :569Cartan_Family = 'B'570n = n-1571k = n572for t in [ 0 .. n-1 ] :573Block = []574for p1 in IntegerListsLex ( length=t , min_part=t , max_part=n-1 , max_slope=0 ) :575p1 = list(p1)576p2 = [ t for Node in [ t+1 .. n ] ]577Highest_Weight = p1+p2578Block += [ Highest_Weight ]579Block.reverse()580Blocks.update({ 2*t : Block })581Blocks.update({ 2*t+1 : [ [ Entry+1/2 for Entry in Highest_Weight ] for Highest_Weight in Blocks[2*t] ] })582583# Theorem 9.2. on page 42584elif Cartan_Family == 'C' :585for t in [ 0 .. k-1 ] :586Block = []587for p1 in IntegerListsLex ( length=t , min_part=t , max_part=2*n-k , max_slope=0 ) :588p1 = list(p1)589p2 = [ t for Node in [ t+1 .. k ] ]590for p3 in IntegerListsLex ( length=n-k , min_part=0 , max_part=floor((k-t)/2) , max_slope=0 ) :591p3 = list(p3)592Highest_Weight = p1+p2+p3593Block += [ Highest_Weight ]594Block.reverse()595Blocks.update({ t : Block })596for t in [ k .. 2*n-k ] :597Highest_Weights = []598for p1 in IntegerListsLex ( length=k-1 , min_part=t , max_part=2*n-k , max_slope=0 ) :599p1 = list(p1)600p2 = [t]601p3 = [ 0 for Node in [ k+1 .. n ] ]602Highest_Weight = p1+p2+p3603Block += [ Highest_Weight ]604Block.reverse()605Blocks.update({ t : Block })606607else :608raise ValueError('The algorithm is not implement for the exceptional cases E_6, E_7, E_8, F_4, or G_2.')609610fw = self.Basis('fw')611CM = self.Cartan_Matrix( From='ambt' , To='fw' )612if Cartan_Family == 'A' :613CM = block_matrix( QQ , [ [ CM , matrix( QQ , (n-1)*[ [0] ] + [ [-1] ] ) ] ] , subdivide=False )614TotalCounter = 0615for t , Block in Blocks.items() :616Previous_Objects = []617for BlockCounter , Highest_Weight_in_ambtBasis in enumerate( Block , start=1 ) :618TotalCounter += 1619Highest_Weight_in_fwBasis = CM*vector( QQ , Highest_Weight_in_ambtBasis )620Highest_Weight = sum([ Coefficient*fw[Node] for Node , Coefficient in enumerate( Highest_Weight_in_fwBasis , start=1 ) ])621cU = str(self.calU(Highest_Weight))622if Cartan_Family in [ 'A' ] :623cE = cU624elif Cartan_Family in [ 'B' , 'C' , 'D' ] :625if len(Previous_Objects) == 0 : cE = cU626else : cE = 'Right mutation of '+cU+' through <'+', '.join(Previous_Objects)+'>'627yield TotalCounter , BlockCounter , t , Highest_Weight , cE628Previous_Objects += [ cU ]629630631def Included_Nodes ( self ) -> set :632"""Returns the attribute ``Included_Nodes`` of the parabolic subgroup P."""633return self.Parabolic_Subgroup().Included_Nodes()634635636def Irreducible_Equivariant_Vector_Bundle ( self , Highest_Weight:"Weight" ) -> "Irreducible_Equivariant_Vector_Bundle" :637"""Returns the equivariant vector bundle induced by the given highest weight."""638if Highest_Weight == 0 :639fw = self.Basis('fw')640Highest_Weight = 0 * fw[1]641from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Overlying_Structure.Equivariant_Vector_Bundle import Irreducible_Equivariant_Vector_Bundle642return Irreducible_Equivariant_Vector_Bundle( Base_Space=self , Highest_Weight=Highest_Weight )643644645# ..ToDo : Improve the testing. Get a cleaner algorithm based immediately on the definition.646def Is_Adjoint ( self ) -> bool :647"""Tests if ``self`` is adjoint (cf. grassmannian.info)"""648G = self.Parent_Group()649Cartan_Family = G.Cartan_Family()650Cartan_Degree = G.Cartan_Degree()651P = self.Parabolic_Subgroup()652assert P.Is_Maximal() , \653ValueError('This method is only implemented for maximal parabolic subgroups.')654k = self.k()655if Cartan_Family == 'B' : return k == 2656elif Cartan_Family == 'C' : return k == 1657elif Cartan_Family == 'D' : return k == 2 and 4 <= Cartan_Degree658elif Cartan_Family == 'E' : return ( Cartan_Degree == 6 and k == 2 ) or ( Cartan_Degree == 7 and k == 1 ) or ( Cartan_Degree == 8 and k == 8 )659elif Cartan_Family == 'F' : return ( Cartan_Degree == 4 and k == 1 )660elif Cartan_Family == 'G' : return ( Cartan_Degree == 2 and k == 2 )661else : return False662663664# ..ToDo : Improve the testing. Get a cleaner algorithm based immediately on the definition.665def Is_Coadjoint ( self ) -> bool :666"""Tests if ``self`` is coadjoint (cf. grassmannian.info)"""667G = self.Parent_Group()668Cartan_Family = G.Cartan_Family()669Cartan_Degree = G.Cartan_Degree()670P = self.Parabolic_Subgroup()671assert P.Is_Maximal() , \672ValueError('This method is only implemented for maximal parabolic subgroups.')673k = self.k()674if Cartan_Family == 'B' : return k == 1675elif Cartan_Family == 'C' : return k == 2676elif Cartan_Family == 'D' : return k == 2 and 4 <= Cartan_Degree677elif Cartan_Family == 'E' : return ( Cartan_Degree == 6 and k == 2 ) or ( Cartan_Degree == 7 and k == 1 ) or ( Cartan_Degree == 8 and k == 8 )678elif Cartan_Family == 'F' : return ( Cartan_Degree == 4 and k == 4 )679elif Cartan_Family == 'G' : return ( Cartan_Degree == 2 and k == 1 )680else : return False681682683# ..ToDo : Improve the testing. Get a cleaner algorithm based immediately on the definition.684def Is_Cominuscule ( self ) -> bool :685"""Tests if ``self`` is cominuscule (cf. grassmannian.info)"""686G = self.Parent_Group()687Cartan_Family = G.Cartan_Family()688Cartan_Degree = G.Cartan_Degree()689P = self.Parabolic_Subgroup()690assert P.Is_Maximal() , \691ValueError('This function is only implemented for maximal parabolic subgroups.')692k = self.k()693if Cartan_Family == 'A' : return True694elif Cartan_Family == 'B' : return k == 1695elif Cartan_Family == 'C' : return k == Cartan_Degree696elif Cartan_Family == 'D' : return k in [ 1 , CartenDegree-1 , Cartan_Degree ]697elif Cartan_Family == 'E' : return ( Cartan_Degree == 6 and k in [ 1 , 6 ] ) or ( Cartan_Degree == 7 and k == 7 )698else : return False699700701# ..ToDo : Specify the type for the input ``Weight``!702def Is_Levi_Dominant ( self , Weight ) -> bool :703"""Tests if a given weight on ``self`` is Levi-dominant (i.e. all coefficients over included nodes are non-negative)."""704assert Weight in self.Parent_Group().Cartan_Type().root_system().weight_space() , \705ValueError('The weight must be an element of the weight space: '+str(self.Parent_Group().Cartan_Type().root_system().weight_space()))706for Node in self.Parabolic_Subgroup().Included_Nodes() :707if Weight.coefficient(Node) < 0 : return False708return True709710711# ..ToDo : Improve the testing. Get a cleaner algorithm based immediately on the definition.712def Is_Minuscule ( self ) -> bool :713"""Tests if ``self`` is minuscule (cf. grassmannian.info)"""714G = self.Parent_Group()715Cartan_Family = G.Cartan_Family()716Cartan_Degree = G.Cartan_Degree()717P = self.Parabolic_Subgroup()718assert P.Is_Maximal() , \719ValueError('This function is only implemented for maximal parabolic subgroups.')720k = self.k()721if Cartan_Family == 'A' : return True722elif Cartan_Family == 'B' : return k == Cartan_Degree723elif Cartan_Family == 'C' : return k == 1724elif Cartan_Family == 'D' : return k in [ 1 , CartenDegree-1 , Cartan_Degree ]725elif Cartan_Family == 'E' : return ( Cartan_Degree == 6 and k in [ 1 , 6 ] ) or ( Cartan_Degree == 7 and k == 7 )726else : return False727728729def Is_Regular ( self , Weight:"Weight" ) -> bool :730"""Tests if a given weight on ``self`` is G-regular (i.e. does not ly on a wall of a Weyl chamber)."""731assert Weight in self.Parent_Group().Cartan_Type().root_system().weight_space() , \732ValueError('The weight must be an element of the weight space: '+str(self.Parent_Group().Cartan_Type().root_system().weight_space()))733return not self.Is_Singular( Weight )734735736def Is_Singular ( self , Weight:"Weight" ) -> bool :737"""Tests if a given weight on ``self`` is G-singular (i.e. lies on a wall of a Weyl chamber)."""738assert Weight in self.Parent_Group().Cartan_Type().root_system().weight_space() , \739ValueError('The weight must be an element of the weight space: '+str(self.Parent_Group().Cartan_Type().root_system().weight_space()))740# Move ``Weight`` to dominant chamber741Weight_In_Dominant_Chamber = Weight.to_dominant_chamber()742# Consider list of reflections of ``Weight`` and check whether ``Weight`` is invariant under some reflection743Reflections = [ Weight_In_Dominant_Chamber.simple_reflection( Index ) for Index in self.Parent_Group().Cartan_Type().index_set() ]744return Weight_In_Dominant_Chamber in Reflections745746747def k ( self ) -> int :748"""Returns the number ``k`` given in the realisation as Grassmannian."""749P = self.Parabolic_Subgroup()750Excluded_Nodes = P.Excluded_Nodes(Output_Type=list)751if P.Is_Maximal() : return Excluded_Nodes[0]752else : return Excluded_Nodes753754755# Synonym for the method ``Grothendieck_Group``756def K0 ( self ) -> FreeModule :757"""Returns the Grothendieck Group of X=G/P."""758return self.Grothendieck_Group()759760761def Lefschetz_Collection ( self , Starting_Block , Twist=None , Support_Pattern='Trivial' ) -> "Lefschetz_Collection" :762"""Returns a Lefschetz collection over ``self``."""763from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Overlying_Structure.Lefschetz_Collection import Lefschetz_Collection764return Lefschetz_Collection( Base_Space=self , Starting_Block=Starting_Block , Twist=Twist , Support_Pattern=Support_Pattern )765766767def Mapping ( self , Image:"Irreducible_Homogeneous_Variety" , Dictionary:dict , Output_Type:str='fw' ) -> dict :768"""769INPUT:770- ``self`` -- Irreducible homoegenous variety (Source)771- ``Image`` -- Irreducible homoegenous variety (Image)772- ``Dictionary`` -- Dictionary (Image); Description of the mapping on the level of simple roots773- ``Output_Type`` -- str 'fw' (default) or 'sr'; Output on the level of fundamental weights (fw) or simple roots (sr)774775OUTPUT:776- ``Output`` -- Dictionary; { Simple roots of Source : Root of Image } or { Fundamental weights of source : weight of Image }777778Caution: The mapping of the simple roots described by the input of ``Dictionary`` is a mapping of the form Torus(Image) --> Torus(Source)779and therefore in the opposite direction as the underlying mapping Source --> Image.780"""781Source = self782sr_Source = Source.Basis('sr')783fw_Source = Source.Basis('fw')784785assert isinstance( Image , Irreducible_Homogeneous_Variety ) , \786'The input for ``Image`` need Image be an irreducible homogeneous variety.'787WeightSpace_Image = Image.Parent_Group().Cartan_Type().root_system().weight_space()788sr_Image = Image.Basis('sr')789fw_Image = Image.Basis('fw')790791assert isinstance( Dictionary , dict ) , \792'The input for ``Dictionary`` need Image be a dictionary.'793794srOutput = dict({})795for Node in sr_Source.keys() :796From = sr_Source[Node]797assert From in Dictionary.keys() , \798'The '+str(Node)+'-th simple root of ```self``` is not a key in ```Dictionary```.'799To = Dictionary[From]800assert To in WeightSpace_Image , \801'The values of the dictionary need to be roots of weight space `'+str(WeightSpace_Image)+'`.'802srOutput.update({ From : To })803804if Output_Type in self.BASIS_LABELLING['sr'] :805return srOutput806elif Output_Type in self.BASIS_LABELLING['fw'] :807808fwOutput = { fw_Source[Node] : sum([ Coefficient*srOutput[sr_Source[i]] for i , Coefficient in enumerate( Row , start=1 ) ])809for Node , Row in enumerate( Source.Parent_Group().Cartan_Type().cartan_matrix().inverse().transpose() , start=1 )810}811return fwOutput812else :813raise ValueError('The input for ``Output_Type`` is inappropriate.')814815816def N ( self ) -> int :817"""Returns the number ``N`` given in the realisation as Grassmannian."""818G = self.Parent_Group()819assert G.Is_Ordinary() , \820ValueError('This method is only implemented for ordinary parent groups.')821Cartan_Family = G.Cartan_Family()822Cartan_Degree = G.Cartan_Degree()823if Cartan_Family == 'A' : return Cartan_Degree + 1 # Grassmannians Gr(k,N) or Flag varieties FL( k1 , k2 , ... ; N )824elif Cartan_Family == 'B' : return 2*Cartan_Degree + 1 # Orthogonal Grassmannians OGr(k,N) or orthogonal Flag varieties OFl( k1 , k2 , ... ; N )825elif Cartan_Family == 'C' : return 2*Cartan_Degree # Symplectic Grassmannians OGr(k,N) or symplectic Flag varieties SFl( k1 , k2 , ... ; N )826elif Cartan_Family == 'D' : return 2*Cartan_Degree # Orthogonal Grassmannians OGr(k,N) or orthogonal Flag varieties OFl( k1 , k2 , ... ; N )827828829def Null_Weight ( self ) -> "Weight" :830"""Returns the null weight of ``self``."""831fw = self.Basis('fw')832return 0*fw[1]833834835def Parent_Group ( self ) -> Irreducible_Cartan_Group :836"""Returns the parent group of ``self``."""837return self.Parabolic_Subgroup().Parent_Group()838839840def Parabolic_Subgroup ( self ) -> Parabolic_Subgroup_In_Irreducible_Cartan_Group :841"""Returns the attribute ``_Parabolic_Subgroup``."""842return self._Parabolic_Subgroup843844845# ..ToDo: Is not correct for Grassmannian!846#def SemiSimplification_Of_G_Bundle ( self ) :847# """Returns the semi-simplification of the tangent bundle on ``self``."""848# sr = self.Basis('sr')849# calTB = self.Zero_Vector_Bundle()850# for Counter1 , Root1 in enumerate( self.Available_Negative_Roots() ) :851# Comparison = [ self.Compare_Roots( Root1 , Root2 ) for Root2 in self.Available_Negative_Roots() ]852# if not ( '>' in Comparison[ : Counter1 ] or '>' in Comparison[ Counter1+1 : ] ) :853# # Write the root as linear combination of weights; as we worked with negative roots, we had the lowest weights and therefore need to mulitply with -1.854# Highest_Weight = -1*sum([ Coefficient * sr[Node] for Node , Coefficient in Root1 ])855# calTB += self.Equivariant_Vector_Bundle( Highest_Weight )856#857# return calTB858859860def Structure_Sheaf ( self , *Twists:tuple[int] ) -> "Irreducible_Equivariant_Vector_Bundle" :861"""Returns the structure sheaf or a twist of it."""862if len(Twists) == 0 : Twists = tuple( len(self.Excluded_Nodes())*[0] )863else :864assert len(Twists) == len(self.Excluded_Nodes()) , \865ValueError('The input for ``Twists`` must be of the length ' + str( len(self.Excluded_Nodes()) ) +'(= number of excluded nodes).')866for Twist_Counter , Twist in enumerate( Twists , start=1 ) :867assert Twist in Integers() , 'The input data of the ' + str(Twist_Counter) + 'th twist is not an integer.'868fw = self.Basis('fw')869return self.Irreducible_Equivariant_Vector_Bundle( sum([ Twists[Counter]*fw[Node] for Counter , Node in enumerate( self.Excluded_Nodes() ) ]) )870871872def Tautological_Subbundle ( self ) -> "Irreducible_Equivariant_Vector_Bundle" :873"""Returns the tautological subbundle, i.e. the dual of the equivariant vector bundle induced by the highest weight omega_1."""874fw = self.Basis('fw')875return self.Irreducible_Equivariant_Vector_Bundle( fw[1] ).Dual()876877878def Trivial_Vector_Bundle ( self ) -> "Direct_Sum_Of_Equivariant_Vector_Bundles" :879"""Returns the trivial vector bundle, i.e. V^{ omega_1 } * calO."""880fw = self.Basis('fw')881return self.calO() * self.Parent_Group().rmV( fw[1] )882883884# Synonym for the method ``Equivariant_Vector_Bundle``885def VB ( self , *Input :tuple ) -> "Direct_Sum_Of_Equivariant_Vector_Bundle" :886"""Returns the equivariant vector bundle induced by the given highest weights."""887return self.Equivariant_Vector_Bundle( *Input )888889890def Weyl_Group_Coset_Representatives_Of_Minimal_Length ( self ) : #-> Iterator[ "Weyl group element" ] :891"""Returns the Weyl group coset representatives of minimal length"""892G = self.Parent_Group()893WG = WeylGroup( G.Cartan_Type() )894sr = WG.simple_reflections()895Identity = sr[1]*(sr[1].inverse())896897Stock = [ [ i+1 for i in w._reduced_word ] for w in WeylGroup( G.Cartan_Type() , implementation='permutation' ).iteration('breadth',True) ]898Stock = [ ( prod([ Identity ] + [ sr[Node] for Node in ReducedDescription ]) , ReducedDescription ) for ReducedDescription in Stock ]899900for WeylElement0 , ReducedDescription0 in Stock :901Length0 = len(ReducedDescription0)902903WeylElement0_Is_CosetRepresentaion_Of_Minimal_Length = True904for Node in self.Parabolic_Subgroup().Included_Nodes(Output_Type=list) :905WeylElement1 = sr[Node]*WeylElement0906907for WeylElement , ReducedDescription in Stock :908if WeylElement1 == WeylElement :909ReducedDescription1 = ReducedDescription910Length1 = len(ReducedDescription1)911break912913if Length1 != Length0+1 :914WeylElement0_Is_CosetRepresentaion_Of_Minimal_Length = False915break916917if WeylElement0_Is_CosetRepresentaion_Of_Minimal_Length :918yield WeylElement0 , ReducedDescription0919920921def Zero_Vector_Bundle ( self ) -> "Direct_Sum_Of_Equivariant_Vector_Bundle" :922"""Returns the zero vector bundle over ``self``."""923return self.Equivariant_Vector_Bundle()924925926927class Direct_Sum_Of_Homogeneous_Varieties ( Direct_Sum_Of_Structures , Homogeneous_Variety ) :928pass929930