Haskell中的部分导数

Ben*_*ero 7 haskell calculus

不久前,一位朋友想要一个可以使用牛顿方法解决函数根源的程序的帮助,当然我需要一些方法来用数字计算函数的导数,这就是我想出的:

deriv f x = (f (x+h) - f x) / h where h = 0.00001
Run Code Online (Sandbox Code Playgroud)

牛顿的方法是一个相当容易实现的方法,它运作得相当好.但现在我开始怀疑 - 我是否可以通过某种方式使用此函数以数字方式求解偏导数,或者是否需要全面的CAS?我会发布我的尝试,但我完全不知道该做什么.

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

lef*_*out 9

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

deriv :: (Double -> Double) -> Double -> Double
Run Code Online (Sandbox Code Playgroud)

(这不是最常见的签名,但可能对你需要的一切足够一般.)我会打电话

type ? = Double
Run Code Online (Sandbox Code Playgroud)

在下文中为了简洁,即

deriv :: (? -> ?) -> ? -> ?
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

不得不单独写出组件并使特定于特定维向量空间的定义变得尴尬.这样做的一般方法:

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
Run Code Online (Sandbox Code Playgroud)

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


luq*_*qui 3

这称为自动微分,Haskell 在这个领域有很多非常巧妙的工作,尽管我不知道它的易用性如何。

从维基页面: