我需要为一个函数实现一个根搜索算法,该算法可能有一些(不可移除的)分歧点(DP)/奇点,例如
f(x) = x**2 * np.tan(x)
问题是,通常的条件
f(x1)*f(x2) < 0
表示区间[x1, x2]
内的根不能应用于不连续函数。如果对上述函数执行此操作,算法会将 DP 识别为根。
我尝试通过此标准将 DP 与根区分开:
# assume x1, x2 as interval points identified by the f(x1)*f(x2) < 0 condition
x3 = (x1+x2)/2
f1, f2, f3 = f(x1), f(x2), f(x3)
if abs(f1-f2) < (abs(f1-f3)+abs(f2-f3))*0.9999999999999:
print("DP possibly found")
这对我来说有点麻烦(而且可能也不正确,因为这很大程度上取决于计算的精度)。我放在那里 0.9999999999999 只是为了避免可能的数字错误,但有时操作数之间的差异可能非常小。
(该标准的想法是,如果函数是非单调的,则可能存在 DP。单调性检查只是边缘处的函数值的距离应该与左侧和中心以及中心和右侧的函数值的距离之和相同我知道一些(病态的)例子可能会错误地识别DP,但我认为。 )
那么, 识别 DP 的正确/更好的方法是什么?
如果可能的话,我正在寻找一种没有外部模块(例如
sympy
)的解决方案。
I将我的测试代码发布为 MWE here (它有点长,主要是由于文档字符串)。
有一个类似的问题,但似乎没有人在那里回答得很好(接受的答案是错误的): 求函数的根但不求渐近线
确定不连续函数中根查找的发散点(DP)可能很棘手,并且通常比检查符号变化更复杂。你当前的方法(试图分析局部行为)是正确的,但是正如你所承认的,它可能很脆弱,并且高度依赖于所选的公差和函数的特定属性。
以下是你可以用来更稳健地识别 DP 的一些更强大的方法:
1. 基于导数的方法:
-
检查导数的符号变化:
在 DP 附近,函数的导数(斜率)通常会改变符号。你可以通过在当前区间
[x1, x2]
内计算几个点的导数来数值计算并检查导数的符号变化。如果检测到符号变化,则它表示 DP 的潜在存在。 - 检查导数的幅度: DP 通常表现出导数的大幅度值。设置一个阈值,如果导数的绝对值超过该阈值,则你可以将该点标记为潜在的 DP。
2. 基于极限的方法:
-
接近可疑点:
不是直接评估 DP 处的函数,而是尝试从两侧接近它。例如,如果你的区间是
[x1, x2]
,并且怀疑x2
处有一个 DP,则计算f(x2 - ε)
和f(x2 + ε)
,其中ε
是一个很小的数字。如果这两个值之间存在显著差异或趋于无穷,则它表明存在 DP。
3. 结合领域知识:
-
分析你的函数:
通常,你知道正在处理的函数类型。利用这些知识来识别潜在的 DP。例如,你知道
tan(x)
在x = (2n + 1)π/2
处有 DP,其中n
是一个整数。 - 排除已知的 DP: 如果可能,请修改你的根查找算法以排除或在已知的 DP 附近小心操作。
提高鲁棒性的技巧:
- 自适应步长: 使用自适应步长算法(如布伦特方法或 Ridders 方法),它们可以更好地处理不连续性。这些方法根据函数的行为调整搜索区间的步长大小。
- 多方法: 结合不同的方法来提高 DP 检测的置信度。例如,你可以将基于导数的检查与基于极限的方法结合起来。
你的代码示例的改进:
你的代码可以通过检查函数值是否超过某个阈值来改进,而不是依赖于差异:
import numpy as np
def has_divergence_point(f, x1, x2, threshold=1e6):
"""检查区间 [x1, x2] 内是否存在潜在的发散点。
Args:
f: 函数。
x1: 区间的下限。
x2: 区间的上限。
threshold: 用于检测发散的阈值。
Returns:
如果检测到发散点,则为 True,否则为 False。
"""
x3 = (x1 + x2) / 2
f1, f2, f3 = f(x1), f(x2), f(x3)
return (
np.abs(f1) > threshold
or np.abs(f2) > threshold
or np.abs(f3) > threshold
)
# 示例用法
def f(x):
return x**2 * np.tan(x)
x1 = 1.0
x2 = 3.0
if has_divergence_point(f, x1, x2):
print(f"区间 [{x1}, {x2}] 中可能存在一个发散点。")
else:
print(f"区间 [{x1}, {x2}] 中没有找到发散点。")
请记住,没有一种方法可以保证在所有情况下都能完美地检测到 DP。为你的特定问题和函数选择最合适的方法的组合至关重要。
标签:python,math,numerical-methods From: 78840039