数值线性代数实验-共轭梯度法

Posted cniwoq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数值线性代数实验-共轭梯度法相关的知识,希望对你有一定的参考价值。

一开始用c++的运算符重载程序总是莫名其妙的崩掉,然后以为是运算符重载的问题就写了个class对矩阵重新封装,结果还是崩,然后好久才发现是我把空间开的太大导致程序崩掉,无语,这样就浪费了我一个上午。。。。

课本上的例题:

$$
egin{equation}
{left[ egin{array}{ccc}
10&1&2&3&4\
1& 9& -1& 2& -3\
2& -1& 7& 3& -5\
3& 2& 3& 12& -1\
4& -3& -5 &-1 &15
end{array}
ight ]} imes {
left[ egin{array}{ccc}
x_1\
x_2\
x_3\
x_4\
x_5
end{array}
ight ]}
={
left[ egin{array}{ccc}
12\ -27\ 14\ -17\ 12
end{array}
ight ]}
end{equation}
$$

输入数据

5 5
10 1 2 3 4
1 9 -1 2 -3
2 -1 7 3 -5
3 2 3 12 -1
4 -3 -5 -1 15
12 -27 14 -17 12

#include "cstdio"
#include "cstring"
#include "cstdlib"
#include "cmath"
#include "iostream"
using namespace std;

const double eps = 1e-6;
const int maxr = 10;
const int maxc = 10;

class Matrix {
private:
    double m[maxr][maxc];
    int row, col;
public:
    Matrix operator - (Matrix b) {
        Matrix c;
        c.col = this->col; c.row = this->row;
        for (int i = 0; i < this->row; i++) {
            for (int j = 0; j < this->col; j++) {
                c.m[i][j] = this->m[i][j]-b.m[i][j];
            }
        }
        return c;
    }
    Matrix operator + (Matrix b) {
        Matrix c;
        c.col = this->col; c.row = this->row;
        for (int i = 0; i < this->row; i++) {
            for (int j = 0; j < this->col; j++) {
                c.m[i][j] = this->m[i][j] + b.m[i][j];
            }
        }
        return c;
    }
    Matrix operator * (Matrix b) {
        Matrix c;
        memset(c.m, 0, sizeof(c.m));
        c.row = this->row; c.col = b.col;
        for (int i = 0; i < this->row; i++) {
            for (int k = 0; k < this->col; k++) {
                for (int j = 0; j < b.col; j++) {
                    c.m[i][j] += this->m[i][k]*b.m[k][j];
                }
            }
        }
        return c;
    }
    Matrix operator & (double a) {
        Matrix c = *this;
        for (int i = 0; i < this->row; i++) {
            for (int j = 0; j < this->col; j++) {
                c.m[i][j] = a*this->m[i][j];
            }
        }
        return c;
    }
    Matrix operator !() {
        Matrix c = *this;
        c.row = this->col, c.col = this->row;
        for (int i = 0; i < this->row; i++) {
            for (int j = 0; j < this->col; j++) {
                c.m[j][i] = this->m[i][j];
            }
        }
        return c;
    }
    int dcmp() {
        for (int i = 0; i < this->row; i++) {
            for (int j = 0; j < this->col; j++) {
                if (fabs(this->m[i][j]) > eps) return 1;
            }
        }
        return 0;
    }
    void show_Matrix() {
        for (int i = 0; i < this->row; i++) {
            printf("%.6f", this->m[i][0]);
            for (int j = 1; j < this->col; j++) {
                printf(" %.8f", this->m[i][j]);
            }
            printf("
");
        }
    }
    void set_matrix(int n, int m) {
        this->row = n, this->col = m;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                scanf("%lf", &this->m[i][j]);
            }
        }
    }
    void init(int n, int m) {
        this->row = n, this->col = m;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                this->m[i][j] = 1.0;
            }
        }
    }
    int Col(){return this->col;}
    int Row(){return this->row;}
    double get(int i, int j) {return this->m[i-1][j-1];}
};

Matrix Conjugate_gradient(Matrix A, Matrix B) {
    Matrix x0 = B, p0, r1, p1;
    double alf, bet;
    x0.init(A.Col(), 1);
    Matrix r0 = B-(A*x0);
    int k = 0;
    r1 = r0;
    while (r1.dcmp()) {
        k++;
        if (k == 1) p1 = r0;
        else {
            bet = (!r1*r1).get(1, 1)/(!r0*r0).get(1, 1);
            p1 = r1 + (p0&bet);
        }
        alf = (!r1*r1).get(1, 1)/(!p1*A*p1).get(1, 1);
        x0 = x0 + (p1&alf);
        r0 = r1;
        r1 = r1-((A&alf)*p1);
    }
    return x0;
}

int main(int argc, char const *argv[])
{
   // freopen("in.txt", "r", stdin);
    Matrix A, B, C;
    int n, m;
    printf("输入系数矩阵的维数和矩阵A
");
    scanf("%d %d", &n, &m);
    A.set_matrix(n, m);
    printf("输入矩阵B
");
    B.set_matrix(n, 1);
    C = Conjugate_gradient(A, B);
    printf("利用共轭梯度法得到的解为
");
    C.show_Matrix();
    return 0;
}

 

 

  

 

以上是关于数值线性代数实验-共轭梯度法的主要内容,如果未能解决你的问题,请参考以下文章

什么是共轭梯度法?

最优化方法:共轭梯度法(Conjugate Gradient)

线性方程组的迭代解法——共轭梯度法

广义最小残差法和共轭梯度法的区别

共轭梯度法(CG)详解

第十章 共轭方向法