o
    8VaE                     @   s  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 d dlmZmZmZ d dlmZ d d	lmZ d d
l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mZ d dl m!Z! dd Z"d ddZ#dd Z$dd Z%dd Z&ddddZ'dS )!    )Add)ordered)
expand_log)Pow)S)Dummy)LambertWexplog)root)roots)Polyfactor)_mexpand)separatevars)collect)powsimp)solve_invert)uniqc                    s^    fdd| j D }t|D ]}d| }||v r,||v r,| d tjur'|}|| q|S )a  process the generators of ``poly``, returning the set of generators that
    have ``symbol``.  If there are two generators that are inverses of each other,
    prefer the one that has no denominator.

    Examples
    ========

    >>> from sympy.solvers.bivariate import _filtered_gens
    >>> from sympy import Poly, exp
    >>> from sympy.abc import x
    >>> _filtered_gens(Poly(x + 1/x + exp(x)), x)
    {x, exp(x)}

    c                    s   h | ]	} |j v r|qS  free_symbols).0gsymbolr   9/usr/lib/python3/dist-packages/sympy/solvers/bivariate.py	<setcomp>"   s    z!_filtered_gens.<locals>.<setcomp>   )genslistas_numer_denomr   ZOneremove)Zpolyr   r    r   Zagr   r   r   _filtered_gens   s   
r$   Nc                    sP    fdd|  D }t|dkr|d S |r&ttt|fdddS dS )	aL  Returns the term in lhs which contains the most of the
    func-type things e.g. log(log(x)) wins over log(x) if both terms appear.

    ``func`` can be a function (exp, log, etc...) or any other SymPy object,
    like Pow.

    If ``X`` is not ``None``, then the function returns the term composed with the
    most ``func`` having the specified variable.

    Examples
    ========

    >>> from sympy.solvers.bivariate import _mostfunc
    >>> from sympy.functions.elementary.exponential import exp
    >>> from sympy.abc import x, y
    >>> _mostfunc(exp(x) + exp(exp(x) + 2), exp)
    exp(exp(x) + 2)
    >>> _mostfunc(exp(x) + exp(exp(y) + 2), exp)
    exp(exp(y) + 2)
    >>> _mostfunc(exp(x) + exp(exp(y) + 2), exp, x)
    exp(x)
    >>> _mostfunc(x, exp, x) is None
    True
    >>> _mostfunc(exp(x) + exp(x*y), exp, x)
    exp(x)
    c                    s4   g | ]} r j r |jv s j s| r|qS r   )Z	is_Symbolr   hasr   tmp)Xr   r   
<listcomp>G   s    
z_mostfunc.<locals>.<listcomp>r   r   c                    s
   |   S N)count)x)funcr   r   <lambda>M   s   
 z_mostfunc.<locals>.<lambda>)keyN)atomslenmaxr!   r   )lhsr-   r(   Zftermsr   )r(   r-   r   	_mostfunc,   s   r4   c                 C   s   ddl m} ||  } | |\}}| jr*|jr*t||\}}}|| || |fS | js5d}||}}n|}t|j|dd\}}| rL| }| }|||fS )a(  Return ``a, b, X`` assuming ``arg`` can be written as ``a*X + b``
    where ``X`` is a symbol-dependent factor and ``a`` and ``b`` are
    independent of ``symbol``.

    Examples
    ========

    >>> from sympy.functions.elementary.exponential import exp
    >>> from sympy.solvers.bivariate import _linab
    >>> from sympy.abc import x, y
    >>> from sympy import S
    >>> _linab(S(2), x)
    (2, 0, 1)
    >>> _linab(2*x, x)
    (2, 0, x)
    >>> _linab(y + y*x + 2*x, x)
    (y + 2, y, x)
    >>> _linab(3 + 2*exp(x), x)
    (2, 3, exp(x))
    r   )factor_termsFZas_Add)	Zsympy.core.exprtoolsr5   expandas_independentis_Mulis_Add_linabr   could_extract_minus_sign)argr   r5   ZindZdepabr,   r   r   r   r;   Q   s   
r;   c              	      s  t t| } t| t|}|sg S | |d}t| tr>| | ||jd } |jd }t|ts3g S | jd  }| |7 } ||jvrEg S t||\}}t	| | |}|
|  du sb| jv rdg S |jd }t||\}}	|	|krwg S td}
t|	|
 |}ddg}g }| |      \}}| \}}t|| }td} fddt|| | | D }|D ]+}|D ]&}t||}|r|jsq|    |  }|D ]}|||
| qqq|S )z
    Given an expression assumed to be in the form
        ``F(X, a..f) = a*log(b*X + c) + d*X + f = 0``
    where X = g(x) and x = g^-1(X), return the Lambert solution,
        ``x = g^-1(-c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(-f/a)))``.
    r   Nrhstc                    s   g | ]
}   | qS r   r   )r   rB   r>   r?   dr   r   r)      s    z_lambert.<locals>.<listcomp>)r   r   r4   r
   subs
isinstanceargsr   r;   r   Zas_coefficientr   r   r"   Zas_coeff_Mulr	   r   keysr   Zis_realappend)eqr,   mainlogotherfZX2ZlogtermZlogargcZX1uZxusolnsZlambert_real_branchesZsolZnumZdenperB   rG   r=   kwr@   Zxur   rC   r   _lambertx   sV   





 
(

rT   c                    s   fdd}| j dd\}}| }fdd D }|s t |js&|jrtdi j|fdd	fd
d	}|jrp|rp|d}|| }	|| }
|	jso|
ro|	t	j
t	jsott|	t|
 }||S n#|jr|rtt|dd}t|}|r|jr|| }||S |i}tt|dd}t }t|| \}}|||i}g }|st|t}|r|jr|dkrtt|t| }nG|jr||d}|r|jsfdd|tD r|st|t||  }nt|| t||  }tt|}nt|| }|sxt|t}|rxt||}|jrE|dkrEttt|t| }n3|jrx||d}|| }|| }| ri| ri|d9 }|d9 }t|t| }tt|}|st|t}|rȈ|jjv rt||}|jr|dkrttt|t| }n!|jr||d}|| }|| }t|t| }tt|}|std|  tt|S )a  Return solution to ``f`` if it is a Lambert-type expression
    else raise NotImplementedError.

    For ``f(X, a..f) = a*log(b*X + c) + d*X - f = 0`` the solution
    for ``X`` is ``X = -c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(f/a))``.
    There are a variety of forms for `f(X, a..f)` as enumerated below:

    1a1)
      if B**B = R for R not in [0, 1] (since those cases would already
      be solved before getting here) then log of both sides gives
      log(B) + log(log(B)) = log(log(R)) and
      X = log(B), a = 1, b = 1, c = 0, d = 1, f = log(log(R))
    1a2)
      if B*(b*log(B) + c)**a = R then log of both sides gives
      log(B) + a*log(b*log(B) + c) = log(R) and
      X = log(B), d=1, f=log(R)
    1b)
      if a*log(b*B + c) + d*B = R and
      X = B, f = R
    2a)
      if (b*B + c)*exp(d*B + g) = R then log of both sides gives
      log(b*B + c) + d*B + g = log(R) and
      X = B, a = 1, f = log(R) - g
    2b)
      if g*exp(d*B + h) - b*B = c then the log form is
      log(g) + d*B + h - log(b*B + c) = 0 and
      X = B, a = -1, f = -h - log(g)
    3)
      if d*p**(a*B + g) - b*B = c then the log form is
      log(d) + (a*B + g)*log(p) - log(b*B + c) = 0 and
      X = B, a = -1, d = a*log(p), f = -log(d) - g*log(p)
    c                    sL    fdddD \}}t |}||kr |t | tt|S )a  Return the unique solutions of equations derived from
        ``expr`` by replacing ``t`` with ``+/- symbol``.

        Parameters
        ==========

        expr : Expr
            The expression which includes a dummy variable t to be
            replaced with +symbol and -symbol.

        symbol : Symbol
            The symbol for which a solution is being sought.

        Returns
        =======

        List of unique solution of the two equations generated by
        replacing ``t`` with positive and negative ``symbol``.

        Notes
        =====

        If ``expr = 2*log(t) + x/2` then solutions for
        ``2*log(x) + x/2 = 0`` and ``2*log(-x) + x/2 = 0`` are
        returned by this function. Though this may seem
        counter-intuitive, one must note that the ``expr`` being
        solved here has been derived from a different expression. For
        an expression like ``eq = x**2*g(x) = 1``, if we take the
        log of both sides we obtain ``log(x**2) + log(g(x)) = 0``. If
        x is positive then this simplifies to
        ``2*log(x) + log(g(x)) = 0``; the Lambert-solving routines will
        return solutions for this, but we must also consider the
        solutions for  ``2*log(-x) + log(g(x))`` since those must also
        be a solution of ``eq`` which has the same value when the ``x``
        in ``x**2`` is negated. If `g(x)` does not have even powers of
        symbol then we don't want to replace the ``x`` there with
        ``-x``. So the role of the ``t`` in the expression received by
        this function is to mark where ``+/-x`` should be inserted
        before obtaining the Lambert solutions.

        c                    s   g | ]}  | iqS r   )xreplace)r   Zsgnexprr   rB   r   r   r)     s    zC_solve_lambert.<locals>._solve_even_degree_expr.<locals>.<listcomp>)rA   r   )_solve_lambertextendr!   r   )rW   rB   r   ZnlhsZplhsZsols)r    rV   r   _solve_even_degree_expr   s   *
z/_solve_lambert.<locals>._solve_even_degree_exprTr6   c                    s0   g | ]}|j ttfv s|jr |jjv r|qS r   )r-   r	   r
   is_Powr   r&   r   r   r   r)     s    

z"_solve_lambert.<locals>.<listcomp>rB   c                    s   | j o| j ko| jjS r*   )r[   baser	   Zis_evenir   r   r   r.   (  s   z _solve_lambert.<locals>.<lambda>c                    s
    | j  S r*   )r	   r]   rB   r   r   r.   *  s   
r   )Zforce)Zdeepc                    s   g | ]	} |j v r|qS r   r   r&   r   r   r   r)   \  s    rA   z:%s does not appear to have a solution in terms of LambertWNr_   )r8   NotImplementedErrorr:   r9   r   Zassumptions0replacer%   rE   r   ZComplexInfinityZNaNr   r
   rU   r   r   r   r4   rT   r0   r   r	   r   r<   r   r!   r   )rM   r   r    rZ   Znrhsr3   r@   ZlamcheckZt_indepZt_termZ_rhsrJ   rr^   ZsolnrK   rL   ZdiffZmainexpZmaintermZmainpowr   )r    r   rB   r   rX      s   "6






rX   Tfirstc                   s8  t ddd}|rFt|  }| } t  }t  }tt|  ||i||||dd}|rD| |i}	|d |	|d |	|d fS d	S | }| } t| }
g }|
D ]}t| | }|j	} |v sn|v rp n|
| qW  t| |fS  fd
d}g }| }||krt| | |}t|| |}||  ||  | }|d	ur|  |  ||fS g }| }||krtdD ]C}t| | |  |}t|| |}||  ||  |  }|d	ur|   |  ||f  S   qd	S d	S )a  Given an expression, f, 3 tests will be done to see what type
    of composite bivariate it might be, options for u(x, y) are::

        x*y
        x+y
        x*y+x
        x*y+y

    If it matches one of these types, ``u(x, y)``, ``P(u)`` and dummy
    variable ``u`` will be returned. Solving ``P(u)`` for ``u`` and
    equating the solutions to ``u(x, y)`` and then solving for ``x`` or
    ``y`` is equivalent to solving the original expression for ``x`` or
    ``y``. If ``x`` and ``y`` represent two functions in the same
    variable, e.g. ``x = g(t)`` and ``y = h(t)``, then if ``u(x, y) - p``
    can be solved for ``t`` then these represent the solutions to
    ``P(u) = 0`` when ``p`` are the solutions of ``P(u) = 0``.

    Only positive values of ``u`` are considered.

    Examples
    ========

    >>> from sympy.solvers.solvers import solve
    >>> from sympy.solvers.bivariate import bivariate_type
    >>> from sympy.abc import x, y
    >>> eq = (x**2 - 3).subs(x, x + y)
    >>> bivariate_type(eq, x, y)
    (x + y, _u**2 - 3, _u)
    >>> uxy, pu, u = _
    >>> usol = solve(pu, u); usol
    [sqrt(3)]
    >>> [solve(uxy - s) for s in solve(pu, u)]
    [[{x: -y + sqrt(3)}]]
    >>> all(eq.subs(s).equals(0) for sol in _ for s in sol)
    True

    rO   T)ZpositiveFrc   r   r      Nc                    s.   t | ||}|j} |v s|v rd S |S r*   )r   rE   r   )rM   vrN   newfreer,   yr   r   ok  s   zbivariate_type.<locals>.ok)r   r   Zas_exprbivariate_typerE   rU   r   Z	make_argsr   r   rI   Zdegreer   Zcoeff_monomialrange)rM   r,   rj   rd   rO   rP   Z_xZ_yZrvZrepsrG   rg   r>   rh   rk   rD   r?   Zitryr   ri   r   rl     sV   '&"


rl   r*   )(Zsympy.core.addr   Zsympy.core.compatibilityr   Zsympy.core.functionr   Zsympy.core.powerr   Zsympy.core.singletonr   Zsympy.core.symbolr   Z&sympy.functions.elementary.exponentialr   r	   r
   Z(sympy.functions.elementary.miscellaneousr   Zsympy.polys.polyrootsr   Zsympy.polys.polytoolsr   r   r   Zsympy.simplify.simplifyr   Zsympy.simplify.radsimpr   r   Zsympy.solvers.solversr   r   Zsympy.utilities.iterablesr   r$   r4   r;   rT   rX   rl   r   r   r   r   <module>   s.    
%'I a