2

I'm trying to speed up my code because it's running very long. I already found out where the problem lies. Consider the following example:

x<-c((2+2i),(3+1i),(4+1i),(5+3i),(6+2i),(7+2i))
P<-matrix(c(2,0,0,3),nrow=2)
out<-sum(c(0.5,0.5)%*%mtx.exp(P%*%(matrix(c(x,0,0,x),nrow=2)),5))

I have a vector x with complex values, the vector has 12^11 entries and then I want to calculate the sum in the third row. (I need the function mtx.exp because it's a complex matrix power (the function is in the package Biodem). I found out that the %^% function does not support complex arguments.)

So my problem is that if I try

sum(c(0.5,0.5)%*%mtx.exp(P%*%(matrix(c(x,0,0,x),nrow=2)),5))

I get an error: "Error in pot %*% pot : non-conformable arguments." So my solution was to use a loop:

tmp<-NULL
for (i in 1:length(x)){
  tmp[length(tmp)+1]<-sum(c(0.5,0.5)%*%mtx.exp(P%*%matrix(c(x[i],0,0,x[i]),nrow=2),5))
}

But as said, this takes very long. Do you have any ideas how to speed up the code? I also tried sapply but that takes just as long as the loop.

I hope you can help me, because i have to run this function approximatly 500 times and this took in first try more than 3 hours. Which is not very satisfying..

Thank u very much

Vincent Zoonekynd
  • 31,893
  • 5
  • 69
  • 78
rainer
  • 929
  • 2
  • 14
  • 25

1 Answers1

1

The code can be sped up by pre-allocating your vector,

tmp <- rep(NA,length(x))

but I do not really understand what you are trying to compute: in the first example,
you are trying to take the power of a non-square matrix, in the second, you are taking the power of a diagonal matrix (which can be done with ^).

The following seems to be equivalent to your computations:

sum(P^5/2) * x^5

EDIT

If P is not diagonal and C not scalar, I do not see any easy simplification of mtx.exp( P %*% C, 5 ).

You could try something like

y <- sapply(x, function(u) 
  sum( 
    c(0.5,0.5) 
    %*% 
    mtx.exp( P %*% matrix(c(u,0,0,u),nrow=2), 5 )
  )
)

but if your vector really has 12^11 entries, that will take an insanely long time.

Alternatively, since you have a very large number of very small (2*2) matrices, you can explicitely compute the product P %*% C and its 5th power (using some computer algebra system: Maxima, Sage, Yacas, Maple, etc.) and use the resulting formulas: these are just (50 lines of) straightforward operations on vectors.

/* Maxima code */ 
p: matrix([p11,p12], [p21,p22]);
c: matrix([c1,0],[0,c2]);
display2d: false;
factor(p.c . p.c . p.c . p.c . p.c);

I then copy and paste the result in R:

c1 <- dnorm(abs(x),0,1); # C is still a diagonal matrix
c2 <- dnorm(abs(x),1,3);
p11 <- P[1,1]
p12 <- P[1,2]
p21 <- P[2,1]
p22 <- P[2,2]
# Result of the Maxima computations: 
# I just add all the elements of the resulting 2*2 matrix,
# but you may want to do something slightly different with them.

          c1*(c2^4*p12*p21*p22^3+2*c1*c2^3*p11*p12*p21*p22^2
                                +2*c1*c2^3*p12^2*p21^2*p22
                                +3*c1^2*c2^2*p11^2*p12*p21*p22
                                +3*c1^2*c2^2*p11*p12^2*p21^2
                                +4*c1^3*c2*p11^3*p12*p21+c1^4*p11^5)
          +
          c2*p12
            *(c2^4*p22^4+c1*c2^3*p11*p22^3+3*c1*c2^3*p12*p21*p22^2
                        +c1^2*c2^2*p11^2*p22^2+4*c1^2*c2^2*p11*p12*p21*p22
                        +c1^3*c2*p11^3*p22+c1^2*c2^2*p12^2*p21^2
                        +3*c1^3*c2*p11^2*p12*p21+c1^4*p11^4)
         +
         c1*p21
            *(c2^4*p22^4+c1*c2^3*p11*p22^3+3*c1*c2^3*p12*p21*p22^2
                        +c1^2*c2^2*p11^2*p22^2+4*c1^2*c2^2*p11*p12*p21*p22
                        +c1^3*c2*p11^3*p22+c1^2*c2^2*p12^2*p21^2
                        +3*c1^3*c2*p11^2*p12*p21+c1^4*p11^4)
         +
         c2*(c2^4*p22^5+4*c1*c2^3*p12*p21*p22^3
                        +3*c1^2*c2^2*p11*p12*p21*p22^2
                        +3*c1^2*c2^2*p12^2*p21^2*p22
                        +2*c1^3*c2*p11^2*p12*p21*p22
                        +2*c1^3*c2*p11*p12^2*p21^2+c1^4*p11^3*p12*p21)
Vincent Zoonekynd
  • 31,893
  • 5
  • 69
  • 78
  • Sorry, maybe I didn't explain the problem properly: So I have this matrix P (which is normaly not a diagonal matrix) consider P<-matrix(c(2.1,20.,0.3,3.2),nrow=2) this matrix gets multiplied by another (diagonal, this time) matrix let's call it C C<-matrix(c(x[i],0,0,x[i]),nrow=2) (for each i in (1:length(x)) Then i want to take the n-th power in this case n=5 (P*C)^5 This is again multiplied by a vector and the elements sumed up. My problem is that I do not want to do it with a loop (so for every entry in x this sum has to be calculated) – rainer Apr 04 '12 at 13:57
  • If the matrix `C` is scalar (i.e., diagonal, with the same element everywhere on the diagonal), this can still be written `sum(mtx.exp(P,5)/2) * x^5`. – Vincent Zoonekynd Apr 05 '12 at 03:14
  • Okey thank you, that helps a bit. The next problem I face is that my entries in the matrix C are not the same they depend on a function for example: C<-matrix(dnorm(x[i],0,1),0,0,dnorm(x[i],1,3)) – rainer Apr 05 '12 at 06:09
  • And the complex matrix exponential is in the matrix C. P is just a square matrix with real entries. I'm sorry, it's a little bit confusing. But I do not want to upload the whole code. – rainer Apr 05 '12 at 06:52
  • In this case, I do not see any easy way to simplify the problem -- but I have edited my answer with a complicated way to speed up the computations. – Vincent Zoonekynd Apr 05 '12 at 07:52