Select all pivot Gaussian elimination method C++ code

The code of the last blog used the function of solving linear algebraic equations. At that time, it used the function cagaus of the Gaussian elimination method for all selections in Xu Shiliang's "C Common Algorithms Program".

This book written by Xu Shiliang is still very practical, and the codes in it are all available for use. But there is a disadvantage that the code is not commented, and the variable names in it are also very arbitrary, often i, j, k, a, b, c. So the code inside is quite laborious to read. Taking advantage of the time on the weekend, I organized the cagaus in Xu Shiliang's book, added the necessary comments, and tried to name the variables as much as possible related to the use of the variables.

The all-selected pivot Gaussian elimination method is an algorithm with relatively low computational efficiency, but the robustness is very good. Usually used in the calculation of relatively small-scale linear algebraic equations.

inline static void swapCols(double A[], int N, int col1, int col2)
{
    for (int row = 0; row <= N-1; row++)
    {
        int p = row * N + col1;
        int q = row * N + col2;
        double t = A[p];
        A[p] = A[q];
        A[q] = t;
    }
}

inline static void swap(double &a, double &b)
{
    double t = a;
    a = b;
    b = t;
}

/**
 * @brief cagaus 全选主元高斯消去法求解线性代数方程组 Ax = b
 * @note 这个代码改编自徐世良编著的《C常用算法程序集》
 * @param A[] 线性代数方程组的系数矩阵,要求系数矩阵是 n * n 方阵,行优先存储。
 * @param b[] n 个元素的数组。
 * @param perm[] 辅助数组,n 个元素。函数利用这个数组来记录选主元过程中的位置交换。
 * @param n 线性代数方程组的阶数。
 * @param x[] 计算的结果。
 * @return true 表示计算成功,false 则表明系数矩阵奇异
 */
bool cagaus(double A[],double b[], int perm[], int N, double x[])
{    
    for (int row = 0; row <= N - 2; row++) //依次找每一行的主元,这个主元不一定在当前行。
    {
        double pivot = 0.0; //主元
        int pivot_row; //主元所在的行
        for (int i = row; i <= N - 1; i++) //全选主元,即选择矩阵中最大的一个,转化为找最大值问题
        {
            for (int j = row; j <= N - 1; j++)
            {
                double t = fabs(A[i * N + j]); //当然是绝对值最大一个,这里用到了数学库绝对值函数fabs()
                if (t > pivot)
                {
                    pivot = t;
                    perm[row] = j; //第 row 行的主元所在的列
                    pivot_row = i; //主元所在的行
                }
            }
        }
        if (pivot + 1.0 == 1.0)
        {
            return false; //主元为 0, 说明是奇异矩阵
        }
        else
        {
            if (perm[row] != row) //主元不在当前列,所以要进行列交换
            {
                swapCols(A, N, row, perm[row]);
            }
            if (pivot_row != row) //主元不在当前行,所以要进行行交换
            {
                for (int j = row; j <= N-1; j++)
                {
                    int p = row * N + j;
                    int q = pivot_row * N + j;
                    swap(A[p], A[q]);
                }
                swap(b[row], b[pivot_row]);
            }
        }

        pivot = A[row * N + row]; //归一化 start
        for (int j = row + 1; j <= N-1; j++)
        {
            int p = row * N + j;
            A[p] = A[p] / pivot;
        }
        b[row] = b[row] / pivot; //归一化 end

        for (int i = row + 1; i <= N - 1; i++) //消元
        {
            for (int j = row + 1; j <= N - 1; j++)
            {
                int p = i * N + j;
                A[p] = A[p] - A[i * N + row] * A[row * N + j];
            }
            b[i] = b[i] - A[i * N + row] * b[row];
        }
    }
    double d = A[(N-1) * N + N - 1]; // 最后一行的主元
    if (d + 1.0 == 1.0)
    {
        return false; // 如果这个主元是 0,说明是奇异矩阵
    }
    x[N - 1] = b[N - 1] / d; //计算解向量的最后一个分量
    for (int i = N - 2; i >= 0; i--) //回代过程
    {
        double t = 0.0;
        for (int j = i + 1; j <= N - 1; j++)
        {
            t = t + A[i * N + j] * x[j];
        }
        x[i] = b[i] - t;
    }
    perm[N - 1] = N - 1;
    for (int k = N - 1; k >= 0; k--) //恢复解向量,交换位置的地方再交换回来
    {
        if (perm[k] != k)
        {
            swap(x[k], x[perm[k]]);
        }
    }
    return true;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325648129&siteId=291194637
Recommended