
    MZdI                        d 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 ddlmZmZ ddlmZ ddlmZmZ edd
       Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d Z! G d d      Z"e G d de             Z#y	)z@Tools and arithmetics for monomials of distributed polynomials.     )combinations_with_replacementproduct)dedent)MulSTuplesympify)ExactQuotientFailed)PicklableWithSlotsdict_from_expr)public)is_sequenceiterableNc              #   d  K   t        |       }t              rqt              |k7  rt        d      dg|z  nLt              st        d      t              |k7  rt        d      t        d D              rt        d      d}n+}|dk  rt        d      d}ndk  rt        d	      }d
}|rZkD  ry| r|dk(  rt        j
                   yt        |       t        j
                  gz   } t        d | D              rg }t        | |      D ]`  }| D 	ci c]  }	|	d }
}	|D ]  }	|	dk7  s	|
|	xx   dz  cc<    t        |
j                               |k\  sJ|j                  t        |        b t        |      E d{    yg }t        | |      D ]`  }| D 	ci c]  }	|	d }
}	|D ]  }	|	dk7  s	|
|	xx   dz  cc<    t        |
j                               |k\  sJ|j                  t        |        b t        |      E d{    yt        fdt        |      D              rt        d      g }t!        |       D ]5  \  }}}|j                  t        ||dz         D cg c]  }||z  	 c}       7 t        | D ]  }
t        |
   yc c}	w 7 c c}	w 7 c c}w w)a  
    ``max_degrees`` and ``min_degrees`` are either both integers or both lists.
    Unless otherwise specified, ``min_degrees`` is either ``0`` or
    ``[0, ..., 0]``.

    A generator of all monomials ``monom`` is returned, such that
    either
    ``min_degree <= total_degree(monom) <= max_degree``,
    or
    ``min_degrees[i] <= degree_list(monom)[i] <= max_degrees[i]``,
    for all ``i``.

    Case I. ``max_degrees`` and ``min_degrees`` are both integers
    =============================================================

    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.

    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)
        >>> set(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]

    Case II. ``max_degrees`` and ``min_degrees`` are both lists
    ===========================================================

    If ``max_degrees = [d_1, ..., d_n]`` and
    ``min_degrees = [e_1, ..., e_n]``, the number of monomials generated
    is:

    .. math::
        (d_1 - e_1 + 1) (d_2 - e_2 + 1) \cdots (d_n - e_n + 1)

    Let us generate all monomials ``monom`` in variables $x$ and $y$
    such that ``[1, 2][i] <= degree_list(monom)[i] <= [2, 4][i]``,
    ``i = 0, 1`` ::

        >>> 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, 4], [1, 2]), reverse=True, key=monomial_key('lex', [x, y]))
        [x**2*y**4, x**2*y**3, x**2*y**2, x*y**4, x*y**3, x*y**2]
    zArgument sizes do not matchNr   zmin_degrees is not a listc              3   &   K   | ]	  }|d k    ywr   N ).0is     7/usr/lib/python3/dist-packages/sympy/polys/monomials.py	<genexpr>z itermonomials.<locals>.<genexpr>b   s     .Q1q5.   z+min_degrees cannot contain negative numbersFzmax_degrees cannot be negativezmin_degrees cannot be negativeTc              3   4   K   | ]  }|j                     y wN)is_commutative)r   variables     r   r   z itermonomials.<locals>.<genexpr>x   s     A8x&&As      )repeatc              3   4   K   | ]  }|   |   kD    y wr   r   )r   r   max_degreesmin_degreess     r   r   z itermonomials.<locals>.<genexpr>   s     A1{1~A.As   z2min_degrees[i] must be <= max_degrees[i] for all i)lenr   
ValueErroranyr   Onelistallr   sumvaluesappendr   setr   rangezip)	variablesr    r!   ntotal_degree
max_degree
min_degreemonomials_list_commitemr   powersmonomials_list_non_commpower_listsvarmin_dmax_dr   s    ``              r   itermonomialsr;      s    T 	IA;{q :;;#a%K[)899;1$ !>??.+.. !NOO 
>=>>JQ !ABB$J
"J!O%%KOquug-	AyAA"$5iL ;6?@((A+@@ $ .H1}x(A-(. v}}':5'..sDz:; .///&(#	*= ?6?@((A+@@ $ .H1}x(A-(. v}}':5+223:>? 2333AaAAQRR!$Y[!I 	JCeUQY0GH1QHI	J{+ 	Fv,	/ A 0 A 4  Isg   DJ0
J(J05+J0!'J0J!	J0$
J$.J0;+J0''J0J)A J0/J+
;'J0$J0+J0c                 H    ddl m}  || |z          ||       z   ||      z  S )aW  
    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 = list(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)(sympy.functions.combinatorial.factorialsr=   )VNr=   s      r   monomial_countrA      s)    < CQUil*Yq\99    c                 d    t        t        | |      D cg c]
  \  }}||z    c}}      S c c}}w )a%  
    Multiplication of tuples representing monomials.

    Examples
    ========

    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`.

    tupler-   ABabs       r   monomial_mulrK      s+    " SAY0TQ1q50110   ,
c                 V    t        | |      }t        d |D              rt        |      S y)a  
    Division of tuples representing monomials.

    Examples
    ========

    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              3   &   K   | ]	  }|d k\    ywr   r   )r   cs     r   r   zmonomial_div.<locals>.<genexpr>   s     
a16
r   N)monomial_ldivr'   rE   )rG   rH   Cs      r   monomial_divrR      s*    , 	aA

1
QxrB   c                 d    t        t        | |      D cg c]
  \  }}||z
   c}}      S c c}}w )a  
    Division of tuples representing monomials.

    Examples
    ========

    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`.

    rD   rF   s       r   rP   rP      s+    , SAY0TQ1q50110rL   c                 D    t        | D cg c]  }||z  	 c}      S c c}w )z%Return the n-th pow of the monomial. )rE   )rG   r/   rI   s      r   monomial_powrU      s    #11Q3#$$#s   c           
      r    t        t        | |      D cg c]  \  }}t        ||       c}}      S c c}}w )a.  
    Greatest common divisor of tuples representing monomials.

    Examples
    ========

    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`.

    )rE   r-   minrF   s       r   monomial_gcdrX     -    " Q4A3q!94554   3
c           
      r    t        t        | |      D cg c]  \  }}t        ||       c}}      S c c}}w )a1  
    Least common multiple of tuples representing monomials.

    Examples
    ========

    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`.

    )rE   r-   maxrF   s       r   monomial_lcmr]     rY   rZ   c                 :    t        d t        | |      D              S )z
    Does there exist a monomial X such that XA == B?

    Examples
    ========

    >>> from sympy.polys.monomials import monomial_divides
    >>> monomial_divides((1, 2), (3, 4))
    True
    >>> monomial_divides((1, 2), (0, 2))
    False
    c              3   ,   K   | ]  \  }}||k    y wr   r   )r   rI   rJ   s      r   r   z#monomial_divides.<locals>.<genexpr>5  s     ,$!QqAv,s   )r'   r-   )rG   rH   s     r   monomial_dividesr`   (  s     ,#a),,,rB   c                      t        | d         }| dd D ]'  }t        |      D ]  \  }}t        ||   |      ||<    ) t        |      S )a  
    Returns maximal degree for each variable in a set of monomials.

    Examples
    ========

    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\   rE   monomsMr@   r   r/   s        r   monomial_maxrf   7  [    " 	VAYAABZ  aL 	 DAqqtQ<AaD	   8OrB   c                      t        | d         }| dd D ]'  }t        |      D ]  \  }}t        ||   |      ||<    ) t        |      S )a  
    Returns minimal degree for each variable in a set of monomials.

    Examples
    ========

    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&   rb   rW   rE   rc   s        r   monomial_minri   P  rg   rB   c                     t        |       S )z
    Returns the total degree of a monomial.

    Examples
    ========

    The total degree of `xy^2` is 3:

    >>> from sympy.polys.monomials import monomial_deg
    >>> monomial_deg((1, 2))
    3
    )r(   )re   s    r   monomial_degrk   i  s     q6MrB   c                     | \  }}|\  }}t        ||      }|j                  r|||j                  ||      fS y|||z  s||j                  ||      fS y)z,Division of two terms in over a ring/field. N)rR   is_Fieldquo)rI   rJ   domaina_lma_lcb_lmb_lcmonoms           r   term_divru   x  sj    JD$JD$t$E&**T4000&**T4000rB   c                   L    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zy)MonomialOpsz6Code generator of fast monomial arithmetic functions. c                     || _         y r   )ngens)selfry   s     r   __init__zMonomialOps.__init__  s	    
rB   c                 (    i }t        ||       ||   S r   )exec)rz   codenamenss       r   _buildzMonomialOps._build  s    T2$xrB   c                 Z    t        | j                        D cg c]  }||
 c}S c c}w r   )r,   ry   )rz   r   r   s      r   _varszMonomialOps._vars  s$    -24::->@4#@@@s   (c                 D   d}t        d      }| j                  d      }| j                  d      }t        ||      D cg c]  \  }}|d| }}}||dj                  |      dj                  |      dj                  |      dz  }| j	                  ||      S c c}}w )NrK   s        def %(name)s(A, B):
            (%(A)s,) = A
            (%(B)s,) = B
            return (%(AB)s,)
        rI   rJ    + , r   rG   rH   ABr   r   r-   joinr   	rz   r   templaterG   rH   rI   rJ   r   r~   s	            r   mulzMonomialOps.mul  s       JJsOJJsO.1!Qi9daAq!994diil1UYU^U^_aUbcc{{4&& :   Bc                     d}t        d      }| j                  d      }|D cg c]  }d|z  	 }}||dj                  |      dj                  |      dz  }| j                  ||      S c c}w )NrU   zZ        def %(name)s(A, k):
            (%(A)s,) = A
            return (%(Ak)s,)
        rI   z%s*kr   )r   rG   Ak)r   r   r   r   )rz   r   r   rG   rI   r   r~   s          r   powzMonomialOps.pow  ss      
 JJsO#$&avz&&4diil$))B-PP{{4&& 's   A*c                 F   d}t        d      }| j                  d      }| j                  d      }t        ||      D cg c]  \  }}|d|d }}}||dj                  |      dj                  |      dj                  |      dz  }| j	                  ||      S c c}}w )	Nmonomial_mulpowzw        def %(name)s(A, B, k):
            (%(A)s,) = A
            (%(B)s,) = B
            return (%(ABk)s,)
        rI   rJ   r   z*kr   )r   rG   rH   ABkr   )	rz   r   r   rG   rH   rI   rJ   r   r~   s	            r   mulpowzMonomialOps.mulpow  s        JJsOJJsO14Q<Aq!$<<4diil1VZV_V_`cVdee{{4&& =s   Bc                 D   d}t        d      }| j                  d      }| j                  d      }t        ||      D cg c]  \  }}|d| }}}||dj                  |      dj                  |      dj                  |      dz  }| j	                  ||      S c c}}w )NrP   r   rI   rJ   z - r   r   r   r   s	            r   ldivzMonomialOps.ldiv  s       JJsOJJsO.1!Qi9daAq!994diil1UYU^U^_aUbcc{{4&& :r   c                    d}t        d      }| j                  d      }| j                  d      }t        | j                        D cg c]	  }dd|iz   }}| j                  d      }||dj	                  |      dj	                  |      d	j	                  |      dj	                  |      d
z  }| j                  ||      S c c}w )NrR   z        def %(name)s(A, B):
            (%(A)s,) = A
            (%(B)s,) = B
            %(RAB)s
            return (%(R)s,)
        rI   rJ   z7r%(i)s = a%(i)s - b%(i)s
    if r%(i)s < 0: return Noner   rr   z
    )r   rG   rH   RABR)r   r   r,   ry   r   r   )	rz   r   r   rG   rH   r   r   r   r~   s	            r   divzMonomialOps.div  s       JJsOJJsO_deieoeo_prZ[JcSTXUrrJJsO4diil1V^VcVcdgVhosoxoxyzo{||{{4&& ss   Cc                 P   d}t        d      }| j                  d      }| j                  d      }t        ||      D cg c]  \  }}|d|d|d| }}}||dj                  |      dj                  |      dj                  |      d	z  }| j	                  ||      S c c}}w )
Nr]   r   rI   rJ    if z >=  else r   r   r   r   s	            r   lcmzMonomialOps.lcm         JJsOJJsOCFq!9N41a1aA6NN4diil1UYU^U^_aUbcc{{4&& O   B"c                 P   d}t        d      }| j                  d      }| j                  d      }t        ||      D cg c]  \  }}|d|d|d| }}}||dj                  |      dj                  |      dj                  |      d	z  }| j	                  ||      S c c}}w )
NrX   r   rI   rJ   r   z <= r   r   r   r   r   s	            r   gcdzMonomialOps.gcd  r   r   N)__name__
__module____qualname____doc__r{   r   r   r   r   r   r   r   r   r   r   rB   r   rw   rw     s8    @
A'
'''' ''rB   rw   c                   v    e Zd ZdZdZddZddZd Zd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zd ZeZd Zd Zd Zy)Monomialz9Class representing a monomial, i.e. a product of powers. )	exponentsgensNc                 ^   t        |      s}t        t        |      |      \  }}t        |      dk(  r<t	        |j                               d   dk(  rt	        |j                               d   }nt        dj                  |            t        t        t        |            | _        || _        y )N)r   r   r   zExpected a monomial got {})r   r   r	   r"   r&   r)   keysr#   formatrE   mapintr   r   )rz   rt   r   reps       r   r{   zMonomial.__init__   s    &wu~DAIC3x1}cjjl!3A!6!!;SXXZ(+ !=!D!DU!KLLs3/	rB   c                 B    | j                  ||xs | j                        S r   )	__class__r   )rz   r   r   s      r   rebuildzMonomial.rebuild  s    ~~i):;;rB   c                 ,    t        | j                        S r   )r"   r   rz   s    r   __len__zMonomial.__len__  s    4>>""rB   c                 ,    t        | j                        S r   )iterr   r   s    r   __iter__zMonomial.__iter__  s    DNN##rB   c                      | j                   |   S r   )r   )rz   r4   s     r   __getitem__zMonomial.__getitem__  s    ~~d##rB   c                 n    t        | j                  j                  | j                  | j                  f      S r   )hashr   r   r   r   r   s    r   __hash__zMonomial.__hash__  s&    T^^,,dnndiiHIIrB   c           	          | j                   rGdj                  t        | j                   | j                        D cg c]  \  }}|d| c}}      S | j                  j
                  d| j                  dS c c}}w )N*z**())r   r   r-   r   r   r   )rz   genexps      r   __str__zMonomial.__str__  s]    9988C		SWSaSaDbdS#s3dee#~~66GG es   A:
c                     |xs | j                   }|st        d| z        t        t        || j                        D cg c]
  \  }}||z   c}} S c c}}w )z3Convert a monomial instance to a SymPy expression. z5Cannot convert %s to an expression without generators)r   r#   r   r-   r   )rz   r   r   r   s       r   as_exprzMonomial.as_expr   sX     tyyG$NP P s4/HJ83c3hJKKJs   A
c                     t        |t              r|j                  }nt        |t        t        f      r|}ny| j                  |k(  S )NF)
isinstancer   r   rE   r   rz   otherr   s      r   __eq__zMonomial.__eq__*  s:    eX&Iu~.I~~**rB   c                     | |k(   S r   r   )rz   r   s     r   __ne__zMonomial.__ne__4  s    5=  rB   c                     t        |t              r|j                  }nt        |t        t        f      r|}nt
        | j                  t        | j                  |            S r   )r   r   r   rE   r   NotImplementedErrorr   rK   r   s      r   __mul__zMonomial.__mul__7  sH    eX&Iu~.I%%||LCDDrB   c                     t        |t              r|j                  }nt        |t        t        f      r|}nt
        t        | j                  |      }|| j                  |      S t        | t        |            r   )	r   r   r   rE   r   r   rR   r   r
   )rz   r   r   results       r   __truediv__zMonomial.__truediv__A  sd    eX&Iu~.I%%dnni8<<''%dHUO<<rB   c                    t        |      }|s| j                  dgt        |       z        S |dkD  rD| j                  }t	        d|      D ]  }t        || j                        } | j                  |      S t        d|z        )Nr   r   z'a non-negative integer expected, got %s)r   r   r"   r   r,   rK   r#   )rz   r   r/   r   r   s        r   __pow__zMonomial.__pow__R  s    J<<CI..UI1a[ D(DNNC	D <<	**FNOOrB   c                     t        |t              r|j                  }n't        |t        t        f      r|}nt        d|z        | j                  t        | j                  |            S )z&Greatest common divisor of monomials. .an instance of Monomial class expected, got %s)r   r   r   rE   r   	TypeErrorr   rX   r   s      r   r   zMonomial.gcda  [    eX&Iu~.I@5HJ J ||LCDDrB   c                     t        |t              r|j                  }n't        |t        t        f      r|}nt        d|z        | j                  t        | j                  |            S )z$Least common multiple of monomials. r   )r   r   r   rE   r   r   r   r]   r   s      r   r   zMonomial.lcmm  r   rB   r   )r   r   r   r   	__slots__r{   r   r   r   r   r   r   r   r   r   r   r   __floordiv__r   r   r   r   rB   r   r   r     sc    C%I	<#$$JHL+!E= LP
E
ErB   r   r   )$r   	itertoolsr   r   textwrapr   
sympy.corer   r   r   r	   sympy.polys.polyerrorsr
   sympy.polys.polyutilsr   r   sympy.utilitiesr   sympy.utilities.iterablesr   r   r;   rA   rK   rR   rP   rU   rX   r]   r`   rf   ri   rk   ru   rw   r   r   rB   r   <module>r      s    F =  - - 6 D " ;E EN:B2&:20%6&6&-22$n' n'` |E! |E |ErB   