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
3
from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Base_Space.Homogeneous_Variety import Irreducible_Homogeneous_Variety
4
from Equivariant_Vector_Bundles_On_Homogeneous_Varieties.Overlying_Structure.Equivariant_Vector_Bundle import Equivariant_Vector_Bundle , \
5
Irreducible_Equivariant_Vector_Bundle , \
6
Direct_Sum_Of_Equivariant_Vector_Bundles , \
7
Extension_Of_Equivariant_Vector_Bundles
8
9
10
11
class Lefschetz_Collection ( Structure ) :
12
13
SUPPORT_PATTERN_LABELLING = { True : [ True , 1 , 'x' , 'X' ] ,
14
False : [ False , 0 , 'o' , 'O' ]
15
}
16
17
18
def __add__ ( self , other:"Lefschetz_Collection" ) -> "Lefschetz_Collection" :
19
"""Returns the concatenation of ``self`` with ``other``."""
20
assert isinstance( other , self.__class__ ) , \
21
TypeError('The input for ``other`` must be a Lefschetz collection.')
22
assert self.Base_Space() == other.Base_Space() , \
23
ValueError('The base spaces of ``self`` and ``other`` need to coincide.')
24
assert self.Twist() == other.Twist() , \
25
ValueError('The twists of ``self`` and ``other`` need to coincide.')
26
27
New_Starting_Block = self.Starting_Block()+other.Starting_Block()
28
29
New_Support_Pattern = dict({})
30
Row_IDs = list(self.Support_Pattern().keys())+list(other.Support_Pattern().keys())
31
if 0 < len(Row_IDs) :
32
for Row_ID in [ min(Row_IDs) .. max(Row_IDs) ] :
33
Row = []
34
if Row_ID in self.Support_Pattern().keys() : Row += self.Support_Pattern()[Row_ID]
35
else : Row += self.Width() * [ False ]
36
if Row_ID in other.Support_Pattern().keys() : Row += other.Support_Pattern()[Row_ID]
37
else : Row += other.Width() * [ False ]
38
New_Support_Pattern.update({ Row_ID : Row })
39
40
return self.__class__( Base_Space=self.Base_Space() , Starting_Block=New_Starting_Block , Twist=self.Twist() , Support_Pattern=New_Support_Pattern )
41
42
43
def __call__ ( self , *Twists:tuple[int] ) -> "Lefschetz_Collection" :
44
"""Returns a Lefschetz collection with twisted starting block."""
45
return self.__class__( Base_Space=self.Base_Space() , Starting_Block=[ Object(*Twists) for Object in self.Starting_Block() ] , Twist=self.Twist() , Support_Pattern=self.Support_Pattern() )
46
47
48
def __getitem__ ( self , Input:int or slice
49
) -> Irreducible_Equivariant_Vector_Bundle or Direct_Sum_Of_Equivariant_Vector_Bundles or Extension_Of_Equivariant_Vector_Bundles or \
50
list[ Irreducible_Equivariant_Vector_Bundle or Direct_Sum_Of_Equivariant_Vector_Bundles or Extension_Of_Equivariant_Vector_Bundles ] :
51
"""Returns a single datum or slices of data."""
52
if Input in ZZ :
53
Index = Input
54
if Index <= -len(self)-1 : return None
55
elif Index in [ -len(self) .. -1 ] : Index += len(self)
56
elif Index in [ 0 .. len(self)-1 ] : pass
57
else : return None
58
for Counter , Object in enumerate( self ) :
59
if Counter == Index : return Object
60
61
elif type(Input) == slice :
62
Slice = Input
63
Indices = range(len(self))[Slice]
64
List = []
65
for Counter , Object in enumerate( self ) :
66
if Counter in Indices : List += [ Object ]
67
return List
68
69
else :
70
raise ValueError('The variable ``Input`` is inappropriate.')
71
72
73
def __init__ ( self , \
74
Base_Space:Irreducible_Homogeneous_Variety , \
75
Starting_Block:list[ Equivariant_Vector_Bundle ] , \
76
Twist:Irreducible_Equivariant_Vector_Bundle or None=None , \
77
Support_Pattern:list or str or None='Trivial'
78
) -> None :
79
"""
80
Initialize a Lefschetz collection over an irreducible homogeneous variety.
81
82
INPUT:
83
- ``Base_Space`` -- Irreducible Homogeneous Variety;
84
- ``Starting_Block`` -- List;
85
- ``Twist`` -- Vector bundle over an irreducible homogeneous variety;
86
- ``Support_Pattern`` -- Tuple;
87
88
OUTPUT: None.
89
"""
90
# Base space
91
assert isinstance( Base_Space , Irreducible_Homogeneous_Variety ) , \
92
TypeError('The input for ``base space`` must be an irreducible homogeneous variety.')
93
self._Base_Space = Base_Space
94
95
# Starting block
96
if isinstance( Starting_Block , tuple ) : Starting_Block = list(Starting_Block)
97
self._Starting_Block = []
98
if isinstance( Starting_Block , list ) :
99
for Object_Counter , Object in enumerate( Starting_Block , start=1 ) :
100
assert isinstance( Object , ( Irreducible_Equivariant_Vector_Bundle , Direct_Sum_Of_Equivariant_Vector_Bundles , Extension_Of_Equivariant_Vector_Bundles ) ) , \
101
'The '+str(Object_Counter)+'-th object need to be an equivariant vector bundle.'
102
assert self._Base_Space == Object.Base_Space() , \
103
ValueError('The base space of the '+str(Object_Counter)+'-th object does not coincide with the given base space.')
104
self._Starting_Block += [ Object ]
105
else : raise ValueError( 'The input for ``Starting_Block`` is inappropriate.' )
106
107
# Twist
108
if Twist == None :
109
if self._Base_Space.Parabolic_Subgroup().Is_Maximal() : Twist = self._Base_Space.calO(1)
110
else : raise ValueError( 'For a non-maximal paralic subgroup, one need to clearify the twist explicitly.' )
111
assert isinstance( Twist , Irreducible_Equivariant_Vector_Bundle ) , \
112
TypeError('The input for ``Twist`` must be a vector bundle over an irreducible homogeneous variety.')
113
assert Twist.Is_Line_Bundle() , \
114
ValueError('The input for ``Twist`` need to be a line bundle.')
115
self._Twist = Twist
116
117
# Support pattern
118
if Support_Pattern in [ 'Trivial' , None ] :
119
self._Support_Pattern = { 0 : len(self._Starting_Block) * [ True ] }
120
121
elif Support_Pattern in [ 'Maximal' , 'Max' , 'Maximal Length' , infinity ] :
122
raise ValueError('The method constructing the maximal support pattern is yet not implemented.')
123
124
elif isinstance( Support_Pattern , ( tuple , list ) ) :
125
Support_Pattern = list(Support_Pattern)
126
Cases = []
127
for Entry_Counter , Entry in enumerate( Support_Pattern , start=1 ) :
128
129
if Entry in ZZ :
130
if not 0 <= Entry :
131
raise ValueError('If the '+str(Entry_Counter)+'-th entry of the input ``Support_Pattern`` is an integer, ' \
132
+ 'then it must be non-negative.')
133
if not Entry <= len(self._Starting_Block) :
134
raise ValueError('If the '+str(Entry_Counter)+'-th entry of the input ``Support_Pattern`` is an integer, ' \
135
+ 'then it must be bounded by the length of the starting block; namely <= '+str(len(self._Starting_Block))+'.'
136
)
137
Label = 'Support partition'
138
elif instance( Entry , [ tuple , list ] ) :
139
Entry = list(Entry)
140
141
for Subentry_Counter , Subentry in enumerate( Entry ) :
142
if not ( Subentry in self.SUPPORT_PATTERN_LABELLING[True] or Subentry in self.SUPPORT_PATTERN_LABELLING[False] ) :
143
raise ValueError('If the '+str(Entry_Counter)+'-th entry of the input ``Support_Pattern`` is a tuple or a list, ' \
144
+ 'then it must contain labellings '+str(self.SUPPORT_PATTERN_LABELLING[True])+' or '+str(self.SUPPORT_PATTERN_LABELLING[False])+'.'
145
)
146
if not len(Entry) <= len(self._Starting_Block) :
147
raise ValueError('If the '+str(Entry_Counter)+'-th entry of the input ``Support_Pattern`` is an row with labellings, ' \
148
+ 'then its length must be bounded by the length of the starting block; namely <= '+str(len(self._Starting_Block))+'.'
149
)
150
Label = 'Grid'
151
152
if not Label in Cases : Cases += [ Label ]
153
154
if len( Cases ) == 0 : Case = 'Empty support pattern'
155
elif len( Cases ) == 1 : Case = Cases[0]
156
else : raise ValueError( 'The entries of the input ``Support_Pattern`` are inappropriate.' )
157
158
if Case == 'Empty support pattern' :
159
self._Support_Pattern = dict({})
160
elif Case == 'Support partition' :
161
self._Support_Pattern = { Row_Counter : Row_Width*[ True ] + (len(self._Starting_Block)-Row_Width)*[ False ]
162
for Row_Counter , Row_Width in enumerate( Support_Pattern )
163
}
164
elif Case == 'Grid' :
165
self._Support_Pattern = { Row_Counter : [ Entry in self.SUPPORT_PATTERN_LABELLING[True] for Entry in Row ] + (len(self._Starting_Block)-len(Row))*[ False ]
166
for Row_Counter , Row in enumerate( Support_Pattern )
167
}
168
169
elif isinstance( Support_Pattern , dict ) :
170
self._Support_Pattern = dict({})
171
for Row_ID , Row in Support_Pattern.items() :
172
if not Row_ID in ZZ :
173
raise ValueError('If the input ``Support_Pattern`` is an dictionary, then the keys must be integers.')
174
if not type( Row ) in [ list ] :
175
raise ValueError('If the input ``Support_Pattern`` is an dictionary, then the values must be lists.')
176
if not len(Row) <= len(self._Starting_Block) :
177
raise ValueError('If the input ``Support_Pattern`` is an dictionary, ' \
178
+'then the length of the rows must be bounded by the length of the starting block, namely <= '+str(len(self._Starting_Block))+'.')
179
for Entry_Counter , Entry in enumerate( Row , start=1 ) :
180
if ( not Entry in self.SUPPORT_PATTERN_LABELLING[True] ) and ( not Entry in self.SUPPORT_PATTERN_LABELLING[False] ) :
181
raise ValueError('If the input ``Support_Pattern`` is an dictionary, then the '+str(Entry_Counter)+'-th entry in the row '+str(Row_ID) \
182
+ 'must be a labelling of the form '+str(self.SUPPORT_PATTERN_LABELLING[True])+' or '+str(self.SUPPORT_PATTERN_LABELLING[False])+'.'
183
)
184
for Row_ID , Row in Support_Pattern.items() :
185
Adjusted_Row = [ Entry in self.SUPPORT_PATTERN_LABELLING[True] for Entry in Row ] + (len(self._Starting_Block)-len(Row))*[ False ]
186
if True in Adjusted_Row : self._Support_Pattern.update({ Row_ID : Adjusted_Row })
187
188
if 0 < len( self._Support_Pattern.keys() ) :
189
for Row_ID in [ min(self._Support_Pattern.keys()) .. max(self._Support_Pattern.keys()) ] :
190
if not Row_ID in self._Support_Pattern.keys() :
191
self._Support_Pattern.update({ Row_ID : len(self._Starting_Block)*[ False ] })
192
193
Sorted_Row_IDs = sorted( self._Support_Pattern.keys() )
194
self._Support_Pattern = { Row_ID : self._Support_Pattern[Row_ID] for Row_ID in Sorted_Row_IDs }
195
196
else :
197
raise TypeError( 'The input for ``Support_Pattern`` is inappropriate.' )
198
199
# Gram matrix
200
self._Gram_Matrix = dict({})
201
202
203
def __iter__ ( self ) -> Iterator[ Equivariant_Vector_Bundle ] :
204
"""Returns a generator for the objects of ``self``."""
205
for yPos , Row in self.Support_Pattern().items() :
206
for xPos , Object_Is_Accessible in enumerate( Row ) :
207
if Object_Is_Accessible :
208
yield self.Starting_Block(xPos) * self.Twist()^yPos
209
210
211
def __len__ ( self ) -> int :
212
"""Returns the number of objects of ``self``."""
213
return sum([ sum([ 1 for Object_Is_Accessible in Row if Object_Is_Accessible ]) for Row in self.Support_Pattern().values() ])
214
215
216
def __lshift__ ( self , Shift:int=1 ) -> "Lefschetz_Collection" :
217
"""Returns the left shift of ``self``."""
218
return self >> -Shift
219
220
221
def __repr__ ( self ) :
222
"""Returns all attributes which are necessary to initialize the object."""
223
return self.Base_Space() , self.Starting_Block() , self.Twist() , self.Support_Pattern()
224
225
226
def __rshift__ ( self , Shift:int=1 ) -> "Lefschetz_Collection" :
227
"""Returns a sheft of ``self``."""
228
assert Shift in ZZ , \
229
TypeError('The input for ``Shift`` need to be an integer.')
230
New_Support_Pattern = { Row_ID+Shift : Row for Row_ID , Row in self.Support_Pattern().items() }
231
return self.__class__( Base_Space=self.Base_Space() , Starting_Block=self.Starting_Block() , Twist=self.Twist() , Support_Pattern=New_Support_Pattern )(-Shift)
232
233
234
def __str__ ( self ) -> str :
235
"""Returns a one-line string as short description."""
236
return 'Lefschetz collection consisting of '+str(len(self))+' objects in a grid with width = '+str(self.Width())+' and height = '+str(self.Height())
237
238
239
def Base_Space ( self ) -> Irreducible_Homogeneous_Variety :
240
"""Returns the attribute ``_Base_Space``."""
241
return self._Base_Space
242
243
244
# Synonym for the method ``Row`` :
245
def Block ( self , Input:int ) -> Iterator[ Equivariant_Vector_Bundle ] :
246
"""Returns a single block (= row)."""
247
self.Row( Input )
248
249
250
def Column ( self , Input:int ) -> Iterator[ Equivariant_Vector_Bundle ] :
251
"""Returns a single column."""
252
Width = self.Width()
253
if Input in ZZ :
254
if Input <= -Width-1 :
255
Start_Iteration = False
256
elif Input in [ -Width .. -1 ] :
257
Start_Iteration = True
258
xPos = Input + Width
259
elif Input in [ 0 .. Width-1 ] :
260
Start_Iteration = True
261
xPos = Input
262
elif Width <= Input :
263
Start_Iteration = False
264
265
if Start_Iteration :
266
for yPos , Row in self.Support_Pattern().items() :
267
Object_Is_Accessible = Row[xPos]
268
if Object_Is_Accessible : yield self.Starting_Block(xPos)(yPos)
269
270
else :
271
raise TypeError('The input data must be an integer in the range '+str( [ -Width .. Width-1 ] )+'.')
272
273
274
def Gram_Matrix ( self , Base_Ring:'Ring'=ZZ , Compute_Now:bool=False ) -> Matrix :
275
"""
276
Returns a Gram matrix associated to the computations of EXT( E_p , E_q ) (p: row , q: column).
277
For the entry in the p-th row and q-th column, it is the dim Euler_Sum( E_p , E_q ) = dim ( sum_i (-1)^i EXT^i( E_p , E_q ) ).
278
"""
279
if Compute_Now == True :
280
WCR = self.Base_Space().Parent_Group().Weyl_Character_Ring()
281
if Base_Ring == ZZ : self._Gram_Matrix.update({ ZZ : Matrix( ZZ , [ [ E1.Euler_Sum(E2).degree() for E2 in self ] for E1 in self ] ) })
282
elif Base_Ring == WCR : self._Gram_Matrix.update({ WCR : [ [ E1.Euler_Sum(E2) for E2 in self ] for E1 in self ] })
283
else : raise ValueError("The input for `Base_Ring` is inappropriate.")
284
285
return self._Gram_Matrix[Base_Ring]
286
287
else :
288
if Base_Ring in self._Gram_Matrix.keys() : return self._Gram_Matrix[Base_Ring]
289
else : return self.Gram_Matrix( Base_Ring=Base_Ring , Compute_Now=True )
290
291
292
def Grid ( self , Labelling:list or None=None ) -> list[ list[ str ] ] :
293
"""Returns a grid of the objects of ``self``."""
294
if Labelling == None : Labelling = [ 'E'+str(xPos) for xPos in range(self.Width()) ]
295
assert type(Labelling) == list , TypeError('The input for ``Labelling`` must be a list.')
296
assert len(Labelling) == self.Width() , ValueError('The ``Labelling`` must be of length '+str(len(self.Width()))+'.')
297
for Label_Counter , Label in enumerate( Labelling , start=1 ) :
298
assert type(Label) == str , TypeError('The '+str(Label_Counter)+'-th label must be a string.')
299
300
Table = []
301
for yPos , self_Row in self.Support_Pattern().items() :
302
Table_Row = []
303
for xPos , Object_Is_Accessible in enumerate( self_Row ) :
304
if Object_Is_Accessible :
305
Label = Labelling[xPos]
306
if not yPos == 0: Twist = '('+str(yPos)+')'
307
else : Twist = ''
308
Table_Row_Entry = Label+Twist
309
else : Table_Row_Entry = ''
310
Table_Row += [ Table_Row_Entry ]
311
Table += [ Table_Row ]
312
313
if 0 < len(self) : return table( Table )
314
315
316
def Has_Maximal_Expected_Length ( self ) -> bool :
317
"""Tests if ``self`` is maximal; i.e. len(self) == rk K_0(X)."""
318
return len(self) == self.Base_Space().Grothendieck_Group().rank()
319
320
321
def Height ( self ) -> int :
322
"""Returns the height of ``self``."""
323
return len(self.Support_Pattern().keys())
324
325
326
def Is_Exceptional ( self , Test_Numerically:bool=False ) -> bool :
327
"""
328
Tests if the Lefschetz collection is (numerically) exceptional.
329
330
INPUT:
331
- ``self`` -- LefschetzCollection.
332
333
OUTPUT:
334
- Boolean; return True if ``self`` is exceptional, otherwise False as soon as possible.
335
336
ALGORITHM:
337
Compare to Lemma 2.2. in [Kuz2006]_
338
339
REFERENCE:
340
- [Kuz2006] Alexander Kuznetsov: Exceptional collections for Grassmannians of isotropic lines; 2006.
341
"""
342
assert type(Test_Numerically) == bool , \
343
TypeError('The input for ``Test_Numerically`` need to be boolean.')
344
345
# Test if the accessible objects are exceptional.
346
# Let E be from the starting block.
347
# If E is accessible in the same row (i.e. E(y) is object of ``self`` for some y), then test if E is exceptional.
348
# NOTE: EXT( E(y) , E(y) ) = EXT( E , E )
349
for xPos in range(self.Width()) :
350
# Test if the object is accessible in some row.
351
Object_Is_Accessible_In_Same_Row = False
352
for Row in self.Support_Pattern().values() :
353
if Row[xPos] == True : Object_Is_Accessible_In_Same_Row = True ; break
354
# If the object is accessible in some row, then test if it is exceptional.
355
if Object_Is_Accessible_In_Same_Row :
356
Obj = self.Starting_Block(xPos)
357
if not Obj.Is_Exceptional(Test_Numerically) : return False
358
359
# Test for accessible objects of the same row, if latter ones are semi-orthogonal to previous ones.
360
# Let E_1 , E_2 be from the starting block and E_1 is positioned before E_2.
361
# If E_1 and E_2 are simultaneously accessible in the same row (i.e. E_1(y) and E_2(y) are both objects of ``self`` for some y), then test if E_2 is semi-orthogonal to E_1.
362
# NOTE: EXT( E_2(y) , E_1(y) ) = EXT( E_2 , E_1 )
363
for xPos1 in range(self.Width()) :
364
for xPos2 in range(self.Width())[ xPos1+1 : ] :
365
# Test if there is a row where both objects are simultaneously accessible.
366
Both_Objects_Are_Simultaneously_Accessible_In_The_Same_Row = False
367
for Row in self.Support_Pattern().values() :
368
if Row[xPos1] == True and Row[xPos2] == True : Both_Objects_Are_Simultaneously_Accessible_In_The_Same_Row = True ; break
369
# If both objects are simultaneously accessible in the same row, then check semi-orthogonality.
370
if Both_Objects_Are_Simultaneously_Accessible_In_The_Same_Row :
371
Obj1 = self.Starting_Block(xPos1)
372
Obj2 = self.Starting_Block(xPos2)
373
for Obj2_Is_SemiOrthogonal_To_Obj1 in Obj2.Is_SemiOrthogonal_To( Obj1 , Test_Numerically ) :
374
if not Obj2_Is_SemiOrthogonal_To_Obj1 : return False
375
376
# Test for accessible objects of the same row, if latter ones are semi-orthogonal to previous ones.
377
# Let E_1 , E_2 be from the starting block.
378
# If E_1 and E_2 are simultaneously accessible with respect to the row-difference yDelta (i.e. E_1(y_1) and E_2(y_2) are both objects of ``self``
379
# for some y_1 and y_2 with yDela = y_2-y_1), then test if E_2(yDelta) is semi-orthogonal to E_1.
380
# NOTE: EXT( E_2(y_2) , E_1(y_1) ) = EXT( E_2(yDelta) , E_1 )
381
for xPos1 in range(self.Width()) :
382
for xPos2 in range(self.Width()) :
383
for yDelta in range(self.Height())[ 1 : ] :
384
# Test if there are two rows with yDelta difference where both objects are simultaneously accessible.
385
Both_Objects_Are_Simultaneously_Accessible_In_Rows_With_Difference_yDelta = False
386
for Row1_ID in self.Support_Pattern().keys() :
387
Row2_ID = Row1_ID + yDelta
388
if not Row2_ID in self.Support_Pattern().keys() : break
389
Row1 = self.Support_Pattern()[Row1_ID]
390
Row2 = self.Support_Pattern()[Row2_ID]
391
if Row1[xPos1] == True and Row2[xPos2] == True : Both_Objects_Are_Simultaneously_Accessible_In_Rows_With_Difference_yDelta = True ; break
392
393
# If both objects are simultaneously accessible with respect to yDelta, then check semi-orthogonality.
394
if Both_Objects_Are_Simultaneously_Accessible_In_Rows_With_Difference_yDelta :
395
Obj1 = self.Starting_Block(xPos1)
396
Obj2 = self.Starting_Block(xPos2) * self.Twist()^yDelta
397
for Obj2_Is_SemiOrthogonal_To_Obj1 in Obj2.Is_SemiOrthogonal_To( Obj1 , Test_Numerically ) :
398
if not Obj2_Is_SemiOrthogonal_To_Obj1 : return False
399
400
if 0 < len(self) : return True
401
402
403
def Is_Numerically_Exceptional ( self ) -> bool :
404
"""Tests if the Lefschetz collection is numerically exceptional."""
405
return self.Is_Exceptional( Test_Numerically=True )
406
407
408
def Numerical_Left_Dual ( self , Index:int ) -> Equivariant_Vector_Bundle :
409
"""Returns the i-th numerical left dual with respect to ``self.``"""
410
l = len(self)-1
411
assert Index in [ 0 .. l ] , \
412
'The input for ``Index`` need to be in the range from 0 to '+str(l)+'.'
413
LD = LC[l-Index]
414
for j in range(l-Index+1,l+1) :
415
LD = self[j].Numerical_Right_Mutation( LD )
416
return LD
417
418
419
def Numerical_Right_Dual ( self , Index:int ) -> Equivariant_Vector_Bundle :
420
"""Returns the i-th numerical right dual with respect to ``self.``"""
421
l = len(self)-1
422
assert Index in [ 0 .. l ] , \
423
'The input for ``Index`` need to be in the range from 0 to '+str(l)+'.'
424
RD = LC[l-Index]
425
for j in range(l-Index-1,0,-1) :
426
RD = self[j].Numerical_Left_Mutation( RD )
427
return RD
428
429
430
# Synonyms for the method ``Column`` :
431
def Orbit ( self , Input:int ) -> Iterator[ Equivariant_Vector_Bundle ] :
432
"""Returns a single orbit (= column)."""
433
self.Column( Input )
434
435
436
def Row ( self , Input:int ) -> Iterator[ Equivariant_Vector_Bundle ] :
437
"""Returns a single row."""
438
Height = self.Height()
439
if Input in ZZ :
440
if Input <= -Height-1 :
441
Start_Iteration = False
442
elif Input in [ -Height .. -1 ] :
443
Start_Iteration = True
444
yPos = Input + Height
445
elif Input in [ 0 .. Height-1 ] :
446
Start_Iteration = True
447
yPos = Input
448
elif Height <= Input :
449
Start_Iteration = False
450
451
if Start_Iteration :
452
for xPos , Object_Is_Accessible in enumerate( self.Support_Pattern()[yPos] ) :
453
if Object_Is_Accessible : yield self.Starting_Block(xPos)(yPos)
454
455
else :
456
raise TypeError('The input data must be an integer in the range '+str( [ -Height .. Height-1 ] )+'.')
457
458
459
def Subcollection( self , Columns:list or None=None , Rows:list or None=None ) -> "Lefschetz_Collection" :
460
"""Returns the subcollection of the given columns and rows."""
461
if Columns == None : Columns = range( len( self.Starting_Block() ) )
462
assert type(Columns) in [ list , range ] , \
463
TypeError('The input for ``Columns`` need to be a list or a range.')
464
if Rows == None : Rows = list( self.Support_Pattern().keys() )
465
assert type(Rows) in [ list , range ] , \
466
TypeError('The input for ``Rows`` need to be a list or a range.')
467
468
New_Starting_Block = [ Object for Object_Counter , Object in enumerate( self.Starting_Block() ) if Object_Counter in Columns ]
469
New_Support_Pattern = { Row_ID : [ Value for Column_Counter , Value in enumerate( Row ) if Column_Counter in Columns ] \
470
for Row_ID , Row in self.Support_Pattern().items() \
471
if Row_ID in Rows
472
}
473
return self.__class__( Base_Space=self.Base_Space() , Starting_Block=New_Starting_Block , Twist=self.Twist() , Support_Pattern=New_Support_Pattern )
474
475
476
def Support_Pattern ( self ) -> list[ list[ bool ] ] :
477
"""Returns the attribute ``_Support_Pattern``."""
478
return self._Support_Pattern
479
480
481
def Starting_Block ( self , Input:None or int or slice=None ) -> Equivariant_Vector_Bundle or list[ Equivariant_Vector_Bundle ] :
482
"""Returns the attribute ``_Starting_Block``."""
483
if Input == None : return self._Starting_Block
484
elif Input in ZZ :
485
Index = Input % len(self._Starting_Block)
486
return self._Starting_Block[Index]
487
elif type(Input) == slice :
488
Slice = Input
489
return self._Starting_Block[Slice]
490
else : raise ValueError('The input data is inappropriate.')
491
492
493
def Twist ( self ) -> Irreducible_Equivariant_Vector_Bundle :
494
"""Returns the attribute ``_Twist``."""
495
return self._Twist
496
497
498
def Width ( self ) -> int :
499
"""Returns the width of ``self``."""
500
return len(self.Starting_Block())
501
502
503
def Mutate ( self , Dictionary:dict , Base_Ring:'Ring'=ZZ , Basis=None , Gram_Matrix=None ) -> ( list[ list[ 'Ring element' ] ] , list[ list[ 'Ring element' ] ] ) :
504
"""Describes the left mutation on the K_0-level."""
505
# ..ToDo: Implement test for thoses objects, which are mutated through, are exceptional.
506
507
Length = len(self)
508
509
WCR = self.Base_Space().Parent_Group().Weyl_Character_Ring()
510
if Base_Ring == ZZ : pass
511
elif Base_Ring == WCR : pass
512
else : raise ValueError('The input for ``Base_Ring`` is inappropriate.')
513
514
if Basis == None : Basis = [ i*[ Base_Ring(0) ] + [ Base_Ring(1) ] + (Length-1-i)*[ Base_Ring(0) ] for i in range(Length) ]
515
516
assert type(Basis) == list , \
517
TypeError('The input for ``Basis`` must be a list.')
518
for Element_Counter , Element in enumerate( Basis , start=1 ) :
519
assert type(Element) == list , \
520
ValueError('The '+str(Element_Counter)+'-th element is not a list.')
521
for Entry_Counter , Entry in enumerate( Element , start=1 ) :
522
assert Entry in Base_Ring , \
523
ValueError('The '+str(Entry_Counter)+'-th entry of the '+str(Element_Counter)+'-th element is not an object of the base ring, namely '+str(Base_Ring)+'.')
524
525
if Gram_Matrix == None : Gram_Matrix = self.Gram_Matrix( Base_Ring )
526
527
for Row_Counter , Row in enumerate( Gram_Matrix , start=1 ) :
528
for Column_Counter , Entry in enumerate( Row , start=1 ) :
529
assert Entry in Base_Ring , \
530
ValueError('The '+str(Column_Counter)+'-th entry of the '+str(Row_Counter)+'-th row is not an object of the base ring, namely '+str(Base_Ring)+'.')
531
assert Column_Counter == Length , \
532
ValueError('The Gram matrix does not have rows of length '+str(Length)+'.')
533
assert Row_Counter == Length , \
534
ValueError('The Gram matrix does not have columns of length '+str(Length)+'.')
535
536
Bases = dict({})
537
Gram_Matrices = dict({})
538
539
Timer = 0
540
Bases.update({ Timer : Basis })
541
Gram_Matrices.update({ Timer : Gram_Matrix })
542
543
for Mutation_Counter , ( Start , End ) in enumerate( Dictionary.items() , start=1 ) :
544
assert Start in range(Length) , \
545
ValueError('The '+str(Mutation_Counter)+'-th key of the mutation dictionary is not an element in the range '+str([ 0 .. Length-1 ])+'.')
546
assert End in range(Length) , \
547
ValueError('The '+str(Mutation_Counter)+'-th value of the mutation dictionary is not an element in the range '+str([ 0 .. Length-1 ])+'.')
548
549
Index = Start
550
while Index != End :
551
Timer += 1
552
if End <= Start : # Left mutation
553
# Mutation triangle: 0 ----> EXT( E , F ) * E --ev--> F ----> LL_E(F) ----> 0
554
# i.e. [ LL_E(F) ] = [ F ] - EXT( E , F ) * [ E ] in K_0( self.Base_Space() )
555
e = Bases[Timer-1][ Index-1 ] # The object which is mutated through
556
f = Bases[Timer-1][ Index ] # The object which is mutated
557
chi = Gram_Matrices[Timer-1][ Index-1 ][ Index ]
558
mutation = [ f[i] - chi * e[i] for i in range(Length) ]
559
560
Bases.update({ Timer : Bases[Timer-1][ : Index-1 ] + [ mutation , e ] + Bases[Timer-1][ Index+1 : ] })
561
Gram_Matrices.update({ Timer : [ [ sum([ Base_Ring(0) ] + [ Bases[Timer][ Row_Index ][j] * Gram_Matrix[j][i] * Bases[Timer][ Column_Index ][i]
562
for i in range(Length)
563
for j in range(Length)
564
])
565
for Column_Index in range(Length)
566
]
567
for Row_Index in range(Length)
568
]
569
})
570
Index -= 1
571
572
else : # Right mutation
573
# Mutation triangle: 0 ----> RR_F(E) ----> E --coev--> EXT( F , E )^vee * F ----> 0 ???
574
# i.e. [ RR_F(E) ] = ?
575
#e = ? # The object which is mutated
576
#f = ? # The object which is mutated through
577
#chi = ?
578
#mutation = ?
579
580
Bases.update({ Timer : Bases[Timer-1][ : Index-1 ] + [ f , mutation ] + Bases[Timer-1][ Index+1 : ] })
581
#Gram_Matrices.update({ Timer : ? })
582
583
raise ValueError('The method for right mutations is yet not implemented.')
584
Index += 1
585
586
return Bases[Timer] , Gram_Matrices[Timer]
587
588
589
def Test_For_Extension ( self ,
590
New_Object :Equivariant_Vector_Bundle ,
591
Relevant_Columns :set[ int ] or None =None ,
592
Test_Numerically :bool =True ,
593
Test_If_Self_Is_Exceptional :bool =True
594
) -> Iterator[ int ] :
595
"""Test if ``New_Object`` can be inserted to ``self`` at the columns ``Relevant_Columns``."""
596
597
assert isinstance( New_Object , Equivariant_Vector_Bundle ) , \
598
'The input for `New_Object` need to be an equivariant vector bundle.'
599
New_Orbit = New_Object.Maximal_Exceptional_Orbit( Test_Numerically=Test_Numerically )
600
601
if Relevant_Columns == None : Relevant_Columns = set(range(self.Width()+1))
602
assert isinstance( Relevant_Columns , set ) , \
603
'If the input for `Relevant_Columns` is not None, then it need to be a set.'
604
assert Relevant_Columns.issubset( set(range(self.Width()+1)) ) , \
605
'The relevant columns need to be in the range from 0 to '+str(self.Width()+1)+'.'
606
607
if Test_If_Self_Is_Exceptional == True :
608
assert self.Is_Exceptional( Test_Numerically=Test_Numerically ) , \
609
'The collection `self` is not exceptional.'
610
611
def Test_For ( xPos1 , yPos1 ) :
612
Object1 = New_Object(yPos1)
613
for yPos2 , Row in self.Support_Pattern().items() :
614
for xPos2 , Object2_Is_Accessible in enumerate( Row ) :
615
if Object2_Is_Accessible :
616
Object2 = self.Starting_Block(xPos2)(yPos2)
617
#if not xPos2 in Already_Tested.keys() : Already_Tested.update({ xPos2 : ( set({}) , set({}) ) })
618
if yPos2 < yPos1 or ( yPos2 == yPos1 and xPos2 < xPos1 ) :
619
#if not yPos1-yPos2 in Already_Tested[xPos2][0] :
620
# Already_Tested[xPos2][0].add( yPos1-yPos2 )
621
if not next( Object1.Is_SemiOrthogonal_To( Object2 , Test_Numerically=Test_Numerically ) ) : return False
622
else :
623
#if not yPos2-yPos1 in Already_Tested[xPos2][1] :
624
# Already_Tested[xPos2][1].add( yPos2-yPos1 )
625
if not next( Object2.Is_SemiOrthogonal_To( Object1 , Test_Numerically=Test_Numerically ) ) : return False
626
return True
627
628
for Tested_xPos in Relevant_Columns :
629
#Already_Tested = dict({})
630
yield ( Tested_xPos , [ Tested_yPos for Tested_yPos in range(len(New_Orbit)) if Test_For( Tested_xPos , Tested_yPos ) ] )
631
632
633
def Test_For_SemiOrthogonal_Relations ( self ) :
634
G = self.Base_Space().Parent_Group()
635
636
for x1 , Obj1 in enumerate( self.Starting_Block() ) :
637
for x2 , Obj2 in enumerate( self.Starting_Block() ) :
638
Done = []
639
for y1 , Row1 in LC.Support_Pattern().items() :
640
if Row1[x1] == True :
641
for y2 , Row2 in LC.Support_Pattern().items() :
642
if Row2[x2] == True :
643
y = y1-y2
644
if not y in Done :
645
if 0 < y : Position = 'LowerHalf'
646
elif y == 0 and x2 < x1 : Position = 'LowerHalf'
647
elif y == 0 and x2 == x1 : Position = 'Diagonal'
648
else : Position = 'UpperHalf'
649
650
if Position == 'LowerHalf' or Position == 'Diagonal' :
651
Done += [y]
652
EXT_Space = Obj1(y).EXT(Obj2)
653
Euler_Sum = Obj1(y).Euler_Sum(Obj2)
654
655
if Position == 'LowerHalf' :
656
if EXT_Space == dict({}) : SemiOrthogonal_Relation = 'Correct.'
657
elif Euler_Sum == G.rmV(0) : SemiOrthogonal_Relation = 'Numerically correct.'
658
else : SemiOrthogonal_Relation = 'Not correct.'
659
660
elif Position == 'Diagonal' :
661
if EXT_Space == { 0 : G.rmV(1) } : SemiOrthogonal_Relation = 'Correct.'
662
elif Euler_Sum == G.rmV(1) : SemiOrthogonal_Relation = 'Numerically correct.'
663
else : SemiOrthogonal_Relation = 'Not correct.'
664
665
yield ( x1 , x2 , y , SemiOrthogonal_Relation , EXT_Space , Euler_Sum )
666
667