WUT_Computer_Science/NotProgramming/ENUME/projectA/QRShifts.m

136 lines
5.0 KiB
Mathematica
Raw Normal View History

2021-11-12 07:59:54 +01:00
% finds the eigenValues of a matrix using QR with shifts
function [eigenValues, whatIterationAreWeOn, Matrix] = QRShifts(Matrix)
eigenFromMatlab = eig(Matrix);
2021-11-12 08:41:21 +01:00
initialMatrix = Matrix;
2021-11-12 07:59:54 +01:00
[eigenValues, whatIterationAreWeOn, matrixSize, minThreshold] = initiateValues(Matrix);
[Matrix, whatIterationAreWeOn, eigenValues] = QRShiftLoop(matrixSize, Matrix, eigenValues, minThreshold, whatIterationAreWeOn);
2021-11-12 19:01:29 +01:00
dispResults(eigenValues, Matrix, whatIterationAreWeOn, eigenFromMatlab, initialMatrix);
2021-11-12 07:59:54 +01:00
end
function [eigenValues, whatIterationAreWeOn, matrixSize, minThreshold] = initiateValues(Matrix)
eigenValues = double.empty(1, 0);
whatIterationAreWeOn = 0;
matrixSize = size(Matrix, 1);
minThreshold = 1e-6;
end
function [Matrix, whatIterationAreWeOn, eigenValues] = QRShiftLoop(matrixSize, Matrix, eigenValues, minThreshold, whatIterationAreWeOn)
while matrixSize >= 2
flag = 0;
[Matrix, matrixSize, whatIterationAreWeOn, eigenValues] = findEigenValue(Matrix, matrixSize, whatIterationAreWeOn, eigenValues, minThreshold, flag);
[matrixSize, Matrix] = deflateMatrix(Matrix, matrixSize);
end
eigenValues(size(eigenValues, 2) + 1) = Matrix(1, 1);
end
function [Matrix, matrixSize, whatIterationAreWeOn, eigenValues] = findEigenValue(Matrix, matrixSize, whatIterationAreWeOn, eigenValues, minThreshold, flag)
while flag == 0
eigenValueCorner = getEigenValueFromCorner(Matrix, matrixSize);
[Matrix, whatIterationAreWeOn] = shiftAndIterate(matrixSize, Matrix, eigenValueCorner, whatIterationAreWeOn);
[flag, eigenValues] = thresholdBreached(Matrix, matrixSize, minThreshold, eigenValues);
end
end
function eigenValueCorner = getEigenValueFromCorner(Matrix, matrixSize)
corner = Matrix((matrixSize - 1) : matrixSize, (matrixSize - 1) : matrixSize);
% get 2 x 2 corner of the matrix
eigenValueCorner = solveCharactersticEquation(corner);
end
function [Matrix, whatIterationAreWeOn] = shiftAndIterate(matrixSize, Matrix, eigenValueCorner, whatIterationAreWeOn)
% shift and iterate algorithm
identityMatrix = eye(matrixSize);
Matrix = Matrix - identityMatrix * eigenValueCorner;
[Q, R] = gramSchmidtAlgorithm(Matrix);
Matrix = R * Q + identityMatrix * eigenValueCorner;
whatIterationAreWeOn = whatIterationAreWeOn + 1;
end
function [matrixSize, Matrix] = deflateMatrix(Matrix, matrixSize)
matrixSize = matrixSize - 1;
Matrix = Matrix(1:matrixSize, 1:matrixSize);
end
function [flag, eigenValues] = thresholdBreached(Matrix, matrixSize, minThreshold, eigenValues)
flag = 0;
threshold = max(abs(Matrix(matrixSize, 1:(matrixSize - 1))));
% once we zero the row (or rather get close enough to zero) exit loop
if (threshold <= minThreshold)
eigenValues(size(eigenValues, 2) + 1) = Matrix(matrixSize, matrixSize);
flag = 1;
end
end
% finds the eigenvalue of a 2x2 matrix that is closer to the lower right corner
function eigen = solveCharactersticEquation(Matrix)
[eigenOne, eigenTwo] = calculateZeros(Matrix);
eigen = valueCloserToLowerRightCorner(eigenOne, eigenTwo, Matrix);
end
function eigen = valueCloserToLowerRightCorner(eigenOne, eigenTwo, Matrix)
if abs(Matrix(4) - eigenOne) < abs(Matrix(4) - eigenTwo)
eigen = eigenOne;
else
eigen = eigenTwo;
end
end
function [zeroOne, zeroTwo] = calculateZeros(Matrix)
b = Matrix(1) + Matrix(4);
ac = Matrix(1) * Matrix(4) - Matrix(2) * Matrix(3);
delta = (b) ^ 2 - 4 * ac;
% get delta of quadratic equation
squareRootDelta = sqrt(delta);
% square delta
zeroOne = (b - squareRootDelta) / 2;
zeroTwo = (b + squareRootDelta) / 2;
end
% performs QR or QRdash decomposition of a matrix
function [Q, R] = gramSchmidtAlgorithm(Matrix)
[columns, Q, R, d] = initializeGramSchmid(Matrix);
[Q, R] = factorizeColumnsOfQ(columns, Q, Matrix, R, d);
[Q, R] = normalizeColumns(columns, Q, R);
end
function [columns, Q, R, d] = initializeGramSchmid(Matrix)
% We start with empty matrices
[rows, columns] = size(Matrix);
Q = zeros(rows, columns);
R = zeros(columns, columns);
d = zeros(1, columns);
end
function [Q, R] = factorizeColumnsOfQ(columns, Q, Matrix, R, d)
for i = 1 : columns
Q(:, i) = Matrix(:, i);
R(i, i) = 1;
d(i) = Q(:, i)' * Q(:, i);
for i2 = i + 1 : columns
R(i, i2) = (Q(:, i)' * Matrix(:, i2)) / d(i);
Matrix(:, i2) = Matrix(:, i2) - R(i, i2) * Q(:, i);
end
end
end
function [Q, R] = normalizeColumns(columns, Q, R)
for i = 1 : columns
dd = norm(Q(:, i));
Q(:, i) = Q(:, i) / dd;
R(i, i:columns) = R(i, i : columns) * dd;
end
end
2021-11-12 09:44:22 +01:00
function dispResults(eigenValues, Matrix, whatIterationAreWeOn, eigenFromMatlab, initialMatrix)
2021-11-12 08:41:21 +01:00
disp("Initial matrix: ");
disp(initialMatrix);
2021-11-12 07:59:54 +01:00
disp("Final matrix: ");
disp(Matrix);
disp("Number of iterations: ");
disp(whatIterationAreWeOn);
disp("Eigen values from eig(Matrix):");
disp(eigenFromMatlab);
disp("Our eigen values: ");
2021-11-12 09:44:22 +01:00
disp(eigenValues);
2021-11-12 07:59:54 +01:00
end