跳转到主要内容

纯Python单变量函数求解器

项目描述

image

pyroots

摘要

一个Python库,实现了单变量函数的各种根查找方法。

目前实现了以下方法

  • 二分法。
  • Ridders方法。
  • Brent方法。

关于Brent方法,有两种实现,第一个使用逆二次外推(Brentq),而另一个使用双曲外推(Brenth)。

如果您不知道使用哪种方法,您可能应该使用Brentq。但话说回来,Bisect方法安全但速度慢(即迭代次数多)。

示例

# define the function whose root you are searching
def f(x, a):
    return x ** 2 - a + 1

# Create the Solver object (instead of Brentq you could also import Brenth/Ridder/Bisect)
from pyroots import Brentq
brent = Brentq(epsilon=1e-5)

# solve the function in `[-3, 0]` while `a` is equal to 2
result = brent(f, -3, 0, a=2)
print(result)

将输出

 converged : True
   message : Solution converged.
iterations :   6
func calls :   9
        x0 :    -1.0000000748530762
      xtol :     0.0000000000000002
     f(x0) :     0.0000001497061579
   epsilon :     0.0000100000000000
   x_steps : [-3, 0, -0.3333333333333333, -1.6666666666666665, -0.7777777777777779, -1.0686868686868687, -0.9917335278385606, -0.9997244260982788, -1.0000000748530762]
  fx_steps : [8, -1, -0.8888888888888888, 1.7777777777777772, -0.3950617283950615, 0.14209162330374459, -0.01646460976088293, -0.0005510718624670563, 1.4970615791476405e-07]

理由

pyroots的功能已经在scipy中实现,所以自然会问,为什么还要重新发明轮子?

主要原因在于scipy是一个庞大的依赖。而Pyroots只是一个简单的包,可以轻松安装,并且可以轻松地与py2exe或类似的项目捆绑在一起。甚至不需要安装,只需将pyroots文件夹放入你的项目,你就可以开始使用了。

除此之外,scipy函数所使用的API并不是非常用户友好。例如,你不能为你的函数使用关键字参数。此外,在scipy中,没有可靠的方式来定义你希望获得的根的位数精度。例如,你可能要求6位数字,但scipy可能会计算多达14(或12或更多)位数字。这个“故障”的主要影响是,scipy的方法可能会比实际需要的次数更多地进行函数评估。如果函数计算的是一些简单的东西,比如以下示例中的函数,那么这些额外的函数调用并不是什么大问题,但如果你的函数需要花费大量时间来评估,比如超过几秒钟,那么这可能会很快变得令人烦恼,甚至简单到无法接受,比如函数需要几分钟才能返回一个值。

安装

使用pip

pip install pyroots

使用

所有求解器共享相同的API,因此你可以轻松地在各种方法之间切换。

函数

你正在寻找根的函数必须至少接受一个参数并返回一个单一的数字。这个第一个参数也是依赖变量,除此之外,函数还可以接受任意数量的位置/关键字参数。例如,以下函数是完全有效的

def f(x, a):
    return x ** 2 - a + 1

def g(x, a, b, c=3):
    return x ** 2 + a ** b - c

求解器对象

首先,你需要为你要使用的方法创建一个Solver对象

from pyroots import Brentq

brent = Brentq()

当你创建Solver对象时,你可以指定几个会影响收敛性的参数。其中最重要的是

  • epsilon指定了在检查收敛性时要考虑的位数数量。默认值为1e-6
  • raise_on_fail如果收敛失败则会引发异常。默认值为True。

使用上述函数定义,为了找到f的根,你必须首先定义一个包含根的区间。假设这个区间被定义为[xa, xb]。在这种情况下,你会这样调用求解器

def f(x, a):
    return x ** 2 - a + 1

solver = Brentq()
result = solver(f, xa, xb, a=3)

结果对象

所有方法都返回一个具有以下属性的Result对象

result.x0               # the root
result.fx0              # the value of ``f(x0)`
result.convergence      # True/False
result.iterations       # the number of iterations
result.func_calls       # the number of function evaluations.
result.msg              # a descriptive message regarding the convergence (or the failure of convergence)
result.x_steps          # a list containing the x values  that have been tried while the solver run
result.fx_steps         # a list containing the f(x) values that have been calculated while the solver run

如果由于某种原因无法达到收敛,则会引发一个ConvergenceError。如果你不希望发生这种情况,那么你必须将False作为raise_on_fail参数的值。

def f(x):
    return x ** 2 - 1

result = brent(f, xa=-10, xb=-5, raise_on_fail=False)
print(result)

API

每个求解器工厂都有以下签名

SolverFactory(epsilon=1e-6, xtol=EPS, max_iter=500, raise_on_fail=True, debug_precision=10)

其中

  • epsilon是所需解的精度,即当|f(x0)|小于epsilon时,即达到了解。
  • max_iter是允许的最大迭代次数。
  • raise_on_fail是一个布尔标志,表示是否在收敛失败时引发异常。默认值为True。

每个求解器对象都有以下签名

solver_object(f, xa, xb, *args, **kwargs)

其中

  • f是我们正在寻找根的函数。
  • xa是我们正在寻找的解区间的下限。
  • xb是我们正在寻找的解区间的上限。
  • *args在评估f时作为位置参数传递。
  • **kwargs在评估f时作为关键字参数传递。

文档

目前,文档尚未准备就绪,但README中的示例应该足以让你入门。

pyroots的源代码仓库可以在以下位置找到:https://github.com/pmav99/pyroots

欢迎反馈和贡献。

pmav99 <gmail>

https://www.embeddedrelated.com/showarticle/855.php

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分布

pyroots-0.5.0.tar.gz (14.0 kB 查看哈希值)

上传时间 源代码

构建分布

pyroots-0.5.0-py2.py3-none-any.whl (18.0 kB 查看哈希值)

上传时间 Python 2 Python 3

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面