【计算方法】迭代法(线性方程组求解)

解线性方程组的方法有如下两类
直接法:高斯消去法,三角分解法等,这些方法可用于求解低阶稠密方程组
迭代法:雅可比迭代法,高斯-赛德尔迭代法等,用于求解高阶稀疏方程组

雅可比迭代法

【计算方法】迭代法(线性方程组求解)_第1张图片

高斯-赛德尔迭代法

【计算方法】迭代法(线性方程组求解)_第2张图片

收敛问题

首先时矩阵A应具有严格的对角优势–在矩阵的每一行中,对角线的上的元素的绝对值大于其它元素的绝对值的和。当且仅当此时,雅可比迭代才具有唯一解。且经过数学家证明此时高斯-赛德尔迭代法同样会收敛。
那么如何判断收敛呢?
【计算方法】迭代法(线性方程组求解)_第3张图片

迭代跳出条件

个人所设置的最大迭代次数。
收敛时所计算的精度问题。具体展示为前后两次迭代结果的相对误差以及绝对误差;

判断代码主要如下:

forab(i, 1, M) // 迭代次数判断
---------------------
---------------------
double err = fabs(normal_form(x, p));// 精度判断
            double relerr = err / (normal_form(x, s) + 1e-7);
            if (err < delta || relerr < delta)
                break;

例题

【问题描述】为求解一个线性方程组,使用高斯赛德尔迭代法,采用欧几里得距离判定是否收敛。精度delta为1E-9,最大迭代次数为20。
【输入形式】在屏幕上依次输入方阵阶数n,系数矩阵A,常数矩阵B和起始点P。
【输出形式】输出实际迭代次数,然后每一行输出一个根。
【样例1输入】
3
4 -1 1
4 -8 1
-2 1 5
7
-21
15
1
2
2
【样例1输出】
10
2
4
3
【样例1说明】输入:第1行为方阵阶数3,第2行至4行为系数矩阵A,第5行至7行为常数矩阵B,第8行至10行为起始点。输出:实际迭代次数为10,然后每行依次输出方程解:x1, x2, x3。
【评分标准】根据输入得到的输出准确

ACcode:

/*
 * @Author: csc
 * @Date: 2021-04-09 12:43:20
 * @LastEditTime: 2021-04-09 20:36:00
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \code_formal\course\cal\gauss_saierd.cpp
 */
#include <bits/stdc++.h>
#define pr printf
#define sc scanf
#define sf(n) scanf("%d", &n)
#define sff(n1, n2) scanf("%d %d", &n1, &n2)
#define sfff(n1, n2, n3) scanf("%d %d %d", &n1, &n2, &n3)
#define sl(n) scanf("%lld", &n)
#define sll(n1, n2) scanf("%lld %lld", &n1, &n2)
#define slll(n1, n2, n3) scanf("%lld %lld %lld", &n1, &n2, &n3)
#define for0(i, n) for (i = 0; i < n; i++)
#define for1n(i, n) for (i = 1; i <= n; i++)
#define forab(i, a, b) for (i = a; i <= b; i++)
#define forba(i, a, b) for (i = b; i >= a; i--)
#define pb push_back
#define fi first
#define se second
#define int long long
#define endl '\n'
#define vi vector<int>
#define vii vector<vector<int>>
#define pt pair<int, int>
#define mem(ara, n) memset(ara, n, sizeof(ara))
#define memb(ara) memset(ara, false, sizeof(ara))
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))
#define sz(x) x.size()
const int N = 1e6 + 100;
const int mod = 1e9 + 7;
namespace fastIO
{
     
    inline void input(int &res)
    {
     
        char c = getchar();
        res = 0;
        int f = 1;
        while (!isdigit(c))
        {
     
            f ^= c == '-';
            c = getchar();
        }
        while (isdigit(c))
        {
     
            res = (res << 3) + (res << 1) + (c ^ 48);
            c = getchar();
        }
        res = f ? res : -res;
    }
    inline int qpow(int a, int b)
    {
     
        int ans = 1, base = a;
        while (b)
        {
     
            if (b & 1)
                ans = (ans * base % mod + mod) % mod;
            base = (base * base % mod + mod) % mod;
            b >>= 1;
        }
        return ans;
    }
    int fact(int n)
    {
     
        int res = 1;
        for (int i = 1; i <= n; i++)
        {
     
            res = res * 1ll * i % mod;
        }
        return res;
    }
    int C(int n, int k)
    {
     
        return fact(n) * 1ll * qpow(fact(k), mod - 2) % mod * 1ll * qpow(fact(n - k), mod - 2) % mod;
    }
}
using namespace fastIO;

using namespace std;

signed main()
{
     
    int _ = 1;
    //input(_);
    while (_--)
    {
     
        int n, i, j, k;
        input(n);
        vector<vector<double>> v(n + 1, vector<double>(n + 1));
        for1n(i, n) for1n(j, n) cin >> v[i][j];
        vector<double> b(n + 1), p(n + 1), x(n + 1, 1);
        vector<double> s(n + 1);
        for1n(i, n) cin >> b[i];
        for1n(i, n) cin >> p[i];

        double delta = 1e-9;
        int M = 20;

        auto dot = [&](vector<double> &g, vector<double> &h, int _start, int _end) -> double {
     
            double res = 0.0;
            for (int kk = _start; kk <= _end; kk++)
                res += g[kk] * h[kk];
            return res;
        };
        auto normal_form = [&](vector<double> g, vector<double> h) -> double {
     
            double res = 0.0;
            for (int kk = 1; kk <= n; kk++)
                res += fabs(g[kk] - h[kk]);
            return res;
        };

        forab(i, 1, M)
        {
     
            forab(j, 1, n)
            {
     
                if (j == 1)
                    x[1] = (b[1] - dot(v[1], p, 2, n)) / v[1][1];
                else if (j == n)
                    x[n] = (b[n] - dot(v[n], x, 1, n - 1)) / v[n][n];
                else
                    x[j] = (b[j] - dot(v[j], x, 1, j - 1) - dot(v[j], p, j + 1, n)) / v[j][j];
            }

            double err = fabs(normal_form(x, p));
            double relerr = err / (normal_form(x, s) + 1e-7);
            p = x;

            if (err < delta || relerr < delta)
                break;
        }

        cout << i - 1;
        puts("");
        for1n(j, n) pr("%g\n",x[j]);
    }

    return 0;
}

你可能感兴趣的:(计算方法,算法,数学建模)