用python找出超越方程的根

时间:2017-03-27 13:12:44

标签: python numpy numeric transcendental-equation

我必须解决以下超越方程

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?)但我真的找不到像这样的问题的任何好的现有答案。有人可以帮忙吗?

4 个答案:

答案 0 :(得分:4)

我过去实现这一目标的一种方法是使用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会在下坡方向找到一个'从您选择的初始点开始,我选择了一个小的正值。

另一个需要注意的问题是,最小化问题总是如此,这个数字的数量级差别很大。在你的等式中,当c变得非常大时,第一个正根变得非常小。如果你最终试图在这种情况下寻找根源,你可能需要将x缩放到接近1才能获得准确的结果(an example here)。

答案 1 :(得分:4)

或者,您可以使用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求解方程组,可以查看this answer

答案 2 :(得分:2)

对于这种简单的单变量函数,您可以使用Chebfun的python实现轻松找到感兴趣区间内的所有根。我知道有两个,Chebpypychebfun,它们都非常出色。

例如,使用Chebpy,可以执行以下操作,在cos(x)/x - 0.05区间内找到[0.5, 12]的根:

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]

enter image description here

答案 3 :(得分:1)

您可以使用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')]