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