Algorithm 最小化函数

Algorithm 最小化函数,algorithm,math,language-agnostic,Algorithm,Math,Language Agnostic,假设给您一个单变量函数和参数a和b,并要求您查找该函数在区间[a,b]上的最小值。(您可以假设参数是双精度的,但在我的应用程序中,我可能需要使用任意精度的库。) 一般来说,这是一个困难的问题,因为函数可能很奇怪。这个问题的一个简单版本是最小化函数,假设它是连续的(没有间隙或跳跃)和单峰的(有一个唯一的最小值;在最小值的左边函数是递减的,在右边函数是递增的)。有没有好办法解决这个更容易(但可能不容易)的问题 假设函数可能很难计算,但存储已计算的答案并不特别昂贵。(显然,如果不必制作巨大的键/值对数

假设给您一个单变量函数和参数a和b,并要求您查找该函数在区间[a,b]上的最小值。(您可以假设参数是双精度的,但在我的应用程序中,我可能需要使用任意精度的库。)


一般来说,这是一个困难的问题,因为函数可能很奇怪。这个问题的一个简单版本是最小化函数,假设它是连续的(没有间隙或跳跃)和单峰的(有一个唯一的最小值;在最小值的左边函数是递减的,在右边函数是递增的)。有没有好办法解决这个更容易(但可能不容易)的问题

假设函数可能很难计算,但存储已计算的答案并不特别昂贵。(显然,如果不必制作巨大的键/值对数组,效果会更好。)


在幸运的情况下(例如:存在导数,函数是平滑的/解析的,导数可以以闭合形式计算,在计算函数时可以免费计算导数),改进算法的好主意的奖励积分。

如果你有函数的表达式,有基于区间分析的全局优化算法。

Boost项目有一个可能有用的实现。
它似乎假设函数是连续的,并且在输入间隔内没有最大值(只有最小值)。

不是直接答案,而是指向更多读数的指针:

  • scipy.optimize:
  • naglib第e04节:
对于函数可微两次的特殊情况(两个导数可以很容易地计算),可以使用,即基本上求一阶导数的根(这是求最小值的必要条件)


关于一般情况,请注意“怪异”的极端情况是一个函数,如果不是不可能的话,很难找到最小值(在有限时间内)。所以我想你应该试着至少对你试图最小化的函数做一些假设。

你描述的版本,只有一个最小值,很容易解决

想法是这样的。假设我有3个点,分别是
a
f(b)
f(b)
。那么真正的最小值在
a
c
之间。此外,如果在区间中的某个地方选择了另一个点<代码> d>代码>,那么我可以扔掉一个<代码> a < /> >或<代码> d>代码>,中间还有一个与真最小值的间隔。随着迭代次数的增加,我的近似值将以指数级的速度提高


我们不是从这个开始的。我们从2个点开始,<代码> a <代码> >代码> b <代码>,并且知道答案在中间。以中点为例。如果
f
在端点以下,我们进入了我上面讨论的案例。否则,它必须低于一个端点,高于另一个端点。我们可以扔掉较高的端点并重复。

如果函数很好,即单峰且严格单调(即严格减少到最小值的左侧,严格增加到右侧),则可以通过二进制搜索找到最小值:

  • 设置
    x=(b-a)/2
  • 测试
    x
    是在最小值的右侧还是左侧
  • 如果
    x
    在最小值的左边:
    b=x
  • 如果
    x
    在最小值的右边:
    a=x
  • 从头开始重复,直到感到厌烦为止
  • 最小值为
    x
要测试
x
是否为最小值的左/右,请创建一个小值
epsilon
,并检查
f(x-epsilon)
。如果是,最小值在左边,否则在右边。“直到你感到厌烦”,我的意思是:发明另一个小值
delta
,如果
fabs(f(x-epsilon)-f(x+epsilon))
停止



请注意,在一般情况下,如果您对函数f的行为一无所知,则不可能确定f的非平凡属性。除非你愿意尝试所有可能的输入。有关详细信息,请参阅。

您想要的是优化一个。正确的算法与btilly的类似,但您需要额外的点数

Take 4 points a < b < c < d.
We want to minimize f in [a,d].

If f(b) < f(c) we know the minimum is in [a, c]
If f(b) > f(c) "  "    "   "       is in [b, d]
取4分af(c)“”在[b,d]中

这本身就可以给出一个算法,但是有一个很好的黄金比率,它允许您重用中间值(在某种程度上,您只需要在每次迭代中计算f一次,而不是两次)

“函数在最小值的左侧递减”-我不认为这是最小值,那么,@Greg:每个函数都在最小值的左边递减。(当x向右移动时,它会减小。)@Greg Hewgill:值会减小,直到达到最小值,然后再增大。你现在回头看它(不可否认,可能是因为我描述它的方式)。Mathematica没有解决大部分问题吗?@linuxuser27:函数的封闭形式可以给出,也可以不给出。如果不是,符号算法就不适用,只有数值算法。我不适用。我有一个黑匣子,当我给它参数时,它会给我值。这些假设在我最初的问题中,并且非常强:函数是连续的和单峰的。OP将他的帖子标记为“语言不可知”…但OP仍然欣赏工作代码作为示例。在这种情况下,算法需要一本文字书来描述,而且实现起来太费劲了(不能按原样使用,我需要任意精度)。幸运的是,我确实了解函数的相关知识,否则,正如您所建议的那样,这将是毫无希望的。谢谢你的回答,太好了。现在我看了一下,我认为这是t