As you probably guessed from the title, I'm attempting to do tridiagonal GaussJordan elimination. I'm trying to do it without the default solver. My answers aren't coming out correct and I need some assistance as to where the error is in my code.
I'm getting different values for A/b and x, using the code I have.
n = 4;
#Range for diagonals
ranged = [15 20];
rangesd = [1 5];
#Vectors for tridiagonal matrix
supd = randi(rangesd,[1,n-1]);
d = randi(ranged,[1,n]);
subd = randi(rangesd,[1,n-1]);
#Creates system Ax+b
A = diag(supd,1) + diag(d,0) + diag(subd,-1)
b = randi(10,[1,n])
#Uses default solver
y = A/b
function x = naive_gauss(A,b);
#Forward elimination
for k=1:n-1
for i=k+1:n
xmult = A(i,k)/A(k,k);
for j=k+1:n
A(i,j) = A(i,j)-xmult*A(k,j);
end
b(i) = b(i)-xmult*b(k);
end
end
#Backwards elimination
x(n) = b(n)/A(n,n);
for i=n-1:-1:1
sum = b(i);
for j=i+1:n
sum = sum-A(i,j)*x(j);
end
x(i) = sum/A(i,i)
end
end
x
Your algorithm is correct. The value of y that you compare against is wrong.
you have y=A/b, but the correct syntax to get the solution of the system should be y=A\b.
Related
I'm having some issues getting my RK2 algorithm to work for a certain second-order linear differential equation. I have posted my current code (with the provided parameters) below. For some reason, the value of y1 deviates from the true value by a wider margin each iteration. Any input would be greatly appreciated. Thanks!
Code:
f = #(x,y1,y2) [y2; (1+y2)/x];
a = 1;
b = 2;
alpha = 0;
beta = 1;
n = 21;
h = (b-a)/(n-1);
yexact = #(x) 2*log(x)/log(2) - x +1;
ye = yexact((a:h:b)');
s = (beta - alpha)/(b - a);
y0 = [alpha;s];
[y1, y2] = RungeKuttaTwo2D(f, a, b, h, y0);
error = abs(ye - y1);
function [y1, y2] = RungeKuttaTwo2D(f, a, b, h, y0)
n = floor((b-a)/h);
y1 = zeros(n+1,1); y2 = y1;
y1(1) = y0(1); y2(1) = y0(2);
for i=1:n-1
ti = a+(i-1)*h;
fvalue1 = f(ti,y1(i),y2(i));
k1 = h*fvalue1;
fvalue2 = f(ti+h/2,y1(i)+k1(1)/2,y2(i)+k1(2)/2);
k2 = h*fvalue2;
y1(i+1) = y1(i) + k2(1);
y2(i+1) = y2(i) + k2(2);
end
end
Your exact solution is wrong. It is possible that your differential equation is missing a minus sign.
y2'=(1+y2)/x has as its solution y2(x)=C*x-1 and as y1'=y2 then y1(x)=0.5*C*x^2-x+D.
If the sign in the y2 equation were flipped, y2'=-(1+y2)/x, one would get y2(x)=C/x-1 with integral y1(x)=C*log(x)-x+D, which contains the given exact solution.
0=y1(1) = -1+D ==> D=1
1=y1(2) = C*log(2)-1 == C=1/log(2)
Additionally, the arrays in the integration loop have length n+1, so that the loop has to be from i=1 to n. Else the last element remains zero, which gives wrong residuals for the second boundary condition.
Correcting that and enlarging the computation to one secant step finds the correct solution for the discretization, as the ODE is linear. The error to the exact solution is bounded by 0.000285, which is reasonable for a second order method with step size 0.05.
At first I create a script giving the name multi_002
After I create the function that includes the equation
The script calls the function and reads the array 'a'.
Each array include one equation a(i) = x - i
I want to minimize its equation of the 4 lines array 'a'.
I suspect that something doesn't work right. I notice that
Optimtool works but f1,f2,f3,f4 doesn't go to zero. With another words
there isn't convergence.
FitnessFunction = #array_002;
numberOfVariables = 1;
[x,fval] = gamultiobj(FitnessFunction,numberOfVariables);
function [a,y,c]= array_002(x)
size = 4; n = 4;
y = zeros(size,1);
c = zeros(size,1);
for i = 1:n
y(i) = x;
c(i) = i;
a = y - c;
end
Why my genetic algorithm doesn't converge? Is there any idea?
Thank you in advance!
I can't seem to find a fix to my infinite loop. I have coded a Jacobi solver to solve a system of linear equations.
Here is my code:
function [x, i] = Jacobi(A, b, x0, TOL)
[m n] = size(A);
i = 0;
x = [0;0;0];
while (true)
i =1;
for r=1:m
sum = 0;
for c=1:n
if r~=c
sum = sum + A(r,c)*x(c);
else
x(r) = (-sum + b(r))/A(r,c);
end
x(r) = (-sum + b(r))/A(r,c);
xxx end xxx
end
if abs(norm(x) - norm(x0)) < TOL;
break
end
x0 = x;
i = i + 1;
end
When I terminate the code it ends at the line with xxx
The reason why your code isn't working is due to the logic of your if statements inside your for loops. Specifically, you need to accumulate all values for a particular row that don't belong to the diagonal of that row first. Once that's done, you then perform the division. You also need to make sure that you're dividing by the diagonal coefficient of A for that row you're concentrating on, which corresponds to the component of x you're trying to solve for. You also need to remove the i=1 statement at the beginning of your loop. You're resetting i each time.
In other words:
function [x, i] = Jacobi(A, b, x0, TOL)
[m n] = size(A);
i = 0;
x = [0;0;0];
while (true)
for r=1:m
sum = 0;
for c=1:n
if r==c %// NEW
continue;
end
sum = sum + A(r,c)*x(c); %// NEW
end
x(r) = (-sum + b(r))/A(r,r); %// CHANGE
end
if abs(norm(x) - norm(x0)) < TOL;
break
end
x0 = x;
i = i + 1;
end
Example use:
A = [6 1 1; 1 5 3; 0 2 4]
b = [1 2 3].';
[x,i] = Jacobi(A, b, [0;0;0], 1e-10)
x =
0.048780487792648
-0.085365853612062
0.792682926806031
i =
20
This means it took 20 iterations to achieve a solution with tolerance 1e-10. Compare this with MATLAB's built-in inverse:
x2 = A \ b
x2 =
0.048780487804878
-0.085365853658537
0.792682926829268
As you can see, I specified a tolerance of 1e-10, which means we are guaranteed to have 10 decimal places of accuracy. We can certainly see 10 decimal places of accuracy between what Jacobi gives us with what MATLAB gives us built-in.
In Matlab I want to create the partial derivative of a cost function called J(theta_0, theta_1) (in order to do the calculations necessary to do gradient descent).
The function J(theta_0, theta_1) is defined as:
Lets say h_theta(x) = theta_1 + theta_2*x. Also: alpha is fixed, the starting values of theta_1 and theta_2 are given. Let's say in this example: alpha = 0.1 theta_1 = 0, theta_2 = 1. Also I have all the values for x and y in two different vectors.
VectorOfX =
5
5
6
VectorOfX =
6
6
10
Steps I took to try to solve this in Matlab: I have no clue how to solve this problem in matlab. So I started off with trying to define a function in Matlab and tried this:
theta_1 = 0
theta_2 = 1
syms x;
h_theta(x) = theta_1 + t2*x;
This worked, but is not what I really wanted. I wanted to get x^(i), which is in a vector. The next thing I tried was:
theta_1 = 0
theta_2 = 1
syms x;
h_theta(x) = theta_1 + t2*vectorOfX(1);
This gives the following error:
Error using sym/subsindex (line 672)
Invalid indexing or function definition. When defining a
function, ensure that the body of the function is a SYM
object. When indexing, the input must be numeric, logical or
':'.
Error in prog1>gradientDescent (line 46)
h_theta(x) = theta_1 + theta_2*vectorOfX(x);
I looked up this error and don't know how to solve it for this particular example. I have the feeling that I make matlab work against me instead of using it in my favor.
When I have to perform symbolic computations I prefer to use Mathematica. In that environment this is the code to get the partial derivatives you are looking for.
J[th1_, th2_, m_] := Sum[(th1 + th2*Subscript[x, i] - Subscript[y, i])^2, {i, 1, m}]/(2*m)
D[J[th1, th2, m], th1]
D[J[th1, th2, m], th2]
and gives
Coming back to MATLAB we can solve this problem with the following code
%// Constants.
alpha = 0.1;
theta_1 = 0;
theta_2 = 1;
X = [5 ; 5 ; 6];
Y = [6 ; 6 ; 10];
%// Number of points.
m = length(X);
%// Partial derivatives.
Dtheta1 = #(theta_1, theta_2) sum(2*(theta_1+theta_2*X-Y))/2/m;
Dtheta2 = #(theta_1, theta_2) sum(2*X.*(theta_1+theta_2*X-Y))/2/m;
%// Loop initialization.
toll = 1e-5;
maxIter = 100;
it = 0;
err = 1;
theta_1_Last = theta_1;
theta_2_Last = theta_2;
%// Iterations.
while err>toll && it<maxIter
theta_1 = theta_1 - alpha*Dtheta1(theta_1, theta_2);
theta_2 = theta_2 - alpha*Dtheta2(theta_1, theta_2);
it = it + 1;
err = norm([theta_1-theta_1_Last ; theta_2-theta_2_Last]);
theta_1_Last = theta_1;
theta_2_Last = theta_2;
end
Unfortunately for this case the iterations does not converge.
MATLAB is not very flexible for symbolic computations, however a way to get those partial derivatives is the following
m = 10;
syms th1 th2
x = sym('x', [m 1]);
y = sym('y', [m 1]);
J = #(th1, th2) sum((th1+th2.*x-y).^2)/2/m;
diff(J, th1)
diff(J, th2)
I need to code the Gauss Seidel and Successive over relaxation iterative methods in Matlab. I have created the below code for each of them, however my final solution vector does not return the correct answers and i'm really struggling to figure out why. Could anyone please help me?
In both cases, x is the final solution vector and i returns the number of iterations.
Thanks in advance
Gauss Seidel Method:
function [x,i] = gaussSeidel(A,b,x0,tol)
x2 = x0;
count = 0;
D = diag(diag(A));
U = triu(A-D);
disp(U);
L = tril(A-D);
disp(L);
C = diag(diag(A));
disp(C);
Inv = inv(C+D);
error = inf;
while error>tol
x1 = x2;
x2 = Inv*(b-(U*x1));
error = max(abs(x2-x1)/abs(x1));
count = count + 1;
end
x = x2;
i = count;
end
SOR Method:
function [x,i] = sor(A,b,x0,tol,omega)
[m,n] = size(A);
D = diag(diag(A));
U = triu(A-D);
L = tril(A-D);
count = 1;
xtable = x0;
w = omega;
if size(b) ~= size(x0)
error('The given approximation vector does not match the x vector size');
elseif m~=n
error('The given coefficient matrix is not a square');
else
xnew = (inv(D+w*L))*(((1-w)*D-w*U)*x0 +w*b);
RelError = (abs(xnew-x0))/(abs(xnew));
RelErrorCol = max(max(RelError));
while RelErrorCol>tol
xnew = (inv(D+w*L))*(((1-w)*D-w*U)*x0 +w*b);
RelError = (abs(xnew-x0))/(abs(xnew));
RelErrorCol = max(max(RelError));
x0 = xnew;
count = count+1;
xtable = [xtable, xnew];
end
disp(xtable);
x = xnew;
i = count;
end
Gauss-Seidel: Your line that describes C is wrong. Actually it shouldn't be there. Also for the Inv line, it should be inv(D+L), not inv(C+D).
As for the SOR method, in hindsight it seems right. To double check, compare with this method:
http://www.netlib.org/templates/matlab/sor.m. This method relies on http://www.netlib.org/templates/matlab/split.m
Edit: April 4, 2014 - Also check: https://www.dropbox.com/s/p9wlzi9x9evqj5k/MTH719W2013_Assn4_Part1.pdf?dl=1 . I taught a course on Applied Linear Algebra and have MATLAB code that implements Gauss-Seidel and SOR. Check slides 12-20 for the theory and how to implement Gauss-Seidel and slides 35-37 for the SOR method.
Let me know how it goes.