diff --git a/ENUME/references/ENUME_Project1/README.md b/ENUME/references/ENUME_Project1/README.md new file mode 100644 index 00000000..7bd595bb --- /dev/null +++ b/ENUME/references/ENUME_Project1/README.md @@ -0,0 +1,30 @@ +# ENUME_Project1 +A Numerical Method project cointaining 4 tasks. +## 1. +Write a program finding macheps in the MATLAB environment on a lab computer or your +computer. +## 2. +Write a general program solving a system of n linear equations Ax = b using the indicated +method Apply the program to solve the system of linear equations for given matrix A and vector b, for increasing numbers +of equations n = 10,20,40,80,160,… until the solution time becomes prohibitive (or the +method fails), for: +### a) +Aij { for i = j -> 13, for i = j-1 or i = j+1 -> 4, other -> 0 \ +Bi = 2.4 + 0.6i, \ +i,j = 1..n; +### b) +Aij = 4/[5(i + j – 1)], Bi = 1/(2 i), i – odd; Bi = 0, i – even, i, j = 1,…,n; + +## 3 +Write a general program for solving the system of n linear equations Ax = b using the +Gauss-Seidel and Jacobi iterative algorithms. Apply it for the system: \ +13x1 + 2x2 – 8x3 + x4 =16 \ +x1 + 10x2 + 5x3 – 2x4 = 24 \ +6x1 + 2x2 – 23x3 + 15x4 = 184 \ +x1 + 2x2 – x3 + 13x4 = 82 + +## 4 +Write a program of the QR method for finding eigenvalues of 5×5 matrices: \ +a) without shifts; \ +b) with shifts calculated on the basis of an eigenvalue of the 2×2 right-lower-corner +submatrix. diff --git a/ENUME/references/ENUME_Project1/Raport.pdf b/ENUME/references/ENUME_Project1/Raport.pdf new file mode 100644 index 00000000..344a33e5 Binary files /dev/null and b/ENUME/references/ENUME_Project1/Raport.pdf differ diff --git a/ENUME/references/ENUME_Project1/ResidualCorrection.m b/ENUME/references/ENUME_Project1/ResidualCorrection.m new file mode 100644 index 00000000..708bb5e8 --- /dev/null +++ b/ENUME/references/ENUME_Project1/ResidualCorrection.m @@ -0,0 +1,30 @@ +function [TableOfErrors] = ResidualCorrection(n, subpoint) + TableOfErrors = zeros(n, 1); + TableOfErrorsAC = zeros(n, 1); + TableOfErrorsAC2 = zeros(n, 1); + TableOfNValues = zeros(n, 1); + for i = 1:n + TableOfNValues(i) = 10*2^(i-1); + disp(i); + x = TASK2(10*2^(i-1)); + if subpoint == 'A' + x = TaskA(x); + elseif subpoint == 'B' + x = TaskB(x); + end + TableOfErrors(i) = norm(x.errors); + x = ResidualCorrection(x); + x= GetErrors(x); + TableOfErrorsAC(i) = norm(x.errors); + x = ResidualCorrection(x); + x= GetErrors(x); + TableOfErrorsAC2(i) = norm(x.errors); + end + plot(TableOfNValues, TableOfErrors, '-o'); + hold on; + ylabel('Maximal absolute value of an error') + xlabel('N') + plot(TableOfNValues, TableOfErrorsAC, '-or'); + plot(TableOfNValues, TableOfErrorsAC2, '-og'); + hold off; +end \ No newline at end of file diff --git a/ENUME/references/ENUME_Project1/TASK1.m b/ENUME/references/ENUME_Project1/TASK1.m new file mode 100644 index 00000000..80c27653 --- /dev/null +++ b/ENUME/references/ENUME_Project1/TASK1.m @@ -0,0 +1,8 @@ +function macheps = Task1() + macheps = 1; + while 1 + (macheps/2)>1 + macheps = macheps/2; + end +end + + diff --git a/ENUME/references/ENUME_Project1/TASK2.m b/ENUME/references/ENUME_Project1/TASK2.m new file mode 100644 index 00000000..2c793a01 --- /dev/null +++ b/ENUME/references/ENUME_Project1/TASK2.m @@ -0,0 +1,161 @@ +classdef TASK2 + properties + %main array size n by n + A; + %second array size n + B; + %answer + x; + %errors + errors; + %size of a matricx + n; + end + methods (Access = 'protected') + function [obj, locx] = gaussWithPartialPiv(obj) + locx = zeros(obj.n, 1); + for j = 1:obj.n + %finding the maximal value of a column + index = j; + locMax = abs(obj.A(j, j)); + for i = j+1:obj.n + if abs(obj.A(i, j)) > locMax + locMax = abs(obj.A(i, j)); + index = i; + end + end + %checking neccessary condition for the further execution + if locMax == 0 + disp(locMax); + disp('Wrong Matrix'); + return + end + if index ~= j + %swaping the rows in neccessary (highest value found + %not in j row) + obj.A([index, j],:) = obj.A([j, index],:); + obj.B([index, j]) = obj.B([j, index]); + end + for i = j+1:obj.n + r = obj.A(i, j)/obj.A(j,j); + %if r == 0 we dont need to continue + if r ~= 0 + %changing the main array A + for locj = j+1:obj.n + obj.A(i, locj) = obj.A(i, locj) - r*obj.A(j, locj); + end + %and the B array aswell + obj.B(i) = obj.B(i) - r*obj.B(j); + end + end + end + %now finally we can obtain the results + %Xn value is rather obvious + locx(obj.n) = obj.B(obj.n)/obj.A(obj.n, obj.n); + for i = obj.n-1:-1:1 + buffor = 0; + for j = i+1:obj.n + buffor = buffor + obj.A(i, j)*locx(j); + end + locx(i) = (obj.B(i) - buffor)/obj.A(i,i); + end + end + function obj = TaskAArray(obj) + [row, columns] = size(obj.A); + if row ~= size(obj.B) + disp('A and B array size is different!'); + return + end + for i = 1:row + %setting the A array + for j = 1:columns + if i == j + obj.A(i, j) = 13; + elseif i == j-1 || i == j+1 + obj.A(i, j) = 4; + else + obj.A(i, j) = 0; + end + end + %setting he B array + obj.B(i) = 2.4 + 0.6*i; + end + end + function obj = TaskBArray(obj) + [row, columns] = size(obj.A); + if row ~= size(obj.B) + disp('A and B array size is differn!'); + return + end + for i = 1:row + %setting the A array + for j = 1:columns + obj.A(i, j) = 4/(5*(i + j - 1)); + end + %setting he B array + if mod(i, 2) == 0 + obj.B(i) = 1/(2*i); + else + obj.B(i) = 0; + end + end + end + function obj = SetSize(obj, n) + obj.A = zeros(n); + obj.B = zeros(n, 1); + obj.x = zeros(n,1); + obj.errors = zeros(n,1); + obj.n = n; + end + end + %public methods + methods + function obj = TASK2(n) + obj.n = n; + end + function obj = GetErrors(obj) + %colculating the error following the formula r = Ax - b + for i = 1:obj.n + result = 0; + for j = i:obj.n + result = result + obj.A(i,j) * obj.x(j); + end + obj.errors(i) = result - obj.B(i); + end + end + function obj = ResidualCorrection(obj) + newObj = TASK2(obj.n); + newObj = obj; + newObj.B = newObj.errors; + [newObj, newObj.x] = gaussWithPartialPiv(newObj); + for i = 1:obj.n + obj.x(i) = obj.x(i) - newObj.x(i); + end + end + function obj = TaskA(obj) + obj = SetSize(obj, obj.n); + obj = TaskAArray(obj); + [obj, obj.x] = gaussWithPartialPiv(obj); + obj = GetErrors(obj); + end + function obj = TaskB(obj) + obj = SetSize(obj, obj.n); + obj = TaskBArray(obj); + [obj, obj.x] = gaussWithPartialPiv(obj); + obj = GetErrors(obj); + end + function DispSolutionAndError(obj) + format long + disp('x for n ='); disp(obj.n); + obj.x + disp('errors for n ='); disp(obj.n); + obj.errors + end + function DispObjects(obj) + obj.A + obj.B + obj.x + obj.errors + end + end +end \ No newline at end of file diff --git a/ENUME/references/ENUME_Project1/TASK3.m b/ENUME/references/ENUME_Project1/TASK3.m new file mode 100644 index 00000000..7ebc916f --- /dev/null +++ b/ENUME/references/ENUME_Project1/TASK3.m @@ -0,0 +1,155 @@ +classdef TASK3 < TASK2 + properties + acc = 1e-10; + end + methods (Access = 'private') + function [obj, array]= gaussSeidel(obj, type) + array = []; + err = inf; + k = 1; + m = 10000; + while k <= m && err > obj.acc + localMax = 0; + for i = 1 : obj.n + s = 0; + for j = 1 : obj.n + s = s+(-obj.A(i,j)*obj.x(j)); + end + s = (s+obj.B(i))/obj.A(i,i); + if abs(s) > localMax + localMax = abs(s); + end + obj.x(i) = obj.x(i) + s; + end + if err > localMax + err = localMax ; + end + k = k+1; + obj = GetErrors(obj); + if(type == 'N')%norm + array(end+1) = norm(obj.errors); + elseif(type == 'E')%maximal value of s + array(end+1) = localMax; + end + end + disp(k - 1); + end + function [obj, array]= jacobi(obj, type) + array = []; + err = inf; + k = 1; + m = 10000; + x1 = zeros(obj.n, 1); + while k <= m && err > obj.acc + localMax = 0; + for i = 1 : obj.n + s = 0; + for j = 1 : obj.n + s = s+(-obj.A(i,j)*x1(j)); + end + x1 = obj.x; + s = (s+obj.B(i))/obj.A(i,i); + obj.x(i) = obj.x(i) + s; + if abs(s) > localMax + localMax = abs(s); + end + end + if err > localMax + err = localMax ; + end + k = k+1; + obj = GetErrors(obj); + if(type == 'N')%norm + array(end+1) = norm(obj.errors); + elseif(type == 'E')%maximal value of s + array(end+1) = localMax; + end + end + disp(k - 1); + end + end + methods + function obj = TASK3() + obj = obj@TASK2(4); + end + function obj = SetTask3(obj) + obj = SetSize(obj, 4); + obj.A = [13 2 -8 1; 1 10 5 -2; 6 2 -23 15; 1 22 -1 13]; + obj.B = [16 24 184 82]; + end + function obj = Example(obj) + obj = SetSize(obj, 4); + obj.A = [5 -2 3 0; -3 9 1 -2; 2 -1 -7 1; 4 3 -5 7]; + obj.B = [-1 2 3 0.5]; + [obj, array] = gaussSeidel(obj, 'N'); + plot(array, '-o'); + end + %type in 'G' for Gauss Seidel and 'J' for Jacobi method. + function obj = Task3System(obj, alg) + obj = SetSize(obj, 4); + obj.A = [13 2 -8 1; 1 10 5 -2; 6 2 -23 15; 1 22 -1 13]; + obj.B = [16 24 184 82]; + if alg == 'G' + [obj, array] = gaussSeidel(obj); + plot(array, '-o'); + elseif alg == 'J' + [obj, array] = jacobi(obj); + plot(array, '-or'); + end + end + function obj = Task3a(obj, type) + if type ~= 'N' && type ~= 'E' + disp('Wrong type parameter!'); + return + end + obj = SetTask3(obj); + [obj, array1] = gaussSeidel(obj, type); + obj = SetTask3(obj); + [obj, array2] = jacobi(obj, type); + plot(array1, 'ob-'); + hold on + plot(array2, 'or-'); + hold off + end + function obj = Task3With2a(obj, input, type) + obj = SetSize(obj, 10); + obj = TaskAArray(obj); + if input == 'G' + [obj, table] = gaussSeidel(obj, type); + plot(table, '-o'); + elseif input == 'J' + [obj, table] = jacobi(obj,type); + plot(table, '-o'); + elseif input == 'B' + [obj, table] = gaussSeidel(obj,type); + obj = SetSize(obj, 10); + obj = TaskAArray(obj); + [obj, table2] = jacobi(obj,type); + plot(table, '-o'); + hold on + plot(table2, '-or'); + hold off + end + end + function obj = Task3With2b(obj, input, type) + obj = SetSize(obj, 10); + obj = TaskBArray(obj); + if input == 'G' + [obj, table] = gaussSeidel(obj, type); + plot(table, '-o'); + elseif input == 'J' + [obj, table] = jacobi(obj,type); + plot(table, '-o'); + elseif input == 'B' + [obj, table] = gaussSeidel(obj,type); + obj = SetSize(obj, 10); + obj = TaskBArray(obj); + [obj, table2] = jacobi(obj,type); + plot(table, '-o'); + hold on + plot(table2, '-o'); + hold off + end + end + end +end \ No newline at end of file diff --git a/ENUME/references/ENUME_Project1/TASK4.m b/ENUME/references/ENUME_Project1/TASK4.m new file mode 100644 index 00000000..178f513a --- /dev/null +++ b/ENUME/references/ENUME_Project1/TASK4.m @@ -0,0 +1,95 @@ +classdef TASK4 < TASK2 + properties + tol = 1e-6; + imax = 10000; + end + methods + function obj = TASK4() + obj = obj@TASK2(5); + end + function [obj, Q, R]=QR(obj) + Q=zeros(obj.n,obj.n); + R=zeros(obj.n,obj.n); + d=zeros(1,obj.n); + for i=1:obj.n + Q(:,i)=obj.A(:,i); + R(i,i)=1; + d(i)=Q(:,i)'*Q(:,i); + for j=i+1:obj.n + R(i,j)=(Q(:,i)'*obj.A(:,j))/d(i); + obj.A(:,j)=obj.A(:,j)-R(i,j)*Q(:,i); + end + end + for i=1:obj.n + dd=norm(Q(:,i)); + Q(:,i)=Q(:,i)/dd; + R(i,i:obj.n)=R(i,i:obj.n)*dd; + end + end + function [obj, eig, i] = EigvalQRshifts(obj) + obj.n=size(obj.A,1); + eig=diag(ones(obj.n)); + INITIALsubmatrix=obj.A; + for k=obj.n:-1:2 + DK=INITIALsubmatrix; + i=0; + while i<=obj.imax && max(abs(DK(k,1:k-1)))>obj.tol + DD=DK(k-1:k,k-1:k); + [ev1,ev2]=roots(1,-(DD(1,1)+DD(2,2)),DD(2,2)*DD(1,1)-DD(2,1)*DD(1,2)); + if abs(ev1-DD(2,2)) < abs(ev2-DD(2,2)) + shift=ev1; + else + shift=ev2; + end + DP=DK-eye(k)*shift; + [Q1,R1]=qr(DP); + DK=R1*Q1+eye(k)*shift; + i=i+1; + end + if i > obj.imax + error("Too many iterations!"); + end + eig(k)=DK(k,k); + if k > 2 + INITIALsubmatrix=DK(1:k-1,1:k-1); + else + eig(1)=DK(1,1); + end + DK + end + end + function [obj, eigenvalues, i] = EigvalQRNoShift(obj) + i=1; + while i <= obj.imax && max(max(obj.A-diag(diag(obj.A)))) > obj.tol + [obj, Q1,R1] = QR(obj); + obj.A=R1*Q1; + i=i+1; + end + if i > obj.imax + error("Too many iterations!"); + end + eigenvalues=diag(obj.A); + end + function obj = SetExampleShifts(obj) + obj = SetSize(obj, 5); + obj.A = [2 33 8 -3 4; 33 1 -6 5 -3; 8 -6 -5 -6 8; -3 5 -6 3 2; 4 -3 8 2 45]; + [obj, eig, k] = EigvalQRshifts(obj); + eig + k + end + function obj = SetExample(obj) + obj = SetSize(obj, 5); + obj.A = [2 33 8 -3 4; 33 1 -6 5 -3; 8 -6 -5 -6 8; -3 5 -6 3 2; 4 -3 8 2 45]; + [obj, eig, k] = EigvalQRNoShift(obj); + eig + k + end + end +end +function [x1, x2] = roots(a, b, c) + first = -b + sqrt(b * b - 4 * a * c); + second = -b - sqrt(b * b - 4 * a * c); + li = max(abs(first), abs(second)); + x1 = li/(2*a); + x2 = ((-b)/a); +end \ No newline at end of file diff --git a/ENUME/references/ENUME_ProjectA_No31/KacperWojakowski-ProjectA-ENUME.pdf b/ENUME/references/ENUME_ProjectA_No31/KacperWojakowski-ProjectA-ENUME.pdf new file mode 100644 index 00000000..26cf6d6e Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/KacperWojakowski-ProjectA-ENUME.pdf differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 1/macheps.m b/ENUME/references/ENUME_ProjectA_No31/task 1/macheps.m new file mode 100644 index 00000000..03b9abd4 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 1/macheps.m @@ -0,0 +1,8 @@ +function [macheps] = macheps() +%MACHEPS function calculates machine epsilon +% finds smallest number E that 1+E>1 +macheps = 1; +while( 1 + ( macheps / 2 ) > 1 ) + macheps = macheps/2; +end +end \ No newline at end of file diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/euclideanNorm.m b/ENUME/references/ENUME_ProjectA_No31/task 2/euclideanNorm.m new file mode 100644 index 00000000..4a55de97 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 2/euclideanNorm.m @@ -0,0 +1,21 @@ +function [r] = euclideanNorm(rMatrix) +%EUCLIDEANNORM calculates Euclidean Norm +% yes +sr = size(rMatrix); +if( size(sr) > 2 ) + return; +end +if( sr(1) == 1 ) + n = sr(2); +elseif( sr(2) == 1 ); + n = sr(1); +else + return; +end +sum = 0; +for i = 1:n + sum = sum + rMatrix(i)*rMatrix(i); +end +r = sqrt(sum); +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/matrixGen2a.m b/ENUME/references/ENUME_ProjectA_No31/task 2/matrixGen2a.m new file mode 100644 index 00000000..ceefd6fd --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 2/matrixGen2a.m @@ -0,0 +1,21 @@ +function [A, b] = matrixGen2a(n) +%matrixGen2a Generates matrices for the task 2a +% generates matrices for a system Ax = B of n linear equations + +A = zeros(n, n); +b = zeros(n, 1); + +for i = 1:n + b(i) = 0.9*i; + for j = 1:n + if(i == j) + A(i, j) = 11; + elseif (i == j-1) + A(i, j) = 5; + elseif (i == j+1) + A(i, j) = 5; + end + end +end +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/matrixGen2b.m b/ENUME/references/ENUME_ProjectA_No31/task 2/matrixGen2b.m new file mode 100644 index 00000000..12c77699 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 2/matrixGen2b.m @@ -0,0 +1,18 @@ +function [A,b] = matrixGen2b(n) +%matrixGen2b Generates matrices for the task 2b +% generates matrices for a system Ax = B of n linear equations + +A = zeros(n, n); +b = zeros(n, 1); + +for i = 1:n + if( mod(i,2) == 0 ) + b(i) = 2/(3*i); + else + b(i) = 0; + end + for j = 1:n + A(i,j) = 7/(8*(i+j+1)); + end +end +end \ No newline at end of file diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aBIG.fig b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aBIG.fig new file mode 100644 index 00000000..aed4a1e2 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aBIG.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aBIG.png b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aBIG.png new file mode 100644 index 00000000..6f234ebe Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aBIG.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aSMALL.fig b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aSMALL.fig new file mode 100644 index 00000000..827b5507 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aSMALL.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aSMALL.png b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aSMALL.png new file mode 100644 index 00000000..2bc708c9 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2aSMALL.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bBIG.fig b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bBIG.fig new file mode 100644 index 00000000..a62e0313 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bBIG.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bBIG.png b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bBIG.png new file mode 100644 index 00000000..f6954136 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bBIG.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bSMALL.fig b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bSMALL.fig new file mode 100644 index 00000000..acb23384 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bSMALL.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bSMALL.png b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bSMALL.png new file mode 100644 index 00000000..5b4d0591 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/2bSMALL.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualA.fig b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualA.fig new file mode 100644 index 00000000..8c9ea012 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualA.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualA.png b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualA.png new file mode 100644 index 00000000..bc6a633b Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualA.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualB.fig b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualB.fig new file mode 100644 index 00000000..b809b7c3 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualB.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualB.png b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualB.png new file mode 100644 index 00000000..85b082bb Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 2/plots/residualB.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/residualCorrection.m b/ENUME/references/ENUME_ProjectA_No31/task 2/residualCorrection.m new file mode 100644 index 00000000..cfe2f62f --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 2/residualCorrection.m @@ -0,0 +1,17 @@ +function [Rnew,Xnew] = residualCorrection(r,x,AT,b,A) +%RESIDUALCORRECTION calculates an iteration of residual correction +% currently not working properly +n = length(x); +dx = zeros(n, 1); +for o = 1:n + k = n-o+1; + sum = 0; + for j = k+1:n + sum = sum + (AT(k,j) * dx(j)); + end + dx(k) = (r(k) - sum)/AT(k,k); +end +Xnew = x - dx; +Rnew = A*Xnew - b; +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/solveIndicated.m b/ENUME/references/ENUME_ProjectA_No31/task 2/solveIndicated.m new file mode 100644 index 00000000..b604ee51 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 2/solveIndicated.m @@ -0,0 +1,46 @@ +function [x, A, b] = solveIndicated(A, b) +%SOLVEINDICATED solves system of linear equations Ax=b +% uses the indicated method (Gaussain elimination with partial pivoting) +% returns x - the solution and A,b - the system after transformation + +sa = size(A); +sb = size(b); +if( sa(1) ~= sa(2) ) + return; +elseif ( sa(1) ~= sb(1) ) + return; +end + +n = sa(1); + +for k = 1:n +% Partial pivoting + i = k; + for j = k+1:n + if ( abs(A(j, k)) > abs(A(i, k)) ) + i = j; + end + end + if( k~=i ) + A([k i], :) = A([i k], :); + b([k i]) = b([i k]); + end +% Gauss transform + for j = k+1:n + l = A(j,k) / A(k,k); + A(j, :) = A(j, :) - A(k, :) * l; + b(j) = b(j) - b(k) * l; + end +end +%Backwards substitution +x = zeros(n, 1); +for o = 1:n + k = n-o+1; + sum = 0; + for j = k+1:n + sum = sum + (A(k,j) * x(j)); + end + x(k) = (b(k) - sum)/A(k,k); +end +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 2/task2.m b/ENUME/references/ENUME_ProjectA_No31/task 2/task2.m new file mode 100644 index 00000000..d01b63c0 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 2/task2.m @@ -0,0 +1,130 @@ +clear all; + +repeatSmall = 4; +repeatBig = 9; +repeatEqua = 10; +%-----TASK 2A +%big graph +repeats = zeros(1,repeatBig); +errors = zeros(1,repeatBig); +n = repeatEqua; +for i = 1:1:repeatBig + [A, b] = matrixGen2a( n ); + [x] = solveIndicated( A, b ); + repeats(i) = n; + errors(i) = euclideanNorm( A*x - b ); + n = n*2; +end +figure(1) +plot(repeats, errors, 'o'); +title(sprintf("Errors in task 2a, up to %d equations", n/2)); +xlabel('Number of equations'); +ylabel('Euclidean norm of errors'); +grid on; +box off; +saveas(1, "./plots/2aBIG.fig"); +saveas(1, "./plots/2aBIG.png"); +%small +repeats = zeros(1,repeatSmall); +errors = zeros(1,repeatSmall); +n = repeatEqua; +for i = 1:1:repeatSmall + [A, b] = matrixGen2a( n ); + [x] = solveIndicated( A, b ); + repeats(i) = n; + errors(i) = euclideanNorm( A*x - b ); + n = n*2; +end +figure(2) +plot(repeats, errors, 'o'); +title(sprintf("Errors in task 2a, up to %d equations", n/2)); +xlabel('Number of equations'); +ylabel('Euclidean norm of errors'); +grid on; +box off; +saveas(2, "./plots/2aSMALL.fig"); +saveas(2, "./plots/2aSMALL.png"); +[Aa, ba] = matrixGen2a( 10 ); +[xa, AaT, baT] = solveIndicated( Aa, ba ); +Ra = Aa*xa - ba; +%TODO: RESIDUAL +repeatResidual = 10; +residualA = zeros(1,repeatResidual+1); +residualA(1) = euclideanNorm(Ra); +xaR = xa; +RaR = Ra; +for i = 1:1:repeatResidual + [RaR, xaR] = residualCorrection(RaR,xaR,AaT,ba,Aa); + residualA(i+1) = euclideanNorm(RaR); +end +figure(5) +plot(0:1:repeatResidual,residualA,'o'); +title("Results of residual correction"); +xlabel('Iteration'); +ylabel('Euclidean norm of errors'); +grid on; +box off; +saveas(5, "./plots/residualA.fig"); +saveas(5, "./plots/residualA.png"); +%-----TASK 2B +%big graph +repeats = zeros(1,repeatBig); +errors = zeros(1,repeatBig); +n = repeatEqua; +for i = 1:1:repeatBig + [A, b] = matrixGen2b( n ); + [x] = solveIndicated( A, b ); + repeats(i) = n; + errors(i) = euclideanNorm( A*x - b ); + n = n*2; +end +figure(3) +plot(repeats, errors, 'o'); +title(sprintf("Errors in task 2b, up to %d equations", n/2)); +xlabel('Number of equations'); +ylabel('Euclidean norm of errors'); +grid on; +box off; +saveas(3, "./plots/2bBIG.fig"); +saveas(3, "./plots/2bBIG.png"); +%small +repeats = zeros(1,repeatSmall); +errors = zeros(1,repeatSmall); +n = repeatEqua; +for i = 1:1:repeatSmall + [A, b] = matrixGen2b( n ); + [x] = solveIndicated( A, b ); + repeats(i) = n; + errors(i) = euclideanNorm( A*x - b ); + n = n*2; +end +figure(4) +plot(repeats, errors, 'o'); +title(sprintf("Errors in task 2b, up to %d equations", n/2)); +xlabel('Number of equations'); +ylabel('Euclidean norm of errors'); +grid on; +box off; +saveas(4, "./plots/2bSMALL.fig"); +saveas(4, "./plots/2bSMALL.png"); +[Ab, bb] = matrixGen2b( 10 ); +[xb, AbT, bbT] = solveIndicated( Ab, bb ); +Rb = Ab*xb - bb; +%TODO: RESIDUAL +residualB = zeros(1,repeatResidual+1); +residualB(1) = euclideanNorm(Rb); +xbR = xb; +RbR = Rb; +for i = 1:1:repeatResidual + [RbR, xbR] = residualCorrection(Rb,xb,AbT,bb,Ab); + residualB(i+1) = euclideanNorm(RbR); +end +figure(6) +plot(0:1:repeatResidual,residualB,'o'); +title("Results of residual correction"); +xlabel('Iteration'); +ylabel('Euclidean norm of errors'); +grid on; +box off; +saveas(6, "./plots/residualB.fig"); +saveas(6, "./plots/residualB.png"); diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/GaussSeidelMethod.m b/ENUME/references/ENUME_ProjectA_No31/task 3/GaussSeidelMethod.m new file mode 100644 index 00000000..015ae860 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 3/GaussSeidelMethod.m @@ -0,0 +1,40 @@ +function [x, errors] = GaussSeidelMethod(A, b) +%GAUSSSEIDELMETHOD solves a system Ax = b using the Gauss-Seidel iterative method +% The accuracy target is 10e-10 +% returns x - the solution and errors - vector of errors for each +% iteration + +[L, D, U] = decomposeLDU(A); + +%Checking covergence conditions +if ~(rowDominant(A) || columnDominant(A)) + sr = max(abs(eig(-inv(D)*(L+U)))); + if sr >= 1 + x = sr; + return + end +end + +%Initial guess +x = zeros(length(A), 1); + +n = length(A); +iteration = 1; +errors(iteration) = vecnorm(A*x - b); + +while errors(iteration) > 10^-10 + w = U*x - b; + for i = 1:1:n + sum = 0; + for j = 1:1:i-1 + sum = sum - L(i,j) * x(j); + end + sum = sum - w(i); + x(i) = sum / D(i,i); + end + + iteration = iteration + 1; + + errors(iteration) = vecnorm(A*x - b); +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/JacobiMethod.m b/ENUME/references/ENUME_ProjectA_No31/task 3/JacobiMethod.m new file mode 100644 index 00000000..a509f88f --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 3/JacobiMethod.m @@ -0,0 +1,32 @@ +function [x, errors] = JacobiMethod(A, b) +%JACOBIMETHOD solves a system Ax = b using the Jacobi iterative method +% The accuracy target is 10e-10 +% returns x - the solution and errors - vector of errors for each +% iteration + +[L, D, U] = decomposeLDU(A); + +%Checking covergence conditions +if ~(rowDominant(A) || columnDominant(A)) + sr = max(abs(eig(-inv(D)*(L+U)))); + if sr >= 1 + x = sr; + return + end +end + +%Initial guess +x = zeros(length(A), 1); + +Di = inv(D); +iteration = 1; +errors(iteration) = vecnorm(A*x - b); + +while errors(iteration) > 10^-10 + x = -Di * (L+U) * x + Di*b; + + iteration = iteration + 1; + + errors(iteration) = vecnorm(A*x - b); +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/columnDominant.m b/ENUME/references/ENUME_ProjectA_No31/task 3/columnDominant.m new file mode 100644 index 00000000..bcd8cff4 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 3/columnDominant.m @@ -0,0 +1,20 @@ +function [out] = columnDominant(A) +%COLUMNDOMINANT checks column dominance of matrix A +% returns true when dominant, false otherwise +n = size(A); + +for j = 1:1:n + sum = 0; + for i = 1:1:n + if i == j + continue + end + sum = sum + abs(A(i,j)); + end + if abs(A(j,j)) <= sum + out = false; + return + end +end +out = true; +end \ No newline at end of file diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/decomposeLDU.m b/ENUME/references/ENUME_ProjectA_No31/task 3/decomposeLDU.m new file mode 100644 index 00000000..5c45ef5d --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 3/decomposeLDU.m @@ -0,0 +1,27 @@ +function [L,D,U] = decomposeLDU(A) +%DECOMPOSELDU decomposes the matrix A into L+D+U +% returns L - lowerdiagonal, D - diagonal, U - upperdiagonal + +n = size(A); +L = zeros(n); +D = zeros(n); +U = zeros(n); + +for i = 2:1:n + for j = 1:1:i-1 + L(i,j) = A(i,j); + end +end + +for i = 1:1:n + D(i,i) = A(i,i); +end + +for i = 1:1:n + for j = i+1:1:n + U(i,j) = A(i,j); + end +end + +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/matrixGen2a.m b/ENUME/references/ENUME_ProjectA_No31/task 3/matrixGen2a.m new file mode 100644 index 00000000..ceefd6fd --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 3/matrixGen2a.m @@ -0,0 +1,21 @@ +function [A, b] = matrixGen2a(n) +%matrixGen2a Generates matrices for the task 2a +% generates matrices for a system Ax = B of n linear equations + +A = zeros(n, n); +b = zeros(n, 1); + +for i = 1:n + b(i) = 0.9*i; + for j = 1:n + if(i == j) + A(i, j) = 11; + elseif (i == j-1) + A(i, j) = 5; + elseif (i == j+1) + A(i, j) = 5; + end + end +end +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/matrixGen2b.m b/ENUME/references/ENUME_ProjectA_No31/task 3/matrixGen2b.m new file mode 100644 index 00000000..12c77699 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 3/matrixGen2b.m @@ -0,0 +1,18 @@ +function [A,b] = matrixGen2b(n) +%matrixGen2b Generates matrices for the task 2b +% generates matrices for a system Ax = B of n linear equations + +A = zeros(n, n); +b = zeros(n, 1); + +for i = 1:n + if( mod(i,2) == 0 ) + b(i) = 2/(3*i); + else + b(i) = 0; + end + for j = 1:n + A(i,j) = 7/(8*(i+j+1)); + end +end +end \ No newline at end of file diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel2a.fig b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel2a.fig new file mode 100644 index 00000000..f6a69122 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel2a.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel2a.png b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel2a.png new file mode 100644 index 00000000..3abe6f7e Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel2a.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel3.fig b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel3.fig new file mode 100644 index 00000000..2e13d302 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel3.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel3.png b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel3.png new file mode 100644 index 00000000..c598426a Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/GaussSeidel3.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi2a.fig b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi2a.fig new file mode 100644 index 00000000..80a8fac0 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi2a.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi2a.png b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi2a.png new file mode 100644 index 00000000..7515ae49 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi2a.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi3.fig b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi3.fig new file mode 100644 index 00000000..4f76244e Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi3.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi3.png b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi3.png new file mode 100644 index 00000000..a0ea4af9 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/Jacobi3.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/plots/compare.fig b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/compare.fig new file mode 100644 index 00000000..7b8b34b6 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/compare.fig differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/plots/compare.png b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/compare.png new file mode 100644 index 00000000..a5073b76 Binary files /dev/null and b/ENUME/references/ENUME_ProjectA_No31/task 3/plots/compare.png differ diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/rowDominant.m b/ENUME/references/ENUME_ProjectA_No31/task 3/rowDominant.m new file mode 100644 index 00000000..821cbe40 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 3/rowDominant.m @@ -0,0 +1,21 @@ +function [out] = rowDominant(A) +%ROWDOMINANT checks row dominance of matrix A +% returns true when dominant, false otherwise +n = size(A); + +for i = 1:1:n + sum = 0; + for j = 1:1:n + if i == j + continue + end + sum = sum + abs(A(i,j)); + end + if abs(A(i,i)) <= sum + out = false; + return + end +end +out = true; +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 3/task3.m b/ENUME/references/ENUME_ProjectA_No31/task 3/task3.m new file mode 100644 index 00000000..e77cd9ad --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 3/task3.m @@ -0,0 +1,56 @@ +clear all; +%First case +A = [20 10 8 1; + 1 10 6 2; + 2 1 8 4; + 1 1 1 4;]; +b = [100; 80; 60; 40]; +%From task 2 +[Aa, ba] = matrixGen2a( 10 ); +[Ab, bb] = matrixGen2b( 10 ); + +[xJ, errorsJ] = JacobiMethod(A, b); +[xGS, errorsGS] = GaussSeidelMethod(A, b); +[xJa, errorsJa] = JacobiMethod(Aa, ba); +[xGSa, errorsGSa] = GaussSeidelMethod(Aa, ba); +[sr] = JacobiMethod(Ab, bb); + +%Plots +figure(1); +plot(1:1:length(errorsJ), errorsJ, '.') +title("Jacobi method, matrices 3"); +xlabel("Iteration"); ylabel("Euclidean norm of errors"); +saveas(1, "./plots/Jacobi3.fig"); +saveas(1, "./plots/Jacobi3.png"); + +figure(2); +plot(1:1:length(errorsJa), errorsJa, '.') +title("Jacobi method, matrices 2a"); +xlabel("Iteration"); ylabel("Euclidean norm of errors"); +saveas(2, "./plots/Jacobi2a.fig"); +saveas(2, "./plots/Jacobi2a.png"); + +figure(3); +plot(1:1:length(errorsGS), errorsGS, '.') +title("Gauss-Seidel method, matrices 3"); +xlabel("Iteration"); ylabel("Euclidean norm of errors"); +saveas(3, "./plots/GaussSeidel3.fig"); +saveas(3, "./plots/GaussSeidel3.png"); + +figure(4) +plot(1:1:length(errorsGSa), errorsGSa, '.') +title("Gauss-Seidel method, matrices 2a"); +xlabel("Iteration"); ylabel("Euclidean norm of errors"); +saveas(4, "./plots/GaussSeidel2a.fig"); +saveas(4, "./plots/GaussSeidel2a.png"); + +figure(5); +hold on; +plot(1:1:length(errorsJ), errorsJ, 'o') +plot(1:1:length(errorsGS), errorsGS, 'o') +legend('Jacobi', 'Gauss-Seidel'); +title("Jacobi and Gauss-Seidel comparison"); +xlabel("Iteration"); ylabel("Euclidean norm of errors"); +xlim([0 40]); +saveas(5, "./plots/compare.fig"); +saveas(5, "./plots/compare.png"); \ No newline at end of file diff --git a/ENUME/references/ENUME_ProjectA_No31/task 4/QRfactorize.m b/ENUME/references/ENUME_ProjectA_No31/task 4/QRfactorize.m new file mode 100644 index 00000000..5f848bfe --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 4/QRfactorize.m @@ -0,0 +1,26 @@ +function [Q,R] = QRfactorize(A) +%QRFACTORIZE factorizes the matrix A using QR factorization +% returns the matrices Q and R +[m, n] = size(A); +Q = zeros(m, n); +R = zeros(m, n); +d = zeros(m, n); +%Factorization +for i = 1:1:n + Q(:, i) = A(:, i); + R(i, i) = 1; + d(i) = Q(:, i)' * Q(:, i); + + for j = i+1:1:n + R(i, j) = (Q(: ,i)' * A(:, j)) / d(i); + A(:, j) = A(:, j) - R(i, j) * Q(:, i); + end +end +%Normalization +for i = 1:1:n + dd = norm(Q(:, i)); + Q(:, i) = Q(:, i) / dd; + R(i, i:n) = R(i, i:n) * dd; +end +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 4/eigenvalueQRnoshift.m b/ENUME/references/ENUME_ProjectA_No31/task 4/eigenvalueQRnoshift.m new file mode 100644 index 00000000..8aa878db --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 4/eigenvalueQRnoshift.m @@ -0,0 +1,17 @@ +function [eigenvalues,iteration,Afinal] = eigenvalueQRnoshift(A) +%EIGENVALUEQRNOSHIFT calculates eigenvalues using the QR method with no +%shifts +% returns eigenvalues, the number of iterations and the transformed +% matrix A +iteration = 1; +while max(max(A-diag(diag(A)))) > 10^-6 + [Q, R] = QRfactorize(A); + A = R * Q; + iteration = iteration+1; +end + +eigenvalues = diag(A); +Afinal = A; + +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 4/eigenvalueQRshift.m b/ENUME/references/ENUME_ProjectA_No31/task 4/eigenvalueQRshift.m new file mode 100644 index 00000000..ed55f140 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 4/eigenvalueQRshift.m @@ -0,0 +1,37 @@ +function [eigenvalues,iteration,Afinal] = eigenvalueQRshift(A) +%EIGENVALUEQRSHIFT calculates eigenvalues using the QR method with shifts +% returns eigenvalues, the number of iterations and the transformed +% matrix A +n = size(A, 1); +eigenvalues = diag(ones(n)); + +initialSub = A; +iteration = 0; + for k = n:-1:2 + DK = initialSub; + + while max(abs(DK(k, 1:k-1))) > 10^-6 + DD = DK(k-1:k, k-1:k); + [ev1, ev2] = quadpolynroots(1, -(DD(1,1) + DD(2,2)), DD(2,2) * DD(1,1) - DD(2,1) * DD(1,2)); + + if abs(ev1 - DD(2, 2)) < abs(ev2 - DD(2, 2)) + shift = ev1; + else + shift = ev2; + end + DP = DK - eye(k) * shift; + [Q, R] = QRfactorize(DP); + DK = R * Q + eye(k) * shift; + iteration = iteration + 1; + end + eigenvalues(k) = DK(k, k); + A(1:k, 1:k) = DK(1:k, 1:k); + if k > 2 + initialSub = DK(1:k-1, 1:k-1); + else + eigenvalues(1) = DK(1, 1); + end + end + Afinal = A; +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 4/quadpolynroots.m b/ENUME/references/ENUME_ProjectA_No31/task 4/quadpolynroots.m new file mode 100644 index 00000000..06d6a3e3 --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 4/quadpolynroots.m @@ -0,0 +1,18 @@ +function [x1, x2] = quadpolynroots(a,b,c) +%UNTITLED4 Summary of this function goes here +% Detailed explanation goes here + +l1 = -b + sqrt(b*b - 4*a*c); +l2 = -b - sqrt(b*b - 4*a*c); + +if abs(l1) > abs(l2) + ctr = l1; +else + ctr = l2; +end + +x1 = ctr/(2 * a); +x2 = ((-b) / a) - x1; + +end + diff --git a/ENUME/references/ENUME_ProjectA_No31/task 4/task4.m b/ENUME/references/ENUME_ProjectA_No31/task 4/task4.m new file mode 100644 index 00000000..7351f02a --- /dev/null +++ b/ENUME/references/ENUME_ProjectA_No31/task 4/task4.m @@ -0,0 +1,11 @@ +clear all; + +A = [23 12 3 5 10; + 12 14 8 5 22; + 3 8 9 13 11; + 5 5 13 10 17; + 10 22 11 17 25]; + +[eigNS, iteNS, finNS] = eigenvalueQRnoshift(A); +[eigS, iteS, finS] = eigenvalueQRshift(A); +eigE = eig(A); \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/PROJEKT1 - treść.jpg b/ENUME/references/MNUM/Projekt1/PROJEKT1 - treść.jpg new file mode 100644 index 00000000..630e25b0 Binary files /dev/null and b/ENUME/references/MNUM/Projekt1/PROJEKT1 - treść.jpg differ diff --git a/ENUME/references/MNUM/Projekt1/Zadanie1/Zadanie1.m b/ENUME/references/MNUM/Projekt1/Zadanie1/Zadanie1.m new file mode 100644 index 00000000..96defa3e --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie1/Zadanie1.m @@ -0,0 +1,10 @@ +function [] = Zadanie1() + x = 1.5; %pocztkowe zainicjalizowanie zmiennej + g = 1.0; + while( x > 1 ) %przechodzenie przez ptle i dzielenie epsilona + g = g/2; %tak dugo a dodanie go nie wpynie na wynik + x = 1.0 + g; + end + g = g*2; %jeden przebieg ptli w ty + fprintf('Wyznaczony epsilon maszynowy: %d \n',g); +end diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/Zadanie2a.m b/ENUME/references/MNUM/Projekt1/Zadanie2/Zadanie2a.m new file mode 100644 index 00000000..45694b11 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/Zadanie2a.m @@ -0,0 +1,16 @@ +function [] = Zadanie2a(n) + A = a_genA(n); %generator macierzy wejciowej A + b = a_genB(n); %generator macierzy wejciowej b + b=b'; + + tic %rozpoczcie pomiaru czasu + L1 = cholesky(A,n); %rozkad metod Cholesky'ego-Banachiewicza + x = solveEq(L1,b); %rozwizanie rwnania + t = toc; %koniec pomiaru czasu + + r = b - A * x; %obliczenie residuum + br = norm(r); %obliczenie bdu rozwizania jako normy z residuum + + fprintf("Zmierzony czas rozwizania: %d \n",t); + fprintf("Liczba rwna i bd rozwizania: \n %d %d \n",n,br); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/Zadanie2b.m b/ENUME/references/MNUM/Projekt1/Zadanie2/Zadanie2b.m new file mode 100644 index 00000000..65e2e1fd --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/Zadanie2b.m @@ -0,0 +1,16 @@ +function [] = Zadanie2b(n) + A = b_genA(n); + b = b_genB(n); + b=b'; + + tic %rozpoczcie pomiaru czasu + L1 = cholesky(A,n); %rozkad metod Cholesky'ego-Banachiewicza + x = solveEq(L1,b); %rozwizanie rwnania + t = toc; %koniec pomiaru czasu + + r = b - A * x; %obliczenie residuum + br = norm(r); %obliczenie bdu rozwizania jako normy z residuum + + fprintf("Zmierzony czas rozwizania: %d \n",t); + fprintf("Liczba rwna i bd rozwizania: \n %d %d \n",n,br); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/Zadanie2c.m b/ENUME/references/MNUM/Projekt1/Zadanie2/Zadanie2c.m new file mode 100644 index 00000000..1a0ad3cb --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/Zadanie2c.m @@ -0,0 +1,16 @@ +function [] = Zadanie2c(n) + A = c_genA(n); + b = c_genB(n); + b=b'; + + tic %rozpoczcie pomiaru czasu + L1 = cholesky(A,n); %rozkad metod Cholesky'ego-Banachiewicza + x = solveEq(L1,b); %rozwizanie rwnania + t = toc; %koniec pomiaru czasu + + r = b - A * x; %obliczenie residuum + br = norm(r); %obliczenie bdu rozwizania jako normy z residuum + + fprintf("Zmierzony czas rozwizania: %d \n",t); + fprintf("Liczba rwna i bd rozwizania: \n %d %d \n",n,br); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/a/a_genA.m b/ENUME/references/MNUM/Projekt1/Zadanie2/a/a_genA.m new file mode 100644 index 00000000..c4cab128 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/a/a_genA.m @@ -0,0 +1,5 @@ +function [A] = a_genA(n) + v1 = ones(1,n)*10; + v2 = ones(1,n-1)*4; + A = diag(v1) + diag(v2,1) + diag(v2,-1); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/a/a_genB.m b/ENUME/references/MNUM/Projekt1/Zadanie2/a/a_genB.m new file mode 100644 index 00000000..f4aa117c --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/a/a_genB.m @@ -0,0 +1,4 @@ +function [b] = a_genB(n) + bottom = 2.5 - 0.5*n; + b = 2:-0.5:bottom; +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/b/b_genA.m b/ENUME/references/MNUM/Projekt1/Zadanie2/b/b_genA.m new file mode 100644 index 00000000..09813ad9 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/b/b_genA.m @@ -0,0 +1,12 @@ +function [A] = b_genA(n) + v1 = 4*n^2-1:-1:4*n^2-n; + A = diag(v1); + for i = 1:n-1 + j=i+1; + while(j <= n) + A(i,j) = 2*(i+j)+1; %dodanie wartoci do odpowiedniego indeksu macierzy + j=j+1; + end + end + A = triu(A)+triu(A,1)'; %odbicie symetrzyczne wobec przektnej +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/b/b_genB.m b/ENUME/references/MNUM/Projekt1/Zadanie2/b/b_genB.m new file mode 100644 index 00000000..8b44fe2f --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/b/b_genB.m @@ -0,0 +1,4 @@ +function [b] = b_genB(n) + top = 2.5 + 0.6*n; + b = 3.1:0.6:top; +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/backwardSubstitution.m b/ENUME/references/MNUM/Projekt1/Zadanie2/backwardSubstitution.m new file mode 100644 index 00000000..da565568 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/backwardSubstitution.m @@ -0,0 +1,7 @@ +function [x] = backwardSubstitution(A,b) + m = length(b); %wyuskanie ostatniego indeksu + x(m,1) = b(m)/A(m,m); %wyliczenie ostatniego elementu + for i = m-1:-1:1 %iteracja po wszystkiech rwnaniach poczwszy od przedostatniego wiersza + x(i,1)=(b(i)-A(i,i+1:m)*x(i+1:m,1))./A(i,i); %wyznaczenie niewiadomych + end +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/c/c_genA.m b/ENUME/references/MNUM/Projekt1/Zadanie2/c/c_genA.m new file mode 100644 index 00000000..1d6fd4aa --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/c/c_genA.m @@ -0,0 +1,12 @@ +function [A] = c_genA(n) + v1 = 0.2*n+0.3:0.3:0.2*n+0.3*n; + A = diag(v1); + for i = 1:n-1 + j=i+1; + while(j <= n) + A(i,j) = 1/(4*(i+j+1)); %dodanie wartoci do odpowiedniego indeksu macierzy + j=j+1; + end + end + A = triu(A)+triu(A,1)'; %odbicie symetryczne wobec przektnej +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/c/c_genB.m b/ENUME/references/MNUM/Projekt1/Zadanie2/c/c_genB.m new file mode 100644 index 00000000..422df3c6 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/c/c_genB.m @@ -0,0 +1,4 @@ +function [b] = c_genB(n) + b = 1:1:n; + b = (1./b).*(5/3); %odwrcenie i przemnoenie kadego elementu +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/cholesky.m b/ENUME/references/MNUM/Projekt1/Zadanie2/cholesky.m new file mode 100644 index 00000000..c8c8f284 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/cholesky.m @@ -0,0 +1,12 @@ +function[L1] = cholesky(A,n) + L1 = zeros(n,n); + for i = 1:n %przechodzenie po kolumnach + for j = i:n %przechodzenie wierszy wewntrz kolumny + if(i == j) + L1(i,i) = sqrt(A(i,i)-sumDiag(L1,i)); %przypisanie wartoci na przektnej macierzy + else + L1(j,i) = (A(j,i)-sumRest(L1,i,j))/L1(i,i); %przypisanie wartoci w reszcie przypadkw + end + end + end +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/forwardSubstitution.m b/ENUME/references/MNUM/Projekt1/Zadanie2/forwardSubstitution.m new file mode 100644 index 00000000..92a3708f --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/forwardSubstitution.m @@ -0,0 +1,7 @@ +function [x] = forwardSubstitution(A,b) + m = length(b); %wyuskanie ostatniego indeksu + x(1,1) = b(1)/A(1,1); %wyliczenie pierwszego elementu + for i = 2:m %iteracja po wszystkich rwnaniach poczwszy od drugiego wiersza + x(i,1)=(b(i)-A(i,1:i-1)*x(1:i-1,1))./A(i,i); %wyznaczanie niewiadomych + end +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/solveEq.m b/ENUME/references/MNUM/Projekt1/Zadanie2/solveEq.m new file mode 100644 index 00000000..9246ad61 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/solveEq.m @@ -0,0 +1,5 @@ +function [x] = solveEq(L1,b) + b = b'; %transponowanie macierzy + y = forwardSubstitution(L1,b); + x = backwardSubstitution(L1',y); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/sumDiag.m b/ENUME/references/MNUM/Projekt1/Zadanie2/sumDiag.m new file mode 100644 index 00000000..a9d079e1 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/sumDiag.m @@ -0,0 +1,6 @@ +function[sum] = sumDiag(L1,i) + sum=0; + for k = 1:1:i-1 + sum=sum+L1(i,k)^2; + end +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie2/sumRest.m b/ENUME/references/MNUM/Projekt1/Zadanie2/sumRest.m new file mode 100644 index 00000000..e0faa334 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie2/sumRest.m @@ -0,0 +1,6 @@ +function[sum] = sumRest(L1,i,j) + sum=0; + for k = 1:1:i-1 + sum=sum+(L1(j,k)*L1(i,k)); + end +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie3/GaussSeidel.m b/ENUME/references/MNUM/Projekt1/Zadanie3/GaussSeidel.m new file mode 100644 index 00000000..57c7f433 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie3/GaussSeidel.m @@ -0,0 +1,21 @@ +function[x,iter,od] = GaussSeidel(A,b,n,e) + x = zeros(n,1); + + %Stworzenie macierzy naddiagonalne, poddiagonalnej i diagonalnej + [L,D,U] = rozkladGaussSeidel(A,n); + b=b'; + r = 1; + iter = 1; + while(r>e || norm(A*x-b)>e) %kolejne iteracje + y = x; %zapamietujemy wektor x z poprzedniej iteracji + w = U*x - b; + for i = 1:n + x(i) = (-L(i,:)*x- w(i))/D(i,i); + end + r = norm(x-y); %liczmy blad z nomrmy euklidesowej, po kazdej iteracji + iter = iter + 1; %zliczamy ilosc iteracji + + end + %fprintf('norm(A*x-b):%d\n',norm(A*x-b)); + od=norm(A*x-b); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie3/Zadanie3.m b/ENUME/references/MNUM/Projekt1/Zadanie3/Zadanie3.m new file mode 100644 index 00000000..b8619fad --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie3/Zadanie3.m @@ -0,0 +1,24 @@ +function[x] = Zadanie3(n,e2) + i=1; + e=1; + A = b_genA(n); + b = b_genB(n); + + %Sprawdzenie warunku dostatecznego zbienoci + if(warDost(A,n) == 0) + disp('Warunek silnej dominacji diagonalnej nie jest spelniony'); + return + end + + while e>e2 % 0.0000001 + [x,iter(i),od] = GaussSeidel(A,b,n,e); + e = e/10; + r(i) = od; + i = i+1; + end + plot(iter, r); + disp(norm(A*x-b)); + title('Zaleznosc bledu wyniku od ilosci iteracji') + xlabel('Ilosc iteracji'); + ylabel('Blad wyniku'); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie3/poprawionyWykres.fig b/ENUME/references/MNUM/Projekt1/Zadanie3/poprawionyWykres.fig new file mode 100644 index 00000000..6eac999d Binary files /dev/null and b/ENUME/references/MNUM/Projekt1/Zadanie3/poprawionyWykres.fig differ diff --git a/ENUME/references/MNUM/Projekt1/Zadanie3/rozkladGaussSeidel.m b/ENUME/references/MNUM/Projekt1/Zadanie3/rozkladGaussSeidel.m new file mode 100644 index 00000000..e8da0f03 --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie3/rozkladGaussSeidel.m @@ -0,0 +1,15 @@ +function[L,D,U] = rozkladGaussSeidel(A,n) + L = zeros(n,n); %macierz poddiagonalna + U = zeros(n,n); %macierz naddiagonalna + D = diag(diag(A)); %macierz diagonalna + + for i = 1:n + for j = 1:n + if(ij) + L(i,j) = A(i,j); + end + end + end +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/Zadanie3/warDost.m b/ENUME/references/MNUM/Projekt1/Zadanie3/warDost.m new file mode 100644 index 00000000..bec2124b --- /dev/null +++ b/ENUME/references/MNUM/Projekt1/Zadanie3/warDost.m @@ -0,0 +1,17 @@ +function[bool] = warDost(A,n) + for i = 1:n + %Sumujemy wszystkie elementy w wierszu oprcz gwnej przektnej + sum = 0; + for j = 1:n + if i~=j + sum = sum + abs(A(i,j)); + end + end + %Sprawdzamy warunek silnej dominancji dla jednego wiersza + if sum > abs(A(i,i)) + bool = 0; + return; + end + end + bool = 1; +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt1/[MNUM]_Suchocki_Maciej_Projekt1.pdf b/ENUME/references/MNUM/Projekt1/[MNUM]_Suchocki_Maciej_Projekt1.pdf new file mode 100644 index 00000000..56c222d7 Binary files /dev/null and b/ENUME/references/MNUM/Projekt1/[MNUM]_Suchocki_Maciej_Projekt1.pdf differ diff --git a/ENUME/references/MNUM/Projekt2/PROJEKT2 - treść.jpg b/ENUME/references/MNUM/Projekt2/PROJEKT2 - treść.jpg new file mode 100644 index 00000000..4af32b4c Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/PROJEKT2 - treść.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie1/Zadanie1.m b/ENUME/references/MNUM/Projekt2/Zadanie1/Zadanie1.m new file mode 100644 index 00000000..58957821 --- /dev/null +++ b/ENUME/references/MNUM/Projekt2/Zadanie1/Zadanie1.m @@ -0,0 +1,73 @@ +function [] = Zadanie1(czyPrzesun,czySym) + % czyPrzesun - wartosc 1 jesli wersja z przesunieciami + % czySym - wartosc 1 jestli macierz symetryczna + + iterQR = 0; %liczba wartosci wlasnej QR bez przesuniec + iterQRS = 0; %liczba wartosci wlasnej QR z przesunieciami + + timeQR = 0; %czas wykonania alg QR bez przesuniec + timeQRS = 0; %czas wykonania alg QR z przesunieciami + timeE = 0; %czas wykonania alg eig() wbudowanym w MATLAB + + SIZE = 20; %rozmiar maciery + matrixNumberR = 30; %ilosc losowych macierzy + + ILEMACQR = 0; + ILEMACQRS = 0; + + %Generowanie danych + for i=1:matrixNumberR + + A = genA(SIZE,czySym); + tolerance = 0.0000001; + imax = 200; + + start = tic; + [~,D] = eig(A); + timeEig = toc(start); + timeE = timeE + timeEig; + + if czyPrzesun == 1 %QR z przesunieciami (eignes - wartWlasne) + [eigens, iteracje, time, ok] = zPrzesun(A, tolerance, imax); + if ok == 1 + ILEMACQRS = ILEMACQRS + 1; + iterQRS = iterQRS + iteracje; + timeQRS = timeQRS + time; + end + else %QR bez przesuniec (eigens - wartWlasne) + [eigens, iteracje, time, ok] = bezPrzesun(A, tolerance, imax); + if ok == 1 + ILEMACQR = ILEMACQR + 1; + iterQR = iterQR + iteracje; + timeQR = timeQR + time; + end + end + end + + fprintf('Ilosc macierzy: %d\n',matrixNumberR); + fprintf('Wielkosc macierzy: %d\n',SIZE); + SREDNIAczasEig = timeE / matrixNumberR; + + if czyPrzesun == 1 + %Wyniki z przesunieciami: + SREDNIAQRSI = iterQRS / ILEMACQRS; + SREDNIAczasQRS = timeQRS / ILEMACQRS; + fprintf('Z przesunieciami:\n'); + fprintf('Ilosc zkonczonych sukcesem: %d\n', ILEMACQRS); + fprintf('Srednia ilosci iteracji %d\n',SREDNIAQRSI); + fprintf('Sredni czas obliczen %d\n',SREDNIAczasQRS); + else + %Wyniki bez przesuniec: + SREDNIAQRI = iterQR / ILEMACQR; + SREDNIAczasQR = timeQR / ILEMACQR; + fprintf('Bez przesuniec:\n'); + fprintf('Ilosc zkonczonych sukcesem: %d\n', ILEMACQR); + fprintf('Srednia ilosci iteracji %d\n',SREDNIAQRI); + fprintf('Sredni czas obliczen %d\n',SREDNIAczasQR); + end + + fprintf('Sredni czas obliczen eig %d\n',SREDNIAczasEig); + d = diag(D); + disp(sort(d)); + disp(sort(eigens)); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt2/Zadanie1/bezPrzesun.m b/ENUME/references/MNUM/Projekt2/Zadanie1/bezPrzesun.m new file mode 100644 index 00000000..a63cac01 --- /dev/null +++ b/ENUME/references/MNUM/Projekt2/Zadanie1/bezPrzesun.m @@ -0,0 +1,20 @@ +function [wartWlasne, iteracje, time, ok] = bezPrzesun(D, tolerance, imax) + %imax - maksymalna liczba iteracji + % ok - czy funkcja wykonala sie z przekroczeniem imax + start = tic; + ok = 1; + i = 1; + + while i <= imax && max(max(D-diag(diag(D)))) > tolerance + [Q1, R1] = qrZmodGS(D); + D = R1*Q1; %macierz po przeksztaceniu + i = i + 1; + end + + if i > imax + ok = 0; + end + iteracje = i; + wartWlasne = diag(D); %wykstraktowanie wektora wartoci wasnych + time = toc(start); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt2/Zadanie1/genA.m b/ENUME/references/MNUM/Projekt2/Zadanie1/genA.m new file mode 100644 index 00000000..c3916241 --- /dev/null +++ b/ENUME/references/MNUM/Projekt2/Zadanie1/genA.m @@ -0,0 +1,10 @@ +function [A] = genA(SIZE,czySym) + A = rand(SIZE); + while rank(A)~= SIZE %powstanie macierzy o pelnym rzedzie + A = rand(SIZE); + end + + if czySym == 1 + A = A'+A; %dla symetrycznych + end +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt2/Zadanie1/qrZmodGS.m b/ENUME/references/MNUM/Projekt2/Zadanie1/qrZmodGS.m new file mode 100644 index 00000000..5ae5e773 --- /dev/null +++ b/ENUME/references/MNUM/Projekt2/Zadanie1/qrZmodGS.m @@ -0,0 +1,25 @@ +%rozkad QR (waski) macierzy zmodyfikowanym alg. Grama-Schmidta dla +%macierzy mxn (m>=n) o pelnym rzedzie, rzeczywistej lub zespolonej +%na podstawie ksizki prof. Tatjewskiego +function [Q,R] = qrZmodGS(A) + [m n] = size(A); + Q = zeros(m,n); + R = zeros(n,n); + d = zeros(1,n); + %rozkad A z kolumnami Q ortogonalnymi + for i=1:n + R(i,i)=1; + Q(:,i)=A(:,i); + d(i)=Q(:,i)'*Q(:,i); + for j=i+1:n + R(i,j)=(Q(:,i)'*A(:,j))/d(i); + A(:,j)=A(:,j)-R(i,j)*Q(:,i); + end + end + %normowanie rozkladu (kolumny Q ortogonalne) + for i=1:n + dd = norm(Q(:,i)); + Q(:,i) = Q(:,i)/dd; + R(i,i:n) = R(i,i:n)*dd; + end +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt2/Zadanie1/zPrzesun.m b/ENUME/references/MNUM/Projekt2/Zadanie1/zPrzesun.m new file mode 100644 index 00000000..421fec6c --- /dev/null +++ b/ENUME/references/MNUM/Projekt2/Zadanie1/zPrzesun.m @@ -0,0 +1,44 @@ +function [wartWlasne, iteracje, time, ok] = zPrzesun(A,tolerance,imax) + % ok - czy funkcja wykonala sie z przekroczeniem imax + % tolerance - toleracnaj jako grna granica wartoci elementw zerowanych + start = tic; + ok = 1; + n = size(A,1); + wartWlasne = diag(zeros(n)); + iteracje = 0; + INITIALsubmatrix = A; + for k=n:-1:2 + DK = INITIALsubmatrix(1:k, 1:k); %macierz potrzebna do wyznaczenia wartosci w1 + i = 0; + + while i <= imax && max(abs(DK(k,1:k-1))) > tolerance + + ev = roots([1, -(DK(k-1,k-1)+DK(k,k)), DK(k,k)*DK(k-1,k-1)-DK(k,k-1)*DK(k-1,k)]); + if abs(ev(1)-DK(k,k)) < abs(ev(2)-DK(k,k)) + shift = ev(1); % nasze przesuniecie jako najblisza DK(k,k) wartosc + % wlasna analizowanej macierzy 2x2 + else + shift = ev(2); + end + DK = DK - eye(k)*shift; %nasza macierz przesunita + [Q1, R1] = qrZmodGS(DK); %faktoryzacja QR + DK = R1*Q1 + eye(k)*shift; %macierz przeksztacona + i = i+1; + + iteracje = iteracje + 1; + end + + if i > imax + ok = 0; + break; + end + wartWlasne(k) = DK(k,k); + + if k>2 + INITIALsubmatrix = DK(1:k-1,1:k-1); %definicja macierzy + else + wartWlasne(1) = DK(1,1); %ostatnia wartosc wlasna + end + end + time = toc(start); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/Zadanie2.m b/ENUME/references/MNUM/Projekt2/Zadanie2/Zadanie2.m new file mode 100644 index 00000000..f8c977d1 --- /dev/null +++ b/ENUME/references/MNUM/Projekt2/Zadanie2/Zadanie2.m @@ -0,0 +1,25 @@ +function [] = Zadanie2(STOPIEN) + x = -5:1:5; + x2 = -5:0.1:5; + y = [-7.7743 -0.2235 1.9026 0.6572 0.1165 -1.8144 -1.0968 -0.8261 1.3327 6.1857 8.2891]; + x=x'; + y=y'; + a = najmnKwadratow(STOPIEN,x,y); + + eukNorm = euklidesNorm(a,y,x); + czebNorm = czebyszewNorm(a,y,x); + + fprintf('Bd aproksymacji w normie Czebyszewa dla rwnania rzdu %d wynosi %d\n',STOPIEN,czebNorm); + fprintf('Bd aproksymacji w normie Euklidesowej dla rwnania rzdu %d wynosi %d\n',STOPIEN,eukNorm); + + %Rysowanie wykresu + scatter(x,y,'filled') + hold on + p = polyval(a,x2); + plot(x2,p); + grid; + title('Aproksymacja przy stopniu rwnym 10 - rwnania normalne'); + xlabel('x'); + ylabel('y'); + legend('Punkty oryginalne','funkcja aproksymujca') +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/czebyszewNorm.m b/ENUME/references/MNUM/Projekt2/Zadanie2/czebyszewNorm.m new file mode 100644 index 00000000..f224f155 --- /dev/null +++ b/ENUME/references/MNUM/Projekt2/Zadanie2/czebyszewNorm.m @@ -0,0 +1,13 @@ +function [maxError] = czebyszewNorm(a,f,x) + p = polyval(a,x); + [s,~] = size(f); + i = 1; + maxError = 0; + while i<=s + err = abs(p(i)-f(i)); + if err > maxError + maxError = err; + end + i = i + 1; + end +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/euklidesNorm.m b/ENUME/references/MNUM/Projekt2/Zadanie2/euklidesNorm.m new file mode 100644 index 00000000..5ba6701f --- /dev/null +++ b/ENUME/references/MNUM/Projekt2/Zadanie2/euklidesNorm.m @@ -0,0 +1,11 @@ +function [err] = euklidesNorm(a,f,x) + p = polyval(a,x); + [s,~] = size(f); + i = 1; + sum=0; + while i<=s + sum = sum + (p(i)-f(i))^2; + i = i + 1; + end + err = sqrt((1/s)*sum); +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/najmnKwadratow.m b/ENUME/references/MNUM/Projekt2/Zadanie2/najmnKwadratow.m new file mode 100644 index 00000000..43315e8f --- /dev/null +++ b/ENUME/references/MNUM/Projekt2/Zadanie2/najmnKwadratow.m @@ -0,0 +1,24 @@ +function [a] = najmnKwadratow(n, x, y) + % n - zadany stopien wielomianu + % x - wektor argumentow + % y - wektor wartosci + + % a - wektor wyznaczonych wspolczynnikow + + + [m, ~] = size(x); %pobranie rozmiarow + A = zeros(m, n+1); + + for i=1:m %wiersze + for j=0:n %kolumny + A(i,n+1-j) = x(i)^(j); %wypeniamy odpowiednimi wartooeciami potegi x + end + end + + %Rozkad QR + [Q, R] = qrZmodGS(A); %rozklad qr metoda g-s z poprzedniego zadania + a = R \ (Q'*y); + + %Uklad rwna normalnych + %a = (A'*A)\(A'*y); %rozwiazanie ukaadu rwnan +end \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR1.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR1.fig new file mode 100644 index 00000000..86c7aa2d Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR1.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR1.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR1.jpg new file mode 100644 index 00000000..7cce230a Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR1.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR10.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR10.fig new file mode 100644 index 00000000..84e8a7b1 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR10.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR10.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR10.jpg new file mode 100644 index 00000000..a130ea07 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR10.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR2.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR2.fig new file mode 100644 index 00000000..1e9b3b46 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR2.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR2.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR2.jpg new file mode 100644 index 00000000..92676b7c Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR2.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR3.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR3.fig new file mode 100644 index 00000000..4c886914 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR3.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR3.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR3.jpg new file mode 100644 index 00000000..5f4f64a8 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR3.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR4.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR4.fig new file mode 100644 index 00000000..ba33638f Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR4.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR4.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR4.jpg new file mode 100644 index 00000000..2f30b846 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR4.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR5.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR5.fig new file mode 100644 index 00000000..25e58b80 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR5.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR5.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR5.jpg new file mode 100644 index 00000000..19283d2c Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR5.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR6.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR6.fig new file mode 100644 index 00000000..9b3baeff Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR6.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR6.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR6.jpg new file mode 100644 index 00000000..26efe79b Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR6.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR7.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR7.fig new file mode 100644 index 00000000..c870206a Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR7.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR7.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR7.jpg new file mode 100644 index 00000000..9aed5baa Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR7.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR8.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR8.fig new file mode 100644 index 00000000..3e3b236b Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR8.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR8.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR8.jpg new file mode 100644 index 00000000..e968e069 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR8.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR9.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR9.fig new file mode 100644 index 00000000..f255a0f4 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR9.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR9.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR9.jpg new file mode 100644 index 00000000..a259adf5 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/QR9.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne1.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne1.fig new file mode 100644 index 00000000..591917d7 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne1.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne1.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne1.jpg new file mode 100644 index 00000000..82423260 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne1.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne10.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne10.fig new file mode 100644 index 00000000..6f6e9fa0 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne10.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne10.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne10.jpg new file mode 100644 index 00000000..8065248c Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne10.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne2.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne2.fig new file mode 100644 index 00000000..5b28e64a Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne2.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne2.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne2.jpg new file mode 100644 index 00000000..3ecd3148 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne2.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne3.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne3.fig new file mode 100644 index 00000000..c5315a4a Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne3.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne3.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne3.jpg new file mode 100644 index 00000000..2eb30474 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne3.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne4.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne4.fig new file mode 100644 index 00000000..e27d047f Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne4.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne4.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne4.jpg new file mode 100644 index 00000000..51252c27 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne4.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne5.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne5.fig new file mode 100644 index 00000000..7ba12392 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne5.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne5.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne5.jpg new file mode 100644 index 00000000..4fa45c44 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne5.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne6.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne6.fig new file mode 100644 index 00000000..1c71a777 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne6.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne6.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne6.jpg new file mode 100644 index 00000000..d6344358 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne6.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne7.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne7.fig new file mode 100644 index 00000000..7cbe7d2a Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne7.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne7.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne7.jpg new file mode 100644 index 00000000..5a4e3c31 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne7.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne8.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne8.fig new file mode 100644 index 00000000..0a7f967d Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne8.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne8.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne8.jpg new file mode 100644 index 00000000..6a665a51 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne8.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne9.fig b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne9.fig new file mode 100644 index 00000000..e957e504 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne9.fig differ diff --git a/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne9.jpg b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne9.jpg new file mode 100644 index 00000000..def397bd Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/Zadanie2/wykresy/rownaniaNormalne9.jpg differ diff --git a/ENUME/references/MNUM/Projekt2/[MNUM] Projekt 2 zadanie 2.4.pdf b/ENUME/references/MNUM/Projekt2/[MNUM] Projekt 2 zadanie 2.4.pdf new file mode 100644 index 00000000..b33ea820 Binary files /dev/null and b/ENUME/references/MNUM/Projekt2/[MNUM] Projekt 2 zadanie 2.4.pdf differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/Bisekcja-1zero.PNG b/ENUME/references/MNUM/Projekt3/Zadanie1/Bisekcja-1zero.PNG new file mode 100644 index 00000000..6421077e Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie1/Bisekcja-1zero.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/Bisekcja-2zero.PNG b/ENUME/references/MNUM/Projekt3/Zadanie1/Bisekcja-2zero.PNG new file mode 100644 index 00000000..c7d8c71f Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie1/Bisekcja-2zero.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/Newton-1zero.PNG b/ENUME/references/MNUM/Projekt3/Zadanie1/Newton-1zero.PNG new file mode 100644 index 00000000..985a5c53 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie1/Newton-1zero.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/Newton-2zero.PNG b/ENUME/references/MNUM/Projekt3/Zadanie1/Newton-2zero.PNG new file mode 100644 index 00000000..ab7f232c Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie1/Newton-2zero.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/Sieczne-1zero.PNG b/ENUME/references/MNUM/Projekt3/Zadanie1/Sieczne-1zero.PNG new file mode 100644 index 00000000..85084752 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie1/Sieczne-1zero.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/Sieczne-2zero.PNG b/ENUME/references/MNUM/Projekt3/Zadanie1/Sieczne-2zero.PNG new file mode 100644 index 00000000..20900028 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie1/Sieczne-2zero.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/Zadanie1.m b/ENUME/references/MNUM/Projekt3/Zadanie1/Zadanie1.m new file mode 100644 index 00000000..d28666ef --- /dev/null +++ b/ENUME/references/MNUM/Projekt3/Zadanie1/Zadanie1.m @@ -0,0 +1,42 @@ +%Zadanie1 +clear; +%Generowanie wykresu funkcji aby sprawdzic poprwanosc otrzymanych rozwiazan +x = -5: .1 : 5; +plot(x, fun(x), 'b','LineWidth', 2) +grid on +axis([-5 5 -150 50]) +hold on; +plot([-1 -1], [-150 50],'r-'); +plot([1.1 1.1], [-150 50],'r-'); +plot([1.9 1.9], [-150 50],'g-'); +plot([4 4], [-150 50],'g-'); +plot(0.2397479765971350,0,'.','MarkerSize',24,'MarkerEdge','k'); +plot(2.8270409098836571,0,'.','MarkerSize',24,'MarkerEdge','k'); + +n=100; +x1 = -1; +x2 = 0; + +%wyznaczanie przedzialow izolacji na podstawie skryptu MNUM +for k=1:2 + for j=1:n + if fun(x1)*fun(x2)<0 + a = x1; + b = x2; + fprintf('Wyniki dla %d miejsca zerowego w przedziale [%d,%d]\n',k,a,b); + bisection('fun',a,b,100); + %secant('fun',a,b,100); + %newton('fun',a,100); + x1 = 3; + x2 = 4; + break; + elseif abs(fun(x1))5)&&(x2<(-5)) + break; %wyjscie z petli po przekroczeniu przedzialu + end + end +end diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/bisection.m b/ENUME/references/MNUM/Projekt3/Zadanie1/bisection.m new file mode 100644 index 00000000..1bea5dc4 --- /dev/null +++ b/ENUME/references/MNUM/Projekt3/Zadanie1/bisection.m @@ -0,0 +1,34 @@ +%funkcja wyznaczajaca zera funkcji metoda bisekcji +%Dane wejsciowe: l,r - lewa i prawa sterona przedzialu poszukiwan +% fun - funkcja +% iter - maksymalna liczba iteracji +%Dane wyjsciowe: zerospoint - wyznaczone miejsce zerowe +function bzeropoint = bisection(fun,l,r,iter) + a = l; + b = r; + fa =feval(fun,a); % Wartosci poczatkowe f(a) i f(b) + fb =feval(fun,b); + for k=1:iter + xm = a + 0.5*(b-a); % Poprawne obliczenie srodka przedzialu + fm = feval(fun,xm); % f(x) w srodku przedzialu + fprintf('%3d [%12.10f;%12.10f] %12.16f %12.3e\n',k,a,b,xm,fm); + if(fm == 0) + return + end + if sign(fm)==sign(fa) % Zero lezy w przedziale [xm,b], zamiana a + a = xm; + fa = fm; + else % Zero lezy w przedziale [a,xm], zamiana b + b = xm; + fb = fm; + end + if(fm == 0) %dodatkowy warunek zakonczenia wykonywania + return + end + end + bzeropoint = xm; + return +end + + + diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/fun.m b/ENUME/references/MNUM/Projekt3/Zadanie1/fun.m new file mode 100644 index 00000000..04cf3f66 --- /dev/null +++ b/ENUME/references/MNUM/Projekt3/Zadanie1/fun.m @@ -0,0 +1,5 @@ +%funkcja zwracajaca wartosc i pochodna z zadania 1 +function [y,dy] = fun (x) +y = 1.4*sin(x)-exp(x)+6*(x)-0.5; +dy = 1.4*cos(x)-exp(x) +6; +end diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/kod_bis.PNG b/ENUME/references/MNUM/Projekt3/Zadanie1/kod_bis.PNG new file mode 100644 index 00000000..b63ad160 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie1/kod_bis.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/kod_newton.PNG b/ENUME/references/MNUM/Projekt3/Zadanie1/kod_newton.PNG new file mode 100644 index 00000000..82aba287 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie1/kod_newton.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/kod_sieczne.PNG b/ENUME/references/MNUM/Projekt3/Zadanie1/kod_sieczne.PNG new file mode 100644 index 00000000..76bf1025 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie1/kod_sieczne.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/newton.m b/ENUME/references/MNUM/Projekt3/Zadanie1/newton.m new file mode 100644 index 00000000..b971919c --- /dev/null +++ b/ENUME/references/MNUM/Projekt3/Zadanie1/newton.m @@ -0,0 +1,23 @@ +%funkcja obliczajaca zera funkcji metoda Newtona +%Dane wejsciowe: +% l - prawa strona przedzialu poszukiwan +% fun - funkcja +% iter - maksymalna liczba iteracji +%Dane wyjsciowe: zerospoint - wyznaczone miejsce zerowe +function nzeropoint = newton(fun,l,iter) + x0 = l; + for k = 1:iter + [fold, fpold] = feval(fun,x0); + dx = fold / fpold; %wyznaczenie przyrostu funkcji + x0 = x0 - dx; + fprintf('%3d %12.10f %12.16f %12.3e \n',k,dx,x0,fold); + if(fold == 0) + return + end + if fold==0 %dodatkowy warunek zatrzumania + nzeropoint = x0; + break; + end + end +end + \ No newline at end of file diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/secant.m b/ENUME/references/MNUM/Projekt3/Zadanie1/secant.m new file mode 100644 index 00000000..af58351f --- /dev/null +++ b/ENUME/references/MNUM/Projekt3/Zadanie1/secant.m @@ -0,0 +1,27 @@ +%funkcja obliczajaca zera funkcji metoda siecznych +%Dane wejsciowe: +% l.r - lewa i prawa strona przedzialu poszukiwan +% fun - funkcja +% iter - maksymalna liczba uteracji +%Dane wyjsciowe: zerospoint - wyznaczone miejsce zerowe +function szeropoint = secant(fun,l,r,iter) + a = l; + b = r; + fa = feval(fun,a); %wartosc funkcji w punkcie start. + for k = 1:iter + fb = feval(fun,b); + dx = fb * (b-a) / (fb-fa); %wyznaczenie przeciecia sieczna + xm = b-dx; %zawezenie przedzialu + if(isnan(xm)) + return + end + a = b; + b = xm; + fa = fb; + szeropoint = b; + fprintf('%3d [%12.10f;%12.10f] %12.16f %12.3e\n',k,a,b,xm,fb); + if(fb == 0) %dodatkowy warunek zakonczenia wykonywania + return + end + end +end diff --git a/ENUME/references/MNUM/Projekt3/Zadanie1/wykres.jpg b/ENUME/references/MNUM/Projekt3/Zadanie1/wykres.jpg new file mode 100644 index 00000000..5f07f629 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie1/wykres.jpg differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie2/Zadanie2.m b/ENUME/references/MNUM/Projekt3/Zadanie2/Zadanie2.m new file mode 100644 index 00000000..62f5c5c7 --- /dev/null +++ b/ENUME/references/MNUM/Projekt3/Zadanie2/Zadanie2.m @@ -0,0 +1,16 @@ +%Generowanie wykresu funkcji aby sprawdzic poprwanosc otrzymanych rozwiazan +clear; +x = -5: .1 : 2; +plot(x, df(x,0), 'b','LineWidth', 2) +grid on +axis([-5 2 -100 50]) + +for i = -5:4 + result(i+6,:) = muller(i,6); +end + +disp(result); + + + + diff --git a/ENUME/references/MNUM/Projekt3/Zadanie2/df.m b/ENUME/references/MNUM/Projekt3/Zadanie2/df.m new file mode 100644 index 00000000..7ed65361 --- /dev/null +++ b/ENUME/references/MNUM/Projekt3/Zadanie2/df.m @@ -0,0 +1,19 @@ +%DF funkcja zwracajaca wyznaczona analitycznie pochodna wielomianu +%danego w zadaniu. +%x - argument +%n - 0-wartosac funkcji,1-pierwsza pochodna,2-druga pochodna +% f(x) = x^4+3x^3-8x^2+4x+2 +% f'(x) = 4x^3+9x^2-16x+4 +% f''(x) = 12x^2+18x-16 +function [value] = df(x,n) + if n == 0 + value = x.^4+3*x.^3-8*x.^2+4*x+2; + elseif n == 1 + value = 4*x.^3+9*x.^2-16*x+4; + elseif n == 2 + value = 12*x.^2+18*x-16; + else + value = 0; + end +end + diff --git a/ENUME/references/MNUM/Projekt3/Zadanie2/kod_Muller.PNG b/ENUME/references/MNUM/Projekt3/Zadanie2/kod_Muller.PNG new file mode 100644 index 00000000..03df3241 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie2/kod_Muller.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie2/miejscaZerowe.PNG b/ENUME/references/MNUM/Projekt3/Zadanie2/miejscaZerowe.PNG new file mode 100644 index 00000000..60457f7e Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie2/miejscaZerowe.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie2/muller.m b/ENUME/references/MNUM/Projekt3/Zadanie2/muller.m new file mode 100644 index 00000000..86eae29d --- /dev/null +++ b/ENUME/references/MNUM/Projekt3/Zadanie2/muller.m @@ -0,0 +1,21 @@ +%Funkcja zwracajaca wektor pierwiastkow rzeczywistych wielomianu +%danego w zadaniu +%x - punkt startowy +%n - ilosc iteracji +function [z] = muller(x,n) + %z = (1:n); + for i = 1:n + %obliczamy mianowniki punktow w celu ich porownania + z1 = df(x,1)+sqrt(df(x,1)^2-2*df(x,0)*df(x,2)); + z2 = df(x,1)-sqrt(df(x,1)^2-2*df(x,0)*df(x,2)); + + if abs(z1) > abs(z2) + zmin = -2*df(x,0)/z1; + else + zmin = -2*df(x,0)/z2; + end + x = x+zmin; + fprintf('%d %f %f\n ',i,x,zmin); + end + z = x; +end diff --git a/ENUME/references/MNUM/Projekt3/Zadanie2/wykres.jpg b/ENUME/references/MNUM/Projekt3/Zadanie2/wykres.jpg new file mode 100644 index 00000000..820bdf68 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie2/wykres.jpg differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie2/wyniki1.PNG b/ENUME/references/MNUM/Projekt3/Zadanie2/wyniki1.PNG new file mode 100644 index 00000000..5e9cf7d8 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie2/wyniki1.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/Zadanie2/wyniki2.PNG b/ENUME/references/MNUM/Projekt3/Zadanie2/wyniki2.PNG new file mode 100644 index 00000000..d3f7fce8 Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/Zadanie2/wyniki2.PNG differ diff --git a/ENUME/references/MNUM/Projekt3/[MNUM] Projekt 3 zadanie 3.1.pdf b/ENUME/references/MNUM/Projekt3/[MNUM] Projekt 3 zadanie 3.1.pdf new file mode 100644 index 00000000..6e2fdece Binary files /dev/null and b/ENUME/references/MNUM/Projekt3/[MNUM] Projekt 3 zadanie 3.1.pdf differ diff --git a/ENUME/references/MNUM/README.md b/ENUME/references/MNUM/README.md new file mode 100644 index 00000000..4aff412c --- /dev/null +++ b/ENUME/references/MNUM/README.md @@ -0,0 +1 @@ +# MNUM \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0101_Eps_maszynowy.m b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0101_Eps_maszynowy.m new file mode 100644 index 00000000..d2308909 --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0101_Eps_maszynowy.m @@ -0,0 +1,23 @@ +%% +% obliczenie epsa maszynowego + +i = 0; +while (1 + 2^i > 1) + i = i - 1; +end +i = i + 1; + +fprintf('epsilon maszynowy to %e\n', 2^i); +fprintf('czyli 2^%d\n', i); +%% +% wywolanie funkcji matlaba obliczajacej eps maszynowy + +fprintf('epsilon maszynowy wyznaczony przez MatLaba to: %e\n', eps); +%% +% sprawdzenie + +if (eps == 2^i) + disp("eps wyznaczony poprawnie") +else + disp("blad wyznaczenia epsa") +end \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0101_Eps_maszynowy.mlx b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0101_Eps_maszynowy.mlx new file mode 100644 index 00000000..2de824b2 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0101_Eps_maszynowy.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_Gauss.m b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_Gauss.m new file mode 100644 index 00000000..de4b0975 --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_Gauss.m @@ -0,0 +1,216 @@ +%% +% zaimportowanie macierzy + +clear; +clc; +typ = 3; %a-1,b-2,c-3 +blad_res_a = zeros(17,2); +blad_res_b = zeros(17,2); +blad_res_c = zeros(17,2); + +for r = 5:10:165 + for typ = 1:3 + if(typ == 1) + temp = macierzA(r); + elseif(typ == 2) + temp = macierzB(r); + elseif(typ == 3) + temp = macierzC(r); + end + A = temp(:, 1:end-1); + b = temp(:,end); + % wywolanie funkcji Gaussa oraz residuum + temp = gauss(A, b); + A = temp(:, 1:end-2); + rozwiazanie = temp(:, end-1); + b = temp(:, end); + a = norma_residuum(A, rozwiazanie, b); + + if(typ == 1) + blad_res_a((r+5)/10,:) = [a*100000000000, r]; + elseif(typ == 2) + blad_res_b((r+5)/10,:) = [a*100000000000, r]; + elseif(typ == 3) + blad_res_c((r+5)/10,:) = [a, r]; + end + end +end +%% +% utworzenie wykresow + +plot(blad_res_a(:,2),blad_res_a(:,1)); +title('Zaleznosc wartosci bledu od ilosci rownan w ukladzie (typ A)') +xlabel('ilosc rownan') +ylabel('norma residuum *10^-12') + +plot(blad_res_b(:,2),blad_res_b(:,1)); +title('Zaleznosc wartosci bledu od ilosci rownan w ukladzie (typ B)') +xlabel('ilosc rownan') +ylabel('norma residuum *10^-12') + +plot(blad_res_c(:,2),blad_res_c(:,1)); +title('Zaleznosc wartosci bledu od ilosci rownan w ukladzie (typ C)') +xlabel('ilosc rownan') +ylabel('norma residuum') +%% +% algorytm Gaussa + +function g = gauss(wspolczynniki, rozw) + rozmiar = size(rozw); + pierwotne_b = rozw; + pierwotne_wspolczynniki = wspolczynniki; + % A B C + % D E F + % G H I + % a - element uznany za glowny w danej kolumnie, + % w tym przypadku kolejno: A, E + % wspolczynniki(l,i) - wspolczynnik "pod schodkiem", + % czyli tutaj: D/A, G/A, H/E + for i = 1:(rozmiar-1) + % wybor elementu glownego + podmacierz = wspolczynniki(i:rozmiar, i:rozmiar); + [el_glowny, ind_glowny] = max(podmacierz(:)); + [ind_wiersz, ind_kolumna] = ind2sub(size(podmacierz), ind_glowny); + % z powyzszej linii uzyskujemy indexy w podmacierzy + % wiec musimy dodac 'i-1' + wspolczynniki([i,ind_wiersz+i-1],:) = wspolczynniki([ind_wiersz+i-1,i],:); + pierwotne_wspolczynniki([i,ind_wiersz+i-1],:) = pierwotne_wspolczynniki([i,ind_wiersz+i-1],:); + rozw([i,ind_wiersz+i-1],:) = rozw([ind_wiersz+i-1,i],:); + pierwotne_b([i,ind_kolumna+i-1], :) = pierwotne_b([i,ind_kolumna+i-1], :); + wspolczynniki(:,[i,ind_kolumna+i-1]) = wspolczynniki(:,[ind_kolumna+i-1,i]); + pierwotne_wspolczynniki(:,[i,ind_kolumna+i-1]) = pierwotne_wspolczynniki(:,[ind_kolumna+i-1,i]); + % wyznaczenie rozkladu LU + a = wspolczynniki(i,i); + for l = (i+1):rozmiar + wspolczynniki(l,i) = wspolczynniki(l,i) / a; + wspolczynniki(l, (i+1):end) = wspolczynniki(l, (i+1):end) - wspolczynniki(l,i) * wspolczynniki(i, (i+1):end); + rozw(l) = rozw(l) - wspolczynniki(l,i) * rozw(i); + end + end + + % U * x = rozw -> wyznaczenie x + for i = (rozmiar:-1:1) + % Ax=b; -> odejmowanie wartosci znanych ze strony rozwiazan + for j = (i+1):(rozmiar) + rozw(i) = rozw(i) - wspolczynniki((i),(j))*wspolczynniki((j),(j)); + end + wspolczynniki(i,i) = rozw(i)/wspolczynniki(i,i); + end + + %przepisanie rozwiazan do macierzy rozw + for i = (1:rozmiar) + rozw(i) = wspolczynniki(i,i); + end + g = [pierwotne_wspolczynniki, rozw, pierwotne_b]; +end +%% +% norma residuum + +function nr = norma_residuum(wspolczynniki, x, rozw) + residuum = wspolczynniki*x - rozw; + nr = norm(residuum); +end +%% +% tworzenie macierzy typu a o zadanym rozmiarze rozmiar_a + +function mac_a = macierzA(rozmiar_a) + macierz_a = zeros(rozmiar_a); + + for j = 1:rozmiar_a + for i = 1:rozmiar_a + if (i < j-1) || (i > j+1) + macierz_a(i,j) = 0; + elseif (i == j-1) || (i == j+1) + macierz_a(i,j) = 2; + else + macierz_a(i,j) = 6; + end + end + end + + wolne_a = zeros(rozmiar_a, 1); + % deklaracja pierwszej waroci, aby pozostale + % mogly powstac przez dodawanie zamiast mnozenia + wolne_a(1) = 9.5; + + for i = 2:rozmiar_a + wolne_a(i) = wolne_a(i-1) + 0.5; + end + + mac_a = [macierz_a, wolne_a]; +end +%% +% tworzenie macierzy typu b o zadanym rozmiarze rozmiar_b + +function mac_b = macierzB(rozmiar_b) + macierz_b = zeros(rozmiar_b); + % wygenerowanie pierwszej i ostatniej kolumny pozwoli w pozniejszych + % etapach przekopiowywac wartosci zamiast obliczac je na nowo + macierz_b(1,1) = 1/8; + macierz_b(end,end) = 1/8; + % pierwsza kolumna + macierz_b(2, 1) = 6; + for i = 3:rozmiar_b + macierz_b(i, 1) = macierz_b(i-1, 1) + 5; + end + % ostatnia kolumna + macierz_b(end - 1, end) = -4; + for i = (rozmiar_b-2):-1:1 + macierz_b(i, end) = macierz_b(i + 1, end) - 5; + end + + % wykorzystanie wartosci ze skrajnych kolumn + for j = 2:(rozmiar_b-1) + for i = 1:rozmiar_b + if (i < j) + macierz_b(i,j) = macierz_b(end-(j-i),end); + else + macierz_b(i,j) = macierz_b(i-1,j-1); + end + end + end + + wolne_b = zeros(rozmiar_b, 1); + % deklaracja pierwszej waroci, aby pozostale + % mogly powstac przez dodawanie zamiast mnozenia + wolne_b(1) = -2.5; + + for i = 2:rozmiar_b + wolne_b(i) = wolne_b(i-1) + 0.5; + end + + mac_b = [macierz_b, wolne_b]; +end +%% +% tworzenie macierzy typu c o zadanym rozmiarze rozmiar_c + +function mac_c = macierzC(rozmiar_c) + macierz_c = zeros(rozmiar_c); + + % wygenerowanie pierwszej kolumny + % kolumny od 2 do end bd przekopiowywac + % (rozmiar_c-1) wartosci z poprzednich kolumn + % i wyliczac jedna wlasna + for i = 1:rozmiar_c + macierz_c(i, 1) = 4/(5*i); + end + + % wykorzystanie wartosci z pierwszej kolumny + for j = 2:rozmiar_c + for i = 1:(rozmiar_c-1) + macierz_c(i,j) = macierz_c(i+1, j-1); + end + macierz_c(rozmiar_c, j) = 4/(5*(rozmiar_c+j-1)); + end + wolne_c = zeros(rozmiar_c, 1); + + % deklaracja pierwszej waroci, aby pozostale + % mogly powstac przez dodawanie zamiast mnozenia + wolne_c(1) = 0.5; + + for i = 3:2:rozmiar_c + wolne_c(i) = wolne_c(i-2) + 1; + end + + mac_c = [macierz_c, wolne_c]; +end \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_Gauss.mlx b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_Gauss.mlx new file mode 100644 index 00000000..e43cc1ea Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_Gauss.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzA.m b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzA.m new file mode 100644 index 00000000..0aae8ebf --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzA.m @@ -0,0 +1,34 @@ +%% +% tworzenie macierzy typu a o zadanym rozmiarze rozmiar_a z wykorzystaniem +% prealokacji pamici + +rozmiar_a = 10; + +macierz_a = zeros(rozmiar_a); + +for j = 1:rozmiar_a + for i = 1:rozmiar_a + if (i < j-1) || (i > j+1) + macierz_a(i,j) = 0; + elseif (i == j-1) || (i == j+1) + macierz_a(i,j) = 2; + else + macierz_a(i,j) = 6; + end + end +end + +%macierz_a +%% +% wyrazy wolne a + +wolne_a = zeros(rozmiar_a, 1); +% deklaracja pierwszej waroci, aby pozostale +% mogly powstac przez dodawanie zamiast mnozenia +wolne_a(1) = 9.5; + +for i = 2:rozmiar_a + wolne_a(i) = wolne_a(i-1) + 0.5; +end + +%wolne_a \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzA.mlx b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzA.mlx new file mode 100644 index 00000000..dbde8787 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzA.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzB.m b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzB.m new file mode 100644 index 00000000..df85b6ea --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzB.m @@ -0,0 +1,47 @@ +%% +% tworzenie macierzy typu b o zadanym rozmiarze rozmiar_b z wykorzystaniem +% prealokacji pamici + +rozmiar_b = 5; + +macierz_b = zeros(rozmiar_b); + +% wygenerowanie pierwszej i ostatniej kolumny pozwoli w pozniejszych +% etapach przekopiowywac wartosci zamiast obliczac je na nowo +macierz_b(1,1) = 1/8; +macierz_b(end,end) = 1/8; +% pierwsza kolumna +macierz_b(2, 1) = 6; +for i = 3:rozmiar_b + macierz_b(i, 1) = macierz_b(i-1, 1) + 5; +end +% ostatnia kolumna +macierz_b(end - 1, end) = -4; +for i = (rozmiar_b-2):-1:1 + macierz_b(i, end) = macierz_b(i + 1, end) - 5; +end + +% wykorzystanie wartosci ze skrajnych kolumn +for j = 2:(rozmiar_b-1) + for i = 1:rozmiar_b + if (i < j) + macierz_b(i,j) = macierz_b(end-(j-i),end); + else + macierz_b(i,j) = macierz_b(i-1,j-1); + end + end +end + +macierz_b +%% +% wyrazy wolne b + +wolne_b = zeros(rozmiar_b, 1); + +% deklaracja pierwszej waroci, aby pozostale +% mogly powstac przez dodawanie zamiast mnozenia +wolne_b(1) = -2.5; + +for i = 2:rozmiar_b + wolne_b(i) = wolne_b(i-1) + 0.5; +end \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzB.mlx b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzB.mlx new file mode 100644 index 00000000..da5819f0 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzB.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzC.m b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzC.m new file mode 100644 index 00000000..e37bc014 --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzC.m @@ -0,0 +1,37 @@ +%% +% tworzenie macierzy typu c o zadanym rozmiarze rozmiar_c z wykorzystaniem +% prealokacji pamici + +rozmiar_c = 4; + +macierz_c = zeros(rozmiar_c); + +% wygenerowanie pierwszej kolumny +% kolumny od 2 do end bd przekopiowywac +% (rozmiar_c-1) wartosci z poprzednich kolumn +% i wyliczac jedna wlasna +for i = 1:rozmiar_c + macierz_c(i, 1) = 4/(5*i); +end + +% wykorzystanie wartosci z pierwszej kolumny +for j = 2:rozmiar_c + for i = 1:(rozmiar_c-1) + macierz_c(i,j) = macierz_c(i+1, j-1); + end + macierz_c(rozmiar_c, j) = 4/(5*(rozmiar_c+j-1)); +end +%% +% wyrazy wolne c + +wolne_c = zeros(rozmiar_c, 1); + +% deklaracja pierwszej waroci, aby pozostale +% mogly powstac przez dodawanie zamiast mnozenia +wolne_c(1) = 0.5; + +for i = 3:2:rozmiar_c + wolne_c(i) = wolne_c(i-2) + 1; +end + +wolne_c \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzC.mlx b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzC.mlx new file mode 100644 index 00000000..a78ab295 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_macierzC.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_testowa53.m b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_testowa53.m new file mode 100644 index 00000000..61d38abf --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_testowa53.m @@ -0,0 +1,22 @@ +%% +% probne dane + +% pierwsze 3 kolumny - lewa strona rownania - niewiadome +test5 = true; + +if(test5) + wspolczynniki = [2 -1 4 1 -1; + -1 3 -2 -1 2; + 5 1 3 -4 1; + 3 -2 -2 -2 3; + -4 -1 -5 3 -4]; + rozw = [7; 1; 33; 24; -49]; +else + wspolczynniki = [3 1 6; + 2 1 3; + 1 1 1]; + rozw = [2; 7; 4]; +end + +rozmiar = (size(wspolczynniki,1)); +wspolczynniki \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_testowa53.mlx b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_testowa53.mlx new file mode 100644 index 00000000..4a115026 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0102_testowa53.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0103_GaussSeidel.m b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0103_GaussSeidel.m new file mode 100644 index 00000000..d6a6966a --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0103_GaussSeidel.m @@ -0,0 +1,207 @@ +%% +% dane z zadania + +clear; +clc; + +A = [12 2 1 -6; + 4 -15 2 -5; + 2 -1 8 -2; + 5 -2 1 -8]; +b = [6; 8; 20; 2]; +e = 0.01; +%% +% wywolanie funkcji + +display(gauss_seidel(A, b, e)); +norma_residuum(A, gauss_seidel(A, b, e), b) +%% +% test dla macierzy z zad 2 + +blad_res_a = zeros(5,2); +blad_res_b = zeros(5,2); +blad_res_c = zeros(5,2); + +for r = 5:3:15 + for typ = 1:3 + if(typ == 1) + temp = macierzA(r); + elseif(typ == 2) + temp = macierzB(r); + elseif(typ == 3) + temp = macierzC(r); + end + A = temp(:, 1:end-1); + b = temp(:,end); + % wywolanie funkcji Gaussa oraz residuum + rozwiazanie = gauss_seidel(A, b, e); + a = norma_residuum(A, rozwiazanie, b); + + if(typ == 1) + blad_res_a((r+1)/3,:) = [a, r]; + elseif(typ == 2) + blad_res_b((r+1)/3,:) = [a, r]; + elseif(typ == 3) + blad_res_c((r+1)/3,:) = [a, r]; + end + end +end +%% +% wyswietlenie bledow + +blad_res_a +blad_res_b +blad_res_c + +%% +% algorytm + +function gs = gauss_seidel(wspolczynniki, rozw, err) + rozmiar = (size(wspolczynniki,1)); + x = zeros(rozmiar, 1); + blad = zeros(rozmiar, 1); + % zeby warunek petli byl spelniony + blad(1) = 100; + % rozklad L + D + U + L = zeros(rozmiar); + U = zeros(rozmiar); + for i = 1:rozmiar + L(i, 1:i-1) = wspolczynniki(i, 1:i-1); + U(i, i+1:rozmiar) = wspolczynniki(i, i+1:rozmiar); + end + % wyznaczenie D^-1 + D_odwr = zeros(rozmiar); + for i = 1:rozmiar + D_odwr(i,i) = 1/wspolczynniki(i,i); + end + % wyznaczenie D^-1 * b, D^-1 * L, D^-1 * U + rozw = D_odwr * rozw; + L = D_odwr * L; + U = D_odwr * U; + % polaczenie odwroconych macierzy L i U + % dla latwosci wykonywania petli + LU = (-1) * (L + U); + + while(max(abs(blad)) > err) + for i = 1:rozmiar + poprzednia_wartosc = x(i); + x(i) = rozw(i); + for j = 1:(rozmiar) + x(i) = x(i) + LU(i,j) * x(j); + end + blad(i) = (x(i)-poprzednia_wartosc)/x(i); + end + end + gs = x; +end +%% +% norma residuum + +function nr = norma_residuum(wspolczynniki, x, rozw) + residuum = wspolczynniki*x - rozw; + nr = norm(residuum); +end +%% +% tworzenie macierzy typu a o zadanym rozmiarze rozmiar_a + +function mac_a = macierzA(rozmiar_a) + macierz_a = zeros(rozmiar_a); + + for j = 1:rozmiar_a + for i = 1:rozmiar_a + if (i < j-1) || (i > j+1) + macierz_a(i,j) = 0; + elseif (i == j-1) || (i == j+1) + macierz_a(i,j) = 2; + else + macierz_a(i,j) = 6; + end + end + end + + wolne_a = zeros(rozmiar_a, 1); + % deklaracja pierwszej waroci, aby pozostale + % mogly powstac przez dodawanie zamiast mnozenia + wolne_a(1) = 9.5; + + for i = 2:rozmiar_a + wolne_a(i) = wolne_a(i-1) + 0.5; + end + + mac_a = [macierz_a, wolne_a]; +end +%% +% tworzenie macierzy typu b o zadanym rozmiarze rozmiar_b + +function mac_b = macierzB(rozmiar_b) + macierz_b = zeros(rozmiar_b); + % wygenerowanie pierwszej i ostatniej kolumny pozwoli w pozniejszych + % etapach przekopiowywac wartosci zamiast obliczac je na nowo + macierz_b(1,1) = 1/8; + macierz_b(end,end) = 1/8; + % pierwsza kolumna + macierz_b(2, 1) = 6; + for i = 3:rozmiar_b + macierz_b(i, 1) = macierz_b(i-1, 1) + 5; + end + % ostatnia kolumna + macierz_b(end - 1, end) = -4; + for i = (rozmiar_b-2):-1:1 + macierz_b(i, end) = macierz_b(i + 1, end) - 5; + end + + % wykorzystanie wartosci ze skrajnych kolumn + for j = 2:(rozmiar_b-1) + for i = 1:rozmiar_b + if (i < j) + macierz_b(i,j) = macierz_b(end-(j-i),end); + else + macierz_b(i,j) = macierz_b(i-1,j-1); + end + end + end + + wolne_b = zeros(rozmiar_b, 1); + % deklaracja pierwszej waroci, aby pozostale + % mogly powstac przez dodawanie zamiast mnozenia + wolne_b(1) = -2.5; + + for i = 2:rozmiar_b + wolne_b(i) = wolne_b(i-1) + 0.5; + end + + mac_b = [macierz_b, wolne_b]; +end +%% +% tworzenie macierzy typu c o zadanym rozmiarze rozmiar_c + +function mac_c = macierzC(rozmiar_c) + macierz_c = zeros(rozmiar_c); + + % wygenerowanie pierwszej kolumny + % kolumny od 2 do end bd przekopiowywac + % (rozmiar_c-1) wartosci z poprzednich kolumn + % i wyliczac jedna wlasna + for i = 1:rozmiar_c + macierz_c(i, 1) = 4/(5*i); + end + + % wykorzystanie wartosci z pierwszej kolumny + for j = 2:rozmiar_c + for i = 1:(rozmiar_c-1) + macierz_c(i,j) = macierz_c(i+1, j-1); + end + macierz_c(rozmiar_c, j) = 4/(5*(rozmiar_c+j-1)); + end + wolne_c = zeros(rozmiar_c, 1); + + % deklaracja pierwszej waroci, aby pozostale + % mogly powstac przez dodawanie zamiast mnozenia + wolne_c(1) = 0.5; + + for i = 3:2:rozmiar_c + wolne_c(i) = wolne_c(i-2) + 1; + end + + mac_c = [macierz_c, wolne_c]; +end \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0103_GaussSeidel.mlx b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0103_GaussSeidel.mlx new file mode 100644 index 00000000..15827961 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt01/Matlab/mnum_0103_GaussSeidel.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt01/Projekt01.lswitaj.1.43.pdf b/ENUME/references/MatLabMNUM/Projekt01/Projekt01.lswitaj.1.43.pdf new file mode 100644 index 00000000..741f56f8 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt01/Projekt01.lswitaj.1.43.pdf differ diff --git a/ENUME/references/MatLabMNUM/Projekt01/Sprawozdanie_01.docx b/ENUME/references/MatLabMNUM/Projekt01/Sprawozdanie_01.docx new file mode 100644 index 00000000..ac3884cf Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt01/Sprawozdanie_01.docx differ diff --git a/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR.m b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR.m new file mode 100644 index 00000000..2ee05510 --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR.m @@ -0,0 +1,229 @@ +%% +% program + +% clc; +% clear; +% +% iteracje_sym_bezprzes = zeros(30); +% iteracje_sym_przes = zeros(30); +% cond_sym = zeros(30); +% cond_niesym = zeros(30); +% iteracje_niesym_przes = zeros(30); +% +% for rozmiar = [5 10 20] +% for i = 1:30 +% A = macierz_symetryczna(rozmiar); +% [B iteracje_sym_bezprzes(i,rozmiar)] = qr_bezprzesuniec(A); +% [B iteracje_sym_przes( i,rozmiar)] = qr_przesuniecia(A); +% cond_sym(i,rozmiar) = cond(A); +% %eig(A); +% A = macierz_niesymetryczna(rozmiar); +% [B iteracje_niesym_przes(i,rozmiar)] = qr_przesuniecia(A); +% cond_niesym(i,rozmiar) = cond(A); +% end +% end +%% +% statystyki i czyszczenie danych + +% for rozmiar = [5 10 20] +% rozmiar +% sr_sym_bezprzes = iteracje_sym_bezprzes(:,rozmiar) +% sr_sym_przes = iteracje_sym_przes(:,rozmiar) +% sr_niesym_przes = iteracje_niesym_przes(:,rozmiar) +% for i = 1:3 +% [wart indx] = max(cond_sym(:,rozmiar)); +% iteracje_sym_bezprzes(indx,rozmiar) = 0; +% iteracje_sym_przes(indx,rozmiar) = 0; +% cond_sym(indx,rozmiar) = 0; +% +% [wart indx] = max(cond_niesym(:,rozmiar)); +% iteracje_niesym_przes(indx,rozmiar) = 0; +% cond_niesym(indx,rozmiar) = 0; +% end +% end + +for rozmiar = [5 10 20] + rozmiar + sr_sym_bezprzes = mean(iteracje_sym_bezprzes(:,rozmiar)) + sr_sym_przes = mean(iteracje_sym_przes(:,rozmiar)) + sr_niesym_przes = mean(iteracje_niesym_przes(:,rozmiar)) +end +%% +% wykresy + +for rozmiar = [5 10 20] + figure + plot(cond_sym(:,rozmiar),iteracje_sym_bezprzes(:,rozmiar),'bo', cond_sym(:,rozmiar), iteracje_sym_przes(:,rozmiar), 'r*'); + title(['Macierz symetryczna o rozmiarze ' num2str(rozmiar)]) + xlabel('wskaznik uwarunkowania') + ylabel('ilosc potrzebnych iteracji') + legend({'bez przesuniec','z przesunieciami'},'Location','northeast'); + figure + plot(cond_niesym(:,rozmiar),iteracje_niesym_przes(:,rozmiar),'go'); + title(['Macierz niesymetryczna o rozmiarze ' num2str(rozmiar)]) + xlabel('wskaznik uwarunkowania') + ylabel('ilosc potrzebnych iteracji') + legend({'z przesunieciami'},'Location','northeast'); +end +%% +% *funkcje pomocnicze* +% +% rozklad QR + +function [Q R] = qr_rozklad(A) + [r_wiersze r_kolumny] = size(A); + Q = zeros(r_wiersze); + if r_wiersze > r_kolumny + R = eye(r_wiersze); + Q = eye(r_wiersze); + else + R = eye(r_kolumny); + Q = eye(r_wiersze); + end + %Gram-Schmidt + for i = 1:r_kolumny + Q(:,i) = A(:,i); + for j = 1:(i-1) + R(j,i) = mydot(Q(:,j),A(:,i))/mydot(Q(:,j),Q(:,j)); + Q(:,i) = Q(:,i) - R(j,i)*Q(:,j); + end + end + Q = Q(1:r_wiersze,1:r_kolumny); + %normalizacja + N = zeros(r_wiersze); + for i = 1:r_kolumny + N(i,i) = norm(Q(:,i)); + Q(:,i) = Q(:,i)/N(i,i); + end + R = N*R; + + if r_wiersze > r_kolumny + R = R(1:r_kolumny,1:r_kolumny); + else + R = R(1:r_wiersze,1:r_wiersze); + end +end + +%% +% algorytm obliczania wartosci wlasnych metoda QR bez przesuniec + +function [wart_wlasne i] = qr_bezprzesuniec(A) + i = 0; + while tolerancja(A) > 0.00001 & i < 200+1 + [Q R] = qr_rozklad(A); + A = R * Q; + i = i+1; + end + wart_wlasne = wektor(A); +end +%% +% algorytm obliczania wartosci wlasnych metoda QR z przesunieciami + +function [wart_wlasne i] = qr_przesuniecia(A) + rozmiar = size(A,1); + i = 0; + wart_wlasne = zeros(rozmiar); + wart_wlasne = wart_wlasne(:,1); + for j = rozmiar:-1:2 + while max(abs(A(j,1:j-1))) > 0.00001 & i < 200+1 + mala_macierz = A(j-1:j,j-1:j); % macierz 2x2, + [x1 x2] = pierw_f_kwadratowej(mala_macierz); + przesuniecie = blizsza_liczba(mala_macierz(2,2), x1, x2); % z ktorej wyznaczana jest najlepsza wart. wlasna + A = A - eye(j)*przesuniecie; + [Q R] = qr_rozklad(A); + A = R * Q + eye(j)*przesuniecie; + i = i+1; + end + wart_wlasne(j) = A(j,j); + if j > 2 + A = A(1:j-1,1:j-1); %deflacja + else + wart_wlasne(1) = A(1,1); + end + end +end +%% +% wyznaczanie pierw f. kwadratowej + +function [x1 x2] = pierw_f_kwadratowej(mala_macierz) + a = 1; + b = -(mala_macierz(1,1)+mala_macierz(2,2)); + c = (mala_macierz(1,1)*mala_macierz(2,2))-(mala_macierz(2,1)*mala_macierz(1,2)); + + x1 = (-b + sqrt(b*b - 4*a*c))/(2*a); + x2 = (-b - sqrt(b*b - 4*a*c))/(2*a); + if abs(x2) > abs(x1) + x1 = x2; + end + %drugi pierwiastek ze wzorw Viete'a + x2 = ((-b)/a) - x1; +end +%% +% wybor pierwiastka blizszego d(n,n) + +function x = blizsza_liczba(wlasciwa, x1, x2) + if abs(wlasciwa-x1) < abs(wlasciwa-x2) + x = x1; + else + x = x2; + end +end +%% +% autorska implementacja matlabowej funkcji dot() + +function md = mydot(A,B) + rozmiar = size(A); + md = 0; + for i = 1:rozmiar + md = md + A(i)*B(i); + end +end +%% +% funkcja wektoryzujaca macierz diagonalna + +function w = wektor(A) + rozmiar = size(A); + for i = 1:rozmiar + w(i,1) = A(i,i); + end +end +%% +% sprawdzenie tolerancji + +function tol = tolerancja(A) + rozmiar = size(A); + A = abs(A); + tol = 0; + if rozmiar > 2 + for i = 1:rozmiar + if max(A(i,i+1:end)) > tol + tol = max(A(i,i+1:end)); + end + if max(A(i,1:i-1)) > tol + tol = max(A(i,1:i-1)); + end + end + else + tol = 0; + end +end +%% +% tworzenie macierzy symetrycznej o zadanym rozmiarze + +function mac_sym = macierz_symetryczna(rozmiar) + mac_sym = randi([0 50],rozmiar,rozmiar); + mac_sym = mac_sym + mac_sym'; +end +%% +% tworzenie macierzy niesymetrycznej o zadanym rozmiarze + +function mac_nsym = macierz_niesymetryczna(rozmiar) + mac_nsym = randi([0 100],rozmiar,rozmiar); +end +%% +% norma residuum + +function nr = norma_residuum(wspolczynniki, x, rozw) + residuum = wspolczynniki*x - rozw; + nr = norm(residuum); +end \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR.mlx b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR.mlx new file mode 100644 index 00000000..e3cd3800 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_przemielone_statystyki.m b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_przemielone_statystyki.m new file mode 100644 index 00000000..62380871 --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_przemielone_statystyki.m @@ -0,0 +1,237 @@ +%% +% program + +% clc; +% clear; +% +% iteracje_sym_bezprzes = zeros(30); +% iteracje_sym_przes = zeros(30); +% cond_sym = zeros(30); +% cond_niesym = zeros(30); +% iteracje_niesym_przes = zeros(30); +% +% for rozmiar = [5 10 20] +% for i = 1:30 +% A = macierz_symetryczna(rozmiar); +% [B iteracje_sym_bezprzes(i,rozmiar)] = qr_bezprzesuniec(A); +% [B iteracje_sym_przes( i,rozmiar)] = qr_przesuniecia(A); +% cond_sym(i,rozmiar) = cond(A); +% %eig(A); +% A = macierz_niesymetryczna(rozmiar); +% [B iteracje_niesym_przes(i,rozmiar)] = qr_przesuniecia(A); +% cond_niesym(i,rozmiar) = cond(A); +% end +% end +%% +% statystyki i czyszczenie danych + +[wart indx] = max(cond_sym(:,5)) + +% for rozmiar = [5 10 20] +% +% iteracje_sym_bezprzes(:,rozmiar); +% iteracje_sym_przes(:,rozmiar); +% cond_sym(:,rozmiar); +% +% iteracje_niesym_przes(:,rozmiar); +% cond_niesym(:,rozmiar); +% end +%% +% wykresy + +plot(cond_sym(:,5),iteracje_sym_bezprzes(:,5),'bo', cond_sym(:,5), iteracje_sym_przes(:,5), 'r*'); +title('Zaleznosc uwarunkowania od ilosci iteracji mac symetryczna o rozmiarze 5') +plot(cond_niesym(:,5),iteracje_niesym_przes(:,5),'go'); +title('Zaleznosc uwarunkowania od ilosci iteracji mac niesymetryczna 5') + +plot(cond_sym(:,10),iteracje_sym_bezprzes(:,10),'bo', cond_sym(:,10), iteracje_sym_przes(:,10), 'r*'); +title('Zaleznosc uwarunkowania od ilosci iteracji mac symetryczna o rozmiarze 10') +plot(cond_niesym(:,5),iteracje_niesym_przes(:,10),'go'); +title('Zaleznosc uwarunkowania od ilosci iteracji mac niesymetryczna 10') + +plot(cond_sym(:,20),iteracje_sym_bezprzes(:,20),'bo', cond_sym(:,20), iteracje_sym_przes(:,20), 'r*'); +title('Zaleznosc uwarunkowania od ilosci iteracji mac symetryczna o rozmiarze 20') +plot(cond_niesym(:,20),iteracje_niesym_przes(:,20),'go'); +title('Zaleznosc uwarunkowania od ilosci iteracji mac niesymetryczna 20') +% eig(A) +% +% plot(blad_res_a(:,2),blad_res_a(:,1)); +% title('Zaleznosc wartosci bledu od ilosci rownan w ukladzie (typ A)') +% xlabel('ilosc rownan') +% ylabel('norma residuum *10^-12') +% +% plot(blad_res_b(:,2),blad_res_b(:,1)); +% title('Zaleznosc wartosci bledu od ilosci rownan w ukladzie (typ B)') +% xlabel('ilosc rownan') +% ylabel('norma residuum *10^-12') +% +% plot(blad_res_c(:,2),blad_res_c(:,1)); +% title('Zaleznosc wartosci bledu od ilosci rownan w ukladzie (typ C)') +% xlabel('ilosc rownan') +% ylabel('norma residuum') +%% +% wyswietlenie bledow + +% blad_res_a +%% +% *funkcje pomocnicze* +% +% rozklad QR + +function [Q R] = qr_rozklad(A) + [r_wiersze r_kolumny] = size(A); + Q = zeros(r_wiersze); + if r_wiersze > r_kolumny + R = eye(r_wiersze); + Q = eye(r_wiersze); + else + R = eye(r_kolumny); + Q = eye(r_wiersze); + end + %Gram-Schmidt + for i = 1:r_kolumny + Q(:,i) = A(:,i); + for j = 1:(i-1) + R(j,i) = mydot(Q(:,j),A(:,i))/mydot(Q(:,j),Q(:,j)); + Q(:,i) = Q(:,i) - R(j,i)*Q(:,j); + end + end + Q = Q(1:r_wiersze,1:r_kolumny); + %normalizacja + N = zeros(r_wiersze); + for i = 1:r_kolumny + N(i,i) = norm(Q(:,i)); + Q(:,i) = Q(:,i)/N(i,i); + end + R = N*R; + + if r_wiersze > r_kolumny + R = R(1:r_kolumny,1:r_kolumny); + else + R = R(1:r_wiersze,1:r_wiersze); + end +end + +%% +% algorytm obliczania wartosci wlasnych metoda QR bez przesuniec + +function [wart_wlasne i] = qr_bezprzesuniec(A) + i = 0; + while tolerancja(A) > 0.00001 & i < 200+1 + [Q R] = qr_rozklad(A); + A = R * Q; + i = i+1; + end + wart_wlasne = wektor(A); +end +%% +% algorytm obliczania wartosci wlasnych metoda QR z przesunieciami + +function [wart_wlasne i] = qr_przesuniecia(A) + rozmiar = size(A,1); + i = 0; + wart_wlasne = zeros(rozmiar); + wart_wlasne = wart_wlasne(:,1); + for j = rozmiar:-1:2 + while max(abs(A(j,1:j-1))) > 0.00001 & i < 200+1 + mala_macierz = A(j-1:j,j-1:j); % macierz 2x2, + [x1 x2] = pierw_f_kwadratowej(mala_macierz); + przesuniecie = blizsza_liczba(mala_macierz(2,2), x1, x2); % z ktorej wyznaczana jest najlepsza wart. wlasna + A = A - eye(j)*przesuniecie; + [Q R] = qr_rozklad(A); + A = R * Q + eye(j)*przesuniecie; + i = i+1; + end + wart_wlasne(j) = A(j,j); + if j > 2 + A = A(1:j-1,1:j-1); %deflacja + else + wart_wlasne(1) = A(1,1); + end + end +end +%% +% wyznaczanie pierw f. kwadratowej + +function [x1 x2] = pierw_f_kwadratowej(mala_macierz) + a = 1; + b = -(mala_macierz(1,1)+mala_macierz(2,2)); + c = (mala_macierz(1,1)*mala_macierz(2,2))-(mala_macierz(2,1)*mala_macierz(1,2)); + + x1 = (-b + sqrt(b*b - 4*a*c))/(2*a); + x2 = (-b - sqrt(b*b - 4*a*c))/(2*a); + if abs(x2) > abs(x1) + x1 = x2; + end + %drugi pierwiastek ze wzorw Viete'a + x2 = ((-b)/a) - x1; +end +%% +% wybor pierwiastka blizszego d(n,n) + +function x = blizsza_liczba(wlasciwa, x1, x2) + if abs(wlasciwa-x1) < abs(wlasciwa-x2) + x = x1; + else + x = x2; + end +end +%% +% autorska implementacja matlabowej funkcji dot() + +function md = mydot(A,B) + rozmiar = size(A); + md = 0; + for i = 1:rozmiar + md = md + A(i)*B(i); + end +end +%% +% funkcja wektoryzujaca macierz diagonalna + +function w = wektor(A) + rozmiar = size(A); + for i = 1:rozmiar + w(i,1) = A(i,i); + end +end +%% +% sprawdzenie tolerancji + +function tol = tolerancja(A) + rozmiar = size(A); + A = abs(A); + tol = 0; + if rozmiar > 2 + for i = 1:rozmiar + if max(A(i,i+1:end)) > tol + tol = max(A(i,i+1:end)); + end + if max(A(i,1:i-1)) > tol + tol = max(A(i,1:i-1)); + end + end + else + tol = 0; + end +end +%% +% tworzenie macierzy symetrycznej o zadanym rozmiarze + +function mac_sym = macierz_symetryczna(rozmiar) + mac_sym = randi([0 50],rozmiar,rozmiar); + mac_sym = mac_sym + mac_sym'; +end +%% +% tworzenie macierzy niesymetrycznej o zadanym rozmiarze + +function mac_nsym = macierz_niesymetryczna(rozmiar) + mac_nsym = randi([0 100],rozmiar,rozmiar); +end +%% +% norma residuum + +function nr = norma_residuum(wspolczynniki, x, rozw) + residuum = wspolczynniki*x - rozw; + nr = norm(residuum); +end \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_przemielone_statystyki.mlx b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_przemielone_statystyki.mlx new file mode 100644 index 00000000..7b2ded4a Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_przemielone_statystyki.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_test.m b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_test.m new file mode 100644 index 00000000..52c8bcb1 --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_test.m @@ -0,0 +1,170 @@ +%% +% program testujcy + +clc; +clear; +rozmiar = 20; +A = macierz_symetryczna(rozmiar); +[B iteracje_sym_bezprzes] = qr_bezprzesuniec(A); +max(sort(B) - eig(A)) +[B iteracje_sym_przes] = qr_przesuniecia(A); +max(sort(B) - eig(A)) +A = macierz_niesymetryczna(rozmiar); +[B iteracje_niesym_przes] = qr_przesuniecia(A); +B +eig(A) +%% +% *funkcje pomocnicze* +% +% rozklad QR + +function [Q R] = qr_rozklad(A) + [r_wiersze r_kolumny] = size(A); + Q = zeros(r_wiersze); + if r_wiersze > r_kolumny + R = eye(r_wiersze); + Q = eye(r_wiersze); + else + R = eye(r_kolumny); + Q = eye(r_wiersze); + end + %Gram-Schmidt + for i = 1:r_kolumny + Q(:,i) = A(:,i); + for j = 1:(i-1) + R(j,i) = mydot(Q(:,j),A(:,i))/mydot(Q(:,j),Q(:,j)); + Q(:,i) = Q(:,i) - R(j,i)*Q(:,j); + end + end + Q = Q(1:r_wiersze,1:r_kolumny); + %normalizacja + N = zeros(r_wiersze); + for i = 1:r_kolumny + N(i,i) = norm(Q(:,i)); + Q(:,i) = Q(:,i)/N(i,i); + end + R = N*R; + + if r_wiersze > r_kolumny + R = R(1:r_kolumny,1:r_kolumny); + else + R = R(1:r_wiersze,1:r_wiersze); + end +end + +%% +% algorytm obliczania wartosci wlasnych metoda QR bez przesuniec + +function [wart_wlasne i] = qr_bezprzesuniec(A) + i = 0; + while tolerancja(A) > 0.00001 & i < 200+1 + [Q R] = qr_rozklad(A); + A = R * Q; + i = i+1; + end + wart_wlasne = wektor(A); +end +%% +% algorytm obliczania wartosci wlasnych metoda QR z przesunieciami + +function [wart_wlasne i] = qr_przesuniecia(A) + rozmiar = size(A,1); + i = 0; + wart_wlasne = zeros(rozmiar); + wart_wlasne = wart_wlasne(:,1); + for j = rozmiar:-1:2 + while max(abs(A(j,1:j-1))) > 0.00001 & i < 200+1 + mala_macierz = A(j-1:j,j-1:j); % macierz 2x2, + [x1 x2] = pierw_f_kwadratowej(mala_macierz); + przesuniecie = blizsza_liczba(mala_macierz(2,2), x1, x2); % z ktorej wyznaczana jest najlepsza wart. wlasna + A = A - eye(j)*przesuniecie; + [Q R] = qr_rozklad(A); + A = R * Q + eye(j)*przesuniecie; + i = i+1; + end + wart_wlasne(j) = A(j,j); + if j > 2 + A = A(1:j-1,1:j-1); %deflacja + else + wart_wlasne(1) = A(1,1); + end + end +end +%% +% wyznaczanie pierw f. kwadratowej + +function [x1 x2] = pierw_f_kwadratowej(mala_macierz) + a = 1; + b = -(mala_macierz(1,1)+mala_macierz(2,2)); + c = (mala_macierz(1,1)*mala_macierz(2,2))-(mala_macierz(2,1)*mala_macierz(1,2)); + + x1 = (-b + sqrt(b*b - 4*a*c))/(2*a); + x2 = (-b - sqrt(b*b - 4*a*c))/(2*a); + if abs(x2) > abs(x1) + x1 = x2; + end + %drugi pierwiastek ze wzorw Viete'a + x2 = ((-b)/a) - x1; +end +%% +% wybor pierwiastka blizszego d(n,n) + +function x = blizsza_liczba(wlasciwa, x1, x2) + if abs(wlasciwa-x1) < abs(wlasciwa-x2) + x = x1; + else + x = x2; + end +end +%% +% autorska implementacja matlabowej funkcji dot() + +function md = mydot(A,B) + rozmiar = size(A); + md = 0; + for i = 1:rozmiar + md = md + A(i)*B(i); + end +end +%% +% funkcja wektoryzujaca macierz diagonalna + +function w = wektor(A) + rozmiar = size(A); + for i = 1:rozmiar + w(i,1) = A(i,i); + end +end +%% +% sprawdzenie tolerancji + +function tol = tolerancja(A) + rozmiar = size(A); + A = abs(A); + tol = 0; + if rozmiar > 2 + for i = 1:rozmiar + if max(A(i,i+1:end)) > tol + tol = max(A(i,i+1:end)); + end + if max(A(i,1:i-1)) > tol + tol = max(A(i,1:i-1)); + end + end + else + tol = 0; + end +end +%% +% tworzenie macierzy symetrycznej o zadanym rozmiarze + +function mac_sym = macierz_symetryczna(rozmiar) + mac_sym = randi([0 50],rozmiar,rozmiar); + mac_sym = mac_sym + mac_sym'; +end +%% +% tworzenie macierzy niesymetrycznej o zadanym rozmiarze + +function mac_nsym = macierz_niesymetryczna(rozmiar) + mac_nsym = randi([0 100],rozmiar,rozmiar); +end \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_test.mlx b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_test.mlx new file mode 100644 index 00000000..c70e3591 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0201_QR_test.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0202_Aproksymacja.m b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0202_Aproksymacja.m new file mode 100644 index 00000000..bdc1b179 --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0202_Aproksymacja.m @@ -0,0 +1,195 @@ +%% +% program + +clc; +clear; +dane = [-5 -5.4606;-4 -3.8804;-3 -1.9699;-2 -1.6666;-1 -0.0764;0 -0.3971;1 -1.0303;2 -4.5483;3 -11.528;4 -21.6417;5 -34.4458]; +x = linspace(-5,5,100); +max_stopien = 8; + +norma_res = zeros(max_stopien); +norma_res = norma_res(:,1:2); + +for stopien = 0:max_stopien + figure + funkcja = uklad_rownan_normalnych(dane, stopien); + y = fun(funkcja, x); + funkcja2 = uklad_qr(dane, stopien); + y2 = fun(funkcja2, x); + plot(dane(:,1),dane(:,2),'bo', x, y, 'r', x, y2, 'g--'); + legend({'dane','met. rownan normalnych','met. rozkladu QR'},'Location','southwest'); + title(['stopien wielomianu ' num2str(stopien)]); + norma_res(stopien+1,1) = norm(dane(:,2) - fun(funkcja, dane(:,1))); + norma_res(stopien+1,2) = norm(dane(:,2) - fun(funkcja2, dane(:,1))); +end + +norma_res +%% +% *funkcje pomocnicze* +% +% uklad rownan normalnych + +function wspolczynniki = uklad_rownan_normalnych(dane, st_wielomianu) + % wyznaczanie macierzy Grama - + [r_wiersze, r_kolumny] = size(dane); + st_wielomianu = st_wielomianu + 1; + macierz_Grama = wyzn_macierz_Grama(dane, st_wielomianu); + + % wektor prawej strony + prawa_strona = zeros(st_wielomianu); + prawa_strona = prawa_strona(:,1); + for i = 1:st_wielomianu + for k = 1:r_wiersze + prawa_strona(i) = prawa_strona(i) + (dane(k,1))^(i-1)*dane(k,2); + end + end + + wspolczynniki = macierz_Grama\prawa_strona; +end +%% +% uklad wynikajacy z rozkladu QR + +function wspolczynniki = uklad_qr(dane, st_wielomianu) + % wyznaczanie macierzy Grama - + [r_wiersze, r_kolumny] = size(dane); + st_wielomianu = st_wielomianu + 1; + macierz_Grama = wyzn_macierz_Grama(dane, st_wielomianu); + + % wektor prawej strony + prawa_strona = zeros(st_wielomianu); + prawa_strona = prawa_strona(:,1); + for i = 1:st_wielomianu + for k = 1:r_wiersze + prawa_strona(i) = prawa_strona(i) + (dane(k,1))^(i-1)*dane(k,2); + end + end + + [Q R] = qr_rozklad(macierz_Grama); + wspolczynniki = R\Q'*prawa_strona; +end + +%% +% wyznaczenie macierzy Grama + +function macierz_Grama = wyzn_macierz_Grama(dane, st_wielomianu) + % wyznaczanie macierzy Grama - + macierz_Grama = zeros(st_wielomianu); + [r_wiersze, r_kolumny] = size(dane); + for i = 1:st_wielomianu + for j = 1:st_wielomianu + for k = 1:r_wiersze + macierz_Grama(i,j) = macierz_Grama(i,j) + (dane(k,1))^(i+j-2); + end + end + end +end +%% +% +% +% wyznaczenie wyjsc dla podanych x-ow i zadanej funkcji + +function y = fun(funkcja, x) + [temp rozmiar_x] = size(x); + if rozmiar_x == 1 + x = x'; + rozmiar_x = temp; + end + st_wielomianu = size(funkcja); + y = zeros(rozmiar_x); + y = y(:,1); + for i = 1:rozmiar_x + for j = 1:st_wielomianu + y(i,1) = y(i,1) + funkcja(j,1)*(x(1,i))^(j-1); + end + end +end +%% +% rozklad QR + +function [Q R] = qr_rozklad(A) + [r_wiersze r_kolumny] = size(A); + Q = zeros(r_wiersze); + if r_wiersze > r_kolumny + R = eye(r_wiersze); + Q = eye(r_wiersze); + else + R = eye(r_kolumny); + Q = eye(r_wiersze); + end + %Gram-Schmidt + for i = 1:r_kolumny + Q(:,i) = A(:,i); + for j = 1:(i-1) + R(j,i) = mydot(Q(:,j),A(:,i))/mydot(Q(:,j),Q(:,j)); + Q(:,i) = Q(:,i) - R(j,i)*Q(:,j); + end + end + Q = Q(1:r_wiersze,1:r_kolumny); + %normalizacja + N = zeros(r_wiersze); + for i = 1:r_kolumny + N(i,i) = norm(Q(:,i)); + Q(:,i) = Q(:,i)/N(i,i); + end + R = N*R; + + if r_wiersze > r_kolumny + R = R(1:r_kolumny,1:r_kolumny); + else + R = R(1:r_wiersze,1:r_wiersze); + end +end +%% +% autorska implementacja matlabowej funkcji dot() + +function md = mydot(A,B) + rozmiar = size(A); + md = 0; + for i = 1:rozmiar + md = md + A(i)*B(i); + end +end +%% +% funkcja wektoryzujaca macierz diagonalna + +function w = wektor(A) + rozmiar = size(A); + for i = 1:rozmiar + w(i,1) = A(i,i); + end +end +%% +% +% +% +% +% +% +% -5 -5.5 +% +% -4 -3.88 +% +% -3 -1.97 +% +% -2 -1.666 +% +% -1 -0.0764 +% +% 0 -0.397 +% +% 1 -1 +% +% 2 -4.55 +% +% 3 -11.5 +% +% 4 -21.65 +% +% 5 -34.45 +% +% +% +% trzeci stopien^ +% +% rysowanie funkcji -> ok \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0202_Aproksymacja.mlx b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0202_Aproksymacja.mlx new file mode 100644 index 00000000..26a3e0c3 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt02/Matlab/mnum_0202_Aproksymacja.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt02/Projekt02.lswitaj.2.43.pdf b/ENUME/references/MatLabMNUM/Projekt02/Projekt02.lswitaj.2.43.pdf new file mode 100644 index 00000000..3c12dfd1 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt02/Projekt02.lswitaj.2.43.pdf differ diff --git a/ENUME/references/MatLabMNUM/Projekt02/Sprawozdanie_02.docx b/ENUME/references/MatLabMNUM/Projekt02/Sprawozdanie_02.docx new file mode 100644 index 00000000..050fa62f Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt02/Sprawozdanie_02.docx differ diff --git a/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0301.m b/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0301.m new file mode 100644 index 00000000..98c6057a --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0301.m @@ -0,0 +1,221 @@ +%% +% start + +clc; +clear; +x = linspace(0,15,100); +%% +% przedzialy poczatkowe + +przedzialy = [6 8; 8.3 10; 12 15]; + +dokladnosc_zer = 0.001; +wielkosc_przedzialu = 0.01; +ilosc_iteracji = 100; + +for i=1:3 + %wybor i-tego przedzialu + if sprawdzenie_przedzialu(przedzialy(i,:)) == 0 + error('Error, zostaly wybrane zle przedzialy'); + end +end +%% +% wykres + +figure +y = wartosc_funkcji(x); +plot(x,y,'b-',[0 15], [0 0], 'k--', przedzialy(1,:), wartosc_funkcji(przedzialy(1,:)), 'r*', przedzialy(2,:), wartosc_funkcji(przedzialy(2,:)), 'c*', przedzialy(3,:), wartosc_funkcji(przedzialy(3,:)), 'k*'); +legend({'f(x)', 'y=0'},'Location','southwest'); +title('wykres funkcji f(x)=2,3*sin(x)+4*ln(x+2)-11'); +%% +% oszacowanie miejsc zerowych na podstawie rysunku (skrypt prof Tatjeskiego +% mowi, zeby estymowac na poodstawie rysunku) + +% wartosc_funkcji(7.25) +% wartosc_funkcji(8) +% wartosc_funkcji(9) +% wartosc_funkcji(12.5) +%% +% porownanie + +x_styczne = met_stycznych([0 8], dokladnosc_zer, ilosc_iteracji) +% x_bisekcja = bisekcja(przedzialy, dokladnosc_zer, wielkosc_przedzialu) +% x_sieczne = met_siecznych(przedzialy, dokladnosc_zer, wielkosc_przedzialu) +% x_styczne = met_stycznych(przedzialy, dokladnosc_zer, ilosc_iteracji) +% y_bisekcja = wartosc_funkcji(x_bisekcja) +% y_sieczne = wartosc_funkcji(x_sieczne) +% y_styczne = wartosc_funkcji(x_styczne) +% +% figure +% plot(x,y,'b-',[0 15], [0 0], 'k--', x_bisekcja, wartosc_funkcji(x_bisekcja), 'go'); +% legend({'f(x)', 'y=0', 'm. zerowe met. bisekcji'},'Location','southwest'); +% title('wykres funkcji f(x)=2,3*sin(x)+4*ln(x+2)-11'); +% +% plot(x,y,'b-',[0 15], [0 0], 'k--', x_sieczne, wartosc_funkcji(x_sieczne), 'go'); +% legend({'f(x)', 'y=0', 'm. zerowe met. siecznych'},'Location','southwest'); +% title('wykres funkcji f(x)=2,3*sin(x)+4*ln(x+2)-11'); +% +% plot(x,y,'b-',[0 15], [0 0], 'k--', x_styczne, wartosc_funkcji(x_styczne), 'go'); +% legend({'f(x)', 'y=0', 'm. zerowe met. stycznych'},'Location','southwest'); +% title('wykres funkcji f(x)=2,3*sin(x)+4*ln(x+2)-11'); +%% +% *funkcje pomocnicze glowne* +% +% *1. metoda bisekcji* + +function x = bisekcja(przedzialy, dokladnosc_zer, wielkosc_przedzialu) + ilosc_pierwiastkow = size(przedzialy,1); + x = zeros(ilosc_pierwiastkow); + x = wektor(x); + for i = 1:ilosc_pierwiastkow + fprintf('metoda bisekcji przedzial nr %d\n', i); + iteracje = 0; + c = 0; + while (abs(wartosc_funkcji(c))>dokladnosc_zer | (przedzialy(i,2)-przedzialy(i,1))>wielkosc_przedzialu) + iteracje = iteracje + 1; + [c przedzialy(i,:)] = polowienie_przedzialu(przedzialy(i,:)); + fprintf('x=%f y=%f\n', c, wartosc_funkcji(c)); + end + x(i) = c; + end +end +%% +% polowienie przedzialow dla metody bisekcji + +function [c nowy_przedzial] = polowienie_przedzialu(przedzial) + c = (przedzial(1)+przedzial(2))/2; + if(sprawdzenie_przedzialu([przedzial(1) c]) == 1) + nowy_przedzial = [przedzial(1) c]; + else + nowy_przedzial = [c przedzial(2)]; + end +end +%% +% *2. metoda siecznych* + +function x = met_siecznych(przedzialy, dokladnosc_zer, wielkosc_przedzialu) + ilosc_pierwiastkow = size(przedzialy,1); + x = zeros(ilosc_pierwiastkow); + x = wektor(x); + for i = 1:ilosc_pierwiastkow + fprintf('metoda siecznych przedzial nr %d\n', i); + c = 0; + while (abs(wartosc_funkcji(c))>dokladnosc_zer | (przedzialy(i,2)-przedzialy(i,1))>wielkosc_przedzialu) + [c przedzialy(i,:)] = nowy_sieczny_przedzial(przedzialy(i,:), c); + fprintf('x=%f y=%f\n', c, wartosc_funkcji(c)); + end + x(i) = c; + end +end +%% +% zmniejszenie przedzialow dla metody siecznych + +function [d nowy_przedzial] = nowy_sieczny_przedzial(przedzial, c) + d = wyznacz_zero_f_liniowej(przedzial); + if(przedzial(2) == c) + nowy_przedzial = [d przedzial(2)]; + else + nowy_przedzial = [przedzial(1) d]; + end +end +%% +% wyznaczenie zera f. liniowej wyznaczonej na podstawie punktow z koncow +% przedzialu na podstawie wyliczonego analitycznie wzoru + +function c = wyznacz_zero_f_liniowej(przedzial) + x1 = przedzial(1); + x2 = przedzial(2); + y1 = wartosc_funkcji(x1); + y2 = wartosc_funkcji(x2); + c = (x2*y1-x1*y2)/(y1-y2); +end +%% +% *3. metoda stycznych* + +function x = met_stycznych(przedzialy, dokladnosc_zer, ilosc_iteracji) + ilosc_pierwiastkow = size(przedzialy,1); + x = zeros(ilosc_pierwiastkow); + x = wektor(x); + for i = 1:ilosc_pierwiastkow + fprintf('metoda stycznych przedzial nr %d\n', i); + iteracje = 0; + c = 0; + pierwotny_przedzial = przedzialy(i,:); + while (abs(wartosc_funkcji(c))>dokladnosc_zer & iteracje < ilosc_iteracji) + iteracje = iteracje + 1; + [c przedzialy(i,:)] = nowy_przedzial_styczny(przedzialy(i,:), pierwotny_przedzial); + fprintf('x=%f y=%f\n', c, wartosc_funkcji(c)); + end + x(i) = c; + end +end +%% +% zmniejszenie przedzialow dla metody stycznych + +function [d nowy_przedzial] = nowy_przedzial_styczny(przedzial, pierwotny_przedzial) + d = nowy_punkt_styczny(przedzial(1)); + if(d >= pierwotny_przedzial(1) & d <= pierwotny_przedzial(2)) + nowy_przedzial = [d przedzial(2)]; + else + disp(przedzial); + disp(d); + error('Error. Punkt poza przedzialem. Nalezy wybrac inny przedzial poczatkowy'); + end +end +%% +% wyznaczenie miejsca zerowego na podstawie pochodnej oraz poprzedniego +% punktu + +function x0 = nowy_punkt_styczny(x) + m = wartosc_pochodnej(x); + y = wartosc_funkcji(x); + x0 = (m*x-y)/m; +end +%% +% wyznaczenie pochodnej dla podanych x-ow + +function y = wartosc_pochodnej(x) + y = 23*cos(x)/10+4/(x+2); +end +%% +% *funkcje pomocnicze dodatkowe* +% +% wyznaczenie wyjsc dla podanych x-ow i zadanej funkcji + +function y = wartosc_funkcji(x) + [temp rozmiar_x] = size(x); + if rozmiar_x == 1 + x = x'; + rozmiar_x = temp; + end + y = zeros(rozmiar_x); + y = y(:,1); + for i = 1:rozmiar_x + y(i,1) = 2.3*sin(x(1,i))+4*log(x(1,i)+2)-11; + end +end +%% +% sprawdzenie czy w podanym przedziale jest miejsce zerowe + +function result = sprawdzenie_przedzialu(przedzial) + if wartosc_funkcji(przedzial(1))*wartosc_funkcji(przedzial(2)) < 0 + result = 1; + else + result = 0; + end +end +%% +% wartosc najwiekszego bledu + +function y = najwieksze_zero(x) + y = max(abs(wartosc_funkcji(x))); +end +%% +% funkcja wektoryzujaca macierz diagonalna + +function w = wektor(A) + rozmiar = size(A); + for i = 1:rozmiar + w(i,1) = A(i,i); + end +end \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0301.mlx b/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0301.mlx new file mode 100644 index 00000000..7612162f Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0301.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0302_MM1.m b/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0302_MM1.m new file mode 100644 index 00000000..7d8a578f --- /dev/null +++ b/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0302_MM1.m @@ -0,0 +1,108 @@ +%% +% program + +clc; +clear; +x = linspace(-1.5,3.5,100); + +dokladnosc_zer = 0.001; +% +% m_zerowe = MM1(-2, -1, 0, dokladnosc_zer) +% m_zerowe' +% abs(wartosc_funkcji(m_zerowe)) +% m_zerowe = MM1(2, 2.5, 3, dokladnosc_zer) +m_zerowe = MM1(-1.5, -1, -.075, dokladnosc_zer) + +figure +y = wartosc_funkcji(x); +plot(x,y,'b-',[-1.5 3.5], [0 0], 'k--')%, m_zerowe, wartosc_funkcji(m_zerowe), 'r*'); +legend({'f(x)', 'y=0'},'Location','southwest'); +title('wykres funkcji f(x)=-x^4+2.5x^3+2.5*x^2+x+0.5'); +%% +% *funkcje metody Mullera* +% +% metoda MM1 + +function x = MM1(x1, x2, x3, dokladnosc_zer) + while (abs(wartosc_funkcji(x3))>dokladnosc_zer) + [x1 x2 x3] = kolejny_punkt(x1,x2,x3); + x3 + wartosc_funkcji(x3) + end + x = x3; +end +%% +% wyznaczenie kolejnego punktu na podstawie paraboli + +function [x1 x2 x3] = kolejny_punkt(x1, x2, x3) + q = (x3-x2)/(x2-x1); + a = q*wartosc_funkcji(x3) - q*(q+1)*wartosc_funkcji(x2) + q^2*wartosc_funkcji(x1); + b = (2*q+1)*wartosc_funkcji(x3) - (q+1)^2*wartosc_funkcji(x2) + q^2*wartosc_funkcji(x1); + c = (q+1)*wartosc_funkcji(x3); + + x1 = x2; + x2 = x3; + + if (b+sqrt(b^2-4*a*c)) > (b-sqrt(b^2-4*a*c)) + x3 = x2 - (x2-x1)*(2*c/(b+sqrt(b^2-4*a*c))); + else + x3 = x2 - (x2-x1)*(2*c/(b-sqrt(b^2-4*a*c))); + end +end +%% +% *funkcje pomocnicze dodatkowe* +% +% wyznaczenie wyjsc dla podanych x-ow i zadanej funkcji + +function y = wartosc_funkcji(x) + wielomian = [0.5 1 2.5 2.5 -1]; + rozmiar_w = size(wielomian,2); + [temp rozmiar_x] = size(x); + if rozmiar_x == 1 + x = x'; + rozmiar_x = temp; + end + y = zeros(rozmiar_x); + y = y(:,1); + for i = 1:rozmiar_x + for j = 1:rozmiar_w + y(i,1) = y(i,1) + wielomian(j)*(x(1,i))^(j-1); + end + end +end +%% +% sprawdzenie czy w podanym przedziale jest miejsce zerowe + +function result = sprawdzenie_przedzialu(przedzial) + if wartosc_funkcji(przedzial(1))*wartosc_funkcji(przedzial(2)) < 0 + result = 1; + else + result = 0; + end +end +%% +% wartosc najwiekszego bledu + +function y = najwieksze_zero(x) + y = max(abs(wartosc_funkcji(x))); +end +%% +% funkcja wektoryzujaca macierz diagonalna + +function w = wektor(A) + rozmiar = size(A); + for i = 1:rozmiar + w(i,1) = A(i,i); + end +end +%% +% +% +% * +% +% +% +% # wzor na kolejnego x: +% +% \ No newline at end of file diff --git a/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0302_MM1.mlx b/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0302_MM1.mlx new file mode 100644 index 00000000..09ebbdc9 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt03/Matlab/mnum_0302_MM1.mlx differ diff --git a/ENUME/references/MatLabMNUM/Projekt03/Projekt03.lswitaj.3.43.pdf b/ENUME/references/MatLabMNUM/Projekt03/Projekt03.lswitaj.3.43.pdf new file mode 100644 index 00000000..2b6dbc32 Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt03/Projekt03.lswitaj.3.43.pdf differ diff --git a/ENUME/references/MatLabMNUM/Projekt03/Sprawozdanie_03.docx b/ENUME/references/MatLabMNUM/Projekt03/Sprawozdanie_03.docx new file mode 100644 index 00000000..ca61f31f Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt03/Sprawozdanie_03.docx differ diff --git a/ENUME/references/MatLabMNUM/Projekt03/Sprawozdanie_03.pdf b/ENUME/references/MatLabMNUM/Projekt03/Sprawozdanie_03.pdf new file mode 100644 index 00000000..b923943f Binary files /dev/null and b/ENUME/references/MatLabMNUM/Projekt03/Sprawozdanie_03.pdf differ diff --git a/ENUME/references/NumericalMethods/README.md b/ENUME/references/NumericalMethods/README.md new file mode 100644 index 00000000..5f8732ad --- /dev/null +++ b/ENUME/references/NumericalMethods/README.md @@ -0,0 +1,2 @@ +# Numerical Methods +Project made during winter 2018 semester for ENUME classes at WUT. Contains researches about some basic numerical algorithms. For more information see final reports. diff --git a/ENUME/references/NumericalMethods/Raport_2/Enume_Task_2.jpg b/ENUME/references/NumericalMethods/Raport_2/Enume_Task_2.jpg new file mode 100644 index 00000000..9998bbc8 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_2/Enume_Task_2.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_2/Report_numerki_2.pdf b/ENUME/references/NumericalMethods/Raport_2/Report_numerki_2.pdf new file mode 100644 index 00000000..ad7d3b12 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_2/Report_numerki_2.pdf differ diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1A.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1A.m new file mode 100644 index 00000000..905fc031 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1A.m @@ -0,0 +1,12 @@ +%----- Initialise Workspace -----% +clear; +clc; + +%----- The Bisection Method -----% + +%----- Initial interval, suspected of contain fnTask_1 roots -----% +lower_bound = 2; +upper_bound = 11; + +%----- Display Roots of function fnTask_1 -----% +the_bisection(lower_bound, upper_bound); diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1A_v2.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1A_v2.m new file mode 100644 index 00000000..24307a5a --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1A_v2.m @@ -0,0 +1,31 @@ +clear; +clc; + +lower_bound = 2; +upper_bound = 11; + +%--- Root bracketing ---% + +root_num = 0; +iter_num = 0; +while (lower_bound < upper_bound) + + iter_num = iter_num + 1; + + if (fnTask_1(lower_bound) * fnTask_1(lower_bound + 1) > 0) + + lower_bound = lower_bound + 1; + else + %--- Interval contains root of function ---% + root_num = root_num + 1; + + %--- Call bisection method to determine exact value of x ---% + %--- for which f(x) = 0 ---% + [solution(root_num), bisection_iter(root_num), accuracy(root_num)] = the_bisection_v2(lower_bound, lower_bound+1, 0); + iter_num = iter_num + bisection_iter(root_num); + %--- Carry on looking for intervals, ---% + %--- which contain root of function ---% + lower_bound = lower_bound + 1; + end + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1B.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1B.m new file mode 100644 index 00000000..f138cb4d --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1B.m @@ -0,0 +1,12 @@ +%----- Initialise Workspace -----% +clear; +clc; + +%----- The Newton's Method -----% + +%----- Initial interval, suspected of contain fnTask_1 roots -----% +lower_bound = 2; +upper_bound = 11; + +%----- Display Roots of function fnTask_1 -----% +the_newton_s(lower_bound, upper_bound); \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1B_v2.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1B_v2.m new file mode 100644 index 00000000..ea0c6da5 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/Task_1B_v2.m @@ -0,0 +1,31 @@ +clear; +clc; + +lower_bound = 2; +upper_bound = 11; + +%--- Root bracketing ---% + +root_num = 0; +iter_num = 0; +while (lower_bound < upper_bound) + + iter_num = iter_num + 1; + + if (fnTask_1(lower_bound) * fnTask_1(lower_bound + 1) > 0) + + lower_bound = lower_bound + 1; + else + %--- Interval contains root of function ---% + root_num = root_num + 1; + + %--- Call bisection method to determine exact value of x ---% + %--- for which f(x) = 0 ---% + [solution(root_num), newton_iter(root_num)] = the_newton_v2(lower_bound, lower_bound+1, lower_bound,0); + iter_num = iter_num + newton_iter(root_num); + %--- Carry on looking for intervals, ---% + %--- which contain root of function ---% + lower_bound = lower_bound + 1; + end + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/dfnTask_1.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/dfnTask_1.m new file mode 100644 index 00000000..2dcfd9b8 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/dfnTask_1.m @@ -0,0 +1,6 @@ +function dy = dfnTask_1 (x) + + dy = ( -1 / (x + 1)) - 0.7 * x * sin(x) + 0.7 * cos(x); + +end + diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/dfnTask_2.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/dfnTask_2.m new file mode 100644 index 00000000..27495f4c --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/dfnTask_2.m @@ -0,0 +1,6 @@ +function y = dfnTask_2 (x) + + y = 4 * x^3 - 21 * x^2 - 8 * x + 2; + +end + diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/fnTask_1.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/fnTask_1.m new file mode 100644 index 00000000..fa586ee2 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/fnTask_1.m @@ -0,0 +1,6 @@ +function y = fnTask_1(x) + + y = 0.7 * x * cos(x) - log(x + 1); + +end + diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/fnTask_2.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/fnTask_2.m new file mode 100644 index 00000000..3e3456a5 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/fnTask_2.m @@ -0,0 +1,7 @@ +function y = fnTask_2(x) + + y = x^4 - 7 * x^3 - 4 * x^2 + 2 * x + 9; + +end + + diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/generateGraphfnTask_1.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/generateGraphfnTask_1.m new file mode 100644 index 00000000..8de39442 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/generateGraphfnTask_1.m @@ -0,0 +1,18 @@ +function generateGraphfnTask_1(density) + + x = linspace(2, 11, density); + + y = zeros(1, density); + y1 = zeros(1, density); + + for i = 1 : (density) + y(i) = fnTask_1(x(i)); + end + + figure + plot(x, y, x, y1); + title ('fnTask1 Graph'); + xlabel ('2 < x < 11'); + ylabel ('y = fnTaks1(x)'); + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/the_bisection.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/the_bisection.m new file mode 100644 index 00000000..bb4c80b3 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/the_bisection.m @@ -0,0 +1,37 @@ +function the_bisection(lower_bound, upper_bound) + + %----- Divide Current Interval Into Two Equal Subintervals -----% + + middle_point = (upper_bound + lower_bound)/2; + + %----- Calculate value of function for given argument -----% + fn_value_upper_bound = fnTask_1(upper_bound); + fn_value_middle_point = fnTask_1(middle_point); + fn_value_lower_bound = fnTask_1(lower_bound); + + %----- Check whether obtained value is close enough -----% + %----- to assumed tolerance -----% + %----- Try code in case result is converge -----% + %----- to inf or nan value -----% + + answer = abs(fn_value_middle_point) > 1e-10; + + if (answer && ~isinf(fn_value_middle_point) && ~isnan(fn_value_middle_point)) + %----- Call the_bisection method -----% + %----- for newly found intervals -----% + if (fn_value_lower_bound * fn_value_middle_point < 0 || upper_bound - lower_bound > 0.001) + + the_bisection(lower_bound, middle_point); + end + + if (fn_value_upper_bound * fn_value_middle_point < 0 || upper_bound - lower_bound > 0.001) + + the_bisection(middle_point, upper_bound); + end + + else + %----- Display found solution -----% + disp(middle_point); + end + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/the_bisection_v2.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/the_bisection_v2.m new file mode 100644 index 00000000..aad6290c --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/the_bisection_v2.m @@ -0,0 +1,24 @@ +function [root, iter_num, accuracy] = the_bisection_v2(lower_bound, upper_bound, iter_num) + + middle_point = (lower_bound + upper_bound) / 2; + fn_middle_point = fnTask_1(middle_point); + + if (abs(fn_middle_point) <= 1e-10 && upper_bound - lower_bound < 0.1) + %--- Test for solution accuracy ---% + %--- and interval length ---% + accuracy = 1/2 * (upper_bound - lower_bound); + iter_num = iter_num + 1; + root = middle_point; + elseif (fn_middle_point * fnTask_1(upper_bound) < 0) + %--- root is located between middle point and upper bound ---% + iter_num = iter_num + 1; + [root, iter_num, accuracy] = the_bisection_v2(middle_point, upper_bound, iter_num); + elseif (fnTask_1(lower_bound) * fn_middle_point < 0) + %--- root is located between lower bound and middle point ---% + iter_num = iter_num + 1; + [root, iter_num, accuracy] = the_bisection_v2(lower_bound, middle_point, iter_num); + else + + error('Interval does not consist of function root.'); + end +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/the_newton_s.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/the_newton_s.m new file mode 100644 index 00000000..549c29dd --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/the_newton_s.m @@ -0,0 +1,40 @@ +function the_newton_s (lower_bound, upper_bound) + + if (fnTask_1(lower_bound) * fnTask_1(upper_bound) < 0) + %--- At least one root within interval ---% + + x = lower_bound; + x_next = x - (fnTask_1(x) / dfnTask_1(x)); + + + if (x_next < lower_bound || x_next > upper_bound) + %--- Method is not convergent over given interval ---% + %--- Narrow range usisng bisection ---% + the_newton_s (lower_bound, (lower_bound + upper_bound) / 2); + the_newton_s ((lower_bound + upper_bound) / 2, upper_bound); + else + %--- Method is convergent over given interval ---% + while (abs(x-x_next) > 1e-10) + x = x_next; + x_next = x - (fnTask_1(x) / dfnTask_1(x)); + end + + disp(double(x_next)); + + end + + else + %--- Function has no root over given interval ---% + %--- or range is to wide ---% + + if (upper_bound - lower_bound > 0.1) + %--- Narrow interval untill it is smaller than one assumed ---% + the_newton_s (lower_bound, (lower_bound + upper_bound) / 2); + the_newton_s ((lower_bound + upper_bound) / 2, upper_bound); + end + + %--- none root found ---% + end + +end + diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_1/the_newton_v2.m b/ENUME/references/NumericalMethods/Raport_2/Task_1/the_newton_v2.m new file mode 100644 index 00000000..95ed714d --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_1/the_newton_v2.m @@ -0,0 +1,15 @@ +function [root, iter_num] = the_newton_v2(lower_bound, upper_bound, x, iter_num) + + iter_num = iter_num + 1; + + x_next = x - (fnTask_2(x) / dfnTask_2(x)); + + if (x_next < lower_bound || x_next > upper_bound) + error ('Method is divergent over given interval'); + elseif (abs(x-x_next) <= 1e-10) + root = x_next; + else + [root, iter_num] = the_newton_v2(lower_bound, upper_bound, x_next, iter_num); + end + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/Laguerre.m b/ENUME/references/NumericalMethods/Raport_2/Task_2/Laguerre.m new file mode 100644 index 00000000..a769cd57 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_2/Laguerre.m @@ -0,0 +1,24 @@ +function [root, iteration] = Laguerre(initial_guess, iteration) + + iteration = iteration + 1; + + %--- Quadratic Function Coefficients ---% + a(1) = fnTask_2(initial_guess); %--- c + a(2) = dfnTask_2(initial_guess); %--- b, dfn - first order derivative + a(3) = ( ddfnTask_2(initial_guess) ) / 2; %--- a, ddfn - second order derivative + + denominator_1 = ( a(2) + sqrt( 3 * ( 3 * a(2)^2 - 2 * a(1) * a(3) ) ) ); + denominator_2 = ( a(2) - sqrt( 3 * ( 3 * a(2)^2 - 2 * a(1) * a(3) ) ) ); + + if abs( denominator_1 ) > abs( denominator_2 ) + initial_guess = initial_guess - ( 4 * a(1) ) / ( a(2) + sqrt( 3 * ( 3 * a(2)^2 - 2 * a(1) * a(3) ) ) ); + else + initial_guess = initial_guess - ( 4 * a(1) ) / ( a(2) - sqrt( 3 * ( 3 * a(2)^2 - 2 * a(1) * a(3) ) ) ); + end + + if (fnTask_2(initial_guess) >= 1e-10) + [root, iteration] = Laguerre(initial_guess, iteration); + else + root = initial_guess; + end +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/Muller_1.m b/ENUME/references/NumericalMethods/Raport_2/Task_2/Muller_1.m new file mode 100644 index 00000000..8adc215d --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_2/Muller_1.m @@ -0,0 +1,116 @@ +clear; +clc; + +%--- Initial guesses ---% +x = [-1, -0.7, -0.5]; + +%--- Find value of function at given points ---% +fn_x = zeros(1, 3); + +for i = 1 : 3 + fn_x(i) = fnTask_2(x(i)); +end + +%--- New incremental variable z ---% +z = zeros(1, 3); + +iteration = 0; + +while abs(fn_x(2)) >= 1e-10 && ~isinf(fn_x(2)) && ~isnan(fn_x(2)) + + for i = 1 : 3 + fn_x(i) = fnTask_2(x(i)); + end + + + iteration = iteration + 1; + + for i = 1 : 2 + z(i) = x(i) - x(3); + end + + %--- y(z) = az^2 + bz + c ---% + %--- a * z(1)^2 + b * z(1) = fn_x(1) - fn_x(3) ---% + %--- a * z(2)^2 + b * z(2) = fn_x(2) - fn_x(3) ---% + + %--- Interpolation of parabola defined in the variable z ---% + A = zeros(2, 2); + b = zeros(2, 1); + + A(1, 1) = z(1)^2; + A(1, 2) = z(1); + A(2, 1) = z(2)^2; + A(2, 2) = z(2); + + b(1) = fn_x(1) - fn_x(3); + b(2) = fn_x(2) - fn_x(3); + + answer = A\b; + + a = zeros(1, 3); + + %--- Quadratic Function Coefficient ---% + a(1) = fn_x(3); %--- c + a(2) = answer(2); %--- b + a(3) = answer(1); %--- a + + %--- Draw the parabola interpolation ---% + %--- and value of polynomial for initial guesses ---% + %--- assigned to incremental variable z ---% + % x_1 = linspace(-4, 4, 100); + % y_1 = zeros(1, 100); + % + % for i = 1 : 100 + % y_1(i) = a(1) + a(2) * x_1(i) + a(3) * x_1(i)^2; + % end + % + % y_2 = zeros(1, 100); + % + % plot(z, fn_x, 'o', x_1, y_1, x_1, y_2); + + %--- Find roots of parabola interpolation ---% + root_1 = ( -2 * a(1) ) / ( a(2) + sqrt(a(2)^2 - 4 * a(1) * a(3)) ); + root_2 = ( -2 * a(1) ) / ( a(2) - sqrt(a(2)^2 - 4 * a(1) * a(3)) ); + + %--- Choose variable for next iteration ---% + if ( abs( a(2) + sqrt( a(2)^2 - 4 * a(1) * a(3) ) ) >= abs( a(2) - sqrt( a(2)^2 - 4 * a(1) * a(3) ) ) ) + z_min = root_1; + else + z_min = root_2; + end + + new_point = x(3) + z_min; + + + if x(2) <= new_point + + x(1) = x(2); + fn_x(1) = fn_x(2); + + if x(3) > new_point + x(2) = new_point; + fn_x(2) = fnTask_2(x(2)); + else + x(2) = x(3); + fn_x(2) = fn_x(3); + x(3) = new_point; + fn_x(3) = fnTask_2(x(3)); + end + else + + x(3) = x(2); + fn_x(3) = fn_x(2); + if x(1) < new_point + x(2) = new_point; + fn_x(2) = fnTask_2(x(2)); + else + x(2) = x(1); + fn_x(2) = fn_x(1); + x(1) = new_point; + fn_x(1) = fnTask_2(x(1)); + end + end + +end + + diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/Muller_1_v2.m b/ENUME/references/NumericalMethods/Raport_2/Task_2/Muller_1_v2.m new file mode 100644 index 00000000..1bfd888f --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_2/Muller_1_v2.m @@ -0,0 +1,56 @@ +function [root, iteration] = Muller_1_v2 (x_0, x_1, x_2, iteration) + + iteration = iteration + 1; + + %--- Incremental variable z ---% + z_0 = x_0 - x_2; + z_1 = x_1 - x_2; + + + A = zeros(2, 2); + b = zeros(2, 1); + + %--- Create&solve system of linear equations, Ax = b ---% + %--- Where x consist of a and b parabola coefficients ---% + A(1, 1) = z_0; + A(1, 2) = z_0^2; + A(2, 1) = z_1; + A(2, 2) = z_1^2; + + b(1) = fnTask_2(x_0) - fnTask_2(x_2); + b(2) = fnTask_2(x_1) - fnTask_2(x_2); + + %--- Quadratic Function Coefficients ---% + a(1) = fnTask_2(x_2); %--- c + a(2:3) = A\b; %--- b - second element, c - third element in vector a + + %--- Roots of parabola interpolation ---% + z_root_1 = ( -2 * a(1) ) / ( a(2) + sqrt(a(2)^2 - 4 * a(1) * a(3)) ); + z_root_2 = ( -2 * a(1) ) / ( a(2) - sqrt(a(2)^2 - 4 * a(1) * a(3)) ); + + if abs( z_root_1 ) <= abs( z_root_2 ) + z_min = z_root_1; + else + z_min = z_root_2; + end + + new_point = x_2 + z_min; + + if abs( fnTask_2(new_point) ) < 1e-10 + + root = new_point; + elseif new_point >= x_0 && new_point < x_1 + + [root, iteration] = Muller_1_v2 (x_0, new_point, x_1, iteration); + elseif new_point >= x_1 && new_point < x_2 + + [root, iteration] = Muller_1_v2 (x_1, new_point, x_2, iteration); + elseif new_point < x_1 + + [root, iteration] = Muller_1_v2 (new_point, x_0, x_1, iteration); + else + + [root, iteration] = Muller_1_v2 (x_1, x_2, new_point, iteration); + end + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/Muller_2.m b/ENUME/references/NumericalMethods/Raport_2/Task_2/Muller_2.m new file mode 100644 index 00000000..12a874dd --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_2/Muller_2.m @@ -0,0 +1,26 @@ +function [root, iteration] = Muller_2(initial_guess, iteration) + + iteration = iteration + 1; + + %--- Quadratic Function Coefficients ---% + a(1) = fnTask_2(initial_guess); %--- c + a(2) = dfnTask_2(initial_guess); %--- b, dfn - first order derivative + a(3) = ( ddfnTask_2(initial_guess) ) / 2; %--- a, ddfn - second order derivative + + %--- Roots of parabola interpolation ---% + z_root_1 = ( -2 * a(1) ) / ( a(2) + sqrt( a(2)^2 - 2 * a(1) * a(3) ) ); + z_root_2 = ( -2 * a(1) ) / ( a(2) + sqrt( a(2)^2 + 2 * a(1) * a(3) ) ); + + if abs(z_root_1) < abs(z_root_2) + z_min = z_root_1; + else + z_min = z_root_2; + end + + if (fnTask_2(initial_guess + z_min) >= 1e-10 ) + [root, iteration] = Muller_2(initial_guess + z_min, iteration); + else + root = initial_guess + z_min; + end + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/ddfnTask_2.m b/ENUME/references/NumericalMethods/Raport_2/Task_2/ddfnTask_2.m new file mode 100644 index 00000000..64db85cc --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_2/ddfnTask_2.m @@ -0,0 +1,5 @@ +function y = ddfnTask_2(x) + + y = 12 * x^2 - 42 * x - 8; + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/dfnTask_2.m b/ENUME/references/NumericalMethods/Raport_2/Task_2/dfnTask_2.m new file mode 100644 index 00000000..27495f4c --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_2/dfnTask_2.m @@ -0,0 +1,6 @@ +function y = dfnTask_2 (x) + + y = 4 * x^3 - 21 * x^2 - 8 * x + 2; + +end + diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/fnTask_2.m b/ENUME/references/NumericalMethods/Raport_2/Task_2/fnTask_2.m new file mode 100644 index 00000000..1d93944c --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_2/fnTask_2.m @@ -0,0 +1,6 @@ +function y = fnTask_2 (x) + + y = x^4 - 7 * x^3 - 4 * x^2 + 2 * x + 9; + +end + diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/generateGraphfnTask_2.m b/ENUME/references/NumericalMethods/Raport_2/Task_2/generateGraphfnTask_2.m new file mode 100644 index 00000000..e5a0721a --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_2/generateGraphfnTask_2.m @@ -0,0 +1,27 @@ +function generateGraphfnTask_2(density) + + x = linspace(-40, 40, density); + + y = zeros(1, density); + + y0 = zeros(1, density); + + y1 = zeros(1, density); + + for i = 1 : (density) + y(i) = fnTask_2(x(i)); + end + + a = v_mm1; + + for i = 1 : (density) + y1(i) = a(1) + a(2) * x(i) + a(3) * x(i)^2; + end + + figure + plot(x, y, x, y0);%, x, y1); + title ('fnTask2 Graph'); + xlabel ('-40 < x < 40'); + ylabel ('y = fnTaks2(x)'); + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/muller.jpg b/ENUME/references/NumericalMethods/Raport_2/Task_2/muller.jpg new file mode 100644 index 00000000..cf1965ec Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_2/Task_2/muller.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/untitled.jpg b/ENUME/references/NumericalMethods/Raport_2/Task_2/untitled.jpg new file mode 100644 index 00000000..04d5cdbf Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_2/Task_2/untitled.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_2/Task_2/v_mm1.m b/ENUME/references/NumericalMethods/Raport_2/Task_2/v_mm1.m new file mode 100644 index 00000000..a6b8a25a --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_2/Task_2/v_mm1.m @@ -0,0 +1,40 @@ +function a = v_mm1() + x = [7 , 7.25, 7.5]; + + g = zeros(3, 3); + q = zeros(3, 1); + + + %--- Second order polynomial approximation ---% + %--- Find Gram's Matrix ---% + for i = 1 : 3 + + for j = 1 : 3 + + for n = 1 : 3 + g(i, j) = g(i, j) + x(n)^(i + j - 2); + end + + end + + end + + %--- Find funny greek letter ---% + for i = 1 : 3 + + for n = 1 : 3 + q(i, 1) = q(i,1) + fnTask_2(x(n)) * x(n)^(i-1); + end + + end + + a = g\q; + + delta = a(2)^2 - 4 * a(3) * a(1); + sqrt_delta = sqrt(delta); + + x_0 = (-a(2) + sqrt_delta) / 2 * a(3); + x_1 = (-a(2) - sqrt_delta) / 2 * a(3); + +end + diff --git a/ENUME/references/NumericalMethods/Raport_3/NumerkiC .pdf b/ENUME/references/NumericalMethods/Raport_3/NumerkiC .pdf new file mode 100644 index 00000000..f7162ddf Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/NumerkiC .pdf differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN1.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN1.jpg new file mode 100644 index 00000000..feff11b4 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN1.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN2.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN2.jpg new file mode 100644 index 00000000..04601967 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN2.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN3.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN3.jpg new file mode 100644 index 00000000..b9efa6b9 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN3.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN6.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN6.jpg new file mode 100644 index 00000000..5c8b0143 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN6.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN9.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN9.jpg new file mode 100644 index 00000000..1bbdee58 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppN9.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN1.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN1.jpg new file mode 100644 index 00000000..feff11b4 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN1.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN2.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN2.jpg new file mode 100644 index 00000000..04601967 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN2.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN3.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN3.jpg new file mode 100644 index 00000000..b9efa6b9 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN3.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN6.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN6.jpg new file mode 100644 index 00000000..5c8b0143 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN6.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN9.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN9.jpg new file mode 100644 index 00000000..1bbdee58 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 1/Graphs/LsAppQRN9.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/Task_1.m b/ENUME/references/NumericalMethods/Raport_3/Task 1/Task_1.m new file mode 100644 index 00000000..252555f0 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_3/Task 1/Task_1.m @@ -0,0 +1,23 @@ +clear; +clc; + +% measurements +x = -5:1:5; +y = [23.4523 11.9631 4.4428 1.1010 -1.6826 -1.2630 -0.0357 -1.3156 -3.4584 -8.4294 -18.4654]; + +n = 9; % polynomial order + +[a, residuum] = ls_approximation(n, x, y); + +% draw graph +x_draw = -5:0.1:5; +scatter(x, y, 'filled') +hold on +appValue = polyval(a, x_draw); +plot(x_draw, appValue); +grid on +title("Approximation for polynomial of order: " + n); +xlabel('x'); +ylabel('y'); +legend("Samples", "Approximation"); +hold off \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/ls_approximation.m b/ENUME/references/NumericalMethods/Raport_3/Task 1/ls_approximation.m new file mode 100644 index 00000000..759abe2f --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_3/Task 1/ls_approximation.m @@ -0,0 +1,24 @@ +function [a, residuum] = ls_approximation(n, x, y) + % n - polynomial order + % x - x samples coordinate vector + % y - f(x) values vector + + % F(x) = a_0*x^0 + a_1*x^1 + a_2*x^2 + ... + a_n*x^n + + [~, m] = size(x); % m - number of samples + + % Gram's Matrix(set of normal equations) + A = zeros(m, n+1); + + for i = 1:m + for j = 1:(n+1) + A(i,j) = x(1, i)^(j-1); + end + end + + % AT*A*a = AT*y + a = (A' * A) \ (A' * y'); + residuum = norm((A' * y') - ((A' * A) * a)); + a = flipud(a); + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/ls_approximationQR.m b/ENUME/references/NumericalMethods/Raport_3/Task 1/ls_approximationQR.m new file mode 100644 index 00000000..6facbfdf --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_3/Task 1/ls_approximationQR.m @@ -0,0 +1,26 @@ +function [a, residuum] = ls_approximationQR(n, x, y) + % n - polynomial order + % x - x samples coordinate vector + % y - f(x) values vector + + % F(x) = a_0*x^0 + a_1*x^1 + a_2*x^2 + ... + a_n*x^n + + [~, m] = size(x); % m - number of samples + + % Gram's Matrix(set of normal equations) + A = zeros(m, n+1); + + for i = 1:m + for j = 1:(n+1) + A(i,j) = x(1, i)^(j-1); + end + end + + % R*a = QT*y + [Q, R] = mgs(A); + a = R \ (Q' * y'); + residuum = norm((R * a) - (Q' * y')); + a = flipud(a); + + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 1/mgs.m b/ENUME/references/NumericalMethods/Raport_3/Task 1/mgs.m new file mode 100644 index 00000000..73f4017c --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_3/Task 1/mgs.m @@ -0,0 +1,16 @@ +function [Q,R] = mgs(X) + % Modified Gram-Schmidt. [Q,R] = mgs(X); + % G. W. Stewart, "Matrix Algorithms, Volume 1", SIAM, 1998. + [n,p] = size(X); + Q = zeros(n,p); + R = zeros(p,p); + for k = 1:p + Q(:,k) = X(:,k); + for i = 1:k-1 + R(i,k) = Q(:,i)'*Q(:,k); + Q(:,k) = Q(:,k) - R(i,k)*Q(:,i); + end + R(k,k) = norm(Q(:,k))'; + Q(:,k) = Q(:,k)/R(k,k); + end +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4Variable00001.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4Variable00001.jpg new file mode 100644 index 00000000..372054e4 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4Variable00001.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4Variable00001Time.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4Variable00001Time.jpg new file mode 100644 index 00000000..10897e06 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4Variable00001Time.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4VariableVsOde.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4VariableVsOde.jpg new file mode 100644 index 00000000..396905c8 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4VariableVsOde.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4VariablesErrosrs.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4VariablesErrosrs.jpg new file mode 100644 index 00000000..8c9605bc Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4VariablesErrosrs.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00001.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00001.jpg new file mode 100644 index 00000000..26fe3e54 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00001.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00001Time.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00001Time.jpg new file mode 100644 index 00000000..48b78842 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00001Time.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00001vsOde45.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00001vsOde45.jpg new file mode 100644 index 00000000..431099f7 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00001vsOde45.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_000625.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_000625.jpg new file mode 100644 index 00000000..c5e26568 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_000625.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_000625Time.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_000625Time.jpg new file mode 100644 index 00000000..2508a4b3 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_000625Time.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00125.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00125.jpg new file mode 100644 index 00000000..a84bfac2 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00125.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00125Time.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00125Time.jpg new file mode 100644 index 00000000..28c90172 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_00125Time.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_0025.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_0025.jpg new file mode 100644 index 00000000..bc8265b9 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_0025.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_0025Time.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_0025Time.jpg new file mode 100644 index 00000000..020a062c Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/RK4_0025Time.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00001.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00001.jpg new file mode 100644 index 00000000..c9940754 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00001.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00001Time.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00001Time.jpg new file mode 100644 index 00000000..d434119d Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00001Time.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00001vsOde45.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00001vsOde45.jpg new file mode 100644 index 00000000..da0e4f95 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00001vsOde45.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams000125Time.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams000125Time.jpg new file mode 100644 index 00000000..8b96f4ac Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams000125Time.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams000625.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams000625.jpg new file mode 100644 index 00000000..d117625c Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams000625.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams000625Time.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams000625Time.jpg new file mode 100644 index 00000000..e0059e11 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams000625Time.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00125.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00125.jpg new file mode 100644 index 00000000..9e04f59d Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams00125.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams025.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams025.jpg new file mode 100644 index 00000000..3adebaf0 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams025.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams025Time.jpg b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams025Time.jpg new file mode 100644 index 00000000..5ef8a782 Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/Graphs/adams025Time.jpg differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/RK4.m b/ENUME/references/NumericalMethods/Raport_3/Task 2/RK4.m new file mode 100644 index 00000000..4c03cb9e --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_3/Task 2/RK4.m @@ -0,0 +1,56 @@ +clear; +clc; + +dx_1 = @(x_1, x_2) x_2 + x_1 * (0.5 - x_1^2 - x_2^2); +dx_2 = @(x_1, x_2) -x_1 + x_2 * (0.5 - x_1^2 - x_2^2); + +%initial conditions +init_x_1 = 8; +init_x_2 = 7; + +h = 0.025; % step + +x_1 = zeros(1, 20/h+1); +x_2 = zeros(1, 20/h+1); +err_x_1 = zeros(1, 20/h+1); +err_x_2 = zeros(1, 20/h+1); +x_1(1) = init_x_1; +x_2(1) = init_x_2; + + +for i = 1:1:ceil(20 / h) + + [k_1, k_2] = computeKs(dx_1, dx_2, x_1(i), x_2(i), h); + + x_1(i+1) = x_1(i) + h * (k_1(1) + 2 * k_1(2) + 2 * k_1(3) + k_1(4)) / 6; + x_2(i+1) = x_2(i) + h * (k_2(1) + 2 * k_2(2) + 2 * k_2(3) + k_2(4)) / 6; + + err_x_1(i) = (16/15)*abs(x_1(i+1) - x_1(i)); + err_x_2(i) = (16/15)*abs(x_2(i+1) - x_2(i)); + +end + +% plot(x_1, x_2, 'b'); grid on; title("Runge-Kutta method with constant step size = " + h + "vs ode45"); xlabel('x_1'); ylabel('x_2'); +% hold on +% [t, y] = ode45(@odefun, [0,20], [8, 7]); +% plot(y(:,1), y(:,2), 'r'); +% %title("Ode45"); xlabel('x_1'); ylabel('x_2'); +% legend('Blue - Rugge-Kutta', 'Red - ode45'); +% hold off + +[N, M] = size(x_1); +plot(0:(M-1), x_1, 'g') +title("RK4 solution versus time for step size: " + h); +xlabel('t'); ylabel('Solution'); +grid on; +hold on; +[n, m] = size(x_2); +plot(0:(M-1), x_2, 'r') +legend('Green x_1', 'Red - x_2'); + + + + + + + diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/RK4Variable.m b/ENUME/references/NumericalMethods/Raport_3/Task 2/RK4Variable.m new file mode 100644 index 00000000..10c0fec6 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_3/Task 2/RK4Variable.m @@ -0,0 +1,107 @@ +clear; +clc; + +dx_1 = @(x_1, x_2) x_2 + x_1 * (0.5 - x_1^2 - x_2^2); +dx_2 = @(x_1, x_2) -x_1 + x_2 * (0.5 - x_1^2 - x_2^2); + +%Relative tolerance user definied +epsr = 1e-6; +%Absolute tolerance user definied +epsa = 1e-6; + +%initial conditions +x_1 = 8; +x_2 = 7; + +i = 1; + +x_1_val(1) = x_1; +x_2_val(1) = x_2; + +h = 0.0001; %Initial step +steps(i) = h; + +a = 0; %initial point [0, 20] +while (a < 20) + [k_1, k_2] = computeKs(dx_1, dx_2, x_1, x_2, h); + + temp_x_1 = x_1; + temp_x_2 = x_2; + + x_1 = x_1 + h * (k_1(1) + 2 * k_1(2) + 2 * k_1(3) + k_1(4)) / 6; + x_2 = x_2 + h * (k_2(1) + 2 * k_2(2) + 2 * k_2(3) + k_2(4)) / 6; + + x_1_val(i + 1) = x_1; + x_2_val(i + 1) = x_2; + + %1st half-step + [k_1, k_2] = computeKs(dx_1, dx_2, x_1, x_2, 0.5 * h); + + temp_1 = x_1 + 0.5 * h * (k_1(1) + 2 * k_1(2) + 2 * k_1(3) + k_1(4)) / 6; + temp_2 = x_2 + 0.5 * h * (k_2(1) + 2 * k_2(2) + 2 * k_2(3) + k_2(4)) / 6; + + %2nd half-step + [k_1, k_2] = computeKs(dx_1, dx_2, temp_1, temp_2, 0.5 * h); + + temp_1 = temp_1 + 0.5 * h * (k_1(1) + 2 * k_1(2) + 2 * k_1(3) + k_1(4)) / 6; + temp_2 = temp_2 + 0.5 * h * (k_2(1) + 2 * k_2(2) + 2 * k_2(3) + k_2(4)) / 6; + + errors(i, 1) = (temp_1 - x_1) / 120; + errors(i, 2) = (temp_2 - x_2) / 120; + + eps_1 = abs(temp_1) * epsr + epsa; + eps_2 = abs(temp_2) * epsr + epsa; + + alpha_1 = (eps_1 / abs(errors(i, 1)))^(1/5); + alpha_2 = (eps_2 / abs(errors(i, 2)))^(1/5); + + alpha = min(alpha_1, alpha_2); + + h_new = 0.9 * alpha * h; %s for RK4 estimated 0.9 estimated. + + if (0.9 * alpha >= 1) + if (a + h >= 20) + break; + else + a = a + h; + h = min([h_new, 5 * h, 20 - a]); + i = i + 1; + steps(i) = h; + continue; + end + else + if (h_new < 0) + error('Solution not possible with assumed accuacy.'); + else + h = h_new; + i = i + 1; + steps(i) = h; + end + end +end + +% plot(x_1_val, x_2_val, 'b'); grid on; +% hold on +% [t, y] = ode45(@odefun, [0,20], [8, 7]); +% plot(y(:,1), y(:,2), 'r'); +% title("RK4 Variable for initial step 0.0001"); xlabel('x_1'); ylabel('x_2'); +% legend('Blue - RK4 Variable', 'Red - ode45'); +% hold off + +% [n, m] = size(x_1_val); +% plot(0:(m-1), x_1_val, 'g') +% title(['RK4 method with variable step size solution versus time']); +% xlabel('t'); ylabel('x_1 - green, x_2 - red'); +% grid on; +% hold on; +% [n m] = size(x_2_val); +% plot(0:(m-1), x_2_val, 'r') + +[n, m] = size(errors); +plot(0:(n-1), errors(:, 1), 'k') +title('RK4 method with variable step size error versus time'); +xlabel('t'); ylabel('x1 - black, x2 - red'); +grid on; +hold on; +plot(0:(n-1), errors(:, 2), 'r') + diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/_DS_Store b/ENUME/references/NumericalMethods/Raport_3/Task 2/_DS_Store new file mode 100644 index 00000000..cef5fa2a Binary files /dev/null and b/ENUME/references/NumericalMethods/Raport_3/Task 2/_DS_Store differ diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/adams.m b/ENUME/references/NumericalMethods/Raport_3/Task 2/adams.m new file mode 100644 index 00000000..69a9ad81 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_3/Task 2/adams.m @@ -0,0 +1,77 @@ +clear; +clc; + +dx_1 = @(x_1, x_2) x_2 + x_1 * (0.5 - x_1^2 - x_2^2); +dx_2 = @(x_1, x_2) -x_1 + x_2 * (0.5 - x_1^2 - x_2^2); + +%initial conditions +init_x_1 = 8; +init_x_2 = 7; + +h = 0.25; % step + +err_fac = (863/60480) / ((-95/288) + (863 / 60480)); + +x_1(1) = init_x_1; +x_2(1) = init_x_2; + +betaE = [1901, -2774, 2616, -1274, 251]; +betaE = betaE / 720; + +betaI = [475, 1427, -798, 482, -173, 27]; +betaI = betaI / 1440; + +for i = 1:5 + [k_1, k_2] = computeKs(dx_1, dx_2, x_1(i), x_2(i), h); + x_1(i + 1) = x_1(i) + h * (k_1(1) + 2 * k_1(2) + 2 * k_1(3) + k_1(4)) / 6; + x_2(i + 1) = x_2(i) + h * (k_2(1) + 2 * k_2(2) + 2 * k_2(3) + k_2(4)) / 6; +end + +for i = 6:ceil(20 / h) + sum_x_1 = 0; + sum_x_2 = 0; + for j = 1:5 + sum_x_1 = sum_x_1 + betaE(j) * dx_1(x_1(i - j), x_2(i - j)); + sum_x_2 = sum_x_2 + betaE(j) * dx_2(x_1(i - j), x_2(i - j)); + end + + temp_x_1 = x_1(i - 1) + h * sum_x_1; + temp_x_2 = x_2(i - 1) + h * sum_x_2; + + sum_x_1 = 0; + sum_x_2 = 0; + for j = 1:5 + sum_x_1 = sum_x_1 + betaI(j + 1) * dx_1(x_1(i - j), x_2(i - j)); + sum_x_2 = sum_x_2 + betaI(j + 1) * dx_2(x_1(i - j), x_2(i - j)); + end + + x_1(i) = x_1(i - 1) + h * sum_x_1 + h * betaI(1) * dx_1(temp_x_1, temp_x_2); + x_2(i) = x_2(i - 1) + h * sum_x_2 + h * betaI(1) * dx_2(temp_x_1, temp_x_2); + + err_x_1 = err_fac * (temp_x_1 - x_1(i)); + err_x_2 = err_fac * (temp_x_2 - x_2(i)); +end + +% plot(x_1, x_2, 'b') +% title("Adams PC (P5EC5E) method with constant step size = " + h + "vs ode45"); +% xlabel('x1'); ylabel('x2'); +% grid on; +% hold on +% [t, y] = ode45(@odefun, [0,20], [8, 7]); +% plot(y(:,1), y(:,2), 'r'); +% xlabel('x_1'); ylabel('x_2'); +% legend('Blue - Adams PC (P5EC5E)', 'Red - ode45'); +% hold off + +[N, M] = size(x_1); +plot(0:(M-1), x_1, 'g') +title("Adams PC (P5EC5E) solution versus time for step size: " + h); +xlabel('t'); ylabel('Solution'); +grid on; +hold on; +[n, m] = size(x_2); +plot(0:(M-1), x_2, 'r') +legend('Green x_1', 'Red - x_2'); + + + diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/computeKs.m b/ENUME/references/NumericalMethods/Raport_3/Task 2/computeKs.m new file mode 100644 index 00000000..d672f5fa --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_3/Task 2/computeKs.m @@ -0,0 +1,19 @@ +function [k_1, k_2] = computeKs(fun_1, fun_2, x, y, h) + + %1st Ks + k_1(1) = fun_1(x, y); + k_2(1) = fun_2(x, y); + + %2nd Ks + k_1(2) = fun_1(x + 0.5 * h * k_1(1), y + 0.5 * h * k_2(1)); + k_2(2) = fun_2(x + 0.5 * h * k_1(1), y + 0.5 * h * k_2(1)); + + %3rd Ks + k_1(3) = fun_1(x + 0.5 * h * k_1(2), y + 0.5 * h * k_2(2)); + k_2(3) = fun_2(x + 0.5 * h * k_1(2), y + 0.5 * h * k_2(2)); + + %4th Ks + k_1(4) = fun_1(x + h * k_1(3), y + h * k_2(3)); + k_2(4) = fun_2(x + h * k_1(3), y + h * k_2(3)); + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Raport_3/Task 2/odefun.m b/ENUME/references/NumericalMethods/Raport_3/Task 2/odefun.m new file mode 100644 index 00000000..3417b1b7 --- /dev/null +++ b/ENUME/references/NumericalMethods/Raport_3/Task 2/odefun.m @@ -0,0 +1,4 @@ +function [dydt] = odefun(t, y) + dydt = [y(2) + y(1) * (0.5 - y(1) * y(1) - y(2) * y(2)); + -y(1) + y(2) * (0.5 - y(1) * y(1) - y(2) * y(2))]; +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Report_1/Enume_Report_1 .pdf b/ENUME/references/NumericalMethods/Report_1/Enume_Report_1 .pdf new file mode 100644 index 00000000..acce905a Binary files /dev/null and b/ENUME/references/NumericalMethods/Report_1/Enume_Report_1 .pdf differ diff --git a/ENUME/references/NumericalMethods/Report_1/Task1/macheps.m b/ENUME/references/NumericalMethods/Report_1/Task1/macheps.m new file mode 100644 index 00000000..a075b8f9 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task1/macheps.m @@ -0,0 +1,16 @@ +clear variable +clear all +clc + +% ----- Matlab build-in function ----- % +machEps_1 = eps; + +% ----- General solution ----- % +machEps_2 = 2^(-52); + +% ----- Solution when matissa is unknown ----- % +machEps_3 = 1; + +while 1.0 + (machEps_3 / 2) > 1.0 + machEps_3 = machEps_3 / 2; +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Report_1/Task2/Indicated_Method.m b/ENUME/references/NumericalMethods/Report_1/Task2/Indicated_Method.m new file mode 100644 index 00000000..59b5657e --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task2/Indicated_Method.m @@ -0,0 +1,63 @@ +% ------- Solving a system of n linear equations Ax = b. ------- % +% -------------------- The Indicated Method -------------------- % + +function x = Indicated_Method(A, b) + + [M,N] = size(A); + + if M ~= N + error ('A is not square matrix!'); + end + + + + for j = 1 : N - 1 + + %--- Find the greatest value within column ---% + m = max(A(j:N,j)); + + %--- Find row whitin greatest value occure ---% + for k = j : N + if A(k,j) == m + %--- SwapRow in matrix A ---% + tempRow = A(j , :); + A(j , :) = A(k, :); + A(k, :) = tempRow; + + %--- SwapValue in vector b ---% + tempVal = b(j); + b(j) = b(k); + b(k) = tempVal; + + break; + end + end + + + for i = j + 1 : N + + l = A(i,j) / A(j,j); + b(i,1) = b(i,1) - l * b(j, 1); + + for t = 1 : N + A(i,t) = A(i,t) - l * A(j, t); + end + + end + end + + x = zeros(N,1); + + + % -------------------- The back-substitution phase -------------------- % + + for k = N : -1 : 1 + + E = 0; + for iter = k+1 : N + E = E + A(k,iter) * x(iter,1); + end + + x(k, 1) = (b(k,1) - E) / A(k,k); + end +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Report_1/Task2/Task2.m b/ENUME/references/NumericalMethods/Report_1/Task2/Task2.m new file mode 100644 index 00000000..9e0b6d82 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task2/Task2.m @@ -0,0 +1,59 @@ +clear variable; +clear all; +clc; + +% -------------------- a) case -------------------- % + A = createMatrixB(100); + b = createVectorB(100); + + x = Indicated_Method(A,b); + + % --- Second Holder Vector Norm for solution error --- % +% r = A*x - b; +% euclideanNormOfR = norm(r); +% new_euclideanNormOfR = 0; + + % --- Residual correction --- % + % --- Iterative Method --- % + +% r = A*x - b; +% euclideanNormOfR = norm(r); +% new_euclideanNormOfR = euclideanNormOfR; +% +% while new_euclideanNormOfR <= euclideanNormOfR +% +% euclideanNormOfR = new_euclideanNormOfR; +% r = A*x - b; +% x = x - r; +% new_euclideanNormOfR = norm(r); +% end + + n = 10; + + while n <= 320 + disp(n) + A = createMatrixB(n); + b = createVectorB(n); + + x = Indicated_Method(A,b); + r = A*x - b; + euclideanNormOfR = norm(r); + + hold on; + plot(n, euclideanNormOfR, '.'); + hold off; + + n = n + 10; + + end + + xlabel('Iteration number'); + ylabel('Solution error'); + title('Task2b'); + +% % -------------------- Example -------------------- % +% %A = [3 1 6 ; 2 1 3 ; 1 1 1]; +% %b = [2 ; 7 ; 4]; +% +% x_1 = A\b; +% x_2 = Indicated_Method(A,b); \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Report_1/Task2/Task2aGraph.jpg b/ENUME/references/NumericalMethods/Report_1/Task2/Task2aGraph.jpg new file mode 100644 index 00000000..41c9c1b9 Binary files /dev/null and b/ENUME/references/NumericalMethods/Report_1/Task2/Task2aGraph.jpg differ diff --git a/ENUME/references/NumericalMethods/Report_1/Task2/Task2bGraph.jpg b/ENUME/references/NumericalMethods/Report_1/Task2/Task2bGraph.jpg new file mode 100644 index 00000000..6ec2f32c Binary files /dev/null and b/ENUME/references/NumericalMethods/Report_1/Task2/Task2bGraph.jpg differ diff --git a/ENUME/references/NumericalMethods/Report_1/Task2/createMatrixA.m b/ENUME/references/NumericalMethods/Report_1/Task2/createMatrixA.m new file mode 100644 index 00000000..caa8e0ae --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task2/createMatrixA.m @@ -0,0 +1,17 @@ +function a = createMatrixA(n) + + a = zeros(n,n); + + for i = 1 : n + for j = 1 : n + if i == j + a(i,j) = 9; + elseif (i == j - 1) || (i == j + 1) + a(i,j) = 3; + else + a(i,j) = 0; + end + end + end + +end diff --git a/ENUME/references/NumericalMethods/Report_1/Task2/createMatrixB.m b/ENUME/references/NumericalMethods/Report_1/Task2/createMatrixB.m new file mode 100644 index 00000000..8b280860 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task2/createMatrixB.m @@ -0,0 +1,12 @@ +function a = createMatrixB(n) + + a = zeros(n,n); + + for i = 1 : n + for j = 1 : n + a(i,j) = 8 / (9 * (i + j + 1)); + end + end + +end + diff --git a/ENUME/references/NumericalMethods/Report_1/Task2/createVectorA.m b/ENUME/references/NumericalMethods/Report_1/Task2/createVectorA.m new file mode 100644 index 00000000..73a1f25c --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task2/createVectorA.m @@ -0,0 +1,10 @@ +function b = createVectorA(n) + + b = zeros(n,1); + + for i = 1 : n + b(i, 1) = 3.4 + 0.6 * i; + end + +end + diff --git a/ENUME/references/NumericalMethods/Report_1/Task2/createVectorB.m b/ENUME/references/NumericalMethods/Report_1/Task2/createVectorB.m new file mode 100644 index 00000000..40a7c6a8 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task2/createVectorB.m @@ -0,0 +1,15 @@ +function b = createVectorB(n) + + b = zeros(n,1); + + for i = 1 : n + if (mod(i,2) == 0 ) + b(i, 1) = 4/(3*i); + else + b(i, 1) = 0; + end + end + +end + + diff --git a/ENUME/references/NumericalMethods/Report_1/Task3/GaussSeidelA.jpg b/ENUME/references/NumericalMethods/Report_1/Task3/GaussSeidelA.jpg new file mode 100644 index 00000000..6058225a Binary files /dev/null and b/ENUME/references/NumericalMethods/Report_1/Task3/GaussSeidelA.jpg differ diff --git a/ENUME/references/NumericalMethods/Report_1/Task3/Gauss_Seidel.m b/ENUME/references/NumericalMethods/Report_1/Task3/Gauss_Seidel.m new file mode 100644 index 00000000..11f9f317 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task3/Gauss_Seidel.m @@ -0,0 +1,60 @@ +clear variable; +clear all; +clc; + + %A = [15, 2, -10, 1 ; 1, 11, 5, -3 ; 6, 1, -23, 15 ; 1, 2, -3, 9]; + %b = [13 ; 24 ; 8 ; 82]; + +%A = createMatrixA(10); +%b = createVectorA(10); + +%A = createMatrixB(10); +%b = createVectorB(10); + +[M,N] = size(A); + +% ---Square matrix test---% +if M ~= N + error ('A is not square matrix!'); +end + +% ---Diagonal dominance test---% +for m = 1:M + row = abs ( A(m,:) ); + d = sum(row) - row(m); + + + + if row(m) <= d + %error ('A is not diagonally dominant!'); + end +end + +D = diag(diag(A)); + +U = triu(A, 1); + +L = tril(A, -1); + +initial_x = zeros(M,1); +x = -inv(D+L) *((U)*initial_x - b); + +iter_num = 0; +err_norm2 = inf; + +while err_norm2 >= 1e-10 %Assumed tolerance + x = -inv(D+L) *((U)*initial_x - b); + initial_x = x; + + iter_num = iter_num + 1; + err_norm2 = norm(abs(A*x-b)); + + hold on; + plot(iter_num, err_norm2, '.'); + hold off; + +end + + xlabel('Iteration number'); + ylabel('Solution error'); + title('Gauss Seidel method'); diff --git a/ENUME/references/NumericalMethods/Report_1/Task3/Jacobi.m b/ENUME/references/NumericalMethods/Report_1/Task3/Jacobi.m new file mode 100644 index 00000000..ca3822e1 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task3/Jacobi.m @@ -0,0 +1,62 @@ +clear variable; +clear all; +clc; + + A = [15, 2, -10, 1 ; 1, 11, 5, -3 ; 6, 1, -23, 15 ; 1, 2, -3, 9]; + b = [13 ; 24 ; 8 ; 82]; + +%A = createMatrixA(10); +%b = createVectorA(10); + +%A = createMatrixB(10); +%b = createVectorB(10); + +%A = [10 2 -1 ; 1 8 3 ; -2 -1 10]; +%b = [7 ; -4 ; 9]; + +[M,N] = size(A); + +% ---Square matrix test---% +if M ~= N + error ('A is not square matrix!'); +end + +% ---Diagonal dominance test---% +for m = 1:M + row = abs ( A(m,:) ); + d = sum(row) - row(m); + + if row(m) <= d + error ('A is not diagonally dominant!'); + end +end + + +D = diag(diag(A)); + +U = triu(A, 1); + +L = tril(A, -1); + +initial_x = zeros(M,1); +x = -inv(D) *( (L+U)*initial_x - b); + +iter_num = 0; +err_norm2 = inf; + +while err_norm2 >= 1e-10 %Assumed tolerance + x = -inv(D) *( (L+U)*initial_x - b); + initial_x = x; + + iter_num = iter_num + 1; + err_norm2 = norm(abs(A*x-b)); + + hold on; + plot(iter_num, err_norm2, '.'); + hold off; + +end + + xlabel('Iteration number'); + ylabel('Solution error'); + title('Jacobis method'); diff --git a/ENUME/references/NumericalMethods/Report_1/Task3/JacobiA.jpg b/ENUME/references/NumericalMethods/Report_1/Task3/JacobiA.jpg new file mode 100644 index 00000000..9ca8e71a Binary files /dev/null and b/ENUME/references/NumericalMethods/Report_1/Task3/JacobiA.jpg differ diff --git a/ENUME/references/NumericalMethods/Report_1/Task3/Task3GaussSeidel.jpg b/ENUME/references/NumericalMethods/Report_1/Task3/Task3GaussSeidel.jpg new file mode 100644 index 00000000..ea75a80c Binary files /dev/null and b/ENUME/references/NumericalMethods/Report_1/Task3/Task3GaussSeidel.jpg differ diff --git a/ENUME/references/NumericalMethods/Report_1/Task3/Task3Jacobi.jpg b/ENUME/references/NumericalMethods/Report_1/Task3/Task3Jacobi.jpg new file mode 100644 index 00000000..aea48304 Binary files /dev/null and b/ENUME/references/NumericalMethods/Report_1/Task3/Task3Jacobi.jpg differ diff --git a/ENUME/references/NumericalMethods/Report_1/Task3/createMatrixA.m b/ENUME/references/NumericalMethods/Report_1/Task3/createMatrixA.m new file mode 100644 index 00000000..caa8e0ae --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task3/createMatrixA.m @@ -0,0 +1,17 @@ +function a = createMatrixA(n) + + a = zeros(n,n); + + for i = 1 : n + for j = 1 : n + if i == j + a(i,j) = 9; + elseif (i == j - 1) || (i == j + 1) + a(i,j) = 3; + else + a(i,j) = 0; + end + end + end + +end diff --git a/ENUME/references/NumericalMethods/Report_1/Task3/createMatrixB.m b/ENUME/references/NumericalMethods/Report_1/Task3/createMatrixB.m new file mode 100644 index 00000000..8b280860 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task3/createMatrixB.m @@ -0,0 +1,12 @@ +function a = createMatrixB(n) + + a = zeros(n,n); + + for i = 1 : n + for j = 1 : n + a(i,j) = 8 / (9 * (i + j + 1)); + end + end + +end + diff --git a/ENUME/references/NumericalMethods/Report_1/Task3/createVectorA.m b/ENUME/references/NumericalMethods/Report_1/Task3/createVectorA.m new file mode 100644 index 00000000..73a1f25c --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task3/createVectorA.m @@ -0,0 +1,10 @@ +function b = createVectorA(n) + + b = zeros(n,1); + + for i = 1 : n + b(i, 1) = 3.4 + 0.6 * i; + end + +end + diff --git a/ENUME/references/NumericalMethods/Report_1/Task3/createVectorB.m b/ENUME/references/NumericalMethods/Report_1/Task3/createVectorB.m new file mode 100644 index 00000000..40a7c6a8 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task3/createVectorB.m @@ -0,0 +1,15 @@ +function b = createVectorB(n) + + b = zeros(n,1); + + for i = 1 : n + if (mod(i,2) == 0 ) + b(i, 1) = 4/(3*i); + else + b(i, 1) = 0; + end + end + +end + + diff --git a/ENUME/references/NumericalMethods/Report_1/Task4/QRfactorization.m b/ENUME/references/NumericalMethods/Report_1/Task4/QRfactorization.m new file mode 100644 index 00000000..a1818801 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task4/QRfactorization.m @@ -0,0 +1,27 @@ +%Function performs QR factorization on matrix A. +%N indicates the size of matrix A. +function [Q, R] = QRfactorization(A, N) + +Q = zeros(N, N); +R = zeros(N, N); +d = zeros(1, N); + +for i = 1:N + + Q(:, i) = A(:, i); + R(i, i) = 1; + d(i) = Q(:, i)' * Q(:, i); + + for j = i+1:N + R(i, j) = (Q(:, i)' * A(:, j)) / d(i); + A(:, j) = A(:, j) - R(i, j) * Q(:,i); + end +end + + for i = 1:N + dd = norm(Q(:,i)); + Q(:, i) = Q(:, i) / dd; + R(i, i:N) = R(i, i:N) * dd; + end + +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Report_1/Task4/Task4.m b/ENUME/references/NumericalMethods/Report_1/Task4/Task4.m new file mode 100644 index 00000000..6a89946c --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task4/Task4.m @@ -0,0 +1,9 @@ +A = [88 1 19 1 11; + 1 2 1 1 1; + 19 1 3 14 1; + 1 1 14 4 12; + 11 1 1 12 5]; + +[eval, iter, finalA] = eigvalQRNoShift(A, 5); +[eval, iter, finalA] = eigvalQRWithShift(A, 5) +eig(A); \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Report_1/Task4/eigvalQRNoShift.m b/ENUME/references/NumericalMethods/Report_1/Task4/eigvalQRNoShift.m new file mode 100644 index 00000000..8ac7a8a7 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task4/eigvalQRNoShift.m @@ -0,0 +1,18 @@ +% Function performs QR method of finding eigenvalues without shifts of matrix A +% N - the size of matrix A +% eigval - vector of eigenvalues +% iterCnt - number of iterations performed +% finalMat - matrix A after procedure +function [eigval, iterCnt, finalMat] = eigvalQRNoShift(A, N) + iterCnt = 0; + while max(max(A-diag(diag(A)))) > 10^-6 + + [Q, R] = QRfactorization(A, N); + A = R * Q; + iterCnt = iterCnt + 1; + + end + eigval = diag(A); + + finalMat = A; +end diff --git a/ENUME/references/NumericalMethods/Report_1/Task4/eigvalQRWithShift.m b/ENUME/references/NumericalMethods/Report_1/Task4/eigvalQRWithShift.m new file mode 100644 index 00000000..0ea3fd0b --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task4/eigvalQRWithShift.m @@ -0,0 +1,36 @@ +% Function performs QR method of finding eigenvalues with shifts of matrix A +% N - the size of matrix A +% eigval - vector of eigenvalues +% iterCnt - number of iterations performed +function [eigval, iterCnt, finalA] = eigvalQRWithShift(A, N) + iterCnt = 0; + eigval = diag(A); + + initSubmatrix = A; + for k = N:-1:2 + cp = initSubmatrix; + + while max(abs(cp(k, 1:k-1))) > 10^-6 + DD = cp(k-1:k, k-1:k); + [ev1, ev2] = quadpolynroots(1, -(DD(1,1) + DD(2,2)), DD(2,2) * DD(1,1) - DD(2,1) * DD(1,2)); + + if abs(ev1 - DD(2, 2)) < abs(ev2 - DD(2, 2)) + shift = ev1; + else + shift = ev2; + end + DP = cp - eye(k) * shift; + [Q, R] = QRfactorization(DP, size(DP, 1)); + cp = R * Q + eye(k) * shift; + iterCnt = iterCnt + 1; + end + eigval(k) = cp(k, k); + A(1:k, 1:k) = cp(1:k, 1:k); + if k > 2 + initSubmatrix = cp(1:k-1, 1:k-1); + else + eigval(1) = cp(1, 1); + end + end + finalA = A; +end \ No newline at end of file diff --git a/ENUME/references/NumericalMethods/Report_1/Task4/quadpolynroots.m b/ENUME/references/NumericalMethods/Report_1/Task4/quadpolynroots.m new file mode 100644 index 00000000..7652ab22 --- /dev/null +++ b/ENUME/references/NumericalMethods/Report_1/Task4/quadpolynroots.m @@ -0,0 +1,14 @@ +function [x1, x2] = quadpolynroots( a,b,c ) + + l1 = -b + sqrt(b*b - 4*a*c); + l2 = -b - sqrt(b*b - 4*a*c); + + if abs(l1) > abs(l2) + counter = l1; + else + counter = l2; + end + x1 = counter/(2 * a); + x2 = ((-b) / a) - x1; + +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project1/calculateEps.m b/ENUME/references/PW-EiTI/MNUM/Project1/calculateEps.m new file mode 100644 index 00000000..9d231c94 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project1/calculateEps.m @@ -0,0 +1,8 @@ +function [eps] = calculateEps() + %finding smallest eps where eps + 1 > 1 + x = 1.0; + while (x + 1 > 1) + eps = x; + x = x/2; + end +end diff --git a/ENUME/references/PW-EiTI/MNUM/Project1/calculateNorm.m b/ENUME/references/PW-EiTI/MNUM/Project1/calculateNorm.m new file mode 100644 index 00000000..88810a18 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project1/calculateNorm.m @@ -0,0 +1,8 @@ +function [err] = calculateNorm(vector) +%norm 2 of vector + sum = 0; + for i = 1:size(vector) + sum = sum + vector(i,1)^2; + end + err = sqrt(sum); +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project1/exampleGenerator.m b/ENUME/references/PW-EiTI/MNUM/Project1/exampleGenerator.m new file mode 100644 index 00000000..9d418fc0 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project1/exampleGenerator.m @@ -0,0 +1,46 @@ +function [A, b] = exampleGenerator(matrixSize, exampleNumber) + if exampleNumber == 1 + A = zeros(matrixSize, matrixSize); + for i = 1:matrixSize + for j = 1:matrixSize + if i==j + A(i,j) = 9.0; + elseif i==j-1 || i==j+1 + A(i,j) = 3.0; + else + A(i,j) = 0.0; + end + end + end + b = zeros(matrixSize, 1); + for i = 1:matrixSize + b(i, 1) = 3.4 + 0.6 * i; + end + elseif exampleNumber == 2 + A = zeros(matrixSize, matrixSize); + for i = 1:matrixSize + for j = 1:matrixSize + if i==j + A(i,j) = 1/3; + else + A(i,j) = 5*(i-j)+2; + end + end + end + b = zeros(matrixSize, 1); + for i = 1:matrixSize + b(i,1) = 8+0.2*i; + end + elseif exampleNumber == 3 + A = zeros(matrixSize, matrixSize); + for i = 1:matrixSize + for j = 1:matrixSize + A(i,j) = 1/[4*(i+j+1)]; + end + end + b = zeros(matrixSize, 1); + for i = 1:matrixSize + b(i,1) = 2+2/(i+1); + end + end +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project1/gaussSeidelMethod.m b/ENUME/references/PW-EiTI/MNUM/Project1/gaussSeidelMethod.m new file mode 100644 index 00000000..243e35a9 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project1/gaussSeidelMethod.m @@ -0,0 +1,16 @@ +function [x] = gaussSeidelMethod(A, b) + iters = 10000; + size = length(A); + x = zeros([size 1]); + for k = 1:iters + for i = 1:size + sum = 0; + for j = 1:size + if j != i + sum = sum + A(i,j)*x(j); + end + end + x(i) = (b(i) - sum)/A(i,i); + end + end +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project1/gaussianElimination.m b/ENUME/references/PW-EiTI/MNUM/Project1/gaussianElimination.m new file mode 100644 index 00000000..3c6c99fd --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project1/gaussianElimination.m @@ -0,0 +1,20 @@ +function [X, AB] = gaussianElimination(M1, V1) + AB = horzcat(M1, V1); + [height, width] = size(AB); + X = zeros([height 1]); + for i = 1:height-1 + for j = i+1:height + ratio = AB(j, i) / AB(i,i); + for k = i:width + AB(j,k) = AB(j,k) - ratio * AB(i,k); + end + end + end + for i = height:-1:1 + s = AB(i,width); + for j = height:-1:i+1 + s = s- AB(i,j) * X(j); + end + X(i) = s / AB(i,i); + end +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project1/gaussianEliminationCompletePivoting.m b/ENUME/references/PW-EiTI/MNUM/Project1/gaussianEliminationCompletePivoting.m new file mode 100644 index 00000000..0553340f --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project1/gaussianEliminationCompletePivoting.m @@ -0,0 +1,38 @@ +function [X, AB] = gaussianEliminationCompletePivoting(A, b) + AB = horzcat(A, b); + [height, width] = size(AB); + P = zeros([height 2]); + X = zeros([height 1]); + for i = 1:height-1 + subMatrix = AB([i:height],[i:height]); + [num idx] = max(subMatrix(:)); + [maxRow maxColumn] = ind2sub(size(subMatrix),idx); + maxRow = maxRow + i - 1; + maxColumn = maxColumn + i - 1; + AB([i maxRow],:) = AB([maxRow i],:); + %Every column change will make change in result X order + P(i,:) = [i maxColumn]; + AB(:,[i maxColumn]) = AB(:,[maxColumn i]);; + for j = i+1:height + ratio = AB(j, i) / AB(i,i); + for k = i:width + AB(j,k) = AB(j,k) - ratio * AB(i,k); + end + end + end + for i = height:-1:1 + s = AB(i,width); + for j = height:-1:i+1 + s = s - AB(i,j) * X(j); + end + X(i) = s / AB(i,i); + end + %for matrix A size 10 we try to do iterative correction + if height == 10 + X = iterativeCorrection(AB, X); + end + %revert column changes which affected result vector + for i = height-1:-1:1 + X([P(i,1) P(i,2)]) = X([P(i,2) P(i,1)]); + end +end diff --git a/ENUME/references/PW-EiTI/MNUM/Project1/iterativeCorrection.m b/ENUME/references/PW-EiTI/MNUM/Project1/iterativeCorrection.m new file mode 100644 index 00000000..bb21f124 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project1/iterativeCorrection.m @@ -0,0 +1,31 @@ +function [X] = iterativeCorrection(AB, X) + matrixSize = size(AB); + height = matrixSize(1); + width = matrixSize(2); + oldX = X; + %spliting data on A and b + A = AB([1:height],[1:height]); + b = AB([1:height],[width:width]); + residuum = A*X - b; + newResiduum = residuum; + for iteration = 1:30 + AB = horzcat(A,newResiduum); + dX = zeros([height 1]); + for i = height:-1:1 + s = AB(i,width); + for j = height:-1:i+1 + s = s - AB(i,j) * dX(j); + end + dX(i) = s / AB(i,i); + end + X = X - dX; + newResiduum = A*X - b; + end + %check if iterative correction had result, if it didnt return old X + if calculateNorm(residuum) > calculateNorm(newResiduum) + fprintf('Result is better after correction\n'); + else + fprintf('Result wasnt better after correction\n'); + X = oldX; + end +end diff --git a/ENUME/references/PW-EiTI/MNUM/Project1/task2main.m b/ENUME/references/PW-EiTI/MNUM/Project1/task2main.m new file mode 100644 index 00000000..dd995412 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project1/task2main.m @@ -0,0 +1,59 @@ +function [] = task2main() + fprintf('DATA 1\n'); + MAX_ITERATIONS = 2; + vsize = zeros(MAX_ITERATIONS, 1); + verr = zeros(MAX_ITERATIONS, 1); + for i = 1:MAX_ITERATIONS + size = 2^(i-1) * 10; + fprintf('\n'); + fprintf('Size %d\n', size); + [A, b] = exampleGenerator(size, 1); + tic; + X = gaussianEliminationCompletePivoting(A, b); + fprintf('Time %d\n', toc); + residuum = A*X - b; + residuumErr = calculateNorm(residuum); + fprintf('Error as residuum norm %d\n', residuumErr); + vsize(i) = size; + verr(i) = residuumErr; + end + figure(); + plot(vsize, verr, '.'); + title('Dane 1'); + fprintf('\nDATA 2\n'); + for i = 1:MAX_ITERATIONS + size = 2^(i-1) * 10; + fprintf('\n'); + fprintf('Size %d\n', size); + [A, b] = exampleGenerator(size, 2); + tic; + X = gaussianEliminationCompletePivoting(A, b); + fprintf('Time %d\n', toc); + residuum = A*X - b; + residuumErr = calculateNorm(residuum); + fprintf('Error as residuum norm %d\n', residuumErr); + vsize(i) = size; + verr(i) = residuumErr; + end + figure(); + plot(vsize, verr, '.'); + title('Dane 2'); + fprintf('\nDATA 3\n'); + for i = 1:MAX_ITERATIONS + size = 2^(i-1) * 10; + fprintf('\n'); + fprintf('Size %d\n', size); + [A, b] = exampleGenerator(size, 3); + tic; + X = gaussianEliminationCompletePivoting(A, b); + fprintf('Time %d\n', toc); + residuum = A*X - b; + residuumErr = calculateNorm(residuum); + fprintf('Error as residuum norm %d\n', residuumErr); + vsize(i) = size; + verr(i) = residuumErr; + end + figure(); + plot(vsize, verr, '.'); + title('Dane 3'); +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project1/task3main.m b/ENUME/references/PW-EiTI/MNUM/Project1/task3main.m new file mode 100644 index 00000000..03353258 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project1/task3main.m @@ -0,0 +1,25 @@ +function [] = task3main() + A = [[14, -1, -6, 5], + [1, -8, -4, -1], + [1, -4, -12, -1], + [1, -1, 8, -16]]; + b = [10; 0; -10; -20]; + x = gaussSeidelMethod(A, b); + residuum = A*x - b; + fprintf('Given example residuum norm %d \n', calculateNorm(residuum)); + fprintf('Results for example 1 with Gauss-Seidel method\n'); + [A b] = exampleGenerator(15, 1); + display(gaussSeidelMethod(A, b)); + fprintf('Results for example 1 with Gauss Elimination with complete pivoting\n'); + display(gaussianEliminationCompletePivoting(A,b)); + fprintf('Results for example 2 with Gauss-Seidel method\n'); + [A b] = exampleGenerator(15, 2); + display(gaussSeidelMethod(A, b)); + fprintf('Results for example 2 with Gauss Elimination with complete pivoting\n'); + display(gaussianEliminationCompletePivoting(A,b)); + fprintf('Results for example 3 with Gauss-Seidel method\n'); + [A b] = exampleGenerator(15, 3); + display(gaussSeidelMethod(A, b)); + fprintf('Results for example 3 with Gauss Elimination with complete pivoting\n'); + display(gaussianEliminationCompletePivoting(A,b)); +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project2/calculateNorm.m b/ENUME/references/PW-EiTI/MNUM/Project2/calculateNorm.m new file mode 100644 index 00000000..88810a18 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project2/calculateNorm.m @@ -0,0 +1,8 @@ +function [err] = calculateNorm(vector) +%norm 2 of vector + sum = 0; + for i = 1:size(vector) + sum = sum + vector(i,1)^2; + end + err = sqrt(sum); +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project2/eigenvalues2x2Matrix.m b/ENUME/references/PW-EiTI/MNUM/Project2/eigenvalues2x2Matrix.m new file mode 100644 index 00000000..ec336084 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project2/eigenvalues2x2Matrix.m @@ -0,0 +1,8 @@ +%calculte from definition eigenvalues for 2x2 matrix +%return eigenvalues = x from equation det(A - xI) = 0 +function [eigenvalues] = eigenvalues2x2Matrix(A) + eigenvalues = zeros([2,1]); + delta = (A(1,1) + A(2,2))^2 - 4*(A(1,1)*A(2,2) - A(1,2)*A(2,1)); + eigenvalues(1) = (A(1,1)+A(2,2) - sqrt(delta))/2; + eigenvalues(2) = (A(1,1) + A(2,2)) - eigenvalues(1); +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project2/eigenvaluesWithShifts.m b/ENUME/references/PW-EiTI/MNUM/Project2/eigenvaluesWithShifts.m new file mode 100644 index 00000000..8080ccea --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project2/eigenvaluesWithShifts.m @@ -0,0 +1,32 @@ +function [eigenvalues, allIterations] = eigenvaluesWithShifts(A, tol, maxIterations) + height = size(A,1); + eigenvalues = diag(zeros(height)); + initialSubmatrix = A; + allIterations = 0; + for k = height:-1:2 + DK = initialSubmatrix; + iteration = 0; + while iteration<=maxIterations && max(abs(DK(k,1:k-1))) > tol + DD = DK(k-1:k,k-1:k); + EV = eigenvalues2x2Matrix(DD); + shift = EV(2); + if abs(EV(1) - DD(2,2)) < abs(EV(2) - DD(2,2)) + shift = EV(1); + end + DK = DK - eye(k) * shift; + [Q, R] = qrGramSchmidt(DK); + DK = R * Q + eye(k) * shift; + iteration = iteration + 1; + allIterations = allIterations + 1; + end + if iteration > maxIterations + error('More iterations needed'); + end + eigenvalues(k) = DK(k,k); + if k > 2 + initialSubmatrix = DK(1:k-1,1:k-1); + else + eigenvalues(1) = DK(1,1); + end + end +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project2/eigenvaluesWithoutShifts.m b/ENUME/references/PW-EiTI/MNUM/Project2/eigenvaluesWithoutShifts.m new file mode 100644 index 00000000..b520f576 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project2/eigenvaluesWithoutShifts.m @@ -0,0 +1,12 @@ +function [eigenvalues, iteration] = eigenvaluesWithoutShifts(A, tol, maxIterations) + iteration = 0; + while iteration < maxIterations && max(max(A-diag(diag(A)))) > tol + [Q, R] = qrGramSchmidt(A); + A = R * Q; + iteration = iteration + 1; + end + if iteration > maxIterations + error('More iterations needed'); + end + eigenvalues = diag(A); +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project2/generateExamples.m b/ENUME/references/PW-EiTI/MNUM/Project2/generateExamples.m new file mode 100644 index 00000000..e0c5d071 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project2/generateExamples.m @@ -0,0 +1,26 @@ +function [A, b] = generateExamples(exampleNumber, size) + height = 2 * size; + width = size; + A = zeros(height, width); + b = zeros(height, 1); + if exampleNumber == 1 + for i = 1:height + for j = 1:width + b(i) = 8 + 0.2 * i; + if i == j + A(i, j) = 1/3; + else + A(i,j) = 5 * (i - j) + 2; + end + end + end + elseif exampleNumber == 2 + for i = 1:height + for j = 1:width + b(i) = 2 + 2/(i + 1); + A(i,j) = 1/(4* (i + j + 1)); + end + end + end +end + diff --git a/ENUME/references/PW-EiTI/MNUM/Project2/qrGramSchmidt.m b/ENUME/references/PW-EiTI/MNUM/Project2/qrGramSchmidt.m new file mode 100644 index 00000000..06110614 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project2/qrGramSchmidt.m @@ -0,0 +1,23 @@ +function [Q, R] = qrGramSchmidt(A) + % modificated Gram-Schmidt algorithm + [height, width] = size(A); + Q = zeros([height, width]); + R = zeros([width, width]); + D = zeros([1, width]); + for i = 1:width + Q(:,i) = A(:,i); + R(i,i) = 1; + D(:,i) = Q(:,i).' * Q(:,i); + for j = i+1:width + R(i,j) = Q(:,i).' * A(:,j) / D(:,i); + A(:,j) = A(:,j) - R(i,j) * Q(:,i); + end + end + % normalization + for i = 1:width + norm = calculateNorm(Q(:,i)); + Q(:,i) = Q(:,i)/norm; + R(i,i:width) = R(i,i:width) * norm; + end +end + diff --git a/ENUME/references/PW-EiTI/MNUM/Project2/symetricMatrixGenerator.m b/ENUME/references/PW-EiTI/MNUM/Project2/symetricMatrixGenerator.m new file mode 100644 index 00000000..21e45593 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project2/symetricMatrixGenerator.m @@ -0,0 +1,7 @@ +function [A] = symetricMatrixGenerator(size) + A = rand(size); + A = 0.5*(A+A.'); + for i = 1:size + A(i,i) = rand; + end +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project2/task1main.m b/ENUME/references/PW-EiTI/MNUM/Project2/task1main.m new file mode 100644 index 00000000..5ac1758f --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project2/task1main.m @@ -0,0 +1,59 @@ +function [] = task1main() + %SIZE 5 + tolerance = 0.1; + for i = 1:5 + sum = 0; + for j = 1:30 + A = rand(5); + [eigenvalues, iterations] = eigenvaluesWithShifts(A, tolerance, 1000000); + sum = sum + iterations; + if j == 30 + g=sprintf('%d ', eig(A)); + fprintf('\nExample results for size 5 matlab\n%s\n', g); + g=sprintf('%d ', eigenvalues); + fprintf('\nExample results for size 5 my\n%s\n', g); + end + end + fprintf('\nMean iterations for tolerance %d\n', tolerance); + fprintf('%d\n', sum/30); + tolerance = tolerance / 10; + end + % SIZE 10 + tolerance = 0.1; + for i = 1:5 + sum = 0; + for j = 1:30 + A = rand(10); + [eigenvalues, iterations] = eigenvaluesWithShifts(A, tolerance, 1000000); + sum = sum + iterations; + if j == 30 + g=sprintf('%d ', eig(A)); + fprintf('\nExample results for size 10 matlab\n%s\n', g); + g=sprintf('%d ', eigenvalues); + fprintf('\nExample results for size 10 my\n%s\n', g); + end + end + fprintf('\nMean iterations for tolerance %d\n', tolerance); + fprintf('%d\n', sum/30); + tolerance = tolerance / 10; + end + % SIZE 20 + tolerance = 0.1; + for i = 1:5 + sum = 0; + for j = 1:30 + A = rand(20); + [eigenvalues, iterations] = eigenvaluesWithShifts(A, tolerance, 1000000); + sum = sum + iterations; + if j == 30 + g=sprintf('%d ', eig(A)); + fprintf('\nExample results for size 20 matlab\n%s\n', g); + g=sprintf('%d ', eigenvalues); + fprintf('\nExample results for size 20 my\n%s\n', g); + end + end + fprintf('\nMean iterations for tolerance %d\n', tolerance); + fprintf('%d\n', sum/30); + tolerance = tolerance / 10; + end +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/Project2/task2main.m b/ENUME/references/PW-EiTI/MNUM/Project2/task2main.m new file mode 100644 index 00000000..e9c12b34 --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/Project2/task2main.m @@ -0,0 +1,29 @@ +function [] = task2main() + iter = 8; + linErr = zeros(iter, 1); + qrErr = zeros(iter, 1); + sizes = zeros(iter, 1); + for i = 1:iter + size = 2^(i-1)*10; + sizes(i) = size; + fprintf('Rozmiar %d\n', size); + [A, b] = generateExamples(2, size); + X = linsolve(A'* A, A' * b); + residuumErr = calculateNorm(A*X-b); + linErr(i) = residuumErr; + fprintf('Uklad rownan normalnych, blad residuum: %d\n', residuumErr); + [Q, R] = qr(A); + X = linsolve(R, Q' * b); + residuumErr = calculateNorm(A*X-b); + qrErr(i) = residuumErr; + fprintf('Uklad rownan z wykorzystaniem QR, blad residuum: %d\n', residuumErr); + end + display(qrErr); + display(linErr); + figure(); + plot(sizes, qrErr, 'Marker', 'o', 'MarkerSize', 4); + title('Blad przy ukladzie QR'); + figure(); + plot(sizes, linErr, 'Marker', 'o', 'MarkerSize', 4); + title('Blad przy ukladzie rownan normalnych'); +end \ No newline at end of file diff --git a/ENUME/references/PW-EiTI/MNUM/readme.md b/ENUME/references/PW-EiTI/MNUM/readme.md new file mode 100644 index 00000000..7cb5eaaf --- /dev/null +++ b/ENUME/references/PW-EiTI/MNUM/readme.md @@ -0,0 +1,5 @@ +Metody numeryczne - MNUM (Numerical Methods) + + +References: +"Metody numeryczne" Piotr Tatjewski diff --git a/ENUME/references/Semester-5-ENUME/README.md b/ENUME/references/Semester-5-ENUME/README.md new file mode 100644 index 00000000..d8b33658 --- /dev/null +++ b/ENUME/references/Semester-5-ENUME/README.md @@ -0,0 +1 @@ +# Numerical Methods diff --git a/ENUME/references/Semester-5-ENUME/projectA.m b/ENUME/references/Semester-5-ENUME/projectA.m new file mode 100644 index 00000000..cd3c4ee6 --- /dev/null +++ b/ENUME/references/Semester-5-ENUME/projectA.m @@ -0,0 +1,527 @@ +% close all windows and figures, clear command window +close all; +clear all; +clc; + +%%%%%%%%%% ENUME %%%%%%%%%% +%%%%% PROJECT A NO.65% %%%% +% JAKUB TOMKIEWICZ 300183 % + + +%%%%%%%% PROBLEM 1 %%%%%%%% + +% matlab generated epsilon + +disp("PROBLEM 1"); + +% format long will give precise answer +format long; + +% eps calculated by matlab +matlab_auto_generated_eps = eps + +% determining epsilon in calculation +i = 1; +count = 0; + +while 1+i > 1 + i = i/2; + count = count + 1; +end + +i = 2*i; + +count = count - 1 +manually_calculated_eps = i + + + +%%%%%%%% PROBLEM 2 %%%%%%%% + +disp("PROBLEM 2"); + +% format back to normal +format short; + +% generate matrix for a) +[A_a,b_a] = generateMatrixForTaskA(10) + +% solve a) using Gaussian elimination with partial pivoting +[x_a,normOfResiduum_a,normOfCorrectResiduum_a] = solveUsingGEWPP(A_a,b_a) + +x_a_by_matlab = A_a\b_a + +% generate matrix for b) +[A_b,b_b] = generateMatrixForTaskB(10) + +% solve b) using Gaussian elimination with partial pivoting +[x_b,normOfResiduum_b,normOfCorrectResiduum_b] = solveUsingGEWPP(A_b,b_b) + +x_b_by_matlab = A_b\b_b + +% plot solution error versus n for a) +plotErrorForTaskA(8); + +% plot solution error versus n for b) +plotErrorForTaskB(8); + +condition_a=cond(A_a) + +condition_b=cond(A_b) + + + +%%%%%%%% PROBLEM 3 %%%%%%%% + +disp("PROBLEM 3"); + +A_3 = [8 2 -3 1; 2 -25 5 -18; 1 3 15 -8; 1 1 -2 -10]; +b_3 = [7; 12; 24; 28]; + +plotJacobiVsGaussSeidel(A_3,b_3) + +% solve using matrix A and vector b from problem 2a +[x_from_2a_jacobi, ~, ~] = solveUsingJacobisMethod(A_a,b_a); +x_from_2a_jacobi + +[x_from_2a_gs, ~, ~] = solveUsingGaussSeidelMethod(A_a,b_a); +x_from_2a_gs + +% plotJacobiVsGaussSeidel(A_a,b_a) + +% solve using matrix A and vector b from problem 2b +[x_from_2b_jacobi, ~, ~] = solveUsingJacobisMethod(A_b,b_b); +x_from_2b_jacobi + +[x_from_2b_gs, ~, ~] = solveUsingGaussSeidelMethod(A_b,b_b); +x_from_2b_gs + +% plotJacobiVsGaussSeidel(A_b,b_b) + + + +%%%%%%%% PROBLEM 4 %%%%%%%% + +disp("PROBLEM 4"); + +compareBothApproaches() + + + +%%%%%%%% FUNCTIONS %%%%%%%% + +% For problem 2 generating matrix for a) % +function [A,b] = generateMatrixForTaskA(n) + + % place for numbers, filled with zeros + A = zeros(n); + b = zeros(n,1); + + for i = 1:n + for j = 1:n + if(i == j) + A(i,j) = 9; + end + if(i == j-1 || i == j+1) + A(i,j) = 1; + end + end + end + + for i = 1:n + b(i) = 1.4 + 0.6*i; + end +end + +% For problem 2 generating matrix for b) % +function [A,b] = generateMatrixForTaskB(n) + + % place for numbers, filled with zeros + A = zeros(n); + b = zeros(n,1); + + for i = 1:n + for j = 1:n + A(i,j) = 3/(4*(i+j-1)); + end + end + + for i = 1:n + if(mod(i,2) == 1) + b(i)=1/i; + end + if(mod(i,2) == 0) + b(i)=0; + end + end +end + +% For problem 2 solving linear equation using Gaussian elimination with partial pivoting % +function [C,normOfResiduum,normOfCorrectResiduum] = solveUsingGEWPP(A,b) + + n = size(A,1); + + % elimination phase + for k = 1:n + + % partial pivoting + for i = k+1:n + if(A(k,k) < A(i,k)) + A([k i],:) = A([i k],:); + b([k i]) = b([i k]); + end + end + + % conversion to upper-triangular matrix + for i = k+1:n + rowMultiplier = A(i,k)/A(k,k); + + A(i,:) = A(i,:) - (rowMultiplier*A(k,:)); + + b(i) = b(i)-(rowMultiplier*b(k)); + end + end + + % back-substitution phase + C = zeros(1,n); + + for i = n:-1:1 + + sum = 0; + + for j = i+1:n + sum = sum + A(i,j)*C(j); + end + + C(i) = (b(i)- sum)/A(i,i); + end + + C = C'; + + % residuum + residuum = A*C - b; + + % norm of residuum + normOfResiduum = norm(residuum); + + % residual correction Ad=r + residuum = residuum'; + d = residuum/A; + + goodX = C-d; + CorrectResiduum = (A*goodX)-b; + + normOfCorrectResiduum = norm(CorrectResiduum); +end + +% For problem 2 a) plotting graph % +function plotErrorForTaskA(numberOfEquations) + + n=10; + + % place for results, filled with 0s + RememberNormOfResiduum = zeros(numberOfEquations); + RememberNormOfCorrectResiduum = zeros(numberOfEquations); + RememberN = zeros(numberOfEquations); + + for i=1:numberOfEquations + [A,b] = generateMatrixForTaskA(n); + + [~,normOfResiduum,normOfCorrectResiduum] = solveUsingGEWPP(A,b); + + RememberNormOfResiduum(i) = normOfResiduum; + RememberNormOfCorrectResiduum(i) = normOfCorrectResiduum; + RememberN(i) = n; + + % n = 10, 20, 40, 80, 160, ... + n = n*2; + end + + % graph % + figure(1); + plot(RememberN, RememberNormOfResiduum, '^b') + hold on; + plot(RememberN, RememberNormOfCorrectResiduum, '^r') + hold off; + + title("For a) Number of equations versus solution error"); + xlabel("Number of equations (n)"); + ylabel("Solution error"); + +end + +% For problem 2 b) plotting graph % +function plotErrorForTaskB(numberOfEquations) + + n=10; + + % place for results, filled with 0s + RememberNormOfResiduum = zeros(numberOfEquations); + RememberNormOfCorrectResiduum = zeros(numberOfEquations); + RememberN = zeros(numberOfEquations); + + for i=1:numberOfEquations + [A,b] = generateMatrixForTaskB(n); + + [~,normOfResiduum,normOfCorrectResiduum] = solveUsingGEWPP(A,b); + + RememberNormOfResiduum(i) = normOfResiduum; + RememberNormOfCorrectResiduum(i) = normOfCorrectResiduum; + RememberN(i) = n; + + % n = 10, 20, 40, 80, 160, ... + n = n*2; + end + + % graph + figure(2); + plot(RememberN, RememberNormOfResiduum, '^b') + hold on; + plot(RememberN, RememberNormOfCorrectResiduum, '^r') + hold off; + + title("For b) Number of equations versus solution error"); + xlabel("Number of equations (n)"); + ylabel("Solution error"); + +end + +% For problem 3 solve using Jacobis Method % +function [x, iterationNr, rememberError] = solveUsingJacobisMethod(A,b) + + x = zeros(size(A, 1), 1); + + % create L subdiagonal matrix + L = tril(A,-1); + + % create D diagonal matrix + D = diag(diag(A)); + + % create U matrix with entries over diagonal + U = triu(A,1); + + % tolerance + assumedTolerance = 1e-10; + + % number of iterations + nrOfIterations = 150; + + for i=1:nrOfIterations + + x = D \ (b + (-L-U)*x); + + % we cant preallocate iterationNr, we dont know how big will be + iterationNr(i,1) = i; + + solutionErrorVector = norm(A*x - b); % checking norm of solution error value + rememberError(i,1) = solutionErrorVector; + + if solutionErrorVector <= assumedTolerance % if test NOT saidsfied continue + break; + end + end +end + +% For problem 3 solve using Gauss-Seidel Method % +function [x, iterationNr, rememberError] = solveUsingGaussSeidelMethod(A,b) + + x = zeros(size(A, 1), 1); + + % create L subdiagonal matrix + L = tril(A,-1); + + % creade D diagonal matrix + D = diag(diag(A)); + + % create U matrix with entries over diagonal + U = triu(A,1); + + % tolerance + assumedTolerance = 1e-10; + + % number of iterations + nrOfIterations = 150; + + for i=1:nrOfIterations + + % create w + w = U*x - b; + + for j=1:size(A, 1) + + % x = -w + x(j) = -w(j); + + % -l*x + for k=1:(j-1) + x(j) = -x(k)*L(j,k) + x(j); + end + + % /d + x(j) = inv(D(j, j)) * x(j); + end + + % we cant preallocate iterationNr, we dont know how big will be + iterationNr(i,1) = i; + + solutionErrorVector = norm(A*x - b); % checking norm of solution error value + rememberError(i,1) = solutionErrorVector; + + if solutionErrorVector <= assumedTolerance % if test NOT sadisfied continue + break + end + end + +end + +% compare results of iterations, plot norm of solution error vs iteration nr % +function plotJacobiVsGaussSeidel(A,b) + + [~,iterationNrJacobi,rememberErrorJacobi] = solveUsingJacobisMethod(A,b); + [~,iterationNrGaussSeidel,rememberErrorGaussSeidel] = solveUsingGaussSeidelMethod(A,b); + + % graph + figure(3); + plot(iterationNrJacobi, rememberErrorJacobi, '-.r*') + hold on; + plot(iterationNrGaussSeidel, rememberErrorGaussSeidel, '--mo') + hold off; + + title("Comparison between iteration number and solution error"); + xlabel("Number of iterations"); + ylabel("Solution error"); + legend("Jacobis method","Gauss-Seidel method"); +end + +% for problem 4 algorithm for the QR factorization % +function [Q,R] = qrmgs(A) + + [m n] = size(A); + + Q = zeros(m,n); + R = zeros(n,n); + d= zeros(1,n); + + % factorization with orthogonal/not orthogonoal columns of Q + for i=1:n + Q(:,i) = A(:,i); + R(i,i) = 1; + d(i) = Q(:,i)'*Q(:,i); + + for j=i+1:n + R(i,j) = (Q(:,i)'*A(:,j))/d(i); + A(:,j) = A(:,j)-R(i,j)*Q(:,i); + end + end + + % column normalization + for i=1:n + dd = norm(Q(:,i)); + Q(:,i) = Q(:,i)/dd; + R(i,i:n) = R(i,i:n)*dd; + end +end + +% for problem 4 QR algorithm without shifts, calculate eigenvalues % +function [eigenvalues, nrOfIterations] = EigvalQRNoShift(D, tol, imax) + + n = size(D,1); + i = 1; + D = hess(D); % hassenberg form + + while i <= imax & max(max(D-diag(diag(D)))) > tol + [Q1, R1] = qrmgs(D); + D = R1 * Q1; % transformed matrix + i = i+1; + end + + if i > imax + disp('i exceed imax'); + end + + nrOfIterations = i; + eigenvalues = diag(D); +end + +% for problem 4 QR algorithm with shifts, calculate eigenvalues % +function [eigenvalues, nrOfIterations] = EigvalQRshifts(A, tol, imax) + + n = size(A,1); + eigenvalues = diag(ones(n)); + A = hess(A); % hassenberg form + + INITIALsubmatrix = A; % initial matrix + + for k = n:-1:2 + DK = INITIALsubmatrix; % initial matrix to calculate + + i = 0; + while i<=imax & max(abs(DK(k,1:k-1)))>tol + DD = DK(k-1:k,k-1:k); % bottom 2x2 right corner submatrix + [ev1, ev2] = quadpolynroots(1,-(DD(1,1)+DD(2,2)),DD(2,2)*DD(1,1)-DD(2,1)*DD(1,2)); + + if abs(ev1 - DD(2,2)) < abs(ev2 - DD(2,2)) + shift = ev1; % shift + else + shift = ev2; + end + + DP = DK - eye(k)*shift; % shifted matrix + [Q1, R1] = qrmgs(DP); % QR factorization + DK = R1*Q1 + eye(k)*shift; % transformed matrix + i = i+1; + end + + if i > imax + disp('imax exceeds program terminated'); + end + + nrOfIterations = i; + + eigenvalues(k) = DK(k,k); + + if k > 2 + INITIALsubmatrix = DK(1:k-1,1:k-1); % matrix deflation + else + eigenvalues(1) = DK(1,1); % last eigenvalue + end + end +end + +% for problem 4 look for roots % +function [x0, x1] = quadpolynroots(a, b, c) + + delta1 = sqrt((b^2) - (4*a*c)) - b; + delta2 = -sqrt((b^2) - (4*a*c)) - b; + + if abs(delta1) > abs(delta2) + delta = delta1; + else + delta = delta2; + end + + x0 = delta/(2*a); + x1 = ((-b/a) - x0); +end + +% for problem 4 compare both approaches and check results with matlab algorithm % +function compareBothApproaches() + + A = rand(5); % generate random 5x5 matrix + A = A - tril(A, -1) + triu(A, 1)'; % taken from problem 3 functions + + [eigenvaluesNoShift, nrOfIterations_no_shift] = EigvalQRNoShift(A, 1e-6, 100); % nr of iterations 100, treshold 10e-6 + [eigenvaluesWithShift, nrOfIterations_with_shift] = EigvalQRshifts(A, 1e-6, 100); % nr of iterations 100, treshold 10e-6 + + disp("Eigenvalues for QR method with no shift"); + disp(eigenvaluesNoShift); + disp("Nr of iterations: " + nrOfIterations_no_shift); + + disp("Eigenvalues for QR method with shift"); + disp(eigenvaluesWithShift); + disp("Nr of iterations: " + nrOfIterations_with_shift); + + % matlab build in function + disp("As confirmation, eigenvalues calculated by MATLAB"); + disp(eig(A)); +end \ No newline at end of file diff --git a/ENUME/references/Semester-5-ENUME/projectB.m b/ENUME/references/Semester-5-ENUME/projectB.m new file mode 100644 index 00000000..a7c8d67e --- /dev/null +++ b/ENUME/references/Semester-5-ENUME/projectB.m @@ -0,0 +1,435 @@ +% close all windows and figures, clear command window +close all; +clear all; +clc; + +%%%%%%%%%% ENUME %%%%%%%%%% +%%%%% PROJECT B NO.61 %%%%% +% JAKUB TOMKIEWICZ 300183 % + +%%%%%%%% PROBLEM 1 %%%%%%%% +f = @(x)0.3*x*sin(x)-log(x-1); % my function + +% interval [2 12] divided into 3 parts +[iter_Sacant1, root_Sacant1] = SecantMethod(f,50,1e-9,2,6,1); % [2 6] +[iter_Sacant2, root_Sacant2] = SecantMethod(f,50,1e-9,6.1,8,2); % [6 8] +[iter_Sacant3, root_Sacant3] = SecantMethod(f,50,1e-9,8.1,12,3); % [8 12] + +hold on; +fplot(f,[2 12],'k'); % plot function in interval +title("f(x)=0.3*x*sin(x)-ln(x-1) Secant method"); +hold off; + +% print nr of iterations and root +iter_Sacant1 +root_Sacant1 + +iter_Sacant2 +root_Sacant2 + +iter_Sacant3 +root_Sacant3 + +figure(2); +% interval [2 12] divided into 3 parts +[iter_Newton1, root_Newton1] = NewtonsMethod(f,50,1e-9,2,6,1,1); % [2 6] +[iter_Newton2, root_Newton2] = NewtonsMethod(f,50,1e-9,6.1,8,2,1); % [6 8] +[iter_Newton3, root_Newton3] = NewtonsMethod(f,50,1e-9,8.1,12,3,1); % [8 12] + +hold on; +fplot(f,[2 12],'k'); % plot function in interval +title("f(x)=0.3*x*sin(x)-ln(x-1) Newtons method"); +hold off; + +% print nr of iterations and root +iter_Newton1 +root_Newton1 + +iter_Newton2 +root_Newton2 + +iter_Newton3 +root_Newton3 + + +%%%%%%%% PROBLEM 2 %%%%%%%% +f = @(x)2*x^4 + 3*x^3 + (-6)*x^2 + 4*x + 7; +p = [2 3 -6 4 7]; + +% MM1 method +figure(1); +hold on; +grid on; +fplot(f,[-5 4],'k'); + +% first root +x0 = -2; +x1 = -2.5; +x2 = -3; +[nrIterationsMM1_1, rootMM1_1] = MM1method(p, x0, x1, x2,50,1e-9); +plot(rootMM1_1,f(rootMM1_1), 'r*'); +plot(x0,f(x0),'bs'); +plot(x1,f(x1),'bs'); +plot(x2,f(x2),'bs'); + +% second root +x0 = 0; +x1 = -0.5; +x2 = -1; +[nrIterationsMM1_2, rootMM1_2] = MM1method(p, x0, x1, x2,50,1e-9); +plot(rootMM1_2,f(rootMM1_2), 'r*'); +plot(x0,f(x0),'bs'); +plot(x1,f(x1),'bs'); +plot(x2,f(x2),'bs'); + +% third root +x0 = 0.5; +x1 = 1-0.25i; +x2 = 1.5; +[nrIterationsMM1_3, rootMM1_3] = MM1method(p, x0, x1, x2,50,1e-9); +plot(rootMM1_3,f(rootMM1_3), 'r*'); +plot(x0,f(x0),'bs'); +plot(x1,f(x1),'bs'); +plot(x2,f(x2),'bs'); + +% fourth root +x0 = 0.5; +x1 = 1+0.25i; +x2 = 1.5; +[nrIterationsMM1_4, rootMM1_4] = MM1method(p, x0, x1, x2,50,1e-9); +plot(rootMM1_4,f(rootMM1_4), 'r*'); +plot(x0,f(x0),'bs'); +plot(x1,f(x1),'bs'); +plot(x2,f(x2),'bs'); + +title("Muller's MM1 method f(x)=2*x^4+3*x^3+(-6)*x^2+4*x+7"); +hold off; + +% print nr of iterations and root +nrIterationsMM1_1 +rootMM1_1 + +nrIterationsMM1_2 +rootMM1_2 + +nrIterationsMM1_3 +rootMM1_3 + +nrIterationsMM1_4 +rootMM1_4 + +% MM2 method +figure(3); +hold on; +grid on; +fplot(f,[-5 4],'k'); + +% first root +xk = -2.5; +[nrIterationsMM2_1, rootMM2_1] = MM2method(p,xk,50,1e-9); +plot(rootMM2_1,f(rootMM2_1), 'r*'); +plot(xk,f(xk),'bs'); + +% second root +xk = -0.5; +[nrIterationsMM2_2, rootMM2_2] = MM2method(p,xk,50,1e-9); +plot(rootMM2_2,f(rootMM2_2), 'r*'); +plot(xk,f(xk),'bs'); + +% third root +xk = 1+0.25i; +[nrIterationsMM2_3, rootMM2_3] = MM2method(p,xk,50,1e-9); +plot(rootMM2_3,f(rootMM2_3), 'r*'); +plot(xk,f(xk),'bs'); + +% fourth root +xk = 1-0.25i; +[nrIterationsMM2_4, rootMM2_4] = MM2method(p,xk,50,1e-9); +plot(rootMM2_4,f(rootMM2_4), 'r*'); +plot(xk,f(xk),'bs'); + +% print nr of iterations and root +nrIterationsMM2_1 +rootMM2_1 + +nrIterationsMM2_2 +rootMM2_2 + +nrIterationsMM2_3 +rootMM2_3 + +nrIterationsMM2_4 +rootMM2_4 + +title("Muller's MM2 method f(x)=2*x^4+3*x^3+(-6)*x^2+4*x+7"); +hold off; + +% Newton's method +figure(4); +[iter_Newton1, root_Newton1] = NewtonsMethod(f,50,1e-9,-2.5,-2.5,1,2); +[iter_Newton2, root_Newton2] = NewtonsMethod(f,50,1e-9,-0.5,-0.5,2,2); + +hold on; +fplot(f,[-5 4],'k'); +title("Newton's method f(x)=2*x^4+3*x^3+(-6)*x^2+4*x+7"); +hold off; + + +%%%%%%%% PROBLEM 3 %%%%%%%% +figure(5); +hold on; +grid on; +fplot(f,[-5 4],'k'); + +% first root +xk = -2.5; +[iter_Laguerre_1, root_Laguerre_1] = LaguerresMethod(p,xk,10,1e-9); +plot(root_Laguerre_1,f(root_Laguerre_1), 'r*'); +plot(xk,f(xk),'bs'); + +% second root +xk = -0.5; +[iter_Laguerre_2, root_Laguerre_2] = LaguerresMethod(p,xk,50,1e-9); +plot(root_Laguerre_2,f(root_Laguerre_2), 'r*'); +plot(xk,f(xk),'bs'); + +% third root +xk = 1+0.25i; +[iter_Laguerre_3, root_Laguerre_3] = LaguerresMethod(p,xk,50,1e-9); +plot(root_Laguerre_3,f(root_Laguerre_3), 'r*'); +plot(xk,f(xk),'bs'); + +% fourth root +xk = 1-0.25i; +[iter_Laguerre_4, root_Laguerre_4] = LaguerresMethod(p,xk,50,1e-9); +plot(root_Laguerre_4,f(root_Laguerre_4), 'r*'); +plot(xk,f(xk),'bs'); + +% print nr of iterations and root +root_Laguerre_1 +iter_Laguerre_1 + +root_Laguerre_2 +iter_Laguerre_2 + +root_Laguerre_3 +iter_Laguerre_3 + +root_Laguerre_4 +iter_Laguerre_4 + +title("Laguerre's method f(x)=2*x^4+3*x^3+(-6)*x^2+4*x+7"); +hold off; + + +%%%%%%%% FUNCTIONS %%%%%%%% + +% Problem 1 Secant Method +function [nrIterations, root] = SecantMethod(f,imax,assumedTolerance,x0,x1,part) + + nrIterations = 1; + + hold on; + grid on; + + % for every part of interval use different colors to define intervals + if(part == 1) + plot(x0, f(x0), 'cs'); + plot(x1, f(x1), 'cs'); + end + + if(part == 2) + plot(x0, f(x0), 'ms'); + plot(x1, f(x1), 'ms'); + end + + if(part == 3) + plot(x0, f(x0), 'bs'); + plot(x1, f(x1), 'bs'); + end + + for i=1:imax % max nr of iterations + + x2=(x0*f(x1)-x1*f(x0))/(f(x1)-f(x0)); % formula to define new point + + x0 = x1; + x1 = x2; + + solutionError = abs(x1 - x0); % calculate error + + root = x2; + + if solutionError < assumedTolerance % if error < tolerance STOP + break; + end + + nrIterations = nrIterations + 1; + end + + plot(root, f(root), 'r*'); % plot root on graph + hold off; +end + +% Problem 1 Newtons Method +function [nrIterations, root] = NewtonsMethod(f,imax,assumedTolerance,x0,x1,part,problem) + + nrIterations = 1; + + hold on; + grid on; + + % for every part of interval use different colours + if(part == 1) + plot(x0, f(x0), 'cs'); + plot(x1, f(x1), 'cs'); + end + + if(part == 2) + plot(x0, f(x0), 'ms'); + plot(x1, f(x1), 'ms'); + end + + if(part == 3) + plot(x0, f(x0), 'bs'); + plot(x1, f(x1), 'bs'); + end + + root = (x0 + x1)/2; % secant + + if problem == 1 + df = @(x)(3*sin(x))/10 - 1/(x - 1) + (3*x*cos(x))/10; % derivative of function + end + + if problem == 2 + df = @(x)8*x^3 + 9*x^2 - 12*x + 4; % derivative of function + end + + for i=1:imax + + root2 = root; % remember old value + root = root - (f(root)/df(root)); % iteration formula + + solutionError = abs(root - root2); + + if solutionError < assumedTolerance % if error < tolerance STOP + break; + end + + nrIterations = nrIterations + 1; + end + + plot(root, f(root), 'r*'); +end + +% Problem 2 MM1 Method +function [nrIterations, root] = MM1method(p,x0,x1,x2,imax,assumedTolerance) + + nrIterations = 0; + c = 1; % something bigger then tolerance to begin with + + while nrIterations < imax && abs(c) > assumedTolerance % c = f(x2) + z0 = x0 - x2; + z1 = x1 - x2; + + % polynomial evaluation + c = polyval(p,x2); + a = (polyval(p,x1)*z0 - c*z0 - polyval(p,x0)*z1 + c*z1)/(z1^2*z0 - z0^2*z1); + b = (polyval(p,x0) - c - a*z0^2)/z0; + + delta = b^2-4*a*c; + + if abs(b + sqrt(delta)) >= abs(b - sqrt(delta)) % chosing root with smaller value + zmin = (-2*c)/(b + sqrt(delta)); + else + zmin = (-2*c)/(b - sqrt(delta)); + end + + root = x2 + zmin; + + % looking for two points close to root + lengthx0 = abs(x0 - root); + lengthx1 = abs(x1 - root); + lengthx2 = abs(x2 - root); + + % we assume that x2 is root of polynomial + if lengthx2 >= lengthx1 && lengthx2 >= lengthx0 + x2 = root; + end + + if lengthx1 >= lengthx2 && lengthx1 >= lengthx0 + x1 = x2; + x2 = root; + end + + if lengthx0 >= lengthx2 && lengthx0 >= lengthx1 + x0 = x2; + x2 = root; + end + + nrIterations = nrIterations+1; + end +end + +% Problem 2 MM2 Method +function [nrIterations, root] = MM2method(p,root,imax,assumedTolerance) + + nrIterations = 0; + + % derivatives + dp = polyder(p); + d2p = polyder(dp); + + c = 1; % something bigger then tolerance to begin with + + while nrIterations < imax && abs(c) > assumedTolerance % c = f(xk) + + c = polyval(p,root); + b = polyval(dp,root); + a = polyval(d2p,root)/2; + delta = b^2-4*a*c; + + if abs(b + sqrt(delta)) >= abs(b - sqrt(delta)) % chosing root with smaller value + zmin = (-2*c)/(b + sqrt(delta)); + else + zmin = (-2*c)/(b - sqrt(delta)); + end + + root = zmin + root; + + nrIterations = nrIterations+1; + end +end + +% Problem 3 Laguerres Method +function [nrIterations, root] = LaguerresMethod(p,root,imax,assumedTolerance) + + nrIterations = 0; + + % derivatives + dp = polyder(p); + d2p = polyder(dp); + n = length(p); + n = n-1; + + c = 1; % something bigger then tolerance to begin with + + while nrIterations < imax && c > assumedTolerance % c = f(xk) + + c = polyval(p,root); + + denominator1 = polyval(dp,root) + sqrt((n-1)*((n-1)*(polyval(dp,root)^2)-n*polyval(p,root)*polyval(d2p,root))); + denominator2 = polyval(dp,root) - sqrt((n-1)*((n-1)*(polyval(dp,root)^2)-n*polyval(p,root)*polyval(d2p,root))); + + % choosing larger value of denominator + if abs(denominator1) > abs(denominator2) + denominator = denominator1; + else + denominator = denominator2; + end + + % xk+1 = xk - fraction + root = root - (n*polyval(p,root))/denominator; + + nrIterations = nrIterations+1; + end +end \ No newline at end of file diff --git a/ENUME/references/Semester-5-ENUME/projectC.m b/ENUME/references/Semester-5-ENUME/projectC.m new file mode 100644 index 00000000..47c144ab --- /dev/null +++ b/ENUME/references/Semester-5-ENUME/projectC.m @@ -0,0 +1,645 @@ +% close all windows and figures, clear command window +close all; +clear all; +clc; + +%%%%%%%%%% ENUME %%%%%%%%%% +%%%%% PROJECT C NO.61 %%%%% +% JAKUB TOMKIEWICZ 300183 % + +%%%%%%%% PROBLEM 1 %%%%%%%% + +% data +x = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]; +y = [-36.4986, -20.1300, -10.4370, -3.8635, -1.3503, 0.8879, 0.8176, 1.4830, 4.4024, 10.3910, 21.3003]; + +% plot graphs of polynomials +solveAndCreateFigure(x,y,2); +solveAndCreateFigure(x,y,4); +solveAndCreateFigure(x,y,6); +solveAndCreateFigure(x,y,8); +solveAndCreateFigure(x,y,10); + +% show errors and condition nr for all +showDataForAllDegrees(x,y); + +%%%%%%%% PROBLEM 2 %%%%%%%% + +%%%%%% PART A %%%%%% + +% Solution curves % + +plotSolutionCurves(1,1); % optimal RK4 +plotSolutionCurves(1,0); % optimal P5EC5E + +plotSolutionCurves(0,1); % larger RK4 +plotSolutionCurves(0,0); % larger P5EC5E + +plotOptimalVsLarger(1); % RK4 +plotOptimalVsLarger(0); % P5EC5E + +% Solution versus time % + +%RK4 +plotSolutionTime(1,1); % x1 +plotSolutionTime(1,0); % x2 + +%P5EC5E +plotSolutionTime(0,1); % x1 +plotSolutionTime(0,0); % x2 + +%%%%%% PART B %%%%%% + +[x1,x2,t,h,error1,error2] = RK4autoAdjust(0.0001,0,20,1e-9,1e-9); + +figure(1); +plot(x1,x2); +title("x1 vs x2"); + +figure(2); +plot(t,h); +title("Step size vs time"); + +figure(3); +plot(t,error1); +title("error for x1 vs time"); + +figure(4); +plot(t,error2); +title("error for x2 vs time"); + +figure(5); +hold on; +plot(t,x1); +plot(t,x2); +hold off; +title("problem solution vs time"); +legend("x1","x2",'Location','southoutside'); + +%%%%%%%% FUNCTIONS %%%%%%%% + +% PROBLEM 1 algorithm for the QR factorization, same as in Project A +function [Q,R] = qrmgs(A) + + [m n] = size(A); + + Q = zeros(m,n); + R = zeros(n,n); + d = zeros(1,n); + + % factorization with orthogonal/not orthogonoal columns of Q + for i=1:n + Q(:,i) = A(:,i); + R(i,i) = 1; + d(i) = Q(:,i)'*Q(:,i); + + for j=i+1:n + R(i,j) = (Q(:,i)'*A(:,j))/d(i); + A(:,j) = A(:,j)-R(i,j)*Q(:,i); + end + end + + % column normalization + for i=1:n + dd = norm(Q(:,i)); + Q(:,i) = Q(:,i)/dd; + R(i,i:n) = R(i,i:n)*dd; + end +end + +% PROBLEM 1 create matrix known as Grams matrix +function [A,b] = createGramsMatrix(x,y,degree) + + degree = degree+1; + + % matrix A and vector b filled with zeros + A = zeros(degree, degree); + b = zeros(degree, 1); + + n = length(x); + + % i and j cant start from 0 as array indices has to be positive + + % matrix A + for i=1:degree + for j=1:degree + for k=1:n % sum + A(i,j) = A(i, j) + (x(1, k)^(i+j-1-1)); % auxiliary definition + end + end + end + + % vector b + for i=1:degree + for k=1:n % sum + b(i, 1) = b(i, 1) + (y(k)*(x(k)^(i-1))); % auxiliary definition + end + end +end + +% PROBLEM 1 solve equations, most code taken from Project A +function [error, conditionNr, C] = solveEquation(A,b) + + [Q, R] = qrmgs(A); % qr factorization + + n = size(A,1); + C = zeros(n,1); + + % connect matrix with vector + D = Q' * b; + + % starting from end until 1 + for i=n:-1:1 % back-substitution phase + C(i) = D(i)/R(i,i); + D(1:i-1) = D(1:i-1) - (C(i)*R(1:i-1,i)); + end + + % residuum + residuum = A*C - b; + + % norm of residuum + error = norm(residuum); + + % conditionNr + conditionNr = cond(A); +end + +% PROBLEM 1 solve equation and print figure +function solveAndCreateFigure(x,y,degree) + + % create Gram's matrix and solve equation + [A,b] = createGramsMatrix(x,y,degree); + + % we need only C + [~,~,C] = solveEquation(A,b); + + disp(C); + %C2 = A\b; % make sure if answer is same as buildin function + %disp(C2); + + % plot x y on graph + figure(degree); + plot(x,y, 'r*'); + hold on; + + % functions various from degree + if(degree == 2) + f = @(x)C(3)*x^2 + C(2)*x + C(1); + end + + if(degree == 4) + f = @(x)C(5)*x^4 + C(4)*x^3 + C(3)*x^2 + C(2)*x + C(1); + end + + if(degree == 6) + f = @(x)C(7)*x^6 + C(6)*x^5 + C(5)*x^4 + C(4)*x^3 + C(3)*x^2 + C(2)*x + C(1); + end + + if(degree == 8) + f = @(x)C(9)*x^8 + C(8)*x^7 + C(7)*x^6 + C(6)*x^5 + C(5)*x^4 + C(4)*x^3 + C(3)*x^2 + C(2)*x + C(1); + end + + if(degree == 10) + f = @(x)C(11)*x^10 + C(10)*x^9 + C(9)*x^8 + C(8)*x^7 + C(7)*x^6 + C(6)*x^5 + C(5)*x^4 + C(4)*x^3 + C(3)*x^2 + C(2)*x + C(1); + end + + % plotting function + fplot(f,[-5 5],'k'); % from -5 to 5 + grid on; + hold off; + title("Polynomial of degree " + degree); + % put legend in less conflict area + legend("Samples","Polynomial",'Location','Best'); + +end + +% PROBLEM 1 show error and condition nr for all degrees +function showDataForAllDegrees(x,y) + + % from degree 1 to degree 10 + for degree=1:1:10 + % create + [A,b] = createGramsMatrix(x,y,degree); + %disp(A); + %disp(b); + % solve + [error,conditionNr,~] = solveEquation(A,b); + disp("Degree "+ degree + " Error " + error + " ConditionNr " + conditionNr); + end + +end + +% PROBLEM 2 calculate Runge Kutta 4th order +function [y1,y2,x] = RK4(h, beginning, ending) + + x = beginning:h:ending; + + % prelocate with zeros + y1 = zeros(1,length(x)); + y2 = zeros(1,length(x)); + + % initial conditions + y1(1) = -0.4; + y2(1) = -0.3; + + % motion of a point + f_1 = @(t, x1, x2) x2 + x1*(0.5 - x1^2 - x2^2); + f_2 = @(t, x1, x2) -x1 + x2*(0.5 - x1^2 - x2^2); + + % loop + for i=1:(length(x)-1) + %k1 + k1_1 = f_1( x(i), y1(i), y2(i) ); + k1_2 = f_2( x(i), y1(i), y2(i) ); + + %k2 + k2_1 = f_1( x(i)+0.5*h, y1(i)+0.5*h, y2(i)+0.5*h*k1_1 ); + k2_2 = f_2( x(i)+0.5*h, y1(i)+0.5*h, y2(i)+0.5*h*k1_2 ); + + %k3 + k3_1 = f_1( x(i)+0.5*h, y1(i)+0.5*h, y2(i)+0.5*h*k2_1 ); + k3_2 = f_2( x(i)+0.5*h, y1(i)+0.5*h, y2(i)+0.5*h*k2_2 ); + + %k4 + k4_1 = f_1( x(i)+h, y1(i)+h, y2(i) + h*k3_1 ); + k4_2 = f_2( x(i)+h, y1(i)+h, y2(i) + h*k3_2 ); + + %y_(n+1) + y1(i+1) = y1(i) + (1/6)*(k1_1 + 2*k2_1 + 2*k3_1 + k4_1)*h; + y2(i+1) = y2(i) + (1/6)*(k1_2 + 2*k2_2 + 2*k3_2 + k4_2)*h; + end +end + +% PROBLEM 2 calculate Adams method P5EC5E +function [y1,y2,x] = P5EC5E(h, beginning, ending) + + %P5EC5E method so k=5 + k = 5; + + % values taken from book, page 177 + betaExplicit = [1901/720, -2774/720, 2616/720, -1274/720, 251/720]; + betaImplicit = [475/1440, 1427/1440, -789/1440, 482/1440, -173/1440, 27/1440]; + + % motion of a point + f_1 = @(t, x1, x2) x2 + x1*(0.5 - x1^2 - x2^2); + f_2 = @(t, x1, x2) -x1 + x2*(0.5 - x1^2 - x2^2); + + % perform RK4 for first 5 iterations + [y1,y2,x] = RK4(h, beginning, (k*h)-beginning); + + % start the loop from 6th iteration and do untill rounded integer value + % of (end of interval-begin of interval)/(step size) + for i=(k+1):(ceil(ending-beginning)/h) + + % at each iteraion x is bigger for h value + x(i+1) = x(i) + h; + + %calculate sum of beta and function in order to have P + sumP_1 = 0; + sumP_2 = 0; + for j=1:k + sumP_1 = sumP_1 + betaExplicit(j)*f_1( x(i-j), y1(i-j), y2(i-j) ); + sumP_2 = sumP_2 + betaExplicit(j)*f_2( x(i-j), y1(i-j), y2(i-j) ); + end + + %P prediction + y1(i+1) = y1(i) + h*sumP_1; + y2(i+1) = y2(i) + h*sumP_2; + + %E evaluation + f1 = f_1( x(i), y1(i+1), y2(i+1) ); + f2 = f_2( x(i), y1(i+1), y2(i+1) ); + + %calculate sum of beta and function in order to have C + sumC_1 = 0; + sumC_2 = 0; + for j=1:k + sumC_1 = sumC_1 + betaImplicit(j)*f_1( x(i-j), y1(i-j), y2(i-j) ); + sumC_2 = sumC_2 + betaImplicit(j)*f_2( x(i-j), y1(i-j), y2(i-j) ); + end + + %C correction + y1(i+1) = y1(i) + h*sumC_1 + h*betaImplicit(1)*f1; + y2(i+1) = y2(i) + h*sumC_2 + h*betaImplicit(1)*f2; + + %E evaluation + f1 = f_1( x(i), y1(i+1), y2(i+1) ); + f2 = f_2( x(i), y1(i+1), y2(i+1) ); + end +end + +% PROBLEM 2 plot solution curves +function plotSolutionCurves(optimal,rk4) + if(optimal == 1) % optimal step size + if(rk4 == 1) % use RK4 + [x1,x2] = RK4(0.004,0,20); + + % ode45( functions, interval, initial_conditions ) + [~,y_ode45] = ode45(@(t,x) [x(2) + x(1)*(0.5 - x(1)^2 - x(2)^2); -x(1) + x(2)*(0.5 - x(1)^2 - x(2)^2)], [0,20], [-0.4,-0.3]); + % t is a time vector, y is a vector solutions of a function + + figure(11); + hold on; + + plot(x1,x2); + plot(y_ode45(:,1),y_ode45(:,2)); + legend("RK4","ODE45",'Location','Best'); + title("RK4 vs ODE45 optimal step-size"); + hold off; + else % use P5EC5E + [x1,x2] = P5EC5E(0.001,0,20); + + % ode45( functions, interval, initial_conditions ) + [~,y_ode45] = ode45(@(t,x) [x(2) + x(1)*(0.5 - x(1)^2 - x(2)^2); -x(1) + x(2)*(0.5 - x(1)^2 - x(2)^2)], [0,20], [-0.4,-0.3]); + % t is a time vector, y is a vector solutions of a function + + figure(12); + hold on; + + plot(x1,x2); + plot(y_ode45(:,1),y_ode45(:,2)); + legend("P5EC5E","ODE45",'Location','Best'); + title("P5EC5E vs ODE45 optimal step-size"); + hold off; + end + else % larger step size + if(rk4 == 1) % use RK4 + [x1,x2] = RK4(0.04,0,20); + + % ode45( functions, interval, initial_conditions ) + [~,y_ode45] = ode45(@(t,x) [x(2) + x(1)*(0.5 - x(1)^2 - x(2)^2); -x(1) + x(2)*(0.5 - x(1)^2 - x(2)^2)], [0,20], [-0.4,-0.3]); + % t is a time vector, y is a vector solutions of a function + + figure(13); + hold on; + + plot(x1,x2); + plot(y_ode45(:,1),y_ode45(:,2)); + legend("RK4","ODE45",'Location','Best'); + title("RK4 vs ODE45 larger step-size"); + hold off; + else % use P5EC5E + [x1,x2] = P5EC5E(0.03,0,20); + + % ode45( functions, interval, initial_conditions ) + [~,y_ode45] = ode45(@(t,x) [x(2) + x(1)*(0.5 - x(1)^2 - x(2)^2); -x(1) + x(2)*(0.5 - x(1)^2 - x(2)^2)], [0,20], [-0.4,-0.3]); + % t is a time vector, y is a vector solutions of a function + + figure(14); + hold on; + + plot(x1,x2); + plot(y_ode45(:,1),y_ode45(:,2)); + legend("P5EC5E","ODE45",'Location','Best'); + title("P5EC5E vs ODE45 larger step-size"); + hold off; + end + end +end + +% PROBLEM 2 plot solutions vs time +function plotSolutionTime(rk4,x1) + if(rk4 == 1) % use RK4 + if(x1 == 1) % for x1 + [x1,~,t1] = RK4(0.004,0,20); + + [x1_2,~,t1_2] = RK4(0.04,0,20); + + % ode45( functions, interval, initial_conditions ) + [t_ode45,y_ode45] = ode45(@(t,x) [x(2) + x(1)*(0.5 - x(1)^2 - x(2)^2); -x(1) + x(2)*(0.5 - x(1)^2 - x(2)^2)], [0,20], [-0.4,-0.3]); + % t is a time vector, y is a vector solutions of a function + + figure(15); + hold on; + + plot(t1,x1); + plot(t1_2,x1_2); + plot(t_ode45,y_ode45(:,1)); + legend("optimal step-size","larger step-size","ODE45",'Location','southoutside'); + title("RK4 x1 solutions vs time"); + xlabel("t"); + ylabel("x1"); + hold off; + else % for x2 + [~,x2,t1] = RK4(0.004,0,20); + + [~,x2_2,t1_2] = RK4(0.04,0,20); + + % ode45( functions, interval, initial_conditions ) + [t_ode45,y_ode45] = ode45(@(t,x) [x(2) + x(1)*(0.5 - x(1)^2 - x(2)^2); -x(1) + x(2)*(0.5 - x(1)^2 - x(2)^2)], [0,20], [-0.4,-0.3]); + % t is a time vector, y is a vector solutions of a function + + figure(16); + hold on; + + plot(t1,x2); + plot(t1_2,x2_2); + plot(t_ode45,y_ode45(:,2)); + legend("optimal step-size","larger step-size","ODE45",'Location','southoutside'); + title("RK4 x2 solutions vs time"); + xlabel("t"); + ylabel("x2"); + hold off; + end + else % use P5EC5E + if(x1 == 1) % for x1 + [x1,~,t1] = P5EC5E(0.001,0,20); + + [x1_2,~,t1_2] = P5EC5E(0.03,0,20); + + % ode45( functions, interval, initial_conditions ) + [t_ode45,y_ode45] = ode45(@(t,x) [x(2) + x(1)*(0.5 - x(1)^2 - x(2)^2); -x(1) + x(2)*(0.5 - x(1)^2 - x(2)^2)], [0,20], [-0.4,-0.3]); + % t is a time vector, y is a vector solutions of a function + + figure(17); + hold on; + + plot(t1,x1); + plot(t1_2,x1_2); + plot(t_ode45,y_ode45(:,1)); + xlim([0 20]); + legend("optimal step-size","larger step-size","ODE45",'Location','southoutside'); + title("P5EC5E x1 solutions vs time"); + xlabel("t"); + ylabel("x1"); + hold off; + else % for x2 + [~,x2,t1] = P5EC5E(0.001,0,20); + + [~,x2_2,t1_2] = P5EC5E(0.03,0,20); + + % ode45( functions, interval, initial_conditions ) + [t_ode45,y_ode45] = ode45(@(t,x) [x(2) + x(1)*(0.5 - x(1)^2 - x(2)^2); -x(1) + x(2)*(0.5 - x(1)^2 - x(2)^2)], [0,20], [-0.4,-0.3]); + % t is a time vector, y is a vector solutions of a function + + figure(18); + hold on; + + plot(t1,x2); + plot(t1_2,x2_2); + plot(t_ode45,y_ode45(:,2)); + xlim([0 20]); + legend("optimal step-size","larger step-size","ODE45",'Location','southoutside'); + title("P5EC5E x2 solutions vs time"); + xlabel("t"); + ylabel("x2"); + hold off; + end + end +end + +% PROBLEM 2 plot optimal vs larger step-size +function plotOptimalVsLarger(rk4) + if(rk4 == 1) % RK4 + [x1,x2] = RK4(0.004,0,20); % optimal + [x1_2,x2_2] = RK4(0.04,0,20); % larger + + figure(19); + hold on; + + plot(x1,x2); + plot(x1_2,x2_2); + legend("optimal step-size","larger step-size",'Location','Best'); + title("RK4 optimal vs larger step-size"); + hold off; + else % P5EC5E + [x1,x2] = P5EC5E(0.001,0,20); % optimal + [x1_2,x2_2] = P5EC5E(0.03,0,20); % larger + + figure(20); + hold on; + + plot(x1,x2); + plot(x1_2,x2_2); + legend("optimal step-size","larger step-size",'Location','Best'); + title("P5EC5E optimal vs larger step-size"); + hold off; + end +end + +% PROBLEM 2 RK4 with adjustable initial variables for RK4autoAdjust +function [root1,root2,x] = RK4withInitialValues(h, beginning, ending, initial1, initial2) + + x = beginning:h:ending; + + % dont prealocate with zeros here + + % initial conditions + y1(1) = initial1; + y2(1) = initial2; + + % motion of a point + f_1 = @(t, x1, x2) x2 + x1*(0.5 - x1^2 - x2^2); + f_2 = @(t, x1, x2) -x1 + x2*(0.5 - x1^2 - x2^2); + + maxi = 1; + % loop + for i=1:(length(x)-1) + %k1 + k1_1 = f_1( x(i), y1(i), y2(i) ); + k1_2 = f_2( x(i), y1(i), y2(i) ); + + %k2 + k2_1 = f_1( x(i)+0.5*h, y1(i)+0.5*h, y2(i)+0.5*h*k1_1 ); + k2_2 = f_2( x(i)+0.5*h, y1(i)+0.5*h, y2(i)+0.5*h*k1_2 ); + + %k3 + k3_1 = f_1( x(i)+0.5*h, y1(i)+0.5*h, y2(i)+0.5*h*k2_1 ); + k3_2 = f_2( x(i)+0.5*h, y1(i)+0.5*h, y2(i)+0.5*h*k2_2 ); + + %k4 + k4_1 = f_1( x(i)+h, y1(i)+h, y2(i) + h*k3_1 ); + k4_2 = f_2( x(i)+h, y1(i)+h, y2(i) + h*k3_2 ); + + %y_(n+1) + y1(i+1) = y1(i) + (1/6)*(k1_1 + 2*k2_1 + 2*k3_1 + k4_1)*h; + y2(i+1) = y2(i) + (1/6)*(k1_2 + 2*k2_2 + 2*k3_2 + k4_2)*h; + + % maxi needed for the last element + maxi = i+1; + end + + % only the last element + root1 = y1(maxi); + root2 = y2(maxi); +end + +% PROBLEM 2 calculate RK4 with automatic step-size adjustement +function [y1,y2,x,auto_h,error_1,error_2] = RK4autoAdjust(h,beginning,ending,epsr,epsa) + + % store different values of h + auto_h(1) = h; + + % this time whole x cannot be defined at this point + x(1) = beginning; + + % initial conditions + y1(1) = -0.4; + y2(1) = -0.3; + + % 2^p and order p=4 so 2^4=16 + + % places for errors + error_1(1) = 0; + error_2(1) = 0; + + for i=1:100000 % more than enought, answer is achieved at 56756 iterations + + % after single step + [y1_single,y2_single,time_single] = RK4withInitialValues(auto_h(i),x(i),auto_h(i)+x(i),y1(i),y2(i)); + + + % after double step + [y1_double,y2_double,time_double] = RK4withInitialValues(auto_h(i)*0.5,x(i),auto_h(i)+x(i),y1(i),y2(i)); + + + % 7.22 from page 169 + y1(i+1) = y1_single + (16/15)*(y1_double-y1_single); %x1 + y2(i+1) = y2_single + (16/15)*(y2_double-y2_single); %x2 + + % error estimate for a double step (for RK) + delta_y1_double = ((y1_double - y1_single)/15); + error_1(i+1)= delta_y1_double; % store error + delta_y2_double = ((y2_double - y2_single)/15); + error_2(i+1)= delta_y2_double; % store error + + % accuracy parameters + eps1 = (abs(y1(i))*epsr)+epsa; %epsr=relative tolerance, epsa=absolute tolerance + eps2 = (abs(y2(i))*epsr)+epsa; + + % step-size correction + alpha_1 = (eps1/abs(delta_y1_double))^(1/5); % 7.33 page 173 + alpha_2 = (eps2/abs(delta_y2_double))^(1/5); + + % we need to take worst case scenerio, so only smallest alpha needs + % to be taken into accound (smallest alpha with the biggest + % denominator) + if(alpha_1 < alpha_2) + smallest_alpha = alpha_1; + else + smallest_alpha = alpha_2; + end + + % with the use of safety factor s=0.9 + auto_h(i+1) = 0.9*smallest_alpha*auto_h(i); + + x(i+1)=x(i); + + % from the block diagram on page 174 + if(0.9*smallest_alpha >=1) %s*alpha + if(x(i)+auto_h(i)>=ending) % meets b or after b + break; + else + x(i+1) = x(i) + auto_h(i); + % beta=5 taken from book, page 174 + minimum_temp = min(5*auto_h(i),auto_h(i+1)); + auto_h(i+1) = min(minimum_temp,ending-x(i)); + end + else + if(auto_h(i+1) < eps) % eps as h_min + disp("Error: No solution for assumed accuracy") + break; + end + end + end +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/README.md b/ENUME/references/metody_numeryczne/README.md new file mode 100644 index 00000000..e0605ee2 --- /dev/null +++ b/ENUME/references/metody_numeryczne/README.md @@ -0,0 +1,29 @@ +# Metody numeryczne + +## Zadanie 1 + +### 1. Dokładność maszynowa +Proszę napisać program wyznaczający dokładność maszynową komputera i wyznaczyć ją na swoim komputerze. + +### 2. Metoda Eliminacji Gaussa z częściowym wyborem elementu podstawowego +Proszę napisać program rozwiązujący układ n równań liniowych Ax=b wykorzystując metodę Eliminacji Gaussa z częściowym wyborem elementu podstawowego. Proszę zastosować program do rozwiązania układów dla liczby równań n = 10, 20, 40 80, 160, .... Liczbę tych równań zwiększać aż do momentu, gdy czas potrzebny na rozwiązanie układu daje staje się zbyt duży lub metoda zawodzi. + +### 3. Metoda Jacobiego +Proszę napisać program rozwiązujący układ n równań liniowych Ax=b wykorzystując metodę Jacobiego. + +## Zadanie 4 + +Ruch punktu jest opisany równaniami: + + +![equation](http://latex.codecogs.com/gif.latex?%5C%5C%20x_1%5E%7B%27%7D%3Dx_2+x_1%280.5-x_1%5E2-x_2%5E2%29%5C%5C%20%5C%5C%20x_2%5E%7B%27%7D%3D-x_1+x_2%280.5-x_1%5E2-x_2%5E2%29) + +Do rozwiązania zadania należy użyć zaimplementowanych przez siebie metod: +### 1. Rungego–Kutty czwartego rzędu (RK4) ze stałym krokiem. +Proszę przy tym wykonać tyle prób (kilka – kilkanaście), ile będzie potrzebnych do znalezienia takiego kroku, którego zmniejszanie nie wpływa znacząco na rozwiązanie, podczas gdy zwiększanie – już wpływa; + +### 2. Wielokrokowej predyktor–korektor Adamsa czwartego rzędu ze stałym krokiem +który należy dobrać w sposób podany dla metody z punktu 1; + +### 3. Rungego–Kutty czwartego rzędu (RK4) ze zmiennym krokiem. +W każdym kroku należy szacować błąd aproksymacji. diff --git a/ENUME/references/metody_numeryczne/zd1/1a.jpg b/ENUME/references/metody_numeryczne/zd1/1a.jpg new file mode 100644 index 00000000..939d96c4 Binary files /dev/null and b/ENUME/references/metody_numeryczne/zd1/1a.jpg differ diff --git a/ENUME/references/metody_numeryczne/zd1/1b.jpg b/ENUME/references/metody_numeryczne/zd1/1b.jpg new file mode 100644 index 00000000..f3d3fcf6 Binary files /dev/null and b/ENUME/references/metody_numeryczne/zd1/1b.jpg differ diff --git a/ENUME/references/metody_numeryczne/zd1/blad_residuum.m b/ENUME/references/metody_numeryczne/zd1/blad_residuum.m new file mode 100644 index 00000000..c9ae2a4e --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/blad_residuum.m @@ -0,0 +1,5 @@ +function [r] = blad_residuum(r) + % norma druga residuum + r = r.^2; + r = sqrt(sum(r)); +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/czy_osobliwa.m b/ENUME/references/metody_numeryczne/zd1/czy_osobliwa.m new file mode 100644 index 00000000..1a1f3851 --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/czy_osobliwa.m @@ -0,0 +1,26 @@ +A = [1 2 3 4; + 7 7 7 8; + 9 10 11 12; + 13 15 15 16]; +n = 4; +M = zeros(n-1); +num = 0; + +for k=1:n + for i=2:n + for j=1:n + if j ~= k + num = num + 1; + M(i-1,num)=A(i,j); + end; + end; + num = 0; + end; + disp(M); + detM = M(1,1)*M(2,2)*M(3,3)+M(2,1)*M(3,2)*M(1,3)+M(3,1)*M(1,2)*M(2,3)-(M(3,1)*M(2,2)*M(1,3)+M(2,1)*M(1,2)*M(3,3)+M(1,1)*M(3,2)*M(2,3)); + %detMk(k)=detM; + detA=detA + (-1)^(k+1)*A(1,k)*detM; + disp(detM); + disp(det(M)); +end; +disp(detA); diff --git a/ENUME/references/metody_numeryczne/zd1/czy_rowne.m b/ENUME/references/metody_numeryczne/zd1/czy_rowne.m new file mode 100644 index 00000000..8909af2d --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/czy_rowne.m @@ -0,0 +1,8 @@ +function czy_rowne(X, Y) + tolerancja = 1e-6; + if abs(X-Y) < tolerancja + disp('Rwne!'); + else + disp('Nie rwne'); + end +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/dane1.m b/ENUME/references/metody_numeryczne/zd1/dane1.m new file mode 100644 index 00000000..4c217ccc --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/dane1.m @@ -0,0 +1,15 @@ +function [A,b,n] = dane1(n) + %n = 10; + A = zeros(n); + b = zeros(n,1); + %dane 1 + for j = 1:n %kolumna + for i = 1:n %wiersz + if i == j-1 || i == j+1 + A(i,j) = 3; + end + end + A(j,j) = 7; + b(j) = 2.5 + 0.5*i; + end +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/dane2.m b/ENUME/references/metody_numeryczne/zd1/dane2.m new file mode 100644 index 00000000..5475658f --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/dane2.m @@ -0,0 +1,15 @@ +function [A,b,n] = dane2(n) + %n = 10; + A = zeros(n); + b = zeros(n,1); + %dane 1 + for j = 1:n %kolumna + for i = 1:n %wiersz + if i ~= j + A(i,j) = 2*(i-j)+2; + end + end + b(j) = 2 + 0.4*i; + A(j,j) = 1/6; + end +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/dane3.m b/ENUME/references/metody_numeryczne/zd1/dane3.m new file mode 100644 index 00000000..ae3b4a7e --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/dane3.m @@ -0,0 +1,13 @@ +function [A,b,n] = dane3(n) + A = zeros(n); + b = zeros(n,1); + %dane 1 + for j = 1:n %kolumna + for i = 1:n %wiersz + if mod(i, 2) == 0 + b(i) = 7/(6*i); + end + A(i,j) = 1/(4*(i+j+1)); + end + end +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/dane_zd3.m b/ENUME/references/metody_numeryczne/zd1/dane_zd3.m new file mode 100644 index 00000000..ac7cded1 --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/dane_zd3.m @@ -0,0 +1,10 @@ +function [A,b,n] = dane_zd3() + A = [4 1 1 1; + 1 9 -5 2; + 2 3 -10 -3; + 1 2 -6 -14]; + + b = [3 ; 15 ; 6 ; 28]; + + n = 4; +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/danetest.m b/ENUME/references/metody_numeryczne/zd1/danetest.m new file mode 100644 index 00000000..76eb7ecd --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/danetest.m @@ -0,0 +1,32 @@ +A = [3 1 6 2; 2 2 1 3; 1 1 1 1; 1 2 3 4]; +b = [2; 7; 4; 1]; +n = 4; + +%A = [1 2; 3 4]; +%b = [2; 3]; +%n = 2; +%A = [4 -1 -0.2 2; + % -1 5 0 -2; + % 0.2 1 10 -1; + % 0 -2 -1 4]; +%b = [30; 0; -10; 5]; +%A1 = A; +%n = 4; + +%n = 10; +%A = zeros(n); +%b = zeros(n,1); +%dane 1 +%for j = 1:n %kolumna + % for i = 1:n %wiersz + % if i == j + % A(i,j) = 0; + % elseif i == j-1 || i == j+1 + % A(i,j) = 0; + % end + % b(i) = 2.5 + 0.5*i; + % end +%end +%end dane1 + +%zd3; \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/norma_1.m b/ENUME/references/metody_numeryczne/zd1/norma_1.m new file mode 100644 index 00000000..c85f2f6f --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/norma_1.m @@ -0,0 +1,7 @@ +function [norm] = norma_1(W, n) + s = 0; + for i = 1:n %wiersz + s = s + abs(W(i)); + end + norm = s; +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/norma_euklidesowa.m b/ENUME/references/metody_numeryczne/zd1/norma_euklidesowa.m new file mode 100644 index 00000000..78e74195 --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/norma_euklidesowa.m @@ -0,0 +1,7 @@ +function [norm] = norma_euklidesowa(W,n) + s = 0; + for i = 1:n %wiersz + s = s + (abs(W(i))).^2; + end + norm = sqrt(s); +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/oblicz.m b/ENUME/references/metody_numeryczne/zd1/oblicz.m new file mode 100644 index 00000000..c986875f --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/oblicz.m @@ -0,0 +1,28 @@ +function [X] = oblicz(U, b, n) + + X(n) = b(n)/U(n,n); + if (n <= 1) + return; + end + X(n-1) = (b(n-1) - U(n-1,n)*X(n))/U(n-1,n-1); + if (n <= 2) + T = zeros(n,1); + T(:) = X(:); + X = T; + return; + end + UX = zeros(n,1); + i = 2; + k = n-i; + while k >= 1 + UX(k) = UX(k) + U(k,:)*X(:); + X(k) = (b(k)-UX(k))/U(k,k); + i = i+1; + k = n-i; + end + + T = zeros(n,1); + T(:) = X(:); + X = T; + +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/wskaznik_uwarunkowania.m b/ENUME/references/metody_numeryczne/zd1/wskaznik_uwarunkowania.m new file mode 100644 index 00000000..2ad91fa4 --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/wskaznik_uwarunkowania.m @@ -0,0 +1,22 @@ +function [cond] = wskaznik_uwarunkowania(A, n) + B = A^-1; + max1 = intmin; + max2 = intmin; + s1 = 0; + s2 = 0; + for i = 1:n %wiersz + for j = 1:n + if abs(A(i,j)) > max1 + max1 = abs(A(i,j)); + end + if abs(B(i,j)) > max2 + max2 = abs(B(i,j)); + end + end + s1 = s1 + max1; + s2 = s2 + max2; + max1 = intmin; + max2 = intmin; + end + cond = s1 * s2; +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/wykres.m b/ENUME/references/metody_numeryczne/zd1/wykres.m new file mode 100644 index 00000000..ca904279 --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/wykres.m @@ -0,0 +1,67 @@ +function wykres(num, dane) + n = 10; + idx = 0; + + if dane == 1 + while idx < num + [A,b,n] = dane1(n); + try + [X,U, b] = zd2(A,b,n); + r = blad_residuum(b - U * X); + dane_n(idx) = n; + dane_r(idx) = r; + catch + if idx > 5 + break; + end + end + idx = idx+1; + n = n*2; + end + elseif dane == 2 + while idx < num + [A,b,n] = dane2(n); + try + [X,U, b] = zd2(A,b,n); + r = blad_residuum(b - U * X); + dane_n(idx) = n; + dane_r(idx) = r; + catch + if idx > 5 + break; + end + end + idx = idx+1; + n = n*2; + end + elseif dane == 3 + while idx < num + [A,b,n] = dane3(n); + disp(idx); + try + [X,U, b] = zd2(A,b,n); + r = blad_residuum(b - U * X); + dane_n(idx) = n; + dane_r(idx) = r; + catch + if idx > 5 + break; + end + end + idx = idx+1; + n = n*2; + end + else + error('Bledny index danych'); + end + try + plot(dane_n, dane_r,'b-'); + catch + return; + end + hold on; + plot(dane_n, dane_r, 'r*'); + xlabel('n') % x-axis label + ylabel('bd') % y-axis label + +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd1/zd1.m b/ENUME/references/metody_numeryczne/zd1/zd1.m new file mode 100644 index 00000000..01cac4bc --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/zd1.m @@ -0,0 +1,16 @@ +function epsi = zd1 + a = 1/2; + c = 1 + a; + t = 1; + + %zliczamy liczbe znakw mantysy na danym komputerze + %ledzimy kiedy z powodu niewystarczajcej liczby mantysy "c" bdzie rwna 1 + while c ~= 1 + t = t + 1; + a = a / 2; + c = 1 + a; + end + + epsi = 2^(-t+1); + disp(t); +end diff --git a/ENUME/references/metody_numeryczne/zd1/zd2.m b/ENUME/references/metody_numeryczne/zd1/zd2.m new file mode 100644 index 00000000..6add18af --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/zd2.m @@ -0,0 +1,58 @@ +function [X, U, b] = zd2(A, b, n) + if det(A) == 0 + warning('Macierz osobliwa. Nie da si wykona zadania'); + return; + end; + %wsk = wskaznik_uwarunkowania(A, n); + if cond(A) > 1e6 + %disp(wsk); + warning('Macierz le uwarunkowana'); + return; + end; + + Y = linsolve(A,b); + + L = eye(n); + U = A; + + for k = 1:n-1 + %odnalezienie max + max = intmin; + P = eye(n); + j = k; %kolumna + for i = j:n %wiersz + if U(i,j) > max + max = U(i,j); + ik = i; + end + end + %end odnalezienie max + + %macierz P + Ptemp = P; + Ptemp(k,:) = P(ik,:); + P(ik,:) = P(k,:); + P(k,:) = Ptemp(k,:); + %end macierz P + + %zamiana wierszy + b = P * b; + U = P * U; + L = P * L * P; + %end zamiana wierszy + + %macierz L, nowa macierz U i wektor b + for i = k+1:n + L(i,k) = U(i,k) / U(k,k); + U(i,:) = U(i,:) - L(i,k) * U(k,:); + b(i) = b(i) - L(i,k) * b(k); + end; + %end macierz L, nowa macierz U i wektor b + end + + [X] = oblicz(U, b, n); + %%% + czy_rowne(X, Y); +end + + diff --git a/ENUME/references/metody_numeryczne/zd1/zd3.m b/ENUME/references/metody_numeryczne/zd1/zd3.m new file mode 100644 index 00000000..f8578ade --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd1/zd3.m @@ -0,0 +1,67 @@ +function [X] = zd3(A, b, n) + if det(A) == 0 + warning('Macierz osobliwa. Nie da si wykona zadania'); + return; + end; + %wsk = wskaznik_uwarunkowania(A, n); + if cond(A) > 1e6 + %disp(wsk); + warning('Macierz le uwarunkowana'); + return; + end; + + A1 = A; + b1 = b; + + L = zeros(n); + U = zeros(n); + D = zeros(n); + N = zeros(n); + X = zeros(n,1); + + for j = 1:n %kolumna + for i = 1:n %wiersz + if i > j + L(i,j) = A(i,j); + elseif i < j + U(i,j) = A(i,j); + end + end + D(j,j) = A(j,j); + N(j,j) = 1/D(j,j); + end + + + M = -N*(L+U); + + %warunki zbierznosci + s = 0; + for i = 1:n + for j = 1:n + if i ~= j + s = s + abs(A(i,j)); + end + end + if s > abs(A(i,i)) + if 1 < max(abs(eig(M))) + error('cig nie jest zbieny'); + end; + end + s = 0; + end + %end warunki zbierznosci + + k = 1; + while k ~= 1000 + k = k + 1; + Xpop = X; + X = M * X + N * b; + if norma_1(X - Xpop,n) <= 1e-6 + if norma_euklidesowa(A*X-b,n) <= 1e-6 + break; + end + k = 1; + end; + end; + Y = linsolve(A1,b1); %do sprawdzenia + czy_rowne(X, Y); \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd4/f1.m b/ENUME/references/metody_numeryczne/zd4/f1.m new file mode 100644 index 00000000..a8170d64 --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd4/f1.m @@ -0,0 +1,3 @@ +function [y] = f1(x1, x2) + y = x2 + x1*(0.5 - x1^2 - x2^2); +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd4/f2.m b/ENUME/references/metody_numeryczne/zd4/f2.m new file mode 100644 index 00000000..e69b5418 --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd4/f2.m @@ -0,0 +1,3 @@ +function [y] = f2(x1, x2) + y = -x1 + x2*(0.5 - x1^2 - x2^2); +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd4/odefun.m b/ENUME/references/metody_numeryczne/zd4/odefun.m new file mode 100644 index 00000000..7a0612e3 --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd4/odefun.m @@ -0,0 +1,6 @@ +%[t,y] = ode45(@odefun, [0 4], [8 9]); %populacja pocztkowa ofiar: 10, drapienikw: 2 +%plot(t, y); % tym razem funkcja ode45 zwrcia argumenty wyjciowe i wykres nie zosta wygenerowany automatycznie + +function dydt = odefun(t,x) + dydt = [ x(2)+x(1)*(0.5-x(1)^2-x(2)^2) ; -x(1)+x(2)*(0.5-x(1)^2-x(2)^2) ]; +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd4/pk.m b/ENUME/references/metody_numeryczne/zd4/pk.m new file mode 100644 index 00000000..77c38821 --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd4/pk.m @@ -0,0 +1,55 @@ +function [ t, x1, x2 ] = pk( w1, w2, h) + p=20/h; + + x1(1)=w1; + x2(1)=w2; + + beta=[55/24,-59/24,37/24,-9/24]; + betag=[251/720,646/720,-264/720,106/720,-19/720]; + tic; + for i = 1:3 + k11 = f1(x1(i),x2(i)); + k12 = f2(x1(i),x2(i)); + k21 = f1(x1(i) + 0.5*h*k11, x2(i) + 0.5*h*k12); + k22 = f2(x1(i) + 0.5*h*k11, x2(i) + 0.5*h*k12); + k31 = f1(x1(i) + 0.5*h*k21, x2(i) + 0.5*h*k22); + k32 = f2(x1(i) + 0.5*h*k21, x2(i) + 0.5*h*k22); + k41 = f1(x1(i) + h*k31, x2(i) + h*k32); + k42 = f2(x1(i) + h*k31, x2(i) + h*k32); + x1(i+1) = x1(i) + (1/6)*h*(k11 + 2*k21 + 2*k31 + k41); + x2(i+1) = x2(i) + (1/6)*h*(k12 + 2*k22 + 2*k32 + k42); + + + end + + for i=5:(p+1) + suma1 = 0; + suma2 = 0; + for j =1:4 + suma1 = suma1 + beta(j)*f1(x1(i-j), x2(i-j)); + suma2 = suma2 + beta(j)*f2(x1(i-j), x2(i-j)); + end + x10 = x1(i-1) + h*suma1; + x20 = x2(i-1) + h*suma2; + ff1 = f1(x10,x20); + ff2 = f2(x10,x20); + suma1 = 0; + suma2 = 0; + for j =1:3 + suma1 = suma1 + betag(j+1)*f1(x1(i-j), x2(i-j)); + suma2 = suma2 + betag(j+1)*f2(x1(i-j), x2(i-j)); + end + x1(i) = x1(i-1) + h*suma1 + h*betag(1)*ff1; + x2(i) = x2(i-1) + h*suma2 + h*betag(1)*ff2; + + end + t = toc; + [~,y] = ode45(@odefun, [0 15], [w1 w2]); + + plot(x1,x2); + hold on; + plot(y(:,1),y(:,2)); + hold off; + + +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd4/rk4.m b/ENUME/references/metody_numeryczne/zd4/rk4.m new file mode 100644 index 00000000..0e73030b --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd4/rk4.m @@ -0,0 +1,36 @@ +function [ t, x1, x2] = rk4(w1, w2, h) + x1(1) = w1; + x2(1) = w2; + + p = 15/h; + + tic + for i=1:p + + k11 = f1(x1(i), x2(i)); + k21 = f2(x1(i), x2(i)); + + k12 = f1(x1(i)+1/2*h*k11 , x2(i)+1/2*k21*h); + k22 = f2(x1(i)+1/2*h*k11 , x2(i)+1/2*k21*h); + + k13 = f1(x1(i)+1/2*h*k12 , x2(i)+1/2*h*k22); + k23 = f2(x1(i)+1/2*h*k12 , x2(i)+1/2*h*k22); + + k14 = f1(x1(i)+h*k13 , x2(i)+h*k23); + k24 = f2(x1(i)+h*k13 , x2(i)+h*k23); + + x1(i+1) = x1(i) + 1/6*h*(k11 +2*k12 + 2*k13 + k14); + x2(i+1) = x2(i) + 1/6*h*(k21 +2*k22 + 2*k23 + k24); + + + end + t = toc; + [~,y] = ode45(@odefun, [0 15], [w1 w2]); + + plot(x1,x2); + hold on; + plot(y(:,1),y(:,2)); + hold off; + + +end \ No newline at end of file diff --git a/ENUME/references/metody_numeryczne/zd4/rk4z.m b/ENUME/references/metody_numeryczne/zd4/rk4z.m new file mode 100644 index 00000000..56d02a4f --- /dev/null +++ b/ENUME/references/metody_numeryczne/zd4/rk4z.m @@ -0,0 +1,76 @@ +function [ t, x1, x2] = rk4z(w1, w2, h) + x1(1) = w1; + x2(1) = w2; + a = 0; + x = a; + b = 20; + s = 0.9; + p = 4; + pp = 15/h; + + epsb = eps(1); + epsn = 10e-7; + + x1(1) = w1; + x2(1) = w2; + + + tic + for i=1:pp + + k11 = f1(x1(i), x2(i)); + k21 = f2(x1(i), x2(i)); + k12 = f1(x1(i)+1/2*h*k11 , x2(i)+1/2*k21*h); + k22 = f2(x1(i)+1/2*h*k11 , x2(i)+1/2*k21*h); + k13 = f1(x1(i)+1/2*h*k12 , x2(i)+1/2*h*k22); + k23 = f2(x1(i)+1/2*h*k12 , x2(i)+1/2*h*k22); + k14 = f1(x1(i)+h*k13 , x2(i)+h*k23); + k24 = f2(x1(i)+h*k13 , x2(i)+h*k23); + x1(i+1) = x1(i) + 1/6*h*(k11 +2*k12 + 2*k13 + k14); + x2(i+1) = x2(i) + 1/6*h*(k21 +2*k22 + 2*k23 + k24); + %krok? + x1h = [x1(i) 0 0]; + x2h = [x2(i) 0 0]; + for j=1:2 + k11 = f1(x1h(j),x2h(j)); + k21 = f2(x1h(j),x2h(j)); + k12 = f1(x1h(j)+0.25*h*k11, x2h(j)+0.25*h*k21); + k22 = f2(x1h(j)+0.25*h*k11, x2h(j)+0.25*h*k21); + k13 = f1(x1h(j)+0.25*h*k12, x2h(j)+0.25*h*k22); + k23 = f2(x1h(j)+0.25*h*k12, x2h(j)+0.25*h*k22); + k14 = f1(x1h(j)+k13*h*0.5, x2h(j)+k23*h*0.5); + k24 = f2(x1h(j)+k13*h*0.5, x2h(j)+k23*h*0.5); + x1h(j+1) = x1h(j) + (1/12)*(k11+2*k12+2*k13+k14)*h; + x2h(j+1) = x2h(j) + (1/12)*(k21+2*k22+2*k23+k24)*h; + end + dn_h1 = (x1(i+1) - x1h(j+1)) / (2^p - 1); + dn_h2 = (x2(i+1) - x2h(j+1)) / (2^p - 1); + eps_1 = abs(x1(i+1)) * epsn + epsb; + eps_2 = abs(x2(i+1)) * epsn + epsb; + alfa1 = (eps_1 / abs(dn_h1))^(1/(p+1)); + alfa2 = (eps_2 / abs(dn_h2))^(1/(p+1)); + if alfa1 > alfa2 + alfa = alfa2; + else + alfa = alfa1; + end + x = x+h; + if(s*alfa >= 1) + if(x >= b) + break; + else + h = min([s*alfa*h 5*h b-x]); + end + else + h = s * alfa * h; %dlugosc kroku dla nastepnej iteracji + end + end + t = toc; + [~,y] = ode45(@odefun, [0 15], [w1 w2]); + + plot(x1,x2); + hold on; + plot(y(:,1),y(:,2)); + hold off; + +end \ No newline at end of file diff --git a/ENUME/references/numerical-methods/LICENSE b/ENUME/references/numerical-methods/LICENSE new file mode 100644 index 00000000..3a07611e --- /dev/null +++ b/ENUME/references/numerical-methods/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Radu Stochitoiu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ENUME/references/numerical-methods/README.md b/ENUME/references/numerical-methods/README.md new file mode 100644 index 00000000..fb460ccb --- /dev/null +++ b/ENUME/references/numerical-methods/README.md @@ -0,0 +1,89 @@ +# numerical-methods +### Repository with the purpose of helping the ones in need on their path to achieving the computer science numerical wisdom. Contains MATLAB/Octave (and Python/C++ soon) implementations of the algorithms. + +### Implemented algorithms + +#### Nonlinear Equations + +| | Matlab | Python | C++ | +| --- | --- | --- | --- | +| Bisection method| :octocat: | | | +| Newton-Raphson method | :octocat: | | | +| Secant method | :octocat: | | | + +#### Gaussian methods + +| |Matlab|Python|C++| +|---|---|---|---| +|Gaussian elimination|:octocat:||| +|Gaussian elimination with Partial Pivoting|:octocat:||| +|Gaussian elimination with Scaled Partial Pivoting|:octocat:||| +|Gaussian elimination with Total Pivoting|:octocat:||| + +#### LU Factorization methods + +| |Matlab|Python|C++| +|---|---|---|---| +|Doolittle|:octocat:||| +|Crout|:octocat:||| +|Cholesky|:octocat:||| + +#### QR Factorization methods + +| |Matlab|Python|C++| +|---|---|---|---| +|Givens|:octocat:||| +|Gram-Schmidt|:octocat:||| +|Householder|:octocat:||| + +#### Iterative methods + +| |Matlab|Python|C++| +|---|---|---|---| +|Gauss-Seidel|:octocat:||| +|Jacobi|:octocat:||| +|Successive over-relaxation (SOR)|:octocat:||| + +#### Eigenvalues decomposition + +| |Matlab|Python|C++| +|---|---|---|---| +|Power method|:octocat:||| +|Inverse Power method|:octocat:||| +|Deflation method|:octocat:||| + +#### Ad-hoc algorithms + +| |Matlab|Python|C++| +|---|---|---|---| +|Diagonally dominance|:octocat:||| +|Positive definition|:octocat:||| +|Triangular matrices evaluation|:octocat:||| +|Gershgorin circles|:octocat:||| +|Gauss-Jordan Matrix Inverse|:octocat:||| + +### Convention + +- Before starting working on something, check the "Pull requests" tab to see if there isn't anyone who's already doing the same thing! +- Convention: The sources' names will start with a capital letter: "Crout", "Doolittle", "Householder", "Givens" etc. +- Comment your sources! +- Test your sources with several input cases: eye matrix, full matrix, triu matrix, tril matric, random matrix, small, big etc. +- Use notation tags: + - [NOTE] for related notes + - [USES] for sources which use other sources that are in a different folder to suggest that the user should first copy the dependencies (sources needed) in the same folder for testing +- before creating a Pull Request, it should look like this: [Householder](https://github.com/radusqrt/help-the-kids/blob/master/MN/Algoritmi/QR/Householder/Householder.m) + +------------------------------------------------------------------------------------------------- + +### Python coding style +https://github.com/google/yapf + +### Contributors + +This project exists thanks to all the people who contribute. + +------------------------------------------------------------------------------------------------- + +Other repositories that might be of interest: +1. [Algorithm design repository](https://github.com/radusqrt/algorithm-design) +2. [Computer Programming repository](https://github.com/radusqrt/computer-programming) diff --git a/ENUME/references/numerical-methods/cpp/.placeholder b/ENUME/references/numerical-methods/cpp/.placeholder new file mode 100644 index 00000000..e69de29b diff --git a/ENUME/references/numerical-methods/lab-instructions-2021.md b/ENUME/references/numerical-methods/lab-instructions-2021.md new file mode 100644 index 00000000..bf740270 --- /dev/null +++ b/ENUME/references/numerical-methods/lab-instructions-2021.md @@ -0,0 +1,61 @@ +# Instructiuni pentru laboratorul de MN + +## Instalare + +### 1. Instalare Octave + +Instructiuni [aici](https://wiki.octave.org/Octave_for_GNU/Linux). + +### 2. Instalare Anaconda + +Instructiuni [aici](https://docs.anaconda.com/anaconda/install/linux/). + +### 3. Creare ```conda env``` pentru laboratoarele de MN + +```conda create -n mn_env anaconda python=3.7``` + +### 4. Activare environment + +```conda activate mn_env``` + +### 5. Instalare kernel Octave pentru Jupyter Notebooks + +``` +conda config --add channels conda-forge +conda install octave_kernel +conda install texinfo +``` + +### 6. Instalare gnuplot pentru grafice in Octave + +``` +conda install -c bioconda gnuplot +``` + +## Folosire + +De fiecare data cand vreti sa lucrati la MN, porniti environment-ul special facut pentru asta. + +```conda activate mn_env``` + +Pentru a porni Jupyter Notebooks intr-un director anume in sistem, folositi comanda urmatoare: + +```jupyter notebook``` + +Nu uitati sa verificati la fiecare fisier in care lucrati ca in dreapta sus apare kernel-ul folosit ca fiind ```Octave```. + +### Tips & tricks + +1. In interiorul celulei puteti folosi ```Enter``` pentru newline; +2. Pentru a executa o celula apasati ```Shift + Enter```; +3. Ordinea de executie a celulelor se vede in stanga fiecarei celule; +4. Celulele pot fi de tip ```Code``` si ```Markdown``` pentru a scrie text in format [markdown](https://guides.github.com/features/mastering-markdown/). + +## Testare + +Dupa ce rezolvati exercitiile din ```assignment.py```: +1. executati celulele care contin functiile rezolvate; +2. executati celulele de test; sunt acelea care contin functii de tip ```assert```; +3. in cazul in care ati rezolvat corect cerintele, nu veti primi [niciun mesaj de eroare](https://drive.google.com/file/d/14qQODLiWBHEjE5D3MH_yXkblYuBUp0aJ/view?usp=sharing); +4. in cazul in care ati rezolvat incorect cerintele, veti primi [mesaje de erroare](https://drive.google.com/file/d/1tDaz_MovUvgZMWef8Jk8Eh8Y790g6I2Y/view?usp=sharing); +5. atentie ca puteti si sta intr-o bucla infinita daca celula nu termina executia niciodata si [apare steluta in stanga ei](https://drive.google.com/file/d/1tf8L0ulsslvqjM5Fet2v338kpUaO14EU/view?usp=sharing). diff --git a/ENUME/references/numerical-methods/lab_instructions_2020.md b/ENUME/references/numerical-methods/lab_instructions_2020.md new file mode 100644 index 00000000..4ee9840d --- /dev/null +++ b/ENUME/references/numerical-methods/lab_instructions_2020.md @@ -0,0 +1,59 @@ +# Instructiuni pentru laboratorul de MN + +## Alegere alias unic + +Intrati [aici](https://docs.google.com/spreadsheets/d/1ZNWChct5qWZcqeay0zMtXWjDHpMtmii-GMOXJwzJ4uY/edit?usp=sharing) si treceti-va numele + un alias pe care il voi folosi pentru autograding. Alias-ul trebuie sa contina doar litere mici si cifre si sa nu inceapa cu cifre. + +Documentul va fi blocat de pe 03.03.2020, deci nu va veti mai putea schimba alias-ul ales. + +## Instalare + +### 1. Instalare Octave + +Instructiuni [aici](https://wiki.octave.org/Octave_for_GNU/Linux). + +### 2. Instalare Anaconda + +Instructiuni [aici](https://docs.anaconda.com/anaconda/install/linux/). + +### 3. Creare ```conda env``` pentru laboratoarele de MN + +```conda create -n mn_env anaconda python=3.7``` + +### 4. Activare environment + +```conda activate mn_env``` + +### 5. Instalare kernel Octave pentru Jupyter Notebooks + +``` +conda config --add channels conda-forge +conda install octave_kernel +conda install texinfo +``` + +### 6. Instalare gnuplot pentru grafice in Octave + +``` +conda install -c bioconda gnuplot +``` + +## Folosire + +De fiecare data cand vreti sa lucrati la MN, porniti environment-ul special facut pentru asta. + +```conda activate mn_env``` + +Pentru a porni Jupyter Notebooks intr-un director anume in sistem, folositi comanda urmatoare: + +```jupyter notebook``` + +Nu uitati sa verificati la fiecare fisier in care lucrati ca in dreapta sus apare kernel-ul folosit ca fiind ```Octave```. + +## Trimitere + +Imi veti trimite pe adresa radu.stochitoiu@gmail.com cate un mail pentru fiecare laborator cu titlul ```[] [] Laborator MN``` si care va contine cate o arhiva cu urmatoarea structura de fisiere: + +```//assignment.ipynb``` + +Exemplu: pentru laboratorul LU, numele laboratorului este ```2-lu```, dupa cum se poate vedea in [drive](https://drive.google.com/open?id=1rgnXmFved0mU9ka_G09D5TKp4Gt_LzIc); titlul email-ului poate fi [2-lu] [radusqrt] Laborator MN. diff --git a/ENUME/references/numerical-methods/matlab/ad-hoc/GaussJordan.m b/ENUME/references/numerical-methods/matlab/ad-hoc/GaussJordan.m new file mode 100644 index 00000000..7bfac604 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/ad-hoc/GaussJordan.m @@ -0,0 +1,38 @@ +% computes reverse of matrix A +function [B, success] = GaussJordan(A) + [n n] = size(A); + B = eye(n); + % I assume A has an inverse matrix + success = 1; + + if det(A) == 0 + %A cannot be reversed + B = NaN; + success = 0; + return; + endif + + % merge the two matrices + Ae = [A B]; + for i = 1 : n + if Ae(i, i) == 0 + B = NaN; + success = 0; + return; + endif + + % make the pivot position equal to one (as in the eye matrix) + Ae(i, :) = Ae(i, :) / Ae(i, i); + + % form zeros above and under the main diagonal in the + % first half and calculate the inverse in the second half + for j = 1 : n + if i ~= j + Ae(j, :) = Ae(j, :) - Ae(i, :) * Ae(j, i); + endif + endfor + endfor + + % extract the inverse of matrix A from the augmented matrix + B = Ae(:, n + 1 : 2 * n); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/ad-hoc/IsDiagonallyDominant.m b/ENUME/references/numerical-methods/matlab/ad-hoc/IsDiagonallyDominant.m new file mode 100644 index 00000000..634f8d9d --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/ad-hoc/IsDiagonallyDominant.m @@ -0,0 +1,17 @@ +% checks if a matrix A is diagonally dominant +function is_diag_dom = IsDiagonallyDominant(A) + [n n] = size(A); + % I assume it is diagonally dominant + is_diag_dom = 1; + + for i = 1 : n + % calculate the sum of absolute value of + %the elements on line i, except A(i, i) + sum_of_line = sum(abs(A(i, :))) - abs(A(i, i)); + + if abs(A(i, i)) <= sum_of_line + is_diag_dom = 0; + break; + endif + endfor +endfunction diff --git a/ENUME/references/numerical-methods/matlab/ad-hoc/IsPositiveDefinite.m b/ENUME/references/numerical-methods/matlab/ad-hoc/IsPositiveDefinite.m new file mode 100644 index 00000000..38c6ff40 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/ad-hoc/IsPositiveDefinite.m @@ -0,0 +1,22 @@ +% checks if a matrix A is positive definite +function is_pos_def = IsPositiveDefinite(A) + [n n] = size(A); + % I assume it is positive definite + is_pos_def = 1; + + % A is positive definite if it is diagonally-dominant, + % A(i, i) > 0 and A is symmetrical + if IsDiagonallyDominant(A) == 1 && diag(A) > 0 && A == A' + return; + endif + + % A can be positive definite with Sylvester theorem + for i = 1 : n + B = A(1 : i, 1 : i); + if det(B) < 0 + % turns out it is not positive-definite + is_pos_def = 0; + break; + endif + endfor +endfunction diff --git a/ENUME/references/numerical-methods/matlab/ad-hoc/SIT.m b/ENUME/references/numerical-methods/matlab/ad-hoc/SIT.m new file mode 100644 index 00000000..e02d8afd --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/ad-hoc/SIT.m @@ -0,0 +1,26 @@ +function [x] = SIT(A, b) + % if the matrix is not lower triangular, we cannot solve the system + % triu(A, 1) returns the upper triangular portion without the main diagonal + % max(matrix) gets us a list of every column's max + % max(list) gets us the maximum from the list + % [NOTE] There is a function called "istril(A)" which returns 1 if A is a + % lower triangular matrix but it doesn't catch the e-16 errors + % which should be ignored + if max(max(abs(triu(A, 1)))) > 10^3 * eps + disp('The matrix A is not lower triangular!'); + x = NaN; + return; + endif + + n = length(b); + x = zeros(n, 1); + + % calculate x1 + x(1) = b(1) / A(1, 1); + + % calculate x(i) forwards + for i = 2 : n + sum_of_xs = A(i, 1 : (i - 1)) * x(1 : (i - 1), 1); + x(i) = (b(i) - sum_of_xs) / A(i, i); + endfor +endfunction diff --git a/ENUME/references/numerical-methods/matlab/ad-hoc/SST.m b/ENUME/references/numerical-methods/matlab/ad-hoc/SST.m new file mode 100644 index 00000000..cfadb48e --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/ad-hoc/SST.m @@ -0,0 +1,26 @@ +function [x] = SST(A, b) + % if the matrix is not upper triangular, we cannot solve the system + % tril(A, -1) gets us what is strictly under the main diagonal + % max(matrix) gets us a list of every column's max + % max(list) gets us the maximum from the list + % [NOTE] There is a function called "istriu(A)" which returns 1 if A is an + % upper triangular matrix but it doesn't catch the e-16 errors + % which should be ignored + if max(max(abs(tril(A, -1)))) > 10^3 * eps + disp('The matrix A is not upper triangular!'); + x = NaN; + return; + endif + + n = length(b); + x = zeros(n, 1); + + % calculate xn + x(n) = b(n) / A(n, n); + + % calculate x(i) backwards + for i = (n - 1): -1 : 1 + sum_of_xs = A(i, (i + 1) : n) * x((i + 1) : n, 1); + x(i) = (b(i) - sum_of_xs) / A(i, i); + endfor +endfunction diff --git a/ENUME/references/numerical-methods/matlab/ad-hoc/plotCircle.m b/ENUME/references/numerical-methods/matlab/ad-hoc/plotCircle.m new file mode 100644 index 00000000..6115a496 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/ad-hoc/plotCircle.m @@ -0,0 +1,12 @@ +function h = plotCircle(x, y, r) + % plot on the current focused figure + hold on + % theta makes a full circle from 0 to 2*pi radians + fraction = 50; + theta = 0 : pi / fraction : 2 * pi; + % build the x-axis and y-axis vectors of points + xs = r * cos(theta) + x; + ys = r * sin(theta) + y; + h = plot(xs, ys); + hold off +endfunction \ No newline at end of file diff --git a/ENUME/references/numerical-methods/matlab/ad-hoc/plotGershgorin.m b/ENUME/references/numerical-methods/matlab/ad-hoc/plotGershgorin.m new file mode 100644 index 00000000..845fdd1f --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/ad-hoc/plotGershgorin.m @@ -0,0 +1,23 @@ +% [USES] ad-hoc/plotCircle +function plotGershgorin(A) + % A must be a square matrix + n = length(A); + figure + + for i = 1 : n + sum_of_line = sum(abs(A(i, :))) - abs(A(i, i)); + left = -sum_of_line + A(i, i); + right = sum_of_line + A(i, i); + % calculate the center of the i-th circle on the x-axis + middle = (left + right) / 2; + % calculate the radius + radius = (right - left) / 2; + % plot the circle + plotCircle(middle, 0, radius); + endfor + + % plot the eigenvalues for proof of concept + hold on + plot(real(eig(A)), imag(eig(A)), 'x', 'markersize', 15) + hold off +endfunction diff --git a/ENUME/references/numerical-methods/matlab/ad-hoc/tests/test_plotGershgorin.m b/ENUME/references/numerical-methods/matlab/ad-hoc/tests/test_plotGershgorin.m new file mode 100644 index 00000000..d9bd957d --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/ad-hoc/tests/test_plotGershgorin.m @@ -0,0 +1,9 @@ +% [USES] ad-hoc/plotGershgorin +A = [5 1 2 17; 2 1 4 8; 2 1 34 4; 10 1 2 5]; +B = [-3 -1 2 14; 5 -4 3 1; 2 3 -4 1; 2 1 16 4]; + +eigA = eig(A) +plotGershgorin(A); + +eigB = eig(B) +plotGershgorin(B); diff --git a/ENUME/references/numerical-methods/matlab/eigenvalues/Deflation.m b/ENUME/references/numerical-methods/matlab/eigenvalues/Deflation.m new file mode 100644 index 00000000..e1a4c039 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/eigenvalues/Deflation.m @@ -0,0 +1,38 @@ +% [USES] Eigenvalues/PowerMethod, Eigenvalues/InversePowerMethod +function [L, V] = Deflation(A, max_iter, tol) + [n n] = size(A); + % initialize the eigenvalues' vector + L = zeros(1, n); + % initialize the eigenvectors' matrix + V = zeros(n); + % save a backup for A + C = A; + + for k = 1 : n - 1 + % get the current eigenvalue + [lam y] = PowerMethod(A, tol, max_iter); + L(k) = lam; + V(:, k) = y; + + % compute Wielandt deflation vector + x = A(k, :)' / (lam * y(k)); + + % remove the dominant eigenvalue and its + % eigenvector from the current matrix + B = A - lam * y * x'; + A = B; + endfor + + % get the last eigenvalue + [lam y] = PowerMethod(A, tol, max_iter); + L(n) = lam; + V(:, n) = y; + + % the eigenvectors are not very precise, so + % we use Inverse Power Method to find a better set of eigenvectors + % because we know the eigenvalues + for k = 1 : n + [lam y] = InversePowerMethod(C, tol, max_iter, L(k)); + V(:, n) = y; + endfor +endfunction diff --git a/ENUME/references/numerical-methods/matlab/eigenvalues/InversePowerMethod.m b/ENUME/references/numerical-methods/matlab/eigenvalues/InversePowerMethod.m new file mode 100644 index 00000000..48b551a7 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/eigenvalues/InversePowerMethod.m @@ -0,0 +1,32 @@ +% [USES] lu/Doolittle +function [lambda, y, step] = InversePowerMethod(A, tol, max_iter, miu) + % Check if it's a square matrix, otherwise there won't be any eigenvalues + [n m] = size(A); + if n ~= m + disp ('Not square matrix') + return; + endif + + y = rand(n, 1); + I = eye(n); + lambda = inf; + + for step = 1 : max_iter + % Solving (A - miu * I) * z = y system using Doolittle LU decomposition + [L U z] = Doolittle(A - miu * I, y); + y = z / norm(z); + + % Update the previous value with the newest one + lambda_old = lambda; + lambda = y' * A * y; + + % When the new values get close enough to the last values + % regarding the imposed tolerance "tol", we reached the solution + if abs((lambda - lambda_old) / lambda) < tol + return; + endif + + % Rayleigh quotient iteration in order to increase the convergence speed + miu = lambda; + endfor +endfunction diff --git a/ENUME/references/numerical-methods/matlab/eigenvalues/PowerMethod.m b/ENUME/references/numerical-methods/matlab/eigenvalues/PowerMethod.m new file mode 100644 index 00000000..c23f89fb --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/eigenvalues/PowerMethod.m @@ -0,0 +1,22 @@ +function [lambda, y, step] = PowerMethod(A, tol, max_iter) + % This function returns the largest eigenvalue of the matrix and the characteristic vector + [n n] = size(A); + % We randomly choose the vector y with values in the interval (0, 1) + y = rand(n, 1); + lambda = inf; + % iterate to the maximum number of iterations + for step = 1 : max_iter + z = A * y; + % update the eigenvector + y = z / norm(z); + % backup the last eigenvalue approximation + lambda_old = lambda; + % update the lambda value + lambda = y' * A * y; + % when the new values get close enough to the last values + % regarding the imposed tolerance "tol", we reached the solution + if abs((lambda - lambda_old) / lambda) < tol + break; + endif + endfor +endfunction \ No newline at end of file diff --git a/ENUME/references/numerical-methods/matlab/gaussian-methods/GEPartialPivoting.m b/ENUME/references/numerical-methods/matlab/gaussian-methods/GEPartialPivoting.m new file mode 100644 index 00000000..d0a6bcac --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/gaussian-methods/GEPartialPivoting.m @@ -0,0 +1,34 @@ +% [USES] ad-hoc/SST +function [x] = GEPartialPivoting(A, b) + n = size(A)(1); + % build the augmented matrix so we do less operations (tr. matrice extinsa) + Ae = [A b]; + + for p = 1 : n - 1 + % we find the absolute maximum from A(p:n, p) to use it as a pivot + [pivot, pivot_line] = max(abs(Ae(p : n, p))); + pivot_line = pivot_line + p - 1; + + % get the new pivot on diagonal position + temp = Ae(p, :); + Ae(p, :) = Ae(pivot_line, :); + Ae(pivot_line, :) = temp; + + % check if the pivot is 0, by comparing it to eps (a very small value) + if abs(Ae(p, p)) < eps + x = NaN; + return; + endif + + % gaussian elimination + for i = p + 1 : n + arg = Ae(i, p) / Ae(p, p); + Ae(i, :) = Ae(i, :) - arg * Ae(p, :); + endfor + endfor + + % solve the upper triangular system after separating A and b from Ae + A = Ae(:, 1 : n); + b = Ae(:, n + 1); + x = SST(A, b); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/gaussian-methods/GEScaledPartialPivoting.m b/ENUME/references/numerical-methods/matlab/gaussian-methods/GEScaledPartialPivoting.m new file mode 100644 index 00000000..b799a1fc --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/gaussian-methods/GEScaledPartialPivoting.m @@ -0,0 +1,37 @@ +% [USES] ad-hoc/SST +function [x] = GEScaledPartialPivoting(A, b) + n = size(A)(1); + % build the augmented matrix so we do less operations (tr. matrice extinsa) + Ae = [A b]; + + for p = 1 : n - 1 + % get the absolute maximum for each line in the s_factors column vector + s_factors = max(abs(A'))'; + % we find the absolute maximum scaled to its factor from A(p:n, p) to + % use it as a pivot + [pivot, pivot_line] = max(A(:, p) ./ s_factors); + pivot_line = pivot_line + p - 1; + + % get the new pivot on diagonal position + temp = Ae(p, :); + Ae(p, :) = Ae(pivot_line, :); + Ae(pivot_line, :) = temp; + + % check if the pivot is 0, by comparing it to eps (a very small value) + if abs(Ae(p, p)) < eps + x = NaN; + return; + endif + + % gaussian elimination + for i = p + 1 : n + arg = Ae(i, p) / Ae(p, p); + Ae(i, :) = Ae(i, :) - arg * Ae(p, :); + endfor + endfor + + % solve the upper triangular system after separating A and b from Ae + A = Ae(:, 1 : n); + b = Ae(:, n + 1); + x = SST(A, b); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/gaussian-methods/GETotalPivoting.m b/ENUME/references/numerical-methods/matlab/gaussian-methods/GETotalPivoting.m new file mode 100644 index 00000000..eda7338f --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/gaussian-methods/GETotalPivoting.m @@ -0,0 +1,51 @@ +% [USES] ad-hoc/SST +function [x] = GETotalPivoting(A, b) + n = size(A)(1); + % build the augmented matrix so we do less operations (tr. matrice extinsa) + Ae = [A b]; + % build the permutation vector + perm = [1:n]; + + for p = 1 : n - 1 + % we find the absolute maximum from A(p:n, p:n) to use it as a pivot + [pivot, pivot_line] = max(abs(Ae(p : n, p : n))); + [pivot, pivot_column] = max(pivot); + pivot_line = pivot_line + p - 1; + pivot_line = pivot_line(pivot_column); + pivot_column = pivot_column + p - 1; + + % get the new pivot on diagonal position + temp = Ae(p, :); + Ae(p, :) = Ae(pivot_line, :); + Ae(pivot_line, :) = temp; + + temp = Ae(:, p); + Ae(:, p) = Ae(:, pivot_column); + Ae(:, pivot_column) = temp; + + % update the permutation vector + temp = perm(p); + perm(p) = perm(pivot_column); + perm(pivot_column) = temp; + + % gaussian elimination + for i = p + 1 : n + % check if the pivot is 0, by comparing it to eps (a very small value) + if abs(A(p, p)) < eps + disp('One of the pivots is 0'); + x = NaN; + return; + endif + + arg = Ae(i, p) / Ae(p, p); + Ae(i, :) = Ae(i, :) - arg * Ae(p, :); + endfor + endfor + + % solve the upper triangular system after separating A and b from Ae + A = Ae(:, 1 : n); + b = Ae(:, n + 1); + x = SST(A, b); + % apply the permutation vector to the solution + x = x(perm); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/gaussian-methods/GaussianElimination.m b/ENUME/references/numerical-methods/matlab/gaussian-methods/GaussianElimination.m new file mode 100644 index 00000000..9df0df25 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/gaussian-methods/GaussianElimination.m @@ -0,0 +1,25 @@ +% [USES] ad-hoc/SST +function [x] = GaussianElimination(A, b) + n = size(A)(1); + % build the augmented matrix so we do less operations (tr. matrice extinsa) + Ae = [A b]; + + for p = 1 : n - 1 + % check if the pivot is 0, by comparing it to eps (a very small value) + if abs(Ae(p, p)) < eps + x = NaN; + return; + endif + + % gaussian elimination + for i = p + 1 : n + arg = Ae(i, p) / Ae(p, p); + Ae(i, :) = Ae(i, :) - arg * Ae(p, :); + endfor + endfor + + % solve the upper triangular system after separating A and b from Ae + A = Ae(:, 1 : n); + b = Ae(:, n + 1); + x = SST(A, b); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/interpolations/NevilleInterpolation.m b/ENUME/references/numerical-methods/matlab/interpolations/NevilleInterpolation.m new file mode 100644 index 00000000..0ce17eff --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/interpolations/NevilleInterpolation.m @@ -0,0 +1,31 @@ +% [USES] interpolations/NevillePoint +% Function that calculates the Neville interpolation polynomial for a vector +% of points (a, b) with a:xs, b:ys in "elements" points between the first of xs +% and the last of xs; it also plots the interpolation +function [xss yss] = NevilleInterpolation(xs, ys, elements) + n = length(xs); + % if "elements" is given, use it; otherwise, use the default value of + % linspace (usually 100) + if exist("elements", "var") == 1 + xss = linspace(xs(1), xs(n), elements); + else + xss = linspace(xs(1), xs(n)); + endif + + % create an empty vector to store the values of the interpolation in the + % xss' points + yss = []; + for i = 1:length(xss) + % Calculate the approximation of the function in xss(i) + yss = [yss NevillePoint(0, n - 1, xss(i), xs, ys)]; + endfor + + % open a new figure to merge two plots + figure + % plot the interpolated function + plot(xss, yss, "linewidth", 3) + % keep the chart in the figure to plot something else on top of it + hold on + % plot the initial points as circles + plot(xs, ys, 'o', 'linewidth', 3) +endfunction \ No newline at end of file diff --git a/ENUME/references/numerical-methods/matlab/interpolations/NevillePoint.m b/ENUME/references/numerical-methods/matlab/interpolations/NevillePoint.m new file mode 100644 index 00000000..751ed5ca --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/interpolations/NevillePoint.m @@ -0,0 +1,22 @@ +% Function that calculates the value of the Neville interpolation polynomial +% P_ij(x) for a vector of points (a, b) with a:xs, b:xs in the abscissa x; +% [NOTE] It doesn't use explicit caching (just the internal Octave caching +% system) +function [y] = NevillePoint(i, j, x, xs, ys) + % Base case: P_ii(x) = f(x_i) + % ys is 1-indexed, so we have to add one to the index + if i == j + y = ys(i + 1); + return; + endif + + % x_j - x_i + delta = xs(j + 1) - xs(i + 1); + % P(i, j - 1, x) + Pij_ = (xs(j + 1) - x) * NevillePoint(i, j - 1, x, xs, ys); + % P(i + 1, j, x) + Pi_j = (x - xs(i + 1)) * NevillePoint(i + 1, j, x, xs, ys); + + % P(i, j, x) + y = (Pij_ + Pi_j) / delta; +endfunction \ No newline at end of file diff --git a/ENUME/references/numerical-methods/matlab/interpolations/tests/test_NevilleInterpolation.m b/ENUME/references/numerical-methods/matlab/interpolations/tests/test_NevilleInterpolation.m new file mode 100644 index 00000000..cd1171d0 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/interpolations/tests/test_NevilleInterpolation.m @@ -0,0 +1,5 @@ +% [USES] interpolations/NevilleInterpolation + +xs = [1, 2, 3, 4, 5, 6, 7, 8]; +ys = sin(xs) + 2; +[xss yss] = NevilleInterpolation(xs, ys, 100); \ No newline at end of file diff --git a/ENUME/references/numerical-methods/matlab/iterative-methods/GaussSeidel.m b/ENUME/references/numerical-methods/matlab/iterative-methods/GaussSeidel.m new file mode 100644 index 00000000..57f02ab9 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/iterative-methods/GaussSeidel.m @@ -0,0 +1,40 @@ +function [x step] = GaussSeidel(A, b, x0, tol, max_iter) + % use this algorithm only if it converges + N = tril(A); + P = N - A; + Ggs = inv(N) * P; + % calculate the spectral radius of Ggs + sr = max(abs(eig(Ggs))); + % check if the algorithm converges + if (sr - 1) >= eps + x = NaN; + step = -1; + disp('Matrix does not converge'); + return; + endif + + n = length(b); + x = x0; + % iterate to the maximum number of iterations + for step = 1 : max_iter + % iterate through every x(i) + for i = 1 : n + % compute the sum using the updated values from the current step + new_values_sum = A(i, 1 : i - 1) * x(1 : i - 1); + + % compute the sum using the previous step values + old_values_sum = A(i, i + 1 : n) * x0(i + 1 : n); + + x(i) = b(i) - (old_values_sum + new_values_sum); + x(i) = x(i) / A(i, i); + endfor + + % when the new values get close enough to the last values + % regarding the imposed tolerance "tol", we reached the solution + if norm(x - x0) < tol + break; + endif + % update the last computed values with the new values + x0 = x; + endfor +endfunction diff --git a/ENUME/references/numerical-methods/matlab/iterative-methods/Jacobi.m b/ENUME/references/numerical-methods/matlab/iterative-methods/Jacobi.m new file mode 100644 index 00000000..8a0d9a1d --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/iterative-methods/Jacobi.m @@ -0,0 +1,40 @@ +function [x step] = Jacobi(A, b, x0, tol, max_iter) + % use this algorithm only if it converges + N = diag(diag(A)); + P = N - A; + Gj = inv(N) * P; + % calculate the spectral radius of Gj + sr = max(abs(eig(Gj))); + % check if the algorithm converges + if (sr - 1) >= eps + x = NaN; + step = -1; + disp('Matrix does not converge'); + return; + endif + + n = length(b); + x = x0; + % iterate to the maximum number of iterations + for step = 1 : max_iter + % iterate through every x(i) + for i = 1 : n + % val_sum represents the sum of the Jacobi algorithm and + % A(i, i) * x0(i) for which we calculate val_x so that we can + % substract it from val_sum + val_sum = A(i, :) * x0(:); + val_x = A(i, i) * x0(i); + + x(i) = b(i) - (val_sum - val_x); + x(i) = x(i) / A(i, i); + endfor + + % when the new values get close enough to the last values + % regarding the imposed tolerance "tol", we reached the solution + if norm(x - x0) < tol + break; + endif + % update the last computed values with the new values + x0 = x; + endfor +endfunction diff --git a/ENUME/references/numerical-methods/matlab/iterative-methods/SOR.m b/ENUME/references/numerical-methods/matlab/iterative-methods/SOR.m new file mode 100644 index 00000000..e5205cfc --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/iterative-methods/SOR.m @@ -0,0 +1,35 @@ +function [x step] = SOR(A, b, x0, tol, max_iter, w) + % sanity checks + if (w >= 2 || w <= 0) + disp('w should be inside (0, 2)'); + step = -1; + x = NaN; + return; + endif + + n = length(b); + x = x0; + % iterate to the maximum number of iterations + for step = 1 : max_iter + % iterate through every x(i) + for i = 1 : n + % compute the sum using the updated values from the current step + new_values_sum = A(i, 1 : i - 1) * x(1 : i - 1); + + % compute the sum using the previous step values + old_values_sum = A(i, i + 1 : n) * x0(i + 1 : n); + + x(i) = (b(i) - (old_values_sum + new_values_sum)) / A(i, i); + % here we introduce our relaxation parameter + x(i) = x(i) * w + x0(i) * (1 - w); + endfor + + % when the new values get close enough to the last values + % regarding the imposed tolerance "tol", we reached the solution + if norm(x - x0) < tol + break; + endif + % update the last computed values with the new values + x0 = x; + endfor +endfunction diff --git a/ENUME/references/numerical-methods/matlab/lu/Cholesky.m b/ENUME/references/numerical-methods/matlab/lu/Cholesky.m new file mode 100644 index 00000000..aececf78 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/lu/Cholesky.m @@ -0,0 +1,45 @@ +% [USES] ad-hoc/SST, ad-hoc/SIT +% calculates Cholesky factorization, A = L * L' +% A must be positive-definite +function [L U x] = Cholesky (A, b) + % get the size of the matrix A + [n n] = size(A); + % initialize the lower and upper matrix of size N + L = zeros(n); + U = zeros(n); + + % check if A is positive definite + if IsPositiveDefinite(A) == 0 || A ~= A' + L = NaN; + U = NaN; + x = NaN; + return; + endif + + % A is positive definite and A is also symmetric, yay! + % calculate the factorization, A = L * L' + L(1, 1) = sqrt(A(1, 1)); + % calculate only the elements situated under and on the main diagonal + for i = 1:n + for j = 1:i + sum_of_line = 0; + if i == j + sum_of_line = sum(L(i, 1:j - 1) .^ 2); + % calculate an element on the main diagonal + L(i, i) = sqrt(A(i, i) - sum_of_line); + else + sum_of_line = sum(L(i, 1: j - 1) .* L(j, 1: j - 1)); + % calculate the sum of the previous elements on the same line + L(i, j) = (A(i, j) - sum_of_line) / L(j, j); + endif + endfor + endfor + + U = L'; + % A * x = b; A = L * U; A = L * L' + % L * (L' * x) = b + % L' * x = y; + % L * y = b; + y = SIT(L, b); + x = SST(U, y); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/lu/Crout.m b/ENUME/references/numerical-methods/matlab/lu/Crout.m new file mode 100644 index 00000000..a7cb01be --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/lu/Crout.m @@ -0,0 +1,30 @@ +% [USES] ad-hoc/SST, ad-hoc/SIT +function [L, U, x] = Crout(A, b) + % U = eye(n) returns an n-by-n identity matrix with ones on the main + % diagonal and zeros elsewhere + % L = zeros(n) returns an n-by-n matrix of zeros + n = length(b); + L = zeros(n); + U = eye(n); + + % Decomposition of matrix into L and U + for i = 1 : n + % calculate the lower triangular matrix + sum_for_L = L(i : n, 1 : (i - 1)) * U(1 : (i - 1), i); + L(i : n, i) = A(i : n, i) - sum_for_L; + + % calculate the upper triangular matrix + sum_for_U = L(i, 1 : (i - 1)) * U(1 : (i - 1), (i + 1) : n); + U(i, (i + 1) : n) = (A(i, (i + 1) : n) - sum_for_U) / L(i, i); + endfor + + % A * x = b; A = L * U + % L * U * x = b; + % L * y = b => y (SIT) + % U * x = y => x (SST) + + % Solve the lower triangular system + y = SIT(L, b); + % Solve the upper triangular system + x = SST(U, y); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/lu/Doolittle.m b/ENUME/references/numerical-methods/matlab/lu/Doolittle.m new file mode 100644 index 00000000..b649a6de --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/lu/Doolittle.m @@ -0,0 +1,30 @@ +% [USES] ad-hoc/SST, ad-hoc/SIT +function [L, U, x] = Doolittle(A, b) + % L = eye(n) returns an identity matrix with ones on the main diagonal + % and zeros elsewhere + % U = zeros(n) returns an n-by-n matrix of zeros + n = length(A); + L = eye(n); + U = zeros(n); + + % Decomposition of matrix into L and U + for i = 1 : n + % calculate the upper triangular matrix + sum_for_U = L(i , 1 : (i - 1)) * U(1 : (i - 1), i : n); + U(i, i : n) = A(i, i : n) - sum_for_U; + + % calculate the lower triangular matrix + sum_for_L = L((i + 1) : n, 1 : (i - 1)) * U(1 : (i - 1), i); + L((i + 1) : n, i) = (A((i + 1) : n, i) - sum_for_L) / U(i, i); + endfor + + % A * x = b; A = L * U + % L * U * x = b; + % L * y = b => y (SIT) + % U * x = y => x (SST) + + % Solve the lower triangular system + y = SIT(L, b); + % Solve the upper triangular system + x = SST(U, y); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/lu/tests/cholesky_1.m b/ENUME/references/numerical-methods/matlab/lu/tests/cholesky_1.m new file mode 100644 index 00000000..58c1d2ba --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/lu/tests/cholesky_1.m @@ -0,0 +1,11 @@ +A = [25 15 -5; 15 18 0; -5 0 11]; +b = [0; 1; 2]; + +[L U x] = Cholesky(A, b); +disp(L); +disp(''); +disp(U); +disp(''); +disp(L * U); +disp(''); +disp(x); diff --git a/ENUME/references/numerical-methods/matlab/nonlinear-equations/BisectionMethod.m b/ENUME/references/numerical-methods/matlab/nonlinear-equations/BisectionMethod.m new file mode 100644 index 00000000..a3baeb52 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/nonlinear-equations/BisectionMethod.m @@ -0,0 +1,36 @@ +function [x, i] = BisectionMethod(f, a, b, tol, max_iter) + % solves the equation f(x) = 0 for the real variable x + % in i steps from the total number of iterations max_iter; + % the method requires a continuous function f; + % the function is defined on a given interval [a, b]; + % f(a) and f(b) have opposite signs; + for i = 1 : max_iter + % calculate the midpoint + x = (a + b) / 2; + fact = feval(f, a) * feval(f, x); + + % if the product is negative, the root is in + % between a and x + if fact < 0 + b = x; + % if the product is positive, the root is in + % between b and x + elseif fact > 0 + a = x; + % if the product is null, the root is found + else + return; + endif + + % if the root is unknown, the new midpoint is calculated + new_x = (a + b) / 2; + + % if the relative absolute error is lower than the given tolerance, + % then the bisection method reached convergence limit + err = abs((new_x - x) / new_x); + if err < tol + x = new_x; + return; + endif + endfor +endfunction diff --git a/ENUME/references/numerical-methods/matlab/nonlinear-equations/NewtonRaphsonMethodPolynomial.m b/ENUME/references/numerical-methods/matlab/nonlinear-equations/NewtonRaphsonMethodPolynomial.m new file mode 100644 index 00000000..a7b011b8 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/nonlinear-equations/NewtonRaphsonMethodPolynomial.m @@ -0,0 +1,33 @@ +function [x, i] = NewtonRaphsonMethodPolynomial(f, x0, tol, max_iter) + % solves f(x) = 0 by doing max_iter steps; + % the method requires one initial value (x0) + % which should be chosen close to the root; + % y = polyval(f, x) returns the value of a polynomial evaluated at x; + % y = polyder(f) returns the coefficients of the derivative of the polynomial + % whose coefficients are given by the vector p; + fd = polyder(f); + for i = 1 : max_iter + fx = polyval(f, x0); + fxd = polyval(fd, x0); + % calculate the value of the new approximation, xi, using the formula; + xi = x0 - fx / fxd; + % calculate the value of the polynomial evaluated at xi; + fxi = polyval(f, xi); + % check if xi is a root of the polynomial; + if abs(fxi) < eps + x = xi; + return; + endif + + epsilon = abs((xi - x0) / xi); + % stop if the method reached its convergence limit; + if epsilon < tol + x = xi; + return; + endif + + % update the last computed value; + x0 = xi; + endfor + disp('Maximum number of iterations reached'); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/nonlinear-equations/SecantMethod.m b/ENUME/references/numerical-methods/matlab/nonlinear-equations/SecantMethod.m new file mode 100644 index 00000000..e8e327b9 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/nonlinear-equations/SecantMethod.m @@ -0,0 +1,37 @@ +function [x, i] = SecantMethod(f, x0, x1, tol, max_iter) + % solves f(x) = 0 by doing max_iter steps of the secant method; + % the secant method requires two initial values, x0 and x1 + % which should ideally be chosen close to the root; + % y = feval(f, x) evaluates a function using its name or its handle + % and using the input arguments; + for i = 1 : max_iter + % function values: f(x0) and f(x1) + f0 = feval(f, x0); + f1 = feval(f, x1); + + % the root of function f is approximated using the formula + xi = x1 - f1 * (x1 - x0) / (f1 - f0); + + % calculate f(xi) + fxi = feval(f, xi); + % xi is the solution + if abs(fxi) < eps + x = xi; + return; + endif + + % calculate eps + epsilon = abs((xi - x1) / xi); + % stop if the secant method reached its convergence limit + if epsilon < tol + x = xi; + return; + endif + + % update the last two computed values + x0 = x1; + x1 = xi; + endfor + + disp('Maximum number of iterations reached'); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/qr/Givens.m b/ENUME/references/numerical-methods/matlab/qr/Givens.m new file mode 100644 index 00000000..4d8f1a23 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/qr/Givens.m @@ -0,0 +1,38 @@ +% [USES] ad-hoc/SST +function [Q, R, x] = Givens(A, b) + [m n] = size(A); + % Gt will be the final rotation matrix (the product of all the others) + Gt = eye(m); + % iterate through the elements below the main diagonal + for k = 1 : n-1 + for l = k+1 : m + % initialize the matrix for this step + G = eye(m); + + % calculate cos and sin + rho = sqrt(A(k, k)^2 + A(l, k)^2); + c = A(k, k) / rho; + s = -A(l, k) / rho; + + % modify the rotation matrix + G(k, k) = c; + G(k, l) = -s; + G(l, k) = s; + G(l, l) = c; + + % eliminate A(l, k) + A = G * A; + % add the matrix to the product + Gt = G * Gt; + endfor + endfor + % the orthogonal matrix is + % the transpose of the multiplication of all the rotation matrices + Q = Gt'; + % A becomes the upper triangular matrix + R = A; + + % Solve the upper triangular system + % A * x = b => Q * R * x = b => R * x = transpose(Q) * b + x = SST(R, Q' * b); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/qr/GramSchmidt.m b/ENUME/references/numerical-methods/matlab/qr/GramSchmidt.m new file mode 100644 index 00000000..7cb705f7 --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/qr/GramSchmidt.m @@ -0,0 +1,28 @@ +% [USES] ad-hoc/SST +function [Q, R, x] = GramSchmidt(A, b) + [m n] = size(A); + Q = []; + % iterate through every column for calculating the orthogonal matrix Q + for k = 1 : n + % initialize q with the current column from A and keep a copy of it + q = A(1 : m, k); + temp = q; + for j = 1 : k-1 + % calculate the scalar product + sp = sum(temp .* Q(:, j)); + % create orthogonal vectors + q = q - sp * Q(1 : m, j); + endfor + % normalize the vector + q = q / norm(q); + % add it to the matrix + Q = [Q q]; + endfor + + % the upper triangular matrix will be transpose(Q) * A + R = Q' * A; + + % solve the system + % A * x = b => Q * R * x = b => R * x = transpose(Q) * b + x = SST(R, Q' * b); +endfunction diff --git a/ENUME/references/numerical-methods/matlab/qr/Householder.m b/ENUME/references/numerical-methods/matlab/qr/Householder.m new file mode 100644 index 00000000..99d4fefd --- /dev/null +++ b/ENUME/references/numerical-methods/matlab/qr/Householder.m @@ -0,0 +1,32 @@ +% [USES] ad-hoc/SST +function [Q, R, x] = Householder(A, b) + n = length(b); + Q = eye(n); + + % iterate through every step for creating the upper triangular matrix + for p = 1 : (n - 1) + % initialize vp with zeros + vp = zeros(n, 1); + % fill vp from i + 1 to n with the values from the p-th column of A + vp((p + 1) : n) = A((p + 1) : n, p); + % Calculate sigma and the p-th element of vp + sigma_p = sign(A(p, p)) * norm(A(p : n, p)); + vp(p) = A(p, p) + sigma_p; + % calculate the p-th step reflector + Hp = eye(n) - 2 * vp * vp' / (vp' * vp); + % remove elements under the p-th pivot in A + A = Hp * A; + Q = Hp * Q; + endfor + + % Hn-1 * Hn-2 * ... * H2 * H1 * A = R + % current Q = Hn-1 * Hn-2 * ... * H1, but for A = Q * R + % => Q = inverse(current Q) = transpose(current Q) + Q = Q'; + % A became an upper triangular matrix + R = A; + + % Solve the upper triangular system + % A * x = b <=> Q * R * x = b <=> R * x = transpose(Q) * b + x = SST(R, Q' * b); +endfunction diff --git a/ENUME/references/numerical-methods/python/.placeholder b/ENUME/references/numerical-methods/python/.placeholder new file mode 100644 index 00000000..e69de29b diff --git a/ENUME/references/numerical-methods/python/ad-hoc/SST.py b/ENUME/references/numerical-methods/python/ad-hoc/SST.py new file mode 100644 index 00000000..40c96d92 --- /dev/null +++ b/ENUME/references/numerical-methods/python/ad-hoc/SST.py @@ -0,0 +1,19 @@ +import numpy as np +def SST(A, b): + # if the matrix is not upper triangular, we cannot solve the system + if not np.allclose(A, np.triu(A)): + print("The matrix A is not upper triangular!") + return np.nan + + n = len(b) + x = np.zeros((n, 1)) + + # calculate xn + x[n - 1, 0] = b[n - 1, 0] / A[n - 1, n - 1] + + # calculate x(i) backwards + for i in range(n - 2, -1, -1): + sum_of_xs = np.dot(A[i, (i + 1) : n], x[(i + 1) : n, 0]) + x[i, 0] = (b[i, 0] - sum_of_xs) / A[i, i] + + return x \ No newline at end of file diff --git a/ENUME/references/numerical-methods/regulament_intern.md b/ENUME/references/numerical-methods/regulament_intern.md new file mode 100644 index 00000000..a3850b5a --- /dev/null +++ b/ENUME/references/numerical-methods/regulament_intern.md @@ -0,0 +1,9 @@ +Ca totul sa mearga blana pentru restul semestrului, o sa va rog urmatoarele lucruri: + +- veniti la timp ca sa putem incepe la si 5 minute laboratorul; +- lasati feedback dupa fiecare laborator in formularele pe care le voi posta, probabil, in fiecare vineri; +- daca puteti, folositi-va laptopurile personale in laboratoare cand este nevoie pentru ca o sa va fie mai usor pe termen lung; daca nu, dati-mi un mesaj in privat si rezolvam; +- urmati instructiunile de [aici](https://github.com/radusqrt/numerical-methods/blob/master/lab_instructions.md +) pentru a nu avea probleme cu rezolvarea sau trimiterea laboratoarelor; +- respectati deadline-urile pe care le voi alege pentru trimiterea laboratoarelor; +- fiti curiosi si distrati-va. diff --git a/ENUME/references/szopinski-enume/.gitattributes b/ENUME/references/szopinski-enume/.gitattributes new file mode 100644 index 00000000..53ecfbb5 --- /dev/null +++ b/ENUME/references/szopinski-enume/.gitattributes @@ -0,0 +1,4 @@ +# Auto detect text files and perform LF normalization +* text=auto + +*.tex linguist-documentation diff --git a/ENUME/references/szopinski-enume/README.md b/ENUME/references/szopinski-enume/README.md new file mode 100644 index 00000000..855f67ee --- /dev/null +++ b/ENUME/references/szopinski-enume/README.md @@ -0,0 +1,17 @@ +# szopinski-enume + +My implementation of the ENUME project for Dr Marusak. This repository serves to document my journey in passing EiTI's most difficult subject and to aid the later generations in achieving the same. Young engineer, be aware that your legacy is built upon the sacrifice of those who perished here. + +## Running the MATLAB scripts + +Set `projX` as your working directory in MATLAB and type in the names of the scripts starting with `task`. This will generate text output in the command window as well as 2D plot figures. The figures will also be printed as PDFs in the `report` subdirectory, to be included in the project report. + +## Compiling the reports + +The reports are written in LaTeX. Navigate to `projX/report` (make sure it's your working directory) and execute the following command: + +``` +pdflatex projXreport.tex +``` + +Running the MATLAB scripts beforehand is required for figures to be included. diff --git a/ENUME/references/szopinski-enume/projA/backsubst.m b/ENUME/references/szopinski-enume/projA/backsubst.m new file mode 100644 index 00000000..7129b1b0 --- /dev/null +++ b/ENUME/references/szopinski-enume/projA/backsubst.m @@ -0,0 +1,20 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT A NUMBER 62 +% https://github.com/Lachcim/szopinski-enume + +% solves system with triangular matrix +function result = backsubst(eqsys) + for col = size(eqsys, 1):-1:1 + % normalize diagonal coefficients to 1 + eqsys(col, :) = eqsys(col, :) / eqsys(col, col); + + % eliminate factor from other rows + for row = (col - 1):-1:1 + reductor = eqsys(row, col) / eqsys(col, col); + eqsys(row, :) = eqsys(row, :) - eqsys(col, :) * reductor; + end + end + + % rightmost column is now the result + result = eqsys(:, size(eqsys, 2)); +end diff --git a/ENUME/references/szopinski-enume/projA/genmatrix.m b/ENUME/references/szopinski-enume/projA/genmatrix.m new file mode 100644 index 00000000..9b82abcf --- /dev/null +++ b/ENUME/references/szopinski-enume/projA/genmatrix.m @@ -0,0 +1,25 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT A NUMBER 62 +% https://github.com/Lachcim/szopinski-enume + +% generates coefficient matrix for task 2, sub-task a or b +function output = genmatrix(task, size) + % initialize empty matrix + output = zeros(size); + + if task == 'a' + % 4's for the diagonal, 1's around it + for i = 1:size + output(i, i) = 4; + if i ~= 1; output(i - 1, i) = 1; end + if i ~= size; output(i + 1, i) = 1; end + end + else + % formula for a_ij given explicitly + for i = 1:size + for j = 1:size + output(i, j) = 6 / (7 * (i + j + 1)); + end + end + end +end diff --git a/ENUME/references/szopinski-enume/projA/genvector.m b/ENUME/references/szopinski-enume/projA/genvector.m new file mode 100644 index 00000000..c63010b2 --- /dev/null +++ b/ENUME/references/szopinski-enume/projA/genvector.m @@ -0,0 +1,21 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT A NUMBER 62 +% https://github.com/Lachcim/szopinski-enume + +% generates the b vector for task 2, sub-task a or b +function output = genvector(task, size) + % initialize empty vector + output = zeros(size, 1); + + if task == 'a' + % formula for b_i given explicitly + for i = 1:size + output(i) = 4 + 0.3 * i; + end + else + % 1/(3i) for even positions only + for i = 2:2:size + output(i) = 1 / (3 * i); + end + end +end diff --git a/ENUME/references/szopinski-enume/projA/qrdecomp.m b/ENUME/references/szopinski-enume/projA/qrdecomp.m new file mode 100644 index 00000000..72d2e85b --- /dev/null +++ b/ENUME/references/szopinski-enume/projA/qrdecomp.m @@ -0,0 +1,42 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT A NUMBER 62 +% https://github.com/Lachcim/szopinski-enume + +% performs QR or QRdash decomposition of a matrix +function [Q, R, invqtq] = qrdecomp(A, dash) + % initialize empty matrices + Q = zeros(size(A)); + R = eye(size(A, 2)); + invqtq = zeros(size(A, 2)); + + % modified Gram-Schmidt, use each column to orthogonalize the ones in front of it + for col = 1:size(A, 2) + % by the time we've reached this column, it's already been orthogonalized + Q(:, col) = A(:, col); + + % calculate current column dot product for R + coldot = dot(Q(:, col), Q(:, col)); + invqtq(col, col) = 1 / coldot; + + % orthogonalize further columns + for next = (col + 1):size(A, 2) + % calculate R cell for this column pair + R(col, next) = dot(Q(:, col), A(:, next)) / coldot; + + % orthogonalize column + A(:, next) = A(:, next) - R(col, next) * Q(:, col); + end + end + + % don't normalize in QRdash mode + if nargin >= 2 && dash; return; end + + % normalize matrix + normalizer = zeros(size(Q)); + for col = 1:size(Q, 2) + colnorm = norm(Q(:, col)); + normalizer(col, col) = colnorm; + Q(:, col) = Q(:, col) / colnorm; + end + R = normalizer * R; +end diff --git a/ENUME/references/szopinski-enume/projA/report/projAreport.tex b/ENUME/references/szopinski-enume/projA/report/projAreport.tex new file mode 100644 index 00000000..283319b2 --- /dev/null +++ b/ENUME/references/szopinski-enume/projA/report/projAreport.tex @@ -0,0 +1,525 @@ +\documentclass{article} + +\usepackage{amsmath} +\usepackage{graphicx} +\usepackage{multicol} +\setlength{\parskip}{1em} + +\begin{document} + + \title{ENUME project report\\Project A: linear equation systems\\and matrix + eigenvalues} + \author{Michał Szopiński\\\\ + https://github.com/Lachcim/szopinski-enume\\ + Project number 62} + \date{November 12, 2020} + \maketitle + + \numberwithin{equation}{section} + + \setcounter{section}{-1} + \section{Abstract} + + This project explores the numerical methods of solving systems of linear + equations and finding eigenvalues of matrices. The following concepts are + discussed within this document: + + \begin{itemize} + \item Computing the machine epsilon of an environment + \item Solving linear equation systems using Gaussian elimination with + partial pivoting + \item Solving linear equation systems using the Jacobi and Gauss-Seidel + algorithms + \item Finding the eigenvalues of a symmetric matrix using the QR method + with and without shifts + \end{itemize} + + \newpage + + \section{Task 1: Computing the machine epsilon} + + \subsection{Overview} + + The goal of this task was to find the machine epsilon of the MATLAB + environment, i.e. the maximum relative error of a floating-point + representation of a number. + + \subsection{Implementation} + + The computation of the machine epsilon is based on the following two + observations: + + \begin{enumerate} + \item In binary computer environments, the epsilon is a negative power + of two. + \item The machine epsilon can also be expressed as: + \begin{equation} + eps = \min\{x \in M: fl(1 + x) > 1 \land x > 0\} + \end{equation} + i.e. the smallest representable number such that, when added to $1$, + has a floating point representation greater than $1$. + \end{enumerate} + + An arbitrary starting point, in this case $2^0$, can thus be chosen, and its + value can then be sequentially halved until the criterion $fl(1 + x) > 1$ is + no longer met. + + \subsection{Program output} + + \begin{verbatim} + Found epsilon is 2.2204e-16 + Epsilon is 2.2204e-16 + \end{verbatim} + + \subsection{Observations} + + An epsilon of $2.2204 \cdot 10^{-16} = 2^{-52}$ is indicative of a standard + double-precision IEEE 754 floating point binary representation. + + \newpage + + \section{Task 2: Solving systems of linear equations using Gaussian + elimination} + + \subsection{Overview} + + The task consisted of two subtasks, each specifying a different system + of equations to solve. The systems were to be solved using Gaussian + elimination with partial pivoting. The size of the system was sequentially + doubled until the computation time became prohibitive. The error of each + solution was to be noted. + + Additionally, for systems whose number of equations was equal to 10, + residual correction was to be applied and the solution was to be noted. + + The systems were given by: + \begin{align*} + &A_{ij}^{(a)} = + \begin{cases} + 4 & \text{for } i = j \\ + 1 & \text{for } i = j \pm 1 \\ + 0 & \text{otherwise} + \end{cases} + && + b_i^{(a)} = 4 + 0.3i + \\ + &A_{ij}^{(b)} = \frac{6}{7(i + j + 1)} + && + b_i^{(b)} = + \begin{cases} + \frac{1}{3i} & \text{for even } i\\ + 0 & \text{for odd } i + \end{cases} + \end{align*} + + \subsection{Implementation} + + Gaussian elimination is a process that takes a matrix describing a linear + equation system and returns its LU (lower-upper) decomposition, enabling the + system to be cheaply solved for any vector $b$. The triangular matrices $L$ + and $U$ can be supplemented with $b$ to find the solution vector $x$ through + a process called back-substitution. + + \subsubsection{LU decomposition of a matrix} + + The function \texttt{gausseli} takes an equation system and returns the $L$ + matrix, the $U$ matrix, the permutation matrix $P$ as well as a matrix + describing the entire system post-elimination, to be immediately handed to + back-substitution for the calculation of the result. + + The elimination itself is done by traveling along the diagonal of + \texttt{eqsys} and for each encountered cell, eliminating (reducing to $0$) + the coefficients directly below it. The program does so by multiplying the + current row by a constant and subtracting it from the rows beneath. + This constant, called \texttt{reductor} in the code, is given as the + ratio of the cell to be reduced and the current diagonal cell. The reductor + is then stored in the $L$ matrix. + + \subsubsection{Partial pivoting} + + The above algorithm alone is prone to errors when a value on the diagonal is + equal to $0$ and the reductor cannot be constructed. For this reason, + partial pivoting is added. + + For each cell on the diagonal, the program looks at the cells beneath it and + finds the one with the greatest absolute value. If it exceeds the absolute + value of the current cell, the corresponding two rows are swapped. This + ensures that the divisor making up the reductor is as far from zero as + possible. + + Because the input matrix changes while being decomposed, a permutation + matrix $P$ is introduced to enable its recomposition from $L$ and $U$, + satisfying the equation: + \begin{equation} + LU = PA + \end{equation} + + Finally, the matrix $L$ is also permuted to reflect changes in the layout + of the system. + + \subsubsection{Back-substitution} + + A triangular matrix supplied with a constant vector $b$ can be easily solved + by traveling along its diagonal and eliminating the factors directly above + the visited cell. In the end, the matrix is transformed into an identity + matrix and the vector alongside it is transformed into $x$. + + \subsubsection{Residual correction} + + Residual correction is a method of improving the accuracy of the results + obtained from Gaussian elimination. By reusing the already obrained matrices + $L$, $U$ and $P$, the system is solved once again, this time with $b$ + replaced with the vector of errors of the solution. The resulting vector + $\delta x$ is then subtracted from the previous solution. This procedure may + be repeated as needed. + + \subsection{Program output} + + \subsubsection{Error plots} + + \includegraphics[width=\textwidth]{aerror} + \includegraphics[width=\textwidth]{berror} + + \subsubsection{Solutions for $n = 10$} + + \begin{multicols}{2} + \begin{verbatim} + Solution to subtask a: + + i x_i error + 1 0.8953 0 + 2 0.71881 -8.8818e-16 + 3 0.82946 0 + 4 0.86335 0 + 5 0.91714 0 + 6 0.9681 0 + 7 1.0105 0 + 8 1.0901 0 + 9 1.0293 0 + 10 1.4927 -8.8818e-16 + + Error: 1.2561e-15 + + With residual correction: + + i x_i error + 1 0.8953 0 + 2 0.71881 0 + 3 0.82946 0 + 4 0.86335 0 + 5 0.91714 0 + 6 0.9681 0 + 7 1.0105 0 + 8 1.0901 0 + 9 1.0293 0 + 10 1.4927 0 + + Error: 0 + \end{verbatim} + \begin{verbatim} + Solution to subtask b: + + i x_i error + 1 -2.7253e+08 7.6294e-06 + 2 9.5052e+09 -6.3578e-05 + 3 -1.2041e+11 -2.2888e-05 + 4 7.6994e+11 -8.138e-05 + 5 -2.8351e+12 5.3406e-05 + 6 6.3794e+12 -5.171e-05 + 7 -8.9152e+12 -1.5259e-05 + 8 7.5508e+12 -2.5431e-05 + 9 -3.5489e+12 8.3923e-05 + 10 7.1024e+11 7.1208e-06 + + Error: 0.00015731 + + With residual correction: + + i x_i error + 1 -2.7292e+08 -5.3406e-05 + 2 9.5191e+09 -7.8837e-05 + 3 -1.2059e+11 -6.8665e-05 + 4 7.7108e+11 -7.3751e-05 + 5 -2.8392e+12 -6.8665e-05 + 6 6.3888e+12 -7.4599e-05 + 7 -8.9283e+12 -8.7738e-05 + 8 7.562e+12 1.2716e-05 + 9 -3.5542e+12 -5.722e-05 + 10 7.1129e+11 3.3061e-06 + + Error: 0.00020161 + \end{verbatim} + \end{multicols} + + \newpage + \subsection{Observations} + + Matrices from both subtasks a and b lent themselves nicely to being solved + using Gaussian elimination. Their absolute errors, when divided by the + solutions themselves, resulted in very small relative errors, nearing the + machine epsilon. + + The computation time became prohibitive beyond $n = 320$, showing that + Gaussian elimination is an effective method of solving large systems + of equations. + + Residual correction was very effective for the matrix from subtask a, + reducing the error to a perfect $0$. For subtask b, on the other hand, no + matter the amount of iterations, the error could not be reduced any further. + This might be related to a high condition number of the matrix, + $2.4225 \cdot 10^{14}$, prohibiting it from producing accurate enough + results. + + \newpage + \section{Task 3: Solving systems of linear equations using the Jacobi and + Gauss-Seidel algorithms} + + \subsection{Overview} + + In this task, a predefined, fixed-size system of equations was to be solved + using the Jacobi and Gauss-Seidel iterative algorithms. The algorithms were + to be iterated until the accuracy $\lVert Ax_k - b \rVert < 10^{-10}$ was + achieved. The error of each iteration was to be noted. + + The system to be solved: + \begin{align*} + 18x_1 + 2x_2 - 3x_3 + x_4 & = 7\\ + 2x_1 - 25x_2 + 5x_3 - 18x^4 & = 12\\ + x_1 + 3x_2 + 13x_3 - 8x_4 & = 24\\ + x_1 + x_2 - 2x_3 - 10x_4 & = 20 + \end{align*} + + Afterwards, one of the algorithms was to be applied to matrices from task 2 + a and b, for $n = 10$. + + \subsection{Implementation} + + The general formula describing iterative methods of solving linear equation + systems is: + \begin{equation}\label{eq:1} + x^{(i + 1)} = Mx^{(i)} + w + \end{equation} + Where the matrix $M$ and the vector $w$ are specific to the chosen + algorithm. + + \subsubsection{The Jacobi algorithm} + + The first step of the Jacobi algorithm is to split the matrix $A$ into three + matrices: the lower triangular matrix, the upper triangular matrix and the + diagonal matrix. + + Because the diagonal matrix is only ever used in its inverse from, the + function doing the splitting only returns the inverse diagonal matrix. It + utilizes the fact that the inverse of a diagonal matrix is a matrix of the + inverse of its diagonal elements. + + Once the matrices $L$, $U$ and $D^{-1}$ have been obtained, the parameters + $M$ and $w$ are given by: + \begin{align*} + M &= -D^{-1}(L + U)\\ + w &= D^{-1}b + \end{align*} + + The step described in \eqref{eq:1} is then performed until the desired + accuracy is achieved. + + \subsubsection{The Gauss-Seidel algorithm} + + The Gauss-Seidel algorithm is similar to the Jacobi algorithm in that it + utilizes the lower, upper and inverse diagonal matrices to calculate + subsequent iterations. An important difference is that $M$ and $w$ are not + constant and they cannot be trivially calculated. + + An iteration of the Gauss-Seidel algorithm can be written as: + \begin{align*} + Dx^{(i + 1)} &= -Lx^{(i + 1)} - (Ux^{(i)} - b)\\ + &= -Lx^{(i + 1)} - w^{(i)} + \end{align*} + + The presence of $x^{(i + 1)}$ on both sides of the equation might appear + problematic, however, it's crucial to observe that individual elements of + the vector $x_n^{(i + 1)}$ can be calculated based solely on the knowledge + of their preceding elements, with $x_1^{(i + 1)}$ being completely + independent: + \begin{align*} + x_1^{(i + 1)} &= (-w_1^{(i)}) \cdot D^{-1}_{11}\\ + x_2^{(i + 1)} &= (-L_{21} \cdot x_1^{(i + 1)} - w_2^{(i)}) + \cdot D^{-1}_{22}\\ + x_3^{(i + 1)} &= (-L_{31} \cdot x_1^{(i + 1)} + - L_{32} \cdot x_2^{(i + 1)} + - w_3^{(i)}) \cdot D^{-1}_{33}\\ + &\ldots + \end{align*} + + And so, on each step, the vector $w^{(i)}$ is calculated first, after which + the elements of $x_n^{(i + 1)}$ are computed in sequence. + + \subsection{Program output} + + \subsubsection{Error plots} + + \includegraphics[width=\textwidth]{jacobierror} + \includegraphics[width=\textwidth]{gaussseidelerror} + + \subsubsection{Solutions} + + \begin{multicols}{2} + \begin{verbatim} + Solution using Jacobi: + + i x_i + 1 0.44705 + 2 1.0232 + 3 0.38763 + 4 -1.9305 + + Error: 6.1548e-11 + \end{verbatim} + \begin{verbatim} + Solution using Gauss-Seidel: + + i x_i + 1 0.44705 + 2 1.0232 + 3 0.38763 + 4 -1.9305 + + Error: 4.6134e-11 + \end{verbatim} + \end{multicols} + + \begin{verbatim} + Solution to task 2a using Gauss-Seidel: + + i x_i + 1 0.8953 + 2 0.71881 + 3 0.82946 + 4 0.86335 + 5 0.91714 + 6 0.9681 + 7 1.0105 + 8 1.0901 + 9 1.0293 + 10 1.4927 + + Error: 3.01e-11 + \end{verbatim} + + \subsection{Observations} + + In both algorithms, the error of the solution decreased exponentially in + relation to the number of iterations. + + The Gauss-Seidel method proved to be faster than the Jacobi method, with the + desired accuracy achieved in just 32 iterations compared to 43. + + The matrix from task 2a was solved correctly. The 2b variant, however, could + not achieve the desired accuracy and the algorithm became stuck in a + loop, iterating infinitely in an attempt to reduce the error. This again + may be related to the high condition number of the matrix, or to the fact + that the measured error is absolute rather than relative. + + \section{Task 4: Finding the eigenvalues of a symmetric matrix using the QR + method} + + \subsection{Overview} + + The problem presented in this task was to find the eigenvalues of a + symmetric matrix by utilizing the properties of its QR decomposition. Two + variants of the algorithm were to be used, one with and one without shifting + the diagonal to accelerate the convergence. The algorithms were to be + iterated until the off-diagonal elements decreased below the threshold of + $10^{-6}$. The resultant final matrices were to be printed. + + The matrix of choice: + \begin{equation*} + \begin{bmatrix} + 1 & 1 & 7 & 5 & 2\\ + 1 & 8 & 5 & 4 & 4\\ + 7 & 5 & 0 & 8 & 8\\ + 5 & 4 & 8 & 0 & 8\\ + 2 & 4 & 8 & 8 & 1 + \end{bmatrix} + \end{equation*} + + \subsection{Implementation} + + The QR method is based on the observation that by repeatedly decomposing the + matrix into its orthogonal matrix $Q$ and triangular matrix $R$ and + recomposing it as $R * Q$, the matrix will converge into a diagonal matrix + of its eigenvalues by means of similarity. + + \subsubsection{QR decomposition using the Gram-Schmidt algorithm} + + The columns of the input matrix $A$ are orthogonalized with the modified + Gram-Schmidt algorithm, producing matrices $Q$ and $R$, which can later be + multiplied together to reverse the process. + + The algorithm iterates over the columns of A and orthogonalizes every column + in front of it with relation to the currently visited column. This is done + by calculating the dot product of the two columns and using it to subtract + the ``common part" from the second column. The matrix $Q$ is produced in the + process, as well as $R$ as a byproduct. + + \subsubsection{QR method without shifts} + + The QR method for finding the eigenvalues of a matrix without shifts is a + naive implementation of the observation described at the beginning of this + section. The matrix is repeatedly decomposed and recomposed until its + off-diagonal elements converge below the prescribed threshold. + + \subsubsection{QR method with shifts} + + The QR method may be accelerated by shifting the diagonal of the matrix + towards an approximation of the expected eigenvalues. The required shift can + be calculated by finding the eigenvalues of the lower right $2 \times 2$ + sub-matrix and choosing the one closer to the lower right corner of said + sub-matrix. + + The eigenvalues of the sub-matrix can be found by solving the characteristic + equation of the sub-matrix, $\det{(A - \lambda I)} = 0$. This will result in + a quadratic equation whose solutions are guaranteed to be real for a + symmetric matrix. + + This shift is applied on every iteration of the algorithm. Once all + non-diagonal values of the lowermost row of the matrix have decreased below + the threshold, the matrix is deflated, i.e. its size is reduced by one in + both dimensions. The algorithm stops once the matrix can't be deflated any + further. + + \newpage + \subsection{Program output} + + \begin{verbatim} + Solution using QR without shifts: + 23.3571 -9.3695 -7.8773 5.0307 -1.1410 + + Final matrix: + 23.3571 0.0000 -0.0000 -0.0000 0.0000 + 0.0000 -9.3695 -0.0000 -0.0000 0.0000 + 0.0000 -0.0000 -7.8773 0.0000 -0.0000 + 0.0000 -0.0000 0.0000 5.0307 0.0000 + 0.0000 0.0000 0.0000 0.0000 -1.1410 + + Iteration count: 75 + + Solution using QR with shifts: + 5.0307 -1.1410 -7.8773 -9.3695 23.3571 + + Final matrix: + 23.3571 -0.0445 0.0000 0.0000 0.0000 + 0.0000 -9.3695 0.0000 -0.0000 0.0000 + 0.0000 -0.0000 -7.8773 0.0000 -0.0000 + 0.0000 -0.0000 0.0000 -1.1410 0.0000 + 0.0000 0.0000 0.0000 0.0000 5.0307 + + Iteration count: 9 + \end{verbatim} + + \subsection{Observations} + + The addition of shifting greatly improved the convergence ratio and the same + values could be obtained in just 9 iterations instead of 75. + +\end{document} diff --git a/ENUME/references/szopinski-enume/projA/task1macheps.m b/ENUME/references/szopinski-enume/projA/task1macheps.m new file mode 100644 index 00000000..df2dffd9 --- /dev/null +++ b/ENUME/references/szopinski-enume/projA/task1macheps.m @@ -0,0 +1,15 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT A NUMBER 62 +% TASK 1 +% https://github.com/Lachcim/szopinski-enume + +% first candidate is 2^0 +foundEps = 1; + +% decrement exponent until floating point underflow occurs +while foundEps / 2 + 1 > 1 + foundEps = foundEps / 2; +end + +disp(['Found epsilon is ', num2str(foundEps)]); +disp(['Epsilon is ', num2str(eps)]); diff --git a/ENUME/references/szopinski-enume/projA/task2gausseli.m b/ENUME/references/szopinski-enume/projA/task2gausseli.m new file mode 100644 index 00000000..c3f19465 --- /dev/null +++ b/ENUME/references/szopinski-enume/projA/task2gausseli.m @@ -0,0 +1,125 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT A NUMBER 62 +% TASK 2 +% https://github.com/Lachcim/szopinski-enume + +% define maximum feasible equation count (10 * 2^n) +maxeqcount = 5; + +% perform calculation for both sub-tasks +for task = 'ab' + % collect error values for different equation counts + errors = zeros(maxeqcount + 1, 2); + + % perform calculation for increasing number of equations + for equationspow = 0:maxeqcount + equationcount = 10 * 2 ^ equationspow; + + % generate coefficient matrix A and vector b + A = genmatrix(task, equationcount); + b = genvector(task, equationcount); + eqsys = [A, b]; + + % perform gaussian elimination and back-substitution + [eqsys, lower, upper, permut] = gausseli(eqsys); + result = backsubst(eqsys); + + % note the error + errorvector = A * result - b; + error = norm(errorvector); + errors(equationspow + 1, :) = [equationcount, error]; + + % additional calculations for 10 equations + if equationspow == 0 + % print solution + disp(['Solution to subtask ', task ', 10 equations:']); + disp([(1:10)', result, errorvector]); + disp(['Error: ', num2str(error)]); + + % residual correction: calculate deltax and correct result + for i = 1:10 + % solve system using LU decomposition + intermediate = backsubstflip([lower, permut * errorvector]); + deltax = backsubst([upper, intermediate]); + + % apply correction to result + result = result - deltax; + errorvector = A * result - b; + end + + % print corrected result + disp('With residual correction:'); + disp([(1:10)', result, errorvector]); + disp(['Error: ', num2str(norm(errorvector))]); + end + end + + % plot error data + figure; + plot(errors(:, 1), errors(:, 2), '-o'); + title(['Linear equation system solution error (subtask ', task, ')']); + xlabel('Equation count'); + ylabel('Error'); + grid on; + set(gcf, 'PaperPosition', [0 0 6 4]); + set(gcf, 'PaperSize', [6 4]); + print(['report/', task, 'error'], '-dpdf') +end + +% performs Gaussian elimination and LU decomposition +function [eqsys, lower, upper, permut] = gausseli(eqsys) + % initialize lower triangular and permutation matrix + lower = zeros(size(eqsys, 1)); + permut = eye(size(eqsys, 1)); + + % for every column, eliminate (size - column) coefficients + for col = 1:size(eqsys, 1) + % partial pivoting - find best row + bestrow = 0; + bestscore = 0; + for row = col:size(eqsys, 1) + score = abs(eqsys(row, col)); + if score > bestscore + bestrow = row; + bestscore = score; + end + end + + % swap first row and best row + eqsys([col, bestrow], :) = eqsys([bestrow, col], :); + permut([col, bestrow], :) = permut([bestrow, col], :); + + for row = (col + 1):size(eqsys, 1) + % calculate reductor constant and perform reduction + reductor = eqsys(row, col) / eqsys(col, col); + eqsys(row, :) = eqsys(row, :) - eqsys(col, :) * reductor; + + % add reductor to lower matrix + lower(row, col) = reductor; + + % simulate perfect reduction + eqsys(row, col) = 0; + end + + % permute the lower matrix + lower([col, bestrow], :) = lower([bestrow, col], :); + lowertmp = lower(col, col); + lower(col, col) = lower(bestrow, col); + lower(bestrow, col) = lowertmp; + end + + % return lower and upper triangular matrices + lower = lower + eye(size(lower)); + upper = eqsys(:, 1:size(eqsys, 2) - 1); +end + +% performs back-substitution for lower triangular matrices +function result = backsubstflip(eqsys) + % flip the equation system for lower triangular matrices + eqcount = size(eqsys, 1); + eqsys(:, 1:eqcount) = rot90(eqsys(:, 1:eqcount), 2); + eqsys(:, eqcount + 1) = flipud(eqsys(:, eqcount + 1)); + + % perform back-substitution and flip the result + result = flipud(backsubst(eqsys)); +end diff --git a/ENUME/references/szopinski-enume/projA/task3jacogauss.m b/ENUME/references/szopinski-enume/projA/task3jacogauss.m new file mode 100644 index 00000000..1242a8a9 --- /dev/null +++ b/ENUME/references/szopinski-enume/projA/task3jacogauss.m @@ -0,0 +1,122 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT A NUMBER 62 +% TASK 3 +% https://github.com/Lachcim/szopinski-enume + +% define matrix A and vector b as specified in the task +taskA = [18, 2, -3, 1; + 2, -25, 5, -18; + 1, 3, 13, -8; + 1, 1, -2, -10]; +taskb = [7, 12, 24, 20]'; + +% define available algorithms +algorithms = { + 'Jacobi', @jacobi; + 'Gauss-Seidel', @gaussseidel +}; + +% perform task for all available algorithms +for alg = 1:size(algorithms, 1) + [algname, algfunc] = algorithms{alg, :}; + + % find solution and step errors using the given algorithm + [solution, errors] = algfunc(taskA, taskb); + disp(['Solution using ', algname, ':']); + disp(solution); + disp(['Error: ', num2str(errors(size(errors, 2)))]); + + % plot error data + figure; + semilogy(1:size(errors, 2), errors, '-o'); + title(['LE solution error (', algname, ' algorithm)']); + xlabel('Step'); + ylabel('Error'); + grid on; + set(gcf, 'PaperPosition', [0 0 6 4]); + set(gcf, 'PaperSize', [6 4]); + print(['report/', func2str(algfunc), 'error'], '-dpdf') +end + +% solve task 2a using the GS algorithm +taskA = genmatrix('a', 10); +taskb = genvector('a', 10); + +[solution, errors] = gaussseidel(taskA, taskb); +disp('Solution to task 2a using Gauss-Seidel:'); +disp(solution); +disp(['Error: ', num2str(errors(size(errors, 2)))]); + +% solves LE system using the Jacobi algorithm, returns error per step +function [x, errors] = jacobi(A, b) + % split input matrix and create step zero result vector + [lower, upper, invdiagonal] = splitmatrix(A); + x = ones(size(A, 1), 1); + + % get Jacobi iterative M and w + M = -invdiagonal * (lower + upper); + w = invdiagonal * b; + + % execute the algorithm until the desired accuracy is achieved + errors = double.empty(1, 0); + while 1 + % calculate next iteration + x = M * x + w; + + % calculate error and stop when it's low enough + error = norm(A * x - b); + errors(size(errors, 2) + 1) = error; + if error < 1e-10; break; end + end +end + +% solves LE system using the Gauss-Seidel algorithm +function [x, errors] = gaussseidel(A, b) + % split input matrix and create step zero result vector + [lower, upper, invdiagonal] = splitmatrix(A); + x = ones(size(A, 1), 1); + + % execute the algorithm until the desired accuracy is achieved + errors = double.empty(1, 0); + while 1 + % calculate step-specific iterative w + w = upper * x - b; + + % calculate next iteration, row by row + for row = 1:size(x) + % reset value, subtract step-specific w + x(row) = -w(row); + + % subtract elements of the lower matrix multiplied by previous results + for col = 1:(row - 1) + x(row) = x(row) - lower(row, col) * x(col); + end + + % divide by the diagonal + x(row) = x(row) * invdiagonal(row, row); + end + + % calculate error and stop when it's low enough + error = norm(A * x - b); + errors(size(errors, 2) + 1) = error; + if error < 1e-10; break; end + end +end + +% splits a matrix a into lower, upper and inverse diagonal matrices +function [lower, upper, invdiagonal] = splitmatrix(input) + % allocate empty matrices + lower = zeros(size(input)); + upper = zeros(size(input)); + invdiagonal = zeros(size(input)); + + % copy each element to the right output matrix + for i = 1:size(input, 1) + for j = 1:size(input, 2) + if i > j; lower(i, j) = input(i, j); + elseif i < j; upper(i, j) = input(i, j); + else; invdiagonal(i, j) = 1 / input(i, j); + end + end + end +end diff --git a/ENUME/references/szopinski-enume/projA/task4qreigen.m b/ENUME/references/szopinski-enume/projA/task4qreigen.m new file mode 100644 index 00000000..5d88d337 --- /dev/null +++ b/ENUME/references/szopinski-enume/projA/task4qreigen.m @@ -0,0 +1,107 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT A NUMBER 62 +% TASK 4 +% https://github.com/Lachcim/szopinski-enume + +% define matrix of choice +A = [1, 1, 7, 5, 2; + 1, 8, 5, 4, 4; + 7, 5, 0, 8, 8; + 5, 4, 8, 0, 8; + 2, 4, 8, 8, 1]; + +% define available algorithms +algorithms = { + 'without shifts', @eigennoshifts; + 'with shifts', @eigenshifts +}; + +% solve problem using both algorithms +for alg = 1:size(algorithms, 1) + [algname, algfunc] = algorithms{alg, :}; + + % find solution and iteration count using the given algorithm + [solution, iterations, finalMatrix] = algfunc(A); + disp(['Solution using QR ', algname, ':']); + disp(solution); + disp('Final matrix:'); + disp(finalMatrix); + disp(['Iteration count: ', num2str(iterations)]); +end + +% finds the eigenvalues of a matrix using the QR method without shifts +function [eigenvalues, iterations, A] = eigennoshifts(A) + % initialize iteration counter + iterations = 0; + + while 1 + % converge to eigenvalue diagonal matrix + [Q, R] = qrdecomp(A); + A = R * Q; + iterations = iterations + 1; + + % iterate until all non-diagonal elements are below the threshold + nondiag = A - diag(diag(A)); + maxnonzero = max(max(abs(nondiag))); + if (maxnonzero <= 1e-6); break; end + end + + % convert eigenvalue matrix to vector + eigenvalues = diag(A)'; +end + +% finds the eigenvalues of a matrix using QR with shifts +function [eigenvalues, iterations, finalMatrix] = eigenshifts(A) + % initialize empty output + eigenvalues = double.empty(1, 0); + iterations = 0; + + % consider increasingly smaller sub-matrices + matsize = size(A, 1); + while matsize >= 2 + % find one eigenvalue + while 1 + % find eigenvalue of the lower right corner + corner = A((matsize - 1):matsize, (matsize - 1):matsize); + cornereigen = eigenoftwo(corner); + + % shift and iterate algorithm + A = A - eye(matsize) * cornereigen; + [Q, R] = qrdecomp(A); + A = R * Q + eye(matsize) * cornereigen; + iterations = iterations + 1; + + % move on once the row has been zeroed out + maxnonzero = max(abs(A(matsize, 1:(matsize - 1)))); + if (maxnonzero <= 1e-6) + % remember discovered eigenvalue + eigenvalues(size(eigenvalues, 2) + 1) = A(matsize, matsize); + break; + end + end + + % deflate matrix + finalMatrix(1:matsize, 1:matsize) = A; + matsize = matsize - 1; + A = A(1:matsize, 1:matsize); + end + + % include final eigenvalue + eigenvalues(size(eigenvalues, 2) + 1) = A(1, 1); +end + +% finds the eigenvalue of a 2x2 matrix that is closer to the lower right corner +function eigen = eigenoftwo(A) + % solve characteristic equation of matrix to find its eigenvalues + delta = (A(1) + A(4)) ^ 2 - 4 * (A(1) * A(4) - A(2) * A(3)); + sqrtdelta = sqrt(delta); + eigen1 = ((A(1) + A(4)) - sqrtdelta) / 2; + eigen2 = ((A(1) + A(4)) + sqrtdelta) / 2; + + % return value closer to lower right corner + if abs(A(4) - eigen1) < abs(A(4) - eigen2) + eigen = eigen1; + else + eigen = eigen2; + end +end diff --git a/ENUME/references/szopinski-enume/projB/deriv.m b/ENUME/references/szopinski-enume/projB/deriv.m new file mode 100644 index 00000000..f2a43f21 --- /dev/null +++ b/ENUME/references/szopinski-enume/projB/deriv.m @@ -0,0 +1,16 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT B NUMBER 60 +% https://github.com/Lachcim/szopinski-enume + +% calculate the nth derivative of func at x +function y = deriv(func, x, deg) + % base case: zeroth derivative + if deg == 0 + y = func(x); + return + end + + % recurse to find the nth derivative + step = sqrt(eps); + y = (deriv(func, x + step, deg - 1) - deriv(func, x - step, deg - 1)) / (2 * step); +end diff --git a/ENUME/references/szopinski-enume/projB/polynomial.m b/ENUME/references/szopinski-enume/projB/polynomial.m new file mode 100644 index 00000000..1d073091 --- /dev/null +++ b/ENUME/references/szopinski-enume/projB/polynomial.m @@ -0,0 +1,8 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT B NUMBER 60 +% https://github.com/Lachcim/szopinski-enume + +% the polynomial function for task 2 +function y = polynomial(x) + y = x^4 - 7 * x^3 + 4* x^2 + 2 * x + 9; +end diff --git a/ENUME/references/szopinski-enume/projB/printcomplex.m b/ENUME/references/szopinski-enume/projB/printcomplex.m new file mode 100644 index 00000000..939139bd --- /dev/null +++ b/ENUME/references/szopinski-enume/projB/printcomplex.m @@ -0,0 +1,43 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT B NUMBER 60 +% https://github.com/Lachcim/szopinski-enume + +% graph the complex roots of a function +function printcomplex(func, algorithms, bracket, plottitle, outputsuffix) + % perform task for all available algorithms + for alg = 1:size(algorithms, 1) + [algname, algfunc] = algorithms{alg, :}; + + % prepare plot + figure; + grid on; + hold on; + title([plottitle, ' (', algname, ')']); + xlabel("Real part"); + ylabel("Imaginary part"); + set(gca, 'XAxisLocation', 'origin'); + + % find all zeros within the bracket using the given algorithm + [zero, steps] = algfunc(func, bracket(1), bracket(2), 1e-15); + + % plot steps on graph + plot(real(steps(1, :)), imag(steps(1, :)), '-o'); + text(real(steps(1, 1)), imag(steps(1, 1)), 'start', ... + 'HorizontalAlignment', 'center', ... + 'VerticalAlignment', 'top'); + text(real(steps(1, end)), imag(steps(1, end)), 'end', ... + 'HorizontalAlignment', 'center', ... + 'VerticalAlignment', 'top'); + + % finish and print graph + hold off; + set(gcf, 'PaperPosition', [0 0 6 4]); + set(gcf, 'PaperSize', [6 4]); + print(['report/', func2str(algfunc), outputsuffix], '-dpdf'); + + % print root table + disp([plottitle, ' (', algname, ')']); + columns = {'step', 'root', 'abs value at root'}; + disp(table([1:size(steps, 2)]', steps(1, :)', abs(steps(2, :))', 'VariableNames', columns)); + end +end diff --git a/ENUME/references/szopinski-enume/projB/printroots.m b/ENUME/references/szopinski-enume/projB/printroots.m new file mode 100644 index 00000000..36f2c764 --- /dev/null +++ b/ENUME/references/szopinski-enume/projB/printroots.m @@ -0,0 +1,47 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT B NUMBER 60 +% https://github.com/Lachcim/szopinski-enume + +% graph the real roots of a function +function printroots(func, algorithms, interval, brackets, plottitle, outputsuffix) + % perform task for all available algorithms + for alg = 1:size(algorithms, 1) + [algname, algfunc] = algorithms{alg, :}; + + % plot function inside interval + figure; + grid on; + hold on; + title([plottitle, ' (', algname, ')']); + set(gca, 'XAxisLocation', 'origin'); + x = interval(1):0.05:interval(2); + y = arrayfun(func, x); + plot(x, y); + + % iterate over root brackets + for bracket = brackets + % find all zeros within the bracket using the given algorithm + [zero, steps] = algfunc(func, bracket(1), bracket(2), 1e-15); + + % plot steps on graph + xline(bracket(1), 'color', [0.5, 0.5, 0.5]); + xline(bracket(2), 'color', [0.5, 0.5, 0.5]); + scatter(steps(1, 2:end), steps(2, 2:end), [], [0.929, 0.694, 0.125]); + scatter(steps(1, 1), steps(2, 1), [], [0.635, 0.078, 0.184]); + text(steps(1, 1), steps(2, 1), 'start', ... + 'HorizontalAlignment', 'center', ... + 'VerticalAlignment', 'top'); + + % print root table + disp([plottitle, ' (', algname, ')']); + columns = {'step', 'root', 'value at root'}; + disp(table([1:size(steps, 2)]', steps(1, :)', steps(2, :)', 'VariableNames', columns)); + end + + % finish and print graph + hold off; + set(gcf, 'PaperPosition', [0 0 6 4]); + set(gcf, 'PaperSize', [6 4]); + print(['report/', func2str(algfunc), outputsuffix], '-dpdf'); + end +end diff --git a/ENUME/references/szopinski-enume/projB/report/projBreport.tex b/ENUME/references/szopinski-enume/projB/report/projBreport.tex new file mode 100644 index 00000000..43e43fe5 --- /dev/null +++ b/ENUME/references/szopinski-enume/projB/report/projBreport.tex @@ -0,0 +1,504 @@ +\documentclass{article} + +\usepackage{amsmath} +\usepackage{graphicx} +\usepackage{multicol} +\setlength{\parskip}{1em} + +\begin{document} + + \title{ENUME project report\\Project B: finding roots of polynomials \\ + and zeros of other functions} + \author{Michał Szopiński\\\\ + https://github.com/Lachcim/szopinski-enume\\ + Project number 60} + \date{December 3, 2020} + \maketitle + + \numberwithin{equation}{section} + + \setcounter{section}{-1} + \section{Abstract} + + This project explores the numerical methods of finding the arguments (real + and complex) for which a function is equal to zero. The following concepts + are discussed within this document: + + \begin{itemize} + \item Computing the zeros of an arbitrary function using the bisection + method and Newton's algorithm + \item Finding the real and complex roots of a + 4\textsuperscript{th}-degree polynomial using M{\"u}ller's method and + Laguerre's algorithm + \end{itemize} + + \newpage + + \section{Task 1: Finding the zeros of an arbitrary function using bisection + and Newton's method} + + \subsection{Overview} + + In this task, the zeros of the following function were to be found: + \begin{align*} + f(x) = 0.7 x \cos(x) - \ln(x + 1) && x \in [2; 11] + \end{align*} + This was to be done using the bisection method and Newton's algorithm. + + \subsection{Implementation} + + \subsubsection{Bracketing} + + The basis for finding the roots of a function within a given interval is a + heuristic algorithm which finds the function's \textit {root brackets}, + i.e. the regions where root-finding algorithms converge to an answer. + + In this project, bracketing was implemented by dividing the original search + interval into 10 sub-intervals and checking the sign of the function at + each of the sub-invervals' boundaries. A sign mismatch signalizes that the + function crosses the x-axis somewhere within the interval, which can then + be passed to a root-finding algorithm. + + \subsubsection{Bisection} + + Bisection is the simplest of root-finding algorithms. It can be thought of + as a variation of the bracketing method. The original root bracket is + divided into two sub-intervals and the next interval to be considered is + chosen based on sign mismatch, implementing a ``binary search" type of + approach. This step is repeated until the considered interval is + sufficiently narrow. + + \subsubsection{Newton's method} + + A much more advanced algorithm is known as Newton's method. This method + uses a linear approximation of the function at the given inquiry point to + predict where the function may be zero. The next inquiry point is given as + the intersection of the current tangent line and the x-axis. + + Because Newton's algorithm isn't strictly interval-based, a speed-based + stop test has to be implemented. The test analyzes the distance between the + current and the previous inquiry point and stops the algorithm when it is + sufficiently small. + + \subsection{Program output} + + \subsubsection{Bisection method} + + \begin{multicols}{2} + \begin{verbatim} + step root value at root + 1 5.15 -0.28874 + 2 5.375 0.46222 + 3 5.2625 0.091218 + 4 5.2063 -0.098017 + 5 5.2344 -0.003167 + 6 5.2484 0.04409 + 7 5.2414 0.020477 + 8 5.2379 0.0086585 + 9 5.2361 0.0027467 + 10 5.2353 -0.00020995 + 11 5.2357 0.0012684 + 12 5.2355 0.00052925 + 13 5.2354 0.00015965 + 14 5.2353 -2.5147e-05 + 15 5.2353 6.7253e-05 + 16 5.2353 2.1053e-05 + 17 5.2353 -2.0473e-06 + 18 5.2353 9.5027e-06 + 19 5.2353 3.7277e-06 + 20 5.2353 8.4017e-07 + 21 5.2353 -6.0359e-07 + 22 5.2353 1.1829e-07 + 23 5.2353 -2.4265e-07 + 24 5.2353 -6.2178e-08 + 25 5.2353 2.8056e-08 + 26 5.2353 -1.7061e-08 + 27 5.2353 5.4976e-09 + 28 5.2353 -5.7818e-09 + 29 5.2353 -1.421e-10 + 30 5.2353 2.6777e-09 + 31 5.2353 1.2678e-09 + 32 5.2353 5.6286e-10 + 33 5.2353 2.1038e-10 + 34 5.2353 3.4142e-11 + 35 5.2353 -5.398e-11 + 36 5.2353 -9.9194e-12 + 37 5.2353 1.2111e-11 + 38 5.2353 1.0942e-12 + 39 5.2353 -4.4122e-12 + 40 5.2353 -1.6607e-12 + 41 5.2353 -2.8288e-13 + 42 5.2353 4.0723e-13 + 43 5.2353 6.0618e-14 + 44 5.2353 -1.128e-13 + 45 5.2353 -2.5979e-14 + 46 5.2353 1.8652e-14 + 47 5.2353 -5.3291e-15 + 48 5.2353 6.6613e-15 + 49 5.2353 8.8818e-16 + 50 5.2353 -2.2204e-15 + 51 5.2353 8.8818e-16 + \end{verbatim} + \end{multicols} + + \newpage + + \begin{multicols}{2} + \begin{verbatim} + step root value at root + 1 7.85 -2.1585 + 2 7.625 -0.94313 + 3 7.5125 -0.38047 + 4 7.4563 -0.1133 + 5 7.4281 0.016422 + 6 7.4422 -0.048105 + 7 7.4352 -0.015758 + 8 7.4316 0.00035306 + 9 7.4334 -0.0076972 + 10 7.4325 -0.0036708 + 11 7.4321 -0.0016585 + 12 7.4319 -0.00065265 + 13 7.4318 -0.00014977 + 14 7.4317 0.00010165 + 15 7.4317 -2.4062e-05 + 16 7.4317 3.8794e-05 + 17 7.4317 7.366e-06 + 18 7.4317 -8.3478e-06 + 19 7.4317 -4.9087e-07 + 20 7.4317 3.4376e-06 + 21 7.4317 1.4734e-06 + 22 7.4317 4.9124e-07 + 23 7.4317 1.8718e-10 + 24 7.4317 -2.4534e-07 + 25 7.4317 -1.2258e-07 + 26 7.4317 -6.1195e-08 + 27 7.4317 -3.0504e-08 + 28 7.4317 -1.5158e-08 + 29 7.4317 -7.4856e-09 + 30 7.4317 -3.6492e-09 + 31 7.4317 -1.731e-09 + 32 7.4317 -7.7191e-10 + 33 7.4317 -2.9237e-10 + 34 7.4317 -5.2595e-11 + 35 7.4317 6.7295e-11 + 36 7.4317 7.3497e-12 + 37 7.4317 -2.2622e-11 + 38 7.4317 -7.6343e-12 + 39 7.4317 -1.4255e-13 + 40 7.4317 3.6025e-12 + 41 7.4317 1.7319e-12 + 42 7.4317 7.9714e-13 + 43 7.4317 3.2552e-13 + 44 7.4317 8.9706e-14 + 45 7.4317 -2.3981e-14 + 46 7.4317 3.2419e-14 + 47 7.4317 3.9968e-15 + 48 7.4317 -7.9936e-15 + 49 7.4317 0 + 50 7.4317 0 + \end{verbatim} + \end{multicols} + + \subsubsection{Newton's method} + + \begin{multicols}{2} + \begin{verbatim} + step root value at root + 1 5.15 -0.28874 + 2 5.2349 -0.0012685 + 3 5.2353 -4.1974e-08 + 4 5.2353 8.8818e-16 + 5 5.2353 8.8818e-16 + \end{verbatim} + \begin{verbatim} + step root value at root + 1 7.85 -2.1585 + 2 7.4649 -0.15373 + 3 7.4321 -0.0017786 + 4 7.4317 -2.561e-07 + 5 7.4317 -7.9936e-15 + 6 7.4317 0 + 7 7.4317 0 + \end{verbatim} + \end{multicols} + + \subsubsection{Function plots with marked zeros} + + \includegraphics[width=\textwidth]{bisectzeros} + \includegraphics[width=\textwidth]{newtonzeros} + + \subsection{Observations} + + The self-evident observation is that the bisection method is excruciatingly + slow compared to Newton's method, achieving in 50 iterations what Newton's + algorithm was able to achieve in just 7. + + One remark which cannot be concluded from this experiment is that the + bisection method is globally convergent, whereas Newton's algorithm only + converges to a finite value within a specific sphere of convergence around + the known root. As a matter of fact, given the right circumstances, Newton's + algorithm may even diverge to infinity. + + A good general root-finding algorithm should use a mixture of both methods, + resorting to the slower one when the faster one fails. + + \newpage + + \section{Task 2: Finding the real and complex roots of a polynomial using + M{\"u}ller's method} + + \subsection{Overview} + + The goal of this task was to find the real and complex roots of the + following polynomial: + \begin{equation*} + f(x) = x^4 - 7 x^3 - 4 x^2 + 2 x + 9 + \end{equation*} + This was to be accomplished using both versions of M{\"u}ller's method + known as MM1 and MM2. In addition, the real roots of the polynomial were to + be found using Newton's algorithm. + + \subsection{Implementation} + + \subsubsection{Bracketing} + + Because any bracket-finding algorithm is heuristic in nature and there's no + guarantee that it will identify all existing brackets, an empirical analysis + of the polynomial was performed to approximate its roots. + + The previously mentioned algorithm was used to find the polynomial's real + root brackets within the interval $[1; 7]$. However, the complex root evaded + algorithmic detection and its bracket had to be hardcoded as $[-1 + i; 0]$. + + \subsubsection{MM1} + + M{\"u}ller's method 1 is an interval-based iterative algorithm which is + similar in operation to the so-called method of splines. The spline method + draws a line connecting the intersection of the function with the currently + considered interval boundaries and calculates its intersection with the + x-axis, determining the boundary of the new interval. + + MM1 expands this idea by approximating the polynomial with a quadratic + function rather than a linear one, yielding better results. This also + enables the algorithm to find the complex roots of the polynomial, provided + a complex arithmetic is used. Roots found in this way come in complex + conjugate pairs. + + \subsubsection{MM2} + + The MM2 variant is identical in principle to MM1, except that it uses the + polynomial's first and second derivatives to calculate the approximating + parabola, which is minor performance improvement. Being a + point-of-inquiry-based algorithm, it implements a stop test identical to + that used in Newton's algorithm. + + \subsection{Program output} + + \subsubsection{Comparison of MM1 and MM2} + + \begin{multicols}{2} + \begin{verbatim} + MM1 + step root value at root + 1 1.9 -7.7409 + 2 1.6141 0.00074121 + 3 1.6141 3.5387e-08 + 4 1.6141 1.7764e-15 + 5 1.6141 1.7764e-15 + + + 1 6.1 -34.243 + 2 6.2745 -0.18262 + 3 6.2754 -0.00033662 + 4 6.2754 -3.0579e-09 + 5 6.2754 -4.2277e-13 + 6 6.2754 1.2079e-13 + 7 6.2754 1.2079e-13 + + 1 -0.5±0.5i 6.6002 + 2 -0.43687±0.77299i 1.3929 + 3 0.44529±0.82695i 0.10396 + 4 -0.44472±0.83109i 0.00076461 + 5 -0.44475±0.83109i 7.0057e-08 + 6 -0.44475±0.83109i 1.986e-15 + 7 -0.44475±0.83109i 6.6613e-16 + \end{verbatim} + \begin{verbatim} + MM2 + step root value at root + 1 1.9 -7.7409 + 2 1.6079 0.1425 + 3 1.6141 0.00014476 + 4 1.6141 -5.0846e-11 + 5 1.6141 1.7764e-15 + 6 1.6141 1.7764e-15 + + 1 6.1 -34.243 + 2 6.2931 3.8249 + 3 6.2753 -0.01103 + 4 6.2754 -9.1773e-09 + 5 6.2754 1.2079e-13 + 6 6.2754 9.0594e-14 + + + 1 -0.5±0.5i 6.6002 + 2 -0.43179±0.82848i 0.32746 + 3 -0.44475±0.83109i 9.1408e-05 + 4 -0.44475±0.83109i 8.0852e-12 + 5 -0.44475±0.83109i 6.6613e-16 + 6 -0.44475±0.83109i 6.6613e-16 + + \end{verbatim} + \end{multicols} + + \subsubsection{Real roots found using M{\"u}ller's method} + + \includegraphics[width=\textwidth]{mm1realroots} + \includegraphics[width=\textwidth]{mm2realroots} + + \subsubsection{Complex roots found using M{\"u}ller's method} + + \includegraphics[width=\textwidth]{mm1complexroots} + \includegraphics[width=\textwidth]{mm2complexroots} + + \newpage + \subsubsection{Comparison of MM2 and Newton's method} + + \begin{multicols}{2} + \begin{verbatim} + MM2 + step root value at root + 1 1.9 -7.7409 + 2 1.6079 0.1425 + 3 1.6141 0.00014476 + 4 1.6141 -5.0846e-11 + 5 1.6141 1.7764e-15 + 6 1.6141 1.7764e-15 + + + 1 6.1 -34.243 + 2 6.2931 3.8249 + 3 6.2753 -0.01103 + 4 6.2754 -9.1773e-09 + 5 6.2754 1.2079e-13 + 6 6.2754 9.0594e-14 + \end{verbatim} + \begin{verbatim} + Newton's method + step root value at root + 1 1.9 -7.7409 + 2 1.6517 -0.88341 + 3 1.615 -0.019292 + 4 1.6141 -1.0035e-05 + 5 1.6141 -2.7409e-12 + 6 1.6141 -3.5527e-15 + 7 1.6141 1.7764e-15 + + 1 6.1 -34.243 + 2 6.2931 3.8249 + 3 6.2755 0.033727 + 4 6.2754 2.7013e-06 + 5 6.2754 9.0594e-14 + 6 6.2754 9.0594e-14 + \end{verbatim} + \end{multicols} + + \subsubsection{Real roots found using Newton's method} + + \includegraphics[width=\textwidth]{newtonrealroots} + + \subsection{Observations} + + Both methods MM1 and MM2 proved to be similarly efficient in terms of the + number of iterations. MM2's advantage over MM1 is that an individual step + takes less time to compute, rather than there being fewer steps. + + MM2 also exhibited a similar number of steps to Newton's method. This is + because both methods have a similar order of convergence (1.84 for + M{\"u}ller's, 2 for Newton's). That said, MM2 has the obvious advantage of + being able to find complex roots as well as real roots, to the latter of + which Newton's method is limited. + + \newpage + \section{Task 3: Finding the real and complex roots of a polynomial using + Laguerre's method} + + \subsection{Overview} + + Task 2 was to be repeated using Laguerre's algorithm. + + \subsection{Implementation} + + Laguerre's algorithm is nearly identical to the MM2 algorithm, except that + it implements a custom formula for calculating the next point of inquiry, + which takes into account the order of the polynomial. + + \subsection{Program output} + + \subsubsection{Comparison of Laguerre's method and MM2} + + \begin{multicols}{2} + \begin{verbatim} + Laguerre's algorithm + step root value at root + 1 1.9 -7.7409 + 2 1.6111 0.070341 + 3 1.6141 7.0457e-06 + 4 1.6141 -2.3448e-13 + 5 1.6141 1.7764e-15 + 6 1.6141 1.7764e-15 + + 1 6.1 -34.243 + 2 6.2931 3.8249 + 3 6.2753 -0.010849 + 4 6.2754 2.7981e-07 + 5 6.2754 9.0594e-14 + 6 6.2754 9.0594e-14 + + 1 -0.5±0.5i 6.6002 + 2 -0.44301±0.82854i 0.07705 + 3 -0.44475±0.83109i 5.4048e-06 + 4 -0.44475±0.83109i 7.2709e-14 + 5 -0.44475±0.83109i 6.6613e-16 + 6 -0.44475±0.83109i 6.6613e-16 + \end{verbatim} + \begin{verbatim} + MM2 + step root value at root + 1 1.9 -7.7409 + 2 1.6079 0.1425 + 3 1.6141 0.00014476 + 4 1.6141 -5.0846e-11 + 5 1.6141 1.7764e-15 + 6 1.6141 1.7764e-15 + + 1 6.1 -34.243 + 2 6.2931 3.8249 + 3 6.2753 -0.01103 + 4 6.2754 -9.1773e-09 + 5 6.2754 1.2079e-13 + 6 6.2754 9.0594e-14 + + 1 -0.5±0.5i 6.6002 + 2 -0.43179±0.82848i 0.32746 + 3 -0.44475±0.83109i 9.1408e-05 + 4 -0.44475±0.83109i 8.0852e-12 + 5 -0.44475±0.83109i 6.6613e-16 + 6 -0.44475±0.83109i 6.6613e-16 + \end{verbatim} + \end{multicols} + + \subsubsection{Function plot with marked zeros} + + \includegraphics[width=\textwidth]{laguerrerealroots} + \includegraphics[width=\textwidth]{laguerrecomplexroots} + + \subsection{Observations} + + Although generally considered better than MM2 (convergence order 3 vs 1.84), + in this case, Laguerre's method proved just as fast as MM2. It's very easy + to implement, it has a high convergence order and it's capable of finding + complex roots -- in short, Laguerre's method is one of the best methods + for finding roots of polynomials. + +\end{document} diff --git a/ENUME/references/szopinski-enume/projB/rootbrac.m b/ENUME/references/szopinski-enume/projB/rootbrac.m new file mode 100644 index 00000000..4f665b61 --- /dev/null +++ b/ENUME/references/szopinski-enume/projB/rootbrac.m @@ -0,0 +1,30 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT B NUMBER 60 +% https://github.com/Lachcim/szopinski-enume + +% finds the root brackets of a function within the given range +function brackets = rootbrac(func, rangestart, rangeend) + % define search resolution + resolution = (rangeend - rangestart) / 10; + + % start search at the start of the range + a = rangestart; + b = rangestart + resolution; + brackets = double.empty(2, 0); + + % keep moving the interval until the range is exceeded + while 1 + % if the function changes sign inside the interval, a bracket has been found + if sign(func(a)) ~= sign(func(b)) + % save bracket + brackets(:, size(brackets, 2) + 1) = [a, b]; + end + + % if the bracket can't be expanded, return + if b == rangeend; return; end + + % check next bracket + a = b; + b = min(a + resolution, rangeend); + end +end diff --git a/ENUME/references/szopinski-enume/projB/task1functroot.m b/ENUME/references/szopinski-enume/projB/task1functroot.m new file mode 100644 index 00000000..a2869432 --- /dev/null +++ b/ENUME/references/szopinski-enume/projB/task1functroot.m @@ -0,0 +1,81 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT B NUMBER 60 +% TASK 1 +% https://github.com/Lachcim/szopinski-enume + +% define available algorithms +algorithms = { + 'bisection', @bisect; + 'Newton''s algorithm', @newton +}; + +% find all root brackets +interval = [2, 11]; +brackets = rootbrac(@taskfunc, interval(1), interval(2)); + +% find and graph zeros using both algorithms +printroots(@taskfunc, algorithms, interval, brackets, ... + 'Approximate zeros of function', 'zeros'); + +% use Newton's algorithm to find roots of polynomial +algorithms = {'Newton''s algorithm', @newton}; +interval = [1, 7]; +brackets = rootbrac(@polynomial, interval(1), interval(2)); +printroots(@polynomial, algorithms, interval, brackets, ... + 'Approximate real roots of polynomial', 'realroots'); + +% the function as given in the task +function y = taskfunc(x) + y = 0.7 * x * cos(x) - log(x + 1); +end + +% uses the bisection algorithm to find the root of a function within the given bracket +function [zero, steps] = bisect(func, a, b, tolerance) + % initialize empty array of steps + steps = double.empty(2, 0); + + % iterate algorithm until the error is within tolerance + while 1 + % calculate midpoint + zero = (a + b) / 2; + steps(:, size(steps, 2) + 1) = [zero, func(zero)]; + + % stop test + if abs(a - b) < tolerance; break; end + + % choose next sub-interval based on sign mismatch + if sign(func(a)) ~= sign(func(zero)) + b = zero; + else + a = zero; + end + end +end + +% uses Newton's algorithm to find the root of a function +function [zero, steps] = newton(func, a, b, tolerance) + % initialize step array and calculate derivative step + steps = double.empty(2, 0); + step = sqrt(eps); + + % calculate first approximation of zero - midpoint of the bracket + zero = (a + b) / 2; + steps(:, size(steps, 2) + 1) = [zero, func(zero)]; + + % iterate algorithm until the error is within tolerance + while 1 + % calculate next approximation of zero + prevzero = zero; + derivative = (func(zero + step) - func(zero - step)) / (2 * step); + zero = zero - func(zero) / derivative; + steps(:, size(steps, 2) + 1) = [zero, func(zero)]; + + % prevent divergence during approximation + if zero < a || zero > b + error('Divergent iteration'); + end + + % stop test + if abs(zero - prevzero) <= tolerance; break; end + end +end diff --git a/ENUME/references/szopinski-enume/projB/task2muller.m b/ENUME/references/szopinski-enume/projB/task2muller.m new file mode 100644 index 00000000..6a8b01ff --- /dev/null +++ b/ENUME/references/szopinski-enume/projB/task2muller.m @@ -0,0 +1,119 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT B NUMBER 60 +% TASK 2 +% https://github.com/Lachcim/szopinski-enume + +% define available algorithms +algorithms = { + 'MM1', @mm1; + 'MM2', @mm2 +}; + +% find all real root brackets +interval = [1, 7]; +brackets = rootbrac(@polynomial, interval(1), interval(2)); + +% find and graph real roots using both algorithms +printroots(@polynomial, algorithms, interval, brackets, ... + 'Approximate real roots of polynomial', 'realroots'); +printcomplex(@polynomial, algorithms, [-1+i, 0], ... + 'Approximate complex roots of polynomial', 'complexroots'); + +% find roots of polynomial using MM1 +function [zero, steps] = mm1(func, a, b, tolerance) + % define the three approximation points + apprx = [a, b, (a + b) / 2]; + apprxval = arrayfun(func, apprx); + + % initialize output + steps = [apprx(3); func(apprx(3))]; + + % iterate algorithm until the error is within tolerance + while abs(apprx(3) - apprx(2)) > tolerance + % prepare linear equation system to find parabola + z0 = apprx(1) - apprx(3); + z1 = apprx(2) - apprx(3); + diff0 = apprxval(1) - apprxval(3); + diff1 = apprxval(2) - apprxval(3); + + % solve equation system using Gaussian elimination (spaghetti code but fast) + eqsys = [z0 ^ 2, z0, diff0; z1 ^ 2, z1, diff1]; + reductor = eqsys(2, 1) / eqsys(1, 1); + eqsys(2, :) = eqsys(2, :) - reductor * eqsys(1, :); + eqsys(2, 1) = 0; + eqsys(2, :) = eqsys(2, :) ./ eqsys(2, 2); + eqsys(1, :) = eqsys(1, :) - eqsys(1, 2) * eqsys(2, :); + eqsys(1, :) = eqsys(1, :) ./ eqsys(1, 1); + + % define approximation parabola + a = eqsys(1, 3); + b = eqsys(2, 3); + c = apprxval(3); + + % find roots of parabola + zplus = -2 * c / (b + sqrt(b ^ 2 - 4 * a * c)); + zminus = -2 * c / (b - sqrt(b ^ 2 - 4 * a * c)); + + % choose root closer to current approximation + if abs(zplus) < abs(zminus) + newapprx = apprx(3) + zplus; + else + newapprx = apprx(3) + zminus; + end + + % update answer + zero = newapprx; + steps(:, size(steps, 2) + 1) = [zero, func(zero)]; + + % eliminate the most distant of the three approximations + worstapprxindex = -1; + worstapprxdiff = 0; + for i = 1:size(apprx, 2) + diff = abs(apprx(i) - newapprx); + if diff > worstapprxdiff + worstapprxindex = i; + worstapprxdiff = diff; + end + end + + % delete old approximation and append new one + apprx(worstapprxindex) = []; + apprx(3) = newapprx; + apprxval = arrayfun(func, apprx); + end +end + +% find roots of polynomial using MM2 +function [approx, steps] = mm2(func, a, b, tolerance) + % define current and (dummy) previous approximation point + approx = (a + b) / 2; + prevapprox = approx + b - a; + + % initialize output + steps = [approx; func(approx)]; + + % iterate algorithm until the error is within tolerance + % the error is defined as the diff between the prev and the current approx + while abs(approx - prevapprox) > tolerance + % calculate approximating parabola using first and second derivative + c = func(approx); + b = deriv(func, approx, 1); + a = deriv(func, approx, 2) / 2; + + % find roots of parabola + zplus = -2 * c / (b + sqrt(b ^ 2 - 4 * a * c)); + zminus = -2 * c / (b - sqrt(b ^ 2 - 4 * a * c)); + + % choose root closer to current approximation + if abs(zplus) < abs(zminus) + newapprox = approx + zplus; + else + newapprox = approx + zminus; + end + + % update answer and prev approx + prevapprox = approx; + approx = newapprox; + steps(:, size(steps, 2) + 1) = [approx, func(approx)]; + end +end diff --git a/ENUME/references/szopinski-enume/projB/task3laguerre.m b/ENUME/references/szopinski-enume/projB/task3laguerre.m new file mode 100644 index 00000000..e09603e9 --- /dev/null +++ b/ENUME/references/szopinski-enume/projB/task3laguerre.m @@ -0,0 +1,54 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT B NUMBER 60 +% TASK 3 +% https://github.com/Lachcim/szopinski-enume + +% use Newton's algorithm to find roots of polynomial +algorithms = {'Laguerre''s algorithm', @laguerre}; +interval = [1, 7]; +brackets = rootbrac(@polynomial, interval(1), interval(2)); +printroots(@polynomial, algorithms, interval, brackets, ... + 'Approximate real roots of polynomial', 'realroots'); +printcomplex(@polynomial, algorithms, [-1+i, 0], ... + 'Approximate complex roots of polynomial', 'complexroots'); + +function [zero, steps] = laguerre(func, a, b, tolerance) + % define hardcoded degree + deg = 4; + + % define current and (dummy) previous approximation point + zero = (a + b) / 2; + prevzero = zero + b - a; + + % initialize output + steps = [zero; func(zero)]; + + % iterate algorithm until the error is within tolerance + while abs(zero - prevzero) > tolerance + % calculate derivatives + deriv0 = func(zero); + deriv1 = deriv(func, zero, 1); + deriv2 = deriv(func, zero, 2); + + % calculate the square root in Laguerre's formula + lagsqrt = sqrt( ... + (deg - 1) * ((deg - 1) * deriv1 ^ 2 - deg * deriv0 * deriv2) ... + ); + + % calculate two possible values + zplus = deg * deriv0 / (deriv1 + lagsqrt); + zminus = deg * deriv0 / (deriv1 - lagsqrt); + + % choose value closer to current approximation + if abs(zplus) < abs(zminus) + newzero = zero - zplus; + else + newzero = zero - zminus; + end + + % update answer + prevzero = zero; + zero = newzero; + steps(:, size(steps, 2) + 1) = [zero, func(zero)]; + end +end diff --git a/ENUME/references/szopinski-enume/projC/adamspc.m b/ENUME/references/szopinski-enume/projC/adamspc.m new file mode 100644 index 00000000..d2d9e755 --- /dev/null +++ b/ENUME/references/szopinski-enume/projC/adamspc.m @@ -0,0 +1,52 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT C NUMBER 60 +% https://github.com/Lachcim/szopinski-enume + +% solve ODE system using Adams PC (P5EC5E) +function x = adamspc(functs, init, interval, stepsize) + % obtain first five steps from RK4 + [x, derivs] = rk4(functs, init, interval, stepsize, 5); + x = x(2:end, :); + + % define coefficient tables + beta = [1901, -2774, 2616, -1274, 251] / 720; + betastar = [475, 1427, -798, 482, -173, 27] / 1440; + + % build output based on preceding values + stepcount = ceil((interval(2) - interval(1)) / stepsize); + for step = 6:(stepcount + 1) + % predict + xpred = x(:, step - 1); + for eqnum = 1:size(functs, 1) + for prev = 1:5 + xpred(eqnum) = xpred(eqnum) ... + + stepsize * beta(prev) * derivs(eqnum, step - prev); + end + end + + % evaluate + derivpred = zeros(size(functs, 1), 1); + for eqnum = 1:size(functs, 1) + derivpred(eqnum) = functs{eqnum}(xpred); + end + + % correct + x(:, step) = x(:, step - 1); + for eqnum = 1:size(functs, 1) + for prev = 1:5 + x(eqnum, step) = x(eqnum, step) ... + + stepsize * betastar(prev + 1) * derivs(eqnum, step - prev); + end + x(eqnum, step) = x(eqnum, step) ... + + stepsize * betastar(1) * derivpred(eqnum); + end + + % evaluate + for eqnum = 1:size(functs, 1) + derivs(eqnum, step) = functs{eqnum}(x(:, step)); + end + end + + % append arguments to output + x = [interval(1):stepsize:(stepcount * stepsize); x]; +end diff --git a/ENUME/references/szopinski-enume/projC/auxplot.m b/ENUME/references/szopinski-enume/projC/auxplot.m new file mode 100644 index 00000000..b8012870 --- /dev/null +++ b/ENUME/references/szopinski-enume/projC/auxplot.m @@ -0,0 +1,41 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT C NUMBER 60 +% https://github.com/Lachcim/szopinski-enume + +% coordinate arguments +argsx = -1:0.1:1; +argsy = -2:0.5:12; + +% available functions +functs = { + "x_1", -67, 50, @(x, y) y + x * (0.5 - x^2 - y^2); + "x_2", -115, 30, @(x, y) -x + y * (0.5 - x^2 - y^2) +}; + +% plot each function +for funct = 1:size(functs, 1) + [functname, cama, camb, functh] = functs{funct, :}; + + % evaluate values + vals = zeros(length(argsx), length(argsy)); + for i = 1:size(argsx, 2) + for j = 1:size(argsy, 2) + vals(i, j) = functh(argsx(i), argsy(j)); + end + end + + % plot + figure; + surf(argsx, argsy, vals'); + title(strcat("Gradient of ", functname)); + xlabel('x_1'); + ylabel('x_2'); + zlabel(strcat("d", functname, "/dt")); + xlim([argsx(1), argsx(end)]); + ylim([argsy(1), argsy(end)]); + view(cama, camb); + grid on; + set(gcf, 'PaperPosition', [0 0 6 4]); + set(gcf, 'PaperSize', [6 4]); + print(strcat('report/', functname, 'gradient'), '-dpdf'); +end diff --git a/ENUME/references/szopinski-enume/projC/report/flowchart.pdf b/ENUME/references/szopinski-enume/projC/report/flowchart.pdf new file mode 100644 index 00000000..cb5589b6 Binary files /dev/null and b/ENUME/references/szopinski-enume/projC/report/flowchart.pdf differ diff --git a/ENUME/references/szopinski-enume/projC/report/projCreport.tex b/ENUME/references/szopinski-enume/projC/report/projCreport.tex new file mode 100644 index 00000000..ac6daf46 --- /dev/null +++ b/ENUME/references/szopinski-enume/projC/report/projCreport.tex @@ -0,0 +1,372 @@ +\documentclass{article} + +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{graphicx} +\usepackage{multicol} +\setlength{\parskip}{1em} + +\begin{document} + + \title{ENUME project report\\Project C: least-squares approximation \\ + and solving systems of differential equations} + \author{Michał Szopiński\\\\ + https://github.com/Lachcim/szopinski-enume\\ + Project number 60} + \date{January 7, 2021} + \maketitle + + \numberwithin{equation}{section} + + \setcounter{section}{-1} + \section{Abstract} + + This project explores the numerical methods of function approximation + and dynamic system analysis. The following concepts are discussed within + this document: + + \begin{itemize} + \item Performing the approximation of a function given by a set of + discrete data points by a polynomial function of a given degree + using the least-squares approach + \item Determining the trajectory of an object whose motion is + defined by a set of ordinary differential equations using the RK4 + and Adams PC algorithms + \end{itemize} + + \newpage + + \section{Task 1: Least-squares approximation} + + \subsection{Overview} + + The goal of this task was to find the approximation of a function given + by a set of data points. The approximating function was to be a + polynomial of varying degree (several degrees were to be tested). The + least-squares problem was to be solved using QR factorization. + + \subsection{Implementation} + + \subsubsection{Finding the vector $\widehat{a}$} + + The approximating function is given by: + \begin{equation} + a_0 + a_1x + a_2x^2 + a_3x^3 + \ldots + a_nx^n = 0 + \end{equation} + where $n$ is the degree of the approximating polynomial. The goal of the + approximation is to find a vector $\widehat{a} = [ a_0; a_1; \ldots; + a_n ]$ such that: + \begin{equation} + (\forall{a \in \mathbb{R}^n})\quad + \left\Vert y - A\widehat{a} \right\Vert_2 \leq + \left\Vert y - Aa \right\Vert_2 + \end{equation} + where $A\widehat{a}$ forms the vector of values of the approximating + function at each data point, and $y$ is the vector of the values of the + data points. In other words, the goal is to minimize the Euclidean norm + of the difference between the approximating function and the data + points. + + The most optimal vector $\widehat{a}$ can be obtained by calculating the + derivative of the error function with respect to $a_n$ and equating it + to zero. The resulting system of equations, called the + \textit{normal equations}, has a unique solution: the vector + $\widehat{a}$. + + \subsubsection{Solving normal equations using QR decomposition} + + Although this system could be solved directly using Gaussian elimination + or an iterative method, the matrix describing this system, called Gram's + matrix, tends to have a high condition number, which limits the accuracy + of the solution. For this reason, the matrix $A$ is defined: + \begin{equation} + A = \begin{bmatrix} + 1 & x_0 & (x_0)^2 & (x_0)^3 & \dots & (x_0)^n \\ + 1 & x_1 & (x_1)^2 & (x_1)^3 & \dots & (x_1)^n \\ + 1 & x_2 & (x_2)^2 & (x_2)^3 & \dots & (x_2)^n \\ + \vdots & \vdots & \vdots & \vdots & \ddots & \vdots \\ + 1 & x_N & (x_N)^2 & (x_N)^3 & \dots & (x_N)^n + \end{bmatrix} + \end{equation} + where $x_N$ is the x-axis position of the $N$-th data point. The system + of natural equations can then be expressed in terms of $A$ as follows: + \begin{equation} + (A^TA)\widehat{a} = A^Ty + \end{equation} + The condition number of $A$ is equal to the square root of the condition + number of the original Gram's matrix, which yields better numerical + properties. Furthermore, this form lends itself nicely to being solved + using QR factorization of $A$: + \begin{equation} + (R^TQ^T)(QR)\widehat{a} = (R^TQ^T)y + \end{equation} + By observing that $Q^TQ = I$ and $\det{R} \neq 0$, this equation can be + further reduced to: + \begin{equation} + R\widehat{a} = Q^Ty + \end{equation} + As an optimization, the QR decomposition can be replaced with a $\bar{Q} + \bar{R}$ decomposition, which is faster to calculate: + \begin{equation} + \bar{R}\widehat{a} = (\bar{Q}^T\bar{Q})^{-1}(\bar{Q}^T)y + \label{eq:rq} + \end{equation} + Because $\bar{R}$ is an upper triangular matrix, the + equation~\ref{eq:rq} can be easily solved using back-substitution. + + \subsubsection{Performing the $\bar{Q}\bar{R}$ decomposition of a + matrix} + + The $\bar{Q}\bar{R}$ decomposition is done using the modified + Gram-Schmidt algorithm. The decomposing function returns + $(\bar{Q}^T\bar{Q})^{-1}$ as part of its output and the final + normalization subroutine used for ordinary QR decomposition is skipped. + + \subsection{Program output} + + \subsubsection{Approximating function plots} + + \includegraphics[width=\textwidth]{approx0} + \includegraphics[width=\textwidth]{approx1} + \includegraphics[width=\textwidth]{approx2} + \includegraphics[width=\textwidth]{approx3} + + \subsubsection{Approximation errors and Gram's matrix condition number} + + \begin{center} + \begin{tabular}{|c|r|r|} + \hline + Degree & Error & Condition number \\ + \hline + 0 & 26.9222 & 1 \\ + 1 & 24.5645 & 10 \\ + 2 & 5.3885 & 408.7796 \\ + 3 & 0.8872 & 8558.4366 \\ + \hline + \end{tabular} + \end{center} + + \subsection{Observations} + + Increasing the degree of the approximating polynomial made it possible + to obtain a better approximation, i.e. one with a lower Euclidean norm + error. By degree 3, the polynomial approximated the data points nearly + perfectly and further approximation yielded no significant improvements. + + Higher polynomial degrees also caused the condition number of the Gram's + matrix to rise exponentially. This problem was mitigated by implementing + the QR decomposition of the matrix A, which made it possible to + calculate the solution to the set on normal equations with a better + accuracy. + + \newpage + \section{Task 2a: Trajectory calculation using fixed-step algorithms} + + \subsection{Overview} + + In this task, the goal was to compute the trajectory of an object whose + motion is described by a system of differential equations: + \begin{gather*} + \begin{cases} + \frac{dx_1}{dt} = x_2 + x_1(\frac{1}{2} - x_1^2 - x_2^2)\\ + \frac{dx_2}{dt} = -x_1 + x_2(\frac{1}{2} - x_1^2 - x_2^2) + \end{cases}\\ + t \in [0; 15]\\ + x_1(0) = 0\\ + x_2(0) = 12 + \end{gather*} + The system was to be solved using two fixed-step algorithms, RK4 and + Adams PC ($P_5EC_5E$). Two step sizes were to be chosen -- an ``optimal" + one and a larger, visibly differing one. + + \subsection{Implementation} + + Numerical methods of solving systems of differential equations involve + computing the value of the solution for a set of arguments belonging to + the prescribed interval. Based on a vector of initial values and a set + of functions describing the derivative of the solution, the output is + computed by integrating the derivative over a small interval, in this + context called a step. + + These algorithms can be divided into single-step and multi-step methods. + Single-step methods only consider one preceding data point of the + solution to calculate the next point, whereas multi-step algorithms + consider multiple predecessors. + + \subsubsection{4\textsuperscript{th}-order Runge-Kutta method (RK4)} + + A single iteration of any single-step method can be described by the + following formula: + \begin{equation} + y_{n + 1} = y_n + h\Phi_f(x_n; y_n; h) + \end{equation} + Where $y$ is the output solution vector, $x$ is the argument vector and + $h$ is the step size. The function $\Phi_f$ is specific to the applied + algorithm and it uses the provided data to calculate the next output + data point. + + The RK4 algorithm is defined as follows: + \begin{align} + \begin{split} + \Phi_f(x_n; y_n; h) &= \frac{1}{6}(k_1 + k_2 + k_3 + k_4)\\ + k_1 &= f(x_n, y_n)\\ + k_2 &= f(x_n + \frac{h}{2}, y_n + \frac{h}{2}k_1)\\ + k_3 &= f(x_n + \frac{h}{2}, y_n + \frac{h}{2}k_2)\\ + k_4 &= f(x_n + h, y_n + hk_3) + \end{split} + \end{align} + This algorithm is fairly simple to implement and produces visually + acceptable results. Because neither the system nor the algorithm utilize + the argument vector $x$, this parameter tends to be omitted in the + implementation. + + \subsubsection{Adams PC method ($P_5EC_5E$)} + + Adams predictor-corrector is a much more complicated, multi-step method + which uses which uses the following algorithm: + \begin{enumerate} + \item Predict: + \begin{equation*} + y^{[0]}_n = y_{n - 1} + h\sum_{j=1}^{5}\beta_j f_{n-j} + \end{equation*} + \item Evaluate: + \begin{equation*} + f^{[0]}_n = f(x_n, y^{[0]}_n) + \end{equation*} + \item Correct: + \begin{equation*} + y_n = y_{n - 1} + h\sum_{j=1}^{5}\beta^*_j f_{n-j} + + h\beta^*_0f^{[0]}_n + \end{equation*} + \item Evaluate: + \begin{equation*} + f_n = f(x_n, y_n) + \end{equation*} + \end{enumerate} + This algorithm serves to efficiently implement the implicit Adams + method. The predictor helps to do so by choosing a suitable starting + point. + + \subsection{Program output} + + \subsubsection{RK4 solution plots} + \includegraphics[width=\textwidth]{rk4x1} + \includegraphics[width=\textwidth]{rk4x2} + \includegraphics[width=\textwidth]{rk4traj} + + \subsubsection{Adams PC solution plots} + \includegraphics[width=\textwidth]{adamspcx1} + \includegraphics[width=\textwidth]{adamspcx2} + \includegraphics[width=\textwidth]{adamspctraj} + + \newpage + \subsection{Observations} + + For the Runge-Kutta method, the ``optimal" step size was 0.01, whereas + the largest feasible step size obtainable was 0.013408. Above this + limit, the integration diverged to the point where the trajectory + coordinates quickly reached infinity. Adams PC exhibited similar + behavior for step sizes above 0.01305. + + Analysis of the $x_2$ function reveals that it is extremely steep in the + neighborhood of the initial conditions, reaching a derivative of -1722 + in the first iteration: + \includegraphics[width=\textwidth]{x_2gradient} + For this reason, the resulting trajectory graph is much denser (in terms + of data points) near the final spiral than it is in the initial entry + path. + + In comparison, the $x_1$ component is relatively flat in the + neighborhood of the trajectory, with an initial derivative of 12:\\ + \includegraphics[width=\textwidth]{x_1gradient} + + This behavior likely serves to illustrate the necessity of the Lipschitz + condition for the integrability of a function. An infinitely steep + function cannot be integrated over a finite step, with additional + limitations superimposed by the machine precision of the computing + system. + + \newpage + \section{Task 2b: Trajectory calculation using variable-step RK4} + + \subsection{Overview} + + This variant of the previous task aims to reimplement the RK4 algorithm + with a variable step size determined by the double-step error + estimation. The step size and the error estimation were to be plotted + against time. Finally, the results were to be compared against a + solution obtained with ODE45. + + \subsection{Implementation} + + There exists an inherent conflict of interest between decreasing the + step size and increasing it -- smaller steps give more accurate results, + but they increase computation time and accumulate floating-point errors. + To solve this problem, the RK4 algorithm can be altered to dynamically + change the step size so as to achieve a predetermined desired accuracy, + in this case, a relative error of $10^{-10}$. + + To do so, the algorithm estimates the current approximation error on + each step and calculates the step scaling factor $\alpha$. The error is + estimated using the double-step method, where each iteration is computed + with a single full-sized step and two half-sized steps. Its value is + given by: + \begin{equation} + \delta_n(h) = \frac{y^{(2)}_n - y^{(1)}_n}{2^p - 1} + \end{equation} + where $y^{(q)}$ denotes the solution obtained after $q$ subsequent + $\frac{1}{q}$-steps. The error of a single step multiplied by $\alpha$ + is equal to: + \begin{equation} + \delta_n(\alpha h) = \alpha^{p + 1} \cdot \delta_n(h) + \end{equation} + If $\delta_n(\alpha h)$ is substituted for the desired error + $\varepsilon$, the above two equations can be combined to obtain: + \begin{equation} + \alpha = \left(\frac{\varepsilon}{\delta_n(h)}\right) + ^\frac{1}{p + 1} + \end{equation} + Finally, because $\varepsilon$ and $\delta_n$ are absolute errors, the + desired error can be formulated in terms of a relative and an absolute + input parameter: + \begin{equation} + \alpha = \left(\frac + {|y^{(2)}_n| \cdot \varepsilon_{rel} + \varepsilon_{abs}} + {|\delta_n(h)|}\right) + ^\frac{1}{p + 1} + \end{equation} + Lastly, the obtained scaling factor $\alpha$ is multiplied by a safety + factor of 0.9 to account for errors in the error estimation itself. + + A flowchart of the variable-stepped RK4 algorithm:\\ + \includegraphics[width=\textwidth]{flowchart} + + \subsection{Program output} + + \includegraphics[width=\textwidth]{rk4autotraj} + \includegraphics[width=\textwidth]{rk4sizes} + \includegraphics[width=\textwidth]{rk4errors} + \includegraphics[width=\textwidth]{ode45} + + \newpage + \subsection{Observations} + + The variable-step Runge-Kutta method provided an optimal solution + visually identical to that returned by Matlab's ODE45. As seen on the + step size plot, the step size was automatically increased for regions + with greater derivatives and decreased where the functions changed + slowly. + + The approximation error plot reveals that the algorithm succeeded in + maintaining an absolute error of $10^{-10}$. The only anomaly visible + at the start of the plot resulted from a poorly chosen initial step + size. + + Although the typical specification of a variable-step RK4 algorithm + calls for the implementation of a minimal step size $h_{min}$, this was + unnecessary for the purpose of this experiment -- the function was + successfully graphed with the desired accuracy. A more generic + implementation could benefit from an $h_{min}$ that would prevent + prohibitive computation times. + +\end{document} diff --git a/ENUME/references/szopinski-enume/projC/rk4.m b/ENUME/references/szopinski-enume/projC/rk4.m new file mode 100644 index 00000000..7c41221d --- /dev/null +++ b/ENUME/references/szopinski-enume/projC/rk4.m @@ -0,0 +1,35 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT C NUMBER 60 +% https://github.com/Lachcim/szopinski-enume + +% solve ODE system using RK4 with constant step size +function [x, derivs] = rk4(functs, init, interval, stepsize, maxsteps) + % set initial values as start points of output + x = init; + + % build derivatives table + derivs = zeros(size(x)); + for eqnum = 1:size(functs, 1) + derivs(eqnum, 1) = functs{eqnum}(x(:, 1)); + end + + % build output based on preceding values + stepcount = ceil((interval(2) - interval(1)) / stepsize); + if nargin >= 5; stepcount = min(stepcount, maxsteps - 1); end + for step = 1:stepcount + % obtain the preceding function values + stepval = x(:, step); + + for eqnum = 1:size(functs, 1) + % generic single-step iteration + phi = rk4phi(functs{eqnum}, stepval, stepsize); + x(eqnum, step + 1) = x(eqnum, step) + stepsize * phi; + + % update derivatives table + derivs(eqnum, step + 1) = functs{eqnum}(x(:, step + 1)); + end + end + + % append arguments to output + x = [interval(1):stepsize:(stepcount * stepsize); x]; +end diff --git a/ENUME/references/szopinski-enume/projC/rk4auto.m b/ENUME/references/szopinski-enume/projC/rk4auto.m new file mode 100644 index 00000000..bc68518b --- /dev/null +++ b/ENUME/references/szopinski-enume/projC/rk4auto.m @@ -0,0 +1,65 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT C NUMBER 60 +% https://github.com/Lachcim/szopinski-enume + +% automatic step size variant of RK4 +function [x, sizes, errors] = rk4auto(functs, init, interval, initstep, eps_rel, eps_abs) + % set start points of output + args = interval(1); + x = init; + + % initialize output plots + sizes = double.empty(); + errors = double.empty(); + + % integrate function until end of interval reached + stepsize = initstep; + step = 0; + while 1 + % obtain the preceding function values + step = step + 1; + stepval = x(:, step); + + % advance output function + for eqnum = 1:size(functs, 1) + % generic single-step iteration + phi = rk4phi(functs{eqnum}, stepval, stepsize); + x(eqnum, step + 1) = x(eqnum, step) + stepsize * phi; + end + + % stop algorithm if function integrated over the whole interval + args(step + 1) = args(step) + stepsize; + if args(end) >= interval(2); break; end + + % also calculate next step using two half-steps + for substep = 1:2 + for eqnum = 1:size(functs, 1) + phi = rk4phi(functs{eqnum}, stepval, stepsize / 2); + stepval(eqnum) = stepval(eqnum) + (stepsize / 2) * phi; + end + end + + % calculate step correction factor + alpha = Inf; + for eqnum = 1:size(functs, 1) + % calculate approximation error + delta = abs(stepval(eqnum) - x(eqnum, step + 1)) / 15; + errors(step) = delta; + + % calculate equation-specific alpha + epsilon = abs(stepval(eqnum)) * eps_rel + eps_abs; + eqalpha = epsilon / delta; + + % minimum alpha wins + if eqalpha < alpha; alpha = eqalpha; end + end + alpha = alpha ^ (1/5); + + % correct step size with safety factor + stepsize = 0.9 * alpha * stepsize; + sizes(step) = stepsize; + end + + % append arguments to output + x = [args; x]; +end diff --git a/ENUME/references/szopinski-enume/projC/rk4phi.m b/ENUME/references/szopinski-enume/projC/rk4phi.m new file mode 100644 index 00000000..12a0f1a0 --- /dev/null +++ b/ENUME/references/szopinski-enume/projC/rk4phi.m @@ -0,0 +1,12 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT C NUMBER 60 +% https://github.com/Lachcim/szopinski-enume + +% calculate the phi for RK4 algorithms +function phi = rk4phi(fun, stepval, stepsize) + k1 = fun(stepval); + k2 = fun(stepval + 0.5 * stepsize * k1); + k3 = fun(stepval + 0.5 * stepsize * k2); + k4 = fun(stepval + stepsize * k3); + phi = (k1 + 2 * k2 + 2 * k3 + k4) / 6; +end diff --git a/ENUME/references/szopinski-enume/projC/task1lsapprox.m b/ENUME/references/szopinski-enume/projC/task1lsapprox.m new file mode 100644 index 00000000..a1c0a1d6 --- /dev/null +++ b/ENUME/references/szopinski-enume/projC/task1lsapprox.m @@ -0,0 +1,88 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT C NUMBER 60 +% TASK 1 +% https://github.com/Lachcim/szopinski-enume + +% use functions from project A if not present in the working directory +if ~exist('qrdecomp', 'var') + addpath('../projA'); +end + +% define function data points +taskfunc = (-5:5)'; +taskfunc(:, 2) = [ + -15.2991; + -11.9874; + -7.8757; + -5.7178; + -3.3653; + -2.5691; + -3.3150; + -6.2274; + -10.7044; + -19.1618; + -30.7795 +]; + +% perform the task +for polydeg = 0:3 + % obtain factors of approximating polynomial + [factors, error, gramcond] = approximate(taskfunc, polydeg); + + % print error and condition number + disp(['Approximation degree ', num2str(polydeg), ':']); + disp(['Error: ', num2str(error)]); + disp(['Condition number: ', num2str(gramcond)]); + + % plot data points + figure; + grid on; + hold on; + title(['Polynomial approximation of the function (degree ', ... + num2str(polydeg), ')']); + scatter(taskfunc(:, 1), taskfunc(:, 2)); + + % plot approximation + x = taskfunc(1):0.05:taskfunc(end, 1); + y = evalapprox(factors, x); + plot(x, y); + + % finish and print graph + hold off; + set(gcf, 'PaperPosition', [0 0 6 4]); + set(gcf, 'PaperSize', [6 4]); + print(['report/approx', num2str(polydeg)], '-dpdf'); +end + +% find the approximating polynomial of the given degree +function [factors, error, gramcond] = approximate(func, polydeg) + % define the A matrix used for solving the error minimization problem + A = zeros(size(func, 1), polydeg + 1); + + % calculate cells of A using natural basis + for row = 1:size(A, 1) + for col = 1:size(A, 2) + A(row, col) = func(row, 1) ^ (col - 1); + end + end + + % solve least-square problem using QRdash decomposition + [Q, eqsys, invqtq] = qrdecomp(A, true); + eqsys(:, end + 1) = invqtq * Q' * func(:, 2); + factors = backsubst(eqsys); + + % calculate error and condition number of Gram's matrix + error = norm(func(:, 2) - A * factors); + gramcond = cond(A' * A); +end + +% evaluate the value of an approximation at the given x +function y = evalapprox(factors, xarray) + y = zeros(1, size(xarray, 2)); + + for xi = 1:size(xarray, 2) + for i = 1:size(factors, 1) + y(xi) = y(xi) + factors(i) * xarray(xi) ^ (i - 1); + end + end +end diff --git a/ENUME/references/szopinski-enume/projC/task2ode.m b/ENUME/references/szopinski-enume/projC/task2ode.m new file mode 100644 index 00000000..470df7d2 --- /dev/null +++ b/ENUME/references/szopinski-enume/projC/task2ode.m @@ -0,0 +1,109 @@ +% ENUME MICHAŁ SZOPIŃSKI +% PROJECT C NUMBER 60 +% TASK 2 +% https://github.com/Lachcim/szopinski-enume + +% functions of the ODE system and initial values +sysfuncts = { + @(x) x(2) + x(1) * (0.5 - x(1)^2 - x(2)^2); + @(x) -x(1) + x(2) * (0.5 - x(1)^2 - x(2)^2) +}; +initvalues = [0; 12]; +interval = [0; 15]; + +% define available algorithms +algorithms = { + 'RK4', @rk4, [0.01, 0.013408]; + 'Adams PC', @adamspc, [0.002, 0.01305] +}; + +% solve ODE using different algorithms and step sizes +for alg = 1:size(algorithms, 1) + [algname, algfunc, stepsizes] = algorithms{alg, :}; + + % solve using the given algorithm for each step size + stepresults = cell(size(stepsizes, 2), 3); + stepnames = {'optimal step', 'larger step'}; + for stepno = 1:size(stepsizes, 2) + result = algfunc(sysfuncts, initvalues, interval, stepsizes(stepno)); + stepresults(stepno, :) = { ... + stepsizes(stepno), ... + stepnames{stepno}, ... + result}; + end + + % plot each component against time + for eqnum = 1:size(sysfuncts, 1) + % begin plot + figure; grid on; hold on; + title([algname, ', x_', num2str(eqnum), ' against time']); + set(gcf, 'PaperPosition', [0 0 6 4]); + set(gcf, 'PaperSize', [6 4]); + + % plot component for each step size + for stepresult = stepresults' + plot(stepresult{3}(1, :), stepresult{3}(eqnum + 1, :)); + end + + % finish plot + hold off; + legend(stepresults{:, 2}); + print(['report/', func2str(algfunc), 'x', num2str(eqnum)], '-dpdf'); + end + + % plot first two components against each other + figure; grid on; hold on; + title([algname, ' trajectory plot (x_2 against x_1)']); + set(gcf, 'PaperPosition', [0 0 6 4]); + set(gcf, 'PaperSize', [6 4]); + + % plot for each step size + for stepresult = stepresults' + plot(stepresult{3}(2, :), stepresult{3}(3, :)); + end + + % finish plot + hold off; + legend(stepresults{:, 2}); + print(['report/', func2str(algfunc), 'traj'], '-dpdf'); +end + +% solve ODE using RK4 with automatic step size +[result, sizes, errors] = rk4auto(sysfuncts, initvalues, interval, ... + 1e-5, 10e-10, 10e-10); + +% plot trajectory +figure; +plot(result(2, :), result(3, :)); +grid on; +title('RK4 auto-step trajectory plot (x_2 against x_1)'); +set(gcf, 'PaperPosition', [0 0 6 4]); +set(gcf, 'PaperSize', [6 4]); +print(['report/', 'rk4autotraj'], '-dpdf'); + +% plot statistics +stats = { + "RK4 auto-step step size", "rk4sizes", sizes; + "RK4 auto-step approximation error", "rk4errors", errors +}; +for stat = stats' + figure; + plot(result(1, 2:(end - 1)), stat{3}); + grid on; + title(stat{1}); + set(gcf, 'PaperPosition', [0 0 6 4]); + set(gcf, 'PaperSize', [6 4]); + print(strcat("report/", stat{2}), '-dpdf'); +end + +% compare results with ODE45 +odefun = @(t, x) [ sysfuncts{1}(x); sysfuncts{2}(x) ]; +odeoptions = odeset('RelTol', 10e-10, 'AbsTol', 10e-10); +[t, x] = ode45(odefun, interval, initvalues, odeoptions); +figure; +plot(x(:, 1), x(:, 2)); +grid on; +title('ODE45 trajectory plot (x_2 against x_1)'); +set(gcf, 'PaperPosition', [0 0 6 4]); +set(gcf, 'PaperSize', [6 4]); +print('report/ode45', '-dpdf');