
    wgiQ                         d dl mZmZmZmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZ d dlmZmZ d dlmZmZ d d	lmZ d d
lmZ  G d de      Z G d de      ZddZd Zd Zd Zd Zy)    )BasicDictsympifyTuple)Integerdefault_sort_key)_sympifybell)zeros)	FiniteSetUnion)flattengroup)as_int)defaultdictc                   ~    e Zd ZdZdZdZd ZddZed        Z	d Z
d Zd Zd	 Zed
        Zed        Zed        Zy)	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
    Nc                    g }d}|D ]T  }t        |t              r(t        |      }t        |      t        |      k  rd} n|}|j	                  t        |             V t        d |D              st        d      t        | }|st        |      t        d |D              k  rt        d      t        j                  | 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})
        FTc              3   <   K   | ]  }t        |t                y wN)
isinstancer   ).0parts     c/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/sympy/combinatorics/partitions.py	<genexpr>z$Partition.__new__.<locals>.<genexpr>N   s     @4:dI.@s   z@Each argument to Partition should be a list, set, or a FiniteSetc              3   2   K   | ]  }t        |        y wr   )len)r   args     r   r   z$Partition.__new__.<locals>.<genexpr>U   s     9SC9s   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'   z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                     | j                   }n#t        t        | j                   fd            }t        t        t        | j
                  || j                  f            S )a  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                     t        |       S r   r   )worders    r   <lambda>z$Partition.sort_key.<locals>.<lambda>u   s    +;Au+E r2   key)r)   r(   sortedmapr	   r*   rank)selfr6   r)   s    ` r   sort_keyzPartition.sort_key]   sQ    ( =llGF4<<!EG HGS)DIIw		+JKLLr2   c           	          | j                   7t        | j                  D cg c]  }t        |t               c}      | _         | j                   S c c}w )zReturn partition as a sorted list of lists.

        Examples
        ========

        >>> from sympy.combinatorics import Partition
        >>> Partition([1], [2, 3]).partition
        [[1], [2, 3]]
        r8   )
_partitionr:   r-   r	   )r=   ps     r   r,   zPartition.partitionx   sK     ??"$/3yy&:*+ '-Q4D&E &: ;DO&:s   Ac                     t        |      }| j                  |z   }t        |t        | j                        z  | j                        }t
        j                  || j                        S )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
        )r   r<   
RGS_unrankRGS_enumr*   r   from_rgsr)   )r=   otheroffsetresults       r   __add__zPartition.__add__   sX    " uU"V$TYY/0 II' !!&$,,77r2   c                 &    | 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
        )rI   r=   rF   s     r   __sub__zPartition.__sub__   s    " ||UF##r2   c                 V    | j                         t        |      j                         k  S )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>   r   rK   s     r   __le__zPartition.__le__   s"    $ }}'%."9"9";;;r2   c                 V    | j                         t        |      j                         k  S )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
        rN   rK   s     r   __lt__zPartition.__lt__   s"     }}!8!8!:::r2   c                 ~    | j                   | j                   S t        | j                        | _         | j                   S )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r=   s    r   r<   zPartition.rank   s2     ::!::dhh'
zzr2   c           
          i }| j                   }t        |      D ]  \  }}|D ]  }|||<   	  t        t        |D cg c]  }|D ]  }|  c}}t              D cg c]  }||   	 c}      S c c}}w c c}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,   ir   jrA   s          r   rU   zPartition.RGS   s    6 NN	 + 	GAt A	 f!-11-aQ-Q-3C'E Fc!f F G 	G-Fs   A0A6c                 0   t        |      t        |      k7  rt        d      t        |      dz   }t        |      D cg c]  }g  }}d}|D ]  }||   j	                  ||          |dz  }  t        d |D              st        d      t        | S c c}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 lengths   r   c              3       K   | ]  }|  y wr    )r   rA   s     r   r   z%Partition.from_rgs.<locals>.<genexpr>/  s     (1(s   z(some blocks of the partition were empty.)r   r%   maxranger#   r$   r   )r=   rY   elementsmax_elemrZ   r,   r[   s          r   rE   zPartition.from_rgs  s    4 s8s8}$BCCs8a<!&x1AR1	1 	AaL,FA	 (i((GHH)$$ 2s   	Br   )__name__
__module____qualname____doc__rS   r@   r'   r>   propertyr,   rI   rL   rO   rQ   r<   rU   classmethodrE   r_   r2   r   r   r      s    
 EJ<|M6  80$&<(;"  "  G  GD #% #%r2   r   c                   \    e Zd ZdZdZdZddZd Zd Zd Z	e
d        Zd Zd	 Zdd
Zd Zy)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
    Nc                 n   |||}}t        |t        t        f      r_g }t        |j	                         d      D ]3  \  }}|s	t        |      t        |      }}|j                  |g|z         5 t        |      }n$t        t        t        t
        |      d            }d}|t        |      }d}nt        |      }|st        |      |k7  rt        d|z        t        d |D              rt        d      t        j                  | 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

        TreverseFzPartition did not add to %sc              3   &   K   | ]	  }|d k    yw)r]   Nr_   )r   rZ   s     r   r   z+IntegerPartition.__new__.<locals>.<genexpr>  s     (q1u(s   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,   rt   _kvsum_okr1   s           r   r'   zIntegerPartition.__new__S  s    B !*GYGi$.Ay0$?  1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
r2   c                    t        t              }|j                  | j                                | j                  }|dgk(  rt        | j                  di      S |d   dk7  r/||d   xx   dz  cc<   |d   dk(  rd|d<   ncdx||d   dz
  <   |d<   nR||d   xx   dz  cc<   |d   |d   z   }|d   }d|d<   |r+|dz  }||z
  dk\  r||xx   ||z  z  cc<   |||   |z  z  }|r+t        | j                  |      S )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
        r]      r   )r   intupdateas_dict_keysrk   rt   )r=   dkeysleftnews        r   prev_lexzIntegerPartition.prev_lex  s    	 zzA3;#T\\1$5668q=d2hK1KBx1}!)**$r(Q,!A$d2hK1KQ4$r(?Dr(CAaDq#:?cFdCi'FAcF3J&D	 
  a00r2   c                    t        t              }|j                  | j                                | j                  }|d   }|| j
                  k(  r |j                          | j
                  |d<   n|dk(  rO||   dkD  r||dz   xx   dz  cc<   ||xx   dz  cc<   n|d   }||dz   xx   dz  cc<   ||   dz
  |z  |d<   d||<   n||   dkD  rbt        |      dk(  r.|j                          d||dz   <   | j
                  |z
  dz
  |d<   n`|dz   }||xx   dz  cc<   ||   |z  |z
  |d<   d||<   n:|d   }|dz   }||xx   dz  cc<   ||   |z  ||   |z  z   |z
  }dx||<   ||<   ||d<   t        | j
                  |      S )a  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
        rz   r]   r{   r|   r   )	r   r}   r~   r   r   rt   clearr   rk   )r=   r   r9   aba1b1needs           r   next_lexzIntegerPartition.next_lex  s    	 jjGGGI<<AaD!Vtax!a%A!	G!a%A!q!|!!taxs8q=GGI Aa!eH<<!+a/AaDQBbEQJEQ46B;AaDAaDGU"
tAv!Q+!qt!a00r2   c                     | j                   ?t        | j                  d      }|D cg c]  }|d   	 c}| _        t	        |      | _         | j                   S c c}w )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   rp   )r=   groupsgs      r   r   zIntegerPartition.as_dict  sN     ::4>>E:F(./1!A$/DJfDJzz 0s   Ac                     d}t        | j                        dgz   }|d   }dg|z  }|dkD  r)|||   kD  r|||dz
  <   |dz  }|||   kD  r|dz  }|dkD  r)|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_arrrv   r   s        r   	conjugatezIntegerPartition.conjugate  s     '1#-QKCE!ehqk/!a%Q hqk/ FA	 !e
 r2   c                 |    t        t        | j                              t        t        |j                              k  S )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,   rK   s     r   rQ   zIntegerPartition.__lt__  s+    " HT^^,-Xeoo5N0OOOr2   c                 |    t        t        | j                              t        t        |j                              k  S )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
        r   rK   s     r   rO   zIntegerPartition.__le__%  s+     HT^^,-hu6O1PPPr2   c                 d    dj                  | j                  D cg c]  }||z  	 c}      S c c}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=   charrZ   s      r   
as_ferrerszIntegerPartition.as_ferrers3  s)     yy$..9Q$q&9::9s   -c                 >    t        t        | j                              S r   )strr!   r,   rV   s    r   __str__zIntegerPartition.__str__B  s    4'((r2   r   )#)rd   re   rf   rg   r   r   r'   r   r   r   rh   r   rQ   rO   r   r   r_   r2   r   rk   rk   4  sT    6 EE<|#1J01d$  .P&Q;)r2   rk   Nc                 F   ddl m} t        |       } | dk  rt        d       ||      }g }| dkD  r6 |d|       } |d| |z        }|j	                  ||f       | ||z  z  } | dkD  r6|j                  d       t        |D cg c]  \  }}|g|z   c}}      }|S c c}}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]   zn must be a positive integerTrm   )sympy.core.randomr   r   r%   r#   sortr   )nseedr   randintr,   rv   multms           r   random_integer_partitionr   F  s    ( +q	A1u788tnGIq5AqMq!Q$!T#	QtV	 q5
 NN4N 9541a!Q56I 6s   B
c                     t        | dz         }t        | dz         D ]	  }d|d|f<    t        d| dz         D ]B  }t        |       D ]2  }|| |z
  k  r!|||dz
  |f   z  ||dz
  |dz   f   z   |||f<   ,d|||f<   4 D |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   )r   r   rZ   r[   s       r   RGS_generalizedr   m  s    & 	a!eA1q5\ !Q$ 1a!e_ q 	AAEzaAqk/Aa!eQUlO;!Q$!Q$		 Hr2   c                 0    | dk  ry| dk(  ryt        |       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]   r   r   )r   s    r   rD   rD     s!    : 	
A
q&Awr2   c                 h   |dk  rt        d      | dk  st        |      | k  rt        d      dg|dz   z  }d}t        |      }t        d|dz         D ]B  }|||z
  |f   }||z  }|| k  r|dz   ||<   | |z  } |dz  }*t	        | |z  dz         ||<   | |z  } D |dd D cg c]  }|dz
  	 c}S c c}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]   zThe superset size must be >= 1r   zInvalid argumentsr{   N)r%   rD   r   ra   r}   )	r<   r   Lr[   DrZ   rw   crxs	            r   rC   rC     s     	1u9::ax8A;$&,--	
q1uA	AA1a!e_ 	a!eQhKqS:q5AaDBJDFAtax!|$AaDAID	 QR5!aAE!!!s    B/c                     t        |       }d}t        |      }t        d|      D ]4  }t        | |dz   d       }t        | d|       }||||dz   f   | |   z  z  }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
    r   r]   N)r   r   ra   r`   )rY   rgs_sizer<   r   rZ   r   r   s          r   rT   rT     s{     3xHD!A1h %QUHAaM!QU(c!f$$% Kr2   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   rk   r   r   rD   rC   rT   r_   r2   r   <module>r      sc    2 2 & / ' 6   , 4 ' $b%	 b%J	O)u O)d$N@"J "Fr2   