# Solve One or a System of Equations Numerically Use SymPy to numerically solve a system of one or more equations. For example, numerically solving $\cos(x) = x $ returns $ x \approx 0.739085133215161$. Solving numerically is useful if: - You only need a numeric solution, not a symbolic one - A closed-form solution is not available or is overly complicated; refer to [](solving-guidance.md#when-you-might-prefer-a-numeric-solution) {func}`~.solve` and {func}`~.solveset` will not try to find a numeric solution, only a mathematically-exact symbolic solution. So if you want a numeric solution, use {func}`~.nsolve`. SymPy is designed for symbolic mathematics. If you do not need to do symbolic operations, then for numerical operations you can use another free and open-source package such as NumPy or SciPy which will be faster, work with arrays, and have more algorithms implemented. The main reasons to use SymPy (or its dependency [mpmath](https://mpmath.org/)) for numerical calculations are: - to do a simple numerical calculation within the context of a symbolic calculation using SymPy - if you need the arbitrary precision capabilities to get more digits of precision than you would get from float64. ## Alternatives to Consider - SciPy's {external:func}`scipy.optimize.fsolve` can solve a system of (non-linear) equations - NumPy's {external:func}`numpy.linalg.solve` can solve a system of linear scalar equations - mpmath's {external:func}`~mpmath.findroot`, which {func}`~.nsolve` calls and can pass parameters to ## Example of Numerically Solving an Equation Here is an example of numerically solving one equation: ```py >>> from sympy import cos, nsolve, Symbol >>> x = Symbol('x') >>> nsolve(cos(x) - x, x, 1) 0.739085133215161 ``` ## Guidance Overdetermined systems of equations are supported. ### Find Complex Roots of a Real Function To solve for complex roots of real functions, specify a nonreal (either purely imaginary, or complex) initial point: ```py >>> from sympy import nsolve >>> from sympy.abc import x >>> nsolve(x**2 + 2, 1) # Real initial point returns no root Traceback (most recent call last): ... ValueError: Could not find root within given tolerance. (4.18466446988997098217 > 2.16840434497100886801e-19) Try another starting point or tweak arguments. >>> from sympy import I >>> nsolve(x**2 + 2, I) # Imaginary initial point returns a complex root 1.4142135623731*I >>> nsolve(x**2 + 2, 1 + I) # Complex initial point returns a complex root 1.4142135623731*I ``` ### Ensure the Root Found is in a Given Interval It is not guaranteed that {func}`~.nsolve` will find the root closest to the initial point. Here, even though the root `-1` is closer to the initial point of `-0.1`, {func}`~.nsolve` finds the root `1`: ```py >>> from sympy import nsolve >>> from sympy.abc import x >>> nsolve(x**2 - 1, -0.1) 1.00000000000000 ``` You can ensure the root found is in a given interval, if such a root exists, using `solver='bisect'` by specifying the interval in a tuple. Here, specifying the interval `(-10, 0)` ensures that the root `-1` is found: ```py >>> from sympy import nsolve >>> from sympy.abc import x >>> nsolve(x**2 - 1, (-10, 0), solver='bisect') -1.00000000000000 ``` ### Solve a System of Equations Numerically To solve a system of multidimensional functions, supply a tuple of - functions `(f1, f2)` - variables to solve for `(x1, x2)` - starting values `(-1, 1)` ```py >>> from sympy import Symbol, nsolve >>> 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]]) ``` ### Increase Precision of the Solution You can increase the precision of the solution using `prec`: ```py >>> from sympy import Symbol, nsolve >>> 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), prec=25)) Matrix([[-1.192873099352460791205211], [1.278444111699106966687122]]) ``` ### Create a Function That Can Be Solved With SciPy As noted above, SymPy focuses on symbolic computation and is not optimized for numerical calculations. If you need to make many calls to a numerical solver, it can be much faster to use a solver optimized for numerical calculations such as SciPy's {external:func}`~scipy.optimize.root_scalar`. A recommended workflow is: 1. use SymPy to generate (by symbolically simplifying or solving an equation) the mathematical expression 2. convert it to a lambda function using {func}`~.lambdify` 3. use a numerical library such as SciPy to generate numerical solutions ```py >>> from sympy import simplify, cos, sin, lambdify >>> from sympy.abc import x, y >>> from scipy.optimize import root_scalar >>> expr = cos(x * (x + x**2)/(x*sin(y)**2 + x*cos(y)**2 + x)) >>> simplify(expr) # 1. symbolically simplify expression cos(x*(x + 1)/2) >>> lam_f = lambdify(x, cos(x*(x + 1)/2)) # 2. lambdify >>> sol = root_scalar(lam_f, bracket=[0, 2]) # 3. numerically solve using SciPy >>> sol.root 1.3416277185114782 ``` ## Use the Solution Result ### Substitute the Result Into an Expression The best practice is to use {func}`~sympy.core.evalf` to substitute numerical values into expressions. The following code demonstrates that the numerical value is not an exact root because substituting it back into the expression produces a result slightly different from zero: ```py >>> from sympy import cos, nsolve, Symbol >>> x = Symbol('x') >>> f = cos(x) - x >>> x_value = nsolve(f, x, 1); x_value 0.739085133215161 >>> f.evalf(subs={x: x_value}) -5.12757857962640e-17 ``` Using [`subs`](sympy.core.basic.Basic.subs) can give an incorrect result due to precision errors, here effectively rounding `-5.12757857962640e-17` to zero: ```py >>> f.subs(x, x_value) 0 ``` When substituting in values, you can also leave some symbols as variables: ```py >>> from sympy import cos, nsolve, Symbol >>> x = Symbol('x') >>> f = cos(x) - x >>> x_value = nsolve(f, x, 1); x_value 0.739085133215161 >>> y = Symbol('y') >>> z = Symbol('z') >>> g = x * y**2 >>> values = {x: x_value, y: 1} >>> (x + y - z).evalf(subs=values) 1.73908513321516 - z ``` ## Not all Equations Can be Solved {func}`~.nsolve` is a numerical solving function, so it can often provide a solution for equations which cannot be solved algebraically. ### Equations With no Solution Some equations have no solution, in which case SymPy may return an error. For example, the equation $e^x = 0$ (`exp(x)` in SymPy) has no solution: ```py >>> from sympy import nsolve, exp >>> from sympy.abc import x >>> nsolve(exp(x), x, 1, prec=20) Traceback (most recent call last): ... ValueError: Could not find root within given tolerance. (5.4877893607115270300540019e-18 > 1.6543612251060553497428174e-24) Try another starting point or tweak arguments. ``` ## Report a Bug If you find a bug with {func}`~.nsolve`, please post the problem on the [SymPy mailing list](https://groups.google.com/g/sympy). Until the issue is resolved, you can use a different method listed in [](#alternatives-to-consider).