mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-07-04 20:03:04 +02:00
136 lines
5.0 KiB
Matlab
136 lines
5.0 KiB
Matlab
% finds the eigenValues of a matrix using QR with shifts
|
|
function [eigenValues, whatIterationAreWeOn, Matrix] = QRShifts(Matrix)
|
|
eigenFromMatlab = eig(Matrix);
|
|
initialMatrix = Matrix;
|
|
[eigenValues, whatIterationAreWeOn, matrixSize, minThreshold] = initiateValues(Matrix);
|
|
[Matrix, whatIterationAreWeOn, eigenValues] = QRShiftLoop(matrixSize, Matrix, eigenValues, minThreshold, whatIterationAreWeOn);
|
|
dispResults(eigenValues, Matrix, whatIterationAreWeOn, eigenFromMatlab, initialMatrix);
|
|
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
|
|
|
|
function dispResults(eigenValues, Matrix, whatIterationAreWeOn, eigenFromMatlab, initialMatrix)
|
|
disp("Initial matrix: ");
|
|
disp(initialMatrix);
|
|
disp("Final matrix: ");
|
|
disp(Matrix);
|
|
disp("Number of iterations: ");
|
|
disp(whatIterationAreWeOn);
|
|
disp("Eigen values from eig(Matrix):");
|
|
disp(eigenFromMatlab);
|
|
disp("Our eigen values: ");
|
|
disp(eigenValues);
|
|
end |