Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

Environment to perform calculations of equivariant vector bundles on homogeneous varieties

1842 views
License: GPL3
ubuntu2204
1
2
3
# This file was *autogenerated* from the file Homogeneous_Variety.sage
4
from sage.all_cmdline import * # import sage library
5
6
_sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_2 = Integer(2); _sage_const_4 = Integer(4); _sage_const_6 = Integer(6); _sage_const_7 = Integer(7); _sage_const_8 = Integer(8)
7
from typing import Iterator
8
from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Foundation.Structure import Structure , Irreducible_Structure , Direct_Sum_Of_Structures
9
from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Base_Space.Cartan_Group import Irreducible_Cartan_Group
10
from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Base_Space.Parabolic_Subgroup import Parabolic_Subgroup_In_Irreducible_Cartan_Group
11
12
13
14
class Homogeneous_Variety ( Structure ) :
15
16
BASIS_LABELLING = { 'sr' : [ 'sr' , 'simple roots' , 'alphas' , 'A' ] ,
17
'mx' : [ 'mx' , 'mixed' , 'simple roots for included nodes and fundamental weights for excluded nodes' , 'B' ] ,
18
'fw' : [ 'fw' , 'fundamental weights' , 'omegas' , 'C' ] ,
19
'ambt' : [ 'ambt' , 'ambient' , 'e_i`s' , 'D' ]
20
}
21
22
23
24
class Irreducible_Homogeneous_Variety ( Irreducible_Structure , Homogeneous_Variety ) :
25
26
def __init__( self , Parabolic_Subgroup:Parabolic_Subgroup_In_Irreducible_Cartan_Group ) -> None :
27
"""
28
Initialize a homogeneous variety X=G/P.
29
30
INPUT:
31
- ``Parabolic_Subgroup`` -- Parabolic_Subgroup_In_Irreducible_Cartan_Group ;
32
33
OUTPUT: None.
34
"""
35
assert isinstance( Parabolic_Subgroup , Parabolic_Subgroup_In_Irreducible_Cartan_Group ) , TypeError('The input must be a parabolic subgroup in an irreducible Cartan group.')
36
self._Parabolic_Subgroup = Parabolic_Subgroup
37
38
39
def __repr__ ( self ) -> Parabolic_Subgroup_In_Irreducible_Cartan_Group :
40
"""Returns all attributes which are necessary to initialize the object."""
41
return self.Parent_Group()
42
43
44
def __str__ ( self , Output_Style='Long' ) -> str :
45
"""Returns a one-line string as short description."""
46
if Output_Style == 'Short' : return self.Parent_Group().Cartan_String() + '/P(' + str( self.Included_Nodes() ) + ')'
47
elif Output_Style == 'Long' : return 'Smooth projective variety ' + self.__str__( Output_Style='Short' ) + '.'
48
else : raise ValueError('The input for ``Output_Style`` is inappropriate.')
49
50
51
def Available_Negative_Roots ( self ) -> "Root" :
52
"""Returns all available negative roots."""
53
for Root in self.Parent_Group().Cartan_Type().root_system().root_lattice().negative_roots() :
54
if not Root in self.Parabolic_Subgroup().Negative_Roots() :
55
yield Root
56
57
58
def Available_Positive_Roots ( self ) -> "Root" :
59
"""Returns all available positive roots."""
60
for Root in self.Parent_Group().Cartan_Type().root_system().root_lattice().positive_roots() :
61
if not Root in self.Parabolic_Subgroup().Negative_Roots() :
62
yield Root
63
64
65
def Available_Roots ( self ) -> "Root" :
66
"""Returns all available roots."""
67
for Root in self.Parent_Group().Cartan_Type().root_system().root_lattice().roots() :
68
if not Root in self.Parabolic_Subgroup().Negative_Roots() :
69
yield Root
70
71
72
def Basis ( self , Label:str='mx' ) -> dict :
73
"""
74
Returns the basis in terms of simple roots and fundamental weights.
75
76
INPUT:
77
- ``self`` -- Parabolic_Subgroup; the parabolic subgroup P of a Cartan group G.
78
- ``Label`` -- str (default: 'mx');
79
80
OUTPUT:
81
- ``Output`` -- Dictionary.
82
83
ALGORITHM:
84
- alpha_i : the simple root associated to the i-th node.
85
- omega_i : the fundamental weight associated to the i-th node.
86
87
- sr = { alpha_i }
88
- mx_{ i : i excluded } = { alpha_i : i included } cup { omega_i : i excluded }.
89
Note: mx_{} = sr and mx_{ all i's } = fw
90
- fw = { omega_i }
91
- ambt = { standard basis e_i }
92
"""
93
if Label in self.BASIS_LABELLING['sr'] :
94
return dict( self.Parent_Group().Cartan_Type().root_system().weight_space().simple_roots() )
95
96
elif Label in self.BASIS_LABELLING['mx'] :
97
MixedBasis = {}
98
for Node in self.Parent_Group().Cartan_Type().index_set() :
99
if Node in self.Parabolic_Subgroup().Included_Nodes() : Element = self.Parent_Group().Cartan_Type().root_system().weight_space().simple_root(Node)
100
elif Node in self.Parabolic_Subgroup().Excluded_Nodes() : Element = self.Parent_Group().Cartan_Type().root_system().weight_space().fundamental_weight(Node)
101
else : raise ValueError('Plausibility? The set of nodes subdivides into the disjoint union of marked ones and excluded ones.')
102
MixedBasis.update( { Node : Element } )
103
return MixedBasis
104
105
elif Label in self.BASIS_LABELLING['fw'] :
106
return dict( self.Parent_Group().Cartan_Type().root_system().weight_space().fundamental_weights() )
107
108
elif Label in self.BASIS_LABELLING['ambt'] :
109
n = self.Parent_Group().Cartan_Degree()
110
return { Node : vector( QQ , (Node-_sage_const_1 )*[ _sage_const_0 ] + [ _sage_const_1 ] + (n-Node)*[ _sage_const_0 ] ) for Node in (ellipsis_range( _sage_const_1 ,Ellipsis, n )) }
111
112
else : raise ValueError('The input of ``Label`` is inappropriate.')
113
114
115
# Synonym for the method ``Tautological_Subbundle``
116
def calO ( self , *Twists:tuple[int] ) -> "Irreducible_Equivariant_Vector_Bundle" :
117
"""Returns the structure sheaf or a twist of it."""
118
return self.Structure_Sheaf( *Twists )
119
120
121
# Snynoms for different methods depending on the input
122
def calU ( self , *Input ) -> "Irreducible_Equivaraint_Vector_Bundle" :
123
"""Returns the tautological subbundle (if there no input) or the irreequivariant vector bundle associated to a highest weight (if there is some input otherwise)."""
124
if len(Input) == _sage_const_0 : # Synonym for the method ``Tautological_Subbundle``
125
return self.Tautological_Subbundle()
126
127
else : # Synonym for the method ``Equivariant_Vector_Bundles``
128
return self.Equivariant_Vector_Bundle( *Input )
129
130
131
# Synonym for the method ``Trivial_Vector_Bundle``
132
def calV ( self ) -> "Direct_Sum_Of_Equivariant_Vector_Bundles" :
133
"""Returns the trivial vector bundle ."""
134
return self.Trivial_Vector_Bundle()
135
136
137
def Cartan_Degree ( self ) -> int :
138
"""Returns the Cartan degree of the parent Group G."""
139
return self.Parent_Group().Cartan_Degree()
140
141
142
def Cartan_Family ( self ) -> str :
143
"""Returns the Cartan family of the parent Group G."""
144
return self.Parent_Group().Cartan_Family()
145
146
147
def Cartan_Matrix ( self , From:str='fw' , To:str='mx' ) -> Matrix :
148
"""
149
Returns the base change between the bases sr, mx or fw.
150
151
INPUT:
152
- ``self`` -- Parabolic_Subgroup; the parabolic subgroup P of a Cartan group G.
153
154
OUTPUT:
155
- ``Output`` -- Matrix.
156
157
ALGORITHM:
158
- alpha_i : the simple root associated to the i-th node.
159
- omega_i : the fundamental weight associated to the i-th node.
160
161
- sr >> fw : Cartan matrix
162
- fw >> sr : Inverse of Cartan matrix (sr >> fw)
163
- mx >> fw : For each excluded node i, replace the i-th column by a standard vector e_i.
164
- fw >> mx : Inverse of mx >> fw
165
- sr >> mx : Composition of sr >> fw >> mx
166
- mx >> sr : Inverse of sr >> mx
167
"""
168
if From in self.BASIS_LABELLING['sr'] : From = 'sr'
169
elif From in self.BASIS_LABELLING['mx'] : From = 'mx'
170
elif From in self.BASIS_LABELLING['fw'] : From = 'fw'
171
elif From in self.BASIS_LABELLING['ambt'] : From = 'ambt'
172
else : raise ValueError('The input for ``From`` is inappropriate.')
173
if To in self.BASIS_LABELLING['sr'] : To = 'sr'
174
elif To in self.BASIS_LABELLING['mx'] : To = 'mx'
175
elif To in self.BASIS_LABELLING['fw'] : To = 'fw'
176
elif To in self.BASIS_LABELLING['ambt'] : To = 'ambt'
177
else : raise ValueError('The input for ``To`` is inappropriate.')
178
179
if From == To : return matrix.identity( self.Parent_Group().Cartan_Degree() )
180
181
elif From == 'sr' :
182
if To == 'mx' : return self.Cartan_Matrix( From = 'fw' , To = 'mx') * self.Cartan_Matrix( From = 'sr' , To = 'fw')
183
elif To == 'fw' : return self.Parent_Group().Cartan_Type().cartan_matrix()
184
elif To == 'ambt' :
185
sr = self.Basis('sr')
186
ambt = self.Basis('ambt')
187
return matrix( QQ , [ sum([ alpha.to_ambient()[Node-_sage_const_1 ]*e for Node , e in ambt.items() ]) for Node , alpha in sr.items() ] ).transpose()
188
189
elif From == 'mx' :
190
if To == 'sr' : return self.Cartan_Matrix( From = 'sr' , To = 'mx' ).inverse()
191
elif To == 'fw' :
192
Matrix = copy( self.Cartan_Matrix( From = 'sr' , To = 'fw' ) )
193
for Node in self.Parabolic_Subgroup().Excluded_Nodes() :
194
Matrix[:,Node-_sage_const_1 ] = vector([ kronecker_delta( I , Node ) for I in (ellipsis_range( _sage_const_1 ,Ellipsis, self.Parent_Group().Cartan_Degree() )) ])
195
return Matrix
196
elif To == 'ambt' : return self.Cartan_Matrix( From = 'fw' , To = 'ambt') * self.Cartan_Matrix( From = 'mx' , To = 'fw')
197
198
elif From == 'fw' :
199
if To == 'sr' : return self.Cartan_Matrix( From = 'sr' , To = 'fw' ).inverse()
200
elif To == 'mx' : return self.Cartan_Matrix( From = 'mx' , To = 'fw' ).inverse()
201
elif To == 'ambt' :
202
fw = self.Basis('fw')
203
ambt = self.Basis('ambt')
204
return matrix( QQ , [ sum([ omega.to_ambient()[Node-_sage_const_1 ]*e for Node , e in ambt.items() ]) for Node , omega in fw.items() ] ).transpose()
205
206
elif From == 'ambt' :
207
if To == 'sr' : return self.Cartan_Matrix( From = 'sr' , To = 'ambt' ).inverse()
208
elif To == 'fw' : return self.Cartan_Matrix( From = 'fw' , To = 'ambt' ).inverse()
209
elif To == 'mx' : return self.Cartan_Matrix( From = 'mx' , To = 'ambt' ).inverse()
210
211
212
def Cartan_String ( self ) -> str :
213
"""Returns the Cartan string of the parent Group G."""
214
return self.Parent_Group().Cartan_String()
215
216
217
def Cartan_Type ( self ) -> CartanType :
218
"""Returns the attribute ``Cartan_Type`` of the parent Group G."""
219
return self.Parent_Group().Cartan_Type()
220
221
222
def Compare_Roots ( self , Root1 , Root2 ) -> str or None :
223
"""Returns None if the two roots are not comparable and a result '<', '==', or '>' otherwise."""
224
225
RL = self.Parent_Group().Cartan_Type().root_system().root_lattice()
226
assert Root1 in RL , ValueError('The input for ``Root1`` is not a root.')
227
assert Root2 in RL , ValueError('The input for ``Root2`` is not a root.')
228
229
if Root1 == Root2 :
230
return '=='
231
232
else :
233
Difference_In_srBasis = Root1-Root2
234
if Difference_In_srBasis.is_positive_root() : return '>'
235
elif (-_sage_const_1 *Difference_In_srBasis).is_positive_root() : return '<'
236
else : return None
237
238
239
def Compare_Weights ( self , Weight1 , Weight2 ) -> str or None :
240
"""Returns None if the two weights are not comparable and a result '<', '==', or '>' otherwise."""
241
242
WS = self.Parent_Group().Cartan_Type().root_system().weight_space()
243
assert Weight1 in WS , ValueError('The input for ``Weight1`` is not a weight.')
244
assert Weight2 in WS , ValueError('The input for ``Weight2`` is not a weight.')
245
246
if Weight1 == Weight2 :
247
return '=='
248
249
else :
250
RL = self.Parent_Group().Cartan_Type().root_system().root_space()
251
scr = RL.simple_coroots()
252
sr = RL.simple_roots()
253
Coefficients_For_fwBasis = [ (Weight1-Weight2).scalar(coroot) for coroot in scr ]
254
Coefficients_For_srBasis = vector( QQ , Coefficients_For_fwBasis ) * self.Cartan_Matrix( From='fw' , To='sr' )
255
Difference_In_srBasis = sum([ QQ(Coefficient)*sr[Node] for Node , Coefficient in enumerate( list( Coefficients_For_srBasis ) , start = _sage_const_1 ) ])
256
257
if Difference_In_srBasis.is_positive_root() : return '>'
258
elif (-_sage_const_1 *Difference_In_srBasis).is_positive_root() : return '<'
259
else : return None
260
261
262
def Complex ( self , Objects ) -> "Complex_Over_Irreducible_Homogeneous_Variety" :
263
"""Returns a complex of equivariant vector bundles over ``self``."""
264
from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Overlying_Structure.Complex_Of_Equivariant_Vector_Bundles import Complex_Of_Coherent_Sheaves
265
return Complex_Of_Coherent_Sheaves( Base_Space=self , Objects=Objects )
266
267
268
# ..ToDo: For PP^n, it is only correct up to sign.
269
def Complex_Defining_Exterior_Power_Of_Tautological_Quotient_Bundle ( self , p :int =_sage_const_1 ) -> "Complex_Over_Irreducible_Homogeneous_Variety" :
270
"""Returns the complex defining the p-th exterior power of the tautological quotient bundle on ``self``."""
271
assert isinstance( p , Integer ) , 'The input for `p` need to be an integer.'
272
273
G = self.Parent_Group()
274
fw = self.Basis('fw')
275
Terms = dict({})
276
for i in (ellipsis_range( _sage_const_0 ,Ellipsis, p+_sage_const_1 )) :
277
if i == _sage_const_0 : Terms.update({ _sage_const_0 : 'Cokernel' })
278
else : Terms.update({ -_sage_const_1 *i : self.Tautological_Subbundle().Symmetric_Power( i-_sage_const_1 ).Multiply_By( G.rmV( fw[_sage_const_1 ] ).exterior_power( p-i+_sage_const_1 ) ) })
279
return self.Complex( Terms )
280
281
282
def Dimension ( self ) -> int :
283
"""Returns the dimension dim X = dim G - dim P."""
284
return self.Parent_Group().Dimension() - self.Parabolic_Subgroup().Dimension()
285
286
287
def Equivariant_Vector_Bundle ( self , *Inputs:tuple ) -> "Equivariant_Vector_Bundles" :
288
"""Returns the direct sum of equivariant vector bundles induced by the given highest weights."""
289
Constituent_Parts = list(Inputs)
290
from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Overlying_Structure.Equivariant_Vector_Bundle import Equivariant_Vector_Bundle
291
return Equivariant_Vector_Bundle.Constructor( Base_Space=self , Constituent_Parts=Constituent_Parts )
292
293
294
def Excluded_Nodes ( self ) -> set :
295
"""Returns the attribute ``Excluded_Nodes`` of the parabolic subgroup P."""
296
return self.Parabolic_Subgroup().Excluded_Nodes()
297
298
299
def Expected_Support_Partition_For_Minimal_Full_Lefschetz_Collection ( self ) -> tuple[ int ] :
300
"""Returns the expected support partition for a minimal Lefschetz collection on ``self``."""
301
assert self.Parabolic_Subgroup().Is_Maximal() , ValueError('The method is only implemented for those homogeneous varieties where the parabolic subgroup is maximal.')
302
303
Collection__Expected_Length = self.K0().rank()
304
Node , Fano_Index = next(self.Fano_Index())
305
306
Rectangular_Part__Expected_Height = Fano_Index
307
Rectangular_Part__Expected_Width = floor( Collection__Expected_Length / Rectangular_Part__Expected_Height )
308
Residual_Part__Expected_Height = Collection__Expected_Length - Rectangular_Part__Expected_Height * Rectangular_Part__Expected_Width
309
if Residual_Part__Expected_Height == _sage_const_0 : Residual_Part__Expected_Width = _sage_const_0
310
else : Residual_Part__Expected_Width = _sage_const_1
311
312
return tuple( Residual_Part__Expected_Height * [ Rectangular_Part__Expected_Width+_sage_const_1 ] + (Rectangular_Part__Expected_Height-Residual_Part__Expected_Height) * [ Rectangular_Part__Expected_Width ] )
313
314
315
def Fano_Index ( self ) -> Iterator[ tuple[ int , int ] ]:
316
"""
317
Returns the Fano index of ``self``.
318
319
INPUT:
320
- ``self`` -- Parabolic_Subgroup; the parabolic subgroup P of a Cartan group G.
321
322
OUTPUT:
323
- ``Node`` -- Excluded node
324
- ``Fano_Index`` -- Index associated to X = G/P(Excluded_Nodes={Node})
325
326
ALGORITHM:
327
Thanks to the post by Pieter Belmans concerning the index of partial flag varieties
328
from Aug 23rd, 2018 on his blog (cf. to [Blog_PieterBelmans]_). The link is
329
https://pbelmans.ncag.info/blog/2018/08/23/index-partial-flag-varieties/
330
(Date: Apr 26th, 2021).
331
332
The 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 i
333
such that ω∨_X ≅ O_X(1) ⊗ i.
334
335
To compute it, we use lemma 2.19 and remark 2.20 of [KP2016]. Combined they say the following:
336
Let β be the simple root corresponding to the chosen maximal parabolic subgroup P, and ξ the associated
337
fundamental weight. Let ¯β be the maximal root of the same length as β such that the coefficient of β
338
in the expression of ¯β is 1.
339
Then the index of G/P equals i_G/P = (ρ,β+¯β)/(ξ,β).
340
341
REFERENCE:
342
[Blog_PieterBelmans] https://pbelmans.ncag.info/blog/
343
[KP2016] Kuznetsov, Alexander; Polishchuk, Alexander Exceptional collections on isotropic Grassmannians.
344
J. Eur. Math. Soc. (JEMS) 18 (2016), no. 3, 507–574.
345
"""
346
Root_Lattice = self.Parent_Group().Cartan_Type().root_system().root_lattice()
347
Ambient_Space = self.Parent_Group().Cartan_Type().root_system().ambient_space()
348
349
for Node in self.Parabolic_Subgroup().Excluded_Nodes() :
350
Beta = Root_Lattice.simple_root(Node).to_ambient() # The simple root associated to ``Node``
351
Xi = Ambient_Space.fundamental_weight(Node) # The fundamental weight associated to ``Node``
352
Rho = Ambient_Space.rho() # Sum of fundamental weights
353
Length = Beta.dot_product(Beta)
354
Beta_Bar = [Alpha for Alpha in Root_Lattice.roots() if Alpha.coefficient(Node) == _sage_const_1 and Alpha.to_ambient().dot_product(Alpha.to_ambient()) == Length][-_sage_const_1 ].to_ambient()
355
# The maximal root of the same length as ``Beta`` such that the coefficient of ``Beta`` in the expression of ``Beta_Bar`` is 1.
356
Fano_Index = Rho.dot_product(Beta + Beta_Bar) / Xi.dot_product(Beta)
357
yield Node , Fano_Index
358
359
360
def Grothendieck_Group ( self ) -> FreeModule :
361
"""
362
Returns the Grothendieck Group of X=G/P.
363
364
INPUT:
365
- ``self`` -- Homogeneous Variety.
366
367
OUTPUT:
368
- ``Output`` -- Integer; The rank of the Grothendieck group of X=G/P.
369
370
ALGORITHM:
371
Thanks to the post by Pieter Belmans concerning the index of partial flag varieties
372
from Aug 22nd, 2018 on his blog (cf. to [Blog_PieterBelmans]_). The link is
373
https://pbelmans.ncag.info/blog/2018/08/22/rank-flag-varieties/
374
(Date: Apr 26th, 2021).
375
376
It can be computed as the rank of the homology of X=G/P using the Bruhat cell decomposition,
377
and is equal to #WG/#WL, where WG (resp. WL) denotes the Weyl group of G (resp. L).
378
L is the Levi subgroup inside the maximal parabolic P.
379
380
.. TODO:
381
- Check if the rank of the Grothendieck group is always be given by the Euler characteristic.
382
- Fix Rank_Of_GrothendieckGroup for Borel subgroups.
383
384
REFERENCE:
385
[Blog_PieterBelmans] https://pbelmans.ncag.info/blog/
386
[KP2016] Kuznetsov, Alexander; Polishchuk, Alexander Exceptional collections on isotropic Grassmannians.
387
J. Eur. Math. Soc. (JEMS) 18 (2016), no. 3, 507–574.
388
"""
389
Cartan_Type_of_Parent_Group = self.Parent_Group().Cartan_Type()
390
Weyl_Group_of_Parent_Group = Cartan_Type_of_Parent_Group.root_system().root_lattice().weyl_group()
391
392
if self.Parabolic_Subgroup().Is_Borel() :
393
# Question: Because WeylGroup_of_Levi_Part.cardinality() == 1?
394
return Integers()**( Weyl_Group_of_Parent_Group.cardinality() )
395
396
else :
397
Cartan_Type_of_Levi_Part = self.Parent_Group().Cartan_Type().dynkin_diagram().subtype( self.Parabolic_Subgroup().Included_Nodes() )
398
Weyl_Group_of_Levi_Part = Cartan_Type_of_Levi_Part.root_system().root_lattice().weyl_group()
399
return Integers()**( Weyl_Group_of_Parent_Group.cardinality() / Weyl_Group_of_Levi_Part.cardinality() )
400
401
402
def Kostant_Space ( self , i:int , j:int , Restriction:str or None =None ) -> Iterator[ "Weight" ] :
403
"""
404
Returns the K(G,P,i,j) as introduced in [BS2023].
405
406
INPUT:
407
- ``self`` -- Homogeneous variety.
408
- ``i`` -- integer.
409
- ``j`` -- integer.
410
411
OUTPUT:
412
- ``Weight`` -- highest weight corresponding to irreducible summand in K(G,P,i,j).
413
414
415
REFERENCE:
416
[BS2023] Belmans, Pieter; Smirnov, Maxim. Hochschild cohomology of generalised Grassmannians.
417
"""
418
G = self.Parent_Group()
419
P = self.Parabolic_Subgroup()
420
assert P.Is_Maximal() , 'The homogeneous variety ``self`` needs to be minimal; or equivalently, its associaed parabolic subgroup needs to be maximal.'
421
k = self.k()
422
423
# Weyl Group
424
WG = WeylGroup( G.Cartan_Type() )
425
sr = WG.simple_reflections()
426
fw = self.Basis('fw')
427
# Weyl Character Ring
428
WCR = G.Weyl_Character_Ring()
429
# Sum of fundamental weights
430
Rho = sum(list(fw.values()))
431
# Fano index
432
Fano_Indices = { Node : Value for ( Node , Value ) in (G/P).Fano_Index() }
433
assert len(Fano_Indices.keys()) == _sage_const_1 and k in Fano_Indices.keys() , 'For minimal homogeneous variety, the Fano index needs to be a unique value associated to the excluded node k='+str(k)+'.'
434
FanoIndex = Fano_Indices[k]
435
# Dimension
436
Dimension = self.Dimension()
437
438
CM = self.Cartan_Matrix( From='ambt' , To='fw' )
439
440
for WeylElement , ReducedDescription in self.Weyl_Group_Coset_Representatives_Of_Minimal_Length() :
441
if len(ReducedDescription) == Dimension-i :
442
# See (1.7): Weight = WeylElement \cdot 0 + ( FanoIndex + j ) * fw[k]
443
Result = WeylElement.action(Rho.to_ambient()) - Rho.to_ambient() + (FanoIndex+j)*fw[k].to_ambient()
444
ambt_Description = vector( QQ , [ Result.coefficient(i) for i in range(G.Cartan_Degree()) ] )
445
fw_Description = CM*ambt_Description
446
Weight = sum([ Coefficient*fw[Node] for Node , Coefficient in enumerate( fw_Description , start=_sage_const_1 ) ])
447
448
if Restriction in [ None , 'None' , 'none' , '' ] :
449
yield Weight
450
elif Restriction in [ 'Regular' , 'regular' , 'Reg' , 'reg' , 'Non-Singular' , 'non-singular' , 'Non-Sing' , 'non-sing' ] :
451
if self.Is_Regular( Weight+Rho ) : yield Weight
452
else :
453
raise ValueError('The input for ``Restriction`` is anppropriate.')
454
455
456
def Kuznetsov_Polishchuk_Collection ( self ) -> Iterator[ tuple[ int , int , int , "weight" , str ] ] :
457
"""
458
Returns the collection of Kuznetsov and Polishchuk on X=G/P.
459
460
INPUT:
461
- ``self`` -- Homogeneous variety.
462
463
OUTPUT:
464
- ``TotalCounter`` -- Counter running over all objects of the collection.
465
- ``BlockCounter`` -- Counter running over all objects of the current block.
466
- ``t`` -- Integer; block index.
467
- ``Lambda`` -- highest weight of object.
468
- ``cE`` -- string description of cE(Lambda).
469
470
.. TODO:
471
- Implement collection for exceptional cases.
472
473
REFERENCE:
474
[KP2016] Kuznetsov, Alexander; Polishchuk, Alexander Exceptional collections on isotropic Grassmannians.
475
J. Eur. Math. Soc. (JEMS) 18 (2016), no. 3, 507–574.
476
"""
477
478
G = self.Parent_Group()
479
assert G.Is_Irreducible() , 'The parent group of ``self`` need to be irreducible.'
480
Cartan_Family = G.Cartan_Family()
481
n = self.Cartan_Degree()
482
483
P = self.Parabolic_Subgroup()
484
assert P.Is_Maximal() , 'The parabolic subgroup of ``self`` need to be maximal.'
485
k = self.k()
486
487
Blocks = dict({})
488
# Conjecture 9.8. on page 49
489
if Cartan_Family in [ 'A' ] :
490
l = n+_sage_const_1 -k
491
# 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 }
492
Slope = l/k
493
Q = []
494
for xRunner1 in (ellipsis_range( _sage_const_0 ,Ellipsis, k )) :
495
yRunner1 = Slope*xRunner1
496
Q += [ ( xRunner1 , yRunner1 ) ]
497
if xRunner1 < k: # Notice: 0 < Slope = (n+1)/k - 1 if and only if k < n+1
498
for yRunner2 in (ellipsis_range( ceil(yRunner1) ,Ellipsis, floor(yRunner1+Slope) )) :
499
xRunner2 = _sage_const_1 /Slope*yRunner2
500
if yRunner1 < yRunner2 and yRunner2 < yRunner1+Slope : Q += [ ( xRunner2 , yRunner2 ) ]
501
for t , (x,y) in enumerate(Q) :
502
a = floor(x)
503
b = floor(y)
504
c = k - ceil(x)
505
d = l - ceil(y)
506
Block = []
507
for p1 in IntegerListsLex( length=a , min_part=t , max_part=d+t , max_slope=_sage_const_0 ) :
508
p1 = list(p1)
509
p2 = [ t for Node in (ellipsis_range( a+_sage_const_1 ,Ellipsis, k )) ]
510
p3 = [ _sage_const_0 for Node in (ellipsis_range( k+_sage_const_1 ,Ellipsis, n+_sage_const_1 -b )) ]
511
for p4 in IntegerListsLex( length=b , min_part=_sage_const_0 , max_part=c , max_slope=_sage_const_0 ) :
512
p4 = [ Entry-c for Entry in p4 ]
513
Highest_Weight = p1+p2+p3+p4
514
Block += [ Highest_Weight ]
515
Block.reverse()
516
Blocks.update({ t : Block })
517
518
elif Cartan_Family in [ 'B' , 'D' ] :
519
# Equation 56 on page 39
520
if Cartan_Family == 'B' : e = _sage_const_1 /_sage_const_2
521
elif Cartan_Family == 'D' : e = _sage_const_0
522
523
# k <= n-1 if Cartan family is B or k <= n-2 if Cartan family is D
524
# Theorem 9.1. on page 42
525
if k in (ellipsis_range( _sage_const_1 ,Ellipsis, n+_sage_const_2 *e-_sage_const_2 )) :
526
for t in (ellipsis_range( _sage_const_0 ,Ellipsis, k-_sage_const_1 )) :
527
Block = []
528
for p1 in IntegerListsLex ( length=t , min_part=t , max_part=_sage_const_2 *n+_sage_const_2 *e-k-_sage_const_2 , max_slope=_sage_const_0 ) :
529
p1 = list(p1)
530
p2 = [ t for Node in (ellipsis_range( t+_sage_const_1 ,Ellipsis, k )) ]
531
for p3 in IntegerListsLex ( length=n-k , min_part=(_sage_const_2 *e-_sage_const_1 )*t , max_part=floor((k-t)/_sage_const_2 ) , max_slope=_sage_const_0 ) :
532
p3 = list(p3)
533
Highest_Weight = p1+p2+p3
534
if Highest_Weight[n-_sage_const_1 ] >= (_sage_const_2 *e-_sage_const_1 )*Highest_Weight[n-_sage_const_2 ] : Block += [ Highest_Weight ]
535
Block.reverse()
536
Blocks.update({ t : Block })
537
Block = []
538
for p1 in IntegerListsLex ( length=t , min_part=t , max_part=_sage_const_2 *n+_sage_const_2 *e-k-_sage_const_2 , max_slope=_sage_const_0 ) :
539
p1 = [ Entry+_sage_const_1 /_sage_const_2 for Entry in p1 ]
540
p2 = [ t+_sage_const_1 /_sage_const_2 for Node in (ellipsis_range( t+_sage_const_1 ,Ellipsis, k )) ]
541
for p3 in IntegerListsLex ( length=n-k , min_part=ceil((_sage_const_2 *e-_sage_const_1 )*t-_sage_const_1 /_sage_const_2 ) , max_part=floor((k-t)/_sage_const_2 -_sage_const_1 /_sage_const_2 ) , max_slope=_sage_const_0 ) :
542
p3 = [ Entry+_sage_const_1 /_sage_const_2 for Entry in p3 ]
543
Highest_Weight = p1+p2+p3
544
if Highest_Weight[n-_sage_const_1 ] >= (_sage_const_2 *e-_sage_const_1 )*Highest_Weight[n-_sage_const_2 ] : Block += [ Highest_Weight ]
545
Block.reverse()
546
Blocks.update({ t+_sage_const_1 /_sage_const_2 : Block })
547
for t in (ellipsis_range( k ,Ellipsis, _sage_const_2 *n+_sage_const_2 *e-k-_sage_const_2 )) :
548
Block = []
549
for p1 in IntegerListsLex ( length=k-_sage_const_1 , min_part=t , max_part=_sage_const_2 *n+_sage_const_2 *e-k-_sage_const_2 , max_slope=_sage_const_0 ) :
550
p1 = list(p1)
551
p2 = [ t ]
552
p3 = [ _sage_const_0 for Node in (ellipsis_range( k+_sage_const_1 ,Ellipsis, n )) ]
553
Highest_Weight = p1+p2+p3
554
Block += [ Highest_Weight ]
555
Block.reverse()
556
Blocks.update({ t : Block })
557
558
# k == n if Cartan family is B or k from { n-1 , n } if Cartan family is D
559
# Theorem 9.3. on page 43
560
elif k in (ellipsis_range( n+_sage_const_2 *e-_sage_const_1 ,Ellipsis, n )) :
561
# D_n/P_n-1 and D_n/P_n are both isomorphic to B_n-1/P_n-1
562
if Cartan_Family == 'D' :
563
Cartan_Family = 'B'
564
n = n-_sage_const_1
565
k = n
566
for t in (ellipsis_range( _sage_const_0 ,Ellipsis, n-_sage_const_1 )) :
567
Block = []
568
for p1 in IntegerListsLex ( length=t , min_part=t , max_part=n-_sage_const_1 , max_slope=_sage_const_0 ) :
569
p1 = list(p1)
570
p2 = [ t for Node in (ellipsis_range( t+_sage_const_1 ,Ellipsis, n )) ]
571
Highest_Weight = p1+p2
572
Block += [ Highest_Weight ]
573
Block.reverse()
574
Blocks.update({ _sage_const_2 *t : Block })
575
Blocks.update({ _sage_const_2 *t+_sage_const_1 : [ [ Entry+_sage_const_1 /_sage_const_2 for Entry in Highest_Weight ] for Highest_Weight in Blocks[_sage_const_2 *t] ] })
576
577
# Theorem 9.2. on page 42
578
elif Cartan_Family == 'C' :
579
for t in (ellipsis_range( _sage_const_0 ,Ellipsis, k-_sage_const_1 )) :
580
Block = []
581
for p1 in IntegerListsLex ( length=t , min_part=t , max_part=_sage_const_2 *n-k , max_slope=_sage_const_0 ) :
582
p1 = list(p1)
583
p2 = [ t for Node in (ellipsis_range( t+_sage_const_1 ,Ellipsis, k )) ]
584
for p3 in IntegerListsLex ( length=n-k , min_part=_sage_const_0 , max_part=floor((k-t)/_sage_const_2 ) , max_slope=_sage_const_0 ) :
585
p3 = list(p3)
586
Highest_Weight = p1+p2+p3
587
Block += [ Highest_Weight ]
588
Block.reverse()
589
Blocks.update({ t : Block })
590
for t in (ellipsis_range( k ,Ellipsis, _sage_const_2 *n-k )) :
591
Highest_Weights = []
592
for p1 in IntegerListsLex ( length=k-_sage_const_1 , min_part=t , max_part=_sage_const_2 *n-k , max_slope=_sage_const_0 ) :
593
p1 = list(p1)
594
p2 = [t]
595
p3 = [ _sage_const_0 for Node in (ellipsis_range( k+_sage_const_1 ,Ellipsis, n )) ]
596
Highest_Weight = p1+p2+p3
597
Block += [ Highest_Weight ]
598
Block.reverse()
599
Blocks.update({ t : Block })
600
601
else :
602
raise ValueError('The algorithm is not implement for the exceptional cases E_6, E_7, E_8, F_4, or G_2.')
603
604
fw = self.Basis('fw')
605
CM = self.Cartan_Matrix( From='ambt' , To='fw' )
606
if Cartan_Family == 'A' :
607
CM = block_matrix( QQ , [ [ CM , matrix( QQ , (n-_sage_const_1 )*[ [_sage_const_0 ] ] + [ [-_sage_const_1 ] ] ) ] ] , subdivide=False )
608
TotalCounter = _sage_const_0
609
for t , Block in Blocks.items() :
610
Previous_Objects = []
611
for BlockCounter , Highest_Weight_in_ambtBasis in enumerate( Block , start=_sage_const_1 ) :
612
TotalCounter += _sage_const_1
613
Highest_Weight_in_fwBasis = CM*vector( QQ , Highest_Weight_in_ambtBasis )
614
Highest_Weight = sum([ Coefficient*fw[Node] for Node , Coefficient in enumerate( Highest_Weight_in_fwBasis , start=_sage_const_1 ) ])
615
cU = str(self.calU(Highest_Weight))
616
if Cartan_Family in [ 'A' ] :
617
cE = cU
618
elif Cartan_Family in [ 'B' , 'C' , 'D' ] :
619
if len(Previous_Objects) == _sage_const_0 : cE = cU
620
else : cE = 'Right mutation of '+cU+' through <'+', '.join(Previous_Objects)+'>'
621
yield TotalCounter , BlockCounter , t , Highest_Weight , cE
622
Previous_Objects += [ cU ]
623
624
625
def Included_Nodes ( self ) -> set :
626
"""Returns the attribute ``Included_Nodes`` of the parabolic subgroup P."""
627
return self.Parabolic_Subgroup().Included_Nodes()
628
629
630
def Irreducible_Equivariant_Vector_Bundle ( self , Highest_Weight:"Weight" ) -> "Irreducible_Equivariant_Vector_Bundle" :
631
"""Returns the equivariant vector bundle induced by the given highest weight."""
632
if Highest_Weight == _sage_const_0 :
633
fw = self.Basis('fw')
634
Highest_Weight = _sage_const_0 * fw[_sage_const_1 ]
635
from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Overlying_Structure.Equivariant_Vector_Bundle import Irreducible_Equivariant_Vector_Bundle
636
return Irreducible_Equivariant_Vector_Bundle( Base_Space=self , Highest_Weight=Highest_Weight )
637
638
639
# ..ToDo : Improve the testing. Get a cleaner algorithm based immediately on the definition.
640
def Is_Adjoint ( self ) -> bool :
641
"""Tests if ``self`` is adjoint (cf. grassmannian.info)"""
642
G = self.Parent_Group()
643
Cartan_Family = G.Cartan_Family()
644
Cartan_Degree = G.Cartan_Degree()
645
P = self.Parabolic_Subgroup()
646
assert P.Is_Maximal() , ValueError('This method is only implemented for maximal parabolic subgroups.')
647
k = self.k()
648
if Cartan_Family == 'B' : return k == _sage_const_2
649
elif Cartan_Family == 'C' : return k == _sage_const_1
650
elif Cartan_Family == 'D' : return k == _sage_const_2 and _sage_const_4 <= Cartan_Degree
651
elif Cartan_Family == 'E' : return ( Cartan_Degree == _sage_const_6 and k == _sage_const_2 ) or ( Cartan_Degree == _sage_const_7 and k == _sage_const_1 ) or ( Cartan_Degree == _sage_const_8 and k == _sage_const_8 )
652
elif Cartan_Family == 'F' : return ( Cartan_Degree == _sage_const_4 and k == _sage_const_1 )
653
elif Cartan_Family == 'G' : return ( Cartan_Degree == _sage_const_2 and k == _sage_const_2 )
654
else : return False
655
656
657
# ..ToDo : Improve the testing. Get a cleaner algorithm based immediately on the definition.
658
def Is_Coadjoint ( self ) -> bool :
659
"""Tests if ``self`` is coadjoint (cf. grassmannian.info)"""
660
G = self.Parent_Group()
661
Cartan_Family = G.Cartan_Family()
662
Cartan_Degree = G.Cartan_Degree()
663
P = self.Parabolic_Subgroup()
664
assert P.Is_Maximal() , ValueError('This method is only implemented for maximal parabolic subgroups.')
665
k = self.k()
666
if Cartan_Family == 'B' : return k == _sage_const_1
667
elif Cartan_Family == 'C' : return k == _sage_const_2
668
elif Cartan_Family == 'D' : return k == _sage_const_2 and _sage_const_4 <= Cartan_Degree
669
elif Cartan_Family == 'E' : return ( Cartan_Degree == _sage_const_6 and k == _sage_const_2 ) or ( Cartan_Degree == _sage_const_7 and k == _sage_const_1 ) or ( Cartan_Degree == _sage_const_8 and k == _sage_const_8 )
670
elif Cartan_Family == 'F' : return ( Cartan_Degree == _sage_const_4 and k == _sage_const_4 )
671
elif Cartan_Family == 'G' : return ( Cartan_Degree == _sage_const_2 and k == _sage_const_1 )
672
else : return False
673
674
675
# ..ToDo : Improve the testing. Get a cleaner algorithm based immediately on the definition.
676
def Is_Cominuscule ( self ) -> bool :
677
"""Tests if ``self`` is cominuscule (cf. grassmannian.info)"""
678
G = self.Parent_Group()
679
Cartan_Family = G.Cartan_Family()
680
Cartan_Degree = G.Cartan_Degree()
681
P = self.Parabolic_Subgroup()
682
assert P.Is_Maximal() , ValueError('This function is only implemented for maximal parabolic subgroups.')
683
k = self.k()
684
if Cartan_Family == 'A' : return True
685
elif Cartan_Family == 'B' : return k == _sage_const_1
686
elif Cartan_Family == 'C' : return k == Cartan_Degree
687
elif Cartan_Family == 'D' : return k in [ _sage_const_1 , CartenDegree-_sage_const_1 , Cartan_Degree ]
688
elif Cartan_Family == 'E' : return ( Cartan_Degree == _sage_const_6 and k in [ _sage_const_1 , _sage_const_6 ] ) or ( Cartan_Degree == _sage_const_7 and k == _sage_const_7 )
689
else : return False
690
691
692
# ..ToDo : Specify the type for the input ``Weight``!
693
def Is_Levi_Dominant ( self , Weight ) -> bool :
694
"""Tests if a given weight on ``self`` is Levi-dominant (i.e. all coefficients over included nodes are non-negative)."""
695
assert Weight in self.Parent_Group().Cartan_Type().root_system().weight_space() , ValueError('The weight must be an element of the weight space: '+str(self.Parent_Group().Cartan_Type().root_system().weight_space()))
696
for Node in self.Parabolic_Subgroup().Included_Nodes() :
697
if Weight.coefficient(Node) < _sage_const_0 : return False
698
return True
699
700
701
# ..ToDo : Improve the testing. Get a cleaner algorithm based immediately on the definition.
702
def Is_Minuscule ( self ) -> bool :
703
"""Tests if ``self`` is minuscule (cf. grassmannian.info)"""
704
G = self.Parent_Group()
705
Cartan_Family = G.Cartan_Family()
706
Cartan_Degree = G.Cartan_Degree()
707
P = self.Parabolic_Subgroup()
708
assert P.Is_Maximal() , ValueError('This function is only implemented for maximal parabolic subgroups.')
709
k = self.k()
710
if Cartan_Family == 'A' : return True
711
elif Cartan_Family == 'B' : return k == Cartan_Degree
712
elif Cartan_Family == 'C' : return k == _sage_const_1
713
elif Cartan_Family == 'D' : return k in [ _sage_const_1 , CartenDegree-_sage_const_1 , Cartan_Degree ]
714
elif Cartan_Family == 'E' : return ( Cartan_Degree == _sage_const_6 and k in [ _sage_const_1 , _sage_const_6 ] ) or ( Cartan_Degree == _sage_const_7 and k == _sage_const_7 )
715
else : return False
716
717
718
def Is_Regular ( self , Weight:"Weight" ) -> bool :
719
"""Tests if a given weight on ``self`` is G-regular (i.e. does not ly on a wall of a Weyl chamber)."""
720
assert Weight in self.Parent_Group().Cartan_Type().root_system().weight_space() , ValueError('The weight must be an element of the weight space: '+str(self.Parent_Group().Cartan_Type().root_system().weight_space()))
721
return not self.Is_Singular( Weight )
722
723
724
def Is_Singular ( self , Weight:"Weight" ) -> bool :
725
"""Tests if a given weight on ``self`` is G-singular (i.e. lies on a wall of a Weyl chamber)."""
726
assert Weight in self.Parent_Group().Cartan_Type().root_system().weight_space() , ValueError('The weight must be an element of the weight space: '+str(self.Parent_Group().Cartan_Type().root_system().weight_space()))
727
# Move ``Weight`` to dominant chamber
728
Weight_In_Dominant_Chamber = Weight.to_dominant_chamber()
729
# Consider list of reflections of ``Weight`` and check whether ``Weight`` is invariant under some reflection
730
Reflections = [ Weight_In_Dominant_Chamber.simple_reflection( Index ) for Index in self.Parent_Group().Cartan_Type().index_set() ]
731
return Weight_In_Dominant_Chamber in Reflections
732
733
734
def k ( self ) -> int :
735
"""Returns the number ``k`` given in the realisation as Grassmannian."""
736
P = self.Parabolic_Subgroup()
737
Excluded_Nodes = P.Excluded_Nodes(Output_Type=list)
738
if P.Is_Maximal() : return Excluded_Nodes[_sage_const_0 ]
739
else : return Excluded_Nodes
740
741
742
# Synonym for the method ``Grothendieck_Group``
743
def K0 ( self ) -> FreeModule :
744
"""Returns the Grothendieck Group of X=G/P."""
745
return self.Grothendieck_Group()
746
747
748
def Lefschetz_Collection ( self , Starting_Block , Twist=None , Support_Pattern='Trivial' ) -> "Lefschetz_Collection" :
749
"""Returns a Lefschetz collection over ``self``."""
750
from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Overlying_Structure.Lefschetz_Collection import Lefschetz_Collection
751
return Lefschetz_Collection( Base_Space=self , Starting_Block=Starting_Block , Twist=Twist , Support_Pattern=Support_Pattern )
752
753
754
def Mapping ( self , Image:"Irreducible_Homogeneous_Variety" , Dictionary:dict , Output_Type:str='fw' ) -> dict :
755
"""
756
INPUT:
757
- ``self`` -- Irreducible homoegenous variety (Source)
758
- ``Image`` -- Irreducible homoegenous variety (Image)
759
- ``Dictionary`` -- Dictionary (Image); Description of the mapping on the level of simple roots
760
- ``Output_Type`` -- str 'fw' (default) or 'sr'; Output on the level of fundamental weights (fw) or simple roots (sr)
761
762
OUTPUT:
763
- ``Output`` -- Dictionary; { Simple roots of Source : Root of Image } or { Fundamental weights of source : weight of Image }
764
765
Caution: The mapping of the simple roots described by the input of ``Dictionary`` is a mapping of the form Torus(Image) --> Torus(Source)
766
and therefore in the opposite direction as the underlying mapping Source --> Image.
767
"""
768
Source = self
769
sr_Source = Source.Basis('sr')
770
fw_Source = Source.Basis('fw')
771
772
assert isinstance( Image , Irreducible_Homogeneous_Variety ) , 'The input for ``Image`` need Image be an irreducible homogeneous variety.'
773
WeightSpace_Image = Image.Parent_Group().Cartan_Type().root_system().weight_space()
774
sr_Image = Image.Basis('sr')
775
fw_Image = Image.Basis('fw')
776
777
assert isinstance( Dictionary , dict ) , 'The input for ``Dictionary`` need Image be a dictionary.'
778
779
srOutput = dict({})
780
for Node in sr_Source.keys() :
781
From = sr_Source[Node]
782
assert From in Dictionary.keys() , 'The '+str(Node)+'-th simple root of ```self``` is not a key in ```Dictionary```.'
783
To = Dictionary[From]
784
assert To in WeightSpace_Image , 'The values of the dictionary need to be roots of weight space `'+str(WeightSpace_Image)+'`.'
785
srOutput.update({ From : To })
786
787
if Output_Type in self.BASIS_LABELLING['sr'] :
788
return srOutput
789
elif Output_Type in self.BASIS_LABELLING['fw'] :
790
791
fwOutput = { fw_Source[Node] : sum([ Coefficient*srOutput[sr_Source[i]] for i , Coefficient in enumerate( Row , start=_sage_const_1 ) ])
792
for Node , Row in enumerate( Source.Parent_Group().Cartan_Type().cartan_matrix().inverse().transpose() , start=_sage_const_1 )
793
}
794
return fwOutput
795
else :
796
raise ValueError('The input for ``Output_Type`` is inappropriate.')
797
798
799
def N ( self ) -> int :
800
"""Returns the number ``N`` given in the realisation as Grassmannian."""
801
G = self.Parent_Group()
802
assert G.Is_Ordinary() , ValueError('This method is only implemented for ordinary parent groups.')
803
Cartan_Family = G.Cartan_Family()
804
Cartan_Degree = G.Cartan_Degree()
805
if Cartan_Family == 'A' : return Cartan_Degree + _sage_const_1 # Grassmannians Gr(k,N) or Flag varieties FL( k1 , k2 , ... ; N )
806
elif Cartan_Family == 'B' : return _sage_const_2 *Cartan_Degree + _sage_const_1 # Orthogonal Grassmannians OGr(k,N) or orthogonal Flag varieties OFl( k1 , k2 , ... ; N )
807
elif Cartan_Family == 'C' : return _sage_const_2 *Cartan_Degree # Symplectic Grassmannians OGr(k,N) or symplectic Flag varieties SFl( k1 , k2 , ... ; N )
808
elif Cartan_Family == 'D' : return _sage_const_2 *Cartan_Degree # Orthogonal Grassmannians OGr(k,N) or orthogonal Flag varieties OFl( k1 , k2 , ... ; N )
809
810
811
def Null_Weight ( self ) -> "Weight" :
812
"""Returns the null weight of ``self``."""
813
fw = self.Basis('fw')
814
return _sage_const_0 *fw[_sage_const_1 ]
815
816
817
def Parent_Group ( self ) -> Irreducible_Cartan_Group :
818
"""Returns the parent group of ``self``."""
819
return self.Parabolic_Subgroup().Parent_Group()
820
821
822
def Parabolic_Subgroup ( self ) -> Parabolic_Subgroup_In_Irreducible_Cartan_Group :
823
"""Returns the attribute ``_Parabolic_Subgroup``."""
824
return self._Parabolic_Subgroup
825
826
827
# ..ToDo: Is not correct for Grassmannian!
828
#def SemiSimplification_Of_G_Bundle ( self ) :
829
# """Returns the semi-simplification of the tangent bundle on ``self``."""
830
# sr = self.Basis('sr')
831
# calTB = self.Zero_Vector_Bundle()
832
# for Counter1 , Root1 in enumerate( self.Available_Negative_Roots() ) :
833
# Comparison = [ self.Compare_Roots( Root1 , Root2 ) for Root2 in self.Available_Negative_Roots() ]
834
# if not ( '>' in Comparison[ : Counter1 ] or '>' in Comparison[ Counter1+1 : ] ) :
835
# # 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.
836
# Highest_Weight = -1*sum([ Coefficient * sr[Node] for Node , Coefficient in Root1 ])
837
# calTB += self.Equivariant_Vector_Bundle( Highest_Weight )
838
#
839
# return calTB
840
841
842
def Structure_Sheaf ( self , *Twists:tuple[int] ) -> "Irreducible_Equivariant_Vector_Bundle" :
843
"""Returns the structure sheaf or a twist of it."""
844
if len(Twists) == _sage_const_0 : Twists = tuple( len(self.Excluded_Nodes())*[_sage_const_0 ] )
845
else :
846
assert len(Twists) == len(self.Excluded_Nodes()) , ValueError('The input for ``Twists`` must be of the length ' + str( len(self.Excluded_Nodes()) ) +'(= number of excluded nodes).')
847
for Twist_Counter , Twist in enumerate( Twists , start=_sage_const_1 ) :
848
assert Twist in Integers() , 'The input data of the ' + str(Twist_Counter) + 'th twist is not an integer.'
849
fw = self.Basis('fw')
850
return self.Irreducible_Equivariant_Vector_Bundle( sum([ Twists[Counter]*fw[Node] for Counter , Node in enumerate( self.Excluded_Nodes() ) ]) )
851
852
853
def Tautological_Subbundle ( self ) -> "Irreducible_Equivariant_Vector_Bundle" :
854
"""Returns the tautological subbundle, i.e. the dual of the equivariant vector bundle induced by the highest weight omega_1."""
855
fw = self.Basis('fw')
856
return self.Irreducible_Equivariant_Vector_Bundle( fw[_sage_const_1 ] ).Dual()
857
858
859
def Trivial_Vector_Bundle ( self ) -> "Direct_Sum_Of_Equivariant_Vector_Bundles" :
860
"""Returns the trivial vector bundle, i.e. V^{ omega_1 } * calO."""
861
fw = self.Basis('fw')
862
return self.calO() * self.Parent_Group().rmV( fw[_sage_const_1 ] )
863
864
865
# Synonym for the method ``Equivariant_Vector_Bundle``
866
def VB ( self , *Input :tuple ) -> "Direct_Sum_Of_Equivariant_Vector_Bundle" :
867
"""Returns the equivariant vector bundle induced by the given highest weights."""
868
return self.Equivariant_Vector_Bundle( *Input )
869
870
871
def Weyl_Group_Coset_Representatives_Of_Minimal_Length ( self ) : #-> Iterator[ "Weyl group element" ] :
872
"""Returns the Weyl group coset representatives of minimal length"""
873
G = self.Parent_Group()
874
WG = WeylGroup( G.Cartan_Type() )
875
sr = WG.simple_reflections()
876
Identity = sr[_sage_const_1 ]*(sr[_sage_const_1 ].inverse())
877
878
Stock = [ [ i+_sage_const_1 for i in w._reduced_word ] for w in WeylGroup( G.Cartan_Type() , implementation='permutation' ).iteration('breadth',True) ]
879
Stock = [ ( prod([ Identity ] + [ sr[Node] for Node in ReducedDescription ]) , ReducedDescription ) for ReducedDescription in Stock ]
880
881
for WeylElement0 , ReducedDescription0 in Stock :
882
Length0 = len(ReducedDescription0)
883
884
WeylElement0_Is_CosetRepresentaion_Of_Minimal_Length = True
885
for Node in self.Parabolic_Subgroup().Included_Nodes(Output_Type=list) :
886
WeylElement1 = sr[Node]*WeylElement0
887
888
for WeylElement , ReducedDescription in Stock :
889
if WeylElement1 == WeylElement :
890
ReducedDescription1 = ReducedDescription
891
Length1 = len(ReducedDescription1)
892
break
893
894
if Length1 != Length0+_sage_const_1 :
895
WeylElement0_Is_CosetRepresentaion_Of_Minimal_Length = False
896
break
897
898
if WeylElement0_Is_CosetRepresentaion_Of_Minimal_Length :
899
yield WeylElement0 , ReducedDescription0
900
901
902
def Zero_Vector_Bundle ( self ) -> "Direct_Sum_Of_Equivariant_Vector_Bundle" :
903
"""Returns the zero vector bundle over ``self``."""
904
return self.Equivariant_Vector_Bundle()
905
906
907
908
class Direct_Sum_Of_Homogeneous_Varieties ( Direct_Sum_Of_Structures , Homogeneous_Variety ) :
909
pass
910
911
912