求具有 python 的超越方程的根
Find root of a transcendental equation with python
我要解下面的超越方程
cos(x)/x=c
对于给定常数 c.
例如我在 Mathematica 中做了一个简短的代码,在那里我为常量 c
生成了一个随机值列表
const = Table[RandomReal[{0, 5}], {i, 1, 10}]
(*{1.67826, 0.616656, 0.290878, 1.10592, 0.0645222, 0.333932, 3.59584, \
2.70337, 3.91535, 2.78268}*)
比我定义的函数
f[x_, i_] := Cos[x]/x - const[[i]]
并开始寻找根源:
Table[FindRoot[f[x, i] == 0, {x, 0.1}][[1, 2]], {i, 1, Length[const]}]
(*{0.517757, 0.947103, 1.21086, 0.694679, 1.47545, 1.16956, 0.26816, \
0.347764, 0.247615, 0.338922}*)
现在我很想在 python 中编写类似的程序(可能使用 numpy?),但我真的找不到任何现有的解决此类问题的好方法。有人可以帮忙吗?
你可以用 sympy
:
>>> from sympy import cos, Symbol, nsolve
>>> x = Symbol('x')
>>> consts = [random.random() for _ in range(10)]
>>> [nsolve(cos(x)/x - c, x, 1) for c in consts]
[mpf('0.89659506789294669'),
mpf('0.96201114853313738'),
mpf('0.74186728791161379'),
mpf('1.1720944924353926'),
mpf('0.92953351945607071'),
mpf('0.96626530553984035'),
mpf('1.4270719610604761'),
mpf('0.85968954499458035'),
mpf('0.86682911058530746'),
mpf('0.91591678333479274')]
我过去实现此目的的一种方法是使用 scipy.optimize.minimize
求平方函数的最小值。
from scipy.optimize import minimize
from numpy import cos
def opt_fun(x, c):
return (cos(x)/x - c)**2
const = 1.2
res = minimize(lambda x: opt_fun(x, const), x0=0.001)
# Check if the optimization was successful
print(res.success)
# >> True
# Extract the root from the minimization result
print(res.x[0])
# >> 0.65889256782472172
这绝不是万无一失的,但可以快速准确。例如,如果有多个根,minimize
将从您 select 的初始点找到 'downhill direction' 中的那个,这就是为什么我在上面选择了一个小的正值。
另一个需要注意的问题是数量级截然不同的数字,这对于最小化问题总是如此。在您的等式中,随着 c
变得非常大,第一个正根变得非常小。如果您最终试图在这种情况下找到根,您可能需要将两个 x
缩放到接近 1 以获得准确的结果 ()。
对于这种简单的单变量函数,您可以使用 Chebfun 的 python 实现轻松找到感兴趣区间内的所有根。我知道有两个 Chebpy and pychebfun,它们都非常好。
例如,使用 Chebpy,可以执行以下操作以在区间 [0.5, 12]
:
中找到 cos(x)/x - 0.05
的根
from chebpy import chebfun
x = chebfun('x', [0.5, 12])
c = 0.05
f = np.cos(x)/x - c
rts = f.roots()
print(rts)
[ 1.4959 4.9632 7.4711 11.6152]
或者,您可以使用 root
:
import numpy as np
from scipy.optimize import root
def func_cos(x, c):
return np.cos(x) / x - c
crange = range(1, 11)
res = [root(func_cos, 0.5, args=(ci, )).x[0] for ci in crange]
然后res
看起来如下:
[0.73908513321516056,
0.45018361129487355,
0.31675082877122118,
0.24267468064089021,
0.19616428118784215,
0.16441893826043114,
0.14143076140757282,
0.12403961812459068,
0.11043425911223313,
0.099505342687387879]
如果您对使用 root
求解方程组感兴趣,您可以查看 。
我要解下面的超越方程
cos(x)/x=c
对于给定常数 c.
例如我在 Mathematica 中做了一个简短的代码,在那里我为常量 c
生成了一个随机值列表const = Table[RandomReal[{0, 5}], {i, 1, 10}]
(*{1.67826, 0.616656, 0.290878, 1.10592, 0.0645222, 0.333932, 3.59584, \
2.70337, 3.91535, 2.78268}*)
比我定义的函数
f[x_, i_] := Cos[x]/x - const[[i]]
并开始寻找根源:
Table[FindRoot[f[x, i] == 0, {x, 0.1}][[1, 2]], {i, 1, Length[const]}]
(*{0.517757, 0.947103, 1.21086, 0.694679, 1.47545, 1.16956, 0.26816, \
0.347764, 0.247615, 0.338922}*)
现在我很想在 python 中编写类似的程序(可能使用 numpy?),但我真的找不到任何现有的解决此类问题的好方法。有人可以帮忙吗?
你可以用 sympy
:
>>> from sympy import cos, Symbol, nsolve
>>> x = Symbol('x')
>>> consts = [random.random() for _ in range(10)]
>>> [nsolve(cos(x)/x - c, x, 1) for c in consts]
[mpf('0.89659506789294669'),
mpf('0.96201114853313738'),
mpf('0.74186728791161379'),
mpf('1.1720944924353926'),
mpf('0.92953351945607071'),
mpf('0.96626530553984035'),
mpf('1.4270719610604761'),
mpf('0.85968954499458035'),
mpf('0.86682911058530746'),
mpf('0.91591678333479274')]
我过去实现此目的的一种方法是使用 scipy.optimize.minimize
求平方函数的最小值。
from scipy.optimize import minimize
from numpy import cos
def opt_fun(x, c):
return (cos(x)/x - c)**2
const = 1.2
res = minimize(lambda x: opt_fun(x, const), x0=0.001)
# Check if the optimization was successful
print(res.success)
# >> True
# Extract the root from the minimization result
print(res.x[0])
# >> 0.65889256782472172
这绝不是万无一失的,但可以快速准确。例如,如果有多个根,minimize
将从您 select 的初始点找到 'downhill direction' 中的那个,这就是为什么我在上面选择了一个小的正值。
另一个需要注意的问题是数量级截然不同的数字,这对于最小化问题总是如此。在您的等式中,随着 c
变得非常大,第一个正根变得非常小。如果您最终试图在这种情况下找到根,您可能需要将两个 x
缩放到接近 1 以获得准确的结果 (
对于这种简单的单变量函数,您可以使用 Chebfun 的 python 实现轻松找到感兴趣区间内的所有根。我知道有两个 Chebpy and pychebfun,它们都非常好。
例如,使用 Chebpy,可以执行以下操作以在区间 [0.5, 12]
:
cos(x)/x - 0.05
的根
from chebpy import chebfun
x = chebfun('x', [0.5, 12])
c = 0.05
f = np.cos(x)/x - c
rts = f.roots()
print(rts)
[ 1.4959 4.9632 7.4711 11.6152]
或者,您可以使用 root
:
import numpy as np
from scipy.optimize import root
def func_cos(x, c):
return np.cos(x) / x - c
crange = range(1, 11)
res = [root(func_cos, 0.5, args=(ci, )).x[0] for ci in crange]
然后res
看起来如下:
[0.73908513321516056,
0.45018361129487355,
0.31675082877122118,
0.24267468064089021,
0.19616428118784215,
0.16441893826043114,
0.14143076140757282,
0.12403961812459068,
0.11043425911223313,
0.099505342687387879]
如果您对使用 root
求解方程组感兴趣,您可以查看