假设您被赋予单个变量和参数a和b的函数,并被要求查找函数在区间[a,b]上采用的最小值。 (您可以假设参数是双精度的,但在我的应用程序中,我可能需要使用任意精度库。)
一般来说,这是一个难题,因为功能可能很奇怪。这个问题的简单版本是假设它是连续(没有间隙或跳跃)和单峰(有一个独特的最小值;对于左边的函数正在递减,而右边的函数正在递增)。有没有一种好方法可以解决这个问题(但也许并不容易!)?
假设该函数可能难以计算,但存储您计算的答案并不是特别昂贵。 (显然,如果你不必制作巨大的键/值对数组,那就更好了。)
关于在幸运案例中改进算法的好主意的好处(例如:导数存在,函数是平滑/解析,导数可以以封闭形式计算,导数可以在函数时免费计算)评估)。
答案 0 :(得分:3)
您描述的版本只有一个最小值,很容易解决。
这个想法是这样的。假设我有a < b < c
和f(b) < f(a)
以及f(b) < f(c)
的3分。然后,真正的最小值介于a
和c
之间。此外,如果我在区间中的某处选择另一个点d
,那么我可以丢弃a
或d
中的一个,并且仍然具有中间的真实最小值的间隔。随着我进行更多迭代,我的近似值将以指数方式快速提高。
我们并没有从这开始。我们从2分开始,a
和b
,并且知道答案在中间某处。以中点为中心。如果f
低于终点,我们将讨论上面讨论过的情况。否则它必须低于其中一个端点,并且高于另一个端点。我们可以扔掉更高端的点并重复。
答案 1 :(得分:2)
如果函数很好,即单峰和严格单调(即严格减小到最小值的左边并严格增加到右边),那么你可以通过二分搜索找到最小值:
x = (b-a)/2
x
是否在最小值或左侧x
剩下最小值:b = x
x
符合最低要求:a = x
x
要测试x
是否为最小值的左/右,请创建一个小值epsilon
并检查f(x - epsilon) < f(x + epsilon)
是否为delta
。如果是,则最小值在左侧,否则在右侧。 “直到你感到无聊”,我的意思是:发明另一个小值fabs(f(x - epsilon) - f(x + epsilon)) < delta
并在{{1}}时停止。
请注意,在一般情况下,您对函数f的行为一无所知,因此无法确定f的非平凡属性。好吧,除非你愿意尝试所有可能的输入。有关详细信息,请参阅http://en.wikipedia.org/wiki/Rice%27s_theorem处的Rice定理(因此,我们不会将此识别为URL)。
答案 2 :(得分:1)
Boost项目的Brent's algorithm实现可能很有用。 它似乎假设函数是连续的,并且在输入间隔中没有最大值(仅最小值)。
答案 3 :(得分:1)
不是直接答案,而是指向更多阅读的指针:
对于函数可微分两次的特殊情况(并且可以轻松计算两个导数),可以使用Newton's method for optimization,即基本上找到一阶导数的根(这是一个必要条件)最小值)。
关于一般情况,请注意“怪异”的极端情况是continuous nowhere的函数,并且如果不是不可能找到最小值(在有限时间内)是非常困难的。所以我想你应该尝试至少对你试图最小化的函数做出一些假设。
答案 4 :(得分:1)
您想要的是优化Unimodal function。正确的算法类似于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]
这可以给出一个算法本身,但是有一个很好的trick涉及黄金比例,它允许你重用中间值(在某种程度上你只需要每次迭代计算一次f而不是两次)
答案 5 :(得分:0)
如果您有该函数的表达式,则存在基于区间分析的全局优化算法。