[英]Minimize a function
假设给定一个单一变量的 function 和 arguments a 和 b,并被要求找到 function 在区间 [a, b] 上的最小值。 (您可以假设参数是双精度的,尽管在我的应用程序中我可能需要使用任意精度的库。)
一般来说,这是一个难题,因为函数可能很奇怪。 这个问题的一个简单版本是最小化 function 假设它是连续的(没有间隙或跳跃)和单峰(有一个唯一的最小值;在最小值的左侧,function 正在减小,在右侧它是增加)。 有没有一种好方法可以解决这个更容易(但可能并不容易?)的问题?
假设 function 可能难以计算,但存储您计算的答案并不是特别昂贵。 (显然,最好不要制作巨大的键/值对 arrays。)
在幸运的情况下改进算法的好点子很好(例如:导数存在,function 是平滑/解析的,导数可以以封闭形式计算,在评估 function 时可以免费计算导数) .
您描述的版本只有一个最小值,很容易解决。
这个想法是这样的。 假设我有 3 个点, a < b < c
和f(b) < f(a)
和f(b) < f(c)
。 那么真正的最小值在a
和c
之间。 此外,如果我在区间的某处选择另一个点d
,那么我可以丢弃a
或d
中的一个,并且仍然有一个中间有真正最小值的区间。 随着我进行更多迭代,我的近似值将呈指数级快速提高。
我们还没有完全从这个开始。 我们从 2 点开始, a
和b
,并且知道答案在中间的某个地方。 取中点。 如果f
低于端点,我们就进入了我上面讨论的情况。 否则,它必须低于端点之一,高于另一个端点。 我们可以丢弃更高的端点并重复。
如果 function 很好,即单峰且严格单调(即严格地从最小值的左侧减少并严格地向右增加),那么您可以通过二进制搜索找到最小值:
x = (ba)/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
时停止。
请注意,在您对 function f 的行为一无所知的一般情况下,无法确定 f 的重要属性。 好吧,除非您愿意尝试所有可能的输入。 有关详细信息,请参阅赖斯定理。
Boost 项目有一个可能有用的Brent 算法的实现。 似乎假设 function 是连续的,并且在输入间隔中没有最大值(只有最小值)。
不是直接的答案,而是指向更多阅读的指针:
对于 function 可微分两次(并且两个导数可以轻松计算)的特殊情况,可以使用 牛顿法进行优化,即基本上找到一阶导数的根(这是最小值的必要条件)。
关于一般情况,请注意“奇怪”的极端情况是 function,它在任何地方都是连续的,并且即使不是不可能找到最小值也非常困难(在有限时间内)。 所以我想你应该至少对你试图最小化的 function 做出一些假设。
您想要的是优化单峰 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]
这可以自己给出一个算法,但是有一个很好的技巧涉及黄金比例,它允许你重用中间值(在某种程度上你只需要计算 f 每次迭代而不是两次)
如果您有 function 的表达式,则有基于区间分析的全局优化算法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.