使用Python

时间:2016-05-28 21:51:02

标签: python optimization scipy

我正在寻找一种有效的方法来查找区间[a,b]上函数f的所有根。 我遇到的问题是来自scipy.optimize的所有好方法要求f(a)和f(b)有不同的符号,或者我提供初始猜测x0,但在运行代码之前我对我的根一无所知

注意:函数f是平滑的(至少是C1),并且没有病态行为[没有像sin(1 / x)]。然而,它需要构建矩阵A(x)并找到其特征值,因此是耗时的。预计在[a,b]上有0到10个根,其位置完全是任意的。我不能错过任何一个(例如我不能接受100个初始猜测x0,只希望我能抓住所有根源)。

我正在考虑实施这样的事情:

  1. 使用scipy.optimize查找f的所有极值{m_1,m_2 ..,m_k} [也许是fmin,但我不知道哪种方法效率最高]:
    • 从点a [渐变算法的初始猜测]
    • 开始搜索最小m_1
    • 从m_1 + dx点开始搜索最大m_2 [强制渐变算法前进]
    • 搜索至少m_3 ...
  2. 如果两个连续的极值m_i和m_(i + 1)具有相反的符号,则在间隔[m_i,m_(i + 1)]上应用brentq以查找根。
    • 有没有更好的方法来解决这个问题?

    • 如果没有,fmin和brentq是scipy.optimize库中的最佳选择,以尽量减少对函数f的调用次数吗?

2 个答案:

答案 0 :(得分:1)

对此的一种“通常”方法是找到函数的近似值,根查找很容易,然后找到近似值的根。

例如,您可以在多个点处对函数值进行采样,使样条拟合点,然后找到样条曲线的根(这是一个简单的问题)。这将至少为根提供初步猜测。

更棘手的部分是确定采样点。如果您知道您的函数是C1,则可以根据函数值在函数显示为非平滑的点处更加密集地进行采样。几年前我需要这样做,所以这里有一种启发式烹饪方法来解决这个问题:https://gist.github.com/pv/acc71bafede0a84b074c7751985ecc6f为我工作,但YMMV。

答案 1 :(得分:0)

取决于您的功能,但可以使用SymPy以符号方式解决。这将给所有的根源。如有必要,它可以象征性地找到特征值。

找到所有极值与找到函数导数的所有根相同,所以它不会比找到所有根更容易(正如WarrenWeckesser所提到的那样)。

以数字方式查找所有根将需要使用有关该函数的知识。举个简单的例子,假设您知道根之间的最小间距。您可以尝试以递归方式对区间进行分区,并在每个区间中找到根。找到最大根数后停止。但是如果间距很小,这可能需要许多功能评估(例如,在最坏的情况下,当根有零时)。您可以施加的约束越多,您就越能减少功能评估。