
    MZd                         d dl mZ d dlmZmZmZ d dlmZ d dlm	Z	m
Z
mZmZmZ d dlmZmZ d dlmZmZ d dlmZmZ d Zd	d
ddZy)    )combinations_with_replacement)symbolsAddDummy)Rational)cancelComputationFailedparallel_poly_from_exprreducedPoly)Monomialmonomial_div)DomainErrorPolificationFailed)debugdebugfc                     t        |       j                         \  }}	 t        ||gdd      \  }}t	        | t        ||z        z   S # t        $ r ||z  cY S w xY w)z
    Put an expression over a common denominator, cancel and reduce.

    Examples
    ========

    >>> from sympy import ratsimp
    >>> from sympy.abc import x, y
    >>> ratsimp(1/x + 1/y)
    (x + y)/(x*y)
    TF)fieldexpand)r   as_numer_denomr   r	   r   )exprfgQrs        8/usr/lib/python3/dist-packages/sympy/simplify/ratsimp.pyratsimpr   	   sh     $<&&(DAqq1#T%81 7VAaC[    s
s   A AATF)quick
polynomialc                   ddl m t        d|        t        |       j	                         \  }}	 t        ||gz   g|i |\  }j                  }	|	j                  r|	j                         _        nt        d|	z        |dd D 
cg c]  }
|
j                  j                         c}
t               fddfd	t        |j                  j                  	      d
   }t        |j                  j                  	      d
   }|r||z  j                         S  t!        |j                  j                        t!        |j                  j                        g       \  }}}ss|rqt#        dt%        |             g }|D ]D  \  }}}} ||dd      }|j'                  |j)                  |      |j)                  |      f       F t+        |d       \  }}|	j,                  s7|j/                  d      \  }}|j/                  d      \  }}t1        ||      }nt1        d
      }||j2                  z  ||j4                  z  z  S # t        $ r | cY S w xY wc c}
w )a  
    Simplifies a rational expression ``expr`` modulo the prime ideal
    generated by ``G``.  ``G`` should be a Groebner basis of the
    ideal.

    Examples
    ========

    >>> from sympy.simplify.ratsimp import ratsimpmodprime
    >>> from sympy.abc import x, y
    >>> eq = (x + y**5 + y)/(x - y)
    >>> ratsimpmodprime(eq, [x*y**5 - x - y], x, y, order='lex')
    (-x**2 - x*y - x - y)/(-x**2 + x*y)

    If ``polynomial`` is ``False``, the algorithm computes a rational
    simplification which minimizes the sum of the total degrees of
    the numerator and the denominator.

    If ``polynomial`` is ``True``, this function just brings numerator and
    denominator into a canonical form. This is much faster, but has
    potentially worse results.

    References
    ==========

    .. [1] M. Monagan, R. Pearce, Rational Simplification Modulo a Polynomial
        Ideal, https://dl.acm.org/doi/pdf/10.1145/1145768.1145809
        (specifically, the second algorithm)
    r   )solveratsimpmodprimez.Cannot compute rational simplification over %s   Nc                    | dk(  rdgS g }t        t        t        j                              |       D ]U  }dgt        j                        z  |D ]  }|xx   dz  cc<    t	        fdD              sE|j                         W |D cg c]$  } t        |      j                  j                   & c} | dz
        z   S c c}w )z
        Compute all monomials with degree less than ``n`` that are
        not divisible by any element of ``leading_monomials``.
        r      c              3   :   K   | ]  }t        |      d u   y w)N)r   ).0lmgms     r   	<genexpr>z5ratsimpmodprime.<locals>.staircase.<locals>.<genexpr>b   s!      &C<3'4/ &s   )r   rangelengensallappendr   as_expr)	nSmiisr)   leading_monomialsopt	staircases	        @r   r8   z"ratsimpmodprime.<locals>.staircaseV   s    
 63J/c#((m0DaH 	BCM!A !	 &$& &	 9::1###SXX.:Yq1u=MMM:s   )C	c                    | |}}d}| j                         |j                         z   }r|dz
  }	n|}	||z   |	k  r||fv rnÉj                  ||f        |      }
 |      }t        d|||
|f       t        dt	        |
      z  t
              }t        dt	        |      z  t
              }||z   }t        t        t        t	        |
            D cg c]  }||   |
|   z   c}      j                  |z         }t        t        t        t	        |            D cg c]  }||   ||   z   c}      j                  |z         }t        | |z  ||z  z
  j                  |z   j                  d      d   }t        |j                  	      j                         } |||z   dd
      }|r8t        d |j                         D              s|j                  |      }|j                  |      }|j                  t!        t#        t%        ||z   dgt	        |      t	        |      z   z                          }|j                  t!        t#        t%        ||z   dgt	        |      t	        |      z   z                          }t        |j                        }t        |j                        }|dk(  rt'        d      |j)                  |||||z   f       ||z   |k7  r|d   g}n|dz  }|dz  }|dz  }||z   |	k  r|dkD  r& ||||||z
        \  }}} |||||z
  |      \  }}}|||fS c c}w c c}w )ak  
        Computes a rational simplification of ``a/b`` which minimizes
        the sum of the total degrees of the numerator and the denominator.

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

        The algorithm proceeds by looking at ``a * d - b * c`` modulo
        the ideal generated by ``G`` for some ``c`` and ``d`` with degree
        less than ``a`` and ``b`` respectively.
        The coefficients of ``c`` and ``d`` are indeterminates and thus
        the coefficients of the normalform of ``a * d - b * c`` are
        linear polynomials in these indeterminates.
        If these linear polynomials, considered as system of
        equations, have a nontrivial solution, then `\frac{a}{b}
        \equiv \frac{c}{d}` modulo the ideal generated by ``G``. So,
        by construction, the degree of ``c`` and ``d`` is less than
        the degree of ``a`` and ``b``, so a simpler representation
        has been found.
        After a simpler representation has been found, the algorithm
        tries to reduce the degree of the numerator and denominator
        and returns the result afterwards.

        As an extension, if quick=False, we look at all possible degrees such
        that the total degree is less than *or equal to* the best current
        solution. We retain a list of all solutions of minimal degree, and try
        to find the best one at the end.
        r   r%   z%s / %s: %s, %szc:%d)clszd:%dT)orderpolys)r-   
particularr   c              3   &   K   | ]	  }|d k(    yw)r   N )r'   r5   s     r   r*   z<ratsimpmodprime.<locals>._ratsimpmodprime.<locals>.<genexpr>   s     <!qAv<s   zIdeal not prime?)total_degreeaddr   r   r,   r   r   sumr+   r-   r   r;   coeffsr.   valuessubsdictlistzip
ValueErrorr/   )aballsolNDcdstepsmaxdegboundM1M2CsDsngr4   c_hatd_hatr   r2   solG_ratsimpmodprimer7   r   r!   r8   testeds                        r   r_   z)ratsimpmodprime.<locals>._ratsimpmodprimeh   s"   : !1!ANN$44QJEE!eun1vJJ1v1B1B$q!Rn5#b')u5B#b')u5BbBE#b'N;qRURU];<chhmMEE#b'N;qRURU];<chhmME E	AI-q#((R-!iit5568A QSXX&--/A27t4@C3<szz|<<JJsOJJsO
 FF4Sb1#R3r79J2K%L MNOFF4Sb1#R3r79J2K%L MNOCHH%CHH%6$%788ueQR89q5F?$Rj\FQJEFAFA_ !eunb 19+Aq&!QYGLAq&+Aq&!e)QGLAq&!V|O <;s   L7!L<)r;   r%   )domainz*Looking for best minimal solution. Got: %sTFr=   c                 t    t        | d   j                               t        | d   j                               z   S )Nr   r%   )r,   terms)xs    r   <lambda>z!ratsimpmodprime.<locals>.<lambda>   s)    QqTZZ\):S1=N)N     )key)convert)r   r   )sympy.solvers.solversr!   r   r   r   r
   r   ra   has_assoc_Field	get_fieldr   LMr;   setr   r-   r   r   r,   r/   rG   minis_Fieldclear_denomsr   qp)r   r^   r   r   r-   argsnumdenomr<   ra   r   rQ   rR   rN   newsolr[   r\   r2   rZ   r]   cndnr   r_   r6   r7   r!   r8   r`   s    ``                    @@@@@@r   r"   r"      sF   < ,	
T" ,,.JC,c5\A-=MMM
s ZZF%%'
<vEG 	G 38)<Qcii<UFN$Z Z| #q#((#))
4Q
7CE1chhcii8;EE	!!###S#((3::.UCHHSZZ0XZ\^LAq&V;S[I#) 	>E5!R2$e<CMM5::c?EJJsO<=	> 6NO1??t,At,ARQKaccEAaccE?o   =s   I% "I6%I32I3N)	itertoolsr   
sympy.corer   r   r   sympy.core.numbersr   sympy.polysr   r	   r
   r   r   sympy.polys.monomialsr   r   sympy.polys.polyerrorsr   r   sympy.utilities.miscr   r   r   r"   r@   rf   r   <module>r      s2    3 * * ' Y Y 8 B .!, +/5 rf   