是否有任何用于顺序非线性优化的库,包括上限和下限,以及不等式约束,这些库是用Haskell编写的,或者可以从Haskell中轻松调用?
答案 0 :(得分:6)
bindings-levmar包提供了对C Levenberg-Marquardt优化器的绑定。
答案 1 :(得分:4)
Hackage的快速grep表明nonlinear-optimization是最好的(唯一的)已写的东西;但是,它似乎没有包含有限优化的任何内容。
你最好的选择似乎是其中之一(按增加吸引力的顺序):
答案 2 :(得分:2)
我知道OP要求一个通用的优化库,我的经验是:
此外,所有提到的软件包似乎都没有任何真实的文档。
幸运的是,对于简单的问题,简单的解决方案就足够了。如果要优化具有单个括号极值但不知道梯度函数的一维,平滑和凸函数(请参见下面的 1 ),则可以使用简单的方法,例如Golden Section搜索即可。
翻译自Wikipedia page:
import Data.Maybe (fromMaybe)
-- 1 / phi
invphi = (sqrt 5 - 1) / 2
-- 1 / phi^2
invphi2 = (3 - sqrt 5) / 2
-- | Enable optional arguments syntax. Use with Maybe a as parameter type, then in the function write param // defaultValue
(//) :: Maybe a -> a -> a
(//) = flip fromMaybe
-- Just a wrapper function because of all the ugly Nothing's of the recursive function
goldenSectionSearch f a b tolerance = goldenSectionSearchRecursive f a b tolerance Nothing Nothing Nothing Nothing Nothing
-- | Golden section search, recursive.
-- Given a function f with a single local maximum in the interval [a, b], golden section search returns a subset interval [c, d] that contains the maximum with d-c <= tolerance
-- Taken from the python implementation at https://en.wikipedia.org/wiki/Golden-section_search
goldenSectionSearchRecursive ::
(Double -> Double) -- ^ Function with a single maximum in [a, b]
-> Double -- ^ One side of the interval
-> Double -- ^ Other side of the interval
-> Double -- ^ Tolerance
-> Maybe Double -- ^ h, Current search interval
-> Maybe Double -- ^ c, New left interval point. If Nothing, a new point is chosen.
-> Maybe Double -- ^ d, New right interval point.
-> Maybe Double -- ^ f(c), Function value at c
-> Maybe Double -- ^ f(d), Function value at d
-> (Double, Double) -- ^ The interval in which the maximum is
goldenSectionSearchRecursive f a' b' tolerance h' c' d' fc' fd'
| h < tolerance = (a, b)
| fc > fd = goldenSectionSearchRecursive f a d tolerance (Just (h * invphi)) Nothing (Just c) Nothing (Just fc)
| otherwise = goldenSectionSearchRecursive f c b tolerance (Just (h * invphi)) (Just d) Nothing (Just fd) Nothing
where
a = min a' b'
b = max a' b'
h = h' // (b - a)
c = c' // (a + invphi2 * h)
d = d' // (a + invphi * h)
fc = fc' // f c
fd = fd' // f d
,然后使用goldenSectionSearch (\x -> -(x-2)^2) 1 5 1e-5
进行调用,返回(1.9999959837979107,2.0000050911830893)
。手动解决这个简单的功能当然会容易得多,但这只是一个例子。
PS黄金分割搜索的有趣之处在于它的收敛速度是确切已知的:在每次迭代中,最优驻留时间间隔的长度除以黄金分割率。
我把它放在GitHub
上[1]请注意,如果您知道梯度函数,则将其等于零并应用求根方法通常会快得多。例如,在一个维度上,威尔·尼斯(Will Ness)指出了his answer,该方法具有比黄金分割搜索更快的收敛速度的简单方法。 当然,您也可以使用上述需要梯度功能的软件包之一。