5

微分タワー (微分タワーを参照) にベクトル空間パッケージを使用する場合、積分を微分する必要があります。数学から、これを達成する方法は非常に明確です。

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

機能付き

g : R -> R

例えば。

x に関する導関数は次のようになります。

f'(x) = g(x)

最初にクラス「統合」を定義して、この動作を取得しようとしました

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

hmatrixintegrateQAGSから_

問題には、導関数の塔を表す値 b が伴います。

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

NC.TNumeric.Complex (numeric-prelude) からのものです。関数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)

関数は私が望むものを返さず、被積分関数を導出しますが、積分は導出しません。問題は、 を返す線形マップが必要なことですf u。はa :> b次のように定義されます。

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

の定義方法がわかりませんderivative。どんな助けでも感謝します、ありがとう

編集:

のインスタンスを提供するのを忘れていました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 からの乗算を意味します (numeric-prelude)

この関数を上記の関数と簡単に統合できますintegrateD

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

f の導関数を見ると、次のようになります。

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

でこれを評価する0と、いくつかの値pi/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 ...
4

3 に答える 3

0

私はついに私の質問に対する解決策を見つけました。解決策の鍵は>-<、ベクトル空間パッケージの関数であり、チェーン ルールを表します。

したがって、次のintegrateD'ような関数を定義します。

integrateD' :: (Integration a b, HasTrie (Basis a), HasBasis a, AdditiveGroup b , b ~ Scalar b, VectorSpace b) => (a -> a :> b) -> a -> a -> (a:>b) -> (a :> b)
integrateD' f l u d_one =  ((\_ -> integrate (powVal . f) l  (u)) >-< (\_ ->  f u)) (d_one)

派生変数とそのd_one導関数が 1 でなければならないことを意味します。この関数を使用すると、次のようなインスタンスをいくつか作成できます。

instance Integration Double (Double :> Double) where
integrate f l u = integrateD' f l u (idD 1)

instance Integration ( Double) (Double :> (NC.T Double)) where
integrate f l u = liftD2 (NC.+:) (integrateD' (\x -> NC.real <$>> f x) l u (idD 1.0 :: Double :> Double)) (integrateD' (\x -> NC.imag <$>> f x) l u (idD 1.0 :: Double :> Double))

残念ながらintegrateD、すぐに複雑な値を使用することはできません。使用する必要がありますliftD2。この理由はidD機能にあるようです。よりエレガントな解決策があるかどうかはわかりません。

質問の例を見ると、希望する解決策が得られます。

*Main> derivAtBasis (integrateD' f 0 (pi AF./ 2) (idD 1.0 :: Double :> Double )) ()
D 23.140692632779267 ...

またはインスタンスを使用して:

*Main> derivAtBasis (integrate f 0 (pi AF./ 2)) ()
D 23.140692632779267 ...
于 2012-08-09T13:25:04.790 に答える
0

「hmatrix」は、Double と非常に密接に結びついています。'vector-space' や 'ad' によって提供されるような他の数値データ型でその関数を使用することはできません。

于 2012-07-11T15:32:19.133 に答える