gpt4 book ai didi

haskell - 如何使用向量空间库(haskell)微分积分

转载 作者:行者123 更新时间:2023-12-02 12:44:31 28 4
gpt4 key购买 nike

使用 vector-space 时导数塔包(参见 derivative towers )我遇到了对积分进行微分的需要。从数学上很清楚如何实现这一点:

f(x) = int g(y) dy from 0 to x

有一个函数

g : R -> R

例如。

关于 x 的导数为:

f'(x) = g(x)

我尝试通过首先定义一个类“Integration”来获得此行为

class Integration a b where
--standard integration function
integrate :: (a -> b) -> a -> a -> b

一个基本实例是

instance  Integration Double Double where
integrate f a b = fst $ integrateQAGS prec 1000 f a b

使用 hmatrix 中的 integrateQAGS

问题在于代表导数塔的值 b:

instance Integration Double (Double :> (NC.T Double)) where
integrate = integrateD

NC.T 来自 Numeric.Complex(数字前奏)。函数integrateD定义如下(但错误):

integrateD ::(Integration a b, HasTrie (Basis a), HasBasis a, AdditiveGroup b) =>  (a -> a :> b) -> a -> a -> (a :> b)
integrateD f l u = D (integrate (powVal . f) l u) (derivative $ f u)

该函数没有返回我想要的结果,它导出了被积数,但不是积分。问题是,我需要一个返回 fu 的线性映射。 a :> b 定义如下:

data a :> b = D { powVal :: b, derivative :: a :-* (a :> b) }

我不知道如何定义导数。任何帮助将不胜感激,谢谢

编辑:

我忘记提供Integration Double (NC.T Double)实例:

instance  Integration Double (NC.T Double) where
integrate f a b = bc $ (\g -> integrate g a b) <$> [NC.real . f, NC.imag . f]
where bc (x:y:[]) = x NC.+: y

我可以举一个例子来说明我的意思:假设我有一个函数

f(x) = exp(2*x)*sin(x)

>let f = \x -> (Prelude.exp ((pureD 2.0) AR.* (idD x))) * (sin (idD x)) :: Double :> Double

(AR.*) 表示 Algebra.Ring 的乘法(数字前奏)

我可以轻松地将这个函数与上面的函数integrateD集成:

>integrateD f 0 1 :: Double :> Double
D 1.888605715258933 ...

当我看一下 f 的导数时:

f'(x) = 2*exp(2*x)*sin(x)+exp(2*x)*cos(x)

并在 0pi/2 处对其进行评估,我得到 1 和一些值:

> derivAtBasis (f 0.0) ()
D 1.0 ...

> derivAtBasis (f (pi AF./ 2)) ()
D 46.281385265558534 ...

现在,在求积分时,我得到函数 f 的导数,而不是它在上限的值

> derivAtBasis (integrate f 0 (pi AF./ 2)) ()
D 46.281385265558534 ...

但我期望:

> f (pi AF./ 2)
D 23.140692632779267 ...

最佳答案

如果您只想对涉及数字积分的函数进行 AD,而 AD 系统本身不知道积分,那么它应该“正常工作”。这是一个例子。 (这个集成例程非常棘手,因此得名。)

import Numeric.AD
import Data.Complex

intIcky :: (Integral a, Fractional b) => a -> (b -> b) -> b -> b -> b
intIcky n f a b = c/n' * sum [f (a+fromIntegral i*c/(n'-1)) | i<-[0..n-1]]
where n' = fromIntegral n
c = b-a

sinIcky t = intIcky 1000 cos 0 t
cosIcky t = diff sinIcky t

test1 = map sinIcky [0,pi/2..2*pi::Float]
-- [0.0,0.9997853,-4.4734867e-7,-0.9966421,6.282018e-3]
test2 = map sin [0,pi/2..2*pi::Float]
-- [0.0,1.0,-8.742278e-8,-1.0,-3.019916e-7]
test3 = map cosIcky [0,pi/2..2*pi::Float]
-- [1.0,-2.8568506e-4,-0.998999,2.857402e-3,0.999997]
test4 = map cos [0,pi/2..2*pi::Float]
-- [1.0,-4.371139e-8,-1.0,1.1924881e-8,1.0]
test5 = diffs sinIcky (2*pi::Float)
-- [6.282019e-3,0.99999696,-3.143549e-3,-1.0004976,3.1454563e-3,1.0014982,-3.1479746e-3,...]
test6 = diffs sinIcky (2*pi::Complex Float)
-- [6.282019e-3 :+ 0.0,0.99999696 :+ 0.0,(-3.143549e-3) :+ 0.0,(-1.0004976) :+ 0.0,...]

唯一需要注意的是数字积分例程需要与 AD 配合良好,并且还接受复杂的参数。更天真的东西,比如

intIcky' dx f x0 x1 = dx * sum [f x|x<-[x0,x0+dx..x1]]

在积分上限中是分段常数,要求积分的极限是 Enum,因此是非复数,并且经常评估被积数超出给定范围,因为:

Prelude> last [0..9.5]
10.0

关于haskell - 如何使用向量空间库(haskell)微分积分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11431530/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com