找回密码
 立即注册
首页 业界区 业界 Hilbert 矩阵的求解

Hilbert 矩阵的求解

墨佳美 2026-3-11 06:05:08
博客地址:https://www.cnblogs.com/zylyehuo/
运行效果

1.png

2.png

3.png

运行代码
  1. clear; clc; close all;
  2. % ============================================ 参数定义 ============================================
  3. n = 2;              % Hilbert矩阵的维数
  4. maxIter = 40;      % 最大迭代次数
  5. omega = 0.75;        % SOR松弛因子
  6. epsilon = 1e-2;     % 迭代绝对误差限
  7. % ============================================ 主函数调用 ============================================
  8. main(n, maxIter, omega, epsilon);
  9. % ============================================ SOR松弛因子优化模块 ============================================
  10. fprintf('\n\n=========================================== SOR松弛因子优化分析 ===========================================\n');
  11. findOptimalOmega(n, maxIter, epsilon, omega);
  12. % ============================================ 主函数模块 ============================================
  13. function main(n, maxIter, omega, epsilon)
  14.     fprintf('=========================================== 主程序开始 ===========================================\n');
  15.     % 生成 Hilbert 矩阵
  16.     H = myHilbert(n);
  17.     fprintf('生成的 Hilbert(%d) 矩阵为:\n', n);
  18.     disp(H);
  19.     fprintf('------------------------------------------------------------------------------------------------------------------------\n');
  20.    
  21.     x_exact = ones(n, 1);
  22.     fprintf('精确解 x* = [' );
  23.     fprintf('%.16f, ', x_exact(1:end-1));
  24.     fprintf('%.16f]^T\n', x_exact(end));
  25.    
  26.     % 计算右端向量 b = H * x_exact
  27.     b = H * x_exact;
  28.     fprintf('右端向量 b = [' );
  29.     fprintf('%.16f, ', b(1:end-1));
  30.     fprintf('%.16f]^T\n', b(end));
  31.     fprintf('------------------------------------------------------------------------------------------------------------------------\n');
  32.     % 高斯消去法
  33.     x_gauss = gaussianElimination(H, b);
  34.     err_gauss = norm(x_gauss - x_exact);
  35.     fprintf('高斯消去法求得解 x = [' );
  36.     fprintf('%.16f, ', x_gauss(1:end-1));
  37.     fprintf('%.16f]^T\n', x_gauss(end));
  38.     fprintf('高斯消去法绝对误差 = %.6e\n', err_gauss);
  39.     fprintf('------------------------------------------------------------------------------------------------------------------------\n');
  40.    
  41.     % Jacobi 迭代
  42.     [x_jacobi, err_history_jacobi, iter_jacobi, spectral_radius_jacobi] = jacobiIteration(H, b, maxIter, epsilon, x_exact);
  43. %     fprintf('Jacobi 迭代法最终解 x = [' );
  44. %     fprintf('%.16f, ', x_jacobi(1:end-1));
  45. %     fprintf('%.16f]^T\n', x_jacobi(end));
  46.     % Gauss-Seidel 迭代
  47.     [x_gs, err_history_gs, iter_gs, spectral_radius_gs] = gaussSeidelIteration(H, b, maxIter, epsilon, x_exact);
  48. %     fprintf('Gauss-Seidel 迭代法最终解 x = [' );
  49. %     fprintf('%.16f, ', x_gs(1:end-1));
  50. %     fprintf('%.16f]^T\n', x_gs(end));
  51.     % SOR 迭代
  52.     [x_sor, err_history_sor, iter_sor, spectral_radius_sor] = SORIteration(H, b, omega, maxIter, epsilon, x_exact);
  53. %     fprintf('SOR 迭代法最终解 x = [' );
  54. %     fprintf('%.16f, ', x_sor(1:end-1));
  55. %     fprintf('%.16f]^T\n', x_sor(end));
  56.     % ============================================ 可视化模块 ============================================
  57.     visualizeResults(x_gauss, x_jacobi, x_gs, x_sor, x_exact, ...
  58.                     err_history_jacobi, err_history_gs, err_history_sor, ...
  59.                     iter_jacobi, iter_gs, iter_sor, ...
  60.                     spectral_radius_jacobi, spectral_radius_gs, spectral_radius_sor, epsilon);
  61.     fprintf('========================================================================================================\n');
  62.     fprintf('程序运行结束。\n');
  63.     fprintf('========================================================================================================\n');
  64. end
  65. % ====================== 生成 Hilbert 矩阵 ======================
  66. function H = myHilbert(n)
  67.     H = zeros(n);
  68.     for i = 1:n
  69.         for j = 1:n
  70.             H(i,j) = 1 / (i + j - 1);
  71.         end
  72.     end
  73. end
  74. % ====================== 高斯消去法 ======================
  75. function x = gaussianElimination(A, b)
  76.     fprintf('=================== 高斯消去法求解过程 ===================\n');
  77.     n = length(b);
  78.     % 构造增广矩阵
  79.     Aug = [A, b];
  80.     fprintf('初始增广矩阵 [A|b]:\n');
  81.     disp(Aug);
  82.    
  83.     % 前向消元
  84.     fprintf('\n--- 前向消元过程 ---\n');
  85.     for k = 1:n-1
  86.         fprintf('第 %d 步消元:\n', k);
  87.         fprintf('主元: A(%d,%d) = %.6f\n', k, k, Aug(k,k));
  88.         
  89.         for i = k+1:n
  90.             factor = Aug(i,k)/Aug(k,k);
  91.             fprintf('对第 %d 行,消元因子 = %.6f\n', i, factor);
  92.             
  93.             Aug(i,k:n+1) = Aug(i,k:n+1) - factor*Aug(k,k:n+1);
  94.             fprintf('消元后的增广矩阵:\n');
  95.             disp(Aug);
  96.         end
  97.         fprintf('\n');
  98.     end
  99.    
  100.     fprintf('消元完成后的上三角增广矩阵:\n');
  101.     disp(Aug);
  102.    
  103.     % 回代求解
  104.     fprintf('\n--- 回代求解过程 ---\n');
  105.     x = zeros(n,1);
  106.     for i = n:-1:1
  107.         if i == n
  108.             x(i) = Aug(i,n+1)/Aug(i,i);
  109.             fprintf('x(%d) = b(%d)/A(%d,%d) = %.6f/%.6f = %.6f\n', ...
  110.                     i, i, i, i, Aug(i,n+1), Aug(i,i), x(i));
  111.         else
  112.             sum_val = Aug(i,i+1:n)*x(i+1:n);
  113.             x(i) = (Aug(i,n+1) - sum_val)/Aug(i,i);
  114.             fprintf('x(%d) = (b(%d) - A(%d,%d:%d)*x(%d:%d))/A(%d,%d) = (%.6f - %.6f)/%.6f = %.6f\n', ...
  115.                     i, i, i, i+1, n, i+1, n, i, i, Aug(i,n+1), sum_val, Aug(i,i), x(i));
  116.         end
  117.     end
  118.    
  119.     fprintf('\n高斯消去法求解完成\n');
  120.     fprintf('==========================================================\n');
  121. end
  122. % ====================== 使用增广矩阵求解线性方程组 ======================
  123. function x = solveWithAugmented(A, b)
  124.     % 使用增广矩阵和高斯消元法求解 Ax = b
  125.     n = length(b);
  126.     Aug = [A, b];
  127.    
  128.     % 前向消元
  129.     for k = 1:n-1
  130.         for i = k+1:n
  131.             factor = Aug(i,k)/Aug(k,k);
  132.             Aug(i,k:n+1) = Aug(i,k:n+1) - factor*Aug(k,k:n+1);
  133.         end
  134.     end
  135.    
  136.     % 回代求解
  137.     x = zeros(n,1);
  138.     for i = n:-1:1
  139.         x(i) = (Aug(i,n+1) - Aug(i,i+1:n)*x(i+1:n))/Aug(i,i);
  140.     end
  141. end
  142. % ====================== 幂方法计算谱半径 ======================
  143. function spectral_radius = powerMethod(M, maxIter, tol)
  144.     % 幂方法计算矩阵的谱半径
  145.     n = size(M, 1);
  146.     x = rand(n, 1);
  147.     x = x / norm(x);
  148.    
  149.     lambda_prev = 0;
  150.    
  151.     for k = 1:maxIter
  152.         y = M * x;
  153.         lambda = norm(y);
  154.         x = y / lambda;
  155.         
  156.         if abs(lambda - lambda_prev) < tol
  157.             break;
  158.         end
  159.         lambda_prev = lambda;
  160.     end
  161.    
  162.     spectral_radius = lambda;
  163. end
  164. % ====================== 手动计算2x2矩阵特征值 ======================
  165. function eigenvalues = manualEigenvalues2x2(M)
  166.     % 手动计算2x2矩阵的特征值
  167.     a = M(1,1); b = M(1,2);
  168.     c = M(2,1); d = M(2,2);
  169.    
  170.     trace_M = a + d;
  171.     det_M = a*d - b*c;
  172.     discriminant = trace_M^2 - 4*det_M;
  173.    
  174.     if discriminant >= 0
  175.         lambda1 = (trace_M + sqrt(discriminant)) / 2;
  176.         lambda2 = (trace_M - sqrt(discriminant)) / 2;
  177.         eigenvalues = [lambda1, lambda2];
  178.     else
  179.         real_part = trace_M / 2;
  180.         imag_part = sqrt(-discriminant) / 2;
  181.         eigenvalues = [real_part + 1i*imag_part, real_part - 1i*imag_part];
  182.     end
  183. end
  184. % ====================== Jacobi 迭代 ======================
  185. function [x, err_history, iter, spectral_radius] = jacobiIteration(A, b, maxIter, epsilon, x_exact)
  186.     n = length(b);
  187.     x = zeros(n,1);
  188.     err_history = zeros(maxIter, 1);
  189.     D = diag(diag(A));
  190.     L = -tril(A,-1);
  191.     U = -triu(A,1);
  192.     fprintf('---------------- Jacobi 迭代 ----------------\n');
  193.     fprintf('系数矩阵 A:\n'); disp(A);
  194.     fprintf('对角矩阵 D:\n'); disp(D);
  195.     fprintf('严格下三角矩阵 -L:\n'); disp(-L);
  196.     fprintf('严格上三角矩阵 -U:\n'); disp(U);
  197.    
  198.     % 计算迭代矩阵 M = D^{-1}(L+U)
  199.     M = zeros(n);
  200.     for i = 1:n
  201.         % 计算 M 的第 i 行:求解 D * m_i = (L+U) 的第 i 行
  202.         rhs = L(i,:)' + U(i,:)';
  203.         m_i = solveWithAugmented(D, rhs);
  204.         M(i,:) = m_i';
  205.     end
  206.    
  207.     % 计算常数向量 c = D^{-1}b
  208.     c = solveWithAugmented(D, b);
  209.    
  210.     % 计算谱半径
  211.     if n == 2
  212.         eigenvalues = manualEigenvalues2x2(M);
  213.         spectral_radius = max(abs(eigenvalues));
  214.     else
  215.         spectral_radius = powerMethod(M, 1000, 1e-10);
  216.     end
  217.    
  218.     fprintf('Jacobi 迭代矩阵 M = D^{-1}(L+U):\n');
  219.     for i = 1:n
  220.         fprintf('[');
  221.         for j = 1:n
  222.             fprintf('%.8f', M(i,j));
  223.             if j < n, fprintf(', '); end
  224.         end
  225.         fprintf(']\n');
  226.     end
  227.     fprintf('Jacobi 常向量 c = D^{-1}b = [' );
  228.     fprintf('%.16f, ', c(1:end-1));
  229.     fprintf('%.16f]^T\n', c(end));
  230.     fprintf('Jacobi 迭代矩阵谱半径 = %.6f\n', spectral_radius);
  231.     for k = 1:maxIter
  232.         % Jacobi迭代: x_new = D^{-1}(b + (L+U)x)
  233.         rhs = b + (L+U)*x;
  234.         x_new = solveWithAugmented(D, rhs);
  235.         
  236.         err = norm(x_new - x_exact);
  237.         err_history(k) = err;
  238.         fprintf('Jacobi 第 %d 次迭代,绝对误差 = %.6e\n', k, err);
  239.         fprintf('Jacobi 迭代法当前解 x = [' );
  240.         fprintf('%.16f, ', x_new(1:end-1));
  241.         fprintf('%.16f]^T\n', x_new(end));
  242.         x = x_new;
  243.         if err < epsilon
  244.             fprintf('收敛达到绝对误差 epsilon = %.1e,在第 %d 次迭代完成。\n', epsilon, k);
  245.             err_history = err_history(1:k);
  246.             iter = k;
  247.             return;
  248.         end
  249.     end
  250.     fprintf('达到最大迭代次数 %d,最终绝对误差 = %.6e\n', maxIter, err);
  251.     iter = maxIter;
  252. end
  253. % ====================== Gauss-Seidel 迭代 ======================
  254. function [x, err_history, iter, spectral_radius] = gaussSeidelIteration(A, b, maxIter, epsilon, x_exact)
  255.     n = length(b);
  256.     x = zeros(n,1);
  257.     err_history = zeros(maxIter, 1);
  258.     D = diag(diag(A));
  259.     L = -tril(A,-1);
  260.     U = -triu(A,1);
  261.     fprintf('---------------- Gauss-Seidel 迭代 ----------------\n');
  262.     fprintf('系数矩阵 A:\n'); disp(A);
  263.     fprintf('对角矩阵 D:\n'); disp(D);
  264.     fprintf('严格下三角矩阵 -L:\n'); disp(-L);
  265.     fprintf('严格上三角矩阵 -U:\n'); disp(U);
  266.    
  267.     % 计算迭代矩阵 M = (D-L)^{-1}U
  268.     M = zeros(n);
  269.     DL = D - L;
  270.    
  271.     % 按列计算 M
  272.     for j = 1:n
  273.         % 计算 M 的第 j 列:求解 (D-L) * m_j = U 的第 j 列
  274.         rhs = U(:, j);
  275.         m_j = solveWithAugmented(DL, rhs);
  276.         M(:, j) = m_j;
  277.     end
  278.    
  279.     % 计算常数向量 c = (D-L)^{-1}b
  280.     c = solveWithAugmented(D-L, b);
  281.    
  282.     % 计算谱半径
  283.     if n == 2
  284.         eigenvalues = manualEigenvalues2x2(M);
  285.         spectral_radius = max(abs(eigenvalues));
  286.         
  287.         % 详细输出2x2矩阵的计算过程
  288.         fprintf('\n--- Gauss-Seidel 谱半径详细计算 ---\n');
  289.         fprintf('迭代矩阵 M:\n');
  290.         for i = 1:n
  291.             fprintf('[');
  292.             for j = 1:n
  293.                 fprintf('%.8f', M(i,j));
  294.                 if j < n, fprintf(', '); end
  295.             end
  296.             fprintf(']\n');
  297.         end
  298.         fprintf('特征值: %.6f, %.6f\n', eigenvalues(1), eigenvalues(2));
  299.     else
  300.         spectral_radius = powerMethod(M, 1000, 1e-10);
  301.     end
  302.    
  303.     fprintf('Gauss-Seidel 迭代矩阵谱半径 = %.6f\n', spectral_radius);
  304.     fprintf('Gauss-Seidel 常向量 c = (D-L)^{-1}b = [' );
  305.     fprintf('%.16f, ', c(1:end-1));
  306.     fprintf('%.16f]^T\n', c(end));
  307.     for k = 1:maxIter
  308.         % Gauss-Seidel迭代: (D-L) * x_new = b + U*x
  309.         rhs = b + U*x;
  310.         x_new = solveWithAugmented(D-L, rhs);
  311.         
  312.         err = norm(x_new - x_exact);
  313.         err_history(k) = err;
  314.         fprintf('Gauss-Seidel 第 %d 次迭代,绝对误差 = %.6e\n', k, err);
  315.         fprintf('Gauss-Seidel 迭代法当前解 x = [' );
  316.         fprintf('%.16f, ', x_new(1:end-1));
  317.         fprintf('%.16f]^T\n', x_new(end));
  318.         x = x_new;
  319.         if err < epsilon
  320.             fprintf('收敛达到绝对误差 epsilon = %.1e,在第 %d 次迭代完成。\n', epsilon, k);
  321.             err_history = err_history(1:k);
  322.             iter = k;
  323.             return;
  324.         end
  325.     end
  326.     fprintf('达到最大迭代次数 %d,最终绝对误差 = %.6e\n', maxIter, err);
  327.     iter = maxIter;
  328. end
  329. % ====================== SOR 迭代 ======================
  330. function [x, err_history, iter, spectral_radius] = SORIteration(A, b, omega, maxIter, epsilon, x_exact)
  331.     n = length(b);
  332.     x = zeros(n,1);
  333.     err_history = zeros(maxIter, 1);
  334.     D = diag(diag(A));
  335.     L = -tril(A,-1);
  336.     U = -triu(A,1);
  337.     fprintf('---------------- SOR 迭代 ----------------\n');
  338.     fprintf('系数矩阵 A:\n'); disp(A);
  339.     fprintf('对角矩阵 D:\n'); disp(D);
  340.     fprintf('严格下三角矩阵 -L:\n'); disp(-L);
  341.     fprintf('严格上三角矩阵 -U:\n'); disp(U);
  342.     fprintf('松弛因子 ω = %.2f\n', omega);
  343.    
  344.     % 计算迭代矩阵 M = (D-ωL)^{-1}[(1-ω)D + ωU]
  345.     M = zeros(n);
  346.     D_omegaL = D - omega*L;
  347.     omegaU_plus = (1-omega)*D + omega*U;
  348.    
  349.     % 按列计算 M
  350.     for j = 1:n
  351.         % 计算 M 的第 j 列:求解 (D-ωL) * m_j = ((1-ω)D + ωU) 的第 j 列
  352.         rhs = omegaU_plus(:, j);
  353.         m_j = solveWithAugmented(D_omegaL, rhs);
  354.         M(:, j) = m_j;
  355.     end
  356.    
  357.     % 计算常数向量 c = ω*(D-ωL)^{-1}b
  358.     c = omega * solveWithAugmented(D-omega*L, b);
  359.    
  360.     % 计算谱半径
  361.     if n == 2
  362.         eigenvalues = manualEigenvalues2x2(M);
  363.         spectral_radius = max(abs(eigenvalues));
  364.     else
  365.         spectral_radius = powerMethod(M, 1000, 1e-10);
  366.     end
  367.    
  368.     fprintf('SOR 迭代矩阵谱半径 = %.6f\n', spectral_radius);
  369.     fprintf('SOR 常向量 c = ω*(D-ωL)^{-1}b = [' );
  370.     fprintf('%.16f, ', c(1:end-1));
  371.     fprintf('%.16f]^T\n', c(end));
  372.     for k = 1:maxIter
  373.         % SOR迭代: (D-ωL) * x_new = ω*b + ((1-ω)D + ωU)*x
  374.         rhs = omega*b + ((1-omega)*D + omega*U)*x;
  375.         x_new = solveWithAugmented(D-omega*L, rhs);
  376.         
  377.         err = norm(x_new - x_exact);
  378.         err_history(k) = err;
  379.         fprintf('SOR 第 %d 次迭代,绝对误差 = %.6e\n', k, err);
  380.         fprintf('SOR 迭代法当前解 x = [' );
  381.         fprintf('%.16f, ', x_new(1:end-1));
  382.         fprintf('%.16f]^T\n', x_new(end));
  383.         x = x_new;
  384.         if err < epsilon
  385.             fprintf('收敛达到绝对误差 epsilon = %.1e,在第 %d 次迭代完成。\n', epsilon, k);
  386.             err_history = err_history(1:k);
  387.             iter = k;
  388.             return;
  389.         end
  390.     end
  391.     fprintf('达到最大迭代次数 %d,最终绝对误差 = %.6e\n', maxIter, err);
  392.     iter = maxIter;
  393. end
  394. % ====================== 可视化结果 ======================
  395. function visualizeResults(x_gauss, x_jacobi, x_gs, x_sor, x_exact, ...
  396.                          err_history_jacobi, err_history_gs, err_history_sor, ...
  397.                          iter_jacobi, iter_gs, iter_sor, ...
  398.                          spectral_radius_jacobi, spectral_radius_gs, spectral_radius_sor, epsilon)
  399.    
  400.     % 创建一张图,包含两个子图
  401.     figure('Position', [100, 100, 1200, 500]);
  402.    
  403.     % 子图1: 绝对误差收敛曲线(对数坐标)
  404.     subplot(1, 2, 1);
  405.    
  406.     iter_range_jacobi = 1:length(err_history_jacobi);
  407.     iter_range_gs = 1:length(err_history_gs);
  408.     iter_range_sor = 1:length(err_history_sor);
  409.    
  410.     % 使用semilogy绘制对数坐标图
  411.     semilogy(iter_range_jacobi, err_history_jacobi, 'r^-', 'LineWidth', 1.5, 'MarkerSize', 2, 'DisplayName', 'Jacobi');
  412.     hold on;
  413.     semilogy(iter_range_gs, err_history_gs, 'gs-', 'LineWidth', 1.5, 'MarkerSize', 2, 'DisplayName', 'Gauss-Seidel');
  414.     semilogy(iter_range_sor, err_history_sor, 'bd-', 'LineWidth', 1.5, 'MarkerSize', 2, 'DisplayName', 'SOR');
  415.    
  416.     % 兼容性方法添加收敛阈值线(替代yline)
  417.     x_limits = xlim;
  418.     plot(x_limits, [epsilon, epsilon], 'k--', 'LineWidth', 1.5, 'DisplayName', sprintf('收敛阈值 (%.0e)', epsilon));
  419.    
  420.     xlabel('迭代次数', 'FontSize', 12, 'FontWeight', 'bold');
  421.     ylabel('绝对误差', 'FontSize', 12, 'FontWeight', 'bold');
  422.     title('迭代法绝对误差收敛曲线', 'FontSize', 14, 'FontWeight', 'bold');
  423.    
  424.     % 设置y轴范围从1e-5到1e+0
  425.     ylim([epsilon, 1e+2]);
  426.    
  427.     % 设置y轴刻度为1e+0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5
  428.     yticks([1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e+0, 1e+1, 1e+2]);
  429.    
  430.     % 设置y轴刻度标签格式
  431.     yticklabels({'10^{-5}', '10^{-4}', '10^{-3}', '10^{-2}', '10^{-1}', '10^{0}', '10^{1}', '10^{2}'});
  432.    
  433.     grid on;
  434.     set(gca, 'FontSize', 11);
  435.    
  436.     % 兼容性修改:先创建legend,然后设置字体大小
  437.     h_legend = legend('Location', 'best');
  438.     try
  439.         set(h_legend, 'FontSize', 11);
  440.     catch
  441.         % 如果设置字体大小失败,忽略错误
  442.     end
  443.    
  444.     % 子图2: 迭代次数比较
  445.     subplot(1, 2, 2);
  446.    
  447.     iter_counts = [iter_jacobi, iter_gs, iter_sor];
  448.     methods_iter = {'Jacobi', 'Gauss-Seidel', 'SOR'};
  449.    
  450.     bar(iter_counts, 'FaceColor', [0.2 0.6 0.8], 'EdgeColor', 'k', 'LineWidth', 1.5);
  451.     set(gca, 'XTickLabel', methods_iter, 'FontSize', 12, 'FontWeight', 'bold');
  452.     ylabel('迭代次数', 'FontSize', 12, 'FontWeight', 'bold');
  453.     title('达到收敛所需的迭代次数', 'FontSize', 14, 'FontWeight', 'bold');
  454.     grid on;
  455.    
  456.     % 添加数值标签
  457.     for i = 1:length(iter_counts)
  458.         text(i, iter_counts(i), sprintf('%d', iter_counts(i)), ...
  459.              'HorizontalAlignment', 'center', 'VerticalAlignment', 'bottom', ...
  460.              'FontSize', 14, 'FontWeight', 'bold', 'Color', 'red');
  461.     end
  462.    
  463.     % 设置y轴范围,使数值标签显示更清晰
  464.     y_max = max(iter_counts) * 1.5;
  465.     ylim([0, y_max]);
  466.    
  467.     % 添加总标题
  468.     try
  469.         sgtitle('Hilbert矩阵方程求解方法性能比较', 'FontSize', 16, 'FontWeight', 'bold');
  470.     catch
  471.         set(gcf, 'Name', 'Hilbert矩阵方程求解方法性能比较');
  472.     end
  473.    
  474.     % 输出对齐的性能统计
  475.     fprintf('\n=============== 性能统计 ===============\n');
  476.     fprintf('方法\t\t\t最终误差\t\t迭代次数\t谱半径\t\t收敛状态\n');
  477.     fprintf('--------\t\t--------\t\t--------\t--------\t--------\n');
  478.     fprintf('高斯消去法\t\t%.6e\t\tN/A\t\t\tN/A\t\t\t直接法\n', norm(x_gauss - x_exact));
  479.     fprintf('Jacobi迭代\t\t%.6e\t\t%d\t\t\t%.16f\t\t%s\n', norm(x_jacobi - x_exact), iter_jacobi, ...
  480.             spectral_radius_jacobi, getConvergenceStatus(err_history_jacobi(end), epsilon));
  481.     fprintf('Gauss-Seidel\t%.6e\t\t%d\t\t\t%.16f\t\t%s\n', norm(x_gs - x_exact), iter_gs, ...
  482.             spectral_radius_gs, getConvergenceStatus(err_history_gs(end), epsilon));
  483.     fprintf('SOR迭代\t\t\t%.6e\t\t%d\t\t\t%.16f\t\t%s\n', norm(x_sor - x_exact), iter_sor, ...
  484.             spectral_radius_sor, getConvergenceStatus(err_history_sor(end), epsilon));
  485. end
  486. % ====================== 辅助函数:获取收敛状态 ======================
  487. function status = getConvergenceStatus(final_error, epsilon)
  488.     if final_error < epsilon
  489.         status = '已收敛';
  490.     else
  491.         status = '未收敛';
  492.     end
  493. end
  494. % ====================== SOR松弛因子优化函数 ======================
  495. function findOptimalOmega(n, maxIter, epsilon, current_omega)
  496.     % SOR松弛因子优化分析
  497.     % 输入:n - Hilbert矩阵维数,maxIter - 最大迭代次数
  498.    
  499.     fprintf('开始SOR松弛因子优化分析...\n');
  500.    
  501.     % 生成Hilbert矩阵和精确解
  502.     H = myHilbert(n);
  503.     x_exact = ones(n, 1);
  504.     b = H * x_exact;
  505.    
  506.     % 定义测试参数 - 使用与主程序相同的精度要求
  507.     omega_range = 0.1:0.05:1.9;  % 松弛因子范围
  508.     epsilon_target = epsilon;  % 修正:使用与主程序相同的精度要求
  509.    
  510.     % 预存储结果
  511.     iter_results = zeros(length(omega_range), 1);
  512.     spectral_radius_results = zeros(length(omega_range), 1);
  513.     final_error_results = zeros(length(omega_range), 1);
  514.    
  515.     fprintf('测试松弛因子范围: %.1f ~ %.1f,步长 %.2f\n', min(omega_range), max(omega_range), omega_range(2)-omega_range(1));
  516.     fprintf('测试精度要求: %.0e\n', epsilon_target);
  517.    
  518.     % 对每个松弛因子进行测试
  519.     for i = 1:length(omega_range)
  520.         omega = omega_range(i);
  521.         
  522.         % 运行SOR迭代
  523.         [x_sor, ~, iter_count, spectral_radius] = SORIteration(H, b, omega, maxIter, epsilon_target, x_exact);
  524.         iter_results(i) = iter_count;
  525.         spectral_radius_results(i) = spectral_radius;
  526.         final_error_results(i) = norm(x_sor - x_exact);
  527.         
  528.         if mod(i, 5) == 0
  529.             fprintf('已完成 %.0f%% 的测试...\n', i/length(omega_range)*100);
  530.         end
  531.     end
  532.    
  533.     % 可视化结果
  534.     figure('Position', [200, 200, 1400, 600]);
  535.    
  536.     % 子图1: 迭代次数 vs 松弛因子
  537.     subplot(1, 1, 1);
  538.     plot(omega_range, iter_results, 'bo-', 'LineWidth', 2, 'MarkerSize', 2);
  539.    
  540.     xlabel('松弛因子 ω', 'FontSize', 12, 'FontWeight', 'bold');
  541.     ylabel('迭代次数', 'FontSize', 12, 'FontWeight', 'bold');
  542.     title(sprintf('SOR方法:迭代次数 vs 松弛因子 (ε=%.0e)', epsilon_target), 'FontSize', 14, 'FontWeight', 'bold');
  543.     grid on;
  544.    
  545.     % 标记最优松弛因子(迭代次数最少)
  546.     [min_iter, min_iter_idx] = min(iter_results);
  547.     optimal_omega_iter = omega_range(min_iter_idx);
  548.     hold on;
  549.     plot(optimal_omega_iter, min_iter, 'rs', 'MarkerSize', 8, 'LineWidth', 2);
  550.    
  551.     % 标记主程序使用的松弛因子
  552.     main_omega = current_omega;
  553.     main_omega_idx = find(abs(omega_range - main_omega) < 0.01);
  554.     if ~isempty(main_omega_idx)
  555.         main_iter = iter_results(main_omega_idx(1));
  556.         plot(main_omega, main_iter, 'g^', 'MarkerSize', 8, 'LineWidth', 2);
  557.         legend_str = {sprintf('迭代次数'), ...
  558.                      sprintf('最优 ω=%.2f', optimal_omega_iter), ...
  559.                      sprintf('主程序 ω=%.2f', main_omega)};
  560.     else
  561.         legend_str = {sprintf('迭代次数'), ...
  562.                      sprintf('最优 ω=%.2f', optimal_omega_iter)};
  563.     end
  564.     legend(legend_str, 'Location', 'best', 'FontSize', 10);
  565.    
  566.     fprintf('精度 ε=%.0e: 最优ω=%.2f, 最少迭代次数=%d\n', epsilon_target, optimal_omega_iter, min_iter);
  567.     fprintf('主程序使用的ω=%.2f: 迭代次数=%d\n', main_omega, main_iter);
  568.    
  569.     % 添加总标题
  570.     try
  571.         sgtitle(sprintf('Hilbert(%d)矩阵SOR方法松弛因子优化分析', n), ...
  572.                 'FontSize', 16, 'FontWeight', 'bold');
  573.     catch
  574.         set(gcf, 'Name', sprintf('Hilbert(%d)矩阵SOR方法松弛因子优化分析', n));
  575.     end
  576.    
  577.     % 输出详细分析结果
  578.     fprintf('\n=============== SOR松弛因子优化结果汇总 ===============\n');
  579.     fprintf('矩阵维数: %d\n', n);
  580.     fprintf('测试的松弛因子范围: %.1f ~ %.1f\n', min(omega_range), max(omega_range));
  581.     fprintf('精度要求: %.0e\n', epsilon_target);
  582.     fprintf('最优松弛因子 (最少迭代次数): ω = %.2f\n', optimal_omega_iter);
  583.     fprintf('最少迭代次数: %d\n', min_iter);
  584.     fprintf('主程序使用的松弛因子: ω = %.2f\n', main_omega);
  585.     fprintf('主程序对应的迭代次数: %d\n', main_iter);
  586.    
  587.     % 提供建议
  588.     fprintf('\n建议:\n');
  589.     if optimal_omega_iter ~= main_omega
  590.         fprintf('建议使用 ω = %.2f 代替当前的 ω = %.2f,可以减少迭代次数从 %d 到 %d\n', ...
  591.                 optimal_omega_iter, main_omega, main_iter, min_iter);
  592.     else
  593.         fprintf('当前使用的松弛因子 ω = %.2f 是最优选择\n', main_omega);
  594.     end
  595.    
  596.     fprintf('========================================================\n');
  597. end
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册