How to deal with recursive loop in MATLAB? - matlab

I am trying to compute x1^i * x2^j * x3^k * ......
This is my code so far:
for l = 1:N
f = 1;
for i = 0:2
for j = 0:2-i
for k = 0:2-j
for m = 0:2-k
g(l,f) = x1(l)^i*x2(l)^j*x3(l)^k*x4(l)^m;
f = f+1;
end
end
end
end
end
How can I do this easier or without a loop?

I do not have MATLAB on hand here, but what I'd do is make a vector X = [x1, x2, ..., xn] of bases and a vector P = [i, j, k, ..., z] of powers, and then compute prod(power(X, P)).
power() does an element-wise power function, and prod takes the product of every element in the vector.

Related

Preventing using for loop in MATLAB

I have written the below MATLAB code. I want to know how can I optimize it without using for loop.
Any help will be very appreciated.
MATLAB code:
%Some parameters:
s = 50;
k = 50;
r = 0.1;
v = 0.2;
t = 2;
n=10000;
% Calculate CT by calling EurCall function
CT = EurCall(s, k, r, v, t, n);
%Function EurCall to be called
function C = EurCall(s, k, r, v, t, n)
X = zeros(n,1);
hh = zeros(n,1);
for ii = 1 : n
X(ii) = normrnd(0, 1);
SS = s*exp((r - v^2/2)*t + v*X(ii)*sqrt(t));
hh(ii) = exp(-r*t)*max(SS - k, 0);
end %end for loop
C = (1/n) * sum(hh);
end %end function
Vectorized Approach:
Here is a vectorized approach that I think replicates the same functionality as the original script. Instead of looping this example declares X as a vector of size n by 1. By using element-wise multiplication .* we can effectively calculate the remaining vectors SS and hh without need to loop through the indices. In this case SS and hh will also be vectors of size n by 1. I do agree with comment above that MATLAB's for-loops are no longer inherently slow.
%Some parameters:
s = 50;
k = 50;
r = 0.1;
v = 0.2;
t = 2;
n=10000;
% Calculate CT by calling EurCall function
[CT] = EurCall(s, k, r, v, t, n);
%Function EurCall to be called
function [C] = EurCall(s, k, r, v, t, n)
X = zeros(n,1);
hh = zeros(n,1);
mu = 0; sigma = 1;
%Creating a vector of normal random numbers of size (n by 1)%
X = normrnd(mu,sigma,[n 1]);
SS = s*exp((r - v^2/2)*t + v.*X.*sqrt(t));
hh = exp(-r*t)*max(SS - k, 0);
C = (1/n) * sum(hh);
end %end function
Ran using MATLAB R2019b

Vectorize a regression map calculation

I compute the regression map of a time series A(t) on a field B(x,y,t) in the following way:
A=1:10; %time
B=rand(100,100,10); %x,y,time
rc=nan(size(B,1),size(B,2));
for ii=size(B,1)
for jj=1:size(B,2)
tmp = cov(A,squeeze(B(ii,jj,:))); %covariance matrix
rc(ii,jj) = tmp(1,2); %covariance A and B
end
end
rc = rc/var(A); %regression coefficient
Is there a way to vectorize/speed up code? Or maybe some built-in function that I did not know of to achieve the same result?
In order to vectorize this algorithm, you would have to "get your hands dirty" and compute the covariance yourself. If you take a look inside cov you'll see that it has many lines of input checking and very few lines of actual computation, to summarize the critical steps:
y = varargin{1};
x = x(:);
y = y(:);
x = [x y];
[m,~] = size(x);
denom = m - 1;
xc = x - sum(x,1)./m; % Remove mean
c = (xc' * xc) ./ denom;
To simplify the above somewhat:
x = [x(:) y(:)];
m = size(x,1);
xc = x - sum(x,1)./m;
c = (xc' * xc) ./ (m - 1);
Now this is something that is fairly straightforward to vectorize...
function q51466884
A = 1:10; %time
B = rand(200,200,10); %x,y,time
%% Test Equivalence:
assert( norm(sol1-sol2) < 1E-10);
%% Benchmark:
disp([timeit(#sol1), timeit(#sol2)]);
%%
function rc = sol1()
rc=nan(size(B,1),size(B,2));
for ii=1:size(B,1)
for jj=1:size(B,2)
tmp = cov(A,squeeze(B(ii,jj,:))); %covariance matrix
rc(ii,jj) = tmp(1,2); %covariance A and B
end
end
rc = rc/var(A); %regression coefficient
end
function rC = sol2()
m = numel(A);
rB = reshape(B,[],10).'; % reshape
% Center:
cA = A(:) - sum(A)./m;
cB = rB - sum(rB,1)./m;
% Multiply:
rC = reshape( (cA.' * cB) ./ (m-1), size(B(:,:,1)) ) ./ var(A);
end
end
I get these timings: [0.5381 0.0025] which means we saved two orders of magnitude in the runtime :)
Note that a big part of optimizing the algorithm is assuming you don't have any "strangeness" in your data, like NaN values etc. Take a look inside cov.m to see all the checks that we skipped.

Compute weighted summation of matrix power (matrix polynomial) in Matlab

Given an nxn matrix A_k and a nx1 vector x, is there any smart way to compute
using Matlab? x_i are the elements of the vector x, therefore J is a sum of matrices. So far I have used a for loop, but I was wondering if there was a smarter way.
Short answer: you can use the builtin matlab function polyvalm for matrix polynomial evaluation as follows:
x = x(end:-1:1); % flip the order of the elements
x(end+1) = 0; % append 0
J = polyvalm(x, A);
Long answer: Matlab uses a loop internally. So, you didn't gain that much or you perform even worse if you optimise your own implementation (see my calcJ_loopOptimised function):
% construct random input
n = 100;
A = rand(n);
x = rand(n, 1);
% calculate the result using different methods
Jbuiltin = calcJ_builtin(A, x);
Jloop = calcJ_loop(A, x);
JloopOptimised = calcJ_loopOptimised(A, x);
% check if the functions are mathematically equivalent (should be in the order of `eps`)
relativeError1 = max(max(abs(Jbuiltin - Jloop)))/max(max(Jbuiltin))
relativeError2 = max(max(abs(Jloop - JloopOptimised)))/max(max(Jloop))
% measure the execution time
t_loopOptimised = timeit(#() calcJ_loopOptimised(A, x))
t_builtin = timeit(#() calcJ_builtin(A, x))
t_loop = timeit(#() calcJ_loop(A, x))
% check if builtin function is faster
builtinFaster = t_builtin < t_loopOptimised
% calculate J using Matlab builtin function
function J = calcJ_builtin(A, x)
x = x(end:-1:1);
x(end+1) = 0;
J = polyvalm(x, A);
end
% naive loop implementation
function J = calcJ_loop(A, x)
n = size(A, 1);
J = zeros(n,n);
for i=1:n
J = J + A^i * x(i);
end
end
% optimised loop implementation (cache result of matrix power)
function J = calcJ_loopOptimised(A, x)
n = size(A, 1);
J = zeros(n,n);
A_ = eye(n);
for i=1:n
A_ = A_*A;
J = J + A_ * x(i);
end
end
For n=100, I get the following:
t_loopOptimised = 0.0077
t_builtin = 0.0084
t_loop = 0.0295
For n=5, I get the following:
t_loopOptimised = 7.4425e-06
t_builtin = 4.7399e-05
t_loop = 1.0496e-04
Note that my timings fluctuates somewhat between different runs, but the optimised loop is almost always faster (up to 6x for small n) than the builtin function.

Vectorization of Matrix Quadratics in MATLAB

I am trying to "vectorize" this loop in Matlab for computational efficiency
for t=1:T
j=1;
for m=1:M
for n=1:N
y(t,j) = v{m,n} + data(t,:)*b{m,n} + data(t,:)*f{m,n}*data(t,:)';
j=j+1;
end
end
end
Where v is a (M x N) cell of scalars. b is a (M x N) cell of (K x 1) vectors. f is a (M x N) cell of (K x K) matrices. data is a (T x K) array.
To give an example of what I mean the code I used to vectorize the same loop without the quadratic term is:
B = [reshape(cell2mat(v)',1,N*M);cell2mat(reshape(b'),1,M*N)];
X = [ones(T,1),data];
y = X*B;
Thanks!
For those interested here was the solution I found
f = f';
tMat = blkdiag(f{:})+(blkdiag(f{:}))';
y2BB = [reshape(cell2mat(v)',1,N*M);...
cell2mat(reshape(b',1,M*N));...
reshape(diag(blkdiag(f{:})),K,N*M);...
reshape(tMat((tril(tMat,-1)~=0)),sum(1:K-1),M*N)];
y2YBar = [ones(T,1),data,data.^2];
jj=1;
kk=1;
ll=1;
for k=1:sum(1:K-1)
y2YBar = [y2YBar,data(:,jj).*data(:,kk+jj)];
if kk<(K-ll)
kk=kk+1;
else
kk=1;
jj=jj+1;
ll=ll+1;
end
end
y = y2YBar*y2BB;
Here's the most vectorized form targeted for performance -
% Extract as multi-dim arrays
vA = reshape([v{:}],M,N);
bA = reshape([b{:}],K,M,N);
fA = reshape([f{:}],K,K,M,N);
% Perform : data(t,:)*f{m,n} for all iterations
data_f_mult = reshape(data*reshape(fA,K,[]),T,K,M,N);
% Now there are three parts :
% v{m,n}
% data(t,:)*b{m,n}
% data(t,:)*f{m,n}*data(t,:)';
% Compute those parts one by one
parte1 = vA(:).';
parte2 = data*reshape(bA,[],M*N);
parte3 = zeros(T,M*N);
for t = 1:T
parte3(t,:) = data(t,:)*reshape(data_f_mult(t,:,:),K,[]);
end
% Finally sum those up and to present in desired format permute dims
sums = bsxfun(#plus, parte1, parte2 + parte3);
out = reshape(permute(reshape(sums,T,M,N),[1,3,2]),[],M*N);

MATLAB - vectorize iteration over two matrices used in function

I have two matrices X and Y, both of order mxn. I want to create a new matrix Z of order mx1 such that each i th entry in this new matrix is computed by applying a function to ith and ith row of X and Y respectively. In my case m = 100000 and n = 2. I tried using a loop but it takes forever.
for i = 1:m
Z = function(X(1,:),Y(1,:), constant_parameters)
end
Is there an efficient way to vectorize it?
EDIT 1
This is the function
function [peso] = fxPesoTexturaCN(a,b, img, r, L)
ac = num2cell(a);
bc = num2cell(b);
imgint1 = img(sub2ind(size(img),ac{:}));
imgint2 = img(sub2ind(size(img),bc{:}));
peso = (sum((a - b) .^ 2) + (r/L) * (imgint2 - imgint1)) / (2*r^2);
Where img, r, L are constats. a is X(1,:) and b is Y(1,:)
And the call of this function is
peso = bsxfun(#(a,b) fxPesoTexturaCN(a,b,img,r,L), a, b);