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

Haskell haskel中用于顺序非线性优化的库?,haskell,nonlinear-optimization,Haskell,Nonlinear Optimization,有没有用Haskell编写的或很容易从Haskell调用的用于序列非线性优化(具有上下界以及不等式约束)的库?快速grep of建议这是最好(唯一)已经编写的东西;然而,它似乎不包括任何有界优化 您的最佳选择似乎是以下之一(按吸引力增加的顺序): 开始你自己的项目 扩展上述包 找到一个像样的C库,学习足够的FFI来绑定它 该软件包提供与C Levenberg-Marquardt优化器的绑定。我知道OP要求提供一个通用优化库,我的经验是: 该软件包依赖于blas和lapack库,这使得安装变得非

有没有用Haskell编写的或很容易从Haskell调用的用于序列非线性优化(具有上下界以及不等式约束)的库?

快速grep of建议这是最好(唯一)已经编写的东西;然而,它似乎不包括任何有界优化

您的最佳选择似乎是以下之一(按吸引力增加的顺序):

  • 开始你自己的项目
  • 扩展上述包
  • 找到一个像样的C库,学习足够的FFI来绑定它

  • 该软件包提供与C Levenberg-Marquardt优化器的绑定。

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

    • 该软件包依赖于blas和lapack库,这使得安装变得非常复杂,安装它时ghci仍在Windows上工作
    • 这个包需要一个梯度函数
    • 这个软件包似乎也需要渐变,尽管我不知道如何实际使用它
    此外,所有提到的包似乎都没有任何真正的文档

    幸运的是,对于简单的问题,一个简单的解决方案就足够了。如果你想优化一个一维的,光滑的,凸的函数,它有一个带括号的极值,但是你不知道梯度函数(如果你知道,请参见下文),那么一个简单的方法,比如黄金分割搜索,就可以了

    翻译自:

    导入数据.Maybe(fromMaybe)
    --1/phi
    invphi=(sqrt 5-1)/2
    --1/φ^2
    invphi2=(3-sqrt 5)/2
    --|启用可选参数语法。可能与用作参数类型的一起使用,然后在函数中写入param//defaultValue
    (/)::可能是a->a->a
    (/)=可能
    --仅仅是一个包装器函数,因为递归函数有很多丑陋的东西
    goldenSectionSearch f a b公差=goldenSectionSearch递归f a b公差无
    --|黄金分割搜索,递归。
    --给定一个在区间[a,b]中有一个局部最大值的函数f,黄金分割搜索返回一个子集区间[c,d],该子集区间[c,d]包含一个在[a,b]中有一个最大值的d-c Double)^函数
    ->双击--^间隔的一侧
    ->双击--^间隔的另一侧
    ->双公差
    ->可能是双倍--^h,当前搜索间隔
    ->可能是双--^c,新的左间隔点。如果没有,则选择一个新点。
    ->可能是双--^d,新的右间隔点。
    ->可能是双精度--^f(c),函数值在c
    ->可能是双精度--^f(d),函数值在d处
    ->(双精度,双精度)--^最大值为
    goldensionsearchf a'b'公差h'c'd'fc'fd'
    |h<公差=(a,b)
    |fc>fd=goldensionsearchf a d公差(刚好(h*invphi))无(刚好c)无(刚好fc)
    |否则=goldensionsearchf c b公差(刚好(h*invphi))(刚好d)Nothing(刚好fd)Nothing
    哪里
    a=最小a'b'
    b=最大a‘b’
    h=h'//(b-a)
    c=c'/(a+invphi2*h)
    d=d'/(a+invphi*h)
    fc=fc'//fc
    fd=fd'//fd
    
    然后用
    goldenSectionSearch(\x->-(x-2)^2)1 5 1e-5
    调用,返回
    (1.999998379107,2.0000050911830893)
    。这个简单的函数当然更容易手工求解,但它只是一个例子

    PS黄金分割搜索的有趣之处在于,收敛速度是完全已知的:在每次迭代中,最优值所在区间的长度除以黄金分割比

    PPS我把它戴上了

    []请注意,如果您知道梯度函数,将其等于零并应用求根方法通常要快得多。例如,在一维中,Will Ness指出了一种比黄金分割搜索具有更快收敛速度的简单方法。
    当然,您也可以使用上面提到的需要梯度函数的软件包。

    我更喜欢。@WillNess我看到这种方法收敛得更快,我喜欢,但它是用来求根的。如果你不知道所说的最大值的函数值,我不确定你将如何应用它来寻找最大值?难道不能调整目标函数(正确的术语是什么?)以便它是我们正在搜索的根吗?例如,在最小二乘法中,最小值与导数的根重合。例如,“平方差之和的最小梯度为零[…]”*“目标函数”。谢谢。即使我们没有直接可用的导数,我们也可以通过探测邻域来估计它们。那么括号内的割线原理仍然适用。:)
    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