
    \hiQ                         S SK JrJrJrJr  S SKJr  S SKJr  S SK	J
r
  S SKJr  S SKJr  S SKJrJr  S SKJrJr  S S	KJr  S S
KJr   " S S\5      r " S S\5      rSS jrS rS rS rS rg)    )BasicDictsympifyTuple)Integerdefault_sort_key)_sympifybell)zeros)	FiniteSetUnion)flattengroup)as_int)defaultdictc                       \ rS rSrSrSrSrS rSS jr\	S 5       r
S rS rS	 rS
 r\	S 5       r\	S 5       r\S 5       rSrg)	Partition   z
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
Nc                    / nSnU H[  n[        U[        5      (       a)  [        U5      n[        U5      [        U5      :  a  Sn  O UnUR	                  [        U5      5        M]     [        S U 5       5      (       d  [        S5      e[        U6 nU(       d  [        U5      [        S U 5       5      :  a  [        S5      e[        R                  " U /UQ76 n[        U5      Ul        [        U5      Ul        U$ )a  
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})
FTc              3   B   #    U  H  n[        U[        5      v   M     g 7fN)
isinstancer   ).0parts     V/var/www/auris/envauris/lib/python3.13/site-packages/sympy/combinatorics/partitions.py	<genexpr>$Partition.__new__.<locals>.<genexpr>N   s     @44:dI..4s   z@Each argument to Partition should be a list, set, or a FiniteSetc              3   8   #    U  H  n[        U5      v   M     g 7fr   )len)r   args     r   r   r   U   s     9DSCDs   z'Partition contained duplicate elements.)r   listsetr!   appendr
   all
ValueErrorr   sumr   __new__tuplememberssize)cls	partitionargsdupsr"   as_setUobjs           r   r)   Partition.__new__   s    H C#t$$Sv;S)DKK&  @4@@@./ /
 4L3q6C9D999FGG+d+Ahq6
    c                    ^ Tc  U R                   nO![        [        U R                   U4S jS95      n[        [        [        U R
                  X R                  45      5      $ )a9  Return 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})]
c                    > [        U T5      $ r   r   )worders    r   <lambda>$Partition.sort_key.<locals>.<lambda>u   s    +;Au+Er5   key)r+   r*   sortedmapr	   r,   rank)selfr9   r+   s    ` r   sort_keyPartition.sort_key]   sO    ( =llGF4<<!EG HGS)DIIw		+JKLLr5   c           
          U R                   c7  [        U R                   Vs/ s H  n[        U[        S9PM     sn5      U l         U R                   $ s  snf )zReturn partition as a sorted list of lists.

Examples
========

>>> from sympy.combinatorics import Partition
>>> Partition([1], [2, 3]).partition
[[1], [2, 3]]
r<   )
_partitionr>   r/   r	   )rA   ps     r   r.   Partition.partitionx   sP     ??"$/3yy&:/8! '-Q4D&E/8&: ;DO&:s   Ac                     [        U5      nU R                  U-   n[        U[        U R                  5      -  U R                  5      n[
        R                  X0R                  5      $ )a  
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
)r   r@   
RGS_unrankRGS_enumr,   r   from_rgsr+   )rA   otheroffsetresults       r   __add__Partition.__add__   sV    " uU"V$TYY/0 II' !!&,,77r5   c                 &    U R                  U* 5      $ )z
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
)rO   rA   rL   s     r   __sub__Partition.__sub__   s    " ||UF##r5   c                 V    U R                  5       [        U5      R                  5       :*  $ )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
rB   r   rR   s     r   __le__Partition.__le__   s"    $ }}'%."9"9";;;r5   c                 V    U R                  5       [        U5      R                  5       :  $ )z
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
rV   rR   s     r   __lt__Partition.__lt__   s"     }}!8!8!:::r5   c                     U R                   b  U R                   $ [        U R                  5      U l         U R                   $ )z
Gets the rank of a partition.

Examples
========

>>> from sympy.combinatorics import Partition
>>> a = Partition([1, 2], [3], [4, 5])
>>> a.rank
13
)_rankRGS_rankRGSrA   s    r   r@   Partition.rank   s2     ::!::dhh'
zzr5   c           
          0 nU R                   n[        U5       H  u  p4U H  nX1U'   M	     M     [        [        U VVs/ s H  of  H  o3PM     M     snn[        S9 Vs/ s H  o1U   PM	     sn5      $ s  snnf s  snf )aD  
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)
r<   )r.   	enumerater*   r>   r	   )rA   rgsr.   ir   jrF   s          r   r_   Partition.RGS   s    6 NN	 +GAA  , f!-	11aQ1Q	-3C'E F 'E!f 'E F G 	G-Fs   A5 A;c                 B   [        U5      [        U5      :w  a  [        S5      e[        U5      S-   n[        U5       Vs/ s H  n/ PM     nnSnU H  nXT   R	                  X&   5        US-  nM     [        S U 5       5      (       d  [        S5      e[        U6 $ s  snf )a  
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 lengths   r   c              3   $   #    U  H  ov   M     g 7fr    )r   rF   s     r   r   %Partition.from_rgs.<locals>.<genexpr>/  s     (i1is   z(some blocks of the partition were empty.)r!   r'   maxranger%   r&   r   )rA   rd   elementsmax_elemre   r.   rf   s          r   rK   Partition.from_rgs  s    4 s8s8}$BCCs8a<!&x1AR	1AL,FA  (i(((GHH)$$ 2s   B)rE   r]   r   )__name__
__module____qualname____firstlineno____doc__r]   rE   r)   rB   propertyr.   rO   rS   rW   rZ   r@   r_   classmethodrK   __static_attributes__rk   r5   r   r   r      s    
 EJ<|M6  80$&<(;"  "  G  GD #% #%r5   r   c                   h    \ rS rSrSrSrSrSS jrS rS r	S r
\S 5       rS	 rS
 rSS jrS rSrg)IntegerPartitioni4  a  
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
Nc                    Ub  Xp[        U[        [        45      (       ab  / n[        UR	                  5       SS9 H8  u  pEU(       d  M  [        U5      [        U5      pTUR                  U/U-  5        M:     [        U5      nO![        [        [        [
        U5      SS95      nSnUc  [        U5      nSnO[        U5      nU(       d  [        U5      U:w  a  [        SU-  5      e[        S U 5       5      (       a  [        S5      e[        R                  " U [        U5      [        U6 5      n[!        U5      Ul        X'l        U$ )aP  
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

TreverseFzPartition did not add to %sc              3   *   #    U  H	  oS :  v   M     g7f)ri   Nrk   )r   re   s     r   r   +IntegerPartition.__new__.<locals>.<genexpr>  s     (i1uis   z-All integer summands must be greater than one)r   dictr   r>   itemsr   extendr*   r?   r(   r'   anyr   r)   r   r   r#   r.   integer)r-   r.   r   _kvsum_okr3   s           r   r)   IntegerPartition.__new__S  s   B !*Yi$..Ay0$?ay&)1!Q	 @
 aIfS%;TJKI?)nGFWoG#i.G3:WDEE(i(((LMMmmC!15)3DEY
r5   c                    [        [        5      nUR                  U R                  5       5        U R                  nUS/:X  a  [        U R                  S05      $ US   S:w  a.  XS   ==   S-  ss'   US   S:X  a  SUS'   OiS=XS   S-
  '   US'   OYXS   ==   S-  ss'   US   US   -   nUS   nSUS'   U(       a.  US-  nX4-
  S:  a  X==   X4-  -  ss'   X1U   U-  -  nU(       a  M.  [        U R                  U5      $ )a:  Return 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
ri      r   )r   intupdateas_dict_keysr{   r   )rA   dkeysleftnews        r   prev_lexIntegerPartition.prev_lex  s    	 zzA3;#T\\1$5668q=2hK1KBx1}!)**r(Q,!A$2hK1KQ4$r(?Dr(CAaDq:?Fdi'FcF3J&D	 $
  a00r5   c                    [        [        5      nUR                  U R                  5       5        U R                  nUS   nX0R
                  :X  a   UR                  5         U R
                  US'   OUS:X  aJ  X   S:  a  XS-   ==   S-  ss'   X==   S-  ss'   OUS   nXS-   ==   S-  ss'   X   S-
  U-  US'   SX'   OX   S:  a_  [        U5      S:X  a-  UR                  5         SXS-   '   U R
                  U-
  S-
  US'   OWUS-   nX==   S-  ss'   X   U-  U-
  US'   SX'   O4US   nUS-   nX==   S-  ss'   X   U-  X   U-  -   U-
  nS=X'   X'   XqS'   [        U R
                  U5      $ )a6  Return 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
r   ri   r   r   r   )	r   r   r   r   r   r   clearr!   r{   )rA   r   r=   aba1b1needs           r   next_lexIntegerPartition.next_lex  sw    	 jjGGGI<<AaD!Vtaxa%A	Ga%Aq!|!taxs8q=GGI A!eH<<!+a/AaDQBEQJE46B;AaDADGU
tAvQ+qt!a00r5   c                     U R                   c>  [        U R                  SS9nU Vs/ s H  o"S   PM	     snU l        [	        U5      U l         U R                   $ s  snf )a  Return the partition as a dictionary whose keys are the
partition integers and the values are the multiplicity of that
integer.

Examples
========

>>> from sympy.combinatorics.partitions import IntegerPartition
>>> IntegerPartition([1]*3 + [2] + [3]*4).as_dict()
{1: 3, 2: 1, 3: 4}
F)multipler   )_dictr   r.   r   r   )rA   groupsgs      r   r   IntegerPartition.as_dict  sP     ::4>>E:F(./1A$/DJfDJzz 0s   Ac                     Sn[        U R                  5      S/-   nUS   nS/U-  nUS:  a+  X2U   :  a  XUS-
  '   US-  nX2U   :  a  M  US-  nUS:  a  M+  U$ )z
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]
ri   r   )r#   r.   )rA   rf   temp_arrr   r   s        r   	conjugateIntegerPartition.conjugate  s|     '1#-QKCE!eqk/!a%Q qk/ FA	 !e
 r5   c                 |    [        [        U R                  5      5      [        [        UR                  5      5      :  $ )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([3, 1])
>>> a < a
False
>>> b = a.next_lex()
>>> a < b
True
>>> a == b
False
r#   reversedr.   rR   s     r   rZ   IntegerPartition.__lt__  s+    " HT^^,-Xeoo5N0OOOr5   c                 |    [        [        U R                  5      5      [        [        UR                  5      5      :*  $ )zReturn 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
r   rR   s     r   rW   IntegerPartition.__le__%  s+     HT^^,-hu6O1PPPr5   c                 h    SR                  U R                   Vs/ s H  o!U-  PM	     sn5      $ s  snf )z
Prints the ferrer diagram of a partition.

Examples
========

>>> from sympy.combinatorics.partitions import IntegerPartition
>>> print(IntegerPartition([1, 1, 5]).as_ferrers())
#####
#
#

)joinr.   )rA   charre   s      r   
as_ferrersIntegerPartition.as_ferrers3  s+     yy$..9.Qq&.9::9s   /c                 >    [        [        U R                  5      5      $ r   )strr#   r.   r`   s    r   __str__IntegerPartition.__str__B  s    4'((r5   )r   r   r   )#)rr   rs   rt   ru   rv   r   r   r)   r   r   r   rw   r   rZ   rW   r   r   ry   rk   r5   r   r{   r{   4  sT    6 EE<|#1J01d$  .P&Q;)r5   r{   Nc                 F   SSK Jn  [        U 5      n U S:  a  [        S5      eU" U5      n/ nU S:  a5  U" SU 5      nU" SX-  5      nUR	                  XV45        XU-  -  n U S:  a  M5  UR                  SS9  [        U VVs/ s H  u  pWU/U-  PM     snn5      nU$ s  snnf )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   )_randintri   zn must be a positive integerTr}   )sympy.core.randomr   r   r'   r%   sortr   )nseedr   randintr.   r   multms           r   random_integer_partitionr   F  s    ( +q	A1u788tnGIq5AqMq!$!#	tV	 q5
 NN4N 95941!Q956I 6s   B
c                    [        U S-   5      n[        U S-   5       H
  nSUSU4'   M     [        SU S-   5       HB  n[        U 5       H0  nX0U-
  ::  a  X1US-
  U4   -  XS-
  US-   4   -   XU4'   M*  SXU4'   M2     MD     U$ )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]])
ri   r   )r   rn   )r   r   re   rf   s       r   RGS_generalizedr   m  s    & 	a!eA1q5\!Q$  1a!e_qAEzAqk/A!eQUlO;Q$Q$	   Hr5   c                 4    U S:  a  gU S:X  a  g[        U 5      $ )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

ri   r   r   )r   s    r   rJ   rJ     s!    : 	
A
q&Awr5   c                 j   US:  a  [        S5      eU S:  d  [        U5      U ::  a  [        S5      eS/US-   -  nSn[        U5      n[        SUS-   5       H=  nXAU-
  U4   nX6-  nXp::  a  US-   X%'   X-  n US-  nM'  [	        X-  S-   5      X%'   X-  n M?     USS  Vs/ s H  oS-
  PM	     sn$ s  snf )z
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]
ri   zThe superset size must be >= 1r   zInvalid argumentsr   N)r'   rJ   r   rn   r   )	r@   r   Lrf   Dre   r   crxs	            r   rI   rI     s     	1u9::ax8A;$&,--	
q1uA	AA1a!e_!eQhKS:q5ADJDFAtx!|$ADID  QR5!5aE5!!!s   B0c                     [        U 5      nSn[        U5      n[        SU5       H1  n[        XS-   S 5      n[        U SU 5      nX#XVS-   4   X   -  -  nM3     U$ )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
r   ri   N)r!   r   rn   rm   )rd   rgs_sizer@   r   re   r   r   s          r   r^   r^     sn     3xHD!A1hUHAaM!U(cf$$   Kr5   r   ) 
sympy.corer   r   r   r   sympy.core.numbersr   sympy.core.sortingr	   sympy.core.sympifyr
   %sympy.functions.combinatorial.numbersr   sympy.matricesr   sympy.sets.setsr   r   sympy.utilities.iterablesr   r   sympy.utilities.miscr   collectionsr   r   r{   r   r   rJ   rI   r^   rk   r5   r   <module>r      sc    2 2 & / ' 6   , 4 ' $b%	 b%J	O)u O)d$N@"J "Fr5   