compressed sparse row and Jacobi iterative method - sparse-matrix

I've tried implementing Jacobi method for compressed sparse row format. But i couldnt obtain the output correctly. Below is the coding i tried. I'm trying with a 4 by 4 sparse matrix which is a tridiagonal matrix stored in compressed form before implementing Jacobi iterative method. Please help.
clear all;
close all;
clc;
H=4;
a=2;
b=-1;
c=-1;
A = diag(a*ones(1,H)) + diag(b*ones(1,H-1),1) + diag(c*ones(1,H-1),-1);%Matrix A
n = size(A,1); % no of rows
m = size(A,2); % no of columns
V = [];
C = [];
R = [];
counter=1;
R= [counter];
for i=1:n
for j=1:m
if (A(i,j) ~= 0)
V = [V A(i,j)];
C = [C j];
counter=counter+1;
end
R(i+1)=counter;
end
end
b = [9,18,24,3];
x_new = [1 ; 1 ; 1 ; 1];
eps = 1e-5; % 1 x 10^(-10).
error = 1000; % use any large value greater than eps to make sure that the loop can work
counter2=1;
while (error > eps)
x_old = x_new;
for i=1:length(R)-1 %modified
t = 0;
for j=R(i):R(i+1)-1 %modified
if (C(j)~=i) %not equal
t = t + x_old(C(j))*A(i,C(j)); %modified
end
end
x_new(i,1) = (b(i) - t)/A(i,C(j)); % is a row vector
end
error = norm(x_new-x_old);
counter2=counter2+1;
end
x_new % print x
Expected output is
[28.1987 47.3978 48.5979 25.7986]
this is the coding i tried and the expected output is above. Thank you for your time and consideration.

Related

Multithreading Performance in MATLAB C API

I was reading the article Multi-threaded Mex from Undocumented Matlab and decided to benchmark the given example (a max(a,b) function without an explicit output; the function updates a in-place with the maximal values from corresponding indices of the both matrices).
The multithreading starts to show its power for matrices with more than 1 million elements (1000 x 1000 matrix, for example). For small matrices, since the main function is very simple (a for-loop and an if-statement to copy the values from b to a if b[i] > a[i]), we have basically the time necessary for creating the threads. I was expecting that the multithreading would be slower in this context, but not that slower (more than hundred of times). So I decided to come here and ask if those results are reasonable.
The .c file can be found in MATLAB's File Exchange and the benchmark routine was the following.
function t = max_in_place_tester(r,n,~)
if nargin < 1
r = [1e3,5e2,1e2,1e2,1e1,1e0,1e0,1e0];
r = [r.',r.'].';
r = r(1:(end-1));
end
if isempty(r)
r = 1;
end
if nargin < 2
m = maxNumCompThreads;
n = [1e1,1e2,1e3,1e4,1e5,1e6,1e7,1e8];
n = [n.',5*n.'].';
n = n(1:(end-1));
t = zeros(m,size(n,2));
if size(r,2) == 1
r = repmat(r,1,size(n,2));
end
for i = 1:size(n,2)
t(:,i) = max_in_place_tester(r(i),n(i),[]);
end
n = log10(n);
t = t ./ r(1,:);
%t = t ./ t(1,:);
figure('Color','White');
hold on, grid on;
xlabel('log10(Number of Elements)');
ylabel('Relative Time Spent');
for i = 1:m
plot(n,t(i,:)./t(1,:),'LineWidth',2.5,'DisplayName',sprintf('Number of Threads: %d',i));
end
legend;
else
m = maxNumCompThreads;
n = round(sqrt(n));
t = zeros(m,1);
a = rand(n,n);
b = rand(n,n);
c = a;
d = b;
%getaddress(a,b,c,d)
c(1,1) = a(1,1);
d(1,1) = b(1,1);
%getaddress(a,b,c,d)
for i = 1:m
a = c;
b = d;
%getaddress(a,b,c,d)
a(1,1) = c(1,1);
b(1,1) = d(1,1);
%getaddress(a,b,c,d)
maxNumCompThreads(i);
if nargin > 2
s = tic;
for j = 1:r
max_in_place(a,b);
end
t(i,1) = toc(s);
else
fprintf('Number of Threadings: %d\n',maxNumCompThreads);
tic;
for j = 1:r
max_in_place(a,b);
end
toc;
end
end
end
end

How to create a layer of numbers around an array?

Say I have an array B:
B = [1];
I want to use a loop to create a layer of zeros around this array, creating a 2D array with the original 1 in the centre.
How can I do this?
If you have an array and want to create a layer of zeros around it you can use blkdiag:
A = zeros(padsize);
result = blkdiag(A,B,A);
If B is just a scalar and you want create a layer of padvals around it you can use repmat and indexing.
result = repmat(padavl,2*padsize+1);
result(padsize+1,padsize+1) = B;
Provided you have the image processing toolbox, use padarray:
B=1;
padvalue = 0; % Value to pad
padsize = 1; % Amount of rows/columns to pad
padarray(B,[padsize padsize ],padvalue ,'both')
ans =
0 0 0
0 1 0
0 0 0
If you don't have the image processing toolbox, it's easily done by hand:
[X,Y] = size(B); % Get sizes
padvalue = 0;
padsize = 1; % Amount of rows/columns to pad
A = padvalue*ones(X+2*padsize ,Y+2*padsize ); % Initialise with a size of 2 larger
A(2:end-1,2:end-1) = B % Fill with original B
A =
0 0 0
0 1 0
0 0 0
Using a loop is actually much more difficult in this case, but you could do it:
B = 1;
[X,Y] = size(B); % Get sizes
padvalue = 0;
A = padvalue*ones(X+2*padsize ,Y+2*padsize ); % Initialise with a size of 2 larger
for ii = 1:X
for jj = 1:Y
A(ii+padsize ,jj+padsize ) = B(ii,jj); % Grab correct element
end
end
You could concatenate a few ones arrays around the original matrix, I'll use the same padvalue and padsize syntax as Adriaan's answer for easy comparison:
padvalue = 0; % Value to pad around the outside
padsize = 1; % Depth of padding
B = 1; % Some matrix
[r,c] = size(B);
A = [ padvalue*ones(padsize,c+2*padsize);
[padvalue*ones(r,padsize), B, padvalue*ones(r,padsize)];
padvalue*ones(padsize,c+2*padsize) ];

Storing newton iterations in array

I have written a function in matlab that applies the newton method to a given system of equations and its jacobian. The x vector that approaches the intersection of the two functions given in the system of equations however is stored like this:
2.06733483062522 -0.615946742374531
2.25465524043858 -0.428626332561163
1.13788162420748 -1.54539994879227
1.32520203402085 -1.35807953897890
0.802454971005455 -1.88082660199429
0.989775380818824 -1.69350619218092
0.743382354827609 -1.93989921817214
0.930702764640978 -1.75257880835877
0.741429028102197 -1.94185254489755
0.928749437915565 -1.7545321350841
here
x1 = [2.06733~ ; 2.25465~]
and thus they are stored vertically but i want them horizontally underneath each other. Any help is appreciated
I've tried to take the values out in a for loop using even and odd entries but for a system of equations of higher order this wouldnt work.
% INPUT
% f root function (may be vector valued )
% df derivative of f (or function returning Jacobian matrix )
% x0 initial guess
% tol desired tolerance
% maxIt maximum number of iterations
%
% OUTPUT
% x approximate solution
% success true means converged according to error estimator
% errEst error estimate per iteration
% xHist ( optional ) array with intermediate solutions
function [x, success , errEst, xHist ] = newton (f, df, x0 , tol , maxIt )
errEst = []; xHist = [];
for k = 1:1:size(f)
iter = 0; err = inf; x = x0; success = false;
while err > 0 && iter < maxIt
Fun = f{k}(x);
Jac = df{k}(x);
delta = -Jac\Fun;
err = norm(delta);
x = x + delta;
errEst = [errEst; err];
xHist = [xHist; x];
iter = iter + 1;
end
end
if err < tol
success = true;
end
end
it is called like this:
x0 = 1/sqrt(2) * [2;1]; grad = [sqrt(2)/2;sqrt(2)]; n = grad/norm(grad); t = [n(2),-n(1)]; p = 0.5;
x0 = x0 + 2 * (n+t); %x0 = x0 - 2 * (n+t);
f = {#(x)(x(1)/2)^2 + x(2)^2 - 1, #(x)n .* (x - x0) - p - 0.5 .* (t .* (x - x0)) .^ 2};
df = {#(x)x(1)/2 + 2 * x(2), #(x)n - t .* (t .*(x - x0))};
[x, success , errEst , xHist ] = newton(f, df, x0 , 10^(-12) , 20);

Matlab Code summing terms of array

I have a code that is supposed to do the following:
The first function called on, named CalcNum1.m, will find the sum of all the
values in any sized array using a for loop instead of the sum function. This sum divided
by 2 will be saved to the variable Num1.
Finally, in the second function named PrintTerms.m, reorder your terms using the
built in sort function. Now, find how many terms (starting with the first and the
smallest), when adding upon one another, are necessary to surpass the value of Num1.
Print to the user how many terms are necessary.
Here is my code for the main script:
B = input ('Enter matrix B');
[Num1,sum] = CalcNum1(B);
[Q] = PrintTerms(B, Num1);
And here is my code for the functions
function [sum, Num1] = CalcNum1(B)
n = numel(B);
sum1 =0;
for i = 1:n
sum1 = sum1 + B(i);
end
sum = sum1;
Num1 = sum/2;
end
function [Q] = PrintTerms( B, Num1 )
sort (B)
sum1 = 0;
i = 0;
count = 0;
while sum1<=Num1
i = i+1
sum1 = sum1 + B(i)
count = count+1
end
Q = count;
sum1
fprintf(' This many terms necessary %.2f',Q)
end
Try:
function [Num1, my_sum] = CalcNum1(B)
n = numel(B);
my_sum =0;
for i = 1:n
my_sum = my_sum + B(i);
end
Num1 = my_sum/2;
end
Note that I switched the output order, as you call it [Num1,sum] =
function count = PrintTerms( B, Num1 ) % No need for brackets when only single output
B = sort(B); % Need to save it in a new (or the same variable)
% sort(B) will only print the sorted vector
my_sum = 0;
ii = 0;
count = 0;
while my_sum <= Num1
ii = ii+1; % Use semicolons to supress output
my_sum = my_sum + B(ii);
count = count + 1; % Use space for better readability
end
fprintf(' This many terms necessary %.2f \n', count)
% Include \n to get a line shift
end
Use brackets when you type in B, like this: [1 2 3 4 2 3 4 23 12 32 12 2 3 6]
If you want it simpler, you could also use cumsum and avoid the loops. This is your entire last function (except the print part):
vec_sum = cumsum(sort(B)); % See documentation for explanation
count = find(vec_sum >= Num1,1) ; % the second input 1, is to only include the
% first element larger than Num1
Your PrintTerms function seems to work well. As possible problem is that, asuming Num1 is an arbitrary value, if it's so large that it's not reached even with all elements of B, you will try to pull a non-existent further element from B. To avoid that you can add a condition with if and a flag result to indicate whether you had success or not:
% [...]
success = 1; % for now
while (sum1 <= Num1)
ii = ii+1; % Use semicolons to supress output
if ii>length(B)
success = 0; % we ran out of terms
break; % exit while loop
end
sum1 = sum1 + B(ii);
count = count + 1; % Use space for better readability
end
if success
fprintf(' This many terms necessary %.2f', count)
else
fprintf(' The sum cannot be reached')
end
Also, note that sort(B) does not store the result. Use B = sort(B);

Filtering out Non-integers in my array OCTAVE/MATLAB

I have a code that determines prime factors written as:
N=12345678
for i = 2 : N
q = 0;
while N/i == floor(N/i)
N = N/i;
q = q + 1;
end
if q > 0
fac=i
if N == 1
break
end
end
end
However, I want my desired values which are 2, 3 ,47, and 14593 into one single matrix.
How can I do this?
If as it seems your code is in MATLAB, you simply can do this:
N=12345678
fac = [];
for i = 2 : N
q = 0;
while N/i == floor(N/i)
N = N/i;
q = q + 1;
end
if q > 0
fac=[fac, i];
if N == 1
break
end
end
end
Did you try to do it yourself on purpose? You could use Matlab's factor function instead,
factor(N)
which gives the same result.

Resources