
    EdmQ                         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dS )    )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dS )	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 ]n}t          |t                    r5t          |          }t          |          t          |          k     rd} n%|}|                    t          |                     ot          d |D                       st          d          t          | }|s*t          |          t          d |D                       k     rt          d          t          j        | g|R  }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                    V  d S N)
isinstancer   ).0parts     >lib/python3.11/site-packages/sympy/combinatorics/partitions.py	<genexpr>z$Partition.__new__.<locals>.<genexpr>N   s,      @@4:dI..@@@@@@    z@Each argument to Partition should be a list, set, or a FiniteSetc              3   4   K   | ]}t          |          V  d S r   )len)r   args     r   r   z$Partition.__new__.<locals>.<genexpr>U   s(      99SC999999r   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__   s8   H  	' 	'C#t$$ Sv;;S) DEKK&&&&@@4@@@@@ 	/./ / /
 4L 	H3q66C99D999999 	HFGGG+d+++Ahhq66
r   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})]
        Nc                 $    t          |           S r   r   )worders    r   <lambda>z$Partition.sort_key.<locals>.<lambda>u   s    +;Au+E+E r   key)r*   r)   sortedmapr	   r+   rank)selfr6   r*   s    ` r   sort_keyzPartition.sort_key]   sp    (  	HlGGF4<!E!E!E!EG G G H HGS)DIw	+JKKLLLr   c                 d    | j         #t          d | j        D                       | _         | j         S )zReturn partition as a sorted list of lists.

        Examples
        ========

        >>> from sympy.combinatorics import Partition
        >>> Partition([1], [2, 3]).partition
        [[1], [2, 3]]
        Nc                 :    g | ]}t          |t                     S )r8   )r:   r	   r   ps     r   
<listcomp>z'Partition.partition.<locals>.<listcomp>   s6     &: &: &:*+ '-Q4D&E&E&E &: &: &:r   )
_partitionr:   r.   r=   s    r   r-   zPartition.partitionx   sE     ? 	;$ &: &:/3y&: &: &: ; ;DOr   c                     t          |          }| j        |z   }t          |t          | j                  z  | j                  }t
                              || 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__   s]    " uU"V$TY//0 I' ' !!&$,777r   c                 .    |                      |           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
        )rM   r=   rJ   s     r   __sub__zPartition.__sub__   s    " ||UF###r   c                 p    |                                  t          |                                           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   rO   s     r   __le__zPartition.__le__   s)    $ }}'%.."9"9";";;;r   c                 p    |                                  t          |                                           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
        rR   rO   s     r   __lt__zPartition.__lt__   s)     }}!8!8!:!:::r   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RGSrE   s    r   r<   zPartition.rank   s/     : 	:dh''
zr   c                     i | j         }t          |          D ]\  }}|D ]}||<   t          fdt          d |D             t                    D                       S )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)
        c                      g | ]
}|         S  r\   )r   irgss     r   rC   z!Partition.RGS.<locals>.<listcomp>
  s/     F F Fc!f F F Fr   c                     g | ]	}|D ]}|
S r\   r\   )r   rB   r]   s      r   rC   z!Partition.RGS.<locals>.<listcomp>  s%    ---11--aQ----r   r8   )r-   	enumerater)   r:   r	   )r=   r-   r]   r   jr^   s        @r   rY   zPartition.RGS   s    6 N	 ++ 	 	GAt  A F F F Ff--	---3C'E 'E 'E F F F G G 	Gr   c                 r   t          |          t          |          k    rt          d          t          |          dz   }d t          |          D             }d}|D ](}||                             ||                    |dz  })t          d |D                       st          d          t          | S )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   c                     g | ]}g S r\   r\   r   r]   s     r   rC   z&Partition.from_rgs.<locals>.<listcomp>*  s    111AR111r   r   c              3      K   | ]}|V  d S r   r\   rA   s     r   r   z%Partition.from_rgs.<locals>.<genexpr>/  s"      ((1((((((r   z(some blocks of the partition were empty.)r    r&   maxranger$   r%   r   )r=   r^   elementsmax_elemr-   ra   r]   s          r   rI   zPartition.from_rgs  s    4 s88s8}}$ 	DBCCCs88a<11x111	 	 	AaL,,,FAA((i((((( 	IGHHH)$$r   r   )__name__
__module____qualname____doc__rW   rD   r(   r>   propertyr-   rM   rP   rS   rU   r<   rY   classmethodrI   r\   r   r   r   r      s        
 
 EJ< < <|M M M M6   X8 8 80$ $ $&< < <(; ; ;"   X"  G  G X GD #% #% [#% #% #%r   r   c                   d    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dS )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                 "   |||}}t          |t          t          f          rg }t          t	          |                                          d          D ]?\  }}|st          |          t          |          }}|                    |g|z             @t          |          }n1t          t          t          t          |          d                    }d}|t          |          }d}nt          |          }|s%t          |          |k    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.

        Explantion
        ==========

        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

        NTreverseFzPartition did not add to %sc              3   "   K   | ]
}|d k     V  dS )rc   Nr\   re   s     r   r   z+IntegerPartition.__new__.<locals>.<genexpr>  s&      ((q1u((((((r   z-All integer summands must be greater than one)r   dictr   r:   r"   itemsr   extendr)   r;   r'   r&   anyr   r(   r   r   r-   integer)r,   r-   r{   _kvsum_okr2   s           r   r(   zIntegerPartition.__new__S  s   B  	4!*GYGi$.. 		LAtIOO$5$566EEE    1 ayy&))1!QaIIfS%;%;TJJJKKI 	&)nnGFFWooG 	F#i..G3 	F:WDEEE((i((((( 	NLMMMmC!1!15)3DEEY
r   c                 H   t          t                    }|                    |                                            | j        }|dgk    rt          | j        di          S |d         dk    r<||d         xx         dz  cc<   |d         dk    rd|d<   n{dx||d         dz
  <   |d<   ng||d         xx         dz  cc<   |d         |d         z   }|d         }d|d<   |r1|dz  }||z
  dk    r!||xx         ||z  z  cc<   |||         |z  z  }|1t          | 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
        rc      r   )r   intupdateas_dict_keysrr   r{   )r=   dkeysleftnews        r   prev_lexzIntegerPartition.prev_lex  s^    	   zA3; 	7#T\1$56668q= 	'd2hKKK1KKKBx1} +!)**$r(Q,!A$$d2hKKK1KKKQ4$r(?Dr(CAaD 'q#:? 'cFFFdCi'FFFAcF3J&D	  '
  a000r   c                 b   t          t                    }|                    |                                            | j        }|d         }|| j        k    r |                                 | j        |d<   n&|dk    rb||         dk    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k    rlt          |          dk    r-|                                 d||dz   <   | j        |z
  dz
  |d<   nr|dz   }||xx         dz  cc<   ||         |z  |z
  |d<   d||<   nF|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
        r   rc   r   r   r   )	r   r   r   r   r   r{   clearr    rr   )r=   r   r9   aba1b1needs           r   next_lexzIntegerPartition.next_lex  s    	   jG 	GGIII<AaDD!V 	tax !a%A!	G!a%A!q!|!!tax s88q= GGIII Aa!eH<!+a/AaDDQBbEEEQJEEEQ46B;AaDAaDDGU"
tAv!Q+!qt!a000r   c                     | j         ;t          | j        d          }d |D             | _        t	          |          | _         | j         S )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}
        NF)multiplec                     g | ]
}|d          S )r   r\   )r   gs     r   rC   z,IntegerPartition.as_dict.<locals>.<listcomp>  s    ///1!A$///r   )_dictr   r-   r   rw   )r=   groupss     r   r   zIntegerPartition.as_dict  sL     : 	&4>E:::F/////DJfDJzr   c                     d}t          | j                  dgz   }|d         }dg|z  }|dk    r0|||         k    r|||dz
  <   |dz  }|||         k    |dz  }|dk    0|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]
        rc   r   )r"   r-   )r=   ra   temp_arrr}   r   s        r   	conjugatezIntegerPartition.conjugate  s     ''1#-QKCE!e 	hqk/ !a%Q hqk/  FA	 !e 	
 r   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-   rO   s     r   rU   zIntegerPartition.__lt__  s3    " HT^,,--Xeo5N5N0O0OOOr   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   rO   s     r   rS   zIntegerPartition.__le__%  s3     HT^,,--hu6O6O1P1PPPr   #c                 P    d                     fd| j        D                       S )a  
        Prints the ferrer diagram of a partition.

        Examples
        ========

        >>> from sympy.combinatorics.partitions import IntegerPartition
        >>> print(IntegerPartition([1, 1, 5]).as_ferrers())
        #####
        #
        #
        
c                     g | ]}|z  S r\   r\   )r   r]   chars     r   rC   z/IntegerPartition.as_ferrers.<locals>.<listcomp>@  s    999Q$q&999r   )joinr-   )r=   r   s    `r   
as_ferrerszIntegerPartition.as_ferrers3  s.     yy9999$.999:::r   c                 D    t          t          | j                            S r   )strr"   r-   rE   s    r   __str__zIntegerPartition.__str__B  s    4''(((r   r   )r   )rk   rl   rm   rn   r   r   r(   r   r   r   ro   r   rU   rS   r   r   r\   r   r   rr   rr   4  s         6 EE< < < <|#1 #1 #1J01 01 01d  $   X.P P P&Q Q Q; ; ; ;) ) ) ) )r   rr   Nc                 ^   ddl m} t          |           } | dk     rt          d           ||          }g }| dk    r@ |d|           } |d| |z            }|                    ||f           | ||z  z  } | dk    @|                    d           t          d |D                       }|S )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   )_randintrc   zn must be a positive integerTrt   c                      g | ]\  }}|g|z  S r\   r\   )r   r}   ms      r   rC   z,random_integer_partition.<locals>.<listcomp>i  s"    55541a!Q555r   )sympy.core.randomr   r   r&   r$   sortr   )nseedr   randintr-   r}   mults          r   random_integer_partitionr   F  s    ( +*****q		A1u 97888htnnGIq5 GAqMMwq!Q$!T###	QtV	 q5 
 NN4N   55955566Ir   c                     t          | dz             }t          | dz             D ]	}d|d|f<   
t          d| dz             D ]K}t          |           D ]9}|| |z
  k    r'|||dz
  |f         z  ||dz
  |dz   f         z   |||f<   2d|||f<   :L|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]])
    rc   r   )r   rh   )r   r   r]   ra   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$		
 Hr   c                 @    | dk     rdS | dk    rdS 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

    rc   r   r   )r   s    r   rH   rH     s1    : 	
A q
q& qAwwr   c                    |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 ]J}|||z
  |f         }||z  }|| k    r|dz   ||<   | |z  } |dz  }-t	          | |z  dz             ||<   | |z  } Kd |dd         D             S )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]
    rc   zThe superset size must be >= 1r   zInvalid argumentsr   c                     g | ]}|d z
  S )rc   r\   )r   xs     r   rC   zRGS_unrank.<locals>.<listcomp>  s    !!!aAE!!!r   N)r&   rH   r   rh   r   )r<   r   Lra   Dr]   r~   crs           r   rG   rG     s    	1u ;9:::ax .8A;;$& .,---	
q1uA	AA1a!e__ 	 	a!eQhKqS: 	q5AaDBJDFAAtax!|$$AaDAIDD!!1QRR5!!!!r   c                     t          |           }d}t          |          }t          d|          D ]L}t          | |dz   d                   }t          | d|                   }||||dz   f         | |         z  z  }M|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   rc   N)r    r   rh   rg   )r^   rgs_sizer<   r   r]   r   r   s          r   rX   rX     s     3xxHD!!A1h % %QUHHAaCMM!QU(c!f$$Kr   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   rr   r   r   rH   rG   rX   r\   r   r   <module>r      s   2 2 2 2 2 2 2 2 2 2 2 2 & & & & & & / / / / / / ' ' ' ' ' ' 6 6 6 6 6 6             , , , , , , , , 4 4 4 4 4 4 4 4 ' ' ' ' ' ' $ # # # # #b% b% b% b% b%	 b% b% b%J	O) O) O) O) O)u O) O) O)d$ $ $ $N  @" " "J "  "  "F    r   