Raymond Moore
Raymond Moore

Reputation: 11

Matlab vectorizing equations and matrix multiplication

I have a program that currently uses a for loop to iterate through a set of functions. I've tried using parfor but that only works on the university's version of Matlab. I'd like to vectorize the handling of this so that a for loop isn't necessary. The equations I'm using basically call different types of Bessel functions and are contained in separate functions.

Here's what I'm trying to do: For each value of m, build a vector of matrix elements for each required matrix. Then build each full matrix. I think this is working correctly.

Where it's throwing an error is on the final matrix multiplication... even if I just multiply the left 2x2 by the middle 2x2 I get the dreaded error:

??? Error using ==> mtimes Inner matrix dimensions must agree. Error in ==> @(m)CL(m)*CM(m)*CR(m)

% Vector for summation. 1 row, 301 columns with data from 0->300
m_max=301;
m=[0:m_max-1];

% Build the 300 elements for the left 2x2 matrix.
CL_11=@(m) H1(m,alpha1);
CL_12=@(m) H2(m,alpha1);
CL_21=@(m) n1*dH1(m,alpha1);
CL_22=@(m) n1*dH2(m,alpha1);

% Build the 300 elements for the middle 2x2 matrix.
CM_11=@(m) n1*dH2(m,alpha2);
CM_12=@(m) -1*H2(m,alpha2);
CM_21=@(m) -1*n1*dH1(m,alpha2);        
CM_22=@(m) H1(m,alpha2);

% Build the 300 elements for the right 2x1 matrix.
CR_11=@(m) J(m,alpha3);
CR_21=@(m) n2*dJ(m,alpha3);

% Build the left (CL), middle (CM) and right (CR) matrices.
CL=@(m) [CL_11(m) CL_12(m);CL_21(m) CL_22(m)];
CM=@(m) [CM_11(m) CM_12(m);CM_21(m) CM_22(m)];
CR=@(m) [CR_11(m);CR_21(m)];

% Build the vector containing the products of each triplet of
% matrices. 
C=@(m) CL(m)*CM(m)*CR(m);
cl=CL(m)
cm=CM(m)
cr=CR(m)

c=CL(m)*CM(m)*CR(m)

If you have any suggestions or recommendations, I'd greatly appreciate it! I'm still a newbie with Matlab and am trying to develop a higher level of ability with use of matrices and vectors.

Thanks!!

Upvotes: 1

Views: 152

Answers (2)

bdecaf
bdecaf

Reputation: 4732

If you go through the symbolic toolbox you can construct a function that is easier to handle.

%% symbolic
CL = sym('CL',[2,2])
CM = sym('CM',[2,2])
CR = sym('CR',[2,1])
r = CL*CM*CR
f = matlabFunction(r)
%% use some simple functions so it can be calculated as example
CL_11=@(m) m+1;
CL_12=@(m) m;
CL_21=@(m) m-1;
CL_22=@(m) m+2;

CM_11=@(m) m;
CM_12=@(m) m;
CM_21=@(m) 2*m;        
CM_22=@(m) 2*m;

CR_11=@(m) m;
CR_21=@(m) 1-m;

%% here the substitution happens:
fh = @(m) f(CL_11(m),CL_12(m),CL_21(m),CL_22(m),CM_11(m),CM_12(m),CM_21(m),CM_22(m),CR_11(m),CR_21(m))

Out of interest I did a small speed test:

N=1e5;
v = 1:N;

tic
% .... insert symbolic stuff from above
r1 = fh(v);
t1=toc %  gives  0.0842s for me

vs

CL=@(m) [CL_11(m) CL_12(m);CL_21(m) CL_22(m)];
CM=@(m) [CM_11(m) CM_12(m);CM_21(m) CM_22(m)];
CR=@(m) [CR_11(m);CR_21(m)];

C=@(m) CL(m)*CM(m)*CR(m);
tic
r2 =arrayfun(C,v,'UniformOutput',false);
t2=toc % gives  7.6874s for me

and

tic
r3 = nan(2,N);
for i=1:N
    r3(:,i)=C(v(i));
end
t3=toc %  8.1503s for me

Upvotes: 0

David
David

Reputation: 8459

Your matrices are not 2x2. When you do CL_11(m) with m a 1x300 vector, CL_11(m) will be 1x300 as well. Thus CL(m) is 2x301. To get around this, you have to calculate the matrices one-by-one. There are two approaches here.

c=arrayfun(C,m,'UniformOutput',false)

will return a cell array, and so c{1} corresponds to m(1), c{2} to m(2), etc.

On the other hand, you can do

for i=1:m_max
    c(:,:,i)=C(m(i));
end

and then c(:,:,i) corresponds to m(1), etc.

I'm not sure which version will be faster, but you can test it easily enough with your code.

Upvotes: 3

Related Questions