Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

n environment to decompose the i-th Hochschild cohomology on some homogeneous varieties X=G/P by Hoschild-Kostant-Rosenberg.

383 views
License: GPL3
ubuntu2204
1
from typing import Iterator
2
3
4
5
class irreducible_Cartan_group ( object ) :
6
7
8
ADMISSIBLE_CARTAN_FAMILIES = { 'A' : ( 1 , +infinity ) ,
9
'B' : ( 2 , +infinity ) ,
10
'C' : ( 2 , +infinity ) ,
11
'D' : ( 3 , +infinity ) ,
12
'E' : ( 6 , 8 ) ,
13
'F' : ( 4 , 4 ) ,
14
'G' : ( 2 , 2 )
15
}
16
17
18
def __eq__ ( self , other ) -> bool :
19
"""Tests if ``self`` coincides with ``other``."""
20
assert isinstance( other , irreducible_Cartan_group ) , \
21
'The input for ``other`` needs to be an irreducible Cartan group.'
22
return self.__repr__() == other.__repr__()
23
24
25
26
def __init__ ( self , Cartan_family:str , Cartan_degree:sage.rings.integer.Integer ) -> None :
27
"""Initialise ``self``."""
28
assert Cartan_family in self.ADMISSIBLE_CARTAN_FAMILIES.keys() , \
29
ValueError('The input for ``Cartan_family`` needs to be a letter from the alphabet '+str(self.ADMISSIBLE_CARTAN_FAMILIES.keys())+'.')
30
self._Cartan_family = Cartan_family
31
32
assert Cartan_degree in ZZ , \
33
ValueError('The input for ``Cartan_degree`` needs to be an integer.')
34
lower_bound , upper_bound = self.ADMISSIBLE_CARTAN_FAMILIES[Cartan_family]
35
assert lower_bound <= Cartan_degree and Cartan_degree <= upper_bound , \
36
ValueError('If the Cartan family is '+str(Cartan_family)+', then the input for ``Cartan_degree`` needs to between '+str(lower_bound)+' and '+str(upper_bound)+'.')
37
self._Cartan_degree = Cartan_degree
38
39
40
def __neq__ ( self , other ) -> bool :
41
"""Tests if ``self`` does NOT coincides with ``other``."""
42
return not self == other
43
44
45
def __repr__ ( self ) -> tuple[ str , sage.rings.integer.Integer ] :
46
"""Returns a developers adjusted description."""
47
return self._Cartan_family , self._Cartan_degree
48
49
50
def __str__ ( self ) -> str :
51
"""Returns a human-readable description."""
52
return self._Cartan_family+'_'+str(self._Cartan_degree)
53
54
55
def __truediv__ ( self , other:'maximal_parabolic_subgroup' ) -> 'minimal_irreducible_homogeneous_variety' :
56
"""Returns the minimal irreducible homogeneous variety X=G/P."""
57
assert isinstance( other , maximal_parabolic_subgroup ) , \
58
'The input for ``other`` needs to be a minimal parabolic subgroup.'
59
60
assert self == other._parent_group , \
61
'The parent group of ``other`` needs to be self.'
62
63
return minimal_irreducible_homogeneous_variety( parabolic_subgroup=other )
64
65
66
def Cartan_string ( self ) -> str :
67
"""Returns the Cartan string ``_Cartan_family``+``_Cartan_degree``."""
68
return self._Cartan_family+str(self._Cartan_degree)
69
70
71
def Cartan_type ( self ) -> 'sage.combinat.root_system.type_A.CartanType' \
72
or 'sage.combinat.root_system.type_B.CartanType' \
73
or 'sage.combinat.root_system.type_D.CartanType' \
74
or 'sage.combinat.root_system.type_E.CartanType' \
75
or 'sage.combinat.root_system.type_E.CartanType' \
76
or 'sage.combinat.root_system.type_F.CartanType' \
77
or 'sage.combinat.root_system.type_G.CartanType' :
78
"""Returns the associated Cartan type."""
79
return CartanType( self.Cartan_string() )
80
81
82
def dimension ( self ) -> sage.rings.integer.Integer :
83
"""
84
Return the dimension of ``self`.
85
86
INPUT:
87
- ``self`` -- minimal_irreducible_homogeneous_variety; base space X=G/P.
88
89
OUTPUT:
90
- ``Output`` -- Integer; the dimension of X=G/P
91
92
ALGORITHM:
93
Thanks to the post by Pieter Belmans concerning the dimension of partial flag varieties
94
from Jun 14th, 2017 on his blog (cf. to [Blog_PieterBelmans]_). The link is
95
https://pbelmans.ncag.info/blog/2017/06/14/dimensions-of-partial-flag-varieties/
96
(Date: Apr 21st, 2021).
97
98
For the Borel group B ⊂ G: dim B = # of positive roots + rank (which accounts for the center)
99
For G: dim G = # of roots in the root system + rank (which accounts for the center)
100
i.e. # of roots in the root system = # of positive roots + # negative roots
101
and # of positive roots = # negative roots
102
so # of roots in the root system = 2 * # of positive roots
103
104
REFERENCE:
105
[Blog_PieterBelmans] https://pbelmans.ncag.info/blog/
106
"""
107
rank = self.Cartan_type().dynkin_diagram().rank()
108
number_of_positive_roots = len( list( self.Cartan_type().root_system().root_lattice().positive_roots() ) )
109
return rank + 2*number_of_positive_roots
110
111
112
def parabolic_subgroup ( self , excluded_node:sage.rings.integer.Integer ) -> 'maximal_parabolic_subgroup' :
113
"""Returns a maximal parabolic subgroup associated to a given excluded node."""
114
return maximal_parabolic_subgroup( parent_group=self , excluded_node=excluded_node )
115
116
117
def Weyl_character_ring( self ) -> 'sage.combinat.root_system.weyl_characters.WeylCharacterRing_with_category' :
118
"""Returns the associated Weyl character ring."""
119
return WeylCharacterRing( self.Cartan_type() , style='coroots' )
120
121
122
def Weyl_group( self ) -> 'sage.combinat.root_system.weyl_group.WeylGroup_gens_with_category' :
123
"""Returns the associated Weyl group."""
124
return WeylGroup( self.Cartan_type() )
125
126
127
128
class maximal_parabolic_subgroup ( object ) :
129
130
131
def __eq__ ( self , other ) -> bool :
132
"""Tests if ``self`` coincides with ``other``."""
133
assert isinstance( other , maximal_parabolic_subgroup ) , \
134
'The input for ``other`` needs to be an irreducible Cartan group.'
135
return self.__repr__() == other.__repr__()
136
137
138
def __init__ ( self , parent_group:irreducible_Cartan_group , excluded_node:sage.rings.integer.Integer ) :
139
"""Initialise ``self``."""
140
assert isinstance( parent_group , irreducible_Cartan_group ) , \
141
ValueError('The input for ``parent_group`` needs to be an irreducible Cartan group.')
142
self._parent_group = parent_group
143
144
assert excluded_node in ZZ , \
145
ValueError('The input for ``excluded_node`` needs to be an integer.')
146
assert excluded_node in [ 1 .. self._parent_group._Cartan_degree ] , \
147
ValueError('The input for ``excluded_node`` needs to be in the range from 1 to '+str(self._Cartan_degree)+'.')
148
self._excluded_node = excluded_node
149
150
151
def __neq__ ( self , other ) -> bool :
152
"""Tests if ``self`` does NOT coincides with ``other``."""
153
return not self == other
154
155
156
def __repr__ ( self ) -> tuple[ irreducible_Cartan_group , sage.rings.integer.Integer ] :
157
"""Returns a developers adjusted description."""
158
return self._parent_group , self._excluded_node
159
160
161
def __str__ ( self ) -> str :
162
"""Returns a human-readable description."""
163
return 'P_'+str(self._excluded_node)
164
165
166
def dimension ( self ) -> sage.rings.integer.Integer :
167
"""
168
Return the dimension of ``self`.
169
170
INPUT:
171
- ``self`` -- minimal_irreducible_homogeneous_variety; base space X=G/P.
172
173
OUTPUT:
174
- ``Output`` -- Integer; the dimension of X=G/P
175
176
ALGORITHM:
177
Thanks to the post by Pieter Belmans concerning the dimension of partial flag varieties
178
from Jun 14th, 2017 on his blog (cf. to [Blog_PieterBelmans]_). The link is
179
https://pbelmans.ncag.info/blog/2017/06/14/dimensions-of-partial-flag-varieties/
180
(Date: Apr 21st, 2021).
181
182
For the Borel group B ⊂ G: dim B = # of positive roots + rank (which accounts for the center)
183
For P: dim P = dim B + # of negative roots which are added to construct P
184
185
REFERENCE:
186
[Blog_PieterBelmans] https://pbelmans.ncag.info/blog/
187
"""
188
rank = self._parent_group.Cartan_type().dynkin_diagram().rank()
189
number_of_positive_roots = len( list( self._parent_group.Cartan_type().root_system().root_lattice().positive_roots() ) )
190
negative_roots = [ negative_root for negative_root in list( self._parent_group.Cartan_type().root_system().root_lattice().negative_roots() )
191
if not False in [ node != self._excluded_node for node , coefficient in negative_root ]
192
]
193
number_of_available_negative_roots = len( negative_roots )
194
return rank + number_of_positive_roots + number_of_available_negative_roots
195
196
197
def included_nodes ( self ) -> list[ sage.rings.integer.Integer ] :
198
"""Returns list of included nodes."""
199
return [ node for node in [ 1 .. self._parent_group._Cartan_degree ] if node != self._excluded_node ]
200
201
202
203
class minimal_irreducible_homogeneous_variety ( object ) :
204
205
def __eq__ ( self , other ) -> bool :
206
"""Tests if ``self`` coincides with ``other``."""
207
assert isinstance( other , minimal_irreducible_homogeneous_variety ) , \
208
'The input for ``other`` needs to be an irreducible Cartan group.'
209
return self.__repr__() == other.__repr__()
210
211
212
def __init__ ( self , parabolic_subgroup:maximal_parabolic_subgroup ) -> None :
213
"""Initialise ``self``."""
214
assert isinstance( parabolic_subgroup , maximal_parabolic_subgroup ) , \
215
ValueError('The input for ``parabolic_subgroup`` needs to be a maximal parabolic subgroup.')
216
self._parabolic_subgroup = parabolic_subgroup
217
218
219
def __neq__ ( self , other ) -> bool :
220
"""Tests if ``self`` does NOT coincides with ``other``."""
221
return not self == other
222
223
224
def __repr__ ( self ) -> maximal_parabolic_subgroup :
225
"""Returns a developers adjusted description."""
226
return self._parabolic_subgroup
227
228
229
def __str__ ( self ) -> str :
230
"""Returns a human-readable description."""
231
return str(self._parabolic_subgroup._parent_group)+'/'+str(self._parabolic_subgroup)
232
233
234
def dimension ( self ) -> sage.rings.integer.Integer :
235
"""
236
Return the dimension of ``self`.
237
238
INPUT:
239
- ``self`` -- minimal_irreducible_homogeneous_variety; base space X=G/P.
240
241
OUTPUT:
242
- ``Output`` -- Integer; the dimension of X=G/P
243
244
ALGORITHM:
245
For X=G/P, dim X = dim G - dim P
246
"""
247
return self._parabolic_subgroup._parent_group.dimension() - self._parabolic_subgroup.dimension()
248
249
250
def Fano_index ( self ) -> sage.rings.integer.Integer :
251
"""
252
Returns the Fano index of ``self``.
253
254
INPUT:
255
- ``self`` -- minimal_irreducible_homogeneous_variety; base space X=G/P.
256
257
OUTPUT:
258
- ``Fano_index`` -- integer; index associated to X = G/P.
259
260
ALGORITHM:
261
Thanks to the post by Pieter Belmans concerning the index of partial flag varieties
262
from Aug 23rd, 2018 on his blog (cf. to [Blog_PieterBelmans]_). The link is
263
https://pbelmans.ncag.info/blog/2018/08/23/index-partial-flag-varieties/
264
(Date: Apr 26th, 2021).
265
266
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
267
such that ω∨_X ≅ O_X(1) ⊗ i.
268
269
To compute it, we use lemma 2.19 and remark 2.20 of [KP2016]. Combined they say the following:
270
Let β be the simple root corresponding to the chosen maximal parabolic subgroup P, and ξ the associated
271
fundamental weight. Let ¯β be the maximal root of the same length as β such that the coefficient of β
272
in the expression of ¯β is 1.
273
Then the index of G/P equals i_G/P = (ρ,β+¯β)/(ξ,β).
274
275
REFERENCE:
276
[Blog_PieterBelmans] https://pbelmans.ncag.info/blog/
277
[KP2016] Kuznetsov, Alexander; Polishchuk, Alexander Exceptional collections on isotropic Grassmannians.
278
J. Eur. Math. Soc. (JEMS) 18 (2016), no. 3, 507–574.
279
"""
280
root_lattice = self._parabolic_subgroup._parent_group.Cartan_type().root_system().root_lattice()
281
ambient_space = self._parabolic_subgroup._parent_group.Cartan_type().root_system().ambient_space()
282
beta = root_lattice.simple_root(self._parabolic_subgroup._excluded_node).to_ambient() # The simple root associated to ``excluded_node``
283
xi = ambient_space.fundamental_weight(self._parabolic_subgroup._excluded_node) # The fundamental weight associated to ``excluded_node``
284
rho = ambient_space.rho() # Sum of fundamental weights
285
length = beta.dot_product(beta)
286
beta_bar = [ alpha for alpha in root_lattice.roots()
287
if alpha.coefficient(self._parabolic_subgroup._excluded_node) == 1 and alpha.to_ambient().dot_product(alpha.to_ambient()) == length
288
][-1].to_ambient()
289
# The maximal root of the same length as ``beta`` such that the coefficient of ``beta`` in the expression of ``beta_bar`` is 1.
290
Fano_index = rho.dot_product(beta + beta_bar) / xi.dot_product(beta)
291
return Fano_index
292
293
294
def Kostant_space ( self , i:sage.rings.integer.Integer , j:sage.rings.integer.Integer , restriction:str or None =None ) -> Iterator[ 'sage.combinat.root_system.weight_space.WeightSpace_with_category.element_class' ] :
295
"""
296
Returns the K(G,P,i,j) as introduced in [BS2023].
297
298
INPUT:
299
- ``self`` -- minimal_irreducible_homogeneous_variety, base space X=G/P.
300
- ``i`` -- integer.
301
- ``j`` -- integer.
302
- ``restriction`` -- string.
303
304
OUTPUT:
305
- ``Weight`` -- sage.combinat.root_system.weight_space.WeightSpace_with_category.element_class; highest weight corresponding to irreducible summand in K(G,P,i,j).
306
307
308
REFERENCE:
309
[BS2023] Belmans, Pieter; Smirnov, Maxim. Hochschild cohomology of generalised Grassmannians.
310
"""
311
# basis
312
fw = dict( self._parabolic_subgroup._parent_group.Cartan_type().root_system().weight_space().fundamental_weights() )
313
rho = sum(list(fw.values())) # sum of fundamental weights
314
ambt = { node : vector( QQ , (node-1)*[ 0 ] + [ 1 ] + (self._parabolic_subgroup._parent_group._Cartan_degree-node)*[ 0 ] )
315
for node in [ 1 .. self._parabolic_subgroup._parent_group._Cartan_degree ]
316
}
317
base_change = matrix( QQ , [ sum([ omega.to_ambient()[node-1]*e for node , e in ambt.items() ])
318
for omega in fw.values()
319
]
320
).transpose().inverse() # Cartan matrix describing base change from ambt to fw
321
# Weyl group
322
WG = self._parabolic_subgroup._parent_group.Weyl_group()
323
sr = WG.simple_reflections()
324
# Weyl character ring
325
WCR = self._parabolic_subgroup._parent_group.Weyl_character_ring()
326
327
# integer invariants
328
dimension = self.dimension() # dimension
329
Fano_index = self.Fano_index() # Fano index
330
331
for Weyl_element , reduced_description in self.Weyl_group_coset_representatives_of_minimal_length() :
332
if len(reduced_description) == dimension-i :
333
# See (1.7): Weight = WeylElement \cdot 0 + ( FanoIndex + j ) * fw[k]
334
result = Weyl_element.action(rho.to_ambient()) - rho.to_ambient() + (Fano_index+j)*fw[self._parabolic_subgroup._excluded_node].to_ambient()
335
vector_with_respect_to_ambt_basis = vector( QQ , [ result.coefficient(node) for node in range(self._parabolic_subgroup._parent_group._Cartan_degree) ] )
336
vector_with_respect_to_fw_basis = base_change*vector_with_respect_to_ambt_basis
337
weight = sum([ coefficient*fw[node] for node , coefficient in enumerate( vector_with_respect_to_fw_basis , start=1 ) ])
338
339
if restriction in [ None , 'None' , 'none' , '' ] :
340
yield weight
341
elif restriction in [ 'Regular' , 'regular' , 'Reg' , 'reg' , 'Non-Singular' , 'non-singular' , 'Non-Sing' , 'non-sing' ] :
342
if self.is_regular( weight+rho ) : yield weight
343
else :
344
raise ValueError('The input for ``restriction`` is anppropriate.')
345
346
347
def is_adjoint ( self ) -> bool :
348
"""Tests if ``self`` is adjoint (cf. grassmannian.info)"""
349
if self._parabolic_subgroup._parent_group._Cartan_family == 'B' : return self._parabolic_subgroup._excluded_node == 2
350
elif self._parabolic_subgroup._parent_group._Cartan_family == 'C' : return self._parabolic_subgroup._excluded_node == 1
351
elif self._parabolic_subgroup._parent_group._Cartan_family == 'D' : return self._parabolic_subgroup._excluded_node == 2 and 4 <= self._parabolic_subgroup._parent_group._Cartan_degree
352
elif self._parabolic_subgroup._parent_group._Cartan_family == 'E' : return ( self._parabolic_subgroup._excluded_node == 2 and self._parabolic_subgroup._parent_group._Cartan_degree == 6 ) or \
353
( self._parabolic_subgroup._excluded_node == 1 and self._parabolic_subgroup._parent_group._Cartan_degree == 7 ) or \
354
( self._parabolic_subgroup._excluded_node == 8 and self._parabolic_subgroup._parent_group._Cartan_degree == 8 )
355
elif self._parabolic_subgroup._parent_group._Cartan_family == 'F' : return self._parabolic_subgroup._excluded_node == 1 and self._parabolic_subgroup._parent_group._Cartan_degree == 4
356
elif self._parabolic_subgroup._parent_group._Cartan_family == 'G' : return self._parabolic_subgroup._excluded_node == 2 and self._parabolic_subgroup._parent_group._Cartan_degree == 2
357
else : return False
358
359
360
def is_exceptional ( self ) -> bool :
361
"""Test if the Cartan family of ``self`` is out of [ E , F , G ]."""
362
return self._parabolic_subgroup._parent_group.ADMISSIBLE_CARTAN_FAMILIES[self._parabolic_subgroup._parent_group._Cartan_family][1] < +infinity
363
364
365
def is_ordinary ( self ) -> bool :
366
"""Test if the Cartan family of ``self`` is out of [ A , B , C , D ]."""
367
return not self.is_exceptional()
368
369
370
def is_regular ( self , weight:'sage.combinat.root_system.weight_space.WeightSpace_with_category.element_class' ) -> bool :
371
"""Tests if a given weight on ``self`` is G-regular (i.e. does not ly on a wall of a Weyl chamber)."""
372
return not self.is_singular( weight )
373
374
375
def is_singular ( self , weight:'sage.combinat.root_system.weight_space.WeightSpace_with_category.element_class' ) -> bool :
376
"""Tests if a given weight on ``self`` is G-singular (i.e. lies on a wall of a Weyl chamber)."""
377
assert weight in self._parabolic_subgroup._parent_group.Cartan_type().root_system().weight_space() , \
378
ValueError('The weight must be an element of the weight space: '+str(self._parabolic_subgroup._parent_group.Cartan_type().root_system().weight_space()))
379
# Move ``Weight`` to dominant chamber
380
weight_in_dominant_chamber = weight.to_dominant_chamber()
381
# Consider list of reflections of ``weight`` and check whether ``weight`` is invariant under some reflection
382
reflections = [ weight_in_dominant_chamber.simple_reflection( index ) for index in self._parabolic_subgroup._parent_group.Cartan_type().index_set() ]
383
return weight_in_dominant_chamber in reflections
384
385
386
def Weyl_group_coset_representatives_of_minimal_length ( self ) -> Iterator[ tuple[ 'sage.combinat.root_system.weyl_group.WeylGroup_gens_with_category.element_class' , list ] ] :
387
"""Returns the Weyl group coset representatives of minimal length"""
388
WG = self._parabolic_subgroup._parent_group.Weyl_group()
389
sr = WG.simple_reflections()
390
identity = sr[1]*(sr[1].inverse())
391
392
stock = [ [ i+1 for i in w._reduced_word ] for w in WeylGroup( self._parabolic_subgroup._parent_group.Cartan_type() , implementation='permutation' ).iteration('breadth',True) ]
393
stock = [ ( prod([ identity ] + [ sr[node] for node in reduced_description ]) , reduced_description ) for reduced_description in stock ]
394
395
for Weyl_element_0 , reduced_description_0 in stock :
396
length_0 = len(reduced_description_0)
397
398
Weyl_element_0_is_coset_representaion_of_minimal_length = True
399
for node in self._parabolic_subgroup.included_nodes() :
400
Weyl_element_1 = sr[node]*Weyl_element_0
401
402
for Weyl_element , reduced_description in stock :
403
if Weyl_element_1 == Weyl_element :
404
reduced_description_1 = reduced_description
405
length_1 = len(reduced_description_1)
406
break
407
408
if length_1 != length_0+1 :
409
Weyl_element_0_is_coset_representaion_of_minimal_length = False
410
break
411
412
if Weyl_element_0_is_coset_representaion_of_minimal_length :
413
yield Weyl_element_0 , reduced_description_0
414
415