B
    [2                 @   s   d dl 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 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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 Z!dddZ"dd Z#dd Z$dd Z%dd Z&dS )    )print_functiondivision)Add)orderedrange)
expand_log)Pow)S)Dummy)LambertWexplog)root)Polyfactor)_mexpand)separatevars)collect)solve_invertc                sb    fdd| j D }xHt|D ]<}d| }||kr||kr| d tjk	rP|}|| qW |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 kr|qS  )free_symbols).0g)symbolr   6lib/python3.7/site-packages/sympy/solvers/bivariate.py	<setcomp>!   s    z!_filtered_gens.<locals>.<setcomp>   )genslistZ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 |rLttt|fdddS dS )	a~  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.utilities.pytest import raises
    >>> 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ks, j s| r|qS r   )Z	is_Symbolr   Z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    r.   c             C   sd   |   } | |\}}| js,d}|| }}n|}t|j|dd\}}| rZ| }| }|||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   F)as_Add)expandas_independentis_Addr   could_extract_minus_sign)argr   ZindZdepbar&   r   r   r   _linabQ   s    r7   c             C   s  t t| } t| t|}|s g S | |d}t| tr|| | ||jd } |jd }t|tsfg S | jd  }| |7 } ||jkrg S t||\}}}t	| | |}|
|}|dks||jkrg S |jd }	t|	|\}
}}||krg S td}g }xdD ]}t|||
  t|| | |
  t| |  |}|rJ|jsJq | |
 || |  }t|| |}x4t|D ](\}}|||||< |||  qxW q W |S )a   
    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 if possible:
        ``x = g^-1(-c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(-f/a)))``.
    r   Nrhs)r   )r   r   r.   r   subs
isinstanceargsr   r7   r   Zas_coefficientr
   r   r   Zis_realr   	enumerateappend)eqr&   mainlogotherdfZX2Zlogtermr6   Zlogargr5   cZX1uZsolklr8   Zsolnsir"   r   r   r   _lambertu   sF    





4rI   c                s  | j  dd\}}| } fdd|D }|s4t |jrNtt|}t|}t|dd}t }t||  \}}|||i}g }	|	sPt	|t }
|
rP|jr|dkrt
t|t|  }	n|jrP||
d}|rB|jsB fdd|tD rB|st|t||  }nt|| t||  }t
t| }	nt
||  }	|	st	|t }|rt||}|jr|dkrt
tt|t|  }	nf|jr||d}|| }|| }| r| r|d9 }|d9 }t|t| }t
t| }	|	st	|t }|r |jjkrt||}|jrd|dkrdt
tt|t|  }	nB|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.

    The equality, ``f(x, a..f) = a*log(b*X + c) + d*X - f = 0`` has the
    solution,  `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 [0, 1] then
      log(B) + log(log(B)) = log(log(R))
      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(B) + a*log(b*log(B) + c) = log(R)
      X = log(B); d=1, f=log(R)
    1b)
      if a*log(b*B + c) + d*B = R then
      X = B, f = R
    2a)
      if (b*B + c)*exp(d*B + g) = R then
      log(b*B + c) + d*B + g = log(R)
      a = 1, f = log(R) - g, X = B
    2b)
      if -b*B + g*exp(d*B + h) = c then
      log(g) + d*B + h - log(b*B + c) = 0
      a = -1, f = -h - log(g), X = B
    3)
      if d*p**(a*B + g) - b*B = c then
      log(d) + (a*B + g)*log(p) - log(c + b*B) = 0
      a = -1, d = a*log(p), f = -log(d) - g*log(p)
    T)r/   c                s0   g | ](}|j ttgks(|jr |jjkr|qS r   )r'   r   r   Zis_Powr   )r   r"   )r   r   r   r$      s    z"_solve_lambert.<locals>.<listcomp>)Zdeepr   c                s   g | ]} |j kr|qS r   )r   )r   r"   )r   r   r   r$      s    r9   z:%s does not appear to have a solution in terms of LambertW)r1   NotImplementedErrorZis_Mulr   r   r   r
   r   xreplacer.   rI   r2   r:   r*   r   r   r   r3   r   r   r   )rC   r   r   Znrhsr-   r8   ZlamcheckrrH   Zsolnr@   rA   ZdiffZmainexpZmaintermZmainpowr   )r   r   _solve_lambert   sv    !



rM   c                sD  t ddd}|ddrt|  }| } t  }t  }tt|  ||i||||dd}|r| |i}	|d |	|d |	|d	 fS d
S | }| } t| }
g }xT|
D ]:}t	| | }|j
} |ks|krP || qW   t| |fS  fdd}g }| }||krt| | |}t|| |}||  ||  | }|d
k	r|  |  ||fS g }| }||kr@xtd	D ]}t| | |  |}t|| |}||  ||  |  }|d
k	r0|   |  ||fS    qW 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

    rE   T)ZpositivefirstF)rN   r   r      Nc                s.   t | ||}|j} |ks&|kr*d S |S )N)r   r:   r   )rC   vrD   newfree)r&   yr   r   okw  s    zbivariate_type.<locals>.ok)r
   popr   Zas_exprbivariate_typer:   rK   r   Z	make_argsr   r   r>   Zdegreer   Zcoeff_monomialr   )rC   r&   rS   kwargsrE   pZ_xZ_yrvZrepsr<   rQ   r6   rR   rT   rB   r5   Zitryr   )r&   rS   r   rV   4  sR    '&"




rV   )N)'Z
__future__r   r   Zsympy.core.addr   Zsympy.core.compatibilityr   r   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.polytoolsr   r   r   Zsympy.simplify.simplifyr   Zsympy.simplify.radsimpr   Zsympy.solvers.solversr   r   r!   r.   r7   rI   rM   rV   r   r   r   r   <module>   s(   
&$1 