K iiQddlmZmZmZmZddlmZddlmZddl m Z ddl m Z ddl mZddlmZmZddlmZmZdd lmZdd lmZGd d eZGd deZddZdZdZdZdZy))BasicDictsympifyTuple)Integerdefault_sort_key)_sympifybell)zeros) FiniteSetUnion)flattengroup)as_int) defaultdictc~eZdZdZdZdZdZd dZedZ dZ dZ dZ d Z ed Zed Zed Zy) Partitionz This class represents an abstract partition. A partition is a set of disjoint sets whose union equals a given set. See Also ======== sympy.utilities.iterables.partitions, sympy.utilities.iterables.multiset_partitions Ncg}d}|D]T}t|tr(t|}t|t|krd}n|}|j t |Vt d|Ds tdt|}|st|td|Dkr tdtj|g|}t||_ t||_|S)aW Generates a new partition object. This method also verifies if the arguments passed are valid and raises a ValueError if they are not. Examples ======== Creating Partition from Python lists: >>> from sympy.combinatorics import Partition >>> a = Partition([1, 2], [3]) >>> a Partition({3}, {1, 2}) >>> a.partition [[1, 2], [3]] >>> len(a) 2 >>> a.members (1, 2, 3) Creating Partition from Python sets: >>> Partition({1, 2, 3}, {4, 5}) Partition({4, 5}, {1, 2, 3}) Creating Partition from SymPy finite sets: >>> from sympy import FiniteSet >>> a = FiniteSet(1, 2, 3) >>> b = FiniteSet(4, 5) >>> Partition(a, b) Partition({4, 5}, {1, 2, 3}) FTc3<K|]}t|tywN) isinstancer).0parts d/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/combinatorics/partitions.py z$Partition.__new__..Ns@4:dI.@sz@Each argument to Partition should be a list, set, or a FiniteSetc32K|]}t|ywr)len)rargs rrz$Partition.__new__..Us9SC9sz'Partition contained duplicate elements.)rlistsetrappendr all ValueErrorrsumr__new__tuplememberssize)cls partitionargsdupsr as_setUobjs rr'zPartition.__new__sH 'C#t$Sv;S)D KK & '@4@@./ / 4L 3q6C9D999FG G+d+Ah q6 c |j}n#tt|jfd}ttt|j ||j fS)aReturn a canonical key that can be used for sorting. Ordering is based on the size and sorted elements of the partition and ties are broken with the rank. Examples ======== >>> from sympy import default_sort_key >>> from sympy.combinatorics import Partition >>> from sympy.abc import x >>> a = Partition([1, 2]) >>> b = Partition([3, 4]) >>> c = Partition([1, x]) >>> d = Partition(list(range(4))) >>> l = [d, b, a + 1, a, c] >>> l.sort(key=default_sort_key); l [Partition({1, 2}), Partition({1}, {2}), Partition({1, x}), Partition({3, 4}), Partition({0, 1, 2, 3})] ct|Srr)worders rz$Partition.sort_key..us+;Au+Er2key)r)r(sortedmapr r*rank)selfr6r)s ` rsort_keyzPartition.sort_key]sQ( =llGF4<>> from sympy.combinatorics import Partition >>> Partition([1], [2, 3]).partition [[1], [2, 3]] r8) _partitionr:r-r )r=ps rr,zPartition.partitionxsK ?? "$/3yy&:*+'-Q4D&E&:;DO&:sAct|}|j|z}t|t|jz|j}t j ||jS)ai Return permutation whose rank is ``other`` greater than current rank, (mod the maximum rank for the set). Examples ======== >>> from sympy.combinatorics import Partition >>> a = Partition([1, 2], [3]) >>> a.rank 1 >>> (a + 1).rank 2 >>> (a + 100).rank 1 )rr< RGS_unrankRGS_enumr*rfrom_rgsr))r=otheroffsetresults r__add__zPartition.__add__sX"u U"V$TYY/0 II'!!&$,,77r2c&|j| S)af Return permutation whose rank is ``other`` less than current rank, (mod the maximum rank for the set). Examples ======== >>> from sympy.combinatorics import Partition >>> a = Partition([1, 2], [3]) >>> a.rank 1 >>> (a - 1).rank 0 >>> (a - 100).rank 1 )rIr=rFs r__sub__zPartition.__sub__s"||UF##r2cV|jt|jkS)a Checks if a partition is less than or equal to the other based on rank. Examples ======== >>> from sympy.combinatorics import Partition >>> a = Partition([1, 2], [3, 4, 5]) >>> b = Partition([1], [2, 3], [4], [5]) >>> a.rank, b.rank (9, 34) >>> a <= a True >>> a <= b True r>rrKs r__le__zPartition.__le__s"$}}'%."9"9";;;r2cV|jt|jkS)aA Checks if a partition is less than the other. Examples ======== >>> from sympy.combinatorics import Partition >>> a = Partition([1, 2], [3, 4, 5]) >>> b = Partition([1], [2, 3], [4], [5]) >>> a.rank, b.rank (9, 34) >>> a < b True rNrKs r__lt__zPartition.__lt__s"}}!8!8!:::r2c~|j |jSt|j|_|jS)z Gets the rank of a partition. Examples ======== >>> from sympy.combinatorics import Partition >>> a = Partition([1, 2], [3], [4, 5]) >>> a.rank 13 )_rankRGS_rankRGSr=s rr<zPartition.ranks2 :: !:: dhh' zzr2c i}|j}t|D]\}}|D]}|||< tt|Dcgc] }|D]}| c}}tDcgc]}|| c}Scc}}wcc}w)a Returns the "restricted growth string" of the partition. Explanation =========== The RGS is returned as a list of indices, L, where L[i] indicates the block in which element i appears. For example, in a partition of 3 elements (a, b, c) into 2 blocks ([c], [a, b]) the RGS is [1, 1, 0]: "a" is in block 1, "b" is in block 1 and "c" is in block 0. Examples ======== >>> from sympy.combinatorics import Partition >>> a = Partition([1, 2], [3], [4, 5]) >>> a.members (1, 2, 3, 4, 5) >>> a.RGS (0, 0, 1, 2, 2) >>> a + 1 Partition({3}, {4}, {5}, {1, 2}) >>> _.RGS (0, 0, 1, 2, 3) r8)r, enumerater(r:r )r=rgsr,irjrAs rrUz Partition.RGSs6NN  + GAt A  f! -11 -aQ -Q -3C'EFc!fFG G -Fs A0 A6c0t|t|k7r tdt|dz}t|Dcgc]}g}}d}|D]}||j |||dz } t d|Ds tdt |Scc}w)aB Creates a set partition from a restricted growth string. Explanation =========== The indices given in rgs are assumed to be the index of the element as given in elements *as provided* (the elements are not sorted by this routine). Block numbering starts from 0. If any block was not referenced in ``rgs`` an error will be raised. Examples ======== >>> from sympy.combinatorics import Partition >>> Partition.from_rgs([0, 1, 2, 0, 1], list('abcde')) Partition({c}, {a, d}, {b, e}) >>> Partition.from_rgs([0, 1, 2, 0, 1], list('cbead')) Partition({e}, {a, c}, {b, d}) >>> a = Partition([1, 4], [2], [3, 5]) >>> Partition.from_rgs(a.RGS, a.members) Partition({2}, {1, 4}, {3, 5}) z#mismatch in rgs and element lengthsrc3 K|]}|ywr)rrAs rrz%Partition.from_rgs../s(1(s z(some blocks of the partition were empty.)rr%maxranger#r$r)r=rYelementsmax_elemrZr,r[s rrEzPartition.from_rgs s4 s8s8} $BC Cs8a<!&x1AR1 1  A aL   , FA (i((GH H)$$2s Br)__name__ __module__ __qualname____doc__rSr@r'r>propertyr,rIrLrOrQr<rU classmethodrEr_r2rrrs  EJ<|M6  80$&<(;"" G GD#%#%r2rc\eZdZdZdZdZd dZdZdZdZ e dZ dZ d Z d d Zd Zy)IntegerPartitionaZ This class represents an integer partition. Explanation =========== In number theory and combinatorics, a partition of a positive integer, ``n``, also called an integer partition, is a way of writing ``n`` as a list of positive integers that sum to n. Two partitions that differ only in the order of summands are considered to be the same partition; if order matters then the partitions are referred to as compositions. For example, 4 has five partitions: [4], [3, 1], [2, 2], [2, 1, 1], and [1, 1, 1, 1]; the compositions [1, 2, 1] and [1, 1, 2] are the same as partition [2, 1, 1]. See Also ======== sympy.utilities.iterables.partitions, sympy.utilities.iterables.multiset_partitions References ========== .. [1] https://en.wikipedia.org/wiki/Partition_%28number_theory%29 Ncn|||}}t|ttfr_g}t|j dD]3\}}|s t |t |}}|j |g|z5t|}n$tttt |d}d}|t|}d}n t |}|st||k7rtd|ztd|Dr tdtj|t|t|}t!||_||_|S)a Generates a new IntegerPartition object from a list or dictionary. Explanation =========== The partition can be given as a list of positive integers or a dictionary of (integer, multiplicity) items. If the partition is preceded by an integer an error will be raised if the partition does not sum to that given integer. Examples ======== >>> from sympy.combinatorics.partitions import IntegerPartition >>> a = IntegerPartition([5, 4, 3, 1, 1]) >>> a IntegerPartition(14, (5, 4, 3, 1, 1)) >>> print(a) [5, 4, 3, 1, 1] >>> IntegerPartition({1:3, 2:1}) IntegerPartition(5, (2, 1, 1, 1)) If the value that the partition should sum to is given first, a check will be made to see n error will be raised if there is a discrepancy: >>> IntegerPartition(10, [5, 4, 3, 1]) Traceback (most recent call last): ... ValueError: The partition is not valid TreverseFzPartition did not add to %sc3&K|] }|dk yw)r]Nr_)rrZs rrz+IntegerPartition.__new__..s(q1u(sz-All integer summands must be greater than one)rdictrr:itemsrextendr(r;r&r%anyrr'rrr!r,integer)r+r,rt_kvsum_okr1s rr'zIntegerPartition.__new__Ss B  !*GYG i$ .Ay0$? 1ay&)1!Q  aIfS%;TJKI ?)nGFWoG#i.G3:WDE E (i( (LM MmmC!15)3DEY   r2ctt}|j|j|j}|dgk(rt |j diS|ddk7r/||dxxdzcc<|ddk(rd|d<ncdx||ddz <|d<nR||dxxdzcc<|d|dz}|d}d|d<|r+|dz}||z dk\r||xx||zz cc<||||zz}|r+t |j |S)aReturn the previous partition of the integer, n, in lexical order, wrapping around to [1, ..., 1] if the partition is [n]. Examples ======== >>> from sympy.combinatorics.partitions import IntegerPartition >>> p = IntegerPartition([4]) >>> print(p.prev_lex()) [3, 1] >>> p.partition > p.prev_lex().partition True r]r)rintupdateas_dict_keysrkrt)r=dkeysleftnews rprev_lexzIntegerPartition.prev_lexs    zz A3;#T\\1$56 6 8q= d2hK1 KBx1}!)**$r(Q,!A$ d2hK1 KQ4$r(?Dr(CAaDq#:?cFdCi'FAcF3J&D    a00r2ctt}|j|j|j}|d}||j k(r |j |j |d<n|dk(rO||dkDr||dzxxdz cc<||xxdzcc<n|d}||dzxxdz cc<||dz |z|d<d||<n||dkDrbt|dk(r.|j d||dz<|j |z dz |d<n`|dz}||xxdz cc<|||z|z |d<d||<n:|d}|dz}||xxdz cc<|||z|||zz|z }dx||<||<||d<t|j |S)aReturn the next partition of the integer, n, in lexical order, wrapping around to [n] if the partition is [1, ..., 1]. Examples ======== >>> from sympy.combinatorics.partitions import IntegerPartition >>> p = IntegerPartition([3, 1]) >>> print(p.next_lex()) [4] >>> p.partition < p.next_lex().partition True rzr]r{r|r) rr}r~rrrtclearrrk)r=rr9aba1b1needs rnext_lexzIntegerPartition.next_lexs    jj G   GGI<>> from sympy.combinatorics.partitions import IntegerPartition >>> IntegerPartition([1]*3 + [2] + [3]*4).as_dict() {1: 3, 2: 1, 3: 4} F)multipler)_dictrr,rrp)r=groupsgs rrzIntegerPartition.as_dictsN :: 4>>E:F(./1!A$/DJfDJzz0s Acd}t|jdgz}|d}dg|z}|dkDr)|||kDr|||dz <|dz}|||kDr|dz }|dkDr)|S)a Computes the conjugate partition of itself. Examples ======== >>> from sympy.combinatorics.partitions import IntegerPartition >>> a = IntegerPartition([6, 3, 3, 2, 1]) >>> a.conjugate [5, 4, 3, 1, 1, 1] r]r)r!r,)r=r[temp_arrrvrs r conjugatezIntegerPartition.conjugates '1#- QK CE!ehqk/!a%Qhqk/ FA !e r2c|tt|jtt|jkS)aReturn True if self is less than other when the partition is listed from smallest to biggest. Examples ======== >>> from sympy.combinatorics.partitions import IntegerPartition >>> a = IntegerPartition([3, 1]) >>> a < a False >>> b = a.next_lex() >>> a < b True >>> a == b False r!reversedr,rKs rrQzIntegerPartition.__lt__s+"HT^^,-Xeoo5N0OOOr2c|tt|jtt|jkS)a Return True if self is less than other when the partition is listed from smallest to biggest. Examples ======== >>> from sympy.combinatorics.partitions import IntegerPartition >>> a = IntegerPartition([4]) >>> a <= a True rrKs rrOzIntegerPartition.__le__%s+HT^^,-hu6O1PPPr2cddj|jDcgc]}||z c}Scc}w)a Prints the ferrer diagram of a partition. Examples ======== >>> from sympy.combinatorics.partitions import IntegerPartition >>> print(IntegerPartition([1, 1, 5]).as_ferrers()) ##### # #  )joinr,)r=charrZs r as_ferrerszIntegerPartition.as_ferrers3s)yy$..9Q$q&9::9s -c>tt|jSr)strr!r,rVs r__str__zIntegerPartition.__str__Bs4'((r2r)#)rdrerfrgrrr'rrrrhrrQrOrrr_r2rrkrk4sT6 E E<|#1J01d$.P& Q ;)r2rkNcFddlm}t|}|dkr td||}g}|dkDr6|d|}|d||z}|j ||f|||zz}|dkDr6|j dt |Dcgc] \}}|g|z c}}}|Scc}}w)a Generates a random integer partition summing to ``n`` as a list of reverse-sorted integers. Examples ======== >>> from sympy.combinatorics.partitions import random_integer_partition For the following, a seed is given so a known value can be shown; in practice, the seed would not be given. >>> random_integer_partition(100, seed=[1, 1, 12, 1, 2, 1, 85, 1]) [85, 12, 2, 1] >>> random_integer_partition(10, seed=[1, 2, 3, 1, 5, 1]) [5, 3, 1, 1] >>> random_integer_partition(1) [1] r)_randintr]zn must be a positive integerTrm)sympy.core.randomrrr%r#sortr)nseedrrandintr,rvmultms rrandom_integer_partitionrFs(+q A1u788tnGI q5 AqMq!Q$!T# QtV  q5 NN4N 9541a!Q56I 6sB ct|dz}t|dzD] }d|d|f< td|dzD]B}t|D]2}|||z kr!|||dz |fz||dz |dzfz|||f<,d|||f<4D|S)a Computes the m + 1 generalized unrestricted growth strings and returns them as rows in matrix. Examples ======== >>> from sympy.combinatorics.partitions import RGS_generalized >>> RGS_generalized(6) Matrix([ [ 1, 1, 1, 1, 1, 1, 1], [ 1, 2, 3, 4, 5, 6, 0], [ 2, 5, 10, 17, 26, 0, 0], [ 5, 15, 37, 77, 0, 0, 0], [ 15, 52, 151, 0, 0, 0, 0], [ 52, 203, 0, 0, 0, 0, 0], [203, 0, 0, 0, 0, 0, 0]]) r]r)r ra)rrrZr[s rRGS_generalizedrms& a!e A 1q5\!Q$1a!e_q AAEzaAqk/Aa!eQUlO;!Q$!Q$   Hr2c0|dkry|dk(ryt|S)a} RGS_enum computes the total number of restricted growth strings possible for a superset of size m. Examples ======== >>> from sympy.combinatorics.partitions import RGS_enum >>> from sympy.combinatorics import Partition >>> RGS_enum(4) 15 >>> RGS_enum(5) 52 >>> RGS_enum(6) 203 We can check that the enumeration is correct by actually generating the partitions. Here, the 15 partitions of 4 items are generated: >>> a = Partition(list(range(4))) >>> s = set() >>> for i in range(20): ... s.add(a) ... a += 1 ... >>> assert len(s) == 15 r]rr )rs rrDrDs!: A q&Awr2ch|dkr td|dkst||kr tddg|dzz}d}t|}td|dzD]B}|||z |f}||z}||kr|dz||<||z}|dz }*t ||z dz||<||z}D|ddDcgc]}|dz  c}Scc}w)a Gives the unranked restricted growth string for a given superset size. Examples ======== >>> from sympy.combinatorics.partitions import RGS_unrank >>> RGS_unrank(14, 4) [0, 1, 2, 3] >>> RGS_unrank(0, 4) [0, 0, 0, 0] r]zThe superset size must be >= 1rzInvalid argumentsr{N)r%rDrrar}) r<rLr[DrZrwcrxs rrCrCs 1u9:: ax8A;$&,-- q1u A AA 1a!e_  a!eQhK qS :q5AaD BJD FAtax!|$AaD AID QR5 !aAE !! !s B/ct|}d}t|}td|D]4}t||dzd}t|d|}||||dzf||zz }6|S)z Computes the rank of a restricted growth string. Examples ======== >>> from sympy.combinatorics.partitions import RGS_rank, RGS_unrank >>> RGS_rank([0, 1, 2, 1, 3]) 42 >>> RGS_rank(RGS_unrank(4, 7)) 4 rr]N)rrrar`)rYrgs_sizer<rrZrrs rrTrTs{3xH D!A 1h % QUH  AaM !QU( c!f$$% Kr2r) sympy.corerrrrsympy.core.numbersrsympy.core.sortingr sympy.core.sympifyr %sympy.functions.combinatorial.numbersr sympy.matricesr sympy.sets.setsrrsympy.utilities.iterablesrrsympy.utilities.miscr collectionsrrrkrrrDrCrTr_r2rrsc22&/'6 ,4'$b% b%J O)uO)d$N @"J "Fr2