Beispiel #1
0
def test_unrad():
    s = symbols('s', cls=Dummy)

    # checkers to deal with possibility of answer coming
    # back with a sign change (cf issue 2104)
    def check(rv, ans):
        rv, ans = list(rv), list(ans)
        rv[0] = rv[0].expand()
        ans[0] = ans[0].expand()
        return rv[0] in [ans[0], -ans[0]] and rv[1:] == ans[1:]

    def s_check(rv, ans):
        # get the dummy
        rv = list(rv)
        d = rv[0].atoms(Dummy)
        reps = zip(d, [s]*len(d))
        # replace s with this dummy
        rv = (rv[0].subs(reps).expand(), [(p[0].subs(reps), p[1].subs(reps))
                                   for p in rv[1]],
              [a.subs(reps) for a in rv[2]])
        ans = (ans[0].subs(reps).expand(), [(p[0].subs(reps), p[1].subs(reps))
                                   for p in ans[1]],
               [a.subs(reps) for a in ans[2]])
        return str(rv[0]) in [str(ans[0]), str(-ans[0])] and \
            str(rv[1:]) == str(ans[1:])

    assert check(unrad(sqrt(x)),
                 (x, [], []))
    assert check(unrad(sqrt(x) + 1),
                 (x - 1, [], []))
    assert s_check(unrad(sqrt(x) + x**Rational(1, 3) + 2),
                   (2 + s**2 + s**3, [(s, x - s**6)], []))
    assert check(unrad(sqrt(x)*x**Rational(1, 3) + 2),
                 (x**5 - 64, [], []))
    assert check(unrad(sqrt(x) + (x + 1)**Rational(1, 3)),
                 (x**3 - (x + 1)**2, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + sqrt(2*x)),
                (-2*sqrt(2)*x - 2*x + 1, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + 2),
               (16*x - 9, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + sqrt(1 - x)),
               (-4*x + 5*x**2, [], []))
    assert check(unrad(a*sqrt(x) + b*sqrt(x) + c*sqrt(y) + d*sqrt(y)),
                ((a*sqrt(x) + b*sqrt(x))**2 - (c*sqrt(y) + d*sqrt(y))**2, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x)),
                (2*x - 1, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) - 3),
                (9*x + (x - 5)**2 - 9, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x)),
                (-5*x**2 + 2*x - 1, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x) - 3),
        (-25*x**4 - 376*x**3 - 1256*x**2 + 2272*x - 784, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x) - sqrt(1 - 2*x)),
                (-41*x**4 - 40*x**3 - 232*x**2 + 160*x - 16, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1)), (S(1), [], []))

    eq = sqrt(x) + sqrt(x + 1) + sqrt(1 - sqrt(x))
    assert check(unrad(eq),
               (16*x**3 - 9*x**2, [], []))
    assert set(solve(eq, check=False)) == set([S(0), S(9)/16])
    assert solve(eq) == []
    # but this one really does have those solutions
    assert set(solve(sqrt(x) - sqrt(x + 1) + sqrt(1 - sqrt(x)))) == \
        set([S.Zero, S(9)/16])

    '''NOTE
    real_root changes the value of the result if the solution is
    simplified; `a` in the text below is the root that is not 4/5:
    >>> eq
    sqrt(x) + sqrt(-x + 1) + sqrt(x + 1) - 6*sqrt(5)/5
    >>> eq.subs(x, a).n()
    -0.e-123 + 0.e-127*I
    >>> real_root(eq.subs(x, a)).n()
    -0.e-123 + 0.e-127*I
    >>> (eq.subs(x,simplify(a))).n()
    -0.e-126
    >>> real_root(eq.subs(x, simplify(a))).n()
    0.194825975605452 + 2.15093623885838*I

    >>> sqrt(x).subs(x, real_root(a)).n()
    0.809823827278194 - 0.e-25*I
    >>> sqrt(x).subs(x, (a)).n()
    0.809823827278194 - 0.e-25*I
    >>> sqrt(x).subs(x, simplify(a)).n()
    0.809823827278194 - 5.32999467690853e-25*I
    >>> sqrt(x).subs(x, real_root(simplify(a))).n()
    0.49864610868139 + 1.44572604257047*I
    '''
    eq = (sqrt(x) + sqrt(x + 1) + sqrt(1 - x) - 6*sqrt(5)/5)
    ra = S('''-1484/375 - 4*(-1/2 + sqrt(3)*I/2)*(-12459439/52734375 +
    114*sqrt(12657)/78125)**(1/3) - 172564/(140625*(-1/2 +
    sqrt(3)*I/2)*(-12459439/52734375 + 114*sqrt(12657)/78125)**(1/3))''')
    rb = S(4)/5
    ans = solve(sqrt(x) + sqrt(x + 1) + sqrt(1 - x) - 6*sqrt(5)/5)
    assert all(abs(eq.subs(x, i).n()) < 1e-10 for i in (ra, rb)) and \
        len(ans) == 2 and \
        set([i.n(chop=True) for i in ans]) == \
        set([i.n(chop=True) for i in (ra, rb)])

    raises(ValueError, lambda:
        unrad(-root(x,3)**2 + 2**pi*root(x,3) - x + 2**pi))
    raises(ValueError, lambda:
        unrad(sqrt(x) + sqrt(x + 1) + sqrt(1 - sqrt(x)) + 3))
    raises(ValueError, lambda:
        unrad(sqrt(x) + (x + 1)**Rational(1, 3) + 2*sqrt(y)))
    # same as last but consider only y
    assert check(unrad(sqrt(x) + (x + 1)**Rational(1, 3) + 2*sqrt(y), y),
           (4*y - (sqrt(x) + (x + 1)**(S(1)/3))**2, [], []))
    assert check(unrad(sqrt(x/(1 - x)) + (x + 1)**Rational(1, 3)),
                (x**3/(-x + 1)**3 - (x + 1)**2, [], [(-x + 1)**3]))
    # same as last but consider only y; no y-containing denominators now
    assert s_check(unrad(sqrt(x/(1 - x)) + 2*sqrt(y), y),
           (x/(-x + 1) - 4*y, [], []))
    assert check(unrad(sqrt(x)*sqrt(1 - x) + 2, x),
           (x*(-x + 1) - 4, [], []))

    # http://tutorial.math.lamar.edu/
    #        Classes/Alg/SolveRadicalEqns.aspx#Solve_Rad_Ex2_a
    assert solve(Eq(x, sqrt(x + 6))) == [3]
    assert solve(Eq(x + sqrt(x - 4), 4)) == [4]
    assert solve(Eq(1, x + sqrt(2*x - 3))) == []
    assert set(solve(Eq(sqrt(5*x + 6) - 2, x))) == set([-S(1), S(2)])
    assert set(solve(Eq(sqrt(2*x - 1) - sqrt(x - 4), 2))) == set([S(5), S(13)])
    assert solve(Eq(sqrt(x + 7) + 2, sqrt(3 - x))) == [-6]
    # http://www.purplemath.com/modules/solverad.htm
    assert solve((2*x - 5)**Rational(1, 3) - 3) == [16]
    assert solve((x**3 - 3*x**2)**Rational(1, 3) + 1 - x) == []
    assert set(solve(x + 1 - (x**4 + 4*x**3 - x)**Rational(1, 4))) == \
        set([-S(1)/2, -S(1)/3])
    assert set(solve(sqrt(2*x**2 - 7) - (3 - x))) == set([-S(8), S(2)])
    assert solve(sqrt(2*x + 9) - sqrt(x + 1) - sqrt(x + 4)) == [0]
    assert solve(sqrt(x + 4) + sqrt(2*x - 1) - 3*sqrt(x - 1)) == [5]
    assert solve(sqrt(x)*sqrt(x - 7) - 12) == [16]
    assert solve(sqrt(x - 3) + sqrt(x) - 3) == [4]
    assert solve(sqrt(9*x**2 + 4) - (3*x + 2)) == [0]
    assert solve(sqrt(x) - 2 - 5) == [49]
    assert solve(sqrt(x - 3) - sqrt(x) - 3) == []
    assert solve(sqrt(x - 1) - x + 7) == [10]
    assert solve(sqrt(x - 2) - 5) == [27]
    assert solve(sqrt(17*x - sqrt(x**2 - 5)) - 7) == [3]
    assert solve(sqrt(x) - sqrt(x - 1) + sqrt(sqrt(x))) == []

    # don't posify the expression in unrad and use _mexpand
    z = sqrt(2*x + 1)/sqrt(x) - sqrt(2 + 1/x)
    p = posify(z)[0]
    assert solve(p) == []
    assert solve(z) == []
    assert solve(z + 6*I) == [-S(1)/11]
    assert solve(p + 6*I) == []

    eq = sqrt(2 + I) + 2*I
    assert unrad(eq - x, x, all=True) == (x**4 + 4*x**2 + 8*x + 37, [], [])
    ans = (81*x**8 - 2268*x**6 - 4536*x**5 + 22644*x**4 + 63216*x**3 -
        31608*x**2 - 189648*x + 141358, [], [])
    r = sqrt(sqrt(2)/3 + 7)
    eq = sqrt(r) + r - x
    assert unrad(eq, all=1)
    r2 = sqrt(sqrt(2) + 21)/sqrt(3)
    assert r != r2 and r.equals(r2)
    assert unrad(eq - r + r2, all=True) == ans
Beispiel #2
0
    def transform(self, x, u, inverse=False):
        r"""
        Performs a change of variables from `x` to `u` using the relationship
        given by `x` and `u` which will define the transformations `f` and `F`
        (which are inverses of each other) as follows:

        1) If `x` is a Symbol (which is a variable of integration) then `u`
           will be interpreted as some function, f(u), with inverse F(u).
           This, in effect, just makes the substitution of x with f(x).

        2) If `u` is a Symbol then `x` will be interpreted as some function,
           F(x), with inverse f(u). This is commonly referred to as
           u-substitution.

        The `inverse` option will reverse `x` and `u`. It is a deprecated option
        since `x` and `u` can just be passed in reverse order.

        Once f and F have been identified, the transformation is made as
        follows:

        .. math:: \int_a^b x \mathrm{d}x \rightarrow \int_{F(a)}^{F(b)} f(x)
                  \frac{\mathrm{d}}{\mathrm{d}x}

        where `F(x)` is the inverse of `f(x)` and the limits and integrand have
        been corrected so as to retain the same value after integration.

        Notes
        =====

        The mappings, F(x) or f(u), must lead to a unique integral. Linear
        or rational linear expression, `2*x`, `1/x` and `sqrt(x)`, will
        always work; quadratic expressions like `x**2 - 1` are acceptable
        as long as the resulting integrand does not depend on the sign of
        the solutions (see examples).

        The integral will be returned unchanged if `x` is not a variable of
        integration.

        `x` must be (or contain) only one of of the integration variables. If
        `u` has more than one free symbol then it should be sent as a tuple
        (`u`, `uvar`) where `uvar` identifies which variable is replacing
        the integration variable.
        XXX can it contain another integration variable?

        Examples
        ========

        >>> from sympy.abc import a, b, c, d, x, u, y
        >>> from sympy import Integral, S, cos, sqrt

        >>> i = Integral(x*cos(x**2 - 1), (x, 0, 1))

        transform can change the variable of integration

        >>> i.transform(x, u)
        Integral(u*cos(u**2 - 1), (u, 0, 1))

        transform can perform u-substitution as long as a unique
        integrand is obtained:

        >>> i.transform(x**2 - 1, u)
        Integral(cos(u)/2, (u, -1, 0))

        This attempt fails because x = +/-sqrt(u + 1) and the
        sign does not cancel out of the integrand:

        >>> Integral(cos(x**2 - 1), (x, 0, 1)).transform(x**2 - 1, u)
        Traceback (most recent call last):
        ...
        ValueError:
        The mapping between F(x) and f(u) did not give a unique integrand.

        transform can do a substitution. Here, the previous
        result is transformed back into the original expression
        using "u-substitution":

        >>> ui = _
        >>> _.transform(sqrt(u + 1), x) == i
        True

        We can accomplish the same with a regular substitution:

        >>> ui.transform(u, x**2 - 1) == i
        True

        If the `x` does not contain a symbol of integration then
        the integral will be returned unchanged. Integral `i` does
        not have an integration variable `a` so no change is made:

        >>> i.transform(a, x) == i
        True

        When `u` has more than one free symbol the symbol that is
        replacing `x` must be identified by passing `u` as a tuple:

        >>> Integral(x, (x, 0, 1)).transform(x, (u + a, u))
        Integral(a + u, (u, -a, -a + 1))
        >>> Integral(x, (x, 0, 1)).transform(x, (u + a, a))
        Integral(a + u, (a, -u, -u + 1))

        See Also
        ========

        variables : Lists the integration variables
        as_dummy : Replace integration variables with dummy ones
        """

        if inverse:
            # when this is removed, update the docstring
            from sympy.utilities.exceptions import SymPyDeprecationWarning
            SymPyDeprecationWarning(
                feature="transform(x, f(x), inverse=True)",
                useinstead="transform(f(x), x)",
                issue=3380, deprecated_since_version="0.7.2",
            ).warn()
            # in the old style x and u contained the same variable so
            # don't worry about using the old-style feature with the
            # new style input...but it will still work:
            # i.transform(x, u).transform(x, u, inverse=True) -> i
            x, u = u, x

        d = Dummy('d')

        xfree = x.free_symbols.intersection(self.variables)
        if len(xfree) > 1:
            raise ValueError(
                'F(x) can only contain one of: %s' % self.variables)
        xvar = xfree.pop() if xfree else d

        if xvar not in self.variables:
            return self

        u = sympify(u)
        if isinstance(u, Expr):
            ufree = u.free_symbols
            if len(ufree) != 1:
                raise ValueError(filldedent('''
                When f(u) has more than one free symbol, the one replacing x
                must be identified: pass f(u) as (f(u), u)'''))
            uvar = ufree.pop()
        else:
            u, uvar = u
            if uvar not in u.free_symbols:
                raise ValueError(filldedent('''
                Expecting a tuple (expr, symbol) where symbol identified
                a free symbol in expr, but symbol is not in expr's free
                symbols.'''))
            if not isinstance(uvar, Symbol):
                raise ValueError(filldedent('''
                Expecting a tuple (expr, symbol) but didn't get
                a symbol; got %s''' % uvar))

        if x.is_Symbol and u.is_Symbol:
            return self.xreplace({x: u})

        if not x.is_Symbol and not u.is_Symbol:
            raise ValueError('either x or u must be a symbol')

        if uvar == xvar:
            return self.transform(x, u.subs(uvar, d)).xreplace({d: uvar})

        if uvar in self.limits:
            raise ValueError(filldedent('''
            u must contain the same variable as in x
            or a variable that is not already an integration variable'''))

        if not x.is_Symbol:
            F = [x.subs(xvar, d)]
            soln = solve(u - x, xvar, check=False)
            if not soln:
                raise ValueError('no solution for solve(F(x) - f(u), x)')
            f = [fi.subs(uvar, d) for fi in soln]
        else:
            f = [u.subs(uvar, d)]
            pdiff, reps = posify(u - x)
            puvar = uvar.subs([(v, k) for k, v in reps.items()])
            soln = [s.subs(reps) for s in solve(pdiff, puvar)]
            if not soln:
                raise ValueError('no solution for solve(F(x) - f(u), u)')
            F = [fi.subs(xvar, d) for fi in soln]

        newfuncs = set([(self.function.subs(xvar, fi)*fi.diff(d)
                        ).subs(d, uvar) for fi in f])
        if len(newfuncs) > 1:
            raise ValueError(filldedent('''
            The mapping between F(x) and f(u) did not give
            a unique integrand.'''))
        newfunc = newfuncs.pop()

        def _calc_limit_1(F, a, b):
            """
            replace d with a, using subs if possible, otherwise limit
            where sign of b is considered
            """
            wok = F.subs(d, a)
            if wok is S.NaN or wok.is_bounded is False and a.is_bounded:
                return limit(sign(b)*F, d, a)
            return wok

        def _calc_limit(a, b):
            """
            replace d with a, using subs if possible, otherwise limit
            where sign of b is considered
            """
            avals = list(set([_calc_limit_1(Fi, a, b) for Fi in F]))
            if len(avals) > 1:
                raise ValueError(filldedent('''
                The mapping between F(x) and f(u) did not
                give a unique limit.'''))
            return avals[0]

        newlimits = []
        for xab in self.limits:
            sym = xab[0]
            if sym == xvar:
                if len(xab) == 3:
                    a, b = xab[1:]
                    a, b = _calc_limit(a, b), _calc_limit(b, a)
                    if a > b:
                        a, b = b, a
                        newfunc = -newfunc
                    newlimits.append((uvar, a, b))
                elif len(xab) == 2:
                    a = _calc_limit(xab[1], 1)
                    newlimits.append((uvar, a))
                else:
                    newlimits.append(uvar)
            else:
                newlimits.append(xab)

        return self.func(newfunc, *newlimits)
Beispiel #3
0
def test_unrad():
    s = symbols('s', cls=Dummy)

    # checkers to deal with possibility of answer coming
    # back with a sign change (cf issue 2104)
    def check(rv, ans):
        rv, ans = list(rv), list(ans)
        rv[0] = rv[0].expand()
        ans[0] = ans[0].expand()
        return rv[0] in [ans[0], -ans[0]] and rv[1:] == ans[1:]

    def s_check(rv, ans):
        # get the dummy
        rv = list(rv)
        d = rv[0].atoms(Dummy)
        reps = zip(d, [s] * len(d))
        # replace s with this dummy
        rv = (rv[0].subs(reps).expand(), [
            (p[0].subs(reps), p[1].subs(reps)) for p in rv[1]
        ], [a.subs(reps) for a in rv[2]])
        ans = (ans[0].subs(reps).expand(), [
            (p[0].subs(reps), p[1].subs(reps)) for p in ans[1]
        ], [a.subs(reps) for a in ans[2]])
        return str(rv[0]) in [str(ans[0]), str(-ans[0])] and \
            str(rv[1:]) == str(ans[1:])

    assert check(unrad(sqrt(x)), (x, [], []))
    assert check(unrad(sqrt(x) + 1), (x - 1, [], []))
    assert s_check(unrad(sqrt(x) + x**Rational(1, 3) + 2),
                   (2 + s**2 + s**3, [(s, x - s**6)], []))
    assert check(unrad(sqrt(x) * x**Rational(1, 3) + 2), (x**5 - 64, [], []))
    assert check(unrad(sqrt(x) + (x + 1)**Rational(1, 3)),
                 (x**3 - (x + 1)**2, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + sqrt(2 * x)),
                 (-2 * sqrt(2) * x - 2 * x + 1, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + 2), (16 * x - 9, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + sqrt(1 - x)),
                 (-4 * x + 5 * x**2, [], []))
    assert check(unrad(a * sqrt(x) + b * sqrt(x) + c * sqrt(y) + d * sqrt(y)),
                 ((a * sqrt(x) + b * sqrt(x))**2 -
                  (c * sqrt(y) + d * sqrt(y))**2, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x)), (2 * x - 1, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) - 3),
                 (9 * x + (x - 5)**2 - 9, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x)),
                 (-5 * x**2 + 2 * x - 1, [], []))
    assert check(
        unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x) - 3),
        (-25 * x**4 - 376 * x**3 - 1256 * x**2 + 2272 * x - 784, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x) - sqrt(1 - 2 * x)),
                 (-41 * x**4 - 40 * x**3 - 232 * x**2 + 160 * x - 16, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1)), (S(1), [], []))

    eq = sqrt(x) + sqrt(x + 1) + sqrt(1 - sqrt(x))
    assert check(unrad(eq), (16 * x**3 - 9 * x**2, [], []))
    assert set(solve(eq, check=False)) == set([S(0), S(9) / 16])
    assert solve(eq) == []
    # but this one really does have those solutions
    assert set(solve(sqrt(x) - sqrt(x + 1) + sqrt(1 - sqrt(x)))) == \
        set([S.Zero, S(9)/16])
    '''NOTE
    real_root changes the value of the result if the solution is
    simplified; `a` in the text below is the root that is not 4/5:
    >>> eq
    sqrt(x) + sqrt(-x + 1) + sqrt(x + 1) - 6*sqrt(5)/5
    >>> eq.subs(x, a).n()
    -0.e-123 + 0.e-127*I
    >>> real_root(eq.subs(x, a)).n()
    -0.e-123 + 0.e-127*I
    >>> (eq.subs(x,simplify(a))).n()
    -0.e-126
    >>> real_root(eq.subs(x, simplify(a))).n()
    0.194825975605452 + 2.15093623885838*I

    >>> sqrt(x).subs(x, real_root(a)).n()
    0.809823827278194 - 0.e-25*I
    >>> sqrt(x).subs(x, (a)).n()
    0.809823827278194 - 0.e-25*I
    >>> sqrt(x).subs(x, simplify(a)).n()
    0.809823827278194 - 5.32999467690853e-25*I
    >>> sqrt(x).subs(x, real_root(simplify(a))).n()
    0.49864610868139 + 1.44572604257047*I
    '''
    eq = (sqrt(x) + sqrt(x + 1) + sqrt(1 - x) - 6 * sqrt(5) / 5)
    ra = S('''-1484/375 - 4*(-1/2 + sqrt(3)*I/2)*(-12459439/52734375 +
    114*sqrt(12657)/78125)**(1/3) - 172564/(140625*(-1/2 +
    sqrt(3)*I/2)*(-12459439/52734375 + 114*sqrt(12657)/78125)**(1/3))''')
    rb = S(4) / 5
    ans = solve(sqrt(x) + sqrt(x + 1) + sqrt(1 - x) - 6 * sqrt(5) / 5)
    assert all(abs(eq.subs(x, i).n()) < 1e-10 for i in (ra, rb)) and \
        len(ans) == 2 and \
        set([i.n(chop=True) for i in ans]) == \
        set([i.n(chop=True) for i in (ra, rb)])

    raises(ValueError,
           lambda: unrad(-root(x, 3)**2 + 2**pi * root(x, 3) - x + 2**pi))
    raises(ValueError,
           lambda: unrad(sqrt(x) + sqrt(x + 1) + sqrt(1 - sqrt(x)) + 3))
    raises(ValueError,
           lambda: unrad(sqrt(x) + (x + 1)**Rational(1, 3) + 2 * sqrt(y)))
    # same as last but consider only y
    assert check(unrad(sqrt(x) + (x + 1)**Rational(1, 3) + 2 * sqrt(y), y),
                 (4 * y - (sqrt(x) + (x + 1)**(S(1) / 3))**2, [], []))
    assert check(unrad(sqrt(x / (1 - x)) + (x + 1)**Rational(1, 3)),
                 (x**3 / (-x + 1)**3 - (x + 1)**2, [], [(-x + 1)**3]))
    # same as last but consider only y; no y-containing denominators now
    assert s_check(unrad(sqrt(x / (1 - x)) + 2 * sqrt(y), y),
                   (x / (-x + 1) - 4 * y, [], []))
    assert check(unrad(sqrt(x) * sqrt(1 - x) + 2, x),
                 (x * (-x + 1) - 4, [], []))

    # http://tutorial.math.lamar.edu/
    #        Classes/Alg/SolveRadicalEqns.aspx#Solve_Rad_Ex2_a
    assert solve(Eq(x, sqrt(x + 6))) == [3]
    assert solve(Eq(x + sqrt(x - 4), 4)) == [4]
    assert solve(Eq(1, x + sqrt(2 * x - 3))) == []
    assert set(solve(Eq(sqrt(5 * x + 6) - 2, x))) == set([-S(1), S(2)])
    assert set(solve(Eq(sqrt(2 * x - 1) - sqrt(x - 4),
                        2))) == set([S(5), S(13)])
    assert solve(Eq(sqrt(x + 7) + 2, sqrt(3 - x))) == [-6]
    # http://www.purplemath.com/modules/solverad.htm
    assert solve((2 * x - 5)**Rational(1, 3) - 3) == [16]
    assert solve((x**3 - 3 * x**2)**Rational(1, 3) + 1 - x) == []
    assert set(solve(x + 1 - (x**4 + 4*x**3 - x)**Rational(1, 4))) == \
        set([-S(1)/2, -S(1)/3])
    assert set(solve(sqrt(2 * x**2 - 7) - (3 - x))) == set([-S(8), S(2)])
    assert solve(sqrt(2 * x + 9) - sqrt(x + 1) - sqrt(x + 4)) == [0]
    assert solve(sqrt(x + 4) + sqrt(2 * x - 1) - 3 * sqrt(x - 1)) == [5]
    assert solve(sqrt(x) * sqrt(x - 7) - 12) == [16]
    assert solve(sqrt(x - 3) + sqrt(x) - 3) == [4]
    assert solve(sqrt(9 * x**2 + 4) - (3 * x + 2)) == [0]
    assert solve(sqrt(x) - 2 - 5) == [49]
    assert solve(sqrt(x - 3) - sqrt(x) - 3) == []
    assert solve(sqrt(x - 1) - x + 7) == [10]
    assert solve(sqrt(x - 2) - 5) == [27]
    assert solve(sqrt(17 * x - sqrt(x**2 - 5)) - 7) == [3]
    assert solve(sqrt(x) - sqrt(x - 1) + sqrt(sqrt(x))) == []

    # don't posify the expression in unrad and use _mexpand
    z = sqrt(2 * x + 1) / sqrt(x) - sqrt(2 + 1 / x)
    p = posify(z)[0]
    assert solve(p) == []
    assert solve(z) == []
    assert solve(z + 6 * I) == [-S(1) / 11]
    assert solve(p + 6 * I) == []

    eq = sqrt(2 + I) + 2 * I
    assert unrad(eq - x, x, all=True) == (x**4 + 4 * x**2 + 8 * x + 37, [], [])
    ans = (81 * x**8 - 2268 * x**6 - 4536 * x**5 + 22644 * x**4 +
           63216 * x**3 - 31608 * x**2 - 189648 * x + 141358, [], [])
    r = sqrt(sqrt(2) / 3 + 7)
    eq = sqrt(r) + r - x
    assert unrad(eq, all=1)
    r2 = sqrt(sqrt(2) + 21) / sqrt(3)
    assert r != r2 and r.equals(r2)
    assert unrad(eq - r + r2, all=True) == ans
Beispiel #4
0
def test_unrad():
    s = symbols('s', cls=Dummy)

    # checkers to deal with possibility of answer coming
    # back with a sign change (cf issue 2104)
    def check(rv, ans):
        rv, ans = list(rv), list(ans)
        rv[0] = rv[0].expand()
        ans[0] = ans[0].expand()
        return rv[0] in [ans[0], -ans[0]] and rv[1:] == ans[1:]

    def s_check(rv, ans):
        # get the dummy
        rv = list(rv)
        d = rv[0].atoms(Dummy)
        reps = zip(d, [s]*len(d))
        # replace s with this dummy
        rv = (rv[0].subs(reps).expand(), [(p[0].subs(reps), p[1].subs(reps))
                                   for p in rv[1]],
              [a.subs(reps) for a in rv[2]])
        ans = (ans[0].subs(reps).expand(), [(p[0].subs(reps), p[1].subs(reps))
                                   for p in ans[1]],
               [a.subs(reps) for a in ans[2]])
        return str(rv[0]) in [str(ans[0]), str(-ans[0])] and \
            str(rv[1:]) == str(ans[1:])

    assert check(unrad(sqrt(x)),
                 (x, [], []))
    assert check(unrad(sqrt(x) + 1),
                 (x - 1, [], []))
    assert s_check(unrad(sqrt(x) + x**Rational(1, 3) + 2),
                   (2 + s**2 + s**3, [(s, x - s**6)], []))
    assert check(unrad(sqrt(x)*x**Rational(1, 3) + 2),
                 (x**5 - 64, [], []))
    assert check(unrad(sqrt(x) + (x + 1)**Rational(1, 3)),
                 (x**3 - (x + 1)**2, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + sqrt(2*x)),
                (-2*sqrt(2)*x - 2*x + 1, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + 2),
               (16*x - 9, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + sqrt(1 - x)),
               (-4*x + 5*x**2, [], []))
    assert check(unrad(a*sqrt(x) + b*sqrt(x) + c*sqrt(y) + d*sqrt(y)),
                ((a*sqrt(x) + b*sqrt(x))**2 - (c*sqrt(y) + d*sqrt(y))**2, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x)),
                (2*x - 1, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) - 3),
                (36*x + (2*x - 10)**2 - 36, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x)),
                (-5*x**2 + 2*x - 1, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x) - 3),
        (-25*x**4 - 376*x**3 - 1256*x**2 + 2272*x - 784, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x) - sqrt(1 - 2*x)),
                (-41*x**4 - 40*x**3 - 232*x**2 + 160*x - 16, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1)), (S(1), [], []))

    eq = sqrt(x) + sqrt(x + 1) + sqrt(1 - sqrt(x))
    assert check(unrad(eq),
               (16*x**3 - 9*x**2, [], []))
    assert set(solve(eq, check=False)) == set([S(0), S(9)/16])
    assert solve(eq) == []
    # but this one really does have those solutions
    assert set(solve(sqrt(x) - sqrt(x + 1) + sqrt(1 - sqrt(x)))) == \
        set([S.Zero, S(9)/16])

    '''real_root changes the value of the result if the solution is
    simplified; `a` in the text below is the root that is not 4/5:
    >>> eq
    sqrt(x) + sqrt(-x + 1) + sqrt(x + 1) - 6*sqrt(5)/5
    >>> eq.subs(x, a).n()
    -0.e-123 + 0.e-127*I
    >>> real_root(eq.subs(x, a)).n()
    -0.e-123 + 0.e-127*I
    >>> (eq.subs(x,simplify(a))).n()
    -0.e-126
    >>> real_root(eq.subs(x, simplify(a))).n()
    0.194825975605452 + 2.15093623885838*I

    >>> sqrt(x).subs(x, real_root(a)).n()
    0.809823827278194 - 0.e-25*I
    >>> sqrt(x).subs(x, (a)).n()
    0.809823827278194 - 0.e-25*I
    >>> sqrt(x).subs(x, simplify(a)).n()
    0.809823827278194 - 5.32999467690853e-25*I
    >>> sqrt(x).subs(x, real_root(simplify(a))).n()
    0.49864610868139 + 1.44572604257047*I
    '''
    eq = (sqrt(x) + sqrt(x + 1) + sqrt(1 - x) - 6*sqrt(5)/5)
    ra = S('''-1484/375 - 4*(-1/2 + sqrt(3)*I/2)*(-12459439/52734375 +
    114*sqrt(12657)/78125)**(1/3) - 172564/(140625*(-1/2 +
    sqrt(3)*I/2)*(-12459439/52734375 + 114*sqrt(12657)/78125)**(1/3))''')
    rb = S(4)/5
    ans = solve(sqrt(x) + sqrt(x + 1) + sqrt(1 - x) - 6*sqrt(5)/5)
    assert all(abs(eq.subs(x, i).n()) < 1e-10 for i in (ra, rb)) and \
        len(ans) == 2 and \
        set([i.n(chop=True) for i in ans]) == \
        set([i.n(chop=True) for i in (ra, rb)])

    ans = solve(sqrt(x) + sqrt(x + 1) -
                sqrt(1 - x) - sqrt(2 + x))
    assert len(ans) == 1 and NS(ans[0])[:4] == '0.73'
    # the fence optimization problem
    # http://code.google.com/p/sympy/issues/detail?id=1694#c159
    F = Symbol('F')
    eq = F - (2*x + 2*y + sqrt(x**2 + y**2))
    X = solve(eq, x, hint='minimal')[0]
    Y = solve((x*y).subs(x, X).diff(y), y, simplify=False, minimal=True)
    ans = 2*F/7 - sqrt(2)*F/14
    assert any((a - ans).expand().is_zero for a in Y)

    raises(
        ValueError, lambda: unrad(sqrt(x) + sqrt(x + 1) + sqrt(1 - sqrt(x)) + 3))
    raises(ValueError, lambda: unrad(sqrt(x) + (x + 1)**Rational(1, 3) +
           2*sqrt(y)))
    # same as last but consider only y
    assert check(unrad(sqrt(x) + (x + 1)**Rational(1, 3) + 2*sqrt(y), y),
           (4*y - (sqrt(x) + (x + 1)**(S(1)/3))**2, [], []))
    assert check(unrad(sqrt(x/(1 - x)) + (x + 1)**Rational(1, 3)),
                (x**3/(-x + 1)**3 - (x + 1)**2, [], [(-x + 1)**3]))
    # same as last but consider only y; no y-containing denominators now
    assert s_check(unrad(sqrt(x/(1 - x)) + 2*sqrt(y), y),
           (x/(-x + 1) - 4*y, [], []))
    assert check(unrad(sqrt(x)*sqrt(1 - x) + 2, x),
           (x*(-x + 1) - 4, [], []))

    # http://tutorial.math.lamar.edu/
    #        Classes/Alg/SolveRadicalEqns.aspx#Solve_Rad_Ex2_a
    assert solve(Eq(x, sqrt(x + 6))) == [3]
    assert solve(Eq(x + sqrt(x - 4), 4)) == [4]
    assert solve(Eq(1, x + sqrt(2*x - 3))) == []
    assert set(solve(Eq(sqrt(5*x + 6) - 2, x))) == set([-S(1), S(2)])
    assert set(solve(Eq(sqrt(2*x - 1) - sqrt(x - 4), 2))) == set([S(5), S(13)])
    assert solve(Eq(sqrt(x + 7) + 2, sqrt(3 - x))) == [-6]
    # http://www.purplemath.com/modules/solverad.htm
    assert solve((2*x - 5)**Rational(1, 3) - 3) == [16]
    assert solve((x**3 - 3*x**2)**Rational(1, 3) + 1 - x) == []
    assert set(solve(x + 1 - (x**4 + 4*x**3 - x)**Rational(1, 4))) == \
        set([-S(1)/2, -S(1)/3])
    assert set(solve(sqrt(2*x**2 - 7) - (3 - x))) == set([-S(8), S(2)])
    assert solve(sqrt(2*x + 9) - sqrt(x + 1) - sqrt(x + 4)) == [0]
    assert solve(sqrt(x + 4) + sqrt(2*x - 1) - 3*sqrt(x - 1)) == [5]
    assert solve(sqrt(x)*sqrt(x - 7) - 12) == [16]
    assert solve(sqrt(x - 3) + sqrt(x) - 3) == [4]
    assert solve(sqrt(9*x**2 + 4) - (3*x + 2)) == [0]
    assert solve(sqrt(x) - 2 - 5) == [49]
    assert solve(sqrt(x - 3) - sqrt(x) - 3) == []
    assert solve(sqrt(x - 1) - x + 7) == [10]
    assert solve(sqrt(x - 2) - 5) == [27]
    assert solve(sqrt(17*x - sqrt(x**2 - 5)) - 7) == [3]
    assert solve(sqrt(x) - sqrt(x - 1) + sqrt(sqrt(x))) == []

    # don't posify the expession in unrad and use _mexpand
    z = sqrt(2*x + 1)/sqrt(x) - sqrt(2 + 1/x)
    p = posify(z)[0]
    assert solve(p) == []
    assert solve(z) == []
    assert solve(z + 6*I) == [-S(1)/11]
    assert solve(p + 6*I) == []

    eq = S('''
        -x + (1/2 - sqrt(3)*I/2)*(3*x**3/2 - x*(3*x**2 - 34)/2 + sqrt((-3*x**3
        + x*(3*x**2 - 34) + 90)**2/4 - 39304/27) - 45)**(1/3) + 34/(3*(1/2 -
        sqrt(3)*I/2)*(3*x**3/2 - x*(3*x**2 - 34)/2 + sqrt((-3*x**3 + x*(3*x**2
        - 34) + 90)**2/4 - 39304/27) - 45)**(1/3))''')
    raises(NotImplementedError, lambda: solve(eq)) # not other code errors
Beispiel #5
0
    def transform(self, x, u):
        r"""
        Performs a change of variables from `x` to `u` using the relationship
        given by `x` and `u` which will define the transformations `f` and `F`
        (which are inverses of each other) as follows:

        1) If `x` is a Symbol (which is a variable of integration) then `u`
           will be interpreted as some function, f(u), with inverse F(u).
           This, in effect, just makes the substitution of x with f(x).

        2) If `u` is a Symbol then `x` will be interpreted as some function,
           F(x), with inverse f(u). This is commonly referred to as
           u-substitution.

        Once f and F have been identified, the transformation is made as
        follows:

        .. math:: \int_a^b x \mathrm{d}x \rightarrow \int_{F(a)}^{F(b)} f(x)
                  \frac{\mathrm{d}}{\mathrm{d}x}

        where `F(x)` is the inverse of `f(x)` and the limits and integrand have
        been corrected so as to retain the same value after integration.

        Notes
        =====

        The mappings, F(x) or f(u), must lead to a unique integral. Linear
        or rational linear expression, `2*x`, `1/x` and `sqrt(x)`, will
        always work; quadratic expressions like `x**2 - 1` are acceptable
        as long as the resulting integrand does not depend on the sign of
        the solutions (see examples).

        The integral will be returned unchanged if `x` is not a variable of
        integration.

        `x` must be (or contain) only one of of the integration variables. If
        `u` has more than one free symbol then it should be sent as a tuple
        (`u`, `uvar`) where `uvar` identifies which variable is replacing
        the integration variable.
        XXX can it contain another integration variable?

        Examples
        ========

        >>> from sympy.abc import a, b, c, d, x, u, y
        >>> from sympy import Integral, S, cos, sqrt

        >>> i = Integral(x*cos(x**2 - 1), (x, 0, 1))

        transform can change the variable of integration

        >>> i.transform(x, u)
        Integral(u*cos(u**2 - 1), (u, 0, 1))

        transform can perform u-substitution as long as a unique
        integrand is obtained:

        >>> i.transform(x**2 - 1, u)
        Integral(cos(u)/2, (u, -1, 0))

        This attempt fails because x = +/-sqrt(u + 1) and the
        sign does not cancel out of the integrand:

        >>> Integral(cos(x**2 - 1), (x, 0, 1)).transform(x**2 - 1, u)
        Traceback (most recent call last):
        ...
        ValueError:
        The mapping between F(x) and f(u) did not give a unique integrand.

        transform can do a substitution. Here, the previous
        result is transformed back into the original expression
        using "u-substitution":

        >>> ui = _
        >>> _.transform(sqrt(u + 1), x) == i
        True

        We can accomplish the same with a regular substitution:

        >>> ui.transform(u, x**2 - 1) == i
        True

        If the `x` does not contain a symbol of integration then
        the integral will be returned unchanged. Integral `i` does
        not have an integration variable `a` so no change is made:

        >>> i.transform(a, x) == i
        True

        When `u` has more than one free symbol the symbol that is
        replacing `x` must be identified by passing `u` as a tuple:

        >>> Integral(x, (x, 0, 1)).transform(x, (u + a, u))
        Integral(a + u, (u, -a, -a + 1))
        >>> Integral(x, (x, 0, 1)).transform(x, (u + a, a))
        Integral(a + u, (a, -u, -u + 1))

        See Also
        ========

        variables : Lists the integration variables
        as_dummy : Replace integration variables with dummy ones
        """

        d = Dummy('d')

        xfree = x.free_symbols.intersection(self.variables)
        if len(xfree) > 1:
            raise ValueError('F(x) can only contain one of: %s' %
                             self.variables)
        xvar = xfree.pop() if xfree else d

        if xvar not in self.variables:
            return self

        u = sympify(u)
        if isinstance(u, Expr):
            ufree = u.free_symbols
            if len(ufree) != 1:
                raise ValueError(
                    filldedent('''
                When f(u) has more than one free symbol, the one replacing x
                must be identified: pass f(u) as (f(u), u)'''))
            uvar = ufree.pop()
        else:
            u, uvar = u
            if uvar not in u.free_symbols:
                raise ValueError(
                    filldedent('''
                Expecting a tuple (expr, symbol) where symbol identified
                a free symbol in expr, but symbol is not in expr's free
                symbols.'''))
            if not isinstance(uvar, Symbol):
                raise ValueError(
                    filldedent('''
                Expecting a tuple (expr, symbol) but didn't get
                a symbol; got %s''' % uvar))

        if x.is_Symbol and u.is_Symbol:
            return self.xreplace({x: u})

        if not x.is_Symbol and not u.is_Symbol:
            raise ValueError('either x or u must be a symbol')

        if uvar == xvar:
            return self.transform(x, u.subs(uvar, d)).xreplace({d: uvar})

        if uvar in self.limits:
            raise ValueError(
                filldedent('''
            u must contain the same variable as in x
            or a variable that is not already an integration variable'''))

        if not x.is_Symbol:
            F = [x.subs(xvar, d)]
            soln = solve(u - x, xvar, check=False)
            if not soln:
                raise ValueError('no solution for solve(F(x) - f(u), x)')
            f = [fi.subs(uvar, d) for fi in soln]
        else:
            f = [u.subs(uvar, d)]
            pdiff, reps = posify(u - x)
            puvar = uvar.subs([(v, k) for k, v in reps.items()])
            soln = [s.subs(reps) for s in solve(pdiff, puvar)]
            if not soln:
                raise ValueError('no solution for solve(F(x) - f(u), u)')
            F = [fi.subs(xvar, d) for fi in soln]

        newfuncs = set([
            (self.function.subs(xvar, fi) * fi.diff(d)).subs(d, uvar)
            for fi in f
        ])
        if len(newfuncs) > 1:
            raise ValueError(
                filldedent('''
            The mapping between F(x) and f(u) did not give
            a unique integrand.'''))
        newfunc = newfuncs.pop()

        def _calc_limit_1(F, a, b):
            """
            replace d with a, using subs if possible, otherwise limit
            where sign of b is considered
            """
            wok = F.subs(d, a)
            if wok is S.NaN or wok.is_bounded is False and a.is_bounded:
                return limit(sign(b) * F, d, a)
            return wok

        def _calc_limit(a, b):
            """
            replace d with a, using subs if possible, otherwise limit
            where sign of b is considered
            """
            avals = list(set([_calc_limit_1(Fi, a, b) for Fi in F]))
            if len(avals) > 1:
                raise ValueError(
                    filldedent('''
                The mapping between F(x) and f(u) did not
                give a unique limit.'''))
            return avals[0]

        newlimits = []
        for xab in self.limits:
            sym = xab[0]
            if sym == xvar:
                if len(xab) == 3:
                    a, b = xab[1:]
                    a, b = _calc_limit(a, b), _calc_limit(b, a)
                    if a > b:
                        a, b = b, a
                        newfunc = -newfunc
                    newlimits.append((uvar, a, b))
                elif len(xab) == 2:
                    a = _calc_limit(xab[1], 1)
                    newlimits.append((uvar, a))
                else:
                    newlimits.append(uvar)
            else:
                newlimits.append(xab)

        return self.func(newfunc, *newlimits)
Beispiel #6
0
def test_unrad():
    s = symbols('s', cls=Dummy)

    # checkers to deal with possibility of answer coming
    # back with a sign change (cf issue 2104)
    def check(rv, ans):
        rv, ans = list(rv), list(ans)
        rv[0] = rv[0].expand()
        ans[0] = ans[0].expand()
        return rv[0] in [ans[0], -ans[0]] and rv[1:] == ans[1:]

    def s_check(rv, ans):
        # get the dummy
        rv = list(rv)
        d = rv[0].atoms(Dummy)
        reps = zip(d, [s] * len(d))
        # replace s with this dummy
        rv = (rv[0].subs(reps).expand(), [
            (p[0].subs(reps), p[1].subs(reps)) for p in rv[1]
        ], [a.subs(reps) for a in rv[2]])
        ans = (ans[0].subs(reps).expand(), [
            (p[0].subs(reps), p[1].subs(reps)) for p in ans[1]
        ], [a.subs(reps) for a in ans[2]])
        return str(rv[0]) in [str(ans[0]), str(-ans[0])] and \
               str(rv[1:]) == str(ans[1:])

    assert check(unrad(sqrt(x)), (x, [], []))
    assert check(unrad(sqrt(x) + 1), (x - 1, [], []))
    assert s_check(unrad(sqrt(x) + x**Rational(1, 3) + 2),
                   (2 + s**2 + s**3, [(s, x - s**6)], []))
    assert check(unrad(sqrt(x) * x**Rational(1, 3) + 2), (x**5 - 64, [], []))
    assert check(unrad(sqrt(x) + (x + 1)**Rational(1, 3)),
                 (x**3 - (x + 1)**2, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + sqrt(2 * x)),
                 (-2 * sqrt(2) * x - 2 * x + 1, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + 2), (16 * x - 9, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1) + sqrt(1 - x)),
                 (-4 * x + 5 * x**2, [], []))
    assert check(unrad(a * sqrt(x) + b * sqrt(x) + c * sqrt(y) + d * sqrt(y)),
                 ((a * sqrt(x) + b * sqrt(x))**2 -
                  (c * sqrt(y) + d * sqrt(y))**2, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x)), (2 * x - 1, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) - 3),
                 (36 * x + (2 * x - 10)**2 - 36, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x)),
                 (-5 * x**2 + 2 * x - 1, [], []))
    assert check(
        unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x) - 3),
        (-25 * x**4 - 376 * x**3 - 1256 * x**2 + 2272 * x - 784, [], []))
    assert check(unrad(sqrt(x) + sqrt(1 - x) + sqrt(2 + x) - sqrt(1 - 2 * x)),
                 (-41 * x**4 - 40 * x**3 - 232 * x**2 + 160 * x - 16, [], []))
    assert check(unrad(sqrt(x) + sqrt(x + 1)), (S(1), [], []))

    eq = sqrt(x) + sqrt(x + 1) + sqrt(1 - sqrt(x))
    assert check(unrad(eq), (16 * x**3 - 9 * x**2, [], []))
    assert solve(eq, check=False) == [0, S(9) / 16]
    assert solve(eq) == []
    # but this one really does have those solutions
    assert solve(sqrt(x) - sqrt(x + 1) + sqrt(1 - sqrt(x))) == [0, S(9) / 16]
    '''real_root changes the value of the result if the solution is
    simplified; `a` in the text below is the root that is not 4/5:
    >>> eq
    sqrt(x) + sqrt(-x + 1) + sqrt(x + 1) - 6*sqrt(5)/5
    >>> eq.subs(x, a).n()
    -0.e-123 + 0.e-127*I
    >>> real_root(eq.subs(x, a)).n()
    -0.e-123 + 0.e-127*I
    >>> (eq.subs(x,simplify(a))).n()
    -0.e-126
    >>> real_root(eq.subs(x, simplify(a))).n()
    0.194825975605452 + 2.15093623885838*I

    >>> sqrt(x).subs(x, real_root(a)).n()
    0.809823827278194 - 0.e-25*I
    >>> sqrt(x).subs(x, (a)).n()
    0.809823827278194 - 0.e-25*I
    >>> sqrt(x).subs(x, simplify(a)).n()
    0.809823827278194 - 5.32999467690853e-25*I
    >>> sqrt(x).subs(x, real_root(simplify(a))).n()
    0.49864610868139 + 1.44572604257047*I
    '''
    eq = (sqrt(x) + sqrt(x + 1) + sqrt(1 - x) - 6 * sqrt(5) / 5)
    ra = S('''-1484/375 - 4*(-1/2 + sqrt(3)*I/2)*(-12459439/52734375 +
    114*sqrt(12657)/78125)**(1/3) - 172564/(140625*(-1/2 +
    sqrt(3)*I/2)*(-12459439/52734375 + 114*sqrt(12657)/78125)**(1/3))''')
    rb = S(4) / 5
    ans = solve(sqrt(x) + sqrt(x + 1) + sqrt(1 - x) - 6 * sqrt(5) / 5)
    assert all(abs(eq.subs(x, i).n()) < 1e-10 for i in (ra, rb)) and \
        len(ans) == 2 and \
        sorted([i.n(chop=True) for i in ans]) == \
        sorted([i.n(chop=True) for i in (ra, rb)])

    ans = solve(sqrt(x) + sqrt(x + 1) - \
                 sqrt(1 - x) - sqrt(2 + x))
    assert len(ans) == 1 and NS(ans[0])[:4] == '0.73'
    # the fence optimization problem
    # http://code.google.com/p/sympy/issues/detail?id=1694#c159
    F = Symbol('F')
    eq = F - (2 * x + 2 * y + sqrt(x**2 + y**2))
    X = solve(eq, x, hint='minimal')[0]
    Y = solve((x * y).subs(x, X).diff(y), y, simplify=False, minimal=True)
    ans = 2 * F / 7 - sqrt(2) * F / 14
    assert any((a - ans).expand().is_zero for a in Y)

    raises(ValueError,
           lambda: unrad(sqrt(x) + sqrt(x + 1) + sqrt(1 - sqrt(x)) + 3))
    raises(ValueError,
           lambda: unrad(sqrt(x) + (x + 1)**Rational(1, 3) + 2 * sqrt(y)))
    # same as last but consider only y
    assert check(unrad(sqrt(x) + (x + 1)**Rational(1, 3) + 2 * sqrt(y), y),
                 (4 * y - (sqrt(x) + (x + 1)**(S(1) / 3))**2, [], []))
    assert check(unrad(sqrt(x / (1 - x)) + (x + 1)**Rational(1, 3)),
                 (x**3 / (-x + 1)**3 - (x + 1)**2, [], [(-x + 1)**3]))
    # same as last but consider only y; no y-containing denominators now
    assert s_check(unrad(sqrt(x / (1 - x)) + 2 * sqrt(y), y),
                   (x / (-x + 1) - 4 * y, [], []))
    assert check(unrad(sqrt(x) * sqrt(1 - x) + 2, x),
                 (x * (-x + 1) - 4, [], []))

    # http://tutorial.math.lamar.edu/
    #        Classes/Alg/SolveRadicalEqns.aspx#Solve_Rad_Ex2_a
    assert solve(Eq(x, sqrt(x + 6))) == [3]
    assert solve(Eq(x + sqrt(x - 4), 4)) == [4]
    assert solve(Eq(1, x + sqrt(2 * x - 3))) == []
    assert solve(Eq(sqrt(5 * x + 6) - 2, x)) == [-1, 2]
    assert solve(Eq(sqrt(2 * x - 1) - sqrt(x - 4), 2)) == [5, 13]
    assert solve(Eq(sqrt(x + 7) + 2, sqrt(3 - x))) == [-6]
    # http://www.purplemath.com/modules/solverad.htm
    assert solve((2 * x - 5)**Rational(1, 3) - 3) == [16]
    assert solve((x**3 - 3 * x**2)**Rational(1, 3) + 1 - x) == []
    assert solve(x + 1 - (x**4 + 4*x**3 - x)**Rational(1, 4)) == \
        [-S(1)/2, -S(1)/3]
    assert solve(sqrt(2 * x**2 - 7) - (3 - x)) == [-8, 2]
    assert solve(sqrt(2 * x + 9) - sqrt(x + 1) - sqrt(x + 4)) == [0]
    assert solve(sqrt(x + 4) + sqrt(2 * x - 1) - 3 * sqrt(x - 1)) == [5]
    assert solve(sqrt(x) * sqrt(x - 7) - 12) == [16]
    assert solve(sqrt(x - 3) + sqrt(x) - 3) == [4]
    assert solve(sqrt(9 * x**2 + 4) - (3 * x + 2)) == [0]
    assert solve(sqrt(x) - 2 - 5) == [49]
    assert solve(sqrt(x - 3) - sqrt(x) - 3) == []
    assert solve(sqrt(x - 1) - x + 7) == [10]
    assert solve(sqrt(x - 2) - 5) == [27]
    assert solve(sqrt(17 * x - sqrt(x**2 - 5)) - 7) == [3]
    assert solve(sqrt(x) - sqrt(x - 1) + sqrt(sqrt(x))) == []

    # don't posify the expession in unrad and use _mexpand
    z = sqrt(2 * x + 1) / sqrt(x) - sqrt(2 + 1 / x)
    p = posify(z)[0]
    assert solve(p) == []
    assert solve(z) == []
    assert solve(z + 6 * I) == [-S(1) / 11]
    assert solve(p + 6 * I) == []