Difference between revisions of "Python:Finding roots"
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
== Introduction == | == Introduction == | ||
− | The SciPy package [https://docs.scipy.org/doc/scipy-1.1.0/reference/optimize.html scipy.optimize] has several routines for finding roots of equations. This document is going to focus on the [https://docs.scipy.org/doc/scipy-1.1.0/reference/generated/scipy.optimize.brentq.html#scipy.optimize.brentq brentq] function for finding the root of a single-variable continuous function. The function can only find one root at a time and it requires brackets for the root. For open root-finding, use [https://docs.scipy.org/doc/scipy-1.1.0/reference/generated/scipy.optimize. | + | The SciPy package [https://docs.scipy.org/doc/scipy-1.1.0/reference/optimize.html scipy.optimize] has several routines for finding roots of equations. This document is going to focus on the [https://docs.scipy.org/doc/scipy-1.1.0/reference/generated/scipy.optimize.brentq.html#scipy.optimize.brentq brentq] function for finding the root of a single-variable continuous function. The function can only find one root at a time and it requires brackets for the root. For open root-finding, use [https://docs.scipy.org/doc/scipy-1.1.0/reference/generated/scipy.optimize.root.html#scipy.optimize.root root]. All the options below for <code>brentq</code> work with <code>root</code>, the only difference is instead of giving a left and right bracket you give a single initial guess. |
All of the examples assume that | All of the examples assume that | ||
<syntaxhighlight lang=python> | <syntaxhighlight lang=python> | ||
import numpy as np | import numpy as np | ||
− | import scipy. | + | import scipy.optimize as opt |
</syntaxhighlight> | </syntaxhighlight> | ||
have been called. | have been called. | ||
Line 53: | Line 53: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | == Multiple-Variable Functions == | + | == Alternate Calls for Multiple-Variable Functions == |
If you have a function with multiple variables, first remember that all the other variables need to have known values. For example, if you have <math>f(x,y)=\cos(x)+\sin(y)</math>, and you want to know where <math>f(x,y)=0</math>, you need to know either <math>x</math> or <math>y</math>. | If you have a function with multiple variables, first remember that all the other variables need to have known values. For example, if you have <math>f(x,y)=\cos(x)+\sin(y)</math>, and you want to know where <math>f(x,y)=0</math>, you need to know either <math>x</math> or <math>y</math>. | ||
=== Unknown as first parameter in function call === | === Unknown as first parameter in function call === | ||
− | Imagine you want to | + | Imagine you want to find <math>x</math> when <math>y</math> is 2.5 radians - you can solve this the following ways: |
==== On the fly ==== | ==== On the fly ==== | ||
Line 81: | Line 81: | ||
=== Unknown not first parameter in function call === | === Unknown not first parameter in function call === | ||
− | Now imagine you want to | + | Now imagine you want to find <math>y</math> when <math>x</math> is 2 - you have to create a lambda function for that, either on the fly or based on the defined function: |
==== On the fly ==== | ==== On the fly ==== | ||
<syntaxhighlight lang=python> | <syntaxhighlight lang=python> | ||
− | yval = opt.brentq(lambda | + | yval = opt.brentq(lambda y: np.cos(2) + np.sin(y), 0, 1) |
</syntaxhighlight> | </syntaxhighlight> | ||
Latest revision as of 13:09, 9 November 2021
Contents
Introduction
The SciPy package scipy.optimize has several routines for finding roots of equations. This document is going to focus on the brentq function for finding the root of a single-variable continuous function. The function can only find one root at a time and it requires brackets for the root. For open root-finding, use root. All the options below for brentq
work with root
, the only difference is instead of giving a left and right bracket you give a single initial guess.
All of the examples assume that
import numpy as np
import scipy.optimize as opt
have been called.
Most General Case
The following examples show a method that will work regardless of how many input variables your function has or how you define your function - whether it is a built-in or user-defined function. The paradigm is:
ROOT = opt.brentq(lambda DUMMY_VAR: FUNCTION_THING, LEFT_BRACKET, RIGHT_BRACKET)
where
- ROOT is the calculated value of the requested variable when the function is 0
- DUMMY_VAR is the variable you want to use in this FUNCTION_THING to indicate which of the various inputs
brentq
is allowed to alter - LEFT_BRACKET and RIGHT_BRACKET are values of DUMMY that bracket the root - that is, where FUNCTION_THING has different signs
- Note that
brentq
can only find one root at a time, so you cannot load the brackets with several values and try to havebrentq
find multiple results; for that, you need loops
- Note that
- FUNCTION_THING can be a built-in function, a user-defined function, or a calculation - whatever it is that you are trying to set equal to zero; note that DUMMY_VAR must appear somewhere in this expression for
brentq
to be able to do anything.
Example
If you want to solve \(f(x)=(x+4)(x-1)=x^2+3x-4=0\) for instance, you have several options:
Function on the Fly
If you only want to solve this problem a couple times, and the calculation only requires one line of code, the process with the least "overhead" involves creating the function on the fly inside the brentq
command. All you have to do is put your expression in for the FUNCTION_THING, making sure the DUMMY_VAR is appropriately used - you can use a lambda function
for that:
r1 = opt.brentq(lambda x: x**2+3*x-4, -5, -3)
r2 = opt.brentq(lambda x: x**2+3*x-4, 0, 3)
where -5 and -3 were chosen since they bracket the root at -4 and 0 and 3 were chosen since they bracket the root at 1.
Defined Functions
If you are going to solve roots multiple times, you may want to define a function and then call it using a lambda function:
def fun(x):
return x**2+3*x-4
r1 = opt.brentq(lambda xi: fun(xi), -4, -2)
r2 = opt.brentq(lambda xi: fun(xi), 0, 3)
Note that the dummy variable xi
could have been an x here.
Alternate Calls for Single-Variable Functions
If you have a function that takes a single variable, there is a slightly simpler way to run brentq
- all you need to do is give the name of the function to FUNCTION_THING rather than setting up the DUMMY_VAR:
def fun(x):
return x**2+3*x-4
r1 = opt.brentq(fun, -4, -2)
r2 = opt.brentq(fun, 0, 3)
Alternate Calls for Multiple-Variable Functions
If you have a function with multiple variables, first remember that all the other variables need to have known values. For example, if you have \(f(x,y)=\cos(x)+\sin(y)\), and you want to know where \(f(x,y)=0\), you need to know either \(x\) or \(y\).
Unknown as first parameter in function call
Imagine you want to find \(x\) when \(y\) is 2.5 radians - you can solve this the following ways:
On the fly
xval = opt.brentq(lambda x: np.cos(x) + np.sin(2.5), 0, np.pi)
Defined function
def fun2(x,y):
return np.cos(x)+np.sin(y)
xval = opt.brentq(lambda x: fun2(x, 2.5), 0, np.pi)
or, since the variable you are solving for is first, you can give brentq
a tuple with the 2nd (and beyond) variable values:
def fun2(x,y):
return np.cos(x)+np.sin(y)
xval = opt.brentq(fun2, 0, np.pi, args=(2.5,)) # formally
xval = opt.brentq(fun2, 0, np.pi, 2.5) # less formally since the args positionally come after the right bracket
Unknown not first parameter in function call
Now imagine you want to find \(y\) when \(x\) is 2 - you have to create a lambda function for that, either on the fly or based on the defined function:
On the fly
yval = opt.brentq(lambda y: np.cos(2) + np.sin(y), 0, 1)
Defined Function
def fun2(x,y):
return np.cos(x)+np.sin(y)
yval = opt.brentq(lambda y: fun2(2, y), 0, 1)
Questions
Post your questions by editing the discussion page of this article. Edit the page, then scroll to the bottom and add a question by putting in the characters *{{Q}}, followed by your question and finally your signature (with four tildes, i.e. ~~~~). Using the {{Q}} will automatically put the page in the category of pages with questions - other editors hoping to help out can then go to that category page to see where the questions are. See the page for Template:Q for details and examples.
External Links
References