MATLAB find the average time using tic toc - matlab

Construct an experiment to study the performance of the Cramer rule (with two implementations
determinants) in relation to Gauss's algorithm.
In each iteration 10 random arrays A (NxN), and vectors b (Nx1) will be created.
The 10 linear systems will be solved using the Cramer rule ("cramer.m") using
of rec_det (A) and using det (A), and the Gaussian algorithm
(“GaussianElimination.m”), and the time for each technique will be the average of 10 values.
Repeat the above for N = 2 to 10 and make a graph of the average time
in relation to the dimension N.
This is my task. I dont know if the way that I calculate the average time is correct and the graphic is not displayed.
T1=0;
T2=0;
T3=0;
for N=2:10
for i=1:10
A=rand(N,N);
b=rand(N,1);
t1=[1,i];
t2=[1,i];
t3=[1,i];
tic;
crammer(A,b);
t1(i)=toc;
tic
crammer_rec(A,b);
t2(i)=toc;
tic
gaussianElimination(A,b);
t3(i)=toc;
T1=T1+t1(i);
T2=T2+t2(i);
T3=T3+t3(i);
end
avT1=T1/10;
avT2=T2/10;
avT3=T3/10;
end
plot(2:10 , avT1 , 2:10 , avT2 , 2:10 , avT3);
function x = cramer(A, b)
n = length(b);
d = det(A);
% d = rec_det(A);
x = zeros(n, 1);
for j = 1:n
x(j) = det([A(:,1:j-1) b A(:,j+1:end)]) / d;
% x(j) = rec_det([A(:,1:j-1) b A(:,j+1:end)]) / d;
end
end
function x = cramer(A, b)
n = length(b);
d = rec_det(A);
x = zeros(n, 1);
for j = 1:n
x(j) = rec_det([A(:,1:j-1) b A(:,j+1:end)]) / d;
end
end
function deta = rec_det(R)
if size(R,1)~=size(R,2)
error('Error.Matrix must be square.')
else
n = size(R,1);
if ( n == 2 )
deta=(R(1,1)*R(2,2))-(R(1,2)*R(2,1));
else
for i=1:n
deta_temp=R;
deta_temp(1,:)=[ ];
deta_temp(:,i)=[ ];
if i==1
deta=(R(1,i)*((-1)^(i+1))*rec_det(deta_temp));
else
deta=deta+(R(1,i)*((-1)^(i+1))*rec_det(deta_temp));
end
end
end
end
end
function x = gaussianElimination(A, b)
[m, n] = size(A);
if m ~= n
error('Matrix A must be square!');
end
n1 = length(b);
if n1 ~= n
error('Vector b should be equal to the number of rows and columns of A!');
end
Aug = [A b]; % build the augmented matrix
C = zeros(1, n + 1);
% elimination phase
for k = 1:n - 1
% ensure that the pivoting point is the largest in its column
[pivot, j] = max(abs(Aug(k:n, k)));
C = Aug(k, :);
Aug(k, :) = Aug(j + k - 1, :);
Aug(j + k - 1, :) = C;
if Aug(k, k) == 0
error('Matrix A is singular');
end
for i = k + 1:n
r = Aug(i, k) / Aug(k, k);
Aug(i, k:n + 1) = Aug(i, k:n + 1) - r * Aug(k, k: n + 1);
end
end
% back substitution phase
x = zeros(n, 1);
x(n) = Aug(n, n + 1) / Aug(n, n);
for k = n - 1:-1:1
x(k) = (Aug(k, n + 1) - Aug(k, k + 1:n) * x(k + 1:n)) / Aug(k, k);
end
end

I think the easiest way to do this is by creating a 9 * 3 dimensional matrix to contain all the total times, and then take the average at the end.
allTimes = zeros(9, 3);
for N=2:10
for ii=1:10
A=rand(N,N);
b=rand(N,1);
tic;
crammer(A,b);
temp = toc;
allTimes(N-1,1) = allTimes(N-1,1) + temp;
tic
crammer_rec(A,b);
temp = toc;
allTimes(N-1,2) = allTimes(N-1,2) + temp;
tic
gaussianElimination(A,b);
temp = toc;
allTimes(N-1,3) = allTimes(N-1,3) + temp;
end
end
allTimes = allTimes/10;
figure; plot(2:10, allTimes);
You can use this approach because the numbers are quite straightforward and simple. If you had a more complicated setup, the way to store the times/calculate the averages would have to be tweaked.
If you had more functions you could also use function handles and create a third inner loop, but this is a little more advanced.

Related

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);

Vectorize MATLAB for loop

I have the following lines of code
y = zeros(n, 1);
for i=1:n
b = L * [u(i:-1:max(1,i-M+1));zeros((-i+M)*(i-M<0),1)];
y(i) = b' * gamma;
end
u is nx1, gamma is Mx1 and L is MxM
n takes very large values, so are there any ideas on how to vectorize the for loop?
Discussion and solution code
Initial approach
Matrix-multiplications based approach -
u_pad = [zeros(M-1,1) ; u]; %// Pad u with zeros
idx = bsxfun(#plus,[M:-1:1]',0:n-1);%//'# Calculate sliding indices for u
u_pad_indexed = u_pad(idx); %// Index into padded u
y_vectzed = gamma.'*L*u_pad_indexed;%//'# Matrix-multiplications for final o/p
Modified approach
Now, you have huge datasizes to work with. So, to optimize for such a case, the data could be broken into smaller pieces that are runnable and the operations could be done iteratively. Then, each iteration would calculate a part of the output array.
With this new strategy, the intial setting up could be done once and reused within each iteration. The modified approach would look something like this -
div_factor = [...] %// Make sure it is a divisor of n
nrows = n/div_factor;
start_idx = bsxfun(#plus,[M:-1:1]',0:nrows-1); %//'
u_pad = [zeros(M-1,1) ; u];
y_vectorized = zeros(div_factor,n/div_factor);
for iter = 1:div_factor
u_pad_indexed = u_pad((iter-1)*nrows + start_idx);
y_vectorized(iter,:) = gamma.'*L*u_pad_indexed; %//'
end
y_vectorized = reshape(y_vectorized.',[],1);
Benchmarking
%// Size parameters and input arrays
n = 4000000;
M = 1000;
u = rand(n,1);
gamma = rand(M,1);
L = rand(M,M);
%// Warm up tic/toc.
for k = 1:50000
tic(); elapsed = toc();
end
disp('----------- With Original loopy code');
tic
y = zeros(n, 1);
for i=1:n
b = L * [u(i:-1:max(1,i-M+1));zeros((-i+M)*(i-M<0),1)];
y(i) = b' * gamma; %//'
end
toc
clear b y
disp('----------- With Proposed solution code');
tic
..... Proposed Modified Code with div_factor = 200
toc
Runtimes
----------- With Original loopy code
Elapsed time is 498.563049 seconds.
----------- With Proposed solution code
Elapsed time is 44.273299 seconds.
Edit: I am redoing the solution because I found out that Matlab does not handle anonymous functions well. So I changed the call from an anonymous function to a normal function. Making this change:
Test 1
Comparison(40E3, 3E3)
Elapsed time is 21.731176 seconds.
Elapsed time is 251.327347 seconds.
|y2-y1| = 3.1519e-06
Test 2
Comparison(40E3, 1E3)
Elapsed time is 6.407259 seconds.
Elapsed time is 25.551116 seconds.
|y2-y1| = 2.8402e-07
Test 3
Comparison(20E3, 3E3)
Elapsed time is 10.484422 seconds.
Elapsed time is 125.033313 seconds.
|y2-y1| = 1.5462e-06
Test 4
Comparison(20E3, 1E3)
Elapsed time is 3.153404 seconds.
Elapsed time is 13.200649 seconds.
|y2-y1| = 1.5627e-07
The function is:
function Comparison(n, M)
u = rand(n, 1);
L = rand(M);
gamma = rand(M, 1);
tic
y1 = vectorized(u, L, gamma);
toc
tic
y2 = looped(u, L, gamma);
toc
disp(['|y2-y1| = ', num2str(norm(y2 - y1, 1))])
end
function y = vectorized(u, l, gamma)
global a Column
M = length(gamma);
Column = l' * gamma;
x = bsxfun(#plus, -(1:M)', (1:length(u)) + 1);
x(x < 1) = 1;
a = u(x);
a(1:M, 1:M) = a(1:M, 1:M) .* triu(ones(M));
a = a';
m = 1:size(a,1);
y = arrayfun(#VectorY , m)';
end
function yi = VectorY(j)
global a Column
yi = a(j,:) * Column;
end
function y = looped(U, l, gamma)
n = length(U);
M = length(gamma);
u = U';
L = l';
y = zeros(n, 1);
for i=1:n
y(i) = [u(i:-1:max(1,i-M+1)), zeros(1,(-i+M)*(i-M<0))] * L * gamma;
end
end

MATLAB sparse matrices: Gauss Seidel and power method using a sparse matrix with CSR (Compressed Sparse Row)

this is my first time here so I hope that someone can help me.
I'm trying to implementing the Gauss-Seidel method and the power method using a matrix with the storage CSR or called Morse storage. Unfortunately I can't manage to do better then the following codes:
GS-MORSE:
function [y] = gs_morse(aa, diag, col, row, nmax, tol)
[n, n] = size(A);
y = [1, 1, 1, 1];
m = 1;
while m < nmax,
for i = 1: n,
k1 = row(i);
k2 = row(i + 1) - 1;
for k = k1: k2,
y(i) = y(i) + aa(k) * x(col(k));
y(col(k)) = y(col(k)) + aa(k) * diag(i);
end
k2 = k2 + 1;
y(i) = y(i) + aa(k) * diag(i);
end
if (norm(y - x)) < tol
disp(y);
end
m = m + 1;
for i = 1: n,
x(i) = y(i);
end
end
POWER-MORSE:
I was able only to implement the power method but I don't understand how to use the former matrix... so my code for power method is:
function [y, l] = potencia_iterada(A, v)
numiter=100;
eps=1e-10;
x = v(:);
y = x/norm(x);
l = 0;
for k = 1: numiter,
x = A * y;
y = x / norm(x);
l0 = x.' * y;
if abs(l0) < eps
return
end
l = l0;
end
Please anyone can help me for completing these codes or can explain me how can I do that? I really don't understand how to do. Thank you very much

Vectorizing a nested for loop which fills a dynamic programming table

I was wondering if there was a way to vectorize the nested for loop in this function which is filling up the entries of the 2D dynamic programming table DP. I believe that at the very least the inner loop could be vectorized as each row only depends on the previous row. I'm not sure how to do it though. Note this function is called on large 2D arrays (images) so the nested for loop really doesn't cut it.
function [cols] = compute_seam(energy)
[r, c, ~] = size(energy);
cols = zeros(r);
DP = padarray(energy, [0, 1], Inf);
BP = zeros(r, c);
for i = 2 : r
for j = 1 : c
[x, l] = min([DP(i - 1, j), DP(i - 1, j + 1), DP(i - 1, j + 2)]);
DP(i, j + 1) = DP(i, j + 1) + x;
BP(i, j) = j + (l - 2);
end
end
[~, j] = min(DP(r, :));
j = j - 1;
for i = r : -1 : 1
cols(i) = j;
j = BP(i, j);
end
end
Vectorization of the innermost nested loop
You were right in postulating that at least the inner loop is vectorizable. Here's the modified code for the nested loops part -
rows_DP = size(DP,1); %// rows in DP
%// Get first row linear indices for a group of neighboring three columns,
%// which would be incremented as we move between rows with the row iterator
start_ind1 = bsxfun(#plus,[1:rows_DP:2*rows_DP+1]',[0:c-1]*rows_DP); %//'
for i = 2 : r
ind1 = start_ind1 + i-2; %// setup linear indices for the row of this iteration
[x,l] = min(DP(ind1),[],1); %// get x and l values in one go
DP(i,2:c+1) = DP(i,2:c+1) + x; %// set DP values of a row in one go
BP(i,1:c) = [1:c] + l-2; %// set BP values of a row in one go
end
Benchmarking
Benchmarking Code -
N = 3000; %// Datasize
energy = rand(N);
[r, c, ~] = size(energy);
disp('------------------------------------- With Original Code')
DP = padarray(energy, [0, 1], Inf);
BP = zeros(r, c);
tic
for i = 2 : r
for j = 1 : c
[x, l] = min([DP(i - 1, j), DP(i - 1, j + 1), DP(i - 1, j + 2)]);
DP(i, j + 1) = DP(i, j + 1) + x;
BP(i, j) = j + (l - 2);
end
end
toc,clear DP BP x l
disp('------------------------------------- With Vectorized Code')
DP = padarray(energy, [0, 1], Inf);
BP = zeros(r, c);
tic
rows_DP = size(DP,1); %// rows in DP
start_ind1 = bsxfun(#plus,[1:rows_DP:2*rows_DP+1]',[0:c-1]*rows_DP); %//'
for i = 2 : r
ind1 = start_ind1 + i-2; %// setup linear indices for the row of this iteration
[x,l] = min(DP(ind1),[],1); %// get x and l values in one go
DP(i,2:c+1) = DP(i,2:c+1) + x; %// set DP values of a row in one go
BP(i,1:c) = [1:c] + l-2; %// set BP values of a row in one go
end
toc
Results -
------------------------------------- With Original Code
Elapsed time is 44.200746 seconds.
------------------------------------- With Vectorized Code
Elapsed time is 1.694288 seconds.
Thus, you might enjoy a good 26x speedup improvement in performance with that little vectorization tweak.
More tweaks
Few more optimization tweaks could be tried into your code for performance -
cols = zeros(r) could be replaced with col(r,r) = 0.
DP = padarray(energy, [0, 1], Inf) could be replaced with
DP(1:size(energy,1),1:size(energy,2)+2)=Inf;
DP(:,2:end-1) = energy;
BP = zeros(r, c) could be replaced with BP(r, c) = 0.
The pre-allocation tweaks used here are inspired by this blog post.

How can I make recursive function for binary tree in matlab

V is a image matrix.D0 and D1 are right and left root of binary trees for level 1.
this is a binary tree and it has 8 level. this means a lots of code . I want to make it with recursive function.And as an Output I need all roots of means in array M. Please any idea to make it recursive?
clear all;clc;
V=imread('tire.tif');
[x y]=size(V);
U=V*0;
M=zeros(1,511);
% LEVEL 1
M(1,1)=mean(V(:));
% LEVEL 2
D0=V(V<=mean(V(:))); % right root for V
M(1,2)=mean(D0(:));
D1=V(V>mean(V(:))); %left root for V
M(1,3)=mean(D1(:));
% LEVEL 3
D00=D0(D0<=mean(D0(:))); %left root for D0
M(1,4)=mean(D00(:));
D01=D0(D0>mean(D0(:))); %left root for D0
M(1,5)=mean(D01(:));
D10=D1(D1<=mean(D1(:))); %right root for D1
M(1,6)=mean(D10(:));
D11=D1(D1>mean(D1(:))); %left root for D1
M(1,7)=mean(D11(:));
I believe this is the solution you are looking for. The tricky part is keeping track of the indices (as usual).
function M = myrecfun(V, M, n_max, n, i)
%n: current level (of recursions)
%i: an integer in [1, 2^(n-1)]
i_start = 2^n;
meanV = mean(V(:));
if n == 1
M(1) = meanV
end
DR = V(V <= meanV);
DL = V(V > meanV);
iR = i_start + 2*i - 2;
iL = i_start + 2*i - 1;
M(iR) = mean(DR);
M(iL) = mean(DL);
if n < n_max
M = myrecfun(DR, M, n_max, n+1, iR - i_start + 1);
M = myrecfun(DL, M, n_max, n+1, iL - i_start + 1);
else % else of if n < n_max
M;
end % end of if n < n_max
end % of myrecfun
Call the code:
n_max = 8;
V = 100*rand(100,100); %Just my example
M = zeros(1, 2^(n_max+1)-1);
Mout = myrecfun(V, M, n_max, 1, 1);
Test the output:
sum(Mout< 50)
ans =
256
sum(Mout > 50)
ans =
255