Home > Mobile >  Solve A.x = b using LU factorisation give inf values
Solve A.x = b using LU factorisation give inf values

Time:10-19

I'm trying to solve linear systems of the form Ax = b where A is an (nxn) matrix of real numbers and b a (1xn) vector of real numbers, using the A = LU algorithm. This is my implementation:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int LUPDecompose(double A[N][N], double Tol, int P[N])
{

    int i, j, k, imax;
    double maxA, ptr[N], absA;

    for (i = 0; i <= N; i  )
        P[i] = i; //Unit permutation matrix, P[N] initialized with N

    for (i = 0; i < N; i  ) {
        maxA = 0.0;
        imax = i;

        for (k = i; k < N; k  )
            if ((absA = abs(A[k][i])) > maxA) {
                maxA = absA;
                imax = k;
            }

        if (maxA < Tol) return 0; //failure, matrix is degenerate

        if (imax != i) {
            //pivoting P
            j = P[i];
            P[i] = P[imax];
            P[imax] = j;

            //pivoting rows of A
            for (int ii = 0; ii < N; ii  )
            {
                ptr[ii] = A[i][ii];
                A[i][ii] = A[imax][ii];
                A[imax][ii] = ptr[ii];
            }

            //counting pivots starting from N (for determinant)
            P[N]  ;
        }

        for (j = i   1; j < N; j  ) {
            A[j][i] /= A[i][i];

            for (k = i   1; k < N; k  )
                A[j][k] -= A[j][i] * A[i][k];
        }
    }

    return 1;  //decomposition done
}

/* INPUT: A,P filled in LUPDecompose; b - rhs vector; N - dimension
 * OUTPUT: x - solution vector of A*x=b
 */
void LUPSolve(double A[N][N], int P[N], double b[N], double x[N])
{

    for (int i = 0; i < N; i  ) {
        x[i] = b[P[i]];

        for (int k = 0; k < i; k  )
            x[i] -= A[i][k] * x[k];
    }

    for (int i = N - 1; i >= 0; i--) {
        for (int k = i   1; k < N; k  )
            x[i] -= A[i][k] * x[k];

        x[i] /= A[i][i];
    }
}

int main()
{
    double Am[N][N] = {{0.6289, 0, 0.0128, 0.3184, 0.7151},
                        {0,   1,   0,   0,   0},
                        {0.0128, 0, 0.0021, 0.0045, 0.0380},
                        {0.3184, 0, 0.0045, 0.6618, 0.3371},
                        {0.7151, 0, 0.0380, 0.3371, 1.1381}};
    double bm[N] = {1.6752, 0, 0.0574, 1.3217, 2.2283};
    int Pm[N] = {0};
    double X[N] = {0};

    LUPDecompose( Am, 0.0001, Pm);
    LUPSolve(Am, Pm,  bm, X);

    printf("%f %f %f %f %f",X[0],X[1],X[2],X[3],X[4]);
}

However, I am getting inf values as such.

-1.#IND00 -1.#IND00 3.166387 0.849298 0.670689

I wonder if it is a code issue or algorithm. Any help to solve this issue?

CodePudding user response:

"I wonder if it is a code issue or algorithm. Any help to solve this issue?"

I believe there are code and algorithm issues. The following is your code with corrections to address only compile errors, and warnings (see in-line comments). It is not debugged beyond C syntax to achieve a clean compile, and run w/o error. (i.e. runs with no divide by zero, or inf errors.)

#define N 5 //required to be 5 by hard-coded array definitions in main()

int LUPDecompose(double A[N][N], double Tol, int P[N])
{

    int i, j, k, imax, ii;//added ii here to increase scope below
    double maxA, ptr[N], absA;

    //for (i = 0; i <= N; i  )
    for (i = 0; i < N; i  )
        P[i] = i; //Unit permutation matrix, P[N] initialized with N (actually init with i)

    for (i = 0; i < N; i  ) {
        maxA = 0.0;
        imax = i;

        for (k = i; k < N; k  )
            if ((absA = fabs(A[k][i])) > maxA) {// using fabs, not abs to avoid conversion of double to int.
                maxA = absA;
                imax = k;
            }

        if (maxA < Tol) return 0; //failure, matrix is degenerate

        if (imax != i) {
            //pivoting P
            j = P[i];
            P[i] = P[imax];
            P[imax] = j;

            //pivoting rows of A
           //for (int ii = 0; ii < N; ii  )
           for ( ii = 0; ii < N; ii  )
            {
                ptr[ii] = A[i][ii];
                A[i][ii] = A[imax][ii];
                A[imax][ii] = ptr[ii];
            }

            //counting pivots starting from N (for determinant)
            //P[N]  ;//N will always overflow for array with only N elements
            P[ii-1]  ;//use index here instead
        }

        for (j = i   1; j < N; j  ) {
            A[j][i] /= A[i][i];

            for (k = i   1; k < N; k  ) {//extra brackets added for readability
                A[j][k] -= A[j][i] * A[i][k];
            }
        }
    }

    return 1;  //decomposition done
}

/* INPUT: A,P filled in LUPDecompose; b - rhs vector; N - dimension
 * OUTPUT: x - solution vector of A*x=b
 */
void LUPSolve(double A[N][N], int P[N], double b[N], double x[N])
{

    for (int i = 0; i < N; i  ) {
        x[i] = b[P[i]];
        for (int k = 0; k < i; k  ) {//extra brackets added for readability
            x[i] -= A[i][k] * x[k];
        }
    }

        for (int i = N - 1; i >= 0; i--) {
            for (int k = i   1; k < N; k  ) {//additional brackets added for readability
                x[i] -= A[i][k] * x[k];
            }

            x[i] /= A[i][i];
        }
}
    

//int main()
int main(void)//minimum signature for main includes void
{
    //Note hardcoded arrays in this code require N == 5 (#define at top)
    double Am[N][N] = {{0.6289, 0, 0.0128, 0.3184, 0.7151},
                        {0,   1,   0,   0,   0},
                        {0.0128, 0, 0.0021, 0.0045, 0.0380},
                        {0.3184, 0, 0.0045, 0.6618, 0.3371},
                        {0.7151, 0, 0.0380, 0.3371, 1.1381}};
    double bm[N] = {1.6752, 0, 0.0574, 1.3217, 2.2283};
    int Pm[N] = {0};
    double X[N] = {0};

    LUPDecompose( Am, 0.0001, Pm);
    LUPSolve(Am, Pm,  bm, X);

    printf("%f %f %f %f %f",X[0],X[1],X[2],X[3],X[4]);
    
    return 0;  //int main(void){...} requires return statement.
}  

Based on enter image description here

the correct solution is:

-0.590174531351002
0
-19.76923076923077
1.0517711171662125
2.6772727272727272

But the actual output from code above is:
enter image description here

Algorithm related debugging is left for you to perform.

  • Related