Environment to perform calculations of equivariant vector bundles on homogeneous varieties
Equivariant_Vector_Bundles_On_Homogeneous_Varieties__0-2 / src / Equivariant_Vector_Bundles_On_Homogeneous_Varieties / Extras / Young_Structure.sage
1842 viewsLicense: GPL3
ubuntu2204
from typing import Iterator1234class Young_Structure ( object ) :56def __eq__ ( self , other ) -> bool :7if isinstance( other , self.__class__ ) : return self.Remove_Vanishing_Values().__repr__() == other.Remove_Vanishing_Values().__repr__()8else : return False91011def __getitem__ ( self , Coordinate :tuple[ int ] ) -> int :12"""Returns the value of a given coordinate."""13assert isinstance( Coordinate , tuple ) , \14'The input for `Coordinate` need to be a tuple.'15assert len(Coordinate) == self.Rank() , \16'The length of `Coordinate` need to coincide with the rank of `self`.'17for CoordinateCounter , CoordinateEntry in enumerate( Coordinate , start=1 ) :18assert isinstance( CoordinateEntry , ( int , Integer ) ) , \19'The '+str(CoordinateCounter)+'-th entry of the coordinate need to be an integer.'20if Coordinate in self.Data().keys() : return self.Data()[Coordinate]21else : return 0222324def __ge__ ( self , other ) -> bool :25"""Compares Young structures with respect to the >=-operator."""26return other <= self272829def __gt__ ( self , other ) -> bool :30"""Compares Young structures with respect to the >-operator."""31return other < self323334def __init__( self , Data :dict , Ranges :list ) -> None :35"""36Initialize a Young structure.3738INPUT:39- ``Data`` -- Dictionary ;40- ``Ranges`` -- List of 2-tuples ;4142OUTPUT: None.43"""44assert isinstance( Ranges , list ) , \45'The input for `Ranges` need to be a list.'46for RangeCounter , Entry in enumerate( Ranges , start=1 ) :47assert isinstance( Entry , tuple ) , \48'The '+str(RangeCounter)+'-th range need to be a tuple.'49assert len(Entry) == 2 , \50'The '+str(RangeCounter)+'-th range need to be of length 2.'51Minimum , Maximum = Entry52assert isinstance( Minimum , ( int , Integer ) ) , \53'The minimum entry of the '+str(RangeCounter)+'-th range need to be an integer.'54assert isinstance( Maximum , ( int , Integer ) ) , \55'The maximum entry of the '+str(RangeCounter)+'-th range need to be an integer.'56assert Minimum <= Maximum , \57'For the '+str(RangeCounter)+'-th range, the minimum entry need to smaller or equal to the maximum entry.'58self._Ranges = Ranges5960self._Rank = len(Ranges)6162assert isinstance( Data , dict ) , \63'The input for `Data` need to be dictionary.'64Adjusted_Data = dict({})65for ValueCounter , ( Coordinate , Value ) in enumerate( Data.items() , start=1 ) :66assert isinstance( Coordinate , tuple ) , \67'The '+str(ValueCounter)+'-th coordinates need to be a tuple.'68assert len(Coordinate) <= self._Rank , \69'The '+str(ValueCounter)+'-th coordinates need to be of length <= '+str(self._Rank)+'.'70Coordinate += tuple( ( self._Rank-len(Coordinate) )*[0] )71if Coordinate in Adjusted_Data.keys() : raise ValueError('CONFLICT! There are two values associated the same coordinate (after adjusting).')72else : Adjusted_Data.update({ Coordinate : Value })73for CoordinateCounter , CoordinateValue in enumerate( Coordinate ) :74assert isinstance( CoordinateValue , ( Integer , int ) ) , \75'The '+str(CoordinateCounter+1)+'-th entry of the '+str(ValueCounter)+'-th coordinate need to be an integer.'76Minimum = self._Ranges[CoordinateCounter][0]77assert Minimum <= CoordinateValue , \78'The '+str(CoordinateCounter+1)+'-th entry of the '+str(ValueCounter)+'-th coordinate need to >= '+str(Minimum)+'.'79Maximum = self._Ranges[CoordinateCounter][1]80assert CoordinateValue <= Maximum , \81'The '+str(CoordinateCounter+1)+'-th entry of the '+str(ValueCounter)+'-th coordinate need to <= '+str(Maximum)+'.'82self._Data = Adjusted_Data838485def __iter__ ( self ) -> Iterator[ tuple[ tuple[ int ] , int ] ] :86"""Returns an iterator of ``self``."""87return ( ( Coordinate , Value ) for Coordinate , Value in self.Data().items() )888990def __le__ ( self , other ) -> bool :91"""Compares Young structures with respect to the <=-operator."""92if self == other : return True93elif self < other : return True94else : return False959697# Synonym for the method `Rank`98def __len__( self ) :99"""Returns the rank ``self``."""100return self.Rank()101102103def __ne__ ( self , other ) -> bool :104return not self == other105106107def __repr__ ( self ) -> tuple[ dict[ tuple[int] : int ] , list[ tuple[ int , int ] ] ] :108"""Returns all attributes which are necessary to initialize the object."""109return self.Data() , self.Ranges()110111112def __str__ ( self ) -> str :113"""Returns a description in terms of diagrams (sliced if necessary)."""114if self.Rank() < 3 :115# Low-dimensional Young structures can be printed.116( xMinimum , xMaximum ) , ( yMinimum , yMaximum ) = self.Ranges() + (2-self.Rank())*[ ( 0 , 0 ) ]117Width = xMaximum-xMinimum+1118Height = yMaximum-yMinimum+1119M = matrix( nrows=Height , ncols=Width )120if 0 in [ yMinimum .. yMaximum ] : ySubdivision = [ abs(yMinimum) ]121else : ySubdivision = None122if 0 in [ xMinimum .. xMaximum ] : xSubdivision = [ abs(xMinimum) ]123else : xSubdivision = None124M.subdivide( ySubdivision , xSubdivision )125for Coordinate , Value in self :126xCoordinate , yCoordinate = Coordinate + tuple( (2-self.Rank())*[ 0 ] )127M[ yCoordinate-yMinimum , xCoordinate-xMinimum ] = Value128return str(M)129130else :131# Slice down to the first two coordinates x and y.132Output = ''133x = self.Coordinates()134Condition_Factors = []135for CoordinateCounter in range( self.Rank()-1 , 1 , -1 ) :136Minimum , Maximum = self.Ranges()[CoordinateCounter]137Condition_Factors += [ [ x[CoordinateCounter] == Entry for Entry in [ Minimum .. Maximum ] ] ]138for Conditions in cartesian_product(Condition_Factors) :139YS = self.Locus( *Conditions )140for CoordinateCounter in range( YS.Rank()-1 , 1 , -1 ) :141YS.Remove_Coordinate(CoordinateCounter)142Output += str( Conditions ) + '\n'143Output += str( YS ) + '\n'144Output += '\n'145146return Output147148149#ToDo: Test if `Permutation` is the correct instance.150def Conjugate ( self , Permutation: "Permutation" ) -> "Young_Structure" :151"""Returns a conjugated Young structure."""152assert len(Permutation) == self.Rank() , \153'The length of the permutation need to coincide with the rank of `self`.'154New_Data = { tuple(Permutation.action(list(Coordinate))) : Value for Coordinate , Value in self }155New_Ranges = Permutation.action(self.Ranges())156return self.__class__( New_Data , New_Ranges )157158159@staticmethod160def Constructor ( *Input:tuple ) -> "Young_Structure" :161162def Get_Empty_Young_Structure ( Ranges :list[ tuple[ int , int ] ] ) -> "Young_Structure" :163Data = { tuple(Coordinate) : 0 for Coordinate in cartesian_product([ [ Minimum .. Maximum ]164for Minimum , Maximum in Ranges165])166}167return Young_Structure( Data , Ranges )168169def Get_Young_Structure_From_Binary_Description ( String :str ) -> "Young_Structure" :170Keep_Running = True171while Keep_Running :172Keep_Running = False173for SubString in [ 'RL' , 'LR' , 'DU' , 'UD' ] :174if String.find(SubString) != -1 :175String = String.replace( SubString , '' )176Keep_Running = True177178xAmplitude = [0]+[ String[:Counter].count('R')-String[:Counter].count('L') for Counter in range(len(String)) ]179xRange = ( min(xAmplitude) , max(xAmplitude)-1 )180if xRange == (0,-1) : xRange = (0,0)181xMinimum , xMaximum = xRange182yAmplitude = [0]+[ String[:Counter].count('D')-String[:Counter].count('U') for Counter in range(len(String)) ]183yRange = ( min(yAmplitude) , max(yAmplitude)-1 )184if yRange == (0,-1) : yRange = (0,0)185yMinimum , yMaximum = yRange186187YS = Get_Empty_Young_Structure( [ xRange , yRange ] )188Data = YS.Data()189Ranges = YS.Ranges()190191xPointer , yPointer = (0,0)192for Letter in String :193if Letter == 'R' :194for yPos in [ yPointer .. yMaximum ] :195Data[ (xPointer,yPos) ] += 1196xPointer += 1197elif Letter == 'L' :198xPointer -= 1199for yPos in [ yPointer .. yMaximum ] :200Data[ (xPointer,yPos) ] -= 1201elif Letter == 'D' :202yPointer += 1203elif Letter == 'U' :204yPointer -= 1205return Young_Structure( Data , Ranges )206207def Get_Young_Structure_From_Integer ( IntegerValue :int ) -> "Young_Structure" :208if IntegerValue == 0 :209Data = dict({})210Ranges = [ ( 0 , 0 ) ]211else :212Minimum = min([ 0 , IntegerValue ])213Maximum = max([ 0 , IntegerValue ])214Data = { (Index,) : 1 for Index in range(Minimum,Maximum) }215Ranges = [ ( Minimum , Maximum-1 ) ]216return Young_Structure( Data , Ranges )217218def Stacking_Young_Structures ( Stack :dict[ int : "Young_Structure" ] ) -> "Young_Structure" :219if 0 < len( Stack.keys() ) :220New_Rank = max([0] + [ New_Slice.Rank() for New_Slice in Stack.values() ]) + 1221New_Data = dict({})222New_Ranges = New_Rank * [ ( +infinity , -infinity ) ]223for New_Coordinate , New_Slice in Stack.items() :224Filling = tuple( (New_Rank-New_Slice.Rank()-1)*[ 0 ])225New_Data.update({ Coordinate + Filling + (New_Coordinate,) : Value for Coordinate , Value in New_Slice })226Adjusted_Ranges = [ ( min([ New_Ranges[RangeCounter][0] , Range[0] ]) , max([ New_Ranges[RangeCounter][1] , Range[1] ]) ) for RangeCounter , Range in enumerate( New_Slice.Ranges() ) ]227New_Ranges = Adjusted_Ranges228New_Ranges += [ ( min(Stack.keys()) , max(Stack.keys()) ) ]229else :230New_Data = dict({})231New_Ranges = []232return Young_Structure( New_Data , New_Ranges )233234if len(Input) == 1 :235Input = Input[0]236if isinstance( Input , Integer ) :237return Get_Young_Structure_From_Integer( Input )238239elif isinstance( Input , ( list , tuple ) ) :240Stack = dict({})241for EntryCounter , Entry in enumerate( Input ) :242assert isinstance( Entry , ( int , Integer ) ) , \243'If the input is given as list or tuple, then the '+str(EntryCounter+1)+'-th entry need to be an integer.'244Stack.update({ EntryCounter : Get_Young_Structure_From_Integer(Entry) })245return Stacking_Young_Structures( Stack )246247elif isinstance( Input , str ) :248Input = Input.upper()249RightCounts = Input.count('R')250LeftCounts = Input.count('L')251DownCounts = Input.count('D')252UpCounts = Input.count('U')253assert len(Input) == sum([ RightCounts , LeftCounts , DownCounts , UpCounts ]) , \254'The only admissible letters in `Input` are R (right), L (left), D (down), and U (up).'255assert RightCounts == LeftCounts , \256'The number of R-letters ('+str(RightCounts)+'x) and L-letters ('+str(LeftCounts)+'x) need to coincide.'257assert DownCounts == UpCounts , \258'The number of D-letters ('+str(DownCounts)+'x) and U-letters ('+str(UpCounts)+'x) need to coincide.'259return Get_Young_Structure_From_Binary_Description( Input )260261elif isinstance( Input , dict ) :262for New_Coordinate , New_Slice in Input.items() :263assert isinstance( New_Coordinate , ( int , Integer ) ) , \264'If the input is a dictionary, then the keys need to be integers.'265assert isinstance( New_Slice , ( Young_Structure ) ) , \266'If the input is a dictionary, then the values need to be Young structures.'267return Stacking_Young_Structures( Input )268269elif isinstance( Input , Young_Structure ) :270return Input271272else :273raise ValueError('The single input is inappropriate.')274275elif len(Input) == 2 :276if Input[0] == 'Empty' :277Ranges = Input[1]278return Get_Empty_Young_Structure( Ranges )279280else :281raise ValueError('The two inputs are inappropriate.')282283else :284raise ValueError('The input is inappropriate.')285286287def Coordinates ( self ) -> "Variables" :288"""Returns the variable coordinates."""289return var([ 'x'+str(Counter) for Counter in range(self.Rank()) ])290291292def Data ( self ) -> dict[ tuple : int ] :293"""Returns the attribute ``_Data``."""294return self._Data295296297def Expand_Ranges ( self , New_Ranges ) -> "Young_Structure" :298"""Returns a Young structure with expanded ranges."""299assert isinstance( New_Ranges , list ) , \300'The input for `New_Ranges` need to be a list.'301assert len(New_Ranges) == self.Rank() , \302'The length of `New_Ranges` need to coincide with the rank of `self`.'303YS = self304for RangeCounter , New_Range in enumerate( New_Ranges ) :305if New_Range == None :306pass307308else :309Old_Minimum , Old_Maximum = YS.Ranges()[RangeCounter]310assert isinstance( New_Range , tuple ) , \311'The '+str(RangeCounter)+'-th entry need to be a tuple.'312assert len(New_Range) == 2 , \313'The '+str(RangeCounter)+'-th range tuple need to be of length 2.'314New_Minimum , New_Maximum = New_Range315assert New_Minimum <= New_Maximum , \316'The new minimum need to be smaller than or equal to the new maximum.'317assert New_Minimum <= Old_Minimum , \318'The new minimum need to be smaller than or equal to the old minimum.'319assert Old_Maximum <= New_Maximum , \320'The old maximum need to be smaller than or equal to the new maximum.'321YS._Ranges[RangeCounter] = New_Range322323return YS324325326def Locus ( self , *Conditions ) -> "Young_Structure" :327"""Returns locus of Young structure with respect to given conditions."""328for ConditionCounter , Condition in enumerate( Conditions , start=1 ) :329assert isinstance( Condition , sage.symbolic.expression.Expression ) , \330'The input for the '+str(ConditionCounter)+'-th condition need to be an symbolic expression.'331x = self.Coordinates()332New_Data = dict({})333for Coordinate , Value in self :334Value_Satisfies_All_Conditions = True335for ConditionCounter , Condition in enumerate( Conditions , start=1 ) :336if bool( Condition({x[CoordinateCounter] : CoordinateEntry for CoordinateCounter , CoordinateEntry in enumerate( Coordinate ) }) ) :337pass338else :339Value_Satisfies_All_Conditions = False340break341if Value_Satisfies_All_Conditions : New_Data.update({ Coordinate : Value })342New_Ranges = self.Ranges()343return self.__class__( New_Data , New_Ranges )344345346def Move_Origin ( self , Steps:list[ int ] ) -> "Young_Structure" :347"""Returns a Young structure with moved origin."""348assert isinstance( Steps , list ) , \349'The input for `Steps` need to be a list.'350assert len(Steps) == self.Rank() , \351'The length of the tuple `Steps` need to coincide with the rank of `self`.'352for StepCounter , Step in enumerate( Steps ) :353assert isinstance( Step , ( int , Integer ) ) , \354'The '+str(StepCounter)+'-th step need to be an integer.'355New_Data = { tuple( vector( ZZ , Coordinate ) + vector( ZZ , Steps ) ) : Value for Coordinate , Value in self }356New_Ranges = [ ( Minimum+Steps[RageCounter] , Maximum+Steps[RageCounter] ) for RageCounter , ( Minimum , Maximum ) in enumerate( self.Ranges() ) ]357return self.__class__( New_Data , New_Ranges )358359360def Ranges ( self ) -> list[ tuple[ int , int ] ] :361"""Returns the attribute ``_Ranges``."""362return self._Ranges363364365def Rank ( self ) -> int :366"""Returns the attribute ``_Rank``."""367return self._Rank368369370def Remove_Coordinate ( self , Index ) -> None :371"""Remove non-varying coordinates."""372assert Index in range(self.Rank()) , \373'The input for `Index` need to be in the range '+str(range(self.Rank()))+'-.'374New_Data = dict({})375for Coordinate , Value in self :376Coordinate = tuple([ CoordinateEntry for CoordinateCounter , CoordinateEntry in enumerate(Coordinate) if CoordinateCounter != Index ])377New_Data.update({ Coordinate : Value })378New_Ranges = [ Range for RangeCounter , Range in enumerate( self.Ranges() ) if RangeCounter != Index ]379self.__init__( New_Data , New_Ranges )380381382def Remove_Vanishing_Values ( self ) -> "Young_Structure" :383"""Returns a Young structure without zero-values."""384return self.__class__( { Coordinate : Value for Coordinate , Value in self if Value != 0 } , self.Ranges() )385386387def Sizes ( self ) -> list[ int ] :388"""Returns the sizes per direction."""389return [ Maximum-Minimum+1 for Minimum , Maximum in self.Ranges() ]390391392def Support ( self , Output_Type :str ='Absolute' ) -> "Young_Structure" :393"Returns the support."394if Output_Type in [ 'Absolute' , 'abs' ] :395Data = { tuple(self.Rank()*[0]) : 0 }396Data.update({ Coordinate : 1 for Coordinate , Value in self if Value != 0 })397return self.__class__( Data , self.Ranges() )398elif Output_Type in [ 'Relative' , 'rel' , 'Sign' , 'sgn' ] :399return self.__class__( { Coordinate : sgn(Value) for Coordinate , Value in self } , self.Ranges() )400else :401raise ValueError('The input for `Output_Type` is inappropriate.')402403404def Volumne ( self ) -> int :405"""Returns the sum of all entries."""406return sum([ Value for Coordinate , Value in self ])407408409# ToDo: NEED TO BE DONE.410def __lt__ ( self , other ) -> bool :411"""Compares Young structures with respect to the <-operator."""412raise ValueError('The method `less-than` is not yet implemented.')413414415#def Compress ( self , Direction :int ) -> "Young_Structure" :416# assert isinstance( Direction , ( int , Integer ) ) , \417# 'The input for `Direction` need to be an integer.'418# assert Direction in range(self.Rank()) , \419# 'The value of `Direction` need to be in the range from 0 to '+str(self.Rank())+'.'420421#def Inflate ( self , Direction :int ) -> "Young_Structure" :422# pass423424425426class Young_Diagram ( Young_Structure ) :427428# Synonym for the method `Twist`429def __call__ ( self , Step :int =0 ) -> "Young_Diagram" :430"""Return a twisted Young diagram."""431return self.Twist( Step )432433434def __init__( self , Data :dict , Ranges :list or None =None ) -> None :435super( Young_Diagram , self ).__init__( Data , Ranges )436437assert self.Rank() == 2 , \438'`self` need to be of rank 2.'439440xRange , yRange = self.Ranges()441xMinimum , xMaximum = xRange442yMinimum , yMaximum = yRange443assert xMinimum == 0 , \444'The x-minimum need to be zero.'445assert yMinimum == 0 , \446'The y-minimum need to be zero.'447448for Coordinate , Value in self :449xCoordinate , yCoordinate = Coordinate450assert Value in [ 0 , 1 ] , \451'The value at coordinate '+str(Coordinate)+' need to be zero or one.'452if 0 < xCoordinate :453assert Value <= self[(xCoordinate-1,yCoordinate)] , \454'The value at '+str((xCoordinate-1,yCoordinate))+' need to be smaller than or equal to the value at '+str((xCoordinate,yCoordinate))+'.'455if 0 < yCoordinate :456assert Value <= self[(xCoordinate,yCoordinate-1)] , \457'The value at '+str((xCoordinate,yCoordinate-1))+' need to be smaller than or equal to the value at '+str((xCoordinate,yCoordinate))+'.'458459460def __lshift__ ( self , Step :int =1 ) -> "Young_Diagram" :461"""Returns a shifted Young diagram (cyclic action)."""462return self >> -1*Step463464465# Synonym for the method `Shift`466def __rshift__ ( self , Step :int =1 ) -> "Young_Diagram" :467"""Returns a shifted Young diagram (cyclic action)."""468return self.Shift( Step )469470471def Binary_Description ( self ) -> str :472Width = self.Width()473xPointer = Width474Height = self.Height()475yPointer = 0476Description = ''477while 0 < xPointer and yPointer < Height :478if self[xPointer,yPointer] < self[xPointer-1,yPointer] :479yPointer += 1480Description += 'D'481else :482xPointer -= 1483Description += 'L'484if 0 < xPointer : Description += xPointer*'L'485if yPointer < Height : Description += (Height-yPointer)*'D'486return Description487488489def Complement ( self ) -> "Young_Diagram" :490"""Returns the complement of `self`."""491Width = self.Width()492Height = self.Height()493return self.__class__.Constructor( [ Width-Entry for Entry in self.Usual_Description()[::-1] ] , (Width,Height) )494495496def Column_Differences ( self ) -> list[int] :497"""Returns the differences s_{i}-s_{i+1} for i running through xRange"""498return self.Conjugate().Row_Differences()499500501def Column_Heights ( self ) -> list[ int ] :502"""Returns the height of each column."""503return self.Conjugate().Row_Widths()504505506def Column_Volumnes ( self ) -> list[ int ] :507"""Returns the volumne of each column."""508return self.Conjugate().Row_Volumnes()509510511def Columns ( self ) -> Iterator[ list[ int ] ] :512"""Returns an iterator running over the columns."""513return self.Conjugate().Rows()514515516def Conjugate ( self ) :517"""Returns the conjugated Young diagram."""518return super( Young_Diagram , self ).Conjugate( Permutation( '(1,2)' ) )519520521@staticmethod522def Constructor ( Description :tuple[ int ] or str , Sizes :tuple[ int , int ] or None =None ) -> "Young_Diagram" :523if Description in [ None , 'Empty' , [] , tuple([]) , dict({}) ] :524MinimumWidth = 0525MinimumHeight = 0526Description = [ 0 ]527528elif isinstance( Description , ( list , tuple ) ) :529MinimumWidth = max([1] + list(Description))530MinimumHeight = len(Description)531Previous_Entry = +infinity532for EntryCounter , Current_Entry in enumerate( Description ) :533assert isinstance( Current_Entry , ( int , Integer ) ) , \534'The '+str(EntryCounter)+'-th entry need to be an integer.'535assert Previous_Entry >= Current_Entry , \536'The '+str(EntryCounter)+'-th entry need to be smaller than or equal to the previous one.'537Previous_Entry = Current_Entry538539elif isinstance( Description , str ) :540if set(Description).issubset({ 'D' , 'L' }) :541MinimumWidth = Description.count('L')542MinimumHeight = Description.count('D')543Description = MinimumWidth*'R' + Description + MinimumHeight*'U'544else :545raise ValueError( 'The input for `Description` is given as string, then its letters must be from the set { D (down) , L (letft) }.' )546547else :548raise ValueError( 'The input for `Description is inappropriate.`' )549550if Sizes == None : Sizes = ( MinimumWidth , MinimumHeight )551Width , Height = Sizes552assert MinimumWidth <= Width , \553'The width need to be => '+str(MinimumWidth)+'.'554assert MinimumHeight <= Height , \555'The height need to be => '+str(MinimumHeight)+'.'556557YS = Young_Structure.Constructor( Description )558YD = Young_Diagram( YS.Data() , YS.Ranges() )559return YD.Expand_Sizes( Width , Height )560561562def Cyclic_Orbit ( self ) -> Iterator[ "Young_Diagram" ] :563"""Runs through the cyclic orbit of `self`."""564First_Object = self565Current_Object = First_Object566while True :567yield Current_Object568Current_Object = Current_Object >> 1569if Current_Object == First_Object : break570571572def Expand_Sizes ( self , New_Width :int , New_Height :int ) -> "Young_Diagram" :573"""Returns a Young diagram with expanded sizes."""574assert isinstance( New_Width , ( int , Integer ) ) , \575'The input for `New_Width` need to be an integer.'576assert self.Width() <= New_Width , \577'The new width need to be greater than or equal to the (old) width.'578assert isinstance( New_Height , ( int , Integer ) ) , \579'The input for `New_Height` need to be an integer.'580assert self.Height() <= New_Height , \581'The new height need to be greater than or equal to the (old) height.'582return self.Expand_Ranges( [ ( 0 , New_Width-1 ) , ( 0 , New_Height-1 ) ] )583584585def Height ( self ) -> int :586"""Returns the size in y-direction."""587return self.Sizes()[1]588589590def Is_Upper_Triangular ( self ) -> bool :591"""Tests if `self` is upper triangular"""592Width = self.Width()593Height = self.Height()594for xPos , Column_Height in enumerate( self.Column_Heights() ) :595if not Column_Height <= floor( Height*(Width-xPos-1) / Width ) : return False596return True597598599def N ( self ) -> int :600"""Returns the sum of width and height."""601return sum(self.Sizes())602603604def Row_Differences ( self ) -> list[int] :605"""Returns the differences s_{i}-s_{i+1} for j running through yRange"""606s = self.Row_Volumnes() + [ 0 ]607return [ s[j]-s[j+1] for j in self.yRange() ]608609610def Row_Widths ( self ) -> list[ int ] :611"""Returns the volumne of each row."""612return [ sum(Row) for Row in self.Support().Rows() ]613614615def Row_Volumnes ( self ) -> list[ int ] :616"""Returns the volumne of each row."""617return [ sum(Row) for Row in self.Rows() ]618619620def Rows ( self ) -> Iterator[ list[ int ] ] :621"""Returns an iterator running over the rows."""622xRange = self.xRange()623yRange = self.yRange()624for yPos in yRange :625yield [ self[xPos,yPos] for xPos in xRange ]626627628def Shift ( self , Step :int =1 ) -> "Young_Diagram" :629"""Returns a shifted Young diagram (cyclic action)."""630assert isinstance( Step , ( int , Integer ) ) , \631'The input for `Step` need to be an integer.'632Step = Step % self.N()633if Step == 0 :634return self635else :636Old_Binary_Description = self.Binary_Description()637New_Binary_Description = Old_Binary_Description[-1] + Old_Binary_Description[ : -1 ]638New_Step = Step-1639return Young_Diagram.Constructor( New_Binary_Description ).Shift(New_Step)640641642def Twist ( self , Step :int =1 ) -> "Young_Diagram" :643"""Returns the Young diagram after a twist-action."""644assert isinstance( Step , ( int , Integer ) ) , \645'The input for `Step` need to be an integer.'646New_YD = Young_Diagram.Constructor( [ Entry+Step for Entry in self.Usual_Description() ] )647New_Width = max([ New_YD.Width() , self.Width() ])648New_Height = max([ New_YD.Height() , self.Height() ])649return New_YD.Expand_Sizes( New_Width , New_Height )650651652# Synonym for the method `Row_Volumnes`.653def Usual_Description ( self ) -> list[ int ] :654"""Returns the usual description of `self`."""655return self.Row_Volumnes()656657658def Width ( self ) -> int :659"""Returns the size in x-direction."""660return self.Sizes()[0]661662663def xRange ( self ) -> list[ int ] :664"""Returns the range in x-direction."""665return [ 0 .. self.Width()-1 ]666667668def yRange ( self ) -> list[ int ] :669"""Returns the range in y-direction."""670return [ 0 .. self.Height()-1 ]671672673@staticmethod674def Lexicographically_Ordered ( Width :int , Height :int ) -> Iterator[ "Young_Diagrams" ] :675assert isinstance( Height , ( int , Integer ) ) , \676'The input for `Height` need to be an integer.'677assert 1 <= Height , \678'The integer Height need to be greater than or equal to 1.'679assert isinstance( Width , ( int , Integer ) ) , \680'The input for `Width` need to be an integer.'681assert 1 <= Width , \682'The integer Width need to be greater than or equal to 1.'683Usual_Descriptions = [ list(Usual_Description) for Usual_Description in IntegerListsLex( max_part=Width , length=Height , max_slope=0 ) ]684Usual_Descriptions.reverse()685for Usual_Description in Usual_Descriptions :686yield Young_Diagram.Constructor( Usual_Description , ( Width , Height ) )687688689@staticmethod690def Upper_Triangulars ( Width :int , Height :int ) -> Iterator[ "Young_Diagrams" ] :691assert isinstance( Height , ( int , Integer ) ) , \692'The input for `Height` need to be an integer.'693assert 1 <= Height , \694'The integer Height need to be greater than or equal to 1.'695assert isinstance( Width , ( int , Integer ) ) , \696'The input for `Width` need to be an integer.'697assert 1 <= Width , \698'The integer Width need to be greater than or equal to 1.'699Ceiling = [ floor( Width*(Height-Counter)/Height ) for Counter in [ 1 .. Height ] ]700Usual_Descriptions = [ list(Usual_Description) for Usual_Description in IntegerListsLex( max_part=Width , length=Height , ceiling=Ceiling , max_slope=0 ) ]701Usual_Descriptions.reverse()702for Usual_Description in Usual_Descriptions :703yield Young_Diagram.Constructor( Usual_Description , ( Width , Height ) )704705706@staticmethod707def Minimal_Upper_Triangulars ( Width :int , Height :int ) -> Iterator[ "Young_Diagrams" ] :708Orbits = []709for YD in Young_Diagram.Upper_Triangulars( Width , Height ) :710YD_Did_Already_Appear = False711for Partial_Orbit in Orbits :712if YD in Partial_Orbit :713YD_Did_Already_Appear = True714break715if not YD_Did_Already_Appear :716Orbit_Length = 0717Partial_Orbit = []718for Fellow in YD.Cyclic_Orbit() :719Orbit_Length += 1720if Fellow.Is_Upper_Triangular() : Partial_Orbit += [ Fellow ]721Orbits += [ Partial_Orbit ]722yield YD , Orbit_Length723724725