我需要计算表格
的积分/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
尝试标量示例时,我得到了相同的错误。
我该怎么做才能解决这个问题?
谢谢。
答案 0 :(得分:1)
你可以做
integrateCMat' :: (Double -> Mat.T (Complex Double))
-> Double -> Double
-> Mat.T (Complex Double)
integrateCMat' cmf a b = Mat.fromRows n m integratedRows
where (n,m) = Mat.dimension(cmf undefined)
integratedCell idx = integrateC (cellFunction idx) a b
cellFunction idx = (\(Mat.Cons arr) -> arr ! idx) . cmf
integratedRows = [ [ integratedCell(i,j) | i<-[1..n] ] | j<-[1..m] ]
但我同意这是相当丑陋的,尽管Haskell的懒惰应该确保不会在每个集成步骤中计算所有矩阵条目。