zoukankan      html  css  js  c++  java
  • LUP分解法求解线性方程组

    本节我们讨论如何用LUP分解法求解线性方程组,对于含有n个未知变量x1,x2,x3,…,xn的线性方程组:

    image

    同时满足方程组中所有方程的一个数值集:x1,x2,…,xn称为方程组的解。

    将方程组改写成矩阵向量等式:

    image

    记为:

    Ax=b

    如果A为非奇异矩阵,那么A存在逆矩阵,亦即方程组有解。

    LUP分解的思想是找出三个n*n的矩阵,L、U和P,满足

    PA=LU

    其中,L是一个单位下三角矩阵,U是一个上三角矩阵,P是一个置换矩阵。则称满足上述等式的L、U和P为矩阵A的LUP分解

    等式Ax=b两边同乘以P,变形为PAx=Pb,亦即:

    LUx=Pb

    设y=Ux,其中x就是我们要求的向量解。我们首先通过正向替换求解下三角系统:

    Ly=Pb

    得到未知变量y。然后,通过正向替换求解上三角系统:

    Ux=y

    得到未知变量x。

    由于置换矩阵P是可逆的,等式PA=LU两边同乘以P-1,得:

    A=P-1LU

    =P-1Ly

    =P-1Pb

    =b

    于是x就是Ax=b的解。

    调用方法:

        linear::CLinearEqualtion l(3);
        l.init_A("A.txt");
        l.init_b("b.txt");
        l.lu_decomposition();
        l.lup_solve();
        l.show_y();
        l.show_x();
        l.save_solution();

    C++实现:

    #include <iostream>
    #include <vector>
    #include <cassert>
    #include <fstream>
    
    using namespace std;
    
    namespace linear
    {
    #define array_1(__type) std::vector<__type>
    #define array_2(__type) std::vector<array_1(__type)>
    
        class CLinearEqualtion
        {
            /*
            使用方法:
            1. 定义计算方程组的类对象,并初始化其系数矩阵的大小
            linear::CLinearEqualtion l(3);
    
            2. 读取系数阵 A
            l.init_A("A.txt");
    
            3. 读取 b
            l.init_b("b.txt");
    
            4. 对系数矩阵进行lu分解
            l.lu_decomposition();
    
            5. 求解方程组
            l.lup_solve();
    
            6. 显示反向替换的解
            l.show_y();
    
            7. 显示正向替换的解
            l.show_x();
    
            8. 保存方程的解
            l.save_solution();
    
            A.txt
            1    5    4
            2    0    3
            5    8    2
    
            b.txt
            12
            9
            5
    
            x[0] = -0.157895
            x[1] = -0.0526316
            x[2] = 3.10526
            */
        private:
            array_2(double) A;
            array_2(double) L;
            array_2(double) U;
    
            array_1(double) b;
            array_1(int) p;
    
            array_1(double) x;
            array_1(double) y;
    
        public:
            CLinearEqualtion(int n)
            {
                assert(n>1);
    
                A = array_2(double)(n);
                L = array_2(double)(n);
                U = array_2(double)(n);
                for (int i= 0; i < n;i++)
                {
                    A[i] = array_1(double)(n);
                    L[i] = array_1(double)(n);
                    U[i] = array_1(double)(n);
                }
                b = array_1(double)(n);
                x = array_1(double)(n);
                y = array_1(double)(n);
                p = array_1(int)(n);
            } // !CLinearEqualtion(int n)
            virtual ~CLinearEqualtion(){} // !virtual ~CLinearEqualtion()
    
        public:
            void init_A(array_2(double) _A)
            {
                for (int i = 0; i < _A.size(); i++)
                    A[i].assign(_A[i].begin(), _A[i].end());
            } // !void init_A(array_2(double) _A)
    
            void init_A(std::string _fileName)
            {
                std::ifstream in(_fileName.c_str());
                int i = 0;
                int j = 0;
                while(!in.eof())
                {
                    double e = 0;
                    in>>e;
                    std::cout<<e<<std::endl;
                    A[i][j] = e;
                    if (j==A.size() - 1)
                    {
                        i++;
                        j = 0;
                    }
                    else
                    {
                        j++;
                    }
                }
            } // !void init_A(std::string _fileName)
    
            void init_b(std::string _fileName)
            {
                std::ifstream in(_fileName.c_str());
                int i = 0;
                while(!in.eof())
                {
                    double e = 0;
                    in>>e;
                    std::cout<<e<<std::endl;
                    b[i++] = e;
                }
            } // !void init_b(std::string _fileName)
    
            void lu_decomposition()
            {
                int n = A.size(); // get array size
                for (int i = 0; i < n; i++)
                    p[i] = i;
                for (int k = 0; k < n; k++)
                {
                    int max = 0;
                    int k_ = k;
                    // get max e in col k.
                    for (int i = k; i < n; i++)
                    {
                        if (fabs(A[i][k]) > max)
                        {
                            max = fabs(A[i][k]);
                            k_ = i;
                        }
                    }
                    // make sure not all is zero.
                    if (max == 0)
                        assert("singular matrix");
    
                    // swap cur row,max row.
                    if (k != k_)
                    {
                        swap(p[k], p[k_]);
                        for (int i = 0; i < n; i++)
                            swap(A[k][i], A[k_][i]);                    
                    }
                    
                    for (int i = k + 1; i < n; i++)
                    {
                        // gen v
                        A[i][k] /= A[k][k];
                        for (int j = k + 1; j < n; j++)
                        {
                            A[i][j] -= A[i][k] * A[k][j];
                        }
                    }
                }
    
                init_LU();
            } // !void lu_decomposition()
    
            void init_LU()
            {
                int n = A.size(); // get array size
    
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        if (i > j)
                        {
                            L[i][j] = A[i][j];
                        } 
                        else
                        {
                            U[i][j] = A[i][j];
                            if (i == j)
                                L[i][i] = 1;
                        }
                    }
                }
    
            } // !void init_LU()
    
            void lup_solve()
            {
                int n = A.size();
                int i = 0, j = 0;
                for (i = 0; i < n; i++)
                {
                    x[i] = 0;
                    y[i] = 0;
                }
    
                for (i = 0; i < n; i++)
                {
                    y[i] = b[p[i]];
                    for (j = 0; j < i; j++)
                        y[i] -= L[i][j] * y[j];
                }
                for (i = n - 1; i >= 0; i--)
                {
                    double delt = y[i];
                    for (j = n - 1; j > i; j--)
                        delt -= U[i][j] * x[j];
                    x[i] = delt / U[i][j];
                }
            } // !void lup_solve()
    
            void show_y()
            {
                int n = A.size();
                std::cout << "###" << std::endl;
                for (int i = 0; i < n; i++)
                {
                    std::cout << "y[" << i << "]=" << y[i] << std::endl;
                }
            } // !void show_y()
    
            void show_x()
            {
                int n = A.size();
                std::cout << "###" << std::endl;
                for (int i = 0; i < n; i++)
                    std::cout << "x[" << i << "]=" << x[i] << std::endl;
            } // !void show_x()
    
    
            void save_solution()
            {
                int n = A.size();
                ofstream out("result.txt", ios::out);
                out << "-------------------------------------" << std::endl;
                std::cout << "-------------------------------------" << std::endl;
                for (int i = 0; i < n; i++)
                {                
                    out << "x[" << i << "] = " << x[i]<< std::endl;
                    std::cout << "x[" << i << "] = " << x[i]<< std::endl;
                }
                out << "-------------------------------------" << std::endl;
                std::cout << "-------------------------------------" << std::endl;
                out.close();
            }
        };
    }

    链接:http://pan.baidu.com/s/1hqJes4k 密码:elwz

  • 相关阅读:
    matplotlib 进阶之origin and extent in imshow
    Momentum and NAG
    matplotlib 进阶之Tight Layout guide
    matplotlib 进阶之Constrained Layout Guide
    matplotlib 进阶之Customizing Figure Layouts Using GridSpec and Other Functions
    matplotlb 进阶之Styling with cycler
    matplotlib 进阶之Legend guide
    Django Admin Cookbook-10如何启用对计算字段的过滤
    Django Admin Cookbook-9如何启用对计算字段的排序
    Django Admin Cookbook-8如何在Django admin中优化查询
  • 原文地址:https://www.cnblogs.com/BigBigLiang/p/4962553.html
Copyright © 2011-2022 走看看