用于haskell中顺序非线性优化的库?

时间:2012-07-12 18:51:05

标签: haskell nonlinear-optimization

是否有任何用于顺序非线性优化的库,包括上限和下限,以及不等式约束,这些库是用Haskell编写的,或者可以从Haskell中轻松调用?

3 个答案:

答案 0 :(得分:6)

bindings-levmar包提供了对C Levenberg-Marquardt优化器的绑定。

答案 1 :(得分:4)

Hackage的快速grep表明nonlinear-optimization是最好的(唯一的)已写的东西;但是,它似乎没有包含有限优化的任何内容。

你最好的选择似乎是其中之一(按增加吸引力的顺序):

  1. 开始自己的项目。
  2. 扩展上述包。
  3. 找一个像样的C库并学习足够的FFI来绑定它。

答案 2 :(得分:2)

我知道OP要求一个通用的优化库,我的经验是:

  • levmar软件包取决于blas和lapack库,这使得安装过程非常复杂,I didn't manage的安装使得ghci仍可在Windows上运行。
  • nonlinear-optimization软件包需要渐变函数
  • optimization软件包似乎也需要渐变,尽管我不知道如何实际使用它。

此外,所有提到的软件包似乎都没有任何真实的文档。

幸运的是,对于简单的问题,简单的解决方案就足够了。如果要优化具有单个括号极值但不知道梯度函数的一维,平滑和凸函数(请参见下面的 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,该方法具有比黄金分割搜索更快的收敛速度的简单方法。 当然,您也可以使用上述需要梯度功能的软件包之一。