Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" This module contains functions to solve a single equation for a single variable. """
arg, Piecewise, piecewise_fold) HyperbolicFunction) RootOf)
""" Inverts a real valued function
Reduces the real valued equation ``f(x) = y`` to a set of equations ``{g(x) = h_1(y), g(x) = h_2(y), ..., g(x) = h_n(y) }`` where ``g(x)`` is a simpler function than ``f(x)``. The return value is a tuple ``(g(x), set_h)``, where ``g(x)`` is a function of ``x`` and ``set_h`` is the set of functions ``{h_1(y), h_2(y), ..., h_n(y)}``. Here, ``y`` is not necessarily a symbol.
Examples ========
>>> from sympy.solvers.solveset import invert_real >>> from sympy import tan, Abs, exp >>> from sympy.abc import x, y, n >>> invert_real(exp(Abs(x)), y, x) (x, {-log(y), log(y)}) >>> invert_real(exp(x), 1, x) (x, {0}) >>> invert_real(Abs(x**31 + x), y, x) (x**31 + x, {-y, y}) >>> invert_real(tan(x), y, x) (x, ImageSet(Lambda(_n, _n*pi + atan(y)), Integers()))
See Also ======== invert_complex """ else:
""" Helper function for invert_real """
raise ValueError("Only functions with one argument are supported.") imageset(Lambda(n, f.inverse()(n)), g_ys), symbol)
Union(g_ys, imageset(Lambda(n, -n), g_ys)), symbol)
# f = g + h
# f = g*h
else: else: else: "defined for negative x")
g_ys), symbol)
S.Integers) for g_y in g_ys])
""" Inverts a complex valued function.
Reduces the complex valued equation ``f(x) = y`` to a set of equations ``{g(x) = h_1(y), g(x) = h_2(y), ..., g(x) = h_n(y) }`` where ``g(x)`` is a simpler function than ``f(x)``. The return value is a tuple ``(g(x), set_h)``, where ``g(x)`` is a function of ``x`` and ``set_h`` is the set of function ``{h_1(y), h_2(y), ..., h_n(y)}``. Here, ``y`` is not necessarily a symbol.
Note that `invert\_complex` and `invert\_real` don't always produce the same result even for a seemingly simple function like ``exp(x)`` because the complex extension of real valued ``log`` is multivariate in the complex system and has infinitely many branches. If you are working with real values only or you are not sure with function to use you should use `invert\_real`.
Examples ========
>>> from sympy.solvers.solveset import invert_complex >>> from sympy.abc import x, y >>> from sympy import exp, log >>> invert_complex(log(x), y, x) (x, {exp(y)}) >>> invert_complex(log(x), 0, x) # Second parameter is not a symbol (x, {1}) >>> invert_complex(exp(x), y, x) (x, ImageSet(Lambda(_n, I*(2*_n*pi + arg(y)) + log(Abs(y))), Integers()))
See Also ======== invert_real """ else:
""" Helper function for invert_complex """
raise ValueError("Inverse of constant function doesn't exist")
# f = g + h
# f = g*h
not isinstance(f, TrigonometricFunction) and \ not isinstance(f, exp): raise ValueError("Only functions with one argument are supported.") imageset(Lambda(n, f.inverse()(n)), g_ys), symbol)
log(Abs(g_y))), S.Integers) for g_y in g_ys])
"""Returns False if point p is infinite or any subexpression of f is infinite or becomes so after replacing symbol with p. If none of these conditions is met then True will be returned.
Examples ========
>>> from sympy import Mul, oo >>> from sympy.abc import x >>> from sympy.solvers.solveset import domain_check >>> g = 1/(1 + (1/(x + 1))**2) >>> domain_check(g, x, -1) False >>> domain_check(x**2, x, 0) True >>> domain_check(1/x, x, oo) False
* The function relies on the assumption that the original form of the equation has not been changed by automatic simplification.
>>> domain_check(x/x, x, 0) # x/x is automatically simplified to 1 True
* To deal with automatic evaluations use evaluate=False:
>>> domain_check(Mul(x, 1/x, evaluate=False), x, 0) False """
# helper for domain check else: for g in f.args])
""" Return True if the given expression is finite when all free symbols (that are not already specified as finite) are made finite. """ for s in f.free_symbols if s.is_finite is None])
""" Tests whether the equation is an equation of the given function class.
The given equation belongs to the given function class if it is comprised of functions of the function class which are multiplied by or added to expressions independent of the symbol. In addition, the arguments of all such functions must be linear in the symbol as well.
Examples ========
>>> from sympy.solvers.solveset import _is_function_class_equation >>> from sympy import tan, sin, tanh, sinh, exp >>> from sympy.abc import x >>> from sympy.functions.elementary.trigonometric import (TrigonometricFunction, ... HyperbolicFunction) >>> _is_function_class_equation(TrigonometricFunction, exp(x) + tan(x), x) False >>> _is_function_class_equation(TrigonometricFunction, tan(x) + sin(x), x) True >>> _is_function_class_equation(TrigonometricFunction, tan(x**2), x) False >>> _is_function_class_equation(TrigonometricFunction, tan(x + 2), x) True >>> _is_function_class_equation(HyperbolicFunction, tanh(x) + sinh(x), x) True """ for arg in f.args)
else:
else:
""" Solves a real valued equation.
Parameters ==========
f : Expr The target equation symbol : Symbol The variable for which the equation is solved
Returns =======
Set A set of values for `symbol` for which `f` is equal to zero. An `EmptySet` is returned if no solution is found.
`solveset_real` claims to be complete in the set of the solution it returns.
Raises ======
NotImplementedError The algorithms for to find the solution of the given equation are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report to the github issue tracker.
See Also =======
solveset_complex : solver for complex domain
Examples ========
>>> from sympy import Symbol, exp, sin, sqrt, I >>> from sympy.solvers.solveset import solveset_real >>> x = Symbol('x', real=True) >>> a = Symbol('a', real=True, finite=True, positive=True) >>> solveset_real(x**2 - 1, x) {-1, 1} >>> solveset_real(sqrt(5*x + 6) - 2 - x, x) {-1, 2} >>> solveset_real(x - I, x) EmptySet() >>> solveset_real(x - a, x) {a} >>> solveset_real(exp(x) - a, x) {log(a)}
* In case the equation has infinitely many solutions an infinitely indexed `ImageSet` is returned.
>>> solveset_real(sin(x) - 1, x) ImageSet(Lambda(_n, 2*_n*pi + pi/2), Integers())
* If the equation is true for any arbitrary value of the symbol a `S.Reals` set is returned.
>>> solveset_real(x - x, x) (-oo, oo)
"""
# if f(x) and g(x) are both finite we can say that the solution of # f(x)*g(x) == 0 is same as Union(f(x) == 0, g(x) == 0) is not true in # general. g(x) can grow to infinitely large for the values where # f(x) == 0. To be sure that we not are silently allowing any # wrong solutions we are using this technique only if both f and g and # finite for a finite input. _is_function_class_equation(HyperbolicFunction, f, symbol): else: for g in equation.args): symbol, solveset_real) else: solveset_solver=solveset_real, as_poly_solver=_solve_as_poly_real) else: else: raise NotImplementedError
if isinstance(s, RootOf) or domain_check(original_eq, symbol, s)] else:
""" solve rational functions""" else:
""" Helper to solve trigonometric equations """ raise NotImplementedError
for s in solns]) else: raise NotImplementedError
""" Solve the equation using polynomial techniques if it already is a polynomial equation or, with a change of variables, can be made so. """
quintics=True, domain='EX') else: else: raise NotImplementedError("Couldn't find all roots " "of the equation %s" % f) else: raise NotImplementedError("Could not convert %s to Poly" % f)
quintics=True).keys())
raise NotImplementedError("Couldn't find all the roots of " "the equation %s" % f)
else: raise NotImplementedError( "inversion of %s not handled" % gen) else: raise NotImplementedError("multiple generators not handled" " by solveset")
# this is to simplify solutions like -sqrt(-I) to sqrt(2)/2 # - sqrt(2)*I/2. We are not expanding for solution with free # variables because that makes the solution more complicated. For # example expand_complex(a) returns re(a) + I*im(a) for s in result]): else: raise NotImplementedError
""" Solve real valued equation with methods to solve polynomial equations. """ solveset_solver=solveset_real, invert_func=invert_real)
""" Solve complex valued equation with methods to solve polynomial equations. """ solveset_solver=solveset_complex, invert_func=invert_complex)
""" Returns (bool, den) where bool is True if the term has a non-integer rational power and den is the denominator of the expression's exponent.
Examples ========
>>> from sympy.solvers.solveset import _has_rational_power >>> from sympy import sqrt >>> from sympy.abc import x >>> _has_rational_power(sqrt(x), x) (True, 2) >>> _has_rational_power(x**2, x) (False, 1) """ return (False, S.One) and pattern_match[p].has(symbol):
or isinstance(pattern_match[a], Mul): else:
""" Helper function to solve equations with radicals """ Union(*[solveset_solver(g, symbol) for g in denoms(f, [symbol])]) else: for g_y in g_y_s])
""" Helper function to solve equation involving absolute value function """ relational=False) relational=False)
symbol).intersect(q_pos_cond) symbol).intersect(q_neg_cond) else: raise NotImplementedError
""" Solve a complex valued equation.
Parameters ==========
f : Expr The target equation symbol : Symbol The variable for which the equation is solved
Returns =======
Set A set of values for `symbol` for which `f` equal to zero. An `EmptySet` is returned if no solution is found.
`solveset_complex` claims to be complete in the solution set that it returns.
Raises ======
NotImplementedError The algorithms for to find the solution of the given equation are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report to the github issue tracker.
See Also ========
solveset_real: solver for real domain
Examples ========
>>> from sympy import Symbol, exp >>> from sympy.solvers.solveset import solveset_complex >>> from sympy.abc import x, a, b, c >>> solveset_complex(a*x**2 + b*x +c, x) {-b/(2*a) - sqrt(-4*a*c + b**2)/(2*a), -b/(2*a) + sqrt(-4*a*c + b**2)/(2*a)}
* Due to the fact that complex extension of my real valued functions are multivariate even some simple equations can have infinitely many solution.
>>> solveset_complex(exp(x) - 1, x) ImageSet(Lambda(_n, 2*_n*I*pi), Integers())
"""
# Without this equations like a + 4*x**2 - E keep oscillating # into form a/4 + x**2 - E/4 and (a + 4*x**2 - E)/4
raise NotImplementedError("S.Complex set is not yet implemented") else: for g in equation.args): symbol, solveset_complex) else: solveset_solver=solveset_complex, as_poly_solver=_solve_as_poly_complex) else: else: raise NotImplementedError
if isinstance(s, RootOf) or domain_check(original_eq, symbol, s)] else:
"""Solves a given inequality or equation with set as output
Parameters ==========
f : Expr or a relational. The target equation or inequality symbol : Symbol The variable for which the equation is solved
Returns =======
Set A set of values for `symbol` for which `f` is True or is equal to zero. An `EmptySet` is returned if no solution is found.
`solveset` claims to be complete in the solution set that it returns.
Raises ======
NotImplementedError The algorithms for to find the solution of the given equation are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report to the github issue tracker.
`solveset` uses two underlying functions `solveset_real` and `solveset_complex` to solve equations. They are the solvers for real and complex domain respectively. The domain of the solver is decided by the assumption on the variable for which the equation is being solved.
See Also ========
solveset_real: solver for real domain solveset_complex: solver for complex domain
Examples ========
>>> from sympy import exp, Symbol, Eq, pprint >>> from sympy.solvers.solveset import solveset >>> from sympy.abc import x
* Symbols in Sympy are complex by default. A complex variable will lead to the solving of the equation in complex domain.
>>> pprint(solveset(exp(x) - 1, x), use_unicode=False) {2*n*I*pi | n in Integers()}
* If you want to solve equation in real domain by the `solveset` interface, then specify the variable to real. Alternatively use `solveset\_real`.
>>> x = Symbol('x', real=True) >>> solveset(exp(x) - 1, x) {0} >>> solveset(Eq(exp(x), 1), x) {0}
* Inequalities are always solved in the real domain irrespective of the assumption on the variable for which the inequality is solved.
>>> solveset(exp(x) > 1, x) (0, oo)
"""
else: The independent variable must be specified for a multivariate equation.''')) raise ValueError('A Symbol must be given, not type %s: %s' % (type(symbol), symbol))
warnings.warn(filldedent(''' The variable you are solving for is complex but will assumed to be real since solving complex inequalities is not supported. '''))
else:
############################################################################### ################################ LINSOLVE ##################################### ###############################################################################
r""" Converts a given System of Equations into Matrix form. Here `equations` must be a linear system of equations in `symbols`. The order of symbols in input `symbols` will determine the order of coefficients in the returned Matrix.
The Matrix form corresponds to the augmented matrix form. For example:
4.x + 2.y + 3.z = 1 3.x + y + z = -6 2.x + 4.y + 9.z = 2
This system would return A & b as given below:
[ 4 2 3 ] [ 1 ] [ 3 1 1 ] [-6 ] [ 2 4 9 ] [ 2 ]
Examples ========
>>> from sympy.solvers.solveset import linear_eq_to_matrix >>> from sympy import symbols >>> x, y, z = symbols('x, y, z')
>>> eqns = [x + 2*y + 3*z - 1, 3*x + y + z + 6, 2*x + 4*y + 9*z - 2] >>> A, b = linear_eq_to_matrix(eqns, [x, y, z]) >>> A Matrix([ [1, 2, 3], [3, 1, 1], [2, 4, 9]]) >>> b Matrix([ [ 1], [-6], [ 2]])
>>> eqns = [x + z - 1, y + z, x - y] >>> A, b = linear_eq_to_matrix(eqns, [x, y, z]) >>> A Matrix([ [1, 0, 1], [0, 1, 1], [1, -1, 0]]) >>> b Matrix([ [1], [0], [0]])
* Symbolic coefficients are also supported
>>> a, b, c, d, e, f = symbols('a, b, c, d, e, f') >>> eqns = [a*x + b*y - c, d*x + e*y - f] >>> A, B = linear_eq_to_matrix(eqns, x, y) >>> A Matrix([ [a, b], [d, e]]) >>> B Matrix([ [c], [f]])
"""
are to be found.')
# initialise Matrix with symbols + 1 columns
# Extract coeff of symbols
# append constant term (term free from symbols)
# insert equations coeff's into rows
# delete the initialised (Ist) trivial row
r""" Solve system of N linear equations with M variables, which means both under - and overdetermined systems are supported. The possible number of solutions is zero, one or infinite. Zero solutions throws a ValueError, where as infinite solutions are represented parametrically in terms of given symbols. For unique solution a FiniteSet of ordered tuple is returned.
All Standard input formats are supported: For the given set of Equations, the respective input types are given below:
3*x + 2*y - z = 1 2*x - 2*y + 4*z = -2 2*x - y + 2*z = 0
* Augmented Matrix Form
[3 2 -1 1] system = [2 -2 4 -2] (Matrix) [2 -1 2 0]
* List Of Equations Form
system = [3*x + 2*y - z - 1, 2*x - 2*y + 4*z + 2, 2*x - y + 2*z]
* Input A & b Matrix Form (from Ax = b)
[3 2 -1 ] [ 1 ] A = [2 -2 4 ] b = [ -2 ] [2 -1 2 ] [ 0 ]
system = (A, b)
Symbols to solve for should be given as input in all the cases either in an iterable or as comma separated arguments. This is done to maintain consistency in returning solutions in the form of variable input by the user.
The algorithm used here is Gauss-Jordan elimination, which results, after elimination, in an row echelon form matrix.
Returns =======
A FiniteSet of ordered tuple of values of `symbols` for which the `system` has solution.
Please note that general FiniteSet is unordered, the solution returned here is not simply a FiniteSet of solutions, rather it is a FiniteSet of ordered tuple, i.e. the first & only argument to FiniteSet is a tuple of solutions, which is ordered, & hence the returned solution is ordered.
Also note that solution could also have been returned as an ordered tuple, FiniteSet is just a wrapper `{}` around the tuple. It has no other significance except for the fact it is just used to maintain a consistent output format throughout the solveset.
Raises ======
ValueError The input is not valid. The linear system has no solution. The symbols are not given.
Examples ========
>>> from sympy.solvers.solveset import linsolve >>> from sympy import Matrix, S >>> from sympy import symbols >>> x, y, z = symbols("x, y, z")
>>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 10]]) >>> b = Matrix([3, 6, 9]) >>> A Matrix([ [1, 2, 3], [4, 5, 6], [7, 8, 10]]) >>> b Matrix([ [3], [6], [9]])
>>> linsolve((A, b), [x, y, z]) {(-1, 2, 0)}
* Parametric Solution: In case the system is under determined, the function will return parametric solution in terms of the given symbols. Free symbols in the system are returned as it is. For e.g. in the system below, `z` is returned as the solution for variable z, which means z is a free symbol, i.e. it can take arbitrary values.
>>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> b = Matrix([3, 6, 9]) >>> linsolve((A, b), [x, y, z]) {(z - 1, -2*z + 2, z)}
* List of Equations as input
>>> Eqns = [3*x + 2*y - z - 1, 2*x - 2*y + 4*z + 2, - x + S(1)/2*y - z] >>> linsolve(Eqns, x, y, z) {(1, -2, -2)}
* Augmented Matrix as input
>>> aug = Matrix([[2, 1, 3, 1], [2, 6, 8, 3], [6, 8, 18, 5]]) >>> aug Matrix([ [2, 1, 3, 1], [2, 6, 8, 3], [6, 8, 18, 5]]) >>> linsolve(aug, x, y, z) {(3/10, 2/5, 0)}
* Solve for symbolic coefficients
>>> a, b, c, d, e, f = symbols('a, b, c, d, e, f') >>> eqns = [a*x + b*y - c, d*x + e*y - f] >>> linsolve(eqns, x, y) {(-b*(f - c*d/a)/(a*(e - b*d/a)) + c/a, (f - c*d/a)/(e - b*d/a))}
* A degenerate system returns solution as set of given symbols.
>>> system = Matrix(([0,0,0], [0,0,0], [0,0,0])) >>> linsolve(system, x, y) {(x, y)}
"""
'system is to be found.')
'second argument, not type %s: %s' % (type(symbols[0]), symbols[0]))
# 1). Augmented Matrix input Form
# 2). A & b as input Form
# 3). List of equations Form
else:
# Solve using Gauss-Jordan elimination
# Replace free parameters with free symbols
else:
# Return solutions |