哈斯克尔的部分衍生物

时间:2018-01-11 21:06:19

标签: haskell calculus

前段时间,一位朋友想要一个能够使用Newton方法解决函数根源的程序的帮助,当然我需要一些方法来用数字计算函数的导数,这就是我提出了:

deriv f x = (f (x+h) - f x) / h where h = 0.00001
牛顿的方法是一个相当容易实现的方法,而且效果相当好。但现在我开始怀疑 - 我是否有某种方法可以使用这个函数以数字方式解决偏导数,或者是否需要全面的CAS?我会发布我的尝试,但我完全不知道该做什么。

请记住,我是Haskell的新手。谢谢!

2 个答案:

答案 0 :(得分:8)

你可以做的事情和你已经实施的一样,只是多变量。但首先(正如您应该总是使用顶级函数)添加类型签名:

deriv :: (Double -> Double) -> Double -> Double

(这不是最常见的签名,但可能足以满足你所需的一切。)我会打电话给

type ℝ = Double

以下简洁,即

deriv :: (ℝ -> ℝ) -> ℝ -> ℝ

现在你想要的是,例如在ℝ²

grad :: ((ℝ,ℝ) -> ℝ) -> (ℝ,ℝ) -> (ℝ,ℝ)
grad f (x,y) = ((f (x+h,y) - f (x,y)) / h, (f (x,y+h) - f (x,y)) / h)
 where h = 0.00001

不得不单独写出组件并使特定于特定维向量空间的定义变得尴尬。 generic way执行此操作:

import Data.VectorSpace
import Data.Basis

grad :: (HasBasis v, Scalar v ~ ℝ) => (v -> ℝ) -> v -> v
grad f x = recompose [ (e, (f (x ^+^ h*^basisValue b) - f x) ^/ h)
                     | (e,_) <- decompose x ]
 where h = 0.00001

请注意,这种预先选择的步长有限微分总是在高阶项的不准确性和浮点误差之间进行权衡,因此请务必检查自动区分。

答案 1 :(得分:3)

这被称为automatic differentiation,在Haskell这个领域有很多非常好的工作,虽然我不知道它是多么容易接近。

来自维基页面: