o
    oh>                     @   s2   d dl mZ d dlmZ G dd dZdd ZdS )    combinations)GrayCodec                   @   s  e Zd ZdZdZdZdZdZdZdd Z	dd Z
dd Zd	d
 Zdd Zdd Zdd Zdd Zdd Zdd Zedd Zedd Zedd Zedd Zedd  Zed!d" Zed#d$ Zed%d& Zed'd( Zed)d* Zed+d, Zed-d. Z ed/d0 Z!dS )1Subseta  
    Represents a basic subset object.

    Explanation
    ===========

    We generate subsets using essentially two techniques,
    binary enumeration and lexicographic enumeration.
    The Subset class takes two arguments, the first one
    describes the initial subset to consider and the second
    describes the superset.

    Examples
    ========

    >>> from sympy.combinatorics import Subset
    >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
    >>> a.next_binary().subset
    ['b']
    >>> a.prev_binary().subset
    ['c']
    Nc                 C   sR   t |t |krtd|D ]}||vrtd|qt| }||_||_|S )ax  
        Default constructor.

        It takes the ``subset`` and its ``superset`` as its parameters.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.subset
        ['c', 'd']
        >>> a.superset
        ['a', 'b', 'c', 'd']
        >>> a.size
        2
        zRInvalid arguments have been provided. The superset must be larger than the subset.zFThe superset provided is invalid as it does not contain the element {})len
ValueErrorformatobject__new___subset	_superset)clssubsetsupersetelemobj r   o/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/sympy/combinatorics/subsets.pyr
   $   s   
zSubset.__new__c                 C   s&   t |tstS | j|jko| j|jkS )zReturn a boolean indicating whether a == b on the basis of
        whether both objects are of the class Subset and if the values
        of the subset and superset attributes are the same.
        )
isinstancer   NotImplementedr   r   )selfotherr   r   r   __eq__B   s   
zSubset.__eq__c                 C   sV   t | j| j}td|d| d| j  }t|dd | jd}t 	| j|S )a  
        This is a helper function. It iterates over the
        binary subsets by ``k`` steps. This variable can be
        both positive or negative.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.iterate_binary(-2).subset
        ['d']
        >>> a = Subset(['a', 'b', 'c'], ['a', 'b', 'c', 'd'])
        >>> a.iterate_binary(2).subset
        []

        See Also
        ========

        next_binary, prev_binary
            N0)
r   bitlist_from_subsetr   r   intjoinsuperset_sizebinrjustsubset_from_bitlist)r   kbin_listnbitsr   r   r   iterate_binaryK   s   zSubset.iterate_binaryc                 C   
   |  dS )a  
        Generates the next binary ordered subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.next_binary().subset
        ['b']
        >>> a = Subset(['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.next_binary().subset
        []

        See Also
        ========

        prev_binary, iterate_binary
           r'   r   r   r   r   next_binaryf      
zSubset.next_binaryc                 C   r(   )a  
        Generates the previous binary ordered subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset([], ['a', 'b', 'c', 'd'])
        >>> a.prev_binary().subset
        ['a', 'b', 'c', 'd']
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.prev_binary().subset
        ['c']

        See Also
        ========

        next_binary, iterate_binary
        r*   r+   r   r   r   prev_binary|   r-   zSubset.prev_binaryc                 C   s   | j d }t| j| j}||v rM|d |v r||d  nI|| |d }|dkr<||vr<|d }|dkr<||vs0|dkrL|| ||d  n||vra|dkra|d }||vra|dksU||d  g }| j}|D ]	}|||  qot||S )a  
        Generates the next lexicographically ordered subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.next_lexicographic().subset
        ['d']
        >>> a = Subset(['d'], ['a', 'b', 'c', 'd'])
        >>> a.next_lexicographic().subset
        []

        See Also
        ========

        prev_lexicographic
        r)   r   r   r   subset_indicesr   r   removeappendr   iindicesret_set	super_setr   r   r   next_lexicographic   s.   



zSubset.next_lexicographicc                 C   s   | j d }t| j| j}|dkr!||vr!|d }|dkr!||vs|dks+|d |v r1|| n|dkrA|| ||d  || j d  g }| j}|D ]	}|||  qPt||S )a  
        Generates the previous lexicographically ordered subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset([], ['a', 'b', 'c', 'd'])
        >>> a.prev_lexicographic().subset
        ['d']
        >>> a = Subset(['c','d'], ['a', 'b', 'c', 'd'])
        >>> a.prev_lexicographic().subset
        ['c']

        See Also
        ========

        next_lexicographic
        r)   r   r0   r4   r   r   r   prev_lexicographic   s    


zSubset.prev_lexicographicc                 C   s(   t | j| j| | j }t| j|S )a  
        Helper function used for prev_gray and next_gray.
        It performs ``k`` step overs to get the respective Gray codes.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset([1, 2, 3], [1, 2, 3, 4])
        >>> a.iterate_graycode(3).subset
        [1, 4]
        >>> a.iterate_graycode(-2).subset
        [1, 2, 4]

        See Also
        ========

        next_gray, prev_gray
        )r   unrankr   	rank_graycardinalityr   r"   r   )r   r#   unranked_coder   r   r   iterate_graycode   s   zSubset.iterate_graycodec                 C   r(   )a=  
        Generates the next Gray code ordered subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset([1, 2, 3], [1, 2, 3, 4])
        >>> a.next_gray().subset
        [1, 3]

        See Also
        ========

        iterate_graycode, prev_gray
        r)   r?   r+   r   r   r   	next_gray      
zSubset.next_grayc                 C   r(   )aJ  
        Generates the previous Gray code ordered subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset([2, 3, 4], [1, 2, 3, 4, 5])
        >>> a.prev_gray().subset
        [2, 3, 4, 5]

        See Also
        ========

        iterate_graycode, next_gray
        r.   r@   r+   r   r   r   	prev_gray  rB   zSubset.prev_grayc                 C   s.   | j du rtdt| j| jd| _ | j S )a  
        Computes the binary ordered rank.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset([], ['a','b','c','d'])
        >>> a.rank_binary
        0
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.rank_binary
        3

        See Also
        ========

        iterate_binary, unrank_binary
        Nr   r   )_rank_binaryr   r   r   r   r   r   r+   r   r   r   rank_binary&  s   
zSubset.rank_binaryc                    s>   | j du r fdd t| j| j} | |d| j| _ | j S )aa  
        Computes the lexicographic ranking of the subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.rank_lexicographic
        14
        >>> a = Subset([2, 4, 5], [1, 2, 3, 4, 5, 6])
        >>> a.rank_lexicographic
        43
        Nc                    s^   |g ks||kr
dS ||v r| | d | ||d | S d|| d   | ||d | S )Nr   r)   r   )r2   )r   subset_indexr5   r%   _ranklexr   r   rH   R  s   
"z+Subset.rank_lexicographic.<locals>._ranklexr   )	_rank_lexr   r1   r   r   r   )r   r6   r   rG   r   rank_lexicographicA  s
   
zSubset.rank_lexicographicc                 C   s4   | j du rt| j| j}tt||dj| _ | j S )a  
        Computes the Gray code ranking of the subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c','d'], ['a','b','c','d'])
        >>> a.rank_gray
        2
        >>> a = Subset([2, 4, 5], [1, 2, 3, 4, 5, 6])
        >>> a.rank_gray
        27

        See Also
        ========

        iterate_graycode, unrank_gray
        N)start)_rank_graycoder   r   r   r   r   r   rank)r   r&   r   r   r   r<   ]  s   
zSubset.rank_grayc                 C      | j S )aU  
        Gets the subset represented by the current instance.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.subset
        ['c', 'd']

        See Also
        ========

        superset, size, superset_size, cardinality
        )r   r+   r   r   r   r   w     zSubset.subsetc                 C   
   t | jS )a4  
        Gets the size of the subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.size
        2

        See Also
        ========

        subset, superset, superset_size, cardinality
        )r   r   r+   r   r   r   size     
zSubset.sizec                 C   rN   )aK  
        Gets the superset of the subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.superset
        ['a', 'b', 'c', 'd']

        See Also
        ========

        subset, size, superset_size, cardinality
        )r   r+   r   r   r   r     rO   zSubset.supersetc                 C   rP   )a9  
        Returns the size of the superset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.superset_size
        4

        See Also
        ========

        subset, superset, size, cardinality
        )r   r   r+   r   r   r   r     rR   zSubset.superset_sizec                 C   s
   d| j  S )aD  
        Returns the number of all possible subsets.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        >>> a.cardinality
        16

        See Also
        ========

        subset, superset, size, superset_size
        r   )r   r+   r   r   r   r=     rR   zSubset.cardinalityc                 C   sR   t |t |krtdg }tt |D ]}|| dkr#|||  qt||S )a/  
        Gets the subset defined by the bitlist.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> Subset.subset_from_bitlist(['a', 'b', 'c', 'd'], '0011').subset
        ['c', 'd']

        See Also
        ========

        bitlist_from_subset
        z$The sizes of the lists are not equal1)r   r   ranger3   r   )r   r8   bitlistr7   r5   r   r   r   r"     s   
zSubset.subset_from_bitlistc                 C   sB   dgt | }t|tr|j}t||D ]}d||< qd|S )a,  
        Gets the bitlist corresponding to a subset.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> Subset.bitlist_from_subset(['c', 'd'], ['a', 'b', 'c', 'd'])
        '0011'

        See Also
        ========

        subset_from_bitlist
        r   rS   r   )r   r   r   r   r1   r   )r   r   r   rU   r5   r   r   r   r     s   


zSubset.bitlist_from_subsetc                 C   s(   t |dd t|d}t||S )a5  
        Gets the binary ordered subset of the specified rank.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> Subset.unrank_binary(4, ['a', 'b', 'c', 'd']).subset
        ['b']

        See Also
        ========

        iterate_binary, rank_binary
        r   Nr   )r    r!   r   r   r"   )r   rM   r   r&   r   r   r   unrank_binary  s   zSubset.unrank_binaryc                 C   s   t t||}t||S )a{  
        Gets the Gray code ordered subset of the specified rank.

        Examples
        ========

        >>> from sympy.combinatorics import Subset
        >>> Subset.unrank_gray(4, ['a', 'b', 'c']).subset
        ['a', 'b']
        >>> Subset.unrank_gray(0, ['a', 'b', 'c']).subset
        []

        See Also
        ========

        iterate_graycode, rank_gray
        )r   r;   r   r   r"   )r   rM   r   graycode_bitlistr   r   r   unrank_gray   s   zSubset.unrank_grayc                    s`   ||}}t |}i  t|D ]\}}||v r$| |< || |s$ nqg S  fdd|D S )a  Return indices of subset in superset in a list; the list is empty
        if all elements of ``subset`` are not in ``superset``.

        Examples
        ========

            >>> from sympy.combinatorics import Subset
            >>> superset = [1, 3, 2, 5, 4]
            >>> Subset.subset_indices([3, 2, 1], superset)
            [1, 2, 0]
            >>> Subset.subset_indices([1, 6], superset)
            []
            >>> Subset.subset_indices([], superset)
            []

        c                    s   g | ]} | qS r   r   ).0bidr   r   
<listcomp>S  s    z)Subset.subset_indices.<locals>.<listcomp>)set	enumerater2   )r   r   r   absbr5   air   r[   r   r1   6  s   

zSubset.subset_indices)"__name__
__module____qualname____doc__rD   rI   rL   r   r   r
   r   r'   r,   r/   r9   r:   r?   rA   rC   propertyrE   rJ   r<   r   rQ   r   r   r=   classmethodr"   r   rV   rX   r1   r   r   r   r   r      sV    	-(











r   c                 C   s
   t | |S )a  
    Finds the subsets of size ``k`` in lexicographic order.

    This uses the itertools generator.

    Examples
    ========

    >>> from sympy.combinatorics.subsets import ksubsets
    >>> list(ksubsets([1, 2, 3], 2))
    [(1, 2), (1, 3), (2, 3)]
    >>> list(ksubsets([1, 2, 3, 4, 5], 2))
    [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4),     (2, 5), (3, 4), (3, 5), (4, 5)]

    See Also
    ========

    Subset
    r   )r   r#   r   r   r   ksubsetsV  s   
rj   N)	itertoolsr   sympy.combinatorics.graycoder   r   rj   r   r   r   r   <module>   s        T