Solvers¶
The solvers module in SymPy implements methods for solving equations.
Note
For a beginner-friendly guide focused on solving common types of equations, refer to Solve Equations.
Note
solve()
is an older more mature general
function for solving many types of equations.
solve()
has many options and uses different
methods internally to determine what type of equations you pass it, so if
you know what type of equation you are dealing with you may want to use the
newer solveset()
which solves univariate equations, linsolve()
which solves system of linear equations, and nonlinsolve()
which
solves systems of non linear equations.
Algebraic equations¶
Use solve()
to solve algebraic equations. We suppose all equations are equaled to 0,
so solving x**2 == 1 translates into the following code:
>>> from sympy.solvers import solve
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> solve(x**2 - 1, x)
[-1, 1]
The first argument for solve()
is an equation (equaled to zero) and the second argument
is the symbol that we want to solve the equation for.
- sympy.solvers.solvers.solve(f, *symbols, **flags)[source]¶
Algebraically solves equations and systems of equations.
- Parameters:
f :
a single Expr or Poly that must be zero
an Equality
a Relational expression
a Boolean
iterable of one or more of the above
symbols : (object(s) to solve for) specified as
none given (other non-numeric objects will be used)
single symbol
denested list of symbols (e.g.,
solve(f, x, y)
)ordered iterable of symbols (e.g.,
solve(f, [x, y])
)
flags :
- dict=True (default is False)
Return list (perhaps empty) of solution mappings.
- set=True (default is False)
Return list of symbols and set of tuple(s) of solution(s).
- exclude=[] (default)
Do not try to solve for any of the free symbols in exclude; if expressions are given, the free symbols in them will be extracted automatically.
- check=True (default)
If False, do not do any testing of solutions. This can be useful if you want to include solutions that make any denominator zero.
- numerical=True (default)
Do a fast numerical check if f has only one symbol.
- minimal=True (default is False)
A very fast, minimal testing.
- warn=True (default is False)
Show a warning if
checksol()
could not conclude.- simplify=True (default)
Simplify all but polynomials of order 3 or greater before returning them and (if check is not False) use the general simplify function on the solutions and the expression obtained when they are substituted into the function which should be zero.
- force=True (default is False)
Make positive all symbols without assumptions regarding sign.
- rational=True (default)
Recast Floats as Rational; if this option is not used, the system containing Floats may fail to solve because of issues with polys. If rational=None, Floats will be recast as rationals but the answer will be recast as Floats. If the flag is False then nothing will be done to the Floats.
- manual=True (default is False)
Do not use the polys/matrix method to solve a system of equations, solve them one at a time as you might “manually.”
- implicit=True (default is False)
Allows
solve
to return a solution for a pattern in terms of other functions that contain that pattern; this is only needed if the pattern is inside of some invertible function like cos, exp, ect.- particular=True (default is False)
Instructs
solve
to try to find a particular solution to a linear system with as many zeros as possible; this is very expensive.- quick=True (default is False;
particular
must be True) Selects a fast heuristic to find a solution with many zeros whereas a value of False uses the very slow method guaranteed to find the largest number of zeros possible.
- cubics=True (default)
Return explicit solutions when cubic expressions are encountered. When False, quartics and quintics are disabled, too.
- quartics=True (default)
Return explicit solutions when quartic expressions are encountered. When False, quintics are disabled, too.
- quintics=True (default)
Return explicit solutions (if possible) when quintic expressions are encountered.
Explanation
- Currently supported:
polynomial
transcendental
piecewise combinations of the above
systems of linear and polynomial equations
systems containing relational expressions
systems implied by undetermined coefficients
Examples
The default output varies according to the input and might be a list (possibly empty), a dictionary, a list of dictionaries or tuples, or an expression involving relationals. For specifics regarding different forms of output that may appear, see Solve Output by Type. Let it suffice here to say that to obtain a uniform output from \(solve\) use
dict=True
orset=True
(see below).>>> from sympy import solve, Poly, Eq, Matrix, Symbol >>> from sympy.abc import x, y, z, a, b
The expressions that are passed can be Expr, Equality, or Poly classes (or lists of the same); a Matrix is considered to be a list of all the elements of the matrix:
>>> solve(x - 3, x) [3] >>> solve(Eq(x, 3), x) [3] >>> solve(Poly(x - 3), x) [3] >>> solve(Matrix([[x, x + y]]), x, y) == solve([x, x + y], x, y) True
If no symbols are indicated to be of interest and the equation is univariate, a list of values is returned; otherwise, the keys in a dictionary will indicate which (of all the variables used in the expression(s)) variables and solutions were found:
>>> solve(x**2 - 4) [-2, 2] >>> solve((x - a)*(y - b)) [{a: x}, {b: y}] >>> solve([x - 3, y - 1]) {x: 3, y: 1} >>> solve([x - 3, y**2 - 1]) [{x: 3, y: -1}, {x: 3, y: 1}]
If you pass symbols for which solutions are sought, the output will vary depending on the number of symbols you passed, whether you are passing a list of expressions or not, and whether a linear system was solved. Uniform output is attained by using
dict=True
orset=True
.>>> #### *** feel free to skip to the stars below *** #### >>> from sympy import TableForm >>> h = [None, ';|;'.join(['e', 's', 'solve(e, s)', 'solve(e, s, dict=True)', ... 'solve(e, s, set=True)']).split(';')] >>> t = [] >>> for e, s in [ ... (x - y, y), ... (x - y, [x, y]), ... (x**2 - y, [x, y]), ... ([x - 3, y -1], [x, y]), ... ]: ... how = [{}, dict(dict=True), dict(set=True)] ... res = [solve(e, s, **f) for f in how] ... t.append([e, '|', s, '|'] + [res[0], '|', res[1], '|', res[2]]) ... >>> # ******************************************************* # >>> TableForm(t, headings=h, alignments="<") e | s | solve(e, s) | solve(e, s, dict=True) | solve(e, s, set=True) --------------------------------------------------------------------------------------- x - y | y | [x] | [{y: x}] | ([y], {(x,)}) x - y | [x, y] | [(y, y)] | [{x: y}] | ([x, y], {(y, y)}) x**2 - y | [x, y] | [(x, x**2)] | [{y: x**2}] | ([x, y], {(x, x**2)}) [x - 3, y - 1] | [x, y] | {x: 3, y: 1} | [{x: 3, y: 1}] | ([x, y], {(3, 1)})
If any equation does not depend on the symbol(s) given, it will be eliminated from the equation set and an answer may be given implicitly in terms of variables that were not of interest:
>>> solve([x - y, y - 3], x) {x: y}
When you pass all but one of the free symbols, an attempt is made to find a single solution based on the method of undetermined coefficients. If it succeeds, a dictionary of values is returned. If you want an algebraic solutions for one or more of the symbols, pass the expression to be solved in a list:
>>> e = a*x + b - 2*x - 3 >>> solve(e, [a, b]) {a: 2, b: 3} >>> solve([e], [a, b]) {a: -b/x + (2*x + 3)/x}
When there is no solution for any given symbol which will make all expressions zero, the empty list is returned (or an empty set in the tuple when
set=True
):>>> from sympy import sqrt >>> solve(3, x) [] >>> solve(x - 3, y) [] >>> solve(sqrt(x) + 1, x, set=True) ([x], set())
When an object other than a Symbol is given as a symbol, it is isolated algebraically and an implicit solution may be obtained. This is mostly provided as a convenience to save you from replacing the object with a Symbol and solving for that Symbol. It will only work if the specified object can be replaced with a Symbol using the subs method:
>>> from sympy import exp, Function >>> f = Function('f')
>>> solve(f(x) - x, f(x)) [x] >>> solve(f(x).diff(x) - f(x) - x, f(x).diff(x)) [x + f(x)] >>> solve(f(x).diff(x) - f(x) - x, f(x)) [-x + Derivative(f(x), x)] >>> solve(x + exp(x)**2, exp(x), set=True) ([exp(x)], {(-sqrt(-x),), (sqrt(-x),)})
>>> from sympy import Indexed, IndexedBase, Tuple >>> A = IndexedBase('A') >>> eqs = Tuple(A[1] + A[2] - 3, A[1] - A[2] + 1) >>> solve(eqs, eqs.atoms(Indexed)) {A[1]: 1, A[2]: 2}
To solve for a function within a derivative, use
dsolve()
.
To solve for a symbol implicitly, use implicit=True:
>>> solve(x + exp(x), x) [-LambertW(1)] >>> solve(x + exp(x), x, implicit=True) [-exp(x)]
It is possible to solve for anything in an expression that can be replaced with a symbol using
subs
:>>> solve(x + 2 + sqrt(3), x + 2) [-sqrt(3)] >>> solve((x + 2 + sqrt(3), x + 4 + y), y, x + 2) {y: -2 + sqrt(3), x + 2: -sqrt(3)}
Nothing heroic is done in this implicit solving so you may end up with a symbol still in the solution:
>>> eqs = (x*y + 3*y + sqrt(3), x + 4 + y) >>> solve(eqs, y, x + 2) {y: -sqrt(3)/(x + 3), x + 2: -2*x/(x + 3) - 6/(x + 3) + sqrt(3)/(x + 3)} >>> solve(eqs, y*x, x) {x: -y - 4, x*y: -3*y - sqrt(3)}
If you attempt to solve for a number, remember that the number you have obtained does not necessarily mean that the value is equivalent to the expression obtained:
>>> solve(sqrt(2) - 1, 1) [sqrt(2)] >>> solve(x - y + 1, 1) # /!\ -1 is targeted, too [x/(y - 1)] >>> [_.subs(z, -1) for _ in solve((x - y + 1).subs(-1, z), 1)] [-x + y]
Additional Examples
solve()
with check=True (default) will run through the symbol tags to eliminate unwanted solutions. If no assumptions are included, all possible solutions will be returned:>>> x = Symbol("x") >>> solve(x**2 - 1) [-1, 1]
By setting the
positive
flag, only one solution will be returned:>>> pos = Symbol("pos", positive=True) >>> solve(pos**2 - 1) [1]
When the solutions are checked, those that make any denominator zero are automatically excluded. If you do not want to exclude such solutions, then use the check=False option:
>>> from sympy import sin, limit >>> solve(sin(x)/x) # 0 is excluded [pi]
If
check=False
, then a solution to the numerator being zero is found but the value of \(x = 0\) is a spurious solution since \(\sin(x)/x\) has the well known limit (without discontinuity) of 1 at \(x = 0\):>>> solve(sin(x)/x, check=False) [0, pi]
In the following case, however, the limit exists and is equal to the value of \(x = 0\) that is excluded when check=True:
>>> eq = x**2*(1/x - z**2/x) >>> solve(eq, x) [] >>> solve(eq, x, check=False) [0] >>> limit(eq, x, 0, '-') 0 >>> limit(eq, x, 0, '+') 0
Solving Relationships
When one or more expressions passed to
solve
is a relational, a relational result is returned (and thedict
andset
flags are ignored):>>> solve(x < 3) (-oo < x) & (x < 3) >>> solve([x < 3, x**2 > 4], x) ((-oo < x) & (x < -2)) | ((2 < x) & (x < 3)) >>> solve([x + y - 3, x > 3], x) (3 < x) & (x < oo) & Eq(x, 3 - y)
Although checking of assumptions on symbols in relationals is not done, setting assumptions will affect how certain relationals might automatically simplify:
>>> solve(x**2 > 4) ((-oo < x) & (x < -2)) | ((2 < x) & (x < oo))
>>> r = Symbol('r', real=True) >>> solve(r**2 > 4) (2 < r) | (r < -2)
There is currently no algorithm in SymPy that allows you to use relationships to resolve more than one variable. So the following does not determine that
q < 0
(and trying to solve forr
andq
will raise an error):>>> from sympy import symbols >>> r, q = symbols('r, q', real=True) >>> solve([r + q - 3, r > 3], r) (3 < r) & Eq(r, 3 - q)
You can directly call the routine that
solve
calls when it encounters a relational:reduce_inequalities()
. It treats Expr like Equality.>>> from sympy import reduce_inequalities >>> reduce_inequalities([x**2 - 4]) Eq(x, -2) | Eq(x, 2)
If each relationship contains only one symbol of interest, the expressions can be processed for multiple symbols:
>>> reduce_inequalities([0 <= x - 1, y < 3], [x, y]) (-oo < y) & (1 <= x) & (x < oo) & (y < 3)
But an error is raised if any relationship has more than one symbol of interest:
>>> reduce_inequalities([0 <= x*y - 1, y < 3], [x, y]) Traceback (most recent call last): ... NotImplementedError: inequality has more than one symbol of interest.
Disabling High-Order Explicit Solutions
When solving polynomial expressions, you might not want explicit solutions (which can be quite long). If the expression is univariate,
CRootOf
instances will be returned instead:>>> solve(x**3 - x + 1) [-1/((-1/2 - sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)) - (-1/2 - sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)/3, -(-1/2 + sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)/3 - 1/((-1/2 + sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)), -(3*sqrt(69)/2 + 27/2)**(1/3)/3 - 1/(3*sqrt(69)/2 + 27/2)**(1/3)] >>> solve(x**3 - x + 1, cubics=False) [CRootOf(x**3 - x + 1, 0), CRootOf(x**3 - x + 1, 1), CRootOf(x**3 - x + 1, 2)]
If the expression is multivariate, no solution might be returned:
>>> solve(x**3 - x + a, x, cubics=False) []
Sometimes solutions will be obtained even when a flag is False because the expression could be factored. In the following example, the equation can be factored as the product of a linear and a quadratic factor so explicit solutions (which did not require solving a cubic expression) are obtained:
>>> eq = x**3 + 3*x**2 + x - 1 >>> solve(eq, cubics=False) [-1, -1 + sqrt(2), -sqrt(2) - 1]
Solving Equations Involving Radicals
Because of SymPy’s use of the principle root, some solutions to radical equations will be missed unless check=False:
>>> from sympy import root >>> eq = root(x**3 - 3*x**2, 3) + 1 - x >>> solve(eq) [] >>> solve(eq, check=False) [1/3]
In the above example, there is only a single solution to the equation. Other expressions will yield spurious roots which must be checked manually; roots which give a negative argument to odd-powered radicals will also need special checking:
>>> from sympy import real_root, S >>> eq = root(x, 3) - root(x, 5) + S(1)/7 >>> solve(eq) # this gives 2 solutions but misses a 3rd [CRootOf(7*x**5 - 7*x**3 + 1, 1)**15, CRootOf(7*x**5 - 7*x**3 + 1, 2)**15] >>> sol = solve(eq, check=False) >>> [abs(eq.subs(x,i).n(2)) for i in sol] [0.48, 0.e-110, 0.e-110, 0.052, 0.052]
The first solution is negative so
real_root
must be used to see that it satisfies the expression:>>> abs(real_root(eq.subs(x, sol[0])).n(2)) 0.e-110
If the roots of the equation are not real then more care will be necessary to find the roots, especially for higher order equations. Consider the following expression:
>>> expr = root(x, 3) - root(x, 5)
We will construct a known value for this expression at x = 3 by selecting the 1-th root for each radical:
>>> expr1 = root(x, 3, 1) - root(x, 5, 1) >>> v = expr1.subs(x, -3)
The
solve
function is unable to find any exact roots to this equation:>>> eq = Eq(expr, v); eq1 = Eq(expr1, v) >>> solve(eq, check=False), solve(eq1, check=False) ([], [])
The function
unrad
, however, can be used to get a form of the equation for which numerical roots can be found:>>> from sympy.solvers.solvers import unrad >>> from sympy import nroots >>> e, (p, cov) = unrad(eq) >>> pvals = nroots(e) >>> inversion = solve(cov, x)[0] >>> xvals = [inversion.subs(p, i) for i in pvals]
Although
eq
oreq1
could have been used to findxvals
, the solution can only be verified withexpr1
:>>> z = expr - v >>> [xi.n(chop=1e-9) for xi in xvals if abs(z.subs(x, xi).n()) < 1e-9] [] >>> z1 = expr1 - v >>> [xi.n(chop=1e-9) for xi in xvals if abs(z1.subs(x, xi).n()) < 1e-9] [-3.0]
- sympy.solvers.solvers.solve_linear(lhs, rhs=0, symbols=[], exclude=[])[source]¶
Return a tuple derived from
f = lhs - rhs
that is one of the following:(0, 1)
,(0, 0)
,(symbol, solution)
,(n, d)
.Explanation
(0, 1)
meaning thatf
is independent of the symbols in symbols that are not in exclude.(0, 0)
meaning that there is no solution to the equation amongst the symbols given. If the first element of the tuple is not zero, then the function is guaranteed to be dependent on a symbol in symbols.(symbol, solution)
where symbol appears linearly in the numerator off
, is in symbols (if given), and is not in exclude (if given). No simplification is done tof
other than amul=True
expansion, so the solution will correspond strictly to a unique solution.(n, d)
wheren
andd
are the numerator and denominator off
when the numerator was not linear in any symbol of interest;n
will never be a symbol unless a solution for that symbol was found (in which case the second element is the solution, not the denominator).Examples
>>> from sympy import cancel, Pow
f
is independent of the symbols in symbols that are not in exclude:>>> from sympy import cos, sin, solve_linear >>> from sympy.abc import x, y, z >>> eq = y*cos(x)**2 + y*sin(x)**2 - y # = y*(1 - 1) = 0 >>> solve_linear(eq) (0, 1) >>> eq = cos(x)**2 + sin(x)**2 # = 1 >>> solve_linear(eq) (0, 1) >>> solve_linear(x, exclude=[x]) (0, 1)
The variable
x
appears as a linear variable in each of the following:>>> solve_linear(x + y**2) (x, -y**2) >>> solve_linear(1/x - y**2) (x, y**(-2))
When not linear in
x
ory
then the numerator and denominator are returned:>>> solve_linear(x**2/y**2 - 3) (x**2 - 3*y**2, y**2)
If the numerator of the expression is a symbol, then
(0, 0)
is returned if the solution for that symbol would have set any denominator to 0:>>> eq = 1/(1/x - 2) >>> eq.as_numer_denom() (x, 1 - 2*x) >>> solve_linear(eq) (0, 0)
But automatic rewriting may cause a symbol in the denominator to appear in the numerator so a solution will be returned:
>>> (1/x)**-1 x >>> solve_linear((1/x)**-1) (x, 0)
Use an unevaluated expression to avoid this:
>>> solve_linear(Pow(1/x, -1, evaluate=False)) (0, 0)
If
x
is allowed to cancel in the following expression, then it appears to be linear inx
, but this sort of cancellation is not done bysolve_linear
so the solution will always satisfy the original expression without causing a division by zero error.>>> eq = x**2*(1/x - z**2/x) >>> solve_linear(cancel(eq)) (x, 0) >>> solve_linear(eq) (x**2*(1 - z**2), x)
A list of symbols for which a solution is desired may be given:
>>> solve_linear(x + y + z, symbols=[y]) (y, -x - z)
A list of symbols to ignore may also be given:
>>> solve_linear(x + y + z, exclude=[x]) (y, -x - z)
(A solution for
y
is obtained because it is the first variable from the canonically sorted list of symbols that had a linear solution.)
- sympy.solvers.solvers.solve_linear_system(system, *symbols, **flags)[source]¶
Solve system of \(N\) linear equations with \(M\) variables, which means both under- and overdetermined systems are supported.
Explanation
The possible number of solutions is zero, one, or infinite. Respectively, this procedure will return None or a dictionary with solutions. In the case of underdetermined systems, all arbitrary parameters are skipped. This may cause a situation in which an empty dictionary is returned. In that case, all symbols can be assigned arbitrary values.
Input to this function is a \(N\times M + 1\) matrix, which means it has to be in augmented form. If you prefer to enter \(N\) equations and \(M\) unknowns then use
solve(Neqs, *Msymbols)
instead. Note: a local copy of the matrix is made by this routine so the matrix that is passed will not be modified.The algorithm used here is fraction-free Gaussian elimination, which results, after elimination, in an upper-triangular matrix. Then solutions are found using back-substitution. This approach is more efficient and compact than the Gauss-Jordan method.
Examples
>>> from sympy import Matrix, solve_linear_system >>> from sympy.abc import x, y
Solve the following system:
x + 4 y == 2 -2 x + y == 14
>>> system = Matrix(( (1, 4, 2), (-2, 1, 14))) >>> solve_linear_system(system, x, y) {x: -6, y: 2}
A degenerate system returns an empty dictionary:
>>> system = Matrix(( (0,0,0), (0,0,0) )) >>> solve_linear_system(system, x, y) {}
- sympy.solvers.solvers.solve_linear_system_LU(matrix, syms)[source]¶
Solves the augmented matrix system using
LUsolve
and returns a dictionary in which solutions are keyed to the symbols of syms as ordered.Explanation
The matrix must be invertible.
Examples
>>> from sympy import Matrix, solve_linear_system_LU >>> from sympy.abc import x, y, z
>>> solve_linear_system_LU(Matrix([ ... [1, 2, 0, 1], ... [3, 2, 2, 1], ... [2, 0, 0, 1]]), [x, y, z]) {x: 1/2, y: 1/4, z: -1/2}
See also
- sympy.solvers.solvers.solve_undetermined_coeffs(
- equ,
- coeffs,
- *syms,
- **flags,
Solve a system of equations in \(k\) parameters that is formed by matching coefficients in variables
coeffs
that are on factors dependent on the remaining variables (or those given explicitly bysyms
.Explanation
The result of this function is a dictionary with symbolic values of those parameters with respect to coefficients in \(q\) – empty if there is no solution or coefficients do not appear in the equation – else None (if the system was not recognized). If there is more than one solution, the solutions are passed as a list. The output can be modified using the same semantics as for \(solve\) since the flags that are passed are sent directly to \(solve\) so, for example the flag
dict=True
will always return a list of solutions as dictionaries.This function accepts both Equality and Expr class instances. The solving process is most efficient when symbols are specified in addition to parameters to be determined, but an attempt to determine them (if absent) will be made. If an expected solution is not obtained (and symbols were not specified) try specifying them.
Examples
>>> from sympy import Eq, solve_undetermined_coeffs >>> from sympy.abc import a, b, c, h, p, k, x, y
>>> solve_undetermined_coeffs(Eq(a*x + a + b, x/2), [a, b], x) {a: 1/2, b: -1/2} >>> solve_undetermined_coeffs(a - 2, [a]) {a: 2}
The equation can be nonlinear in the symbols:
>>> X, Y, Z = y, x**y, y*x**y >>> eq = a*X + b*Y + c*Z - X - 2*Y - 3*Z >>> coeffs = a, b, c >>> syms = x, y >>> solve_undetermined_coeffs(eq, coeffs, syms) {a: 1, b: 2, c: 3}
And the system can be nonlinear in coefficients, too, but if there is only a single solution, it will be returned as a dictionary:
>>> eq = a*x**2 + b*x + c - ((x - h)**2 + 4*p*k)/4/p >>> solve_undetermined_coeffs(eq, (h, p, k), x) {h: -b/(2*a), k: (4*a*c - b**2)/(4*a), p: 1/(4*a)}
Multiple solutions are always returned in a list:
>>> solve_undetermined_coeffs(a**2*x + b - x, [a, b], x) [{a: -1, b: 0}, {a: 1, b: 0}]
Using flag
dict=True
(in keeping with semantics insolve()
) will force the result to always be a list with any solutions as elements in that list.>>> solve_undetermined_coeffs(a*x - 2*x, [a], dict=True) [{a: 2}]
- sympy.solvers.solvers.nsolve(*args, dict=False, **kwargs)[source]¶
Solve a nonlinear equation system numerically:
nsolve(f, [args,] x0, modules=['mpmath'], **kwargs)
.Explanation
f
is a vector function of symbolic expressions representing the system. args are the variables. If there is only one variable, this argument can be omitted.x0
is a starting vector close to a solution.Use the modules keyword to specify which modules should be used to evaluate the function and the Jacobian matrix. Make sure to use a module that supports matrices. For more information on the syntax, please see the docstring of
lambdify
.If the keyword arguments contain
dict=True
(default is False)nsolve
will return a list (perhaps empty) of solution mappings. This might be especially useful if you want to usensolve
as a fallback to solve since using the dict argument for both methods produces return values of consistent type structure. Please note: to keep this consistent withsolve
, the solution will be returned in a list even thoughnsolve
(currently at least) only finds one solution at a time.Overdetermined systems are supported.
Examples
>>> from sympy import Symbol, nsolve >>> import mpmath >>> mpmath.mp.dps = 15 >>> x1 = Symbol('x1') >>> x2 = Symbol('x2') >>> f1 = 3 * x1**2 - 2 * x2**2 - 1 >>> f2 = x1**2 - 2 * x1 + x2**2 + 2 * x2 - 8 >>> print(nsolve((f1, f2), (x1, x2), (-1, 1))) Matrix([[-1.19287309935246], [1.27844411169911]])
For one-dimensional functions the syntax is simplified:
>>> from sympy import sin, nsolve >>> from sympy.abc import x >>> nsolve(sin(x), x, 2) 3.14159265358979 >>> nsolve(sin(x), 2) 3.14159265358979
To solve with higher precision than the default, use the prec argument:
>>> from sympy import cos >>> nsolve(cos(x) - x, 1) 0.739085133215161 >>> nsolve(cos(x) - x, 1, prec=50) 0.73908513321516064165531208767387340401341175890076 >>> cos(_) 0.73908513321516064165531208767387340401341175890076
To solve for complex roots of real functions, a nonreal initial point must be specified:
>>> from sympy import I >>> nsolve(x**2 + 2, I) 1.4142135623731*I
mpmath.findroot
is used and you can find their more extensive documentation, especially concerning keyword parameters and available solvers. Note, however, that functions which are very steep near the root, the verification of the solution may fail. In this case you should use the flagverify=False
and independently verify the solution.>>> from sympy import cos, cosh >>> f = cos(x)*cosh(x) - 1 >>> nsolve(f, 3.14*100) Traceback (most recent call last): ... ValueError: Could not find root within given tolerance. (1.39267e+230 > 2.1684e-19) >>> ans = nsolve(f, 3.14*100, verify=False); ans 312.588469032184 >>> f.subs(x, ans).n(2) 2.1e+121 >>> (f/f.diff(x)).subs(x, ans).n(2) 7.4e-15
One might safely skip the verification if bounds of the root are known and a bisection method is used:
>>> bounds = lambda i: (3.14*i, 3.14*(i + 1)) >>> nsolve(f, bounds(100), solver='bisect', verify=False) 315.730061685774
Alternatively, a function may be better behaved when the denominator is ignored. Since this is not always the case, however, the decision of what function to use is left to the discretion of the user.
>>> eq = x**2/(1 - x)/(1 - 2*x)**2 - 100 >>> nsolve(eq, 0.46) Traceback (most recent call last): ... ValueError: Could not find root within given tolerance. (10000 > 2.1684e-19) Try another starting point or tweak arguments. >>> nsolve(eq.as_numer_denom()[0], 0.46) 0.46792545969349058
- sympy.solvers.solvers.checksol(f, symbol, sol=None, **flags)[source]¶
Checks whether sol is a solution of equation f == 0.
Explanation
Input can be either a single symbol and corresponding value or a dictionary of symbols and values. When given as a dictionary and flag
simplify=True
, the values in the dictionary will be simplified. f can be a single equation or an iterable of equations. A solution must satisfy all equations in f to be considered valid; if a solution does not satisfy any equation, False is returned; if one or more checks are inconclusive (and none are False) then None is returned.Examples
>>> from sympy import checksol, symbols >>> x, y = symbols('x,y') >>> checksol(x**4 - 1, x, 1) True >>> checksol(x**4 - 1, x, 0) False >>> checksol(x**2 + y**2 - 5**2, {x: 3, y: 4}) True
To check if an expression is zero using
checksol()
, pass it as f and send an empty dictionary for symbol:>>> checksol(x**2 + x - x*(x + 1), {}) True
None is returned if
checksol()
could not conclude.- flags:
- ‘numerical=True (default)’
do a fast numerical check if
f
has only one symbol.- ‘minimal=True (default is False)’
a very fast, minimal testing.
- ‘warn=True (default is False)’
show a warning if checksol() could not conclude.
- ‘simplify=True (default)’
simplify solution before substituting into function and simplify the function before trying specific simplifications
- ‘force=True (default is False)’
make positive all symbols without assumptions regarding sign.
- sympy.solvers.solvers.unrad(eq, *syms, **flags)[source]¶
Remove radicals with symbolic arguments and return (eq, cov), None, or raise an error.
Explanation
None is returned if there are no radicals to remove.
NotImplementedError is raised if there are radicals and they cannot be removed or if the relationship between the original symbols and the change of variable needed to rewrite the system as a polynomial cannot be solved.
Otherwise the tuple,
(eq, cov)
, is returned where:- eq,
cov
eq is an equation without radicals (in the symbol(s) of interest) whose solutions are a superset of the solutions to the original expression. eq might be rewritten in terms of a new variable; the relationship to the original variables is given by
cov
which is a list containingv
andv**p - b
wherep
is the power needed to clear the radical andb
is the radical now expressed as a polynomial in the symbols of interest. For example, for sqrt(2 - x) the tuple would be(c, c**2 - 2 + x)
. The solutions of eq will contain solutions to the original equation (if there are any).- syms
An iterable of symbols which, if provided, will limit the focus of radical removal: only radicals with one or more of the symbols of interest will be cleared. All free symbols are used if syms is not set.
flags are used internally for communication during recursive calls. Two options are also recognized:
take
, when defined, is interpreted as a single-argument function that returns True if a given Pow should be handled.Radicals can be removed from an expression if:
All bases of the radicals are the same; a change of variables is done in this case.
If all radicals appear in one term of the expression.
There are only four terms with sqrt() factors or there are less than four terms having sqrt() factors.
There are only two terms with radicals.
Examples
>>> from sympy.solvers.solvers import unrad >>> from sympy.abc import x >>> from sympy import sqrt, Rational, root
>>> unrad(sqrt(x)*x**Rational(1, 3) + 2) (x**5 - 64, []) >>> unrad(sqrt(x) + root(x + 1, 3)) (-x**3 + x**2 + 2*x + 1, []) >>> eq = sqrt(x) + root(x, 3) - 2 >>> unrad(eq) (_p**3 + _p**2 - 2, [_p, _p**6 - x])
- eq,
Ordinary Differential equations (ODEs)¶
See ODE.
Partial Differential Equations (PDEs)¶
See PDE.
Deutils (Utilities for solving ODE’s and PDE’s)¶
- sympy.solvers.deutils.ode_order(expr, func)[source]¶
Returns the order of a given differential equation with respect to func.
This function is implemented recursively.
Examples
>>> from sympy import Function >>> from sympy.solvers.deutils import ode_order >>> from sympy.abc import x >>> f, g = map(Function, ['f', 'g']) >>> ode_order(f(x).diff(x, 2) + f(x).diff(x)**2 + ... f(x).diff(x), f(x)) 2 >>> ode_order(f(x).diff(x, 2) + g(x).diff(x, 3), f(x)) 2 >>> ode_order(f(x).diff(x, 2) + g(x).diff(x, 3), g(x)) 3
Recurrence Equations¶
- sympy.solvers.recurr.rsolve(f, y, init=None)[source]¶
Solve univariate recurrence with rational coefficients.
Given \(k\)-th order linear recurrence \(\operatorname{L} y = f\), or equivalently:
\[a_{k}(n) y(n+k) + a_{k-1}(n) y(n+k-1) + \cdots + a_{0}(n) y(n) = f(n)\]where \(a_{i}(n)\), for \(i=0, \ldots, k\), are polynomials or rational functions in \(n\), and \(f\) is a hypergeometric function or a sum of a fixed number of pairwise dissimilar hypergeometric terms in \(n\), finds all solutions or returns
None
, if none were found.Initial conditions can be given as a dictionary in two forms:
{ n_0 : v_0, n_1 : v_1, ..., n_m : v_m}
{y(n_0) : v_0, y(n_1) : v_1, ..., y(n_m) : v_m}
or as a list
L
of values:L = [v_0, v_1, ..., v_m]
where
L[i] = v_i
, for \(i=0, \ldots, m\), maps to \(y(n_i)\).Examples
Lets consider the following recurrence:
\[(n - 1) y(n + 2) - (n^2 + 3 n - 2) y(n + 1) + 2 n (n + 1) y(n) = 0\]>>> from sympy import Function, rsolve >>> from sympy.abc import n >>> y = Function('y')
>>> f = (n - 1)*y(n + 2) - (n**2 + 3*n - 2)*y(n + 1) + 2*n*(n + 1)*y(n)
>>> rsolve(f, y(n)) 2**n*C0 + C1*factorial(n)
>>> rsolve(f, y(n), {y(0):0, y(1):3}) 3*2**n - 3*factorial(n)
See also
- sympy.solvers.recurr.rsolve_poly(coeffs, f, n, shift=0, **hints)[source]¶
Given linear recurrence operator \(\operatorname{L}\) of order \(k\) with polynomial coefficients and inhomogeneous equation \(\operatorname{L} y = f\), where \(f\) is a polynomial, we seek for all polynomial solutions over field \(K\) of characteristic zero.
The algorithm performs two basic steps:
Compute degree \(N\) of the general polynomial solution.
Find all polynomials of degree \(N\) or less of \(\operatorname{L} y = f\).
There are two methods for computing the polynomial solutions. If the degree bound is relatively small, i.e. it’s smaller than or equal to the order of the recurrence, then naive method of undetermined coefficients is being used. This gives a system of algebraic equations with \(N+1\) unknowns.
In the other case, the algorithm performs transformation of the initial equation to an equivalent one for which the system of algebraic equations has only \(r\) indeterminates. This method is quite sophisticated (in comparison with the naive one) and was invented together by Abramov, Bronstein and Petkovsek.
It is possible to generalize the algorithm implemented here to the case of linear q-difference and differential equations.
Lets say that we would like to compute \(m\)-th Bernoulli polynomial up to a constant. For this we can use \(b(n+1) - b(n) = m n^{m-1}\) recurrence, which has solution \(b(n) = B_m + C\). For example:
>>> from sympy import Symbol, rsolve_poly >>> n = Symbol('n', integer=True)
>>> rsolve_poly([-1, 1], 4*n**3, n) C0 + n**4 - 2*n**3 + n**2
References
[R890]S. A. Abramov, M. Bronstein and M. Petkovsek, On polynomial solutions of linear operator equations, in: T. Levelt, ed., Proc. ISSAC ‘95, ACM Press, New York, 1995, 290-296.
[R891]M. Petkovsek, Hypergeometric solutions of linear recurrences with polynomial coefficients, J. Symbolic Computation, 14 (1992), 243-264.
[R892]Petkovsek, H. S. Wilf, D. Zeilberger, A = B, 1996.
- sympy.solvers.recurr.rsolve_ratio(coeffs, f, n, **hints)[source]¶
Given linear recurrence operator \(\operatorname{L}\) of order \(k\) with polynomial coefficients and inhomogeneous equation \(\operatorname{L} y = f\), where \(f\) is a polynomial, we seek for all rational solutions over field \(K\) of characteristic zero.
This procedure accepts only polynomials, however if you are interested in solving recurrence with rational coefficients then use
rsolve
which will pre-process the given equation and run this procedure with polynomial arguments.The algorithm performs two basic steps:
Compute polynomial \(v(n)\) which can be used as universal denominator of any rational solution of equation \(\operatorname{L} y = f\).
Construct new linear difference equation by substitution \(y(n) = u(n)/v(n)\) and solve it for \(u(n)\) finding all its polynomial solutions. Return
None
if none were found.
The algorithm implemented here is a revised version of the original Abramov’s algorithm, developed in 1989. The new approach is much simpler to implement and has better overall efficiency. This method can be easily adapted to the q-difference equations case.
Besides finding rational solutions alone, this functions is an important part of Hyper algorithm where it is used to find a particular solution for the inhomogeneous part of a recurrence.
Examples
>>> from sympy.abc import x >>> from sympy.solvers.recurr import rsolve_ratio >>> rsolve_ratio([-2*x**3 + x**2 + 2*x - 1, 2*x**3 + x**2 - 6*x, ... - 2*x**3 - 11*x**2 - 18*x - 9, 2*x**3 + 13*x**2 + 22*x + 8], 0, x) C0*(2*x - 3)/(2*(x**2 - 1))
See also
References
[R893]S. A. Abramov, Rational solutions of linear difference and q-difference equations with polynomial coefficients, in: T. Levelt, ed., Proc. ISSAC ‘95, ACM Press, New York, 1995, 285-289
- sympy.solvers.recurr.rsolve_hyper(coeffs, f, n, **hints)[source]¶
Given linear recurrence operator \(\operatorname{L}\) of order \(k\) with polynomial coefficients and inhomogeneous equation \(\operatorname{L} y = f\) we seek for all hypergeometric solutions over field \(K\) of characteristic zero.
The inhomogeneous part can be either hypergeometric or a sum of a fixed number of pairwise dissimilar hypergeometric terms.
The algorithm performs three basic steps:
Group together similar hypergeometric terms in the inhomogeneous part of \(\operatorname{L} y = f\), and find particular solution using Abramov’s algorithm.
Compute generating set of \(\operatorname{L}\) and find basis in it, so that all solutions are linearly independent.
Form final solution with the number of arbitrary constants equal to dimension of basis of \(\operatorname{L}\).
Term \(a(n)\) is hypergeometric if it is annihilated by first order linear difference equations with polynomial coefficients or, in simpler words, if consecutive term ratio is a rational function.
The output of this procedure is a linear combination of fixed number of hypergeometric terms. However the underlying method can generate larger class of solutions - D’Alembertian terms.
Note also that this method not only computes the kernel of the inhomogeneous equation, but also reduces in to a basis so that solutions generated by this procedure are linearly independent
Examples
>>> from sympy.solvers import rsolve_hyper >>> from sympy.abc import x
>>> rsolve_hyper([-1, -1, 1], 0, x) C0*(1/2 - sqrt(5)/2)**x + C1*(1/2 + sqrt(5)/2)**x
>>> rsolve_hyper([-1, 1], 1 + x, x) C0 + x*(x + 1)/2
References
Systems of Polynomial Equations¶
- sympy.solvers.polysys.solve_poly_system(
- seq,
- *gens,
- strict=False,
- **args,
Return a list of solutions for the system of polynomial equations or else None.
- Parameters:
seq: a list/tuple/set
Listing all the equations that are needed to be solved
gens: generators
generators of the equations in seq for which we want the solutions
strict: a boolean (default is False)
if strict is True, NotImplementedError will be raised if the solution is known to be incomplete (which can occur if not all solutions are expressible in radicals)
args: Keyword arguments
Special options for solving the equations.
- Returns:
List[Tuple]
a list of tuples with elements being solutions for the symbols in the order they were passed as gens
None
None is returned when the computed basis contains only the ground.
Examples
>>> from sympy import solve_poly_system >>> from sympy.abc import x, y
>>> solve_poly_system([x*y - 2*y, 2*y**2 - x**2], x, y) [(0, 0), (2, -sqrt(2)), (2, sqrt(2))]
>>> solve_poly_system([x**5 - x + y**3, y**2 - 1], x, y, strict=True) Traceback (most recent call last): ... UnsolvableFactorError
- sympy.solvers.polysys.solve_triangulated(polys, *gens, **args)[source]¶
Solve a polynomial system using Gianni-Kalkbrenner algorithm.
The algorithm proceeds by computing one Groebner basis in the ground domain and then by iteratively computing polynomial factorizations in appropriately constructed algebraic extensions of the ground domain.
- Parameters:
polys: a list/tuple/set
Listing all the equations that are needed to be solved
gens: generators
generators of the equations in polys for which we want the solutions
args: Keyword arguments
Special options for solving the equations
- Returns:
List[Tuple]
A List of tuples. Solutions for symbols that satisfy the equations listed in polys
Examples
>>> from sympy import solve_triangulated >>> from sympy.abc import x, y, z
>>> F = [x**2 + y + z - 1, x + y**2 + z - 1, x + y + z**2 - 1]
>>> solve_triangulated(F, x, y, z) [(0, 0, 1), (0, 1, 0), (1, 0, 0)]
References
1. Patrizia Gianni, Teo Mora, Algebraic Solution of System of Polynomial Equations using Groebner Bases, AAECC-5 on Applied Algebra, Algebraic Algorithms and Error-Correcting Codes, LNCS 356 247–257, 1989
Diophantine Equations (DEs)¶
See Diophantine
Inequalities¶
Linear Programming (Optimization)¶
- sympy.solvers.simplex.lpmax(f, constr)[source]¶
return maximum of linear equation
f
under linear constraints expressed using Ge, Le or Eq.All variables are unbounded unless constrained.
Examples
>>> from sympy.solvers.simplex import lpmax >>> from sympy import Eq >>> from sympy.abc import x, y >>> lpmax(x, [2*x - 3*y >= -1, Eq(x+ 3*y,2), x <= 2*y]) (4/5, {x: 4/5, y: 2/5})
Negative values for variables are permitted unless explicitly exluding:
>>> lpmax(x, [x <= -1]) (-1, {x: -1})
If a non-negative constraint is added for x, there is no possible solution:
>>> lpmax(x, [x <= -1, x >= 0]) Traceback (most recent call last): ... sympy.solvers.simplex.InfeasibleLPError: inconsistent/False constraint
- sympy.solvers.simplex.lpmin(f, constr)[source]¶
return minimum of linear equation
f
under linear constraints expressed using Ge, Le or Eq.All variables are unbounded unless constrained.
Examples
>>> from sympy.solvers.simplex import lpmin >>> from sympy import Eq >>> from sympy.abc import x, y >>> lpmin(x, [2*x - 3*y >= -1, Eq(x + 3*y, 2), x <= 2*y]) (1/3, {x: 1/3, y: 5/9})
Negative values for variables are permitted unless explicitly exluding, so minimizing
x
forx <= 3
is an unbounded problem while the following has a bounded solution:>>> lpmin(x, [x >= 0, x <= 3]) (0, {x: 0})
Without indicating that
x
is nonnegative, there is no minimum for this objective:>>> lpmin(x, [x <= 3]) Traceback (most recent call last): ... sympy.solvers.simplex.UnboundedLPError: Objective function can assume arbitrarily large values!
- sympy.solvers.simplex.linprog(
- c,
- A=None,
- b=None,
- A_eq=None,
- b_eq=None,
- bounds=None,
Return the minimization of
c*x
with the given constraintsA*x <= b
andA_eq*x = b_eq
. Unless bounds are given, variables will have nonnegative values in the solution.If
A
is not given, then the dimension of the system will be determined by the length ofC
.By default, all variables will be nonnegative. If
bounds
is given as a single tuple,(lo, hi)
, then all variables will be constrained to be betweenlo
andhi
. Use None for alo
orhi
if it is unconstrained in the negative or positive direction, respectively, e.g.(None, 0)
indicates nonpositive values. To set individual ranges, pass a list with length equal to the number of columns inA
, each element being a tuple; if only a few variables take on non-default values they can be passed as a dictionary with keys giving the corresponding column to which the variable is assigned, e.g.bounds={2: (1, 4)}
would limit the 3rd variable to have a value in range[1, 4]
.Examples
>>> from sympy.solvers.simplex import linprog >>> from sympy import symbols, Eq, linear_eq_to_matrix as M, Matrix >>> x = x1, x2, x3, x4 = symbols('x1:5') >>> X = Matrix(x) >>> c, d = M(5*x2 + x3 + 4*x4 - x1, x) >>> a, b = M([5*x2 + 2*x3 + 5*x4 - (x1 + 5)], x) >>> aeq, beq = M([Eq(3*x2 + x4, 2), Eq(-x1 + x3 + 2*x4, 1)], x) >>> constr = [i <= j for i,j in zip(a*X, b)] >>> constr += [Eq(i, j) for i,j in zip(aeq*X, beq)] >>> linprog(c, a, b, aeq, beq) (9/2, [0, 1/2, 0, 1/2]) >>> assert all(i.subs(dict(zip(x, _[1]))) for i in constr)