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