% Givens旋转变换的QL/R分解脚本(直接运行版)
% 功能:无需函数调用,通过Givens旋转变换实现QL分解(X=1)或QR分解(X=2),输出变换矩阵Q、分解后矩阵A及迭代次数k
% 原理:根据X选择上三角(QL)或下三角(QR)分解,通过Givens旋转逐步消去非三角元素,直到收敛
% 运行方式:直接运行此m脚本,无需命令行操作,结果自动输出
clear; clc; % 清空工作区变量与命令行窗口,避免历史数据干扰
%% 1. 输入计算所需参数(可根据需求替换)
% 待分解的方阵A(示例为3阶矩阵,可替换为任意方阵,确保迭代收敛)
A = [5 2 1;
2 6 3;
1 3 7];
% 分解模式选择:X=1为QL分解(基于上三角);X=2为QR分解(基于下三角)
X = 1; % 可修改为2切换至QR分解
% 输出输入信息,便于后续对比
fprintf('待分解的矩阵A:\n');
disp(A);
if X == 1
fprintf('\n分解模式:QL分解(基于Givens旋转变换,目标化为下三角矩阵)\n');
elseif X == 2
fprintf('\n分解模式:QR分解(基于Givens旋转变换,目标化为上三角矩阵)\n');
else
error('分解模式X必须为1(QL)或2(QR)!'); % 检查输入合法性
end
[m,n] = size(A);
if m ~= n
error('输入矩阵A必须为方阵!'); % QL/R分解仅适用于方阵
end
%% 2. Givens旋转变换QL/R分解核心逻辑(整合原R_QLR函数核心代码)
C2 = 1; % 收敛判断指标(初始设为1,满足循环条件)
Q = eye(n); % 初始化变换矩阵Q为n阶单位矩阵(累积Givens旋转)
k = 0; % 迭代次数计数器
% 根据X选择分解模式(QL或QR),设置对应的矩阵提取函数和参数
switch X
case 1 % QL分解:基于上三角部分,目标将A化为下三角矩阵
fun = @triu; % 提取上三角矩阵(含对角线)
option = 1; % triu的第二个参数,1表示提取主对角线及以上
opbreak = 1; % 停止条件的列索引(当最大元素在第1列时停止)
case 2 % QR分解:基于下三角部分,目标将A化为上三角矩阵
fun = @tril; % 提取下三角矩阵(含对角线)
option = -1; % tril的第二个参数,-1表示提取主对角线及以下
opbreak = n; % 停止条件的列索引(当最大元素在第n列时停止)
end
% 迭代循环:当最大非三角元素的绝对值小于1e-10时收敛
while abs(C2) > 1e-10
% 步骤1:提取当前模式下的三角部分(上三角或下三角)
A1 = fun(A, option);
% 步骤2:寻找三角部分中绝对值最大的元素位置(i,j)
[C1, I1] = max(abs(A1)); % C1为每列最大绝对值,I1为对应行索引
[C2, j] = max(C1); % C2为全局最大绝对值,j为对应列索引
i = I1(j); % i为全局最大元素的行索引
% 步骤3:判断是否达到停止条件(最大元素在目标列时停止)
if j == opbreak
break;
end
% 步骤4:构造Givens旋转矩阵R(用于消去A(i,j)元素)
d = A(i,j) / A(j,j); % 计算旋转参数d
c = 1 / sqrt(1 + d^2); % 旋转矩阵的余弦分量
s = -d * c; % 旋转矩阵的正弦分量
R = eye(n); % 初始化n阶单位矩阵
R(i,i) = c; R(i,j) = s; % 填充旋转矩阵的(i,i)和(i,j)位置
R(j,i) = -s; R(j,j) = c; % 填充旋转矩阵的(j,i)和(j,j)位置
% 步骤5:更新变换矩阵Q和待分解矩阵A
Q = Q * R'; % Q累积旋转(R'为R的转置,因Givens矩阵正交,R'=R逆)
A = R * A; % 左乘R,逐步将A化为目标三角矩阵
k = k + 1; % 迭代次数加1
end
%% 3. 输出计算结果
fprintf('\n==================== Givens旋转变换分解结果 ====================\n');
fprintf('1. 迭代次数 k = %d\n', k); % 输出总迭代次数
fprintf('\n2. 正交变换矩阵 Q(满足Q''=Q逆):\n');
disp(Q);
if X == 1
fprintf('\n3. QL分解后的下三角矩阵 A(满足A = QL,L为下三角):\n');
else
fprintf('\n3. QR分解后的上三角矩阵 A(满足A = QR,R为上三角):\n');
end
disp(A);
%% 4. 结果验证(验证分解正确性)
fprintf('\n==================== 结果验证 ====================\n');
% 验证1:Q是否为正交矩阵(Q'*Q应接近单位矩阵)
ortho_check = Q' * Q;
fprintf('Q的正交性验证(Q''*Q 应接近单位矩阵):\n');
disp(ortho_check);
% 验证2:分解正确性(QL或QR应接近原始矩阵)
if X == 1 % QL分解:原始A ≈ Q * 分解后的A(因A=QL,L为分解后的下三角)
recover_A = Q * A;
fprintf('\nQL分解验证(原始A ≈ Q * 分解后A):\n');
else % QR分解:原始A ≈ Q * 分解后的A(因A=QR,R为分解后的上三角)
recover_A = Q * A;
fprintf('\nQR分解验证(原始A ≈ Q * 分解后A):\n');
end
disp(recover_A);
% 量化误差(Frobenius范数)
error = norm(recover_A - A, 'fro');
fprintf('\n分解误差(||恢复矩阵 - 原始矩阵||_F):%.6e\n', error);
fprintf('说明:误差为浮点计算误差,数值≤1e-10时表明分解正确。\n');