1"""
2This module contain solvers for all kinds of equations:
3
4    - algebraic or transcendental, use solve()
5
6    - recurrence, use rsolve()
7
8    - differential, use dsolve()
9
10    - nonlinear (numerically), use nsolve()
11      (you will need a good starting point)
12
13"""
14
15from sympy import divisors, binomial, expand_func
16from sympy.core.assumptions import check_assumptions
17from sympy.core.compatibility import (iterable, is_sequence, ordered,
18    default_sort_key)
19from sympy.core.sympify import sympify
20from sympy.core import (S, Add, Symbol, Equality, Dummy, Expr, Mul,
21    Pow, Unequality)
22from sympy.core.exprtools import factor_terms
23from sympy.core.function import (expand_mul, expand_log,
24                          Derivative, AppliedUndef, UndefinedFunction, nfloat,
25                          Function, expand_power_exp, _mexpand, expand)
26from sympy.integrals.integrals import Integral
27from sympy.core.numbers import ilcm, Float, Rational
28from sympy.core.relational import Relational
29from sympy.core.logic import fuzzy_not
30from sympy.core.power import integer_log
31from sympy.logic.boolalg import And, Or, BooleanAtom
32from sympy.core.basic import preorder_traversal
33
34from sympy.functions import (log, exp, LambertW, cos, sin, tan, acos, asin, atan,
35                             Abs, re, im, arg, sqrt, atan2)
36from sympy.functions.elementary.trigonometric import (TrigonometricFunction,
37                                                      HyperbolicFunction)
38from sympy.simplify import (simplify, collect, powsimp, posify,  # type: ignore
39    powdenest, nsimplify, denom, logcombine, sqrtdenest, fraction,
40    separatevars)
41from sympy.simplify.sqrtdenest import sqrt_depth
42from sympy.simplify.fu import TR1, TR2i
43from sympy.matrices.common import NonInvertibleMatrixError
44from sympy.matrices import Matrix, zeros
45from sympy.polys import roots, cancel, factor, Poly
46from sympy.polys.polyerrors import GeneratorsNeeded, PolynomialError
47
48from sympy.polys.solvers import sympy_eqs_to_ring, solve_lin_sys
49from sympy.functions.elementary.piecewise import piecewise_fold, Piecewise
50
51from sympy.utilities.lambdify import lambdify
52from sympy.utilities.misc import filldedent
53from sympy.utilities.iterables import (cartes, connected_components,
54    generate_bell, uniq)
55from sympy.utilities.decorator import conserve_mpmath_dps
56
57from mpmath import findroot
58
59from sympy.solvers.polysys import solve_poly_system
60from sympy.solvers.inequalities import reduce_inequalities
61
62from types import GeneratorType
63from collections import defaultdict
64import warnings
65
66
67def recast_to_symbols(eqs, symbols):
68    """
69    Return (e, s, d) where e and s are versions of *eqs* and
70    *symbols* in which any non-Symbol objects in *symbols* have
71    been replaced with generic Dummy symbols and d is a dictionary
72    that can be used to restore the original expressions.
73
74    Examples
75    ========
76
77    >>> from sympy.solvers.solvers import recast_to_symbols
78    >>> from sympy import symbols, Function
79    >>> x, y = symbols('x y')
80    >>> fx = Function('f')(x)
81    >>> eqs, syms = [fx + 1, x, y], [fx, y]
82    >>> e, s, d = recast_to_symbols(eqs, syms); (e, s, d)
83    ([_X0 + 1, x, y], [_X0, y], {_X0: f(x)})
84
85    The original equations and symbols can be restored using d:
86
87    >>> assert [i.xreplace(d) for i in eqs] == eqs
88    >>> assert [d.get(i, i) for i in s] == syms
89
90    """
91    if not iterable(eqs) and iterable(symbols):
92        raise ValueError('Both eqs and symbols must be iterable')
93    new_symbols = list(symbols)
94    swap_sym = {}
95    for i, s in enumerate(symbols):
96        if not isinstance(s, Symbol) and s not in swap_sym:
97            swap_sym[s] = Dummy('X%d' % i)
98            new_symbols[i] = swap_sym[s]
99    new_f = []
100    for i in eqs:
101        isubs = getattr(i, 'subs', None)
102        if isubs is not None:
103            new_f.append(isubs(swap_sym))
104        else:
105            new_f.append(i)
106    swap_sym = {v: k for k, v in swap_sym.items()}
107    return new_f, new_symbols, swap_sym
108
109
110def _ispow(e):
111    """Return True if e is a Pow or is exp."""
112    return isinstance(e, Expr) and (e.is_Pow or isinstance(e, exp))
113
114
115def _simple_dens(f, symbols):
116    # when checking if a denominator is zero, we can just check the
117    # base of powers with nonzero exponents since if the base is zero
118    # the power will be zero, too. To keep it simple and fast, we
119    # limit simplification to exponents that are Numbers
120    dens = set()
121    for d in denoms(f, symbols):
122        if d.is_Pow and d.exp.is_Number:
123            if d.exp.is_zero:
124                continue  # foo**0 is never 0
125            d = d.base
126        dens.add(d)
127    return dens
128
129
130def denoms(eq, *symbols):
131    """
132    Return (recursively) set of all denominators that appear in *eq*
133    that contain any symbol in *symbols*; if *symbols* are not
134    provided then all denominators will be returned.
135
136    Examples
137    ========
138
139    >>> from sympy.solvers.solvers import denoms
140    >>> from sympy.abc import x, y, z
141
142    >>> denoms(x/y)
143    {y}
144
145    >>> denoms(x/(y*z))
146    {y, z}
147
148    >>> denoms(3/x + y/z)
149    {x, z}
150
151    >>> denoms(x/2 + y/z)
152    {2, z}
153
154    If *symbols* are provided then only denominators containing
155    those symbols will be returned:
156
157    >>> denoms(1/x + 1/y + 1/z, y, z)
158    {y, z}
159
160    """
161
162    pot = preorder_traversal(eq)
163    dens = set()
164    for p in pot:
165        # Here p might be Tuple or Relational
166        # Expr subtrees (e.g. lhs and rhs) will be traversed after by pot
167        if not isinstance(p, Expr):
168            continue
169        den = denom(p)
170        if den is S.One:
171            continue
172        for d in Mul.make_args(den):
173            dens.add(d)
174    if not symbols:
175        return dens
176    elif len(symbols) == 1:
177        if iterable(symbols[0]):
178            symbols = symbols[0]
179    rv = []
180    for d in dens:
181        free = d.free_symbols
182        if any(s in free for s in symbols):
183            rv.append(d)
184    return set(rv)
185
186
187def checksol(f, symbol, sol=None, **flags):
188    """
189    Checks whether sol is a solution of equation f == 0.
190
191    Explanation
192    ===========
193
194    Input can be either a single symbol and corresponding value
195    or a dictionary of symbols and values. When given as a dictionary
196    and flag ``simplify=True``, the values in the dictionary will be
197    simplified. *f* can be a single equation or an iterable of equations.
198    A solution must satisfy all equations in *f* to be considered valid;
199    if a solution does not satisfy any equation, False is returned; if one or
200    more checks are inconclusive (and none are False) then None is returned.
201
202    Examples
203    ========
204
205    >>> from sympy import symbols
206    >>> from sympy.solvers import checksol
207    >>> x, y = symbols('x,y')
208    >>> checksol(x**4 - 1, x, 1)
209    True
210    >>> checksol(x**4 - 1, x, 0)
211    False
212    >>> checksol(x**2 + y**2 - 5**2, {x: 3, y: 4})
213    True
214
215    To check if an expression is zero using ``checksol()``, pass it
216    as *f* and send an empty dictionary for *symbol*:
217
218    >>> checksol(x**2 + x - x*(x + 1), {})
219    True
220
221    None is returned if ``checksol()`` could not conclude.
222
223    flags:
224        'numerical=True (default)'
225           do a fast numerical check if ``f`` has only one symbol.
226        'minimal=True (default is False)'
227           a very fast, minimal testing.
228        'warn=True (default is False)'
229           show a warning if checksol() could not conclude.
230        'simplify=True (default)'
231           simplify solution before substituting into function and
232           simplify the function before trying specific simplifications
233        'force=True (default is False)'
234           make positive all symbols without assumptions regarding sign.
235
236    """
237    from sympy.physics.units import Unit
238
239    minimal = flags.get('minimal', False)
240
241    if sol is not None:
242        sol = {symbol: sol}
243    elif isinstance(symbol, dict):
244        sol = symbol
245    else:
246        msg = 'Expecting (sym, val) or ({sym: val}, None) but got (%s, %s)'
247        raise ValueError(msg % (symbol, sol))
248
249    if iterable(f):
250        if not f:
251            raise ValueError('no functions to check')
252        rv = True
253        for fi in f:
254            check = checksol(fi, sol, **flags)
255            if check:
256                continue
257            if check is False:
258                return False
259            rv = None  # don't return, wait to see if there's a False
260        return rv
261
262    if isinstance(f, Poly):
263        f = f.as_expr()
264    elif isinstance(f, (Equality, Unequality)):
265        if f.rhs in (S.true, S.false):
266            f = f.reversed
267        B, E = f.args
268        if isinstance(B, BooleanAtom):
269            f = f.subs(sol)
270            if not f.is_Boolean:
271                return
272        else:
273            f = f.rewrite(Add, evaluate=False)
274
275    if isinstance(f, BooleanAtom):
276        return bool(f)
277    elif not f.is_Relational and not f:
278        return True
279
280    if sol and not f.free_symbols & set(sol.keys()):
281        # if f(y) == 0, x=3 does not set f(y) to zero...nor does it not
282        return None
283
284    illegal = {S.NaN,
285               S.ComplexInfinity,
286               S.Infinity,
287               S.NegativeInfinity}
288    if any(sympify(v).atoms() & illegal for k, v in sol.items()):
289        return False
290
291    was = f
292    attempt = -1
293    numerical = flags.get('numerical', True)
294    while 1:
295        attempt += 1
296        if attempt == 0:
297            val = f.subs(sol)
298            if isinstance(val, Mul):
299                val = val.as_independent(Unit)[0]
300            if val.atoms() & illegal:
301                return False
302        elif attempt == 1:
303            if not val.is_number:
304                if not val.is_constant(*list(sol.keys()), simplify=not minimal):
305                    return False
306                # there are free symbols -- simple expansion might work
307                _, val = val.as_content_primitive()
308                val = _mexpand(val.as_numer_denom()[0], recursive=True)
309        elif attempt == 2:
310            if minimal:
311                return
312            if flags.get('simplify', True):
313                for k in sol:
314                    sol[k] = simplify(sol[k])
315            # start over without the failed expanded form, possibly
316            # with a simplified solution
317            val = simplify(f.subs(sol))
318            if flags.get('force', True):
319                val, reps = posify(val)
320                # expansion may work now, so try again and check
321                exval = _mexpand(val, recursive=True)
322                if exval.is_number:
323                    # we can decide now
324                    val = exval
325        else:
326            # if there are no radicals and no functions then this can't be
327            # zero anymore -- can it?
328            pot = preorder_traversal(expand_mul(val))
329            seen = set()
330            saw_pow_func = False
331            for p in pot:
332                if p in seen:
333                    continue
334                seen.add(p)
335                if p.is_Pow and not p.exp.is_Integer:
336                    saw_pow_func = True
337                elif p.is_Function:
338                    saw_pow_func = True
339                elif isinstance(p, UndefinedFunction):
340                    saw_pow_func = True
341                if saw_pow_func:
342                    break
343            if saw_pow_func is False:
344                return False
345            if flags.get('force', True):
346                # don't do a zero check with the positive assumptions in place
347                val = val.subs(reps)
348            nz = fuzzy_not(val.is_zero)
349            if nz is not None:
350                # issue 5673: nz may be True even when False
351                # so these are just hacks to keep a false positive
352                # from being returned
353
354                # HACK 1: LambertW (issue 5673)
355                if val.is_number and val.has(LambertW):
356                    # don't eval this to verify solution since if we got here,
357                    # numerical must be False
358                    return None
359
360                # add other HACKs here if necessary, otherwise we assume
361                # the nz value is correct
362                return not nz
363            break
364
365        if val == was:
366            continue
367        elif val.is_Rational:
368            return val == 0
369        if numerical and val.is_number:
370            return (abs(val.n(18).n(12, chop=True)) < 1e-9) is S.true
371        was = val
372
373    if flags.get('warn', False):
374        warnings.warn("\n\tWarning: could not verify solution %s." % sol)
375    # returns None if it can't conclude
376    # TODO: improve solution testing
377
378
379def solve(f, *symbols, **flags):
380    r"""
381    Algebraically solves equations and systems of equations.
382
383    Explanation
384    ===========
385
386    Currently supported:
387        - polynomial
388        - transcendental
389        - piecewise combinations of the above
390        - systems of linear and polynomial equations
391        - systems containing relational expressions
392
393    Examples
394    ========
395
396    The output varies according to the input and can be seen by example:
397
398        >>> from sympy import solve, Poly, Eq, Function, exp
399        >>> from sympy.abc import x, y, z, a, b
400        >>> f = Function('f')
401
402    Boolean or univariate Relational:
403
404        >>> solve(x < 3)
405        (-oo < x) & (x < 3)
406
407
408    To always get a list of solution mappings, use flag dict=True:
409
410        >>> solve(x - 3, dict=True)
411        [{x: 3}]
412        >>> sol = solve([x - 3, y - 1], dict=True)
413        >>> sol
414        [{x: 3, y: 1}]
415        >>> sol[0][x]
416        3
417        >>> sol[0][y]
418        1
419
420
421    To get a list of *symbols* and set of solution(s) use flag set=True:
422
423        >>> solve([x**2 - 3, y - 1], set=True)
424        ([x, y], {(-sqrt(3), 1), (sqrt(3), 1)})
425
426
427    Single expression and single symbol that is in the expression:
428
429        >>> solve(x - y, x)
430        [y]
431        >>> solve(x - 3, x)
432        [3]
433        >>> solve(Eq(x, 3), x)
434        [3]
435        >>> solve(Poly(x - 3), x)
436        [3]
437        >>> solve(x**2 - y**2, x, set=True)
438        ([x], {(-y,), (y,)})
439        >>> solve(x**4 - 1, x, set=True)
440        ([x], {(-1,), (1,), (-I,), (I,)})
441
442    Single expression with no symbol that is in the expression:
443
444        >>> solve(3, x)
445        []
446        >>> solve(x - 3, y)
447        []
448
449    Single expression with no symbol given. In this case, all free *symbols*
450    will be selected as potential *symbols* to solve for. If the equation is
451    univariate then a list of solutions is returned; otherwise - as is the case
452    when *symbols* are given as an iterable of length greater than 1 - a list of
453    mappings will be returned:
454
455        >>> solve(x - 3)
456        [3]
457        >>> solve(x**2 - y**2)
458        [{x: -y}, {x: y}]
459        >>> solve(z**2*x**2 - z**2*y**2)
460        [{x: -y}, {x: y}, {z: 0}]
461        >>> solve(z**2*x - z**2*y**2)
462        [{x: y**2}, {z: 0}]
463
464    When an object other than a Symbol is given as a symbol, it is
465    isolated algebraically and an implicit solution may be obtained.
466    This is mostly provided as a convenience to save you from replacing
467    the object with a Symbol and solving for that Symbol. It will only
468    work if the specified object can be replaced with a Symbol using the
469    subs method:
470
471    >>> solve(f(x) - x, f(x))
472    [x]
473    >>> solve(f(x).diff(x) - f(x) - x, f(x).diff(x))
474    [x + f(x)]
475    >>> solve(f(x).diff(x) - f(x) - x, f(x))
476    [-x + Derivative(f(x), x)]
477    >>> solve(x + exp(x)**2, exp(x), set=True)
478    ([exp(x)], {(-sqrt(-x),), (sqrt(-x),)})
479
480    >>> from sympy import Indexed, IndexedBase, Tuple, sqrt
481    >>> A = IndexedBase('A')
482    >>> eqs = Tuple(A[1] + A[2] - 3, A[1] - A[2] + 1)
483    >>> solve(eqs, eqs.atoms(Indexed))
484    {A[1]: 1, A[2]: 2}
485
486        * To solve for a symbol implicitly, use implicit=True:
487
488            >>> solve(x + exp(x), x)
489            [-LambertW(1)]
490            >>> solve(x + exp(x), x, implicit=True)
491            [-exp(x)]
492
493        * It is possible to solve for anything that can be targeted with
494          subs:
495
496            >>> solve(x + 2 + sqrt(3), x + 2)
497            [-sqrt(3)]
498            >>> solve((x + 2 + sqrt(3), x + 4 + y), y, x + 2)
499            {y: -2 + sqrt(3), x + 2: -sqrt(3)}
500
501        * Nothing heroic is done in this implicit solving so you may end up
502          with a symbol still in the solution:
503
504            >>> eqs = (x*y + 3*y + sqrt(3), x + 4 + y)
505            >>> solve(eqs, y, x + 2)
506            {y: -sqrt(3)/(x + 3), x + 2: -2*x/(x + 3) - 6/(x + 3) + sqrt(3)/(x + 3)}
507            >>> solve(eqs, y*x, x)
508            {x: -y - 4, x*y: -3*y - sqrt(3)}
509
510        * If you attempt to solve for a number remember that the number
511          you have obtained does not necessarily mean that the value is
512          equivalent to the expression obtained:
513
514            >>> solve(sqrt(2) - 1, 1)
515            [sqrt(2)]
516            >>> solve(x - y + 1, 1)  # /!\ -1 is targeted, too
517            [x/(y - 1)]
518            >>> [_.subs(z, -1) for _ in solve((x - y + 1).subs(-1, z), 1)]
519            [-x + y]
520
521        * To solve for a function within a derivative, use ``dsolve``.
522
523    Single expression and more than one symbol:
524
525        * When there is a linear solution:
526
527            >>> solve(x - y**2, x, y)
528            [(y**2, y)]
529            >>> solve(x**2 - y, x, y)
530            [(x, x**2)]
531            >>> solve(x**2 - y, x, y, dict=True)
532            [{y: x**2}]
533
534        * When undetermined coefficients are identified:
535
536            * That are linear:
537
538                >>> solve((a + b)*x - b + 2, a, b)
539                {a: -2, b: 2}
540
541            * That are nonlinear:
542
543                >>> solve((a + b)*x - b**2 + 2, a, b, set=True)
544                ([a, b], {(-sqrt(2), sqrt(2)), (sqrt(2), -sqrt(2))})
545
546        * If there is no linear solution, then the first successful
547          attempt for a nonlinear solution will be returned:
548
549            >>> solve(x**2 - y**2, x, y, dict=True)
550            [{x: -y}, {x: y}]
551            >>> solve(x**2 - y**2/exp(x), x, y, dict=True)
552            [{x: 2*LambertW(-y/2)}, {x: 2*LambertW(y/2)}]
553            >>> solve(x**2 - y**2/exp(x), y, x)
554            [(-x*sqrt(exp(x)), x), (x*sqrt(exp(x)), x)]
555
556    Iterable of one or more of the above:
557
558        * Involving relationals or bools:
559
560            >>> solve([x < 3, x - 2])
561            Eq(x, 2)
562            >>> solve([x > 3, x - 2])
563            False
564
565        * When the system is linear:
566
567            * With a solution:
568
569                >>> solve([x - 3], x)
570                {x: 3}
571                >>> solve((x + 5*y - 2, -3*x + 6*y - 15), x, y)
572                {x: -3, y: 1}
573                >>> solve((x + 5*y - 2, -3*x + 6*y - 15), x, y, z)
574                {x: -3, y: 1}
575                >>> solve((x + 5*y - 2, -3*x + 6*y - z), z, x, y)
576                {x: 2 - 5*y, z: 21*y - 6}
577
578            * Without a solution:
579
580                >>> solve([x + 3, x - 3])
581                []
582
583        * When the system is not linear:
584
585            >>> solve([x**2 + y -2, y**2 - 4], x, y, set=True)
586            ([x, y], {(-2, -2), (0, 2), (2, -2)})
587
588        * If no *symbols* are given, all free *symbols* will be selected and a
589          list of mappings returned:
590
591            >>> solve([x - 2, x**2 + y])
592            [{x: 2, y: -4}]
593            >>> solve([x - 2, x**2 + f(x)], {f(x), x})
594            [{x: 2, f(x): -4}]
595
596        * If any equation does not depend on the symbol(s) given, it will be
597          eliminated from the equation set and an answer may be given
598          implicitly in terms of variables that were not of interest:
599
600            >>> solve([x - y, y - 3], x)
601            {x: y}
602
603    **Additional Examples**
604
605    ``solve()`` with check=True (default) will run through the symbol tags to
606    elimate unwanted solutions. If no assumptions are included, all possible
607    solutions will be returned:
608
609        >>> from sympy import Symbol, solve
610        >>> x = Symbol("x")
611        >>> solve(x**2 - 1)
612        [-1, 1]
613
614    By using the positive tag, only one solution will be returned:
615
616        >>> pos = Symbol("pos", positive=True)
617        >>> solve(pos**2 - 1)
618        [1]
619
620    Assumptions are not checked when ``solve()`` input involves
621    relationals or bools.
622
623    When the solutions are checked, those that make any denominator zero
624    are automatically excluded. If you do not want to exclude such solutions,
625    then use the check=False option:
626
627        >>> from sympy import sin, limit
628        >>> solve(sin(x)/x)  # 0 is excluded
629        [pi]
630
631    If check=False, then a solution to the numerator being zero is found: x = 0.
632    In this case, this is a spurious solution since $\sin(x)/x$ has the well
633    known limit (without dicontinuity) of 1 at x = 0:
634
635        >>> solve(sin(x)/x, check=False)
636        [0, pi]
637
638    In the following case, however, the limit exists and is equal to the
639    value of x = 0 that is excluded when check=True:
640
641        >>> eq = x**2*(1/x - z**2/x)
642        >>> solve(eq, x)
643        []
644        >>> solve(eq, x, check=False)
645        [0]
646        >>> limit(eq, x, 0, '-')
647        0
648        >>> limit(eq, x, 0, '+')
649        0
650
651    **Disabling High-Order Explicit Solutions**
652
653    When solving polynomial expressions, you might not want explicit solutions
654    (which can be quite long). If the expression is univariate, ``CRootOf``
655    instances will be returned instead:
656
657        >>> solve(x**3 - x + 1)
658        [-1/((-1/2 - sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)) - (-1/2 -
659        sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)/3, -(-1/2 +
660        sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)/3 - 1/((-1/2 +
661        sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)), -(3*sqrt(69)/2 +
662        27/2)**(1/3)/3 - 1/(3*sqrt(69)/2 + 27/2)**(1/3)]
663        >>> solve(x**3 - x + 1, cubics=False)
664        [CRootOf(x**3 - x + 1, 0),
665         CRootOf(x**3 - x + 1, 1),
666         CRootOf(x**3 - x + 1, 2)]
667
668    If the expression is multivariate, no solution might be returned:
669
670        >>> solve(x**3 - x + a, x, cubics=False)
671        []
672
673    Sometimes solutions will be obtained even when a flag is False because the
674    expression could be factored. In the following example, the equation can
675    be factored as the product of a linear and a quadratic factor so explicit
676    solutions (which did not require solving a cubic expression) are obtained:
677
678        >>> eq = x**3 + 3*x**2 + x - 1
679        >>> solve(eq, cubics=False)
680        [-1, -1 + sqrt(2), -sqrt(2) - 1]
681
682    **Solving Equations Involving Radicals**
683
684    Because of SymPy's use of the principle root, some solutions
685    to radical equations will be missed unless check=False:
686
687        >>> from sympy import root
688        >>> eq = root(x**3 - 3*x**2, 3) + 1 - x
689        >>> solve(eq)
690        []
691        >>> solve(eq, check=False)
692        [1/3]
693
694    In the above example, there is only a single solution to the
695    equation. Other expressions will yield spurious roots which
696    must be checked manually; roots which give a negative argument
697    to odd-powered radicals will also need special checking:
698
699        >>> from sympy import real_root, S
700        >>> eq = root(x, 3) - root(x, 5) + S(1)/7
701        >>> solve(eq)  # this gives 2 solutions but misses a 3rd
702        [CRootOf(7*x**5 - 7*x**3 + 1, 1)**15,
703        CRootOf(7*x**5 - 7*x**3 + 1, 2)**15]
704        >>> sol = solve(eq, check=False)
705        >>> [abs(eq.subs(x,i).n(2)) for i in sol]
706        [0.48, 0.e-110, 0.e-110, 0.052, 0.052]
707
708    The first solution is negative so ``real_root`` must be used to see that it
709    satisfies the expression:
710
711        >>> abs(real_root(eq.subs(x, sol[0])).n(2))
712        0.e-110
713
714    If the roots of the equation are not real then more care will be
715    necessary to find the roots, especially for higher order equations.
716    Consider the following expression:
717
718        >>> expr = root(x, 3) - root(x, 5)
719
720    We will construct a known value for this expression at x = 3 by selecting
721    the 1-th root for each radical:
722
723        >>> expr1 = root(x, 3, 1) - root(x, 5, 1)
724        >>> v = expr1.subs(x, -3)
725
726    The ``solve`` function is unable to find any exact roots to this equation:
727
728        >>> eq = Eq(expr, v); eq1 = Eq(expr1, v)
729        >>> solve(eq, check=False), solve(eq1, check=False)
730        ([], [])
731
732    The function ``unrad``, however, can be used to get a form of the equation
733    for which numerical roots can be found:
734
735        >>> from sympy.solvers.solvers import unrad
736        >>> from sympy import nroots
737        >>> e, (p, cov) = unrad(eq)
738        >>> pvals = nroots(e)
739        >>> inversion = solve(cov, x)[0]
740        >>> xvals = [inversion.subs(p, i) for i in pvals]
741
742    Although ``eq`` or ``eq1`` could have been used to find ``xvals``, the
743    solution can only be verified with ``expr1``:
744
745        >>> z = expr - v
746        >>> [xi.n(chop=1e-9) for xi in xvals if abs(z.subs(x, xi).n()) < 1e-9]
747        []
748        >>> z1 = expr1 - v
749        >>> [xi.n(chop=1e-9) for xi in xvals if abs(z1.subs(x, xi).n()) < 1e-9]
750        [-3.0]
751
752    Parameters
753    ==========
754
755    f :
756        - a single Expr or Poly that must be zero
757        - an Equality
758        - a Relational expression
759        - a Boolean
760        - iterable of one or more of the above
761
762    symbols : (object(s) to solve for) specified as
763        - none given (other non-numeric objects will be used)
764        - single symbol
765        - denested list of symbols
766          (e.g., ``solve(f, x, y)``)
767        - ordered iterable of symbols
768          (e.g., ``solve(f, [x, y])``)
769
770    flags :
771        dict=True (default is False)
772            Return list (perhaps empty) of solution mappings.
773        set=True (default is False)
774            Return list of symbols and set of tuple(s) of solution(s).
775        exclude=[] (default)
776            Do not try to solve for any of the free symbols in exclude;
777            if expressions are given, the free symbols in them will
778            be extracted automatically.
779        check=True (default)
780            If False, do not do any testing of solutions. This can be
781            useful if you want to include solutions that make any
782            denominator zero.
783        numerical=True (default)
784            Do a fast numerical check if *f* has only one symbol.
785        minimal=True (default is False)
786            A very fast, minimal testing.
787        warn=True (default is False)
788            Show a warning if ``checksol()`` could not conclude.
789        simplify=True (default)
790            Simplify all but polynomials of order 3 or greater before
791            returning them and (if check is not False) use the
792            general simplify function on the solutions and the
793            expression obtained when they are substituted into the
794            function which should be zero.
795        force=True (default is False)
796            Make positive all symbols without assumptions regarding sign.
797        rational=True (default)
798            Recast Floats as Rational; if this option is not used, the
799            system containing Floats may fail to solve because of issues
800            with polys. If rational=None, Floats will be recast as
801            rationals but the answer will be recast as Floats. If the
802            flag is False then nothing will be done to the Floats.
803        manual=True (default is False)
804            Do not use the polys/matrix method to solve a system of
805            equations, solve them one at a time as you might "manually."
806        implicit=True (default is False)
807            Allows ``solve`` to return a solution for a pattern in terms of
808            other functions that contain that pattern; this is only
809            needed if the pattern is inside of some invertible function
810            like cos, exp, ect.
811        particular=True (default is False)
812            Instructs ``solve`` to try to find a particular solution to a linear
813            system with as many zeros as possible; this is very expensive.
814        quick=True (default is False)
815            When using particular=True, use a fast heuristic to find a
816            solution with many zeros (instead of using the very slow method
817            guaranteed to find the largest number of zeros possible).
818        cubics=True (default)
819            Return explicit solutions when cubic expressions are encountered.
820        quartics=True (default)
821            Return explicit solutions when quartic expressions are encountered.
822        quintics=True (default)
823            Return explicit solutions (if possible) when quintic expressions
824            are encountered.
825
826    See Also
827    ========
828
829    rsolve: For solving recurrence relationships
830    dsolve: For solving differential equations
831
832    """
833    # keeping track of how f was passed since if it is a list
834    # a dictionary of results will be returned.
835    ###########################################################################
836
837    def _sympified_list(w):
838        return list(map(sympify, w if iterable(w) else [w]))
839    bare_f = not iterable(f)
840    ordered_symbols = (symbols and
841                       symbols[0] and
842                       (isinstance(symbols[0], Symbol) or
843                        is_sequence(symbols[0],
844                        include=GeneratorType)
845                       )
846                      )
847    f, symbols = (_sympified_list(w) for w in [f, symbols])
848    if isinstance(f, list):
849        f = [s for s in f if s is not S.true and s is not True]
850    implicit = flags.get('implicit', False)
851
852    # preprocess symbol(s)
853    ###########################################################################
854    if not symbols:
855        # get symbols from equations
856        symbols = set().union(*[fi.free_symbols for fi in f])
857        if len(symbols) < len(f):
858            for fi in f:
859                pot = preorder_traversal(fi)
860                for p in pot:
861                    if isinstance(p, AppliedUndef):
862                        flags['dict'] = True  # better show symbols
863                        symbols.add(p)
864                        pot.skip()  # don't go any deeper
865        symbols = list(symbols)
866
867        ordered_symbols = False
868    elif len(symbols) == 1 and iterable(symbols[0]):
869        symbols = symbols[0]
870
871    # remove symbols the user is not interested in
872    exclude = flags.pop('exclude', set())
873    if exclude:
874        if isinstance(exclude, Expr):
875            exclude = [exclude]
876        exclude = set().union(*[e.free_symbols for e in sympify(exclude)])
877    symbols = [s for s in symbols if s not in exclude]
878
879
880    # preprocess equation(s)
881    ###########################################################################
882    for i, fi in enumerate(f):
883        if isinstance(fi, (Equality, Unequality)):
884            if 'ImmutableDenseMatrix' in [type(a).__name__ for a in fi.args]:
885                fi = fi.lhs - fi.rhs
886            else:
887                L, R = fi.args
888                if isinstance(R, BooleanAtom):
889                    L, R = R, L
890                if isinstance(L, BooleanAtom):
891                    if isinstance(fi, Unequality):
892                        L = ~L
893                    if R.is_Relational:
894                        fi = ~R if L is S.false else R
895                    elif R.is_Symbol:
896                        return L
897                    elif R.is_Boolean and (~R).is_Symbol:
898                        return ~L
899                    else:
900                        raise NotImplementedError(filldedent('''
901                            Unanticipated argument of Eq when other arg
902                            is True or False.
903                        '''))
904                else:
905                    fi = fi.rewrite(Add, evaluate=False)
906            f[i] = fi
907
908        if fi.is_Relational:
909            return reduce_inequalities(f, symbols=symbols)
910
911        if isinstance(fi, Poly):
912            f[i] = fi.as_expr()
913
914        # rewrite hyperbolics in terms of exp
915        f[i] = f[i].replace(lambda w: isinstance(w, HyperbolicFunction) and \
916            (len(w.free_symbols & set(symbols)) > 0), lambda w: w.rewrite(exp))
917
918        # if we have a Matrix, we need to iterate over its elements again
919        if f[i].is_Matrix:
920            bare_f = False
921            f.extend(list(f[i]))
922            f[i] = S.Zero
923
924        # if we can split it into real and imaginary parts then do so
925        freei = f[i].free_symbols
926        if freei and all(s.is_extended_real or s.is_imaginary for s in freei):
927            fr, fi = f[i].as_real_imag()
928            # accept as long as new re, im, arg or atan2 are not introduced
929            had = f[i].atoms(re, im, arg, atan2)
930            if fr and fi and fr != fi and not any(
931                    i.atoms(re, im, arg, atan2) - had for i in (fr, fi)):
932                if bare_f:
933                    bare_f = False
934                f[i: i + 1] = [fr, fi]
935
936    # real/imag handling -----------------------------
937    if any(isinstance(fi, (bool, BooleanAtom)) for fi in f):
938        if flags.get('set', False):
939            return [], set()
940        return []
941
942    for i, fi in enumerate(f):
943        # Abs
944        while True:
945            was = fi
946            fi = fi.replace(Abs, lambda arg:
947                separatevars(Abs(arg)).rewrite(Piecewise) if arg.has(*symbols)
948                else Abs(arg))
949            if was == fi:
950                break
951
952        for e in fi.find(Abs):
953            if e.has(*symbols):
954                raise NotImplementedError('solving %s when the argument '
955                    'is not real or imaginary.' % e)
956
957        # arg
958        fi = fi.replace(arg, lambda a: arg(a).rewrite(atan2).rewrite(atan))
959
960        # save changes
961        f[i] = fi
962
963    # see if re(s) or im(s) appear
964    freim = [fi for fi in f if fi.has(re, im)]
965    if freim:
966        irf = []
967        for s in symbols:
968            if s.is_real or s.is_imaginary:
969                continue  # neither re(x) nor im(x) will appear
970            # if re(s) or im(s) appear, the auxiliary equation must be present
971            if any(fi.has(re(s), im(s)) for fi in freim):
972                irf.append((s, re(s) + S.ImaginaryUnit*im(s)))
973        if irf:
974            for s, rhs in irf:
975                for i, fi in enumerate(f):
976                    f[i] = fi.xreplace({s: rhs})
977                f.append(s - rhs)
978                symbols.extend([re(s), im(s)])
979            if bare_f:
980                bare_f = False
981            flags['dict'] = True
982    # end of real/imag handling  -----------------------------
983
984    symbols = list(uniq(symbols))
985    if not ordered_symbols:
986        # we do this to make the results returned canonical in case f
987        # contains a system of nonlinear equations; all other cases should
988        # be unambiguous
989        symbols = sorted(symbols, key=default_sort_key)
990
991    # we can solve for non-symbol entities by replacing them with Dummy symbols
992    f, symbols, swap_sym = recast_to_symbols(f, symbols)
993
994    # this is needed in the next two events
995    symset = set(symbols)
996
997    # get rid of equations that have no symbols of interest; we don't
998    # try to solve them because the user didn't ask and they might be
999    # hard to solve; this means that solutions may be given in terms
1000    # of the eliminated equations e.g. solve((x-y, y-3), x) -> {x: y}
1001    newf = []
1002    for fi in f:
1003        # let the solver handle equations that..
1004        # - have no symbols but are expressions
1005        # - have symbols of interest
1006        # - have no symbols of interest but are constant
1007        # but when an expression is not constant and has no symbols of
1008        # interest, it can't change what we obtain for a solution from
1009        # the remaining equations so we don't include it; and if it's
1010        # zero it can be removed and if it's not zero, there is no
1011        # solution for the equation set as a whole
1012        #
1013        # The reason for doing this filtering is to allow an answer
1014        # to be obtained to queries like solve((x - y, y), x); without
1015        # this mod the return value is []
1016        ok = False
1017        if fi.free_symbols & symset:
1018            ok = True
1019        else:
1020            if fi.is_number:
1021                if fi.is_Number:
1022                    if fi.is_zero:
1023                        continue
1024                    return []
1025                ok = True
1026            else:
1027                if fi.is_constant():
1028                    ok = True
1029        if ok:
1030            newf.append(fi)
1031    if not newf:
1032        return []
1033    f = newf
1034    del newf
1035
1036    # mask off any Object that we aren't going to invert: Derivative,
1037    # Integral, etc... so that solving for anything that they contain will
1038    # give an implicit solution
1039    seen = set()
1040    non_inverts = set()
1041    for fi in f:
1042        pot = preorder_traversal(fi)
1043        for p in pot:
1044            if not isinstance(p, Expr) or isinstance(p, Piecewise):
1045                pass
1046            elif (isinstance(p, bool) or
1047                    not p.args or
1048                    p in symset or
1049                    p.is_Add or p.is_Mul or
1050                    p.is_Pow and not implicit or
1051                    p.is_Function and not implicit) and p.func not in (re, im):
1052                continue
1053            elif not p in seen:
1054                seen.add(p)
1055                if p.free_symbols & symset:
1056                    non_inverts.add(p)
1057                else:
1058                    continue
1059            pot.skip()
1060    del seen
1061    non_inverts = dict(list(zip(non_inverts, [Dummy() for _ in non_inverts])))
1062    f = [fi.subs(non_inverts) for fi in f]
1063
1064    # Both xreplace and subs are needed below: xreplace to force substitution
1065    # inside Derivative, subs to handle non-straightforward substitutions
1066    non_inverts = [(v, k.xreplace(swap_sym).subs(swap_sym)) for k, v in non_inverts.items()]
1067
1068    # rationalize Floats
1069    floats = False
1070    if flags.get('rational', True) is not False:
1071        for i, fi in enumerate(f):
1072            if fi.has(Float):
1073                floats = True
1074                f[i] = nsimplify(fi, rational=True)
1075
1076    # capture any denominators before rewriting since
1077    # they may disappear after the rewrite, e.g. issue 14779
1078    flags['_denominators'] = _simple_dens(f[0], symbols)
1079    # Any embedded piecewise functions need to be brought out to the
1080    # top level so that the appropriate strategy gets selected.
1081    # However, this is necessary only if one of the piecewise
1082    # functions depends on one of the symbols we are solving for.
1083    def _has_piecewise(e):
1084        if e.is_Piecewise:
1085            return e.has(*symbols)
1086        return any([_has_piecewise(a) for a in e.args])
1087    for i, fi in enumerate(f):
1088        if _has_piecewise(fi):
1089            f[i] = piecewise_fold(fi)
1090
1091    #
1092    # try to get a solution
1093    ###########################################################################
1094    if bare_f:
1095        solution = _solve(f[0], *symbols, **flags)
1096    else:
1097        solution = _solve_system(f, symbols, **flags)
1098
1099    #
1100    # postprocessing
1101    ###########################################################################
1102    # Restore masked-off objects
1103    if non_inverts:
1104
1105        def _do_dict(solution):
1106            return {k: v.subs(non_inverts) for k, v in
1107                         solution.items()}
1108        for i in range(1):
1109            if isinstance(solution, dict):
1110                solution = _do_dict(solution)
1111                break
1112            elif solution and isinstance(solution, list):
1113                if isinstance(solution[0], dict):
1114                    solution = [_do_dict(s) for s in solution]
1115                    break
1116                elif isinstance(solution[0], tuple):
1117                    solution = [tuple([v.subs(non_inverts) for v in s]) for s
1118                                in solution]
1119                    break
1120                else:
1121                    solution = [v.subs(non_inverts) for v in solution]
1122                    break
1123            elif not solution:
1124                break
1125        else:
1126            raise NotImplementedError(filldedent('''
1127                            no handling of %s was implemented''' % solution))
1128
1129    # Restore original "symbols" if a dictionary is returned.
1130    # This is not necessary for
1131    #   - the single univariate equation case
1132    #     since the symbol will have been removed from the solution;
1133    #   - the nonlinear poly_system since that only supports zero-dimensional
1134    #     systems and those results come back as a list
1135    #
1136    # ** unless there were Derivatives with the symbols, but those were handled
1137    #    above.
1138    if swap_sym:
1139        symbols = [swap_sym.get(k, k) for k in symbols]
1140        if isinstance(solution, dict):
1141            solution = {swap_sym.get(k, k): v.subs(swap_sym)
1142                             for k, v in solution.items()}
1143        elif solution and isinstance(solution, list) and isinstance(solution[0], dict):
1144            for i, sol in enumerate(solution):
1145                solution[i] = {swap_sym.get(k, k): v.subs(swap_sym)
1146                              for k, v in sol.items()}
1147
1148    # undo the dictionary solutions returned when the system was only partially
1149    # solved with poly-system if all symbols are present
1150    if (
1151            not flags.get('dict', False) and
1152            solution and
1153            ordered_symbols and
1154            not isinstance(solution, dict) and
1155            all(isinstance(sol, dict) for sol in solution)
1156    ):
1157        solution = [tuple([r.get(s, s) for s in symbols]) for r in solution]
1158
1159    # Get assumptions about symbols, to filter solutions.
1160    # Note that if assumptions about a solution can't be verified, it is still
1161    # returned.
1162    check = flags.get('check', True)
1163
1164    # restore floats
1165    if floats and solution and flags.get('rational', None) is None:
1166        solution = nfloat(solution, exponent=False)
1167
1168    if check and solution:  # assumption checking
1169
1170        warn = flags.get('warn', False)
1171        got_None = []  # solutions for which one or more symbols gave None
1172        no_False = []  # solutions for which no symbols gave False
1173        if isinstance(solution, tuple):
1174            # this has already been checked and is in as_set form
1175            return solution
1176        elif isinstance(solution, list):
1177            if isinstance(solution[0], tuple):
1178                for sol in solution:
1179                    for symb, val in zip(symbols, sol):
1180                        test = check_assumptions(val, **symb.assumptions0)
1181                        if test is False:
1182                            break
1183                        if test is None:
1184                            got_None.append(sol)
1185                    else:
1186                        no_False.append(sol)
1187            elif isinstance(solution[0], dict):
1188                for sol in solution:
1189                    a_None = False
1190                    for symb, val in sol.items():
1191                        test = check_assumptions(val, **symb.assumptions0)
1192                        if test:
1193                            continue
1194                        if test is False:
1195                            break
1196                        a_None = True
1197                    else:
1198                        no_False.append(sol)
1199                        if a_None:
1200                            got_None.append(sol)
1201            else:  # list of expressions
1202                for sol in solution:
1203                    test = check_assumptions(sol, **symbols[0].assumptions0)
1204                    if test is False:
1205                        continue
1206                    no_False.append(sol)
1207                    if test is None:
1208                        got_None.append(sol)
1209
1210        elif isinstance(solution, dict):
1211            a_None = False
1212            for symb, val in solution.items():
1213                test = check_assumptions(val, **symb.assumptions0)
1214                if test:
1215                    continue
1216                if test is False:
1217                    no_False = None
1218                    break
1219                a_None = True
1220            else:
1221                no_False = solution
1222                if a_None:
1223                    got_None.append(solution)
1224
1225        elif isinstance(solution, (Relational, And, Or)):
1226            if len(symbols) != 1:
1227                raise ValueError("Length should be 1")
1228            if warn and symbols[0].assumptions0:
1229                warnings.warn(filldedent("""
1230                    \tWarning: assumptions about variable '%s' are
1231                    not handled currently.""" % symbols[0]))
1232            # TODO: check also variable assumptions for inequalities
1233
1234        else:
1235            raise TypeError('Unrecognized solution')  # improve the checker
1236
1237        solution = no_False
1238        if warn and got_None:
1239            warnings.warn(filldedent("""
1240                \tWarning: assumptions concerning following solution(s)
1241                can't be checked:""" + '\n\t' +
1242                ', '.join(str(s) for s in got_None)))
1243
1244    #
1245    # done
1246    ###########################################################################
1247
1248    as_dict = flags.get('dict', False)
1249    as_set = flags.get('set', False)
1250
1251    if not as_set and isinstance(solution, list):
1252        # Make sure that a list of solutions is ordered in a canonical way.
1253        solution.sort(key=default_sort_key)
1254
1255    if not as_dict and not as_set:
1256        return solution or []
1257
1258    # return a list of mappings or []
1259    if not solution:
1260        solution = []
1261    else:
1262        if isinstance(solution, dict):
1263            solution = [solution]
1264        elif iterable(solution[0]):
1265            solution = [dict(list(zip(symbols, s))) for s in solution]
1266        elif isinstance(solution[0], dict):
1267            pass
1268        else:
1269            if len(symbols) != 1:
1270                raise ValueError("Length should be 1")
1271            solution = [{symbols[0]: s} for s in solution]
1272    if as_dict:
1273        return solution
1274    assert as_set
1275    if not solution:
1276        return [], set()
1277    k = list(ordered(solution[0].keys()))
1278    return k, {tuple([s[ki] for ki in k]) for s in solution}
1279
1280
1281def _solve(f, *symbols, **flags):
1282    """
1283    Return a checked solution for *f* in terms of one or more of the
1284    symbols. A list should be returned except for the case when a linear
1285    undetermined-coefficients equation is encountered (in which case
1286    a dictionary is returned).
1287
1288    If no method is implemented to solve the equation, a NotImplementedError
1289    will be raised. In the case that conversion of an expression to a Poly
1290    gives None a ValueError will be raised.
1291
1292    """
1293
1294    not_impl_msg = "No algorithms are implemented to solve equation %s"
1295
1296    if len(symbols) != 1:
1297        soln = None
1298        free = f.free_symbols
1299        ex = free - set(symbols)
1300        if len(ex) != 1:
1301            ind, dep = f.as_independent(*symbols)
1302            ex = ind.free_symbols & dep.free_symbols
1303        if len(ex) == 1:
1304            ex = ex.pop()
1305            try:
1306                # soln may come back as dict, list of dicts or tuples, or
1307                # tuple of symbol list and set of solution tuples
1308                soln = solve_undetermined_coeffs(f, symbols, ex, **flags)
1309            except NotImplementedError:
1310                pass
1311        if soln:
1312            if flags.get('simplify', True):
1313                if isinstance(soln, dict):
1314                    for k in soln:
1315                        soln[k] = simplify(soln[k])
1316                elif isinstance(soln, list):
1317                    if isinstance(soln[0], dict):
1318                        for d in soln:
1319                            for k in d:
1320                                d[k] = simplify(d[k])
1321                    elif isinstance(soln[0], tuple):
1322                        soln = [tuple(simplify(i) for i in j) for j in soln]
1323                    else:
1324                        raise TypeError('unrecognized args in list')
1325                elif isinstance(soln, tuple):
1326                    sym, sols = soln
1327                    soln = sym, {tuple(simplify(i) for i in j) for j in sols}
1328                else:
1329                    raise TypeError('unrecognized solution type')
1330            return soln
1331        # find first successful solution
1332        failed = []
1333        got_s = set()
1334        result = []
1335        for s in symbols:
1336            xi, v = solve_linear(f, symbols=[s])
1337            if xi == s:
1338                # no need to check but we should simplify if desired
1339                if flags.get('simplify', True):
1340                    v = simplify(v)
1341                vfree = v.free_symbols
1342                if got_s and any([ss in vfree for ss in got_s]):
1343                    # sol depends on previously solved symbols: discard it
1344                    continue
1345                got_s.add(xi)
1346                result.append({xi: v})
1347            elif xi:  # there might be a non-linear solution if xi is not 0
1348                failed.append(s)
1349        if not failed:
1350            return result
1351        for s in failed:
1352            try:
1353                soln = _solve(f, s, **flags)
1354                for sol in soln:
1355                    if got_s and any([ss in sol.free_symbols for ss in got_s]):
1356                        # sol depends on previously solved symbols: discard it
1357                        continue
1358                    got_s.add(s)
1359                    result.append({s: sol})
1360            except NotImplementedError:
1361                continue
1362        if got_s:
1363            return result
1364        else:
1365            raise NotImplementedError(not_impl_msg % f)
1366    symbol = symbols[0]
1367
1368    #expand binomials only if it has the unknown symbol
1369    f = f.replace(lambda e: isinstance(e, binomial) and e.has(symbol),
1370        lambda e: expand_func(e))
1371
1372    # /!\ capture this flag then set it to False so that no checking in
1373    # recursive calls will be done; only the final answer is checked
1374    flags['check'] = checkdens = check = flags.pop('check', True)
1375
1376    # build up solutions if f is a Mul
1377    if f.is_Mul:
1378        result = set()
1379        for m in f.args:
1380            if m in {S.NegativeInfinity, S.ComplexInfinity, S.Infinity}:
1381                result = set()
1382                break
1383            soln = _solve(m, symbol, **flags)
1384            result.update(set(soln))
1385        result = list(result)
1386        if check:
1387            # all solutions have been checked but now we must
1388            # check that the solutions do not set denominators
1389            # in any factor to zero
1390            dens = flags.get('_denominators', _simple_dens(f, symbols))
1391            result = [s for s in result if
1392                all(not checksol(den, {symbol: s}, **flags) for den in
1393                dens)]
1394        # set flags for quick exit at end; solutions for each
1395        # factor were already checked and simplified
1396        check = False
1397        flags['simplify'] = False
1398
1399    elif f.is_Piecewise:
1400        result = set()
1401        for i, (expr, cond) in enumerate(f.args):
1402            if expr.is_zero:
1403                raise NotImplementedError(
1404                    'solve cannot represent interval solutions')
1405            candidates = _solve(expr, symbol, **flags)
1406            # the explicit condition for this expr is the current cond
1407            # and none of the previous conditions
1408            args = [~c for _, c in f.args[:i]] + [cond]
1409            cond = And(*args)
1410            for candidate in candidates:
1411                if candidate in result:
1412                    # an unconditional value was already there
1413                    continue
1414                try:
1415                    v = cond.subs(symbol, candidate)
1416                    _eval_simplify = getattr(v, '_eval_simplify', None)
1417                    if _eval_simplify is not None:
1418                        # unconditionally take the simpification of v
1419                        v = _eval_simplify(ratio=2, measure=lambda x: 1)
1420                except TypeError:
1421                    # incompatible type with condition(s)
1422                    continue
1423                if v == False:
1424                    continue
1425                if v == True:
1426                    result.add(candidate)
1427                else:
1428                    result.add(Piecewise(
1429                        (candidate, v),
1430                        (S.NaN, True)))
1431        # set flags for quick exit at end; solutions for each
1432        # piece were already checked and simplified
1433        check = False
1434        flags['simplify'] = False
1435    else:
1436        # first see if it really depends on symbol and whether there
1437        # is only a linear solution
1438        f_num, sol = solve_linear(f, symbols=symbols)
1439        if f_num.is_zero or sol is S.NaN:
1440            return []
1441        elif f_num.is_Symbol:
1442            # no need to check but simplify if desired
1443            if flags.get('simplify', True):
1444                sol = simplify(sol)
1445            return [sol]
1446
1447        poly = None
1448        # check for a single Add generator
1449        if not f_num.is_Add:
1450            add_args = [i for i in f_num.atoms(Add)
1451                if symbol in i.free_symbols]
1452            if len(add_args) == 1:
1453                gen = add_args[0]
1454                spart = gen.as_independent(symbol)[1].as_base_exp()[0]
1455                if spart == symbol:
1456                    try:
1457                        poly = Poly(f_num, spart)
1458                    except PolynomialError:
1459                        pass
1460
1461        result = False  # no solution was obtained
1462        msg = ''  # there is no failure message
1463
1464        # Poly is generally robust enough to convert anything to
1465        # a polynomial and tell us the different generators that it
1466        # contains, so we will inspect the generators identified by
1467        # polys to figure out what to do.
1468
1469        # try to identify a single generator that will allow us to solve this
1470        # as a polynomial, followed (perhaps) by a change of variables if the
1471        # generator is not a symbol
1472
1473        try:
1474            if poly is None:
1475                poly = Poly(f_num)
1476            if poly is None:
1477                raise ValueError('could not convert %s to Poly' % f_num)
1478        except GeneratorsNeeded:
1479            simplified_f = simplify(f_num)
1480            if simplified_f != f_num:
1481                return _solve(simplified_f, symbol, **flags)
1482            raise ValueError('expression appears to be a constant')
1483
1484        gens = [g for g in poly.gens if g.has(symbol)]
1485
1486        def _as_base_q(x):
1487            """Return (b**e, q) for x = b**(p*e/q) where p/q is the leading
1488            Rational of the exponent of x, e.g. exp(-2*x/3) -> (exp(x), 3)
1489            """
1490            b, e = x.as_base_exp()
1491            if e.is_Rational:
1492                return b, e.q
1493            if not e.is_Mul:
1494                return x, 1
1495            c, ee = e.as_coeff_Mul()
1496            if c.is_Rational and c is not S.One:  # c could be a Float
1497                return b**ee, c.q
1498            return x, 1
1499
1500        if len(gens) > 1:
1501            # If there is more than one generator, it could be that the
1502            # generators have the same base but different powers, e.g.
1503            #   >>> Poly(exp(x) + 1/exp(x))
1504            #   Poly(exp(-x) + exp(x), exp(-x), exp(x), domain='ZZ')
1505            #
1506            # If unrad was not disabled then there should be no rational
1507            # exponents appearing as in
1508            #   >>> Poly(sqrt(x) + sqrt(sqrt(x)))
1509            #   Poly(sqrt(x) + x**(1/4), sqrt(x), x**(1/4), domain='ZZ')
1510
1511            bases, qs = list(zip(*[_as_base_q(g) for g in gens]))
1512            bases = set(bases)
1513
1514            if len(bases) > 1 or not all(q == 1 for q in qs):
1515                funcs = {b for b in bases if b.is_Function}
1516
1517                trig = {_ for _ in funcs if
1518                    isinstance(_, TrigonometricFunction)}
1519                other = funcs - trig
1520                if not other and len(funcs.intersection(trig)) > 1:
1521                    newf = None
1522                    if f_num.is_Add and len(f_num.args) == 2:
1523                        # check for sin(x)**p = cos(x)**p
1524                        _args = f_num.args
1525                        t = a, b = [i.atoms(Function).intersection(
1526                            trig) for i in _args]
1527                        if all(len(i) == 1 for i in t):
1528                            a, b = [i.pop() for i in t]
1529                            if isinstance(a, cos):
1530                                a, b = b, a
1531                                _args = _args[::-1]
1532                            if isinstance(a, sin) and isinstance(b, cos
1533                                    ) and a.args[0] == b.args[0]:
1534                                # sin(x) + cos(x) = 0 -> tan(x) + 1 = 0
1535                                newf, _d = (TR2i(_args[0]/_args[1]) + 1
1536                                    ).as_numer_denom()
1537                                if not _d.is_Number:
1538                                    newf = None
1539                    if newf is None:
1540                        newf = TR1(f_num).rewrite(tan)
1541                    if newf != f_num:
1542                        # don't check the rewritten form --check
1543                        # solutions in the un-rewritten form below
1544                        flags['check'] = False
1545                        result = _solve(newf, symbol, **flags)
1546                        flags['check'] = check
1547
1548                # just a simple case - see if replacement of single function
1549                # clears all symbol-dependent functions, e.g.
1550                # log(x) - log(log(x) - 1) - 3 can be solved even though it has
1551                # two generators.
1552
1553                if result is False and funcs:
1554                    funcs = list(ordered(funcs))  # put shallowest function first
1555                    f1 = funcs[0]
1556                    t = Dummy('t')
1557                    # perform the substitution
1558                    ftry = f_num.subs(f1, t)
1559
1560                    # if no Functions left, we can proceed with usual solve
1561                    if not ftry.has(symbol):
1562                        cv_sols = _solve(ftry, t, **flags)
1563                        cv_inv = _solve(t - f1, symbol, **flags)[0]
1564                        sols = list()
1565                        for sol in cv_sols:
1566                            sols.append(cv_inv.subs(t, sol))
1567                        result = list(ordered(sols))
1568
1569                if result is False:
1570                    msg = 'multiple generators %s' % gens
1571
1572            else:
1573                # e.g. case where gens are exp(x), exp(-x)
1574                u = bases.pop()
1575                t = Dummy('t')
1576                inv = _solve(u - t, symbol, **flags)
1577                if isinstance(u, (Pow, exp)):
1578                    # this will be resolved by factor in _tsolve but we might
1579                    # as well try a simple expansion here to get things in
1580                    # order so something like the following will work now without
1581                    # having to factor:
1582                    #
1583                    # >>> eq = (exp(I*(-x-2))+exp(I*(x+2)))
1584                    # >>> eq.subs(exp(x),y)  # fails
1585                    # exp(I*(-x - 2)) + exp(I*(x + 2))
1586                    # >>> eq.expand().subs(exp(x),y)  # works
1587                    # y**I*exp(2*I) + y**(-I)*exp(-2*I)
1588                    def _expand(p):
1589                        b, e = p.as_base_exp()
1590                        e = expand_mul(e)
1591                        return expand_power_exp(b**e)
1592                    ftry = f_num.replace(
1593                        lambda w: w.is_Pow or isinstance(w, exp),
1594                        _expand).subs(u, t)
1595                    if not ftry.has(symbol):
1596                        soln = _solve(ftry, t, **flags)
1597                        sols = list()
1598                        for sol in soln:
1599                            for i in inv:
1600                                sols.append(i.subs(t, sol))
1601                        result = list(ordered(sols))
1602
1603        elif len(gens) == 1:
1604
1605            # There is only one generator that we are interested in, but
1606            # there may have been more than one generator identified by
1607            # polys (e.g. for symbols other than the one we are interested
1608            # in) so recast the poly in terms of our generator of interest.
1609            # Also use composite=True with f_num since Poly won't update
1610            # poly as documented in issue 8810.
1611
1612            poly = Poly(f_num, gens[0], composite=True)
1613
1614            # if we aren't on the tsolve-pass, use roots
1615            if not flags.pop('tsolve', False):
1616                soln = None
1617                deg = poly.degree()
1618                flags['tsolve'] = True
1619                solvers = {k: flags.get(k, True) for k in
1620                    ('cubics', 'quartics', 'quintics')}
1621                soln = roots(poly, **solvers)
1622                if sum(soln.values()) < deg:
1623                    # e.g. roots(32*x**5 + 400*x**4 + 2032*x**3 +
1624                    #            5000*x**2 + 6250*x + 3189) -> {}
1625                    # so all_roots is used and RootOf instances are
1626                    # returned *unless* the system is multivariate
1627                    # or high-order EX domain.
1628                    try:
1629                        soln = poly.all_roots()
1630                    except NotImplementedError:
1631                        if not flags.get('incomplete', True):
1632                                raise NotImplementedError(
1633                                filldedent('''
1634    Neither high-order multivariate polynomials
1635    nor sorting of EX-domain polynomials is supported.
1636    If you want to see any results, pass keyword incomplete=True to
1637    solve; to see numerical values of roots
1638    for univariate expressions, use nroots.
1639    '''))
1640                        else:
1641                            pass
1642                else:
1643                    soln = list(soln.keys())
1644
1645                if soln is not None:
1646                    u = poly.gen
1647                    if u != symbol:
1648                        try:
1649                            t = Dummy('t')
1650                            iv = _solve(u - t, symbol, **flags)
1651                            soln = list(ordered({i.subs(t, s) for i in iv for s in soln}))
1652                        except NotImplementedError:
1653                            # perhaps _tsolve can handle f_num
1654                            soln = None
1655                    else:
1656                        check = False  # only dens need to be checked
1657                    if soln is not None:
1658                        if len(soln) > 2:
1659                            # if the flag wasn't set then unset it since high-order
1660                            # results are quite long. Perhaps one could base this
1661                            # decision on a certain critical length of the
1662                            # roots. In addition, wester test M2 has an expression
1663                            # whose roots can be shown to be real with the
1664                            # unsimplified form of the solution whereas only one of
1665                            # the simplified forms appears to be real.
1666                            flags['simplify'] = flags.get('simplify', False)
1667                        result = soln
1668
1669    # fallback if above fails
1670    # -----------------------
1671    if result is False:
1672        # try unrad
1673        if flags.pop('_unrad', True):
1674            try:
1675                u = unrad(f_num, symbol)
1676            except (ValueError, NotImplementedError):
1677                u = False
1678            if u:
1679                eq, cov = u
1680                if cov:
1681                    isym, ieq = cov
1682                    inv = _solve(ieq, symbol, **flags)[0]
1683                    rv = {inv.subs(isym, xi) for xi in _solve(eq, isym, **flags)}
1684                else:
1685                    try:
1686                        rv = set(_solve(eq, symbol, **flags))
1687                    except NotImplementedError:
1688                        rv = None
1689                if rv is not None:
1690                    result = list(ordered(rv))
1691                    # if the flag wasn't set then unset it since unrad results
1692                    # can be quite long or of very high order
1693                    flags['simplify'] = flags.get('simplify', False)
1694            else:
1695                pass  # for coverage
1696
1697    # try _tsolve
1698    if result is False:
1699        flags.pop('tsolve', None)  # allow tsolve to be used on next pass
1700        try:
1701            soln = _tsolve(f_num, symbol, **flags)
1702            if soln is not None:
1703                result = soln
1704        except PolynomialError:
1705            pass
1706    # ----------- end of fallback ----------------------------
1707
1708    if result is False:
1709        raise NotImplementedError('\n'.join([msg, not_impl_msg % f]))
1710
1711    if flags.get('simplify', True):
1712        result = list(map(simplify, result))
1713        # we just simplified the solution so we now set the flag to
1714        # False so the simplification doesn't happen again in checksol()
1715        flags['simplify'] = False
1716
1717    if checkdens:
1718        # reject any result that makes any denom. affirmatively 0;
1719        # if in doubt, keep it
1720        dens = _simple_dens(f, symbols)
1721        result = [s for s in result if
1722                  all(not checksol(d, {symbol: s}, **flags)
1723                    for d in dens)]
1724    if check:
1725        # keep only results if the check is not False
1726        result = [r for r in result if
1727                  checksol(f_num, {symbol: r}, **flags) is not False]
1728    return result
1729
1730
1731def _solve_system(exprs, symbols, **flags):
1732    if not exprs:
1733        return []
1734
1735    if flags.pop('_split', True):
1736        # Split the system into connected components
1737        V = exprs
1738        symsset = set(symbols)
1739        exprsyms = {e: e.free_symbols & symsset for e in exprs}
1740        E = []
1741        sym_indices = {sym: i for i, sym in enumerate(symbols)}
1742        for n, e1 in enumerate(exprs):
1743            for e2 in exprs[:n]:
1744                # Equations are connected if they share a symbol
1745                if exprsyms[e1] & exprsyms[e2]:
1746                    E.append((e1, e2))
1747        G = V, E
1748        subexprs = connected_components(G)
1749        if len(subexprs) > 1:
1750            subsols = []
1751            for subexpr in subexprs:
1752                subsyms = set()
1753                for e in subexpr:
1754                    subsyms |= exprsyms[e]
1755                subsyms = list(sorted(subsyms, key = lambda x: sym_indices[x]))
1756                flags['_split'] = False  # skip split step
1757                subsol = _solve_system(subexpr, subsyms, **flags)
1758                if not isinstance(subsol, list):
1759                    subsol = [subsol]
1760                subsols.append(subsol)
1761            # Full solution is cartesion product of subsystems
1762            sols = []
1763            for soldicts in cartes(*subsols):
1764                sols.append(dict(item for sd in soldicts
1765                    for item in sd.items()))
1766            # Return a list with one dict as just the dict
1767            if len(sols) == 1:
1768                return sols[0]
1769            return sols
1770
1771    polys = []
1772    dens = set()
1773    failed = []
1774    result = False
1775    linear = False
1776    manual = flags.get('manual', False)
1777    checkdens = check = flags.get('check', True)
1778
1779    for j, g in enumerate(exprs):
1780        dens.update(_simple_dens(g, symbols))
1781        i, d = _invert(g, *symbols)
1782        g = d - i
1783        g = g.as_numer_denom()[0]
1784        if manual:
1785            failed.append(g)
1786            continue
1787
1788        poly = g.as_poly(*symbols, extension=True)
1789
1790        if poly is not None:
1791            polys.append(poly)
1792        else:
1793            failed.append(g)
1794
1795    if not polys:
1796        solved_syms = []
1797    else:
1798        if all(p.is_linear for p in polys):
1799            n, m = len(polys), len(symbols)
1800            matrix = zeros(n, m + 1)
1801
1802            for i, poly in enumerate(polys):
1803                for monom, coeff in poly.terms():
1804                    try:
1805                        j = monom.index(1)
1806                        matrix[i, j] = coeff
1807                    except ValueError:
1808                        matrix[i, m] = -coeff
1809
1810            # returns a dictionary ({symbols: values}) or None
1811            if flags.pop('particular', False):
1812                result = minsolve_linear_system(matrix, *symbols, **flags)
1813            else:
1814                result = solve_linear_system(matrix, *symbols, **flags)
1815            if failed:
1816                if result:
1817                    solved_syms = list(result.keys())
1818                else:
1819                    solved_syms = []
1820            else:
1821                linear = True
1822
1823        else:
1824            if len(symbols) > len(polys):
1825                from sympy.utilities.iterables import subsets
1826
1827                free = set().union(*[p.free_symbols for p in polys])
1828                free = list(ordered(free.intersection(symbols)))
1829                got_s = set()
1830                result = []
1831                for syms in subsets(free, len(polys)):
1832                    try:
1833                        # returns [] or list of tuples of solutions for syms
1834                        res = solve_poly_system(polys, *syms)
1835                        if res:
1836                            for r in res:
1837                                skip = False
1838                                for r1 in r:
1839                                    if got_s and any([ss in r1.free_symbols
1840                                           for ss in got_s]):
1841                                        # sol depends on previously
1842                                        # solved symbols: discard it
1843                                        skip = True
1844                                if not skip:
1845                                    got_s.update(syms)
1846                                    result.extend([dict(list(zip(syms, r)))])
1847                    except NotImplementedError:
1848                        pass
1849                if got_s:
1850                    solved_syms = list(got_s)
1851                else:
1852                    raise NotImplementedError('no valid subset found')
1853            else:
1854                try:
1855                    result = solve_poly_system(polys, *symbols)
1856                    if result:
1857                        solved_syms = symbols
1858                        # we don't know here if the symbols provided
1859                        # were given or not, so let solve resolve that.
1860                        # A list of dictionaries is going to always be
1861                        # returned from here.
1862                        result = [dict(list(zip(solved_syms, r))) for r in result]
1863                except NotImplementedError:
1864                    failed.extend([g.as_expr() for g in polys])
1865                    solved_syms = []
1866                    result = None
1867
1868    if result:
1869        if isinstance(result, dict):
1870            result = [result]
1871    else:
1872        result = [{}]
1873
1874    if failed:
1875        # For each failed equation, see if we can solve for one of the
1876        # remaining symbols from that equation. If so, we update the
1877        # solution set and continue with the next failed equation,
1878        # repeating until we are done or we get an equation that can't
1879        # be solved.
1880        def _ok_syms(e, sort=False):
1881            rv = (e.free_symbols - solved_syms) & legal
1882
1883            # Solve first for symbols that have lower degree in the equation.
1884            # Ideally we want to solve firstly for symbols that appear linearly
1885            # with rational coefficients e.g. if e = x*y + z then we should
1886            # solve for z first.
1887            def key(sym):
1888                ep = e.as_poly(sym)
1889                if ep is None:
1890                    complexity = (S.Infinity, S.Infinity, S.Infinity)
1891                else:
1892                    coeff_syms = ep.LC().free_symbols
1893                    complexity = (ep.degree(), len(coeff_syms & rv), len(coeff_syms))
1894                return complexity + (default_sort_key(sym),)
1895
1896            if sort:
1897                rv = sorted(rv, key=key)
1898            return rv
1899
1900        solved_syms = set(solved_syms)  # set of symbols we have solved for
1901        legal = set(symbols)  # what we are interested in
1902        # sort so equation with the fewest potential symbols is first
1903        u = Dummy()  # used in solution checking
1904        for eq in ordered(failed, lambda _: len(_ok_syms(_))):
1905            newresult = []
1906            bad_results = []
1907            got_s = set()
1908            hit = False
1909            for r in result:
1910                # update eq with everything that is known so far
1911                eq2 = eq.subs(r)
1912                # if check is True then we see if it satisfies this
1913                # equation, otherwise we just accept it
1914                if check and r:
1915                    b = checksol(u, u, eq2, minimal=True)
1916                    if b is not None:
1917                        # this solution is sufficient to know whether
1918                        # it is valid or not so we either accept or
1919                        # reject it, then continue
1920                        if b:
1921                            newresult.append(r)
1922                        else:
1923                            bad_results.append(r)
1924                        continue
1925                # search for a symbol amongst those available that
1926                # can be solved for
1927                ok_syms = _ok_syms(eq2, sort=True)
1928                if not ok_syms:
1929                    if r:
1930                        newresult.append(r)
1931                    break  # skip as it's independent of desired symbols
1932                for s in ok_syms:
1933                    try:
1934                        soln = _solve(eq2, s, **flags)
1935                    except NotImplementedError:
1936                        continue
1937                    # put each solution in r and append the now-expanded
1938                    # result in the new result list; use copy since the
1939                    # solution for s in being added in-place
1940                    for sol in soln:
1941                        if got_s and any([ss in sol.free_symbols for ss in got_s]):
1942                            # sol depends on previously solved symbols: discard it
1943                            continue
1944                        rnew = r.copy()
1945                        for k, v in r.items():
1946                            rnew[k] = v.subs(s, sol)
1947                        # and add this new solution
1948                        rnew[s] = sol
1949                        # check that it is independent of previous solutions
1950                        iset = set(rnew.items())
1951                        for i in newresult:
1952                            if len(i) < len(iset) and not set(i.items()) - iset:
1953                                # this is a superset of a known solution that
1954                                # is smaller
1955                                break
1956                        else:
1957                            # keep it
1958                            newresult.append(rnew)
1959                    hit = True
1960                    got_s.add(s)
1961                if not hit:
1962                    raise NotImplementedError('could not solve %s' % eq2)
1963            else:
1964                result = newresult
1965                for b in bad_results:
1966                    if b in result:
1967                        result.remove(b)
1968
1969    default_simplify = bool(failed)  # rely on system-solvers to simplify
1970    if  flags.get('simplify', default_simplify):
1971        for r in result:
1972            for k in r:
1973                r[k] = simplify(r[k])
1974        flags['simplify'] = False  # don't need to do so in checksol now
1975
1976    if checkdens:
1977        result = [r for r in result
1978            if not any(checksol(d, r, **flags) for d in dens)]
1979
1980    if check and not linear:
1981        result = [r for r in result
1982            if not any(checksol(e, r, **flags) is False for e in exprs)]
1983
1984    result = [r for r in result if r]
1985    if linear and result:
1986        result = result[0]
1987    return result
1988
1989
1990def solve_linear(lhs, rhs=0, symbols=[], exclude=[]):
1991    r"""
1992    Return a tuple derived from ``f = lhs - rhs`` that is one of
1993    the following: ``(0, 1)``, ``(0, 0)``, ``(symbol, solution)``, ``(n, d)``.
1994
1995    Explanation
1996    ===========
1997
1998    ``(0, 1)`` meaning that ``f`` is independent of the symbols in *symbols*
1999    that are not in *exclude*.
2000
2001    ``(0, 0)`` meaning that there is no solution to the equation amongst the
2002    symbols given. If the first element of the tuple is not zero, then the
2003    function is guaranteed to be dependent on a symbol in *symbols*.
2004
2005    ``(symbol, solution)`` where symbol appears linearly in the numerator of
2006    ``f``, is in *symbols* (if given), and is not in *exclude* (if given). No
2007    simplification is done to ``f`` other than a ``mul=True`` expansion, so the
2008    solution will correspond strictly to a unique solution.
2009
2010    ``(n, d)`` where ``n`` and ``d`` are the numerator and denominator of ``f``
2011    when the numerator was not linear in any symbol of interest; ``n`` will
2012    never be a symbol unless a solution for that symbol was found (in which case
2013    the second element is the solution, not the denominator).
2014
2015    Examples
2016    ========
2017
2018    >>> from sympy.core.power import Pow
2019    >>> from sympy.polys.polytools import cancel
2020
2021    ``f`` is independent of the symbols in *symbols* that are not in
2022    *exclude*:
2023
2024    >>> from sympy.solvers.solvers import solve_linear
2025    >>> from sympy.abc import x, y, z
2026    >>> from sympy import cos, sin
2027    >>> eq = y*cos(x)**2 + y*sin(x)**2 - y  # = y*(1 - 1) = 0
2028    >>> solve_linear(eq)
2029    (0, 1)
2030    >>> eq = cos(x)**2 + sin(x)**2  # = 1
2031    >>> solve_linear(eq)
2032    (0, 1)
2033    >>> solve_linear(x, exclude=[x])
2034    (0, 1)
2035
2036    The variable ``x`` appears as a linear variable in each of the
2037    following:
2038
2039    >>> solve_linear(x + y**2)
2040    (x, -y**2)
2041    >>> solve_linear(1/x - y**2)
2042    (x, y**(-2))
2043
2044    When not linear in ``x`` or ``y`` then the numerator and denominator are
2045    returned:
2046
2047    >>> solve_linear(x**2/y**2 - 3)
2048    (x**2 - 3*y**2, y**2)
2049
2050    If the numerator of the expression is a symbol, then ``(0, 0)`` is
2051    returned if the solution for that symbol would have set any
2052    denominator to 0:
2053
2054    >>> eq = 1/(1/x - 2)
2055    >>> eq.as_numer_denom()
2056    (x, 1 - 2*x)
2057    >>> solve_linear(eq)
2058    (0, 0)
2059
2060    But automatic rewriting may cause a symbol in the denominator to
2061    appear in the numerator so a solution will be returned:
2062
2063    >>> (1/x)**-1
2064    x
2065    >>> solve_linear((1/x)**-1)
2066    (x, 0)
2067
2068    Use an unevaluated expression to avoid this:
2069
2070    >>> solve_linear(Pow(1/x, -1, evaluate=False))
2071    (0, 0)
2072
2073    If ``x`` is allowed to cancel in the following expression, then it
2074    appears to be linear in ``x``, but this sort of cancellation is not
2075    done by ``solve_linear`` so the solution will always satisfy the
2076    original expression without causing a division by zero error.
2077
2078    >>> eq = x**2*(1/x - z**2/x)
2079    >>> solve_linear(cancel(eq))
2080    (x, 0)
2081    >>> solve_linear(eq)
2082    (x**2*(1 - z**2), x)
2083
2084    A list of symbols for which a solution is desired may be given:
2085
2086    >>> solve_linear(x + y + z, symbols=[y])
2087    (y, -x - z)
2088
2089    A list of symbols to ignore may also be given:
2090
2091    >>> solve_linear(x + y + z, exclude=[x])
2092    (y, -x - z)
2093
2094    (A solution for ``y`` is obtained because it is the first variable
2095    from the canonically sorted list of symbols that had a linear
2096    solution.)
2097
2098    """
2099    if isinstance(lhs, Equality):
2100        if rhs:
2101            raise ValueError(filldedent('''
2102            If lhs is an Equality, rhs must be 0 but was %s''' % rhs))
2103        rhs = lhs.rhs
2104        lhs = lhs.lhs
2105    dens = None
2106    eq = lhs - rhs
2107    n, d = eq.as_numer_denom()
2108    if not n:
2109        return S.Zero, S.One
2110
2111    free = n.free_symbols
2112    if not symbols:
2113        symbols = free
2114    else:
2115        bad = [s for s in symbols if not s.is_Symbol]
2116        if bad:
2117            if len(bad) == 1:
2118                bad = bad[0]
2119            if len(symbols) == 1:
2120                eg = 'solve(%s, %s)' % (eq, symbols[0])
2121            else:
2122                eg = 'solve(%s, *%s)' % (eq, list(symbols))
2123            raise ValueError(filldedent('''
2124                solve_linear only handles symbols, not %s. To isolate
2125                non-symbols use solve, e.g. >>> %s <<<.
2126                             ''' % (bad, eg)))
2127        symbols = free.intersection(symbols)
2128    symbols = symbols.difference(exclude)
2129    if not symbols:
2130        return S.Zero, S.One
2131
2132    # derivatives are easy to do but tricky to analyze to see if they
2133    # are going to disallow a linear solution, so for simplicity we
2134    # just evaluate the ones that have the symbols of interest
2135    derivs = defaultdict(list)
2136    for der in n.atoms(Derivative):
2137        csym = der.free_symbols & symbols
2138        for c in csym:
2139            derivs[c].append(der)
2140
2141    all_zero = True
2142    for xi in sorted(symbols, key=default_sort_key):  # canonical order
2143        # if there are derivatives in this var, calculate them now
2144        if isinstance(derivs[xi], list):
2145            derivs[xi] = {der: der.doit() for der in derivs[xi]}
2146        newn = n.subs(derivs[xi])
2147        dnewn_dxi = newn.diff(xi)
2148        # dnewn_dxi can be nonzero if it survives differentation by any
2149        # of its free symbols
2150        free = dnewn_dxi.free_symbols
2151        if dnewn_dxi and (not free or any(dnewn_dxi.diff(s) for s in free) or free == symbols):
2152            all_zero = False
2153            if dnewn_dxi is S.NaN:
2154                break
2155            if xi not in dnewn_dxi.free_symbols:
2156                vi = -1/dnewn_dxi*(newn.subs(xi, 0))
2157                if dens is None:
2158                    dens = _simple_dens(eq, symbols)
2159                if not any(checksol(di, {xi: vi}, minimal=True) is True
2160                          for di in dens):
2161                    # simplify any trivial integral
2162                    irep = [(i, i.doit()) for i in vi.atoms(Integral) if
2163                            i.function.is_number]
2164                    # do a slight bit of simplification
2165                    vi = expand_mul(vi.subs(irep))
2166                    return xi, vi
2167    if all_zero:
2168        return S.Zero, S.One
2169    if n.is_Symbol: # no solution for this symbol was found
2170        return S.Zero, S.Zero
2171    return n, d
2172
2173
2174def minsolve_linear_system(system, *symbols, **flags):
2175    r"""
2176    Find a particular solution to a linear system.
2177
2178    Explanation
2179    ===========
2180
2181    In particular, try to find a solution with the minimal possible number
2182    of non-zero variables using a naive algorithm with exponential complexity.
2183    If ``quick=True``, a heuristic is used.
2184
2185    """
2186    quick = flags.get('quick', False)
2187    # Check if there are any non-zero solutions at all
2188    s0 = solve_linear_system(system, *symbols, **flags)
2189    if not s0 or all(v == 0 for v in s0.values()):
2190        return s0
2191    if quick:
2192        # We just solve the system and try to heuristically find a nice
2193        # solution.
2194        s = solve_linear_system(system, *symbols)
2195        def update(determined, solution):
2196            delete = []
2197            for k, v in solution.items():
2198                solution[k] = v.subs(determined)
2199                if not solution[k].free_symbols:
2200                    delete.append(k)
2201                    determined[k] = solution[k]
2202            for k in delete:
2203                del solution[k]
2204        determined = {}
2205        update(determined, s)
2206        while s:
2207            # NOTE sort by default_sort_key to get deterministic result
2208            k = max((k for k in s.values()),
2209                    key=lambda x: (len(x.free_symbols), default_sort_key(x)))
2210            x = max(k.free_symbols, key=default_sort_key)
2211            if len(k.free_symbols) != 1:
2212                determined[x] = S.Zero
2213            else:
2214                val = solve(k)[0]
2215                if val == 0 and all(v.subs(x, val) == 0 for v in s.values()):
2216                    determined[x] = S.One
2217                else:
2218                    determined[x] = val
2219            update(determined, s)
2220        return determined
2221    else:
2222        # We try to select n variables which we want to be non-zero.
2223        # All others will be assumed zero. We try to solve the modified system.
2224        # If there is a non-trivial solution, just set the free variables to
2225        # one. If we do this for increasing n, trying all combinations of
2226        # variables, we will find an optimal solution.
2227        # We speed up slightly by starting at one less than the number of
2228        # variables the quick method manages.
2229        from itertools import combinations
2230        from sympy.utilities.misc import debug
2231        N = len(symbols)
2232        bestsol = minsolve_linear_system(system, *symbols, quick=True)
2233        n0 = len([x for x in bestsol.values() if x != 0])
2234        for n in range(n0 - 1, 1, -1):
2235            debug('minsolve: %s' % n)
2236            thissol = None
2237            for nonzeros in combinations(list(range(N)), n):
2238                subm = Matrix([system.col(i).T for i in nonzeros] + [system.col(-1).T]).T
2239                s = solve_linear_system(subm, *[symbols[i] for i in nonzeros])
2240                if s and not all(v == 0 for v in s.values()):
2241                    subs = [(symbols[v], S.One) for v in nonzeros]
2242                    for k, v in s.items():
2243                        s[k] = v.subs(subs)
2244                    for sym in symbols:
2245                        if sym not in s:
2246                            if symbols.index(sym) in nonzeros:
2247                                s[sym] = S.One
2248                            else:
2249                                s[sym] = S.Zero
2250                    thissol = s
2251                    break
2252            if thissol is None:
2253                break
2254            bestsol = thissol
2255        return bestsol
2256
2257
2258def solve_linear_system(system, *symbols, **flags):
2259    r"""
2260    Solve system of $N$ linear equations with $M$ variables, which means
2261    both under- and overdetermined systems are supported.
2262
2263    Explanation
2264    ===========
2265
2266    The possible number of solutions is zero, one, or infinite. Respectively,
2267    this procedure will return None or a dictionary with solutions. In the
2268    case of underdetermined systems, all arbitrary parameters are skipped.
2269    This may cause a situation in which an empty dictionary is returned.
2270    In that case, all symbols can be assigned arbitrary values.
2271
2272    Input to this function is a $N\times M + 1$ matrix, which means it has
2273    to be in augmented form. If you prefer to enter $N$ equations and $M$
2274    unknowns then use ``solve(Neqs, *Msymbols)`` instead. Note: a local
2275    copy of the matrix is made by this routine so the matrix that is
2276    passed will not be modified.
2277
2278    The algorithm used here is fraction-free Gaussian elimination,
2279    which results, after elimination, in an upper-triangular matrix.
2280    Then solutions are found using back-substitution. This approach
2281    is more efficient and compact than the Gauss-Jordan method.
2282
2283    Examples
2284    ========
2285
2286    >>> from sympy import Matrix, solve_linear_system
2287    >>> from sympy.abc import x, y
2288
2289    Solve the following system::
2290
2291           x + 4 y ==  2
2292        -2 x +   y == 14
2293
2294    >>> system = Matrix(( (1, 4, 2), (-2, 1, 14)))
2295    >>> solve_linear_system(system, x, y)
2296    {x: -6, y: 2}
2297
2298    A degenerate system returns an empty dictionary:
2299
2300    >>> system = Matrix(( (0,0,0), (0,0,0) ))
2301    >>> solve_linear_system(system, x, y)
2302    {}
2303
2304    """
2305    assert system.shape[1] == len(symbols) + 1
2306
2307    # This is just a wrapper for solve_lin_sys
2308    eqs = list(system * Matrix(symbols + (-1,)))
2309    eqs, ring = sympy_eqs_to_ring(eqs, symbols)
2310    sol = solve_lin_sys(eqs, ring, _raw=False)
2311    if sol is not None:
2312        sol = {sym:val for sym, val in sol.items() if sym != val}
2313    return sol
2314
2315
2316def solve_undetermined_coeffs(equ, coeffs, sym, **flags):
2317    r"""
2318    Solve equation of a type $p(x; a_1, \ldots, a_k) = q(x)$ where both
2319    $p$ and $q$ are univariate polynomials that depend on $k$ parameters.
2320
2321    Explanation
2322    ===========
2323
2324    The result of this function is a dictionary with symbolic values of those
2325    parameters with respect to coefficients in $q$.
2326
2327    This function accepts both equations class instances and ordinary
2328    SymPy expressions. Specification of parameters and variables is
2329    obligatory for efficiency and simplicity reasons.
2330
2331    Examples
2332    ========
2333
2334    >>> from sympy import Eq
2335    >>> from sympy.abc import a, b, c, x
2336    >>> from sympy.solvers import solve_undetermined_coeffs
2337
2338    >>> solve_undetermined_coeffs(Eq(2*a*x + a+b, x), [a, b], x)
2339    {a: 1/2, b: -1/2}
2340
2341    >>> solve_undetermined_coeffs(Eq(a*c*x + a+b, x), [a, b], x)
2342    {a: 1/c, b: -1/c}
2343
2344    """
2345    if isinstance(equ, Equality):
2346        # got equation, so move all the
2347        # terms to the left hand side
2348        equ = equ.lhs - equ.rhs
2349
2350    equ = cancel(equ).as_numer_denom()[0]
2351
2352    system = list(collect(equ.expand(), sym, evaluate=False).values())
2353
2354    if not any(equ.has(sym) for equ in system):
2355        # consecutive powers in the input expressions have
2356        # been successfully collected, so solve remaining
2357        # system using Gaussian elimination algorithm
2358        return solve(system, *coeffs, **flags)
2359    else:
2360        return None  # no solutions
2361
2362
2363def solve_linear_system_LU(matrix, syms):
2364    """
2365    Solves the augmented matrix system using ``LUsolve`` and returns a
2366    dictionary in which solutions are keyed to the symbols of *syms* as ordered.
2367
2368    Explanation
2369    ===========
2370
2371    The matrix must be invertible.
2372
2373    Examples
2374    ========
2375
2376    >>> from sympy import Matrix
2377    >>> from sympy.abc import x, y, z
2378    >>> from sympy.solvers.solvers import solve_linear_system_LU
2379
2380    >>> solve_linear_system_LU(Matrix([
2381    ... [1, 2, 0, 1],
2382    ... [3, 2, 2, 1],
2383    ... [2, 0, 0, 1]]), [x, y, z])
2384    {x: 1/2, y: 1/4, z: -1/2}
2385
2386    See Also
2387    ========
2388
2389    LUsolve
2390
2391    """
2392    if matrix.rows != matrix.cols - 1:
2393        raise ValueError("Rows should be equal to columns - 1")
2394    A = matrix[:matrix.rows, :matrix.rows]
2395    b = matrix[:, matrix.cols - 1:]
2396    soln = A.LUsolve(b)
2397    solutions = {}
2398    for i in range(soln.rows):
2399        solutions[syms[i]] = soln[i, 0]
2400    return solutions
2401
2402
2403def det_perm(M):
2404    """
2405    Return the determinant of *M* by using permutations to select factors.
2406
2407    Explanation
2408    ===========
2409
2410    For sizes larger than 8 the number of permutations becomes prohibitively
2411    large, or if there are no symbols in the matrix, it is better to use the
2412    standard determinant routines (e.g., ``M.det()``.)
2413
2414    See Also
2415    ========
2416
2417    det_minor
2418    det_quick
2419
2420    """
2421    args = []
2422    s = True
2423    n = M.rows
2424    list_ = M.flat()
2425    for perm in generate_bell(n):
2426        fac = []
2427        idx = 0
2428        for j in perm:
2429            fac.append(list_[idx + j])
2430            idx += n
2431        term = Mul(*fac) # disaster with unevaluated Mul -- takes forever for n=7
2432        args.append(term if s else -term)
2433        s = not s
2434    return Add(*args)
2435
2436
2437def det_minor(M):
2438    """
2439    Return the ``det(M)`` computed from minors without
2440    introducing new nesting in products.
2441
2442    See Also
2443    ========
2444
2445    det_perm
2446    det_quick
2447
2448    """
2449    n = M.rows
2450    if n == 2:
2451        return M[0, 0]*M[1, 1] - M[1, 0]*M[0, 1]
2452    else:
2453        return sum([(1, -1)[i % 2]*Add(*[M[0, i]*d for d in
2454            Add.make_args(det_minor(M.minor_submatrix(0, i)))])
2455            if M[0, i] else S.Zero for i in range(n)])
2456
2457
2458def det_quick(M, method=None):
2459    """
2460    Return ``det(M)`` assuming that either
2461    there are lots of zeros or the size of the matrix
2462    is small. If this assumption is not met, then the normal
2463    Matrix.det function will be used with method = ``method``.
2464
2465    See Also
2466    ========
2467
2468    det_minor
2469    det_perm
2470
2471    """
2472    if any(i.has(Symbol) for i in M):
2473        if M.rows < 8 and all(i.has(Symbol) for i in M):
2474            return det_perm(M)
2475        return det_minor(M)
2476    else:
2477        return M.det(method=method) if method else M.det()
2478
2479
2480def inv_quick(M):
2481    """Return the inverse of ``M``, assuming that either
2482    there are lots of zeros or the size of the matrix
2483    is small.
2484    """
2485    from sympy.matrices import zeros
2486    if not all(i.is_Number for i in M):
2487        if not any(i.is_Number for i in M):
2488            det = lambda _: det_perm(_)
2489        else:
2490            det = lambda _: det_minor(_)
2491    else:
2492        return M.inv()
2493    n = M.rows
2494    d = det(M)
2495    if d == S.Zero:
2496        raise NonInvertibleMatrixError("Matrix det == 0; not invertible")
2497    ret = zeros(n)
2498    s1 = -1
2499    for i in range(n):
2500        s = s1 = -s1
2501        for j in range(n):
2502            di = det(M.minor_submatrix(i, j))
2503            ret[j, i] = s*di/d
2504            s = -s
2505    return ret
2506
2507
2508# these are functions that have multiple inverse values per period
2509multi_inverses = {
2510    sin: lambda x: (asin(x), S.Pi - asin(x)),
2511    cos: lambda x: (acos(x), 2*S.Pi - acos(x)),
2512}
2513
2514
2515def _tsolve(eq, sym, **flags):
2516    """
2517    Helper for ``_solve`` that solves a transcendental equation with respect
2518    to the given symbol. Various equations containing powers and logarithms,
2519    can be solved.
2520
2521    There is currently no guarantee that all solutions will be returned or
2522    that a real solution will be favored over a complex one.
2523
2524    Either a list of potential solutions will be returned or None will be
2525    returned (in the case that no method was known to get a solution
2526    for the equation). All other errors (like the inability to cast an
2527    expression as a Poly) are unhandled.
2528
2529    Examples
2530    ========
2531
2532    >>> from sympy import log
2533    >>> from sympy.solvers.solvers import _tsolve as tsolve
2534    >>> from sympy.abc import x
2535
2536    >>> tsolve(3**(2*x + 5) - 4, x)
2537    [-5/2 + log(2)/log(3), (-5*log(3)/2 + log(2) + I*pi)/log(3)]
2538
2539    >>> tsolve(log(x) + 2*x, x)
2540    [LambertW(2)/2]
2541
2542    """
2543    if 'tsolve_saw' not in flags:
2544        flags['tsolve_saw'] = []
2545    if eq in flags['tsolve_saw']:
2546        return None
2547    else:
2548        flags['tsolve_saw'].append(eq)
2549
2550    rhs, lhs = _invert(eq, sym)
2551
2552    if lhs == sym:
2553        return [rhs]
2554    try:
2555        if lhs.is_Add:
2556            # it's time to try factoring; powdenest is used
2557            # to try get powers in standard form for better factoring
2558            f = factor(powdenest(lhs - rhs))
2559            if f.is_Mul:
2560                return _solve(f, sym, **flags)
2561            if rhs:
2562                f = logcombine(lhs, force=flags.get('force', True))
2563                if f.count(log) != lhs.count(log):
2564                    if isinstance(f, log):
2565                        return _solve(f.args[0] - exp(rhs), sym, **flags)
2566                    return _tsolve(f - rhs, sym, **flags)
2567
2568        elif lhs.is_Pow:
2569            if lhs.exp.is_Integer:
2570                if lhs - rhs != eq:
2571                    return _solve(lhs - rhs, sym, **flags)
2572
2573            if sym not in lhs.exp.free_symbols:
2574                return _solve(lhs.base - rhs**(1/lhs.exp), sym, **flags)
2575
2576            # _tsolve calls this with Dummy before passing the actual number in.
2577            if any(t.is_Dummy for t in rhs.free_symbols):
2578                raise NotImplementedError # _tsolve will call here again...
2579
2580            # a ** g(x) == 0
2581            if not rhs:
2582                # f(x)**g(x) only has solutions where f(x) == 0 and g(x) != 0 at
2583                # the same place
2584                sol_base = _solve(lhs.base, sym, **flags)
2585                return [s for s in sol_base if lhs.exp.subs(sym, s) != 0]
2586
2587            # a ** g(x) == b
2588            if not lhs.base.has(sym):
2589                if lhs.base == 0:
2590                    return _solve(lhs.exp, sym, **flags) if rhs != 0 else []
2591
2592                # Gets most solutions...
2593                if lhs.base == rhs.as_base_exp()[0]:
2594                    # handles case when bases are equal
2595                    sol = _solve(lhs.exp - rhs.as_base_exp()[1], sym, **flags)
2596                else:
2597                    # handles cases when bases are not equal and exp
2598                    # may or may not be equal
2599                    sol = _solve(exp(log(lhs.base)*lhs.exp)-exp(log(rhs)), sym, **flags)
2600
2601                # Check for duplicate solutions
2602                def equal(expr1, expr2):
2603                    _ = Dummy()
2604                    eq = checksol(expr1 - _, _, expr2)
2605                    if eq is None:
2606                        if nsimplify(expr1) != nsimplify(expr2):
2607                            return False
2608                        # they might be coincidentally the same
2609                        # so check more rigorously
2610                        eq = expr1.equals(expr2)
2611                    return eq
2612
2613                # Guess a rational exponent
2614                e_rat = nsimplify(log(abs(rhs))/log(abs(lhs.base)))
2615                e_rat = simplify(posify(e_rat)[0])
2616                n, d = fraction(e_rat)
2617                if expand(lhs.base**n - rhs**d) == 0:
2618                    sol = [s for s in sol if not equal(lhs.exp.subs(sym, s), e_rat)]
2619                    sol.extend(_solve(lhs.exp - e_rat, sym, **flags))
2620
2621                return list(ordered(set(sol)))
2622
2623            # f(x) ** g(x) == c
2624            else:
2625                sol = []
2626                logform = lhs.exp*log(lhs.base) - log(rhs)
2627                if logform != lhs - rhs:
2628                    try:
2629                        sol.extend(_solve(logform, sym, **flags))
2630                    except NotImplementedError:
2631                        pass
2632
2633                # Collect possible solutions and check with substitution later.
2634                check = []
2635                if rhs == 1:
2636                    # f(x) ** g(x) = 1 -- g(x)=0 or f(x)=+-1
2637                    check.extend(_solve(lhs.exp, sym, **flags))
2638                    check.extend(_solve(lhs.base - 1, sym, **flags))
2639                    check.extend(_solve(lhs.base + 1, sym, **flags))
2640                elif rhs.is_Rational:
2641                    for d in (i for i in divisors(abs(rhs.p)) if i != 1):
2642                        e, t = integer_log(rhs.p, d)
2643                        if not t:
2644                            continue  # rhs.p != d**b
2645                        for s in divisors(abs(rhs.q)):
2646                            if s**e== rhs.q:
2647                                r = Rational(d, s)
2648                                check.extend(_solve(lhs.base - r, sym, **flags))
2649                                check.extend(_solve(lhs.base + r, sym, **flags))
2650                                check.extend(_solve(lhs.exp - e, sym, **flags))
2651                elif rhs.is_irrational:
2652                    b_l, e_l = lhs.base.as_base_exp()
2653                    n, d = (e_l*lhs.exp).as_numer_denom()
2654                    b, e = sqrtdenest(rhs).as_base_exp()
2655                    check = [sqrtdenest(i) for i in (_solve(lhs.base - b, sym, **flags))]
2656                    check.extend([sqrtdenest(i) for i in (_solve(lhs.exp - e, sym, **flags))])
2657                    if e_l*d != 1:
2658                        check.extend(_solve(b_l**n - rhs**(e_l*d), sym, **flags))
2659                for s in check:
2660                    ok = checksol(eq, sym, s)
2661                    if ok is None:
2662                        ok = eq.subs(sym, s).equals(0)
2663                    if ok:
2664                        sol.append(s)
2665                return list(ordered(set(sol)))
2666
2667        elif lhs.is_Function and len(lhs.args) == 1:
2668            if lhs.func in multi_inverses:
2669                # sin(x) = 1/3 -> x - asin(1/3) & x - (pi - asin(1/3))
2670                soln = []
2671                for i in multi_inverses[lhs.func](rhs):
2672                    soln.extend(_solve(lhs.args[0] - i, sym, **flags))
2673                return list(ordered(soln))
2674            elif lhs.func == LambertW:
2675                return _solve(lhs.args[0] - rhs*exp(rhs), sym, **flags)
2676
2677        rewrite = lhs.rewrite(exp)
2678        if rewrite != lhs:
2679            return _solve(rewrite - rhs, sym, **flags)
2680    except NotImplementedError:
2681        pass
2682
2683    # maybe it is a lambert pattern
2684    if flags.pop('bivariate', True):
2685        # lambert forms may need some help being recognized, e.g. changing
2686        # 2**(3*x) + x**3*log(2)**3 + 3*x**2*log(2)**2 + 3*x*log(2) + 1
2687        # to 2**(3*x) + (x*log(2) + 1)**3
2688        g = _filtered_gens(eq.as_poly(), sym)
2689        up_or_log = set()
2690        for gi in g:
2691            if isinstance(gi, exp) or (gi.is_Pow and gi.base == S.Exp1) or isinstance(gi, log):
2692                up_or_log.add(gi)
2693            elif gi.is_Pow:
2694                gisimp = powdenest(expand_power_exp(gi))
2695                if gisimp.is_Pow and sym in gisimp.exp.free_symbols:
2696                    up_or_log.add(gi)
2697        eq_down = expand_log(expand_power_exp(eq)).subs(
2698            dict(list(zip(up_or_log, [0]*len(up_or_log)))))
2699        eq = expand_power_exp(factor(eq_down, deep=True) + (eq - eq_down))
2700        rhs, lhs = _invert(eq, sym)
2701        if lhs.has(sym):
2702            try:
2703                poly = lhs.as_poly()
2704                g = _filtered_gens(poly, sym)
2705                _eq = lhs - rhs
2706                sols = _solve_lambert(_eq, sym, g)
2707                # use a simplified form if it satisfies eq
2708                # and has fewer operations
2709                for n, s in enumerate(sols):
2710                    ns = nsimplify(s)
2711                    if ns != s and ns.count_ops() <= s.count_ops():
2712                        ok = checksol(_eq, sym, ns)
2713                        if ok is None:
2714                            ok = _eq.subs(sym, ns).equals(0)
2715                        if ok:
2716                            sols[n] = ns
2717                return sols
2718            except NotImplementedError:
2719                # maybe it's a convoluted function
2720                if len(g) == 2:
2721                    try:
2722                        gpu = bivariate_type(lhs - rhs, *g)
2723                        if gpu is None:
2724                            raise NotImplementedError
2725                        g, p, u = gpu
2726                        flags['bivariate'] = False
2727                        inversion = _tsolve(g - u, sym, **flags)
2728                        if inversion:
2729                            sol = _solve(p, u, **flags)
2730                            return list(ordered({i.subs(u, s)
2731                                for i in inversion for s in sol}))
2732                    except NotImplementedError:
2733                        pass
2734                else:
2735                    pass
2736
2737    if flags.pop('force', True):
2738        flags['force'] = False
2739        pos, reps = posify(lhs - rhs)
2740        if rhs == S.ComplexInfinity:
2741            return []
2742        for u, s in reps.items():
2743            if s == sym:
2744                break
2745        else:
2746            u = sym
2747        if pos.has(u):
2748            try:
2749                soln = _solve(pos, u, **flags)
2750                return list(ordered([s.subs(reps) for s in soln]))
2751            except NotImplementedError:
2752                pass
2753        else:
2754            pass  # here for coverage
2755
2756    return  # here for coverage
2757
2758
2759# TODO: option for calculating J numerically
2760
2761@conserve_mpmath_dps
2762def nsolve(*args, dict=False, **kwargs):
2763    r"""
2764    Solve a nonlinear equation system numerically: ``nsolve(f, [args,] x0,
2765    modules=['mpmath'], **kwargs)``.
2766
2767    Explanation
2768    ===========
2769
2770    ``f`` is a vector function of symbolic expressions representing the system.
2771    *args* are the variables. If there is only one variable, this argument can
2772    be omitted. ``x0`` is a starting vector close to a solution.
2773
2774    Use the modules keyword to specify which modules should be used to
2775    evaluate the function and the Jacobian matrix. Make sure to use a module
2776    that supports matrices. For more information on the syntax, please see the
2777    docstring of ``lambdify``.
2778
2779    If the keyword arguments contain ``dict=True`` (default is False) ``nsolve``
2780    will return a list (perhaps empty) of solution mappings. This might be
2781    especially useful if you want to use ``nsolve`` as a fallback to solve since
2782    using the dict argument for both methods produces return values of
2783    consistent type structure. Please note: to keep this consistent with
2784    ``solve``, the solution will be returned in a list even though ``nsolve``
2785    (currently at least) only finds one solution at a time.
2786
2787    Overdetermined systems are supported.
2788
2789    Examples
2790    ========
2791
2792    >>> from sympy import Symbol, nsolve
2793    >>> import mpmath
2794    >>> mpmath.mp.dps = 15
2795    >>> x1 = Symbol('x1')
2796    >>> x2 = Symbol('x2')
2797    >>> f1 = 3 * x1**2 - 2 * x2**2 - 1
2798    >>> f2 = x1**2 - 2 * x1 + x2**2 + 2 * x2 - 8
2799    >>> print(nsolve((f1, f2), (x1, x2), (-1, 1)))
2800    Matrix([[-1.19287309935246], [1.27844411169911]])
2801
2802    For one-dimensional functions the syntax is simplified:
2803
2804    >>> from sympy import sin, nsolve
2805    >>> from sympy.abc import x
2806    >>> nsolve(sin(x), x, 2)
2807    3.14159265358979
2808    >>> nsolve(sin(x), 2)
2809    3.14159265358979
2810
2811    To solve with higher precision than the default, use the prec argument:
2812
2813    >>> from sympy import cos
2814    >>> nsolve(cos(x) - x, 1)
2815    0.739085133215161
2816    >>> nsolve(cos(x) - x, 1, prec=50)
2817    0.73908513321516064165531208767387340401341175890076
2818    >>> cos(_)
2819    0.73908513321516064165531208767387340401341175890076
2820
2821    To solve for complex roots of real functions, a nonreal initial point
2822    must be specified:
2823
2824    >>> from sympy import I
2825    >>> nsolve(x**2 + 2, I)
2826    1.4142135623731*I
2827
2828    ``mpmath.findroot`` is used and you can find their more extensive
2829    documentation, especially concerning keyword parameters and
2830    available solvers. Note, however, that functions which are very
2831    steep near the root, the verification of the solution may fail. In
2832    this case you should use the flag ``verify=False`` and
2833    independently verify the solution.
2834
2835    >>> from sympy import cos, cosh
2836    >>> f = cos(x)*cosh(x) - 1
2837    >>> nsolve(f, 3.14*100)
2838    Traceback (most recent call last):
2839    ...
2840    ValueError: Could not find root within given tolerance. (1.39267e+230 > 2.1684e-19)
2841    >>> ans = nsolve(f, 3.14*100, verify=False); ans
2842    312.588469032184
2843    >>> f.subs(x, ans).n(2)
2844    2.1e+121
2845    >>> (f/f.diff(x)).subs(x, ans).n(2)
2846    7.4e-15
2847
2848    One might safely skip the verification if bounds of the root are known
2849    and a bisection method is used:
2850
2851    >>> bounds = lambda i: (3.14*i, 3.14*(i + 1))
2852    >>> nsolve(f, bounds(100), solver='bisect', verify=False)
2853    315.730061685774
2854
2855    Alternatively, a function may be better behaved when the
2856    denominator is ignored. Since this is not always the case, however,
2857    the decision of what function to use is left to the discretion of
2858    the user.
2859
2860    >>> eq = x**2/(1 - x)/(1 - 2*x)**2 - 100
2861    >>> nsolve(eq, 0.46)
2862    Traceback (most recent call last):
2863    ...
2864    ValueError: Could not find root within given tolerance. (10000 > 2.1684e-19)
2865    Try another starting point or tweak arguments.
2866    >>> nsolve(eq.as_numer_denom()[0], 0.46)
2867    0.46792545969349058
2868
2869    """
2870    # there are several other SymPy functions that use method= so
2871    # guard against that here
2872    if 'method' in kwargs:
2873        raise ValueError(filldedent('''
2874            Keyword "method" should not be used in this context.  When using
2875            some mpmath solvers directly, the keyword "method" is
2876            used, but when using nsolve (and findroot) the keyword to use is
2877            "solver".'''))
2878
2879    if 'prec' in kwargs:
2880        prec = kwargs.pop('prec')
2881        import mpmath
2882        mpmath.mp.dps = prec
2883    else:
2884        prec = None
2885
2886    # keyword argument to return result as a dictionary
2887    as_dict = dict
2888    from builtins import dict  # to unhide the builtin
2889
2890    # interpret arguments
2891    if len(args) == 3:
2892        f = args[0]
2893        fargs = args[1]
2894        x0 = args[2]
2895        if iterable(fargs) and iterable(x0):
2896            if len(x0) != len(fargs):
2897                raise TypeError('nsolve expected exactly %i guess vectors, got %i'
2898                                % (len(fargs), len(x0)))
2899    elif len(args) == 2:
2900        f = args[0]
2901        fargs = None
2902        x0 = args[1]
2903        if iterable(f):
2904            raise TypeError('nsolve expected 3 arguments, got 2')
2905    elif len(args) < 2:
2906        raise TypeError('nsolve expected at least 2 arguments, got %i'
2907                        % len(args))
2908    else:
2909        raise TypeError('nsolve expected at most 3 arguments, got %i'
2910                        % len(args))
2911    modules = kwargs.get('modules', ['mpmath'])
2912    if iterable(f):
2913        f = list(f)
2914        for i, fi in enumerate(f):
2915            if isinstance(fi, Equality):
2916                f[i] = fi.lhs - fi.rhs
2917        f = Matrix(f).T
2918    if iterable(x0):
2919        x0 = list(x0)
2920    if not isinstance(f, Matrix):
2921        # assume it's a sympy expression
2922        if isinstance(f, Equality):
2923            f = f.lhs - f.rhs
2924        syms = f.free_symbols
2925        if fargs is None:
2926            fargs = syms.copy().pop()
2927        if not (len(syms) == 1 and (fargs in syms or fargs[0] in syms)):
2928            raise ValueError(filldedent('''
2929                expected a one-dimensional and numerical function'''))
2930
2931        # the function is much better behaved if there is no denominator
2932        # but sending the numerator is left to the user since sometimes
2933        # the function is better behaved when the denominator is present
2934        # e.g., issue 11768
2935
2936        f = lambdify(fargs, f, modules)
2937        x = sympify(findroot(f, x0, **kwargs))
2938        if as_dict:
2939            return [{fargs: x}]
2940        return x
2941
2942    if len(fargs) > f.cols:
2943        raise NotImplementedError(filldedent('''
2944            need at least as many equations as variables'''))
2945    verbose = kwargs.get('verbose', False)
2946    if verbose:
2947        print('f(x):')
2948        print(f)
2949    # derive Jacobian
2950    J = f.jacobian(fargs)
2951    if verbose:
2952        print('J(x):')
2953        print(J)
2954    # create functions
2955    f = lambdify(fargs, f.T, modules)
2956    J = lambdify(fargs, J, modules)
2957    # solve the system numerically
2958    x = findroot(f, x0, J=J, **kwargs)
2959    if as_dict:
2960        return [dict(zip(fargs, [sympify(xi) for xi in x]))]
2961    return Matrix(x)
2962
2963
2964def _invert(eq, *symbols, **kwargs):
2965    """
2966    Return tuple (i, d) where ``i`` is independent of *symbols* and ``d``
2967    contains symbols.
2968
2969    Explanation
2970    ===========
2971
2972    ``i`` and ``d`` are obtained after recursively using algebraic inversion
2973    until an uninvertible ``d`` remains. If there are no free symbols then
2974    ``d`` will be zero. Some (but not necessarily all) solutions to the
2975    expression ``i - d`` will be related to the solutions of the original
2976    expression.
2977
2978    Examples
2979    ========
2980
2981    >>> from sympy.solvers.solvers import _invert as invert
2982    >>> from sympy import sqrt, cos
2983    >>> from sympy.abc import x, y
2984    >>> invert(x - 3)
2985    (3, x)
2986    >>> invert(3)
2987    (3, 0)
2988    >>> invert(2*cos(x) - 1)
2989    (1/2, cos(x))
2990    >>> invert(sqrt(x) - 3)
2991    (3, sqrt(x))
2992    >>> invert(sqrt(x) + y, x)
2993    (-y, sqrt(x))
2994    >>> invert(sqrt(x) + y, y)
2995    (-sqrt(x), y)
2996    >>> invert(sqrt(x) + y, x, y)
2997    (0, sqrt(x) + y)
2998
2999    If there is more than one symbol in a power's base and the exponent
3000    is not an Integer, then the principal root will be used for the
3001    inversion:
3002
3003    >>> invert(sqrt(x + y) - 2)
3004    (4, x + y)
3005    >>> invert(sqrt(x + y) - 2)
3006    (4, x + y)
3007
3008    If the exponent is an Integer, setting ``integer_power`` to True
3009    will force the principal root to be selected:
3010
3011    >>> invert(x**2 - 4, integer_power=True)
3012    (2, x)
3013
3014    """
3015    eq = sympify(eq)
3016    if eq.args:
3017        # make sure we are working with flat eq
3018        eq = eq.func(*eq.args)
3019    free = eq.free_symbols
3020    if not symbols:
3021        symbols = free
3022    if not free & set(symbols):
3023        return eq, S.Zero
3024
3025    dointpow = bool(kwargs.get('integer_power', False))
3026
3027    lhs = eq
3028    rhs = S.Zero
3029    while True:
3030        was = lhs
3031        while True:
3032            indep, dep = lhs.as_independent(*symbols)
3033
3034            # dep + indep == rhs
3035            if lhs.is_Add:
3036                # this indicates we have done it all
3037                if indep.is_zero:
3038                    break
3039
3040                lhs = dep
3041                rhs -= indep
3042
3043            # dep * indep == rhs
3044            else:
3045                # this indicates we have done it all
3046                if indep is S.One:
3047                    break
3048
3049                lhs = dep
3050                rhs /= indep
3051
3052        # collect like-terms in symbols
3053        if lhs.is_Add:
3054            terms = {}
3055            for a in lhs.args:
3056                i, d = a.as_independent(*symbols)
3057                terms.setdefault(d, []).append(i)
3058            if any(len(v) > 1 for v in terms.values()):
3059                args = []
3060                for d, i in terms.items():
3061                    if len(i) > 1:
3062                        args.append(Add(*i)*d)
3063                    else:
3064                        args.append(i[0]*d)
3065                lhs = Add(*args)
3066
3067        # if it's a two-term Add with rhs = 0 and two powers we can get the
3068        # dependent terms together, e.g. 3*f(x) + 2*g(x) -> f(x)/g(x) = -2/3
3069        if lhs.is_Add and not rhs and len(lhs.args) == 2 and \
3070                not lhs.is_polynomial(*symbols):
3071            a, b = ordered(lhs.args)
3072            ai, ad = a.as_independent(*symbols)
3073            bi, bd = b.as_independent(*symbols)
3074            if any(_ispow(i) for i in (ad, bd)):
3075                a_base, a_exp = ad.as_base_exp()
3076                b_base, b_exp = bd.as_base_exp()
3077                if a_base == b_base:
3078                    # a = -b
3079                    lhs = powsimp(powdenest(ad/bd))
3080                    rhs = -bi/ai
3081                else:
3082                    rat = ad/bd
3083                    _lhs = powsimp(ad/bd)
3084                    if _lhs != rat:
3085                        lhs = _lhs
3086                        rhs = -bi/ai
3087            elif ai == -bi:
3088                if isinstance(ad, Function) and ad.func == bd.func:
3089                    if len(ad.args) == len(bd.args) == 1:
3090                        lhs = ad.args[0] - bd.args[0]
3091                    elif len(ad.args) == len(bd.args):
3092                        # should be able to solve
3093                        # f(x, y) - f(2 - x, 0) == 0 -> x == 1
3094                        raise NotImplementedError(
3095                            'equal function with more than 1 argument')
3096                    else:
3097                        raise ValueError(
3098                            'function with different numbers of args')
3099
3100        elif lhs.is_Mul and any(_ispow(a) for a in lhs.args):
3101            lhs = powsimp(powdenest(lhs))
3102
3103        if lhs.is_Function:
3104            if hasattr(lhs, 'inverse') and lhs.inverse() is not None and len(lhs.args) == 1:
3105                #                    -1
3106                # f(x) = g  ->  x = f  (g)
3107                #
3108                # /!\ inverse should not be defined if there are multiple values
3109                # for the function -- these are handled in _tsolve
3110                #
3111                rhs = lhs.inverse()(rhs)
3112                lhs = lhs.args[0]
3113            elif isinstance(lhs, atan2):
3114                y, x = lhs.args
3115                lhs = 2*atan(y/(sqrt(x**2 + y**2) + x))
3116            elif lhs.func == rhs.func:
3117                if len(lhs.args) == len(rhs.args) == 1:
3118                    lhs = lhs.args[0]
3119                    rhs = rhs.args[0]
3120                elif len(lhs.args) == len(rhs.args):
3121                    # should be able to solve
3122                    # f(x, y) == f(2, 3) -> x == 2
3123                    # f(x, x + y) == f(2, 3) -> x == 2
3124                    raise NotImplementedError(
3125                        'equal function with more than 1 argument')
3126                else:
3127                    raise ValueError(
3128                        'function with different numbers of args')
3129
3130
3131        if rhs and lhs.is_Pow and lhs.exp.is_Integer and lhs.exp < 0:
3132            lhs = 1/lhs
3133            rhs = 1/rhs
3134
3135        # base**a = b -> base = b**(1/a) if
3136        #    a is an Integer and dointpow=True (this gives real branch of root)
3137        #    a is not an Integer and the equation is multivariate and the
3138        #      base has more than 1 symbol in it
3139        # The rationale for this is that right now the multi-system solvers
3140        # doesn't try to resolve generators to see, for example, if the whole
3141        # system is written in terms of sqrt(x + y) so it will just fail, so we
3142        # do that step here.
3143        if lhs.is_Pow and (
3144            lhs.exp.is_Integer and dointpow or not lhs.exp.is_Integer and
3145                len(symbols) > 1 and len(lhs.base.free_symbols & set(symbols)) > 1):
3146            rhs = rhs**(1/lhs.exp)
3147            lhs = lhs.base
3148
3149        if lhs == was:
3150            break
3151    return rhs, lhs
3152
3153
3154def unrad(eq, *syms, **flags):
3155    """
3156    Remove radicals with symbolic arguments and return (eq, cov),
3157    None, or raise an error.
3158
3159    Explanation
3160    ===========
3161
3162    None is returned if there are no radicals to remove.
3163
3164    NotImplementedError is raised if there are radicals and they cannot be
3165    removed or if the relationship between the original symbols and the
3166    change of variable needed to rewrite the system as a polynomial cannot
3167    be solved.
3168
3169    Otherwise the tuple, ``(eq, cov)``, is returned where:
3170
3171    *eq*, ``cov``
3172        *eq* is an equation without radicals (in the symbol(s) of
3173        interest) whose solutions are a superset of the solutions to the
3174        original expression. *eq* might be rewritten in terms of a new
3175        variable; the relationship to the original variables is given by
3176        ``cov`` which is a list containing ``v`` and ``v**p - b`` where
3177        ``p`` is the power needed to clear the radical and ``b`` is the
3178        radical now expressed as a polynomial in the symbols of interest.
3179        For example, for sqrt(2 - x) the tuple would be
3180        ``(c, c**2 - 2 + x)``. The solutions of *eq* will contain
3181        solutions to the original equation (if there are any).
3182
3183    *syms*
3184        An iterable of symbols which, if provided, will limit the focus of
3185        radical removal: only radicals with one or more of the symbols of
3186        interest will be cleared. All free symbols are used if *syms* is not
3187        set.
3188
3189    *flags* are used internally for communication during recursive calls.
3190    Two options are also recognized:
3191
3192        ``take``, when defined, is interpreted as a single-argument function
3193        that returns True if a given Pow should be handled.
3194
3195    Radicals can be removed from an expression if:
3196
3197        *   All bases of the radicals are the same; a change of variables is
3198            done in this case.
3199        *   If all radicals appear in one term of the expression.
3200        *   There are only four terms with sqrt() factors or there are less than
3201            four terms having sqrt() factors.
3202        *   There are only two terms with radicals.
3203
3204    Examples
3205    ========
3206
3207    >>> from sympy.solvers.solvers import unrad
3208    >>> from sympy.abc import x
3209    >>> from sympy import sqrt, Rational, root
3210
3211    >>> unrad(sqrt(x)*x**Rational(1, 3) + 2)
3212    (x**5 - 64, [])
3213    >>> unrad(sqrt(x) + root(x + 1, 3))
3214    (-x**3 + x**2 + 2*x + 1, [])
3215    >>> eq = sqrt(x) + root(x, 3) - 2
3216    >>> unrad(eq)
3217    (_p**3 + _p**2 - 2, [_p, _p**6 - x])
3218
3219    """
3220    from sympy import Equality as Eq
3221
3222    uflags = dict(check=False, simplify=False)
3223
3224    def _cov(p, e):
3225        if cov:
3226            # XXX - uncovered
3227            oldp, olde = cov
3228            if Poly(e, p).degree(p) in (1, 2):
3229                cov[:] = [p, olde.subs(oldp, _solve(e, p, **uflags)[0])]
3230            else:
3231                raise NotImplementedError
3232        else:
3233            cov[:] = [p, e]
3234
3235    def _canonical(eq, cov):
3236        if cov:
3237            # change symbol to vanilla so no solutions are eliminated
3238            p, e = cov
3239            rep = {p: Dummy(p.name)}
3240            eq = eq.xreplace(rep)
3241            cov = [p.xreplace(rep), e.xreplace(rep)]
3242
3243        # remove constants and powers of factors since these don't change
3244        # the location of the root; XXX should factor or factor_terms be used?
3245        eq = factor_terms(_mexpand(eq.as_numer_denom()[0], recursive=True), clear=True)
3246        if eq.is_Mul:
3247            args = []
3248            for f in eq.args:
3249                if f.is_number:
3250                    continue
3251                if f.is_Pow:
3252                    args.append(f.base)
3253                else:
3254                    args.append(f)
3255            eq = Mul(*args)  # leave as Mul for more efficient solving
3256
3257        # make the sign canonical
3258        margs = list(Mul.make_args(eq))
3259        changed = False
3260        for i, m in enumerate(margs):
3261            if m.could_extract_minus_sign():
3262                margs[i] = -m
3263                changed = True
3264        if changed:
3265            eq = Mul(*margs, evaluate=False)
3266
3267        return eq, cov
3268
3269    def _Q(pow):
3270        # return leading Rational of denominator of Pow's exponent
3271        c = pow.as_base_exp()[1].as_coeff_Mul()[0]
3272        if not c.is_Rational:
3273            return S.One
3274        return c.q
3275
3276    # define the _take method that will determine whether a term is of interest
3277    def _take(d):
3278        # return True if coefficient of any factor's exponent's den is not 1
3279        for pow in Mul.make_args(d):
3280            if not pow.is_Pow:
3281                continue
3282            if _Q(pow) == 1:
3283                continue
3284            if pow.free_symbols & syms:
3285                return True
3286        return False
3287    _take = flags.setdefault('_take', _take)
3288
3289    if isinstance(eq, Eq):
3290        eq = eq.lhs - eq.rhs  # XXX legacy Eq as Eqn support
3291    elif not isinstance(eq, Expr):
3292        return
3293
3294    cov, nwas, rpt = [flags.setdefault(k, v) for k, v in
3295        sorted(dict(cov=[], n=None, rpt=0).items())]
3296
3297    # preconditioning
3298    eq = powdenest(factor_terms(eq, radical=True, clear=True))
3299    eq = eq.as_numer_denom()[0]
3300    eq = _mexpand(eq, recursive=True)
3301    if eq.is_number:
3302        return
3303
3304    # see if there are radicals in symbols of interest
3305    syms = set(syms) or eq.free_symbols  # _take uses this
3306    poly = eq.as_poly()
3307    gens = [g for g in poly.gens if _take(g)]
3308    if not gens:
3309        return
3310
3311    # recast poly in terms of eigen-gens
3312    poly = eq.as_poly(*gens)
3313
3314    # - an exponent has a symbol of interest (don't handle)
3315    if any(g.exp.has(*syms) for g in gens):
3316        return
3317
3318    def _rads_bases_lcm(poly):
3319        # if all the bases are the same or all the radicals are in one
3320        # term, `lcm` will be the lcm of the denominators of the
3321        # exponents of the radicals
3322        lcm = 1
3323        rads = set()
3324        bases = set()
3325        for g in poly.gens:
3326            q = _Q(g)
3327            if q != 1:
3328                rads.add(g)
3329                lcm = ilcm(lcm, q)
3330                bases.add(g.base)
3331        return rads, bases, lcm
3332    rads, bases, lcm = _rads_bases_lcm(poly)
3333
3334    covsym = Dummy('p', nonnegative=True)
3335
3336    # only keep in syms symbols that actually appear in radicals;
3337    # and update gens
3338    newsyms = set()
3339    for r in rads:
3340        newsyms.update(syms & r.free_symbols)
3341    if newsyms != syms:
3342        syms = newsyms
3343    # get terms together that have common generators
3344    drad = dict(list(zip(rads, list(range(len(rads))))))
3345    rterms = {(): []}
3346    args = Add.make_args(poly.as_expr())
3347    for t in args:
3348        if _take(t):
3349            common = set(t.as_poly().gens).intersection(rads)
3350            key = tuple(sorted([drad[i] for i in common]))
3351        else:
3352            key = ()
3353        rterms.setdefault(key, []).append(t)
3354    others = Add(*rterms.pop(()))
3355    rterms = [Add(*rterms[k]) for k in rterms.keys()]
3356
3357    # the output will depend on the order terms are processed, so
3358    # make it canonical quickly
3359    rterms = list(reversed(list(ordered(rterms))))
3360
3361    ok = False  # we don't have a solution yet
3362    depth = sqrt_depth(eq)
3363
3364    if len(rterms) == 1 and not (rterms[0].is_Add and lcm > 2):
3365        eq = rterms[0]**lcm - ((-others)**lcm)
3366        ok = True
3367    else:
3368        if len(rterms) == 1 and rterms[0].is_Add:
3369            rterms = list(rterms[0].args)
3370        if len(bases) == 1:
3371            b = bases.pop()
3372            if len(syms) > 1:
3373                x = b.free_symbols
3374            else:
3375                x = syms
3376            x = list(ordered(x))[0]
3377            try:
3378                inv = _solve(covsym**lcm - b, x, **uflags)
3379                if not inv:
3380                    raise NotImplementedError
3381                eq = poly.as_expr().subs(b, covsym**lcm).subs(x, inv[0])
3382                _cov(covsym, covsym**lcm - b)
3383                return _canonical(eq, cov)
3384            except NotImplementedError:
3385                pass
3386
3387        if len(rterms) == 2:
3388            if not others:
3389                eq = rterms[0]**lcm - (-rterms[1])**lcm
3390                ok = True
3391            elif not log(lcm, 2).is_Integer:
3392                # the lcm-is-power-of-two case is handled below
3393                r0, r1 = rterms
3394                if flags.get('_reverse', False):
3395                    r1, r0 = r0, r1
3396                i0 = _rads0, _bases0, lcm0 = _rads_bases_lcm(r0.as_poly())
3397                i1 = _rads1, _bases1, lcm1 = _rads_bases_lcm(r1.as_poly())
3398                for reverse in range(2):
3399                    if reverse:
3400                        i0, i1 = i1, i0
3401                        r0, r1 = r1, r0
3402                    _rads1, _, lcm1 = i1
3403                    _rads1 = Mul(*_rads1)
3404                    t1 = _rads1**lcm1
3405                    c = covsym**lcm1 - t1
3406                    for x in syms:
3407                        try:
3408                            sol = _solve(c, x, **uflags)
3409                            if not sol:
3410                                raise NotImplementedError
3411                            neweq = r0.subs(x, sol[0]) + covsym*r1/_rads1 + \
3412                                others
3413                            tmp = unrad(neweq, covsym)
3414                            if tmp:
3415                                eq, newcov = tmp
3416                                if newcov:
3417                                    newp, newc = newcov
3418                                    _cov(newp, c.subs(covsym,
3419                                        _solve(newc, covsym, **uflags)[0]))
3420                                else:
3421                                    _cov(covsym, c)
3422                            else:
3423                                eq = neweq
3424                                _cov(covsym, c)
3425                            ok = True
3426                            break
3427                        except NotImplementedError:
3428                            if reverse:
3429                                raise NotImplementedError(
3430                                    'no successful change of variable found')
3431                            else:
3432                                pass
3433                    if ok:
3434                        break
3435        elif len(rterms) == 3:
3436            # two cube roots and another with order less than 5
3437            # (so an analytical solution can be found) or a base
3438            # that matches one of the cube root bases
3439            info = [_rads_bases_lcm(i.as_poly()) for i in rterms]
3440            RAD = 0
3441            BASES = 1
3442            LCM = 2
3443            if info[0][LCM] != 3:
3444                info.append(info.pop(0))
3445                rterms.append(rterms.pop(0))
3446            elif info[1][LCM] != 3:
3447                info.append(info.pop(1))
3448                rterms.append(rterms.pop(1))
3449            if info[0][LCM] == info[1][LCM] == 3:
3450                if info[1][BASES] != info[2][BASES]:
3451                    info[0], info[1] = info[1], info[0]
3452                    rterms[0], rterms[1] = rterms[1], rterms[0]
3453                if info[1][BASES] == info[2][BASES]:
3454                    eq = rterms[0]**3 + (rterms[1] + rterms[2] + others)**3
3455                    ok = True
3456                elif info[2][LCM] < 5:
3457                    # a*root(A, 3) + b*root(B, 3) + others = c
3458                    a, b, c, d, A, B = [Dummy(i) for i in 'abcdAB']
3459                    # zz represents the unraded expression into which the
3460                    # specifics for this case are substituted
3461                    zz = (c - d)*(A**3*a**9 + 3*A**2*B*a**6*b**3 -
3462                        3*A**2*a**6*c**3 + 9*A**2*a**6*c**2*d - 9*A**2*a**6*c*d**2 +
3463                        3*A**2*a**6*d**3 + 3*A*B**2*a**3*b**6 + 21*A*B*a**3*b**3*c**3 -
3464                        63*A*B*a**3*b**3*c**2*d + 63*A*B*a**3*b**3*c*d**2 -
3465                        21*A*B*a**3*b**3*d**3 + 3*A*a**3*c**6 - 18*A*a**3*c**5*d +
3466                        45*A*a**3*c**4*d**2 - 60*A*a**3*c**3*d**3 + 45*A*a**3*c**2*d**4 -
3467                        18*A*a**3*c*d**5 + 3*A*a**3*d**6 + B**3*b**9 - 3*B**2*b**6*c**3 +
3468                        9*B**2*b**6*c**2*d - 9*B**2*b**6*c*d**2 + 3*B**2*b**6*d**3 +
3469                        3*B*b**3*c**6 - 18*B*b**3*c**5*d + 45*B*b**3*c**4*d**2 -
3470                        60*B*b**3*c**3*d**3 + 45*B*b**3*c**2*d**4 - 18*B*b**3*c*d**5 +
3471                        3*B*b**3*d**6 - c**9 + 9*c**8*d - 36*c**7*d**2 + 84*c**6*d**3 -
3472                        126*c**5*d**4 + 126*c**4*d**5 - 84*c**3*d**6 + 36*c**2*d**7 -
3473                        9*c*d**8 + d**9)
3474                    def _t(i):
3475                        b = Mul(*info[i][RAD])
3476                        return cancel(rterms[i]/b), Mul(*info[i][BASES])
3477                    aa, AA = _t(0)
3478                    bb, BB = _t(1)
3479                    cc = -rterms[2]
3480                    dd = others
3481                    eq = zz.xreplace(dict(zip(
3482                        (a, A, b, B, c, d),
3483                        (aa, AA, bb, BB, cc, dd))))
3484                    ok = True
3485        # handle power-of-2 cases
3486        if not ok:
3487            if log(lcm, 2).is_Integer and (not others and
3488                    len(rterms) == 4 or len(rterms) < 4):
3489                def _norm2(a, b):
3490                    return a**2 + b**2 + 2*a*b
3491
3492                if len(rterms) == 4:
3493                    # (r0+r1)**2 - (r2+r3)**2
3494                    r0, r1, r2, r3 = rterms
3495                    eq = _norm2(r0, r1) - _norm2(r2, r3)
3496                    ok = True
3497                elif len(rterms) == 3:
3498                    # (r1+r2)**2 - (r0+others)**2
3499                    r0, r1, r2 = rterms
3500                    eq = _norm2(r1, r2) - _norm2(r0, others)
3501                    ok = True
3502                elif len(rterms) == 2:
3503                    # r0**2 - (r1+others)**2
3504                    r0, r1 = rterms
3505                    eq = r0**2 - _norm2(r1, others)
3506                    ok = True
3507
3508    new_depth = sqrt_depth(eq) if ok else depth
3509    rpt += 1  # XXX how many repeats with others unchanging is enough?
3510    if not ok or (
3511                nwas is not None and len(rterms) == nwas and
3512                new_depth is not None and new_depth == depth and
3513                rpt > 3):
3514        raise NotImplementedError('Cannot remove all radicals')
3515
3516    flags.update(dict(cov=cov, n=len(rterms), rpt=rpt))
3517    neq = unrad(eq, *syms, **flags)
3518    if neq:
3519        eq, cov = neq
3520    eq, cov = _canonical(eq, cov)
3521    return eq, cov
3522
3523from sympy.solvers.bivariate import (
3524    bivariate_type, _solve_lambert, _filtered_gens)
3525