2012-02-24 4 views
6

vector-spaceパッケージにもう一度問題があります。私は最近のpostの@mnishから非常に有益な回答を受けましたが、そこではただ1つの変数に依存する関数しか扱っていませんでした。私が持っているとき、例えば、2つの変数に依存ベクトル空間パッケージを使用した多変数関数とそれに対応するヤコビアンの導関数

f:(0,oo) x [0,2pi] -> R² 
(r,phi) -> (r*cos(phi),r*sin(phi)) 

をcartesiansする極座標からマップする関数を何が起こる 。

私はかなりナイーブなアプローチで、これを試してみました:

次のエラー
polar :: Double -> Double -> ((Double,Double) :~> (Double,Double)) 
polar r phi = \(r,phi) -> (((idD) r)*cos(idD phi),((idD) r)*sin(idD phi)) 

私が取得:

polarx :: Double -> Double -> ((Double,Double) :~> Double) 
polarx r phi = \(r,phi) -> ((idD) r)*cos(idD phi) 

私は

を得る

Couldn't match expected type `(Double, Double) :> (Double, Double)' 
      with actual type `(t0, t1)' 
In the expression: 
    (((idD) r) * cos (idD phi), ((idD) r) * sin (idD phi)) 
In the expression: 
    \ (r, phi) 
    -> (((idD) r) * cos (idD phi), ((idD) r) * sin (idD phi)) 
In an equation for `polar': 
    polar r phi 
     = \ (r, phi) 
      -> (((idD) r) * cos (idD phi), ((idD) r) * sin (idD phi)) 

一つの成分について

Couldn't match expected type `Double' 
      with actual type `(Double, Double)' 
Expected type: (Double, Double) :> Double 
    Actual type: (Double, Double) :> (Double, Double) 
In the return type of a call of `idD' 
In the first argument of `(*)', namely `((idD) r)' 

明らかに何らかのタイプの障害がありますが、何が間違っているかわかりません。

このようなマッピングのヤコビ行列を計算したいときに、別の疑問が生じます。その名前が示唆するように、リニアマップとは何かがあります。もちろん、リニアマップはパッケージによってカバーされていますが、実際にはそれらのマップに基づいています。しかし、私のハスケルの知識は、私自身で解決策を導くには不十分です。

+1

私はConalの非常にエレガントな自動微分定式化の重要な制限は、単一軸に沿って導関数にしか作用しないということです。 Jacobiansなどが欲しい場合は、ekmettの広告パッケージを使用してください:http://hackage.haskell.org/package/ad-1.3.0.1 – sclv

+1

ありがとう@sclv、私はこのモジュールを調べました。うわー、私は感銘を受けたでしょう。私はこのパッケージに気付きませんでした。これを指摘してくれてありがとうございます。 – TheMADMAN

+0

あなたは一人ではありません - 私は多次元タイプがどのように適合しているかを理解するのに苦労しています。私は「美しい差別化」という論文を読んで、それがいくつかの光を放つことを祈っています - 広告パッケージは、タイプ上かなりシンプルに見えます! – Oliver

答えて

2

私は最終的に私の問題の解決策を見つけました。それはそれほど難しいことではありませんでしたが、それを理解するまでにはまだ時間がかかりました。他の誰かが興味を持っている場合、私は詳細を提示する。

polarCoordD :: ((Double,Double) :~> (Double,Double)) 
polarCoordD = \(r,phi) -> pairD (polarx (r,phi), polary (r,phi)) 
where polarx :: (Double,Double) :~> Double 
     polarx = \(r,phi) -> (fst . unpairD $ (idD) (r,phi))*cos(snd . unpairD $ idD (r, phi)) 
     polary :: (Double,Double) :~> Double 
     polary = \(r,phi) -> (fst . unpairD $ (idD) (r,phi))*sin(snd . unpairD $ idD (r, phi)) 

キーは、私は区別したい2つの変数を保持しているタプル(r, phi)(idD)意識し「派生変数」を作ることだった。ここではまず

は、極性の場合のために私のコードです。私はunpairD介してタプルを解凍しなければならないと(polarxpolaryで)得られた一対の第一及び第二の部分を選択しました。どちらもペアに再びパックされます。多分これを行うためのよりエレガントな方法がありますが、それは私がそれを最後に理解する方法です。

ここから円筒形の座標に、実際には他の曲線直交座標系に進むことは難しくありません。円筒形の場合 私が得座標:

Vec3 Doubletype Vec3 a = (a, a, a)に属する
cylCoordD :: (Vec3 Double :~> Vec3 Double) 
cylCoordD = \(r,phi,z) -> tripleD (cylx (r,phi,z), cyly (r,phi,z),cylz (0,0,z)) 
where cylx :: (Double,Double,Double) :~> Double 
     cylx = \(r,phi,z) -> (fst' . untripleD $ (idD) (r,phi,z))*cos(snd' . untripleD $ idD (r, phi,z)) 
     cyly :: (Double,Double,Double) :~> Double 
     cyly = \(r,phi,z) -> (fst' . untripleD $ (idD) (r,phi,z))*sin(snd' . untripleD $ idD (r, phi,z)) 
     cylz :: (Double,Double,Double) :~> Double 
     cylz = \(_,_,z) -> third . untripleD $ idD (0,0,z) 
     fst' :: (a,b,c) -> a 
     fst' (x,_,_) = x 
     snd' :: (a,b,c) -> b 
     snd' (_,y,_) = y 
     third :: (a,b,c) -> c 
     third (_,_,z) = z 

。 今、私たちも、変換行列を構築することができます。

let transmat = \(r,phi,z) -> powVal $ liftD3 (,,) (normalized $ derivAtBasis (cylCoordD (r,phi,z)) (Left())) (normalized $ derivAtBasis (cylCoordD (r,phi,z)) (Right (Left()))) (normalized $ derivAtBasis (cylCoordD (r,phi,z)) (Right (Right()))) 

*Main> transmat (2, rad 0, 0) 
((1.0,0.0,0.0),(0.0,1.0,0.0),(0.0,0.0,1.0)) 

*Main> transmat (2, rad 90, 0) 
((6.123233995736766e-17,1.0,0.0),(-1.0,6.123233995736766e-17,0.0),(0.0,0.0,1.0)) 

radは、今ではNumeric Preludeおよび/またはhmatrixのマトリックス型に、この「マトリックス」を変換するために興味深いものになるだろう

rad :: Double -> Double 
rad = (pi*) . (*recip 180) 

便利な関数ですしかし、これが役に立つのかどうかはわかりません。しかし、それでも、vector-spaceパッケージの使用のための良い例になります。

私はまだ線形マップの使用、特にアプリケーションを理解する必要があります。

0

このフォローアップの質問を見ました。私はあなたが何をしたいかわからない:

  • ヤコビ行列
  • ヤコビアンとベクトルの積
  • ヤコビアン転置ベクトルの積

ような低次元のシステムでは、私は最初を仮定します。 (他のものは主に、システムが高次元で十分なヤコビ行列を保存または計算したくない場合に便利ですが、その代わりに一般化された疎行列として扱います)いずれにしても:

Prelude> :m + Numeric.AD 
Prelude Numeric.AD> let f [r,phi] = map (r*) [cos phi, sin phi] 
Prelude Numeric.AD> jacobian f [2,3::Float] 
[[-0.9899925,-0.28224],[0.14112,-1.979985]] 
関連する問題