Мне нужно вычислить интегралы вида
/t /x
| P(x)*| P(y) dydx
/t0 /t0
где P — это функция R -> C^(nxn)
, обычно матрица, и я хочу сделать это на Haskell. Я добился этого для скалярных функций:
import Numeric.GSL.Integration
import Data.Complex
import Data.List
prec :: Double
prec = 1E-9
integrate :: (Double -> Double) -> Double -> Double -> Double
integrate f a b = fst $ integrateQNG prec f a b
integrateC :: (Double -> Complex Double) -> Double -> Double -> Complex Double
integrateC cf a b = (integrate (\x -> realPart (cf x)) a b :+ integrate (\x -> imagPart (cf x)) a b)
multipleIntegration :: Int -> (Double -> Complex Double) -> Double -> (Double -> Complex Double)
multipleIntegration n f a = foldl' (\ acc g' -> (\ x -> integrateC (g'*acc) a x)) (\_ -> 1:+0) (replicate n f)
Это работает до сих пор, хотя и довольно медленно для n>5.
Теперь мне нужно распространить это вычисление на матрицы, я пробовал это с числовой прелюдией, потому что я могу брать функции как элементы матрицы. Я могу интегрировать матрицу Double -> Complex Double
, но моя реальная цель умножить матрицу внутри интеграла терпит неудачу, сначала мой код:
import MathObj.Matrix as Mat
import Algebra.Ring as AR
import Control.Applicative
import qualified Prelude as P
import Prelude hiding ((*))
import Number.Complex as NC
import Numeric.GSL.Integration
import Data.List
type Complex a = NC.T a
prec :: Double
prec = 1E-9
testMat :: Mat.T (Double -> Complex Double)
testMat = Mat.fromRows 2 2 [[\x-> 0.5 +: 2*x,\y-> cos y +: sin y],[\x-> 0.1*x +:x,\_-> 1 +: 1]]
integrateC :: (Double -> Complex Double) -> Double -> Double -> Complex Double
integrateC cf a b = (integrate (\x -> real (cf x)) a b +: integrate (\x -> imag (cf x)) a b)
integrate :: (Double -> Double) -> Double -> Double -> Double
integrate f a b = fst $ integrateQNG prec f a b
integrateCMat' :: Mat.T (Double -> Complex Double) -> Double -> Mat.T (Double -> Complex Double)
integrateCMat' cmf a = ((\f -> integrateC f a ) <$> cmf)
multipleIntegrationMat :: Int -> Mat.T (Double -> Complex Double) -> Double -> Mat.T (Double -> Complex Double)
multipleIntegrationMat n mf a = integrateCMat' ( testMat * (integrateCMat' testMat a)) a
Здесь multipleIntegrationMat
— это просто функция тестирования, я не использовал фолд, поэтому n лишнее. Сообщение об ошибке:
matmul.hs:27:59:
No instance for (C (Double -> Complex Double))
arising from a use of `*'
Possible fix:
add an instance declaration for (C (Double -> Complex Double))
In the first argument of `integrateCMat'', namely
`(testMat * (integrateCMat' testMat a))'
In the expression:
integrateCMat' (testMat * (integrateCMat' testMat a)) a
In an equation for `multipleIntegrationMat':
multipleIntegrationMat n mf a
= integrateCMat' (testMat * (integrateCMat' testMat a)) a
Failed, modules loaded: none.
Я понимаю, что нет экземпляра для умножения функций. Что было бы лучшим способом для такого экземпляра? С другой стороны, в скалярном примере умножение работает, хотя комплексный тип данных берется из Data.Complex
. Когда я пробую скалярный пример с Number.Complex
, я получаю ту же ошибку.
Что я могу сделать, чтобы решить эту проблему?
Спасибо.
Double -> Mat.T (Complex Double)
не решит проблему немедленно и будет более простым, концептуально? - person leftaroundabout   schedule 06.03.2012Double -> Mat.T (Complex Double)
, когда функция библиотеки обеспечивает только интеграцию поDouble->Double
? - person TheMADMAN   schedule 06.03.2012