Gauss-Seidel method doesn't work for large sparse arrays? - matlab

Once again I have a problem with the Gauss-Seidel Method in Matlab. Here it is:
function [x] = ex1_3(A,b)
format long
sizeA=size(A,1);
x=zeros(sizeA,1);
%Just a check for the conditions of the Gauss-Seidel Method (if it has dominant diagonal)
for i=1:sizeA
sum=0;
for j=1:sizeA
if i~=j
sum=sum+abs(A(i,j));
end
end
if abs(A(i,i))<sum
fprintf('\nGauss-Seidel''s conditions not met!\n');
return
end
end
%Actual Gauss-Seidel Method
max_temp=10^(-6); %Pass first iteration
while max_temp>(0.5*10^(-6))
xprevious=x;
for i=1:sizeA
x(i,1)=b(i,1);
for j=1:sizeA
if i~=j
x(i,1)=x(i,1)-A(i,j)*x(j,1);
end
end
x(i,1)=x(i,1)/A(i,i);
end
x
%Calculating infinite norm of vector x-xprevious
temp=x-xprevious;
max_temp=temp(1,1);
for i=2:sizeA
if abs(temp(i,1))>max_temp
max_temp=abs(temp(i,1));
end
end
end
It actually works fine for a 100x100 matrix or smaller. However, my tutor wants it to work for 100000x100000 matrices. At first it was difficult to even create the matrix itself, but I managed to do it with a little help from here:
Matlab Help Center
Now, I call the ex1_3 function with A as a parameter, but it goes really slow. Actually it never ends. How can I make it work?
Here's my code for creating the specific matrix my tutor wanted:
The important part is just that it meets these conditions:
A(i; i) = 3, A(i - 1; i) = A(i; i + 1) = -1 n=100000
b=ones(100000,1);
b(1,1)=2;
b(100000,1)=2;
i=zeros(299998,1); %Matrix with the lines that we want to put nonzero elements
j=zeros(299998,1); %Matrix with the columns that we want to put nonzero elements
s=zeros(299998,1); %Matrix with the nonzero elements.
number=1;
previousNumberJ=0;
numberJ=0;
for k=1:299998 %Our index in i and j matrices
if mod((k-1),3)==0
s(k,1)=3;
else
s(k,1)=-1;
end
if k==1 || k==2
i(k,1)=1;
j(k,1)=k;
elseif k==299997 || k==299998
i(k,1)=100000;
j(k,1)=(k-200000)+2;
else
if mod(k,3)==0
number=number+1;
numberJ=previousNumberJ+1;
previousNumberJ=numberJ;
end
i(k,1)=number;
j(k,1)=numberJ;
numberJ=numberJ+1;
end
end
A=sparse(i,j,s); %Creating the sparse array
x=ex1_3(A,b);

the for loop works very slowly in Matlab, perhaps you may want to try the matrix form of the iteration:
function x=gseidel(A,b)
max_temp=10^(-6); %Pass first iteration
x=b;
Q=tril(A);
r=b-A*x;
for i=1:100
dx=Q\r;
x=x+1*dx;
r=b-A*x;
% convergence check
if all(abs(r)<max_temp) && all(abs(dx)<max_temp), return; end
end
For your A and b, it only takes 16 steps to converge.
tril extracts the lower triangular part of A, you can also obtain this Q when you build up the matrix. Since Q is already the triangular matrix, you can solve the equation Q*dx=r very easily if you are not allowed to use \ function.

Related

Write a function that takes as input `n` and returns the matrix C, Cij= 0 if i/j<2 , Cij =ij^2 otherwise in MATLAB

Consider the nxn matrix C with elements
Cij = 0 if i/j < 2
Cij = ij^2 otherwise
with 1 <= i,j <= n
Write a Matlab function matSetup that takes as input n and returns the matrix C. Use your function to create C for n = 6. function [Cij]= matSetup(n)
I have written this but it seems not to be correct
function Cij=matSetup(n)
for n=1:n
% whatever you write here is done with i=1, then i=2, then i=3, etc.
Cij(3,j)=i+7;
if (i/j)<2
Cij=0
else
Cij=i*(j)^2
end
end
end
Unfortunately, you can't just write something math-like and have a computer understand it. Things like 1<=i<=n have to be written instead with something like an explicit loop. For Matlab, here's one way to write a loop:
for i=1:n
% whatever you write here is done with i=1, then i=2, then i=3, etc.
end
To assign a value to an element of an array in Matlab, do something like this:
Cij(3,j)=i+7;
To test for a condition in Matlab, do this:
if i+3>2*j
% What you write here is done if the condition is true
else
% What you write here is done if the condition is false
end
If you put all of those things together correctly, you should be able to write your desired function.
Like the other answer, you should first learn to use loops to write a naive program to achieve your goal. When you are comfortable enough, you can try vectorizing your program with functions like meshgrid. Below is an example:
n = 20;
eps = 1/(n+1);
[x, y] = meshgrid(1:n, 1:n);
r = y./x;
z = heaviside(r - 2 + eps) .* y .* x.^2;

Error in regression loop

the following matlab code is a regression loop:
for j=1:size(X,2)
IdentityVector=ones((size(t,1)-1),1);
Y=X((2:end),j);
if j==1
X2=[IdentityVector,X((2:end),((j+1):end)),Diff1X];
elseif j>1 & j<size(X,2)
X2=[IdentityVector,X((2:end),(1:(j-1))),X((2:end),((j+1):end)),Diff1X];
elseif j==size(X,2)
X2=[IdentityVector,X((2:end),(1:(j-1))),Diff1X];
end
[b(:,j)]= regress(Y,X2);
end
this works fine for the beta estimate as it for each j the dimensions of the beta are adjusting accordingly, although if I request from the estimation some additional features/statistics e.g. [b,bint,r,rint,stats] = regress(y,X) the adjustments i have tried for each j do not work. Any help?
My best guess is that you are treating all the outputs as vectors, which they are not. If you read doc regress you will see that bint is a p-by-2, r is n-by-2, so on and so forth. That means you can't assign bint(:,j) because bint itself is a matrix. Instead try cells.
[b{j}, bint{j}, r{j}, rint{j}, stats{j}]= regress(Y,X2);

Matlab: Negative number to the power of n where "n" is bigger than 1 gives an imaginary number

I am running a matlab code in order to solve a matrix in an iterative way, I am trying to solve x=A\b in every iteration until x --> 0 by changing A and b, in the first 3 iterations work fine until I reach a point where I start getting imaginary numbers in my solution.
Here is my code:
Q,H,n,R are predefined variables.
while(eps > 10^-6)
i=1;j=1;
while(i<11)
A11(i,j) = 1.852*R(i)*(abs(Q(i)))^(n-1);
i=i+1;
j=j+1;
end
A11(11,11) = 2*R(11)*abs(Q(11));
%calculate -dE & dq
dE = [200-H(1)-R(1)*Q(1)^1.852
H(1)-H(2)- R(2)*Q(2)^1.852
H(1)-H(3)-R(3)*Q(3)^1.852
H(2)-H(7)-R(4)*Q(4)^1.852
H(6)-H(5)-R(5)*Q(5)^1.852
H(7)-H(4)-R(6)*Q(6)^1.852
H(6)-H(7)-R(7)*(Q(7))^1.852
H(5)-H(4)-R(8)*Q(8)^1.852
H(3)-H(2)-R(9)*Q(9)^1.852
H(3)-H(4)-R(10)*Q(10)^1.852
0-H(3)+240- R(11)*Q(11)];
dq = [-Q(1)+Q(2)+Q(3)
-Q(2)-Q(9)+Q(4)+4
-Q(11)+Q(9)+Q(10)+6
-Q(10)-Q(6)-Q(8)+5
-Q(5)+Q(8)+5
-Q(3)+Q(7)+Q(5)+5
-Q(4)-Q(7)+Q(6)+3];
%formulate the full set of equations
zero=zeros(nn,nn);
b=[dE;dq];
upA = [A11,A12];
downA=[A21,zero];
A= [upA;downA];
%solve the equations (x=A\b)
x = A\b;
%update Q and H
i=1;j=1;
while (i<8 && j<12)
H(i)= x(11+i)+ H(i);
Q(j)= x(j)+ Q(j);
i=i+1;
j=j+1;
end
%check stopping criteria
j=1;sumeps=0;
while (j<12)
sumeps=sumeps+x(j);
j=j+1;
end
epscal = sumeps/12;
eps=abs(epscal)
end
I realized that i start getting problems when one of the values of vector Q turns negative, and when that value is raised to the power of 1.852 (while calculating dE) it gives an imaginary number!!
Maybe someone knows whre
That's correct. (-1)^N has an imaginary component whenever N has a fractional component.
Most obviously, (-1)^0.5 is just i.
It's not the fact hat the power is bigger than 1, it's the fact that the power is not an integer (i.e. X^2, X^3, ...). Imagine X^0.5 which equals sqrt(X). Obviously that yields an imaginary number for negative values of X.

Why the number is not randomized using Matlab

I am trying to write a Matlab code to simulate a dice and compute its mean and standard deviation.
The problem is that no matter how many times we run this code, the result of randi(6) keeps the same. It made me crazy.
n=20;
m=0;
c=0;
for i=1:10000
while m<n
x=randi(6);
c=c+1;
m=m+x;
end
M(i)=m;
count(i)=c;
diff(i)=M(i)-n;
end
I think you forgot to set m back to ZERO at the end of the for. If you want the sequence of randi to change you should take a look at the function "rng".
n=20;
m=0;
c=1;
for i=1:100
while m<n
x(i, c)=randi(6);
m=m+x(i,c);
c=c+1;
end
M(i)=m;
count(i)=c;
diff(i)=M(i)-n;
m = 0;
end
You forgot to reset m and c back to 0 once the while loop terminates. m is set to 0 outside of the for loop only once, and so when m finally surpasses n, m never changes. As such, simply set m = 0 in your for loop before the while loop happens. You also need to set c to 0 because you want to count events each time the for loop iterates.
I'm also not sure how you could think that diff(i) = 2.5 for all i. This difference is a probabilistic value. Also, I don't see how you could get a floating point number in the difference because you are generating integers and accumulating integers for each trial. I think you need to examine what this value should be.
So:
n=20;
%//m=0;
%//c=0;
for i=1:10000
m = 0; %// Change here
c = 0; %// Change here too
while m<n
x=randi(6);
c=c+1;
m=m+x;
end
M(i)=m;
count(i)=c;
diff(i)=M(i)-n;
end

Matlab: fmincon and inequality constraints (implementation issue)

I'm working on an optimization problem in Matlab, but unfortunately, I'm stuck.
I want to maximize \theta using the function fmincon, but this particular problem depends on $n$, and $n$ can get very large. There are $n-1$ inequality constraints, all defined with the relation:
For all i \neq j \leq n : \theta - (x_i - x_j)^2 - (y_i - y_j)^2 \leq 0.
So $c(x)$ is an (n-1)x1 - vector.
I'm looking for a way to implement this, so that I don't have to write a new matlab file for each different $n$. (and as you can imagine, when n gets large, that would be one heck of a job)
Any help would be dearly appreciated.
Cheers!
EDIT : I now have created an extra m.file, just for this constraint:
function constraint(n)
%this is a function which creates the constraints of the distance.
for i= 1: n
for j= 1:n
if j==i
continue;
end
(x(i)-x(j))^2 + (y(i)-y(j))^2;
end
end
But the problem now is that matlab goes over the elements one by one. For example: it doesn't calculate (x(1) - x(4))^2 + (y(1) - y(4))^2.
Any idea on how to solve this one?
Thanks again!
I don't see that your function wouldn't at some point calculate that value (when i = 1 and j = 4). The main issue seems to be that your function doesn't return anything, or take in x. According to this, a constraint function should return two things:
Nonlinear constraint functions must return both c and ceq, the
inequality and equality constraint functions, even if they do not both
exist. Return empty [] for a nonexistent constraint.
So first, we need to make sure our constraints are saved into an output vector, c, that c and an empty ceq are returned, and that our function takes both x and n. There might be prettier ways of doing it but
function [c, ceq] = constraint(x,n)
%this is a function which creates the constraints of the distance.
counter = 1;
for i= 1: n
for j= 1:n
if j==i
continue;
end
c(counter)=(x(i)-x(j))^2 + (y(i)-y(j))^2;
c = c+1;
end
end
ceq = [];
end
Next problem: this function takes two inputs, but nonlcon as an input to fmincon needs to take only one, x. We get around this by wrapping this function in an anonymous function (n needs to be predefined), so in the actual fmincon call you would set it to be something like #(x)constraint(x,n)