Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

Environment to perform calculations of equivariant vector bundles on homogeneous varieties

1842 views
License: GPL3
ubuntu2204
1
2
3
# This file was *autogenerated* from the file Young_Structure.sage
4
from sage.all_cmdline import * # import sage library
5
6
_sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_2 = Integer(2); _sage_const_3 = Integer(3)
7
from typing import Iterator
8
9
10
11
class Young_Structure ( object ) :
12
13
def __eq__ ( self , other ) -> bool :
14
if isinstance( other , self.__class__ ) : return self.Remove_Vanishing_Values().__repr__() == other.Remove_Vanishing_Values().__repr__()
15
else : return False
16
17
18
def __getitem__ ( self , Coordinate :tuple[ int ] ) -> int :
19
"""Returns the value of a given coordinate."""
20
assert isinstance( Coordinate , tuple ) , 'The input for `Coordinate` need to be a tuple.'
21
assert len(Coordinate) == self.Rank() , 'The length of `Coordinate` need to coincide with the rank of `self`.'
22
for CoordinateCounter , CoordinateEntry in enumerate( Coordinate , start=_sage_const_1 ) :
23
assert isinstance( CoordinateEntry , ( int , Integer ) ) , 'The '+str(CoordinateCounter)+'-th entry of the coordinate need to be an integer.'
24
if Coordinate in self.Data().keys() : return self.Data()[Coordinate]
25
else : return _sage_const_0
26
27
28
def __ge__ ( self , other ) -> bool :
29
"""Compares Young structures with respect to the >=-operator."""
30
return other <= self
31
32
33
def __gt__ ( self , other ) -> bool :
34
"""Compares Young structures with respect to the >-operator."""
35
return other < self
36
37
38
def __init__( self , Data :dict , Ranges :list ) -> None :
39
"""
40
Initialize a Young structure.
41
42
INPUT:
43
- ``Data`` -- Dictionary ;
44
- ``Ranges`` -- List of 2-tuples ;
45
46
OUTPUT: None.
47
"""
48
assert isinstance( Ranges , list ) , 'The input for `Ranges` need to be a list.'
49
for RangeCounter , Entry in enumerate( Ranges , start=_sage_const_1 ) :
50
assert isinstance( Entry , tuple ) , 'The '+str(RangeCounter)+'-th range need to be a tuple.'
51
assert len(Entry) == _sage_const_2 , 'The '+str(RangeCounter)+'-th range need to be of length 2.'
52
Minimum , Maximum = Entry
53
assert isinstance( Minimum , ( int , Integer ) ) , 'The minimum entry of the '+str(RangeCounter)+'-th range need to be an integer.'
54
assert isinstance( Maximum , ( int , Integer ) ) , 'The maximum entry of the '+str(RangeCounter)+'-th range need to be an integer.'
55
assert Minimum <= Maximum , 'For the '+str(RangeCounter)+'-th range, the minimum entry need to smaller or equal to the maximum entry.'
56
self._Ranges = Ranges
57
58
self._Rank = len(Ranges)
59
60
assert isinstance( Data , dict ) , 'The input for `Data` need to be dictionary.'
61
Adjusted_Data = dict({})
62
for ValueCounter , ( Coordinate , Value ) in enumerate( Data.items() , start=_sage_const_1 ) :
63
assert isinstance( Coordinate , tuple ) , 'The '+str(ValueCounter)+'-th coordinates need to be a tuple.'
64
assert len(Coordinate) <= self._Rank , 'The '+str(ValueCounter)+'-th coordinates need to be of length <= '+str(self._Rank)+'.'
65
Coordinate += tuple( ( self._Rank-len(Coordinate) )*[_sage_const_0 ] )
66
if Coordinate in Adjusted_Data.keys() : raise ValueError('CONFLICT! There are two values associated the same coordinate (after adjusting).')
67
else : Adjusted_Data.update({ Coordinate : Value })
68
for CoordinateCounter , CoordinateValue in enumerate( Coordinate ) :
69
assert isinstance( CoordinateValue , ( Integer , int ) ) , 'The '+str(CoordinateCounter+_sage_const_1 )+'-th entry of the '+str(ValueCounter)+'-th coordinate need to be an integer.'
70
Minimum = self._Ranges[CoordinateCounter][_sage_const_0 ]
71
assert Minimum <= CoordinateValue , 'The '+str(CoordinateCounter+_sage_const_1 )+'-th entry of the '+str(ValueCounter)+'-th coordinate need to >= '+str(Minimum)+'.'
72
Maximum = self._Ranges[CoordinateCounter][_sage_const_1 ]
73
assert CoordinateValue <= Maximum , 'The '+str(CoordinateCounter+_sage_const_1 )+'-th entry of the '+str(ValueCounter)+'-th coordinate need to <= '+str(Maximum)+'.'
74
self._Data = Adjusted_Data
75
76
77
def __iter__ ( self ) -> Iterator[ tuple[ tuple[ int ] , int ] ] :
78
"""Returns an iterator of ``self``."""
79
return ( ( Coordinate , Value ) for Coordinate , Value in self.Data().items() )
80
81
82
def __le__ ( self , other ) -> bool :
83
"""Compares Young structures with respect to the <=-operator."""
84
if self == other : return True
85
elif self < other : return True
86
else : return False
87
88
89
# Synonym for the method `Rank`
90
def __len__( self ) :
91
"""Returns the rank ``self``."""
92
return self.Rank()
93
94
95
def __ne__ ( self , other ) -> bool :
96
return not self == other
97
98
99
def __repr__ ( self ) -> tuple[ dict[ tuple[int] : int ] , list[ tuple[ int , int ] ] ] :
100
"""Returns all attributes which are necessary to initialize the object."""
101
return self.Data() , self.Ranges()
102
103
104
def __str__ ( self ) -> str :
105
"""Returns a description in terms of diagrams (sliced if necessary)."""
106
if self.Rank() < _sage_const_3 :
107
# Low-dimensional Young structures can be printed.
108
( xMinimum , xMaximum ) , ( yMinimum , yMaximum ) = self.Ranges() + (_sage_const_2 -self.Rank())*[ ( _sage_const_0 , _sage_const_0 ) ]
109
Width = xMaximum-xMinimum+_sage_const_1
110
Height = yMaximum-yMinimum+_sage_const_1
111
M = matrix( nrows=Height , ncols=Width )
112
if _sage_const_0 in (ellipsis_range( yMinimum ,Ellipsis, yMaximum )) : ySubdivision = [ abs(yMinimum) ]
113
else : ySubdivision = None
114
if _sage_const_0 in (ellipsis_range( xMinimum ,Ellipsis, xMaximum )) : xSubdivision = [ abs(xMinimum) ]
115
else : xSubdivision = None
116
M.subdivide( ySubdivision , xSubdivision )
117
for Coordinate , Value in self :
118
xCoordinate , yCoordinate = Coordinate + tuple( (_sage_const_2 -self.Rank())*[ _sage_const_0 ] )
119
M[ yCoordinate-yMinimum , xCoordinate-xMinimum ] = Value
120
return str(M)
121
122
else :
123
# Slice down to the first two coordinates x and y.
124
Output = ''
125
x = self.Coordinates()
126
Condition_Factors = []
127
for CoordinateCounter in range( self.Rank()-_sage_const_1 , _sage_const_1 , -_sage_const_1 ) :
128
Minimum , Maximum = self.Ranges()[CoordinateCounter]
129
Condition_Factors += [ [ x[CoordinateCounter] == Entry for Entry in (ellipsis_range( Minimum ,Ellipsis, Maximum )) ] ]
130
for Conditions in cartesian_product(Condition_Factors) :
131
YS = self.Locus( *Conditions )
132
for CoordinateCounter in range( YS.Rank()-_sage_const_1 , _sage_const_1 , -_sage_const_1 ) :
133
YS.Remove_Coordinate(CoordinateCounter)
134
Output += str( Conditions ) + '\n'
135
Output += str( YS ) + '\n'
136
Output += '\n'
137
138
return Output
139
140
141
#ToDo: Test if `Permutation` is the correct instance.
142
def Conjugate ( self , Permutation: "Permutation" ) -> "Young_Structure" :
143
"""Returns a conjugated Young structure."""
144
assert len(Permutation) == self.Rank() , 'The length of the permutation need to coincide with the rank of `self`.'
145
New_Data = { tuple(Permutation.action(list(Coordinate))) : Value for Coordinate , Value in self }
146
New_Ranges = Permutation.action(self.Ranges())
147
return self.__class__( New_Data , New_Ranges )
148
149
150
@staticmethod
151
def Constructor ( *Input:tuple ) -> "Young_Structure" :
152
153
def Get_Empty_Young_Structure ( Ranges :list[ tuple[ int , int ] ] ) -> "Young_Structure" :
154
Data = { tuple(Coordinate) : _sage_const_0 for Coordinate in cartesian_product([ (ellipsis_range( Minimum ,Ellipsis, Maximum ))
155
for Minimum , Maximum in Ranges
156
])
157
}
158
return Young_Structure( Data , Ranges )
159
160
def Get_Young_Structure_From_Binary_Description ( String :str ) -> "Young_Structure" :
161
Keep_Running = True
162
while Keep_Running :
163
Keep_Running = False
164
for SubString in [ 'RL' , 'LR' , 'DU' , 'UD' ] :
165
if String.find(SubString) != -_sage_const_1 :
166
String = String.replace( SubString , '' )
167
Keep_Running = True
168
169
xAmplitude = [_sage_const_0 ]+[ String[:Counter].count('R')-String[:Counter].count('L') for Counter in range(len(String)) ]
170
xRange = ( min(xAmplitude) , max(xAmplitude)-_sage_const_1 )
171
if xRange == (_sage_const_0 ,-_sage_const_1 ) : xRange = (_sage_const_0 ,_sage_const_0 )
172
xMinimum , xMaximum = xRange
173
yAmplitude = [_sage_const_0 ]+[ String[:Counter].count('D')-String[:Counter].count('U') for Counter in range(len(String)) ]
174
yRange = ( min(yAmplitude) , max(yAmplitude)-_sage_const_1 )
175
if yRange == (_sage_const_0 ,-_sage_const_1 ) : yRange = (_sage_const_0 ,_sage_const_0 )
176
yMinimum , yMaximum = yRange
177
178
YS = Get_Empty_Young_Structure( [ xRange , yRange ] )
179
Data = YS.Data()
180
Ranges = YS.Ranges()
181
182
xPointer , yPointer = (_sage_const_0 ,_sage_const_0 )
183
for Letter in String :
184
if Letter == 'R' :
185
for yPos in (ellipsis_range( yPointer ,Ellipsis, yMaximum )) :
186
Data[ (xPointer,yPos) ] += _sage_const_1
187
xPointer += _sage_const_1
188
elif Letter == 'L' :
189
xPointer -= _sage_const_1
190
for yPos in (ellipsis_range( yPointer ,Ellipsis, yMaximum )) :
191
Data[ (xPointer,yPos) ] -= _sage_const_1
192
elif Letter == 'D' :
193
yPointer += _sage_const_1
194
elif Letter == 'U' :
195
yPointer -= _sage_const_1
196
return Young_Structure( Data , Ranges )
197
198
def Get_Young_Structure_From_Integer ( IntegerValue :int ) -> "Young_Structure" :
199
if IntegerValue == _sage_const_0 :
200
Data = dict({})
201
Ranges = [ ( _sage_const_0 , _sage_const_0 ) ]
202
else :
203
Minimum = min([ _sage_const_0 , IntegerValue ])
204
Maximum = max([ _sage_const_0 , IntegerValue ])
205
Data = { (Index,) : _sage_const_1 for Index in range(Minimum,Maximum) }
206
Ranges = [ ( Minimum , Maximum-_sage_const_1 ) ]
207
return Young_Structure( Data , Ranges )
208
209
def Stacking_Young_Structures ( Stack :dict[ int : "Young_Structure" ] ) -> "Young_Structure" :
210
if _sage_const_0 < len( Stack.keys() ) :
211
New_Rank = max([_sage_const_0 ] + [ New_Slice.Rank() for New_Slice in Stack.values() ]) + _sage_const_1
212
New_Data = dict({})
213
New_Ranges = New_Rank * [ ( +infinity , -infinity ) ]
214
for New_Coordinate , New_Slice in Stack.items() :
215
Filling = tuple( (New_Rank-New_Slice.Rank()-_sage_const_1 )*[ _sage_const_0 ])
216
New_Data.update({ Coordinate + Filling + (New_Coordinate,) : Value for Coordinate , Value in New_Slice })
217
Adjusted_Ranges = [ ( min([ New_Ranges[RangeCounter][_sage_const_0 ] , Range[_sage_const_0 ] ]) , max([ New_Ranges[RangeCounter][_sage_const_1 ] , Range[_sage_const_1 ] ]) ) for RangeCounter , Range in enumerate( New_Slice.Ranges() ) ]
218
New_Ranges = Adjusted_Ranges
219
New_Ranges += [ ( min(Stack.keys()) , max(Stack.keys()) ) ]
220
else :
221
New_Data = dict({})
222
New_Ranges = []
223
return Young_Structure( New_Data , New_Ranges )
224
225
if len(Input) == _sage_const_1 :
226
Input = Input[_sage_const_0 ]
227
if isinstance( Input , Integer ) :
228
return Get_Young_Structure_From_Integer( Input )
229
230
elif isinstance( Input , ( list , tuple ) ) :
231
Stack = dict({})
232
for EntryCounter , Entry in enumerate( Input ) :
233
assert isinstance( Entry , ( int , Integer ) ) , 'If the input is given as list or tuple, then the '+str(EntryCounter+_sage_const_1 )+'-th entry need to be an integer.'
234
Stack.update({ EntryCounter : Get_Young_Structure_From_Integer(Entry) })
235
return Stacking_Young_Structures( Stack )
236
237
elif isinstance( Input , str ) :
238
Input = Input.upper()
239
RightCounts = Input.count('R')
240
LeftCounts = Input.count('L')
241
DownCounts = Input.count('D')
242
UpCounts = Input.count('U')
243
assert len(Input) == sum([ RightCounts , LeftCounts , DownCounts , UpCounts ]) , 'The only admissible letters in `Input` are R (right), L (left), D (down), and U (up).'
244
assert RightCounts == LeftCounts , 'The number of R-letters ('+str(RightCounts)+'x) and L-letters ('+str(LeftCounts)+'x) need to coincide.'
245
assert DownCounts == UpCounts , 'The number of D-letters ('+str(DownCounts)+'x) and U-letters ('+str(UpCounts)+'x) need to coincide.'
246
return Get_Young_Structure_From_Binary_Description( Input )
247
248
elif isinstance( Input , dict ) :
249
for New_Coordinate , New_Slice in Input.items() :
250
assert isinstance( New_Coordinate , ( int , Integer ) ) , 'If the input is a dictionary, then the keys need to be integers.'
251
assert isinstance( New_Slice , ( Young_Structure ) ) , 'If the input is a dictionary, then the values need to be Young structures.'
252
return Stacking_Young_Structures( Input )
253
254
elif isinstance( Input , Young_Structure ) :
255
return Input
256
257
else :
258
raise ValueError('The single input is inappropriate.')
259
260
elif len(Input) == _sage_const_2 :
261
if Input[_sage_const_0 ] == 'Empty' :
262
Ranges = Input[_sage_const_1 ]
263
return Get_Empty_Young_Structure( Ranges )
264
265
else :
266
raise ValueError('The two inputs are inappropriate.')
267
268
else :
269
raise ValueError('The input is inappropriate.')
270
271
272
def Coordinates ( self ) -> "Variables" :
273
"""Returns the variable coordinates."""
274
return var([ 'x'+str(Counter) for Counter in range(self.Rank()) ])
275
276
277
def Data ( self ) -> dict[ tuple : int ] :
278
"""Returns the attribute ``_Data``."""
279
return self._Data
280
281
282
def Expand_Ranges ( self , New_Ranges ) -> "Young_Structure" :
283
"""Returns a Young structure with expanded ranges."""
284
assert isinstance( New_Ranges , list ) , 'The input for `New_Ranges` need to be a list.'
285
assert len(New_Ranges) == self.Rank() , 'The length of `New_Ranges` need to coincide with the rank of `self`.'
286
YS = self
287
for RangeCounter , New_Range in enumerate( New_Ranges ) :
288
if New_Range == None :
289
pass
290
291
else :
292
Old_Minimum , Old_Maximum = YS.Ranges()[RangeCounter]
293
assert isinstance( New_Range , tuple ) , 'The '+str(RangeCounter)+'-th entry need to be a tuple.'
294
assert len(New_Range) == _sage_const_2 , 'The '+str(RangeCounter)+'-th range tuple need to be of length 2.'
295
New_Minimum , New_Maximum = New_Range
296
assert New_Minimum <= New_Maximum , 'The new minimum need to be smaller than or equal to the new maximum.'
297
assert New_Minimum <= Old_Minimum , 'The new minimum need to be smaller than or equal to the old minimum.'
298
assert Old_Maximum <= New_Maximum , 'The old maximum need to be smaller than or equal to the new maximum.'
299
YS._Ranges[RangeCounter] = New_Range
300
301
return YS
302
303
304
def Locus ( self , *Conditions ) -> "Young_Structure" :
305
"""Returns locus of Young structure with respect to given conditions."""
306
for ConditionCounter , Condition in enumerate( Conditions , start=_sage_const_1 ) :
307
assert isinstance( Condition , sage.symbolic.expression.Expression ) , 'The input for the '+str(ConditionCounter)+'-th condition need to be an symbolic expression.'
308
x = self.Coordinates()
309
New_Data = dict({})
310
for Coordinate , Value in self :
311
Value_Satisfies_All_Conditions = True
312
for ConditionCounter , Condition in enumerate( Conditions , start=_sage_const_1 ) :
313
if bool( Condition({x[CoordinateCounter] : CoordinateEntry for CoordinateCounter , CoordinateEntry in enumerate( Coordinate ) }) ) :
314
pass
315
else :
316
Value_Satisfies_All_Conditions = False
317
break
318
if Value_Satisfies_All_Conditions : New_Data.update({ Coordinate : Value })
319
New_Ranges = self.Ranges()
320
return self.__class__( New_Data , New_Ranges )
321
322
323
def Move_Origin ( self , Steps:list[ int ] ) -> "Young_Structure" :
324
"""Returns a Young structure with moved origin."""
325
assert isinstance( Steps , list ) , 'The input for `Steps` need to be a list.'
326
assert len(Steps) == self.Rank() , 'The length of the tuple `Steps` need to coincide with the rank of `self`.'
327
for StepCounter , Step in enumerate( Steps ) :
328
assert isinstance( Step , ( int , Integer ) ) , 'The '+str(StepCounter)+'-th step need to be an integer.'
329
New_Data = { tuple( vector( ZZ , Coordinate ) + vector( ZZ , Steps ) ) : Value for Coordinate , Value in self }
330
New_Ranges = [ ( Minimum+Steps[RageCounter] , Maximum+Steps[RageCounter] ) for RageCounter , ( Minimum , Maximum ) in enumerate( self.Ranges() ) ]
331
return self.__class__( New_Data , New_Ranges )
332
333
334
def Ranges ( self ) -> list[ tuple[ int , int ] ] :
335
"""Returns the attribute ``_Ranges``."""
336
return self._Ranges
337
338
339
def Rank ( self ) -> int :
340
"""Returns the attribute ``_Rank``."""
341
return self._Rank
342
343
344
def Remove_Coordinate ( self , Index ) -> None :
345
"""Remove non-varying coordinates."""
346
assert Index in range(self.Rank()) , 'The input for `Index` need to be in the range '+str(range(self.Rank()))+'-.'
347
New_Data = dict({})
348
for Coordinate , Value in self :
349
Coordinate = tuple([ CoordinateEntry for CoordinateCounter , CoordinateEntry in enumerate(Coordinate) if CoordinateCounter != Index ])
350
New_Data.update({ Coordinate : Value })
351
New_Ranges = [ Range for RangeCounter , Range in enumerate( self.Ranges() ) if RangeCounter != Index ]
352
self.__init__( New_Data , New_Ranges )
353
354
355
def Remove_Vanishing_Values ( self ) -> "Young_Structure" :
356
"""Returns a Young structure without zero-values."""
357
return self.__class__( { Coordinate : Value for Coordinate , Value in self if Value != _sage_const_0 } , self.Ranges() )
358
359
360
def Sizes ( self ) -> list[ int ] :
361
"""Returns the sizes per direction."""
362
return [ Maximum-Minimum+_sage_const_1 for Minimum , Maximum in self.Ranges() ]
363
364
365
def Support ( self , Output_Type :str ='Absolute' ) -> "Young_Structure" :
366
"Returns the support."
367
if Output_Type in [ 'Absolute' , 'abs' ] :
368
Data = { tuple(self.Rank()*[_sage_const_0 ]) : _sage_const_0 }
369
Data.update({ Coordinate : _sage_const_1 for Coordinate , Value in self if Value != _sage_const_0 })
370
return self.__class__( Data , self.Ranges() )
371
elif Output_Type in [ 'Relative' , 'rel' , 'Sign' , 'sgn' ] :
372
return self.__class__( { Coordinate : sgn(Value) for Coordinate , Value in self } , self.Ranges() )
373
else :
374
raise ValueError('The input for `Output_Type` is inappropriate.')
375
376
377
def Volumne ( self ) -> int :
378
"""Returns the sum of all entries."""
379
return sum([ Value for Coordinate , Value in self ])
380
381
382
# ToDo: NEED TO BE DONE.
383
def __lt__ ( self , other ) -> bool :
384
"""Compares Young structures with respect to the <-operator."""
385
raise ValueError('The method `less-than` is not yet implemented.')
386
387
388
#def Compress ( self , Direction :int ) -> "Young_Structure" :
389
# assert isinstance( Direction , ( int , Integer ) ) , \
390
# 'The input for `Direction` need to be an integer.'
391
# assert Direction in range(self.Rank()) , \
392
# 'The value of `Direction` need to be in the range from 0 to '+str(self.Rank())+'.'
393
394
#def Inflate ( self , Direction :int ) -> "Young_Structure" :
395
# pass
396
397
398
399
class Young_Diagram ( Young_Structure ) :
400
401
# Synonym for the method `Twist`
402
def __call__ ( self , Step :int =_sage_const_0 ) -> "Young_Diagram" :
403
"""Return a twisted Young diagram."""
404
return self.Twist( Step )
405
406
407
def __init__( self , Data :dict , Ranges :list or None =None ) -> None :
408
super( Young_Diagram , self ).__init__( Data , Ranges )
409
410
assert self.Rank() == _sage_const_2 , '`self` need to be of rank 2.'
411
412
xRange , yRange = self.Ranges()
413
xMinimum , xMaximum = xRange
414
yMinimum , yMaximum = yRange
415
assert xMinimum == _sage_const_0 , 'The x-minimum need to be zero.'
416
assert yMinimum == _sage_const_0 , 'The y-minimum need to be zero.'
417
418
for Coordinate , Value in self :
419
xCoordinate , yCoordinate = Coordinate
420
assert Value in [ _sage_const_0 , _sage_const_1 ] , 'The value at coordinate '+str(Coordinate)+' need to be zero or one.'
421
if _sage_const_0 < xCoordinate :
422
assert Value <= self[(xCoordinate-_sage_const_1 ,yCoordinate)] , 'The value at '+str((xCoordinate-_sage_const_1 ,yCoordinate))+' need to be smaller than or equal to the value at '+str((xCoordinate,yCoordinate))+'.'
423
if _sage_const_0 < yCoordinate :
424
assert Value <= self[(xCoordinate,yCoordinate-_sage_const_1 )] , 'The value at '+str((xCoordinate,yCoordinate-_sage_const_1 ))+' need to be smaller than or equal to the value at '+str((xCoordinate,yCoordinate))+'.'
425
426
427
def __lshift__ ( self , Step :int =_sage_const_1 ) -> "Young_Diagram" :
428
"""Returns a shifted Young diagram (cyclic action)."""
429
return self >> -_sage_const_1 *Step
430
431
432
# Synonym for the method `Shift`
433
def __rshift__ ( self , Step :int =_sage_const_1 ) -> "Young_Diagram" :
434
"""Returns a shifted Young diagram (cyclic action)."""
435
return self.Shift( Step )
436
437
438
def Binary_Description ( self ) -> str :
439
Width = self.Width()
440
xPointer = Width
441
Height = self.Height()
442
yPointer = _sage_const_0
443
Description = ''
444
while _sage_const_0 < xPointer and yPointer < Height :
445
if self[xPointer,yPointer] < self[xPointer-_sage_const_1 ,yPointer] :
446
yPointer += _sage_const_1
447
Description += 'D'
448
else :
449
xPointer -= _sage_const_1
450
Description += 'L'
451
if _sage_const_0 < xPointer : Description += xPointer*'L'
452
if yPointer < Height : Description += (Height-yPointer)*'D'
453
return Description
454
455
456
def Complement ( self ) -> "Young_Diagram" :
457
"""Returns the complement of `self`."""
458
Width = self.Width()
459
Height = self.Height()
460
return self.__class__.Constructor( [ Width-Entry for Entry in self.Usual_Description()[::-_sage_const_1 ] ] , (Width,Height) )
461
462
463
def Column_Differences ( self ) -> list[int] :
464
"""Returns the differences s_{i}-s_{i+1} for i running through xRange"""
465
return self.Conjugate().Row_Differences()
466
467
468
def Column_Heights ( self ) -> list[ int ] :
469
"""Returns the height of each column."""
470
return self.Conjugate().Row_Widths()
471
472
473
def Column_Volumnes ( self ) -> list[ int ] :
474
"""Returns the volumne of each column."""
475
return self.Conjugate().Row_Volumnes()
476
477
478
def Columns ( self ) -> Iterator[ list[ int ] ] :
479
"""Returns an iterator running over the columns."""
480
return self.Conjugate().Rows()
481
482
483
def Conjugate ( self ) :
484
"""Returns the conjugated Young diagram."""
485
return super( Young_Diagram , self ).Conjugate( Permutation( '(1,2)' ) )
486
487
488
@staticmethod
489
def Constructor ( Description :tuple[ int ] or str , Sizes :tuple[ int , int ] or None =None ) -> "Young_Diagram" :
490
if Description in [ None , 'Empty' , [] , tuple([]) , dict({}) ] :
491
MinimumWidth = _sage_const_0
492
MinimumHeight = _sage_const_0
493
Description = [ _sage_const_0 ]
494
495
elif isinstance( Description , ( list , tuple ) ) :
496
MinimumWidth = max([_sage_const_1 ] + list(Description))
497
MinimumHeight = len(Description)
498
Previous_Entry = +infinity
499
for EntryCounter , Current_Entry in enumerate( Description ) :
500
assert isinstance( Current_Entry , ( int , Integer ) ) , 'The '+str(EntryCounter)+'-th entry need to be an integer.'
501
assert Previous_Entry >= Current_Entry , 'The '+str(EntryCounter)+'-th entry need to be smaller than or equal to the previous one.'
502
Previous_Entry = Current_Entry
503
504
elif isinstance( Description , str ) :
505
if set(Description).issubset({ 'D' , 'L' }) :
506
MinimumWidth = Description.count('L')
507
MinimumHeight = Description.count('D')
508
Description = MinimumWidth*'R' + Description + MinimumHeight*'U'
509
else :
510
raise ValueError( 'The input for `Description` is given as string, then its letters must be from the set { D (down) , L (letft) }.' )
511
512
else :
513
raise ValueError( 'The input for `Description is inappropriate.`' )
514
515
if Sizes == None : Sizes = ( MinimumWidth , MinimumHeight )
516
Width , Height = Sizes
517
assert MinimumWidth <= Width , 'The width need to be => '+str(MinimumWidth)+'.'
518
assert MinimumHeight <= Height , 'The height need to be => '+str(MinimumHeight)+'.'
519
520
YS = Young_Structure.Constructor( Description )
521
YD = Young_Diagram( YS.Data() , YS.Ranges() )
522
return YD.Expand_Sizes( Width , Height )
523
524
525
def Cyclic_Orbit ( self ) -> Iterator[ "Young_Diagram" ] :
526
"""Runs through the cyclic orbit of `self`."""
527
First_Object = self
528
Current_Object = First_Object
529
while True :
530
yield Current_Object
531
Current_Object = Current_Object >> _sage_const_1
532
if Current_Object == First_Object : break
533
534
535
def Expand_Sizes ( self , New_Width :int , New_Height :int ) -> "Young_Diagram" :
536
"""Returns a Young diagram with expanded sizes."""
537
assert isinstance( New_Width , ( int , Integer ) ) , 'The input for `New_Width` need to be an integer.'
538
assert self.Width() <= New_Width , 'The new width need to be greater than or equal to the (old) width.'
539
assert isinstance( New_Height , ( int , Integer ) ) , 'The input for `New_Height` need to be an integer.'
540
assert self.Height() <= New_Height , 'The new height need to be greater than or equal to the (old) height.'
541
return self.Expand_Ranges( [ ( _sage_const_0 , New_Width-_sage_const_1 ) , ( _sage_const_0 , New_Height-_sage_const_1 ) ] )
542
543
544
def Height ( self ) -> int :
545
"""Returns the size in y-direction."""
546
return self.Sizes()[_sage_const_1 ]
547
548
549
def Is_Upper_Triangular ( self ) -> bool :
550
"""Tests if `self` is upper triangular"""
551
Width = self.Width()
552
Height = self.Height()
553
for xPos , Column_Height in enumerate( self.Column_Heights() ) :
554
if not Column_Height <= floor( Height*(Width-xPos-_sage_const_1 ) / Width ) : return False
555
return True
556
557
558
def N ( self ) -> int :
559
"""Returns the sum of width and height."""
560
return sum(self.Sizes())
561
562
563
def Row_Differences ( self ) -> list[int] :
564
"""Returns the differences s_{i}-s_{i+1} for j running through yRange"""
565
s = self.Row_Volumnes() + [ _sage_const_0 ]
566
return [ s[j]-s[j+_sage_const_1 ] for j in self.yRange() ]
567
568
569
def Row_Widths ( self ) -> list[ int ] :
570
"""Returns the volumne of each row."""
571
return [ sum(Row) for Row in self.Support().Rows() ]
572
573
574
def Row_Volumnes ( self ) -> list[ int ] :
575
"""Returns the volumne of each row."""
576
return [ sum(Row) for Row in self.Rows() ]
577
578
579
def Rows ( self ) -> Iterator[ list[ int ] ] :
580
"""Returns an iterator running over the rows."""
581
xRange = self.xRange()
582
yRange = self.yRange()
583
for yPos in yRange :
584
yield [ self[xPos,yPos] for xPos in xRange ]
585
586
587
def Shift ( self , Step :int =_sage_const_1 ) -> "Young_Diagram" :
588
"""Returns a shifted Young diagram (cyclic action)."""
589
assert isinstance( Step , ( int , Integer ) ) , 'The input for `Step` need to be an integer.'
590
Step = Step % self.N()
591
if Step == _sage_const_0 :
592
return self
593
else :
594
Old_Binary_Description = self.Binary_Description()
595
New_Binary_Description = Old_Binary_Description[-_sage_const_1 ] + Old_Binary_Description[ : -_sage_const_1 ]
596
New_Step = Step-_sage_const_1
597
return Young_Diagram.Constructor( New_Binary_Description ).Shift(New_Step)
598
599
600
def Twist ( self , Step :int =_sage_const_1 ) -> "Young_Diagram" :
601
"""Returns the Young diagram after a twist-action."""
602
assert isinstance( Step , ( int , Integer ) ) , 'The input for `Step` need to be an integer.'
603
New_YD = Young_Diagram.Constructor( [ Entry+Step for Entry in self.Usual_Description() ] )
604
New_Width = max([ New_YD.Width() , self.Width() ])
605
New_Height = max([ New_YD.Height() , self.Height() ])
606
return New_YD.Expand_Sizes( New_Width , New_Height )
607
608
609
# Synonym for the method `Row_Volumnes`.
610
def Usual_Description ( self ) -> list[ int ] :
611
"""Returns the usual description of `self`."""
612
return self.Row_Volumnes()
613
614
615
def Width ( self ) -> int :
616
"""Returns the size in x-direction."""
617
return self.Sizes()[_sage_const_0 ]
618
619
620
def xRange ( self ) -> list[ int ] :
621
"""Returns the range in x-direction."""
622
return (ellipsis_range( _sage_const_0 ,Ellipsis, self.Width()-_sage_const_1 ))
623
624
625
def yRange ( self ) -> list[ int ] :
626
"""Returns the range in y-direction."""
627
return (ellipsis_range( _sage_const_0 ,Ellipsis, self.Height()-_sage_const_1 ))
628
629
630
@staticmethod
631
def Lexicographically_Ordered ( Width :int , Height :int ) -> Iterator[ "Young_Diagrams" ] :
632
assert isinstance( Height , ( int , Integer ) ) , 'The input for `Height` need to be an integer.'
633
assert _sage_const_1 <= Height , 'The integer Height need to be greater than or equal to 1.'
634
assert isinstance( Width , ( int , Integer ) ) , 'The input for `Width` need to be an integer.'
635
assert _sage_const_1 <= Width , 'The integer Width need to be greater than or equal to 1.'
636
Usual_Descriptions = [ list(Usual_Description) for Usual_Description in IntegerListsLex( max_part=Width , length=Height , max_slope=_sage_const_0 ) ]
637
Usual_Descriptions.reverse()
638
for Usual_Description in Usual_Descriptions :
639
yield Young_Diagram.Constructor( Usual_Description , ( Width , Height ) )
640
641
642
@staticmethod
643
def Upper_Triangulars ( Width :int , Height :int ) -> Iterator[ "Young_Diagrams" ] :
644
assert isinstance( Height , ( int , Integer ) ) , 'The input for `Height` need to be an integer.'
645
assert _sage_const_1 <= Height , 'The integer Height need to be greater than or equal to 1.'
646
assert isinstance( Width , ( int , Integer ) ) , 'The input for `Width` need to be an integer.'
647
assert _sage_const_1 <= Width , 'The integer Width need to be greater than or equal to 1.'
648
Ceiling = [ floor( Width*(Height-Counter)/Height ) for Counter in (ellipsis_range( _sage_const_1 ,Ellipsis, Height )) ]
649
Usual_Descriptions = [ list(Usual_Description) for Usual_Description in IntegerListsLex( max_part=Width , length=Height , ceiling=Ceiling , max_slope=_sage_const_0 ) ]
650
Usual_Descriptions.reverse()
651
for Usual_Description in Usual_Descriptions :
652
yield Young_Diagram.Constructor( Usual_Description , ( Width , Height ) )
653
654
655
@staticmethod
656
def Minimal_Upper_Triangulars ( Width :int , Height :int ) -> Iterator[ "Young_Diagrams" ] :
657
Orbits = []
658
for YD in Young_Diagram.Upper_Triangulars( Width , Height ) :
659
YD_Did_Already_Appear = False
660
for Partial_Orbit in Orbits :
661
if YD in Partial_Orbit :
662
YD_Did_Already_Appear = True
663
break
664
if not YD_Did_Already_Appear :
665
Orbit_Length = _sage_const_0
666
Partial_Orbit = []
667
for Fellow in YD.Cyclic_Orbit() :
668
Orbit_Length += _sage_const_1
669
if Fellow.Is_Upper_Triangular() : Partial_Orbit += [ Fellow ]
670
Orbits += [ Partial_Orbit ]
671
yield YD , Orbit_Length
672
673
674