B
    [>                 @   s  d 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
mZmZmZ ddlmZmZmZ ddlmZmZ ddlmZ dd	lmZ ed)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"dd Z#d d! Z$d"d# Z%G d$d% d%e&Z'eG d&d' d'eZ(d(S )*z@Tools and arithmetics for monomials of distributed polynomials.     )print_functiondivision)combinations_with_replacementproduct)dedent)MulSTuplesympify)exec_iterablerange)PicklableWithSlotsdict_from_expr)ExactQuotientFailed)publicc             C   sZ  |dk s||krt  S | r"|dkr,tdhS t| tdg } tdd | D rg }xrt| |D ]d}t }x| D ]}d||< qpW x$|D ]}|dkr||  d7  < qW t| |kr`|t	|  q`W t |S g }xxt
| |dD ]h}t }x| D ]}d||< qW x(|D ] }|dkr||  d7  < qW t| |kr|t	|  qW t |S dS )a  
    Generate a set of monomials of the degree greater than or equal
    to `min_degree` and less than or equal to `max_degree`.

    Given a set of variables `V` and a min_degree `N` and a max_degree `M`
    generate a set of monomials of degree less than or equal to `N` and greater
    than or equal to `M`. The total number of monomials in commutative
    variables is huge and is given by the following formula if `M = 0`:

    .. math::

        \frac{(\#V + N)!}{\#V! N!}

    For example if we would like to generate a dense polynomial of
    a total degree `N = 50` and `M = 0`, which is the worst case, in 5
    variables, assuming that exponents and all of coefficients are 32-bit long
    and stored in an array we would need almost 80 GiB of memory! Fortunately
    most polynomials, that we will encounter, are sparse.

    Examples
    ========

    Consider monomials in commutative variables `x` and `y`
    and non-commutative variables `a` and `b`::

        >>> from sympy import symbols
        >>> from sympy.polys.monomials import itermonomials
        >>> from sympy.polys.orderings import monomial_key
        >>> from sympy.abc import x, y

        >>> sorted(itermonomials([x, y], 2), key=monomial_key('grlex', [y, x]))
        [1, x, y, x**2, x*y, y**2]

        >>> sorted(itermonomials([x, y], 3), key=monomial_key('grlex', [y, x]))
        [1, x, y, x**2, x*y, y**2, x**3, x**2*y, x*y**2, y**3]

        >>> a, b = symbols('a, b', commutative=False)
        >>> itermonomials([a, b, x], 2)
        {1, a, a**2, b, b**2, x, x**2, a*b, b*a, x*a, x*b}

        >>> sorted(itermonomials([x, y], 2, 1), key=monomial_key('grlex', [y, x]))
        [x, y, x**2, x*y, y**2]


    r      c             s   s   | ]}|j V  qd S )N)Zis_commutative).0variable r   4lib/python3.7/site-packages/sympy/polys/monomials.py	<genexpr>C   s    z itermonomials.<locals>.<genexpr>)repeatN)setr   listallr   dictmaxvaluesappendr   r   )Z	variablesZ
max_degreeZ
min_degreeZmonomials_list_commitemZpowersr   Zmonomials_list_non_commr   r   r   itermonomials   s8    /





r!   c             C   s(   ddl m} || | ||  || S )aQ  
    Computes the number of monomials.

    The number of monomials is given by the following formula:

    .. math::

        \frac{(\#V + N)!}{\#V! N!}

    where `N` is a total degree and `V` is a set of variables.

    Examples
    ========

    >>> from sympy.polys.monomials import itermonomials, monomial_count
    >>> from sympy.polys.orderings import monomial_key
    >>> from sympy.abc import x, y

    >>> monomial_count(2, 2)
    6

    >>> M = itermonomials([x, y], 2)

    >>> sorted(M, key=monomial_key('grlex', [y, x]))
    [1, x, y, x**2, x*y, y**2]
    >>> len(M)
    6

    r   )	factorial)Zsympyr"   )VNr"   r   r   r   monomial_count\   s    r%   c             C   s   t dd t| |D S )a
  
    Multiplication of tuples representing monomials.

    Lets multiply `x**3*y**4*z` with `x*y**2`::

        >>> from sympy.polys.monomials import monomial_mul

        >>> monomial_mul((3, 4, 1), (1, 2, 0))
        (4, 6, 1)

    which gives `x**4*y**5*z`.

    c             S   s   g | ]\}}|| qS r   r   )r   abr   r   r   
<listcomp>   s    z monomial_mul.<locals>.<listcomp>)tuplezip)ABr   r   r   monomial_mul}   s    r-   c             C   s,   t | |}tdd |D r$t|S dS dS )a  
    Division of tuples representing monomials.

    Lets divide `x**3*y**4*z` by `x*y**2`::

        >>> from sympy.polys.monomials import monomial_div

        >>> monomial_div((3, 4, 1), (1, 2, 0))
        (2, 2, 1)

    which gives `x**2*y**2*z`. However::

        >>> monomial_div((3, 4, 1), (1, 2, 2)) is None
        True

    `x*y**2*z**2` does not divide `x**3*y**4*z`.

    c             s   s   | ]}|d kV  qdS )r   Nr   )r   cr   r   r   r      s    zmonomial_div.<locals>.<genexpr>N)monomial_ldivr   r)   )r+   r,   Cr   r   r   monomial_div   s    
r1   c             C   s   t dd t| |D S )aj  
    Division of tuples representing monomials.

    Lets divide `x**3*y**4*z` by `x*y**2`::

        >>> from sympy.polys.monomials import monomial_ldiv

        >>> monomial_ldiv((3, 4, 1), (1, 2, 0))
        (2, 2, 1)

    which gives `x**2*y**2*z`.

        >>> monomial_ldiv((3, 4, 1), (1, 2, 2))
        (2, 2, -1)

    which gives `x**2*y**2*z**-1`.

    c             S   s   g | ]\}}|| qS r   r   )r   r&   r'   r   r   r   r(      s    z!monomial_ldiv.<locals>.<listcomp>)r)   r*   )r+   r,   r   r   r   r/      s    r/   c                s   t  fdd| D S )z%Return the n-th pow of the monomial. c                s   g | ]}|  qS r   r   )r   r&   )nr   r   r(      s    z monomial_pow.<locals>.<listcomp>)r)   )r+   r2   r   )r2   r   monomial_pow   s    r3   c             C   s   t dd t| |D S )a  
    Greatest common divisor of tuples representing monomials.

    Lets compute GCD of `x*y**4*z` and `x**3*y**2`::

        >>> from sympy.polys.monomials import monomial_gcd

        >>> monomial_gcd((1, 4, 1), (3, 2, 0))
        (1, 2, 0)

    which gives `x*y**2`.

    c             S   s   g | ]\}}t ||qS r   )min)r   r&   r'   r   r   r   r(      s    z monomial_gcd.<locals>.<listcomp>)r)   r*   )r+   r,   r   r   r   monomial_gcd   s    r5   c             C   s   t dd t| |D S )a  
    Least common multiple of tuples representing monomials.

    Lets compute LCM of `x*y**4*z` and `x**3*y**2`::

        >>> from sympy.polys.monomials import monomial_lcm

        >>> monomial_lcm((1, 4, 1), (3, 2, 0))
        (3, 4, 1)

    which gives `x**3*y**4*z`.

    c             S   s   g | ]\}}t ||qS r   )r   )r   r&   r'   r   r   r   r(      s    z monomial_lcm.<locals>.<listcomp>)r)   r*   )r+   r,   r   r   r   monomial_lcm   s    r6   c             C   s   t dd t| |D S )z
    Does there exist a monomial X such that XA == B?

    >>> from sympy.polys.monomials import monomial_divides
    >>> monomial_divides((1, 2), (3, 4))
    True
    >>> monomial_divides((1, 2), (0, 2))
    False
    c             s   s   | ]\}}||kV  qd S )Nr   )r   r&   r'   r   r   r   r      s    z#monomial_divides.<locals>.<genexpr>)r   r*   )r+   r,   r   r   r   monomial_divides   s    
r7   c              G   sR   t | d }x<| dd D ],}x&t|D ]\}}t|| |||< q(W qW t|S )av  
    Returns maximal degree for each variable in a set of monomials.

    Consider monomials `x**3*y**4*z**5`, `y**5*z` and `x**6*y**3*z**9`.
    We wish to find out what is the maximal degree for each of `x`, `y`
    and `z` variables::

        >>> from sympy.polys.monomials import monomial_max

        >>> monomial_max((3,4,5), (0,5,1), (6,3,9))
        (6, 5, 9)

    r   r   N)r   	enumerater   r)   )monomsMr$   ir2   r   r   r   monomial_max   s
    r<   c              G   sR   t | d }x<| dd D ],}x&t|D ]\}}t|| |||< q(W qW t|S )av  
    Returns minimal degree for each variable in a set of monomials.

    Consider monomials `x**3*y**4*z**5`, `y**5*z` and `x**6*y**3*z**9`.
    We wish to find out what is the minimal degree for each of `x`, `y`
    and `z` variables::

        >>> from sympy.polys.monomials import monomial_min

        >>> monomial_min((3,4,5), (0,5,1), (6,3,9))
        (0, 3, 1)

    r   r   N)r   r8   r4   r)   )r9   r:   r$   r;   r2   r   r   r   monomial_min  s
    r=   c             C   s   t | S )z
    Returns the total degree of a monomial.

    For example, the total degree of `xy^2` is 3:

    >>> from sympy.polys.monomials import monomial_deg
    >>> monomial_deg((1, 2))
    3
    )sum)r:   r   r   r   monomial_deg  s    
r?   c             C   sf   | \}}|\}}t ||}|jr>|dk	r8||||fS dS n$|dks^|| s^||||fS dS dS )z,Division of two terms in over a ring/field. N)r1   Zis_FieldZquo)r&   r'   ZdomainZa_lmZa_lcZb_lmZb_lcmonomr   r   r   term_div$  s    
rA   c               @   s`   e 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dS )MonomialOpsz6Code generator of fast monomial arithmetic functions. c             C   s
   || _ d S )N)ngens)selfrC   r   r   r   __init__9  s    zMonomialOps.__init__c             C   s   i }t || || S )N)r   )rD   codenamensr   r   r   _build<  s    
zMonomialOps._buildc                s    fddt | jD S )Nc                s   g | ]}d  |f qS )z%s%sr   )r   r;   )rG   r   r   r(   B  s    z%MonomialOps._vars.<locals>.<listcomp>)r   rC   )rD   rG   r   )rG   r   _varsA  s    zMonomialOps._varsc             C   sf   d}t d}| d}| d}dd t||D }|t|d|d|d|d }| ||S )	Nr-   zs        def %(name)s(A, B):
            (%(A)s,) = A
            (%(B)s,) = B
            return (%(AB)s,)
        r&   r'   c             S   s   g | ]\}}d ||f qS )z%s + %sr   )r   r&   r'   r   r   r   r(   N  s    z#MonomialOps.mul.<locals>.<listcomp>z, )rG   r+   r,   AB)r   rJ   r*   r   joinrI   )rD   rG   templater+   r,   rK   rF   r   r   r   mulD  s    

&zMonomialOps.mulc             C   sN   d}t d}| d}dd |D }|t|d|d|d }| ||S )Nr3   zZ        def %(name)s(A, k):
            (%(A)s,) = A
            return (%(Ak)s,)
        r&   c             S   s   g | ]}d | qS )z%s*kr   )r   r&   r   r   r   r(   Z  s    z#MonomialOps.pow.<locals>.<listcomp>z, )rG   r+   Ak)r   rJ   r   rL   rI   )rD   rG   rM   r+   rO   rF   r   r   r   powR  s    
zMonomialOps.powc             C   sf   d}t d}| d}| d}dd t||D }|t|d|d|d|d }| ||S )	NZmonomial_mulpowzw        def %(name)s(A, B, k):
            (%(A)s,) = A
            (%(B)s,) = B
            return (%(ABk)s,)
        r&   r'   c             S   s   g | ]\}}d ||f qS )z	%s + %s*kr   )r   r&   r'   r   r   r   r(   h  s    z&MonomialOps.mulpow.<locals>.<listcomp>z, )rG   r+   r,   ABk)r   rJ   r*   r   rL   rI   )rD   rG   rM   r+   r,   rQ   rF   r   r   r   mulpow^  s    

&zMonomialOps.mulpowc             C   sf   d}t d}| d}| d}dd t||D }|t|d|d|d|d }| ||S )	Nr/   zs        def %(name)s(A, B):
            (%(A)s,) = A
            (%(B)s,) = B
            return (%(AB)s,)
        r&   r'   c             S   s   g | ]\}}d ||f qS )z%s - %sr   )r   r&   r'   r   r   r   r(   v  s    z$MonomialOps.ldiv.<locals>.<listcomp>z, )rG   r+   r,   rK   )r   rJ   r*   r   rL   rI   )rD   rG   rM   r+   r,   rK   rF   r   r   r   ldivl  s    

&zMonomialOps.ldivc          	   C   sx   d}t d}| d}| d}dd t| jD }| d}|t|d|d|d	|d|d
 }| ||S )Nr1   z        def %(name)s(A, B):
            (%(A)s,) = A
            (%(B)s,) = B
            %(RAB)s
            return (%(R)s,)
        r&   r'   c             S   s   g | ]}d t |d qS )z7r%(i)s = a%(i)s - b%(i)s
    if r%(i)s < 0: return None)r;   )r   )r   r;   r   r   r   r(     s    z#MonomialOps.div.<locals>.<listcomp>rz, z
    )rG   r+   r,   RABR)r   rJ   r   rC   r   rL   rI   )rD   rG   rM   r+   r,   rU   rV   rF   r   r   r   divz  s    


.zMonomialOps.divc             C   sf   d}t d}| d}| d}dd t||D }|t|d|d|d|d }| ||S )	Nr6   zs        def %(name)s(A, B):
            (%(A)s,) = A
            (%(B)s,) = B
            return (%(AB)s,)
        r&   r'   c             S   s    g | ]\}}d ||||f qS )z%s if %s >= %s else %sr   )r   r&   r'   r   r   r   r(     s    z#MonomialOps.lcm.<locals>.<listcomp>z, )rG   r+   r,   rK   )r   rJ   r*   r   rL   rI   )rD   rG   rM   r+   r,   rK   rF   r   r   r   lcm  s    

&zMonomialOps.lcmc             C   sf   d}t d}| d}| d}dd t||D }|t|d|d|d|d }| ||S )	Nr5   zs        def %(name)s(A, B):
            (%(A)s,) = A
            (%(B)s,) = B
            return (%(AB)s,)
        r&   r'   c             S   s    g | ]\}}d ||||f qS )z%s if %s <= %s else %sr   )r   r&   r'   r   r   r   r(     s    z#MonomialOps.gcd.<locals>.<listcomp>z, )rG   r+   r,   rK   )r   rJ   r*   r   rL   rI   )rD   rG   rM   r+   r,   rK   rF   r   r   r   gcd  s    

&zMonomialOps.gcdN)__name__
__module____qualname____doc__rE   rI   rJ   rN   rP   rR   rS   rW   rX   rY   r   r   r   r   rB   6  s   rB   c               @   s   e Zd ZdZddgZd#ddZd$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dd Ze ZZdd Zdd  Zd!d" ZdS )%Monomialz9Class representing a monomial, i.e. a product of powers. 	exponentsgensNc             C   st   t |sZtt||d\}}t|dkrNt| d dkrNt| d }ntd| tt	t
|| _|| _d S )N)r`   r   r   zExpected a monomial got %s)r   r   r
   lenr   r   keys
ValueErrorr)   mapintr_   r`   )rD   r@   r`   Zrepr   r   r   rE     s     zMonomial.__init__c             C   s   |  ||p| jS )N)	__class__r`   )rD   r_   r`   r   r   r   rebuild  s    zMonomial.rebuildc             C   s
   t | jS )N)ra   r_   )rD   r   r   r   __len__  s    zMonomial.__len__c             C   s
   t | jS )N)iterr_   )rD   r   r   r   __iter__  s    zMonomial.__iter__c             C   s
   | j | S )N)r_   )rD   r    r   r   r   __getitem__  s    zMonomial.__getitem__c             C   s   t | jj| j| jfS )N)hashrf   rZ   r_   r`   )rD   r   r   r   __hash__  s    zMonomial.__hash__c             C   s:   | j r$ddd t| j | jD S d| jj| jf S d S )N*c             S   s   g | ]\}}d ||f qS )z%s**%sr   )r   genexpr   r   r   r(     s    z$Monomial.__str__.<locals>.<listcomp>z%s(%s))r`   rL   r*   r_   rf   rZ   )rD   r   r   r   __str__  s    zMonomial.__str__c             G   s4   |p| j }|std|  tdd t|| jD  S )z3Convert a monomial instance to a SymPy expression. z4can't convert %s to an expression without generatorsc             S   s   g | ]\}}|| qS r   r   )r   ro   rp   r   r   r   r(     s    z$Monomial.as_expr.<locals>.<listcomp>)r`   rc   r   r*   r_   )rD   r`   r   r   r   as_expr  s
    

zMonomial.as_exprc             C   s4   t |tr|j}nt |ttfr&|}ndS | j|kS )NF)
isinstancer^   r_   r)   r	   )rD   otherr_   r   r   r   __eq__  s    
zMonomial.__eq__c             C   s
   | |k S )Nr   )rD   rt   r   r   r   __ne__  s    zMonomial.__ne__c             C   s<   t |tr|j}nt |ttfr&|}ntS | t| j|S )N)rs   r^   r_   r)   r	   NotImplementedErrorrg   r-   )rD   rt   r_   r   r   r   __mul__  s    
zMonomial.__mul__c             C   sZ   t |tr|j}nt |ttfr&|}ntS t| j|}|d k	rH| |S t| t|d S )N)	rs   r^   r_   r)   r	   rw   r1   rg   r   )rD   rt   r_   resultr   r   r   __div__  s    

zMonomial.__div__c             C   sh   t |}|s | dgt|  S |dkrX| j}xtd|D ]}t|| j}q:W | |S td| d S )Nr   r   z'a non-negative integer expected, got %s)re   rg   ra   r_   r   r-   rc   )rD   rt   r2   r_   r;   r   r   r   __pow__  s    
zMonomial.__pow__c             C   sD   t |tr|j}n t |ttfr&|}ntd| | t| j|S )z&Greatest common divisor of monomials. z.an instance of Monomial class expected, got %s)rs   r^   r_   r)   r	   	TypeErrorrg   r5   )rD   rt   r_   r   r   r   rY     s    

zMonomial.gcdc             C   sD   t |tr|j}n t |ttfr&|}ntd| | t| j|S )z$Least common multiple of monomials. z.an instance of Monomial class expected, got %s)rs   r^   r_   r)   r	   r|   rg   r6   )rD   rt   r_   r   r   r   rX     s    

zMonomial.lcm)N)N)rZ   r[   r\   r]   	__slots__rE   rg   rh   rj   rk   rm   rq   rr   ru   rv   rx   rz   __floordiv____truediv__r{   rY   rX   r   r   r   r   r^     s$   




r^   N)r   ))r]   Z
__future__r   r   	itertoolsr   r   textwrapr   Z
sympy.corer   r   r	   r
   Zsympy.core.compatibilityr   r   r   Zsympy.polys.polyutilsr   r   Zsympy.polys.polyerrorsr   Zsympy.utilitiesr   r!   r%   r-   r1   r/   r3   r5   r6   r7   r<   r=   r?   rA   objectrB   r^   r   r   r   r   <module>   s2   M!p