From: Fabian Seoane <[EMAIL PROTECTED]> Also fixes a docstring that caused test_doc to fail and some formatting typos where corrected --- sympy/solvers/solvers.py | 167 ++++++++++++++++++----------------- sympy/solvers/tests/test_solvers.py | 27 +++--- 2 files changed, 97 insertions(+), 97 deletions(-)
diff --git a/sympy/solvers/solvers.py b/sympy/solvers/solvers.py index dfe7d1f..5f1d5aa 100644 --- a/sympy/solvers/solvers.py +++ b/sympy/solvers/solvers.py @@ -53,6 +53,8 @@ def guess_solve_strategy(expr, symbol): Examples ======== + >>> from sympy import Symbol, Rational + >>> x = Symbol('x') >>> guess_solve_strategy(x**2 + 1, x) 0 >>> guess_solve_strategy(x**Rational(1,2) + 1, x) @@ -160,89 +162,88 @@ def solve(f, *symbols, **flags): if isinstance(f, Equality): f = f.lhs - f.rhs - if len(symbols) == 1: - symbol = symbols[0] - - strategy = guess_solve_strategy(f, symbol) - - if strategy == GS_POLY: - poly = f.as_poly( symbol ) - assert poly is not None - result = roots(poly, cubics=True, quartics=True).keys() - - elif strategy == GS_RATIONAL: - P, Q = f.as_numer_denom() - #TODO: check for Q != 0 - return solve(P, symbol, **flags) - - elif strategy == GS_POLY_CV_1: - # we must search for a suitable change of variable - # collect exponents - exponents_denom = list() - args = list(f.args) - if isinstance(f, Add): - for arg in args: - if isinstance(arg, Pow): - exponents_denom.append(arg.exp.q) - elif isinstance(arg, Mul): - for mul_arg in arg.args: - if isinstance(mul_arg, Pow): - exponents_denom.append(mul_arg.exp.q) - elif isinstance(f, Mul): - for mul_arg in args: - if isinstance(mul_arg, Pow): - exponents_denom.append(mul_arg.exp.q) - - assert len(exponents_denom) > 0 - if len(exponents_denom) == 1: - m = exponents_denom[0] - else: - # get the GCD of the denominators - m = ilcm(*exponents_denom) - # x -> y**m. - # we assume positive for simplification purposes - t = Symbol('t', positive=True, dummy=True) - f_ = f.subs(symbol, t**m) - if guess_solve_strategy(f_, t) != GS_POLY: - raise TypeError("Could not convert to a polynomial equation: %s" % f_) - cv_sols = solve(f_, t) - result = list() - for sol in cv_sols: - result.append(sol**(S.One/m)) - - elif strategy == GS_POLY_CV_2: - m = 0 - args = list(f.args) - if isinstance(f, Add): - for arg in args: - if isinstance(arg, Pow): - m = min(m, arg.exp) - elif isinstance(arg, Mul): - for mul_arg in arg.args: - if isinstance(mul_arg, Pow): - m = min(m, mul_arg.exp) - elif isinstance(f, Mul): - for mul_arg in args: - if isinstance(mul_arg, Pow): - m = min(m, mul_arg.exp) - f1 = simplify(f*symbol**(-m)) - result = solve(f1, symbol) - # TODO: we might have introduced unwanted solutions - # when multiplied by x**-m - - elif strategy == GS_TRASCENDENTAL: - #a, b = f.as_numer_denom() - # Let's throw away the denominator for now. When we have robust - # assumptions, it should be checked, that for the solution, - # b!=0. - result = tsolve(f, *symbols) - elif strategy == -1: - raise Exception('Could not parse expression %s' % f) + if len(symbols) != 1: + raise NotImplementedError('Support for multivariate equation is not implemented') + + symbol = symbols[0] + + strategy = guess_solve_strategy(f, symbol) + + if strategy == GS_POLY: + poly = f.as_poly( symbol ) + assert poly is not None + result = roots(poly, cubics=True, quartics=True).keys() + + elif strategy == GS_RATIONAL: + P, Q = f.as_numer_denom() + #TODO: check for Q != 0 + return solve(P, symbol, **flags) + + elif strategy == GS_POLY_CV_1: + # we must search for a suitable change of variable + # collect exponents + exponents_denom = list() + args = list(f.args) + if isinstance(f, Add): + for arg in args: + if isinstance(arg, Pow): + exponents_denom.append(arg.exp.q) + elif isinstance(arg, Mul): + for mul_arg in arg.args: + if isinstance(mul_arg, Pow): + exponents_denom.append(mul_arg.exp.q) + elif isinstance(f, Mul): + for mul_arg in args: + if isinstance(mul_arg, Pow): + exponents_denom.append(mul_arg.exp.q) + + assert len(exponents_denom) > 0 + if len(exponents_denom) == 1: + m = exponents_denom[0] else: - raise NotImplementedError("No algorithms where implemented to solve equation %s" % f) + # get the GCD of the denominators + m = ilcm(*exponents_denom) + # x -> y**m. + # we assume positive for simplification purposes + t = Symbol('t', positive=True, dummy=True) + f_ = f.subs(symbol, t**m) + if guess_solve_strategy(f_, t) != GS_POLY: + raise TypeError("Could not convert to a polynomial equation: %s" % f_) + cv_sols = solve(f_, t) + result = list() + for sol in cv_sols: + result.append(sol**(S.One/m)) + + elif strategy == GS_POLY_CV_2: + m = 0 + args = list(f.args) + if isinstance(f, Add): + for arg in args: + if isinstance(arg, Pow): + m = min(m, arg.exp) + elif isinstance(arg, Mul): + for mul_arg in arg.args: + if isinstance(mul_arg, Pow): + m = min(m, mul_arg.exp) + elif isinstance(f, Mul): + for mul_arg in args: + if isinstance(mul_arg, Pow): + m = min(m, mul_arg.exp) + f1 = simplify(f*symbol**(-m)) + result = solve(f1, symbol) + # TODO: we might have introduced unwanted solutions + # when multiplied by x**-m + + elif strategy == GS_TRASCENDENTAL: + #a, b = f.as_numer_denom() + # Let's throw away the denominator for now. When we have robust + # assumptions, it should be checked, that for the solution, + # b!=0. + result = tsolve(f, *symbols) + elif strategy == -1: + raise Exception('Could not parse expression %s' % f) else: - #TODO: if we do it the other way round we can avoid one nesting - raise NotImplementedError('multivariate equation') + raise NotImplementedError("No algorithms where implemented to solve equation %s" % f) if flags.get('simplified', True): return map(simplify, result) @@ -684,10 +685,10 @@ def tsolve(eq, sym): >>> x = Symbol('x') >>> tsolve(3**(2*x+5)-4, x) - (-5*log(3) + log(4))/(2*log(3)) + [(-5*log(3) + log(4))/(2*log(3))] >>> tsolve(log(x) + 2*x, x) - 1/2*LambertW(2) + [1/2*LambertW(2)] """ if patterns is None: diff --git a/sympy/solvers/tests/test_solvers.py b/sympy/solvers/tests/test_solvers.py index a15dd21..b5c09e8 100644 --- a/sympy/solvers/tests/test_solvers.py +++ b/sympy/solvers/tests/test_solvers.py @@ -29,7 +29,7 @@ def test_guess_strategy(): # polynomial equations via a change of variable assert guess_solve_strategy( x**Rational(1,2) + 1, x ) == GS_POLY_CV_1 assert guess_solve_strategy( x**Rational(1,3) + x**Rational(1,2) + 1, x ) == GS_POLY_CV_1 - + # polynomial equation multiplying both sides by x**n assert guess_solve_strategy( x + 1/x + y, x ) @@ -58,8 +58,8 @@ def test_solve_polynomial(): assert solve( x - y**3, x) == [y**3] assert solve( x - y**3, y) == [ - (-x**Rational(1,3))/2 + I*sqrt(3)*x**Rational(1,3)/2, - x**Rational(1,3), + (-x**Rational(1,3))/2 + I*sqrt(3)*x**Rational(1,3)/2, + x**Rational(1,3), (-x**Rational(1,3))/2 - I*sqrt(3)*x**Rational(1,3)/2 ] @@ -75,8 +75,8 @@ def test_solve_polynomial(): assert solve((x-y, x+y), (x, y)) == solution assert solve((x-y, x+y), [x, y]) == solution - assert solve( x**3 - 15*x - 4, x) == [-2 + 3**Rational(1,2), - 4, + assert solve( x**3 - 15*x - 4, x) == [-2 + 3**Rational(1,2), + 4, -2 - 3**Rational(1,2) ] raises(TypeError, "solve(x**2-pi, pi)") @@ -87,28 +87,27 @@ def test_solve_polynomial_cv_1(): Test for solving on equations that can be converted to a polynomial equation using the change of variable y -> x**Rational(p, q) """ - + x = Symbol('x') assert solve( x**Rational(1,2) - 1, x) == [1] assert solve( x**Rational(1,2) - 2, x) == [sqrt(2)] - + def test_solve_polynomial_cv_2(): """ Test for solving on equations that can be converted to a polynomial equation multiplying both sides of the equation by x**m """ - + x = Symbol('x') - + assert solve( x + 1/x - 1, x) == [Rational(1,2) + I*sqrt(3)/2, Rational(1,2) - I*sqrt(3)/2] - + def test_solve_rational(): x = Symbol('x') y = Symbol('y') - + solve( ( x - y**3 )/( (y**2)*sqrt(1 - y**2) ), x) == [x**Rational(1,3)] - def test_linear_system(): x, y, z, t, n = map(Symbol, 'xyztn') @@ -181,7 +180,7 @@ def test_tsolve(): assert solve(cos(x)-y, x) == [acos(y)] assert solve(2*cos(x)-y,x)== [acos(y/2)] # XXX in the following test, log(2*y + 2*...) should -> log(2) + log(y +...) - assert solve(exp(x)+exp(-x)-y,x) == [-log(4) + log(2*y + 2*(-4 + y**2)**Rational(1,2)), + assert solve(exp(x)+exp(-x)-y,x) == [-log(4) + log(2*y + 2*(-4 + y**2)**Rational(1,2)), -log(4) + log(2*y - 2*(-4 + y**2)**Rational(1,2))] assert tsolve(exp(x)-3, x) == [log(3)] assert tsolve(Eq(exp(x), 3), x) == [log(3)] @@ -213,5 +212,5 @@ def test_tsolve(): assert tsolve(z*cos(x), x) == [acos(0)] - assert tsolve(exp(x)+exp(-x)-y, x)== [log(y/2 + Rational(1,2)*(-4 + y**2)**Rational(1,2)), + assert tsolve(exp(x)+exp(-x)-y, x)== [log(y/2 + Rational(1,2)*(-4 + y**2)**Rational(1,2)), log(y/2 - Rational(1,2)*(-4 + y**2)**Rational(1,2))] -- 1.6.0.2 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sympy-patches" group. To post to this group, send email to sympy-patches@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sympy-patches?hl=en -~----------~----~----~----~------~----~------~--~---