Beispiel #1
0
/*************************************************************************
Matrix inverse
*************************************************************************/
static bool rmatrixinvmat(ap::real_2d_array& a, int n)
{
    bool result;
    ap::integer_1d_array pivots;

    rmatrixlu(a, n, n, pivots);
    result = rmatrixinvmatlu(a, pivots, n);
    return result;
}
/*************************************************************************
Calculation of the determinant of a general matrix

Input parameters:
    A       -   matrix, array[0..N-1, 0..N-1]
    N       -   size of matrix A.

Result: determinant of matrix A.

  -- ALGLIB --
     Copyright 2005 by Bochkanov Sergey
*************************************************************************/
double rmatrixdet(ap::real_2d_array a, int n)
{
    double result;
    ap::integer_1d_array pivots;

    rmatrixlu(a, n, n, pivots);
    result = rmatrixludet(a, pivots, n);
    return result;
}
/*************************************************************************
Solving a system of linear equations.

The algorithm solves a system of linear equations by using the
LU decomposition. The algorithm solves systems with a square matrix only.

Input parameters:
    A   -   system matrix.
            Array whose indexes range within [0..N-1, 0..N-1].
    B   -   right side of a system.
            Array whose indexes range within [0..N-1].
    N   -   size of matrix A.

Output parameters:
    X   -   solution of a system.
            Array whose index ranges within [0..N-1].

Result:
    True, if the matrix is not singular.
    False, if the matrix is singular. In this case, X doesn't contain a
solution.

  -- ALGLIB --
     Copyright 2005-2008 by Bochkanov Sergey
*************************************************************************/
bool rmatrixsolve(ap::real_2d_array a,
     ap::real_1d_array b,
     int n,
     ap::real_1d_array& x)
{
    bool result;
    ap::integer_1d_array pivots;
    int i;

    rmatrixlu(a, n, n, pivots);
    result = rmatrixlusolve(a, pivots, b, n, x);
    return result;
}
Beispiel #4
0
/*************************************************************************
Returns True for successful test, False - for failed test
*************************************************************************/
static bool testrmatrixrcond(int maxn, int passcount)
{
    bool result;
    ap::real_2d_array a;
    ap::real_2d_array lua;
    ap::integer_1d_array p;
    int n;
    int i;
    int j;
    int pass;
    bool err50;
    bool err90;
    bool errspec;
    bool errless;
    double erc1;
    double ercinf;
    ap::real_1d_array q50;
    ap::real_1d_array q90;
    double v;

    err50 = false;
    err90 = false;
    errless = false;
    errspec = false;
    q50.setbounds(0, 3);
    q90.setbounds(0, 3);
    for(n = 1; n <= maxn; n++)
    {
        
        //
        // special test for zero matrix
        //
        rmatrixgenzero(a, n);
        rmatrixmakeacopy(a, n, n, lua);
        rmatrixlu(lua, n, n, p);
        errspec = errspec||ap::fp_neq(rmatrixrcond1(a, n),0);
        errspec = errspec||ap::fp_neq(rmatrixrcondinf(a, n),0);
        errspec = errspec||ap::fp_neq(rmatrixlurcond1(lua, n),0);
        errspec = errspec||ap::fp_neq(rmatrixlurcondinf(lua, n),0);
        
        //
        // general test
        //
        a.setbounds(0, n-1, 0, n-1);
        for(i = 0; i <= 3; i++)
        {
            q50(i) = 0;
            q90(i) = 0;
        }
        for(pass = 1; pass <= passcount; pass++)
        {
            rmatrixrndcond(n, exp(ap::randomreal()*log(double(1000))), a);
            rmatrixmakeacopy(a, n, n, lua);
            rmatrixlu(lua, n, n, p);
            rmatrixrefrcond(a, n, erc1, ercinf);
            
            //
            // 1-norm, normal
            //
            v = 1/rmatrixrcond1(a, n);
            if( ap::fp_greater_eq(v,threshold50*erc1) )
            {
                q50(0) = q50(0)+double(1)/double(passcount);
            }
            if( ap::fp_greater_eq(v,threshold90*erc1) )
            {
                q90(0) = q90(0)+double(1)/double(passcount);
            }
            errless = errless||ap::fp_greater(v,erc1*1.001);
            
            //
            // 1-norm, LU
            //
            v = 1/rmatrixlurcond1(lua, n);
            if( ap::fp_greater_eq(v,threshold50*erc1) )
            {
                q50(1) = q50(1)+double(1)/double(passcount);
            }
            if( ap::fp_greater_eq(v,threshold90*erc1) )
            {
                q90(1) = q90(1)+double(1)/double(passcount);
            }
            errless = errless||ap::fp_greater(v,erc1*1.001);
            
            //
            // Inf-norm, normal
            //
            v = 1/rmatrixrcondinf(a, n);
            if( ap::fp_greater_eq(v,threshold50*ercinf) )
            {
                q50(2) = q50(2)+double(1)/double(passcount);
            }
            if( ap::fp_greater_eq(v,threshold90*ercinf) )
            {
                q90(2) = q90(2)+double(1)/double(passcount);
            }
            errless = errless||ap::fp_greater(v,ercinf*1.001);
            
            //
            // Inf-norm, LU
            //
            v = 1/rmatrixlurcondinf(lua, n);
            if( ap::fp_greater_eq(v,threshold50*ercinf) )
            {
                q50(3) = q50(3)+double(1)/double(passcount);
            }
            if( ap::fp_greater_eq(v,threshold90*ercinf) )
            {
                q90(3) = q90(3)+double(1)/double(passcount);
            }
            errless = errless||ap::fp_greater(v,ercinf*1.001);
        }
        for(i = 0; i <= 3; i++)
        {
            err50 = err50||ap::fp_less(q50(i),0.50);
            err90 = err90||ap::fp_less(q90(i),0.90);
        }
        
        //
        // degenerate matrix test
        //
        if( n>=3 )
        {
            a.setlength(n, n);
            for(i = 0; i <= n-1; i++)
            {
                for(j = 0; j <= n-1; j++)
                {
                    a(i,j) = 0.0;
                }
            }
            a(0,0) = 1;
            a(n-1,n-1) = 1;
            errspec = errspec||ap::fp_neq(rmatrixrcond1(a, n),0);
            errspec = errspec||ap::fp_neq(rmatrixrcondinf(a, n),0);
            errspec = errspec||ap::fp_neq(rmatrixlurcond1(a, n),0);
            errspec = errspec||ap::fp_neq(rmatrixlurcondinf(a, n),0);
        }
        
        //
        // near-degenerate matrix test
        //
        if( n>=2 )
        {
            a.setlength(n, n);
            for(i = 0; i <= n-1; i++)
            {
                for(j = 0; j <= n-1; j++)
                {
                    a(i,j) = 0.0;
                }
            }
            for(i = 0; i <= n-1; i++)
            {
                a(i,i) = 1;
            }
            i = ap::randominteger(n);
            a(i,i) = 0.1*ap::maxrealnumber;
            errspec = errspec||ap::fp_neq(rmatrixrcond1(a, n),0);
            errspec = errspec||ap::fp_neq(rmatrixrcondinf(a, n),0);
            errspec = errspec||ap::fp_neq(rmatrixlurcond1(a, n),0);
            errspec = errspec||ap::fp_neq(rmatrixlurcondinf(a, n),0);
        }
    }
    
    //
    // report
    //
    result = !(err50||err90||errless||errspec);
    return result;
}
/*************************************************************************
Dense solver.

This  subroutine  solves  a  system  A*X=B,  where A is NxN non-denegerate
real matrix, X and B are NxM real matrices.

Additional features include:
* automatic detection of degenerate cases
* iterative improvement

INPUT PARAMETERS
    A       -   array[0..N-1,0..N-1], system matrix
    N       -   size of A
    B       -   array[0..N-1,0..M-1], right part
    M       -   size of right part
    
OUTPUT PARAMETERS
    Info    -   return code:
                * -3    if A is singular, or VERY close to singular.
                        X is filled by zeros in such cases.
                * -1    if N<=0 or M<=0 was passed
                *  1    if task is solved (matrix A may be near  singular,
                        check R1/RInf parameters for condition numbers).
    Rep     -   solver report, see below for more info
    X       -   array[0..N-1,0..M-1], it contains:
                * solution of A*X=B if A is non-singular (well-conditioned
                  or ill-conditioned, but not very close to singular)
                * zeros,  if  A  is  singular  or  VERY  close to singular
                  (in this case Info=-3).

SOLVER REPORT

Subroutine sets following fields of the Rep structure:
* R1        reciprocal of condition number: 1/cond(A), 1-norm.
* RInf      reciprocal of condition number: 1/cond(A), inf-norm.

SEE ALSO:
    DenseSolverR() - solves A*x = b, where x and b are Nx1 matrices.

  -- ALGLIB --
     Copyright 24.08.2009 by Bochkanov Sergey
*************************************************************************/
void rmatrixsolvem(const ap::real_2d_array& a,
     int n,
     const ap::real_2d_array& b,
     int m,
     int& info,
     densesolverreport& rep,
     ap::real_2d_array& x)
{
    int i;
    int j;
    int k;
    int rfs;
    int nrfs;
    ap::integer_1d_array p;
    ap::real_1d_array xc;
    ap::real_1d_array y;
    ap::real_1d_array bc;
    ap::real_1d_array xa;
    ap::real_1d_array xb;
    ap::real_1d_array tx;
    ap::real_2d_array da;
    double v;
    double verr;
    bool smallerr;
    bool terminatenexttime;

    
    //
    // prepare: check inputs, allocate space...
    //
    if( n<=0||m<=0 )
    {
        info = -1;
        return;
    }
    da.setlength(n, n);
    x.setlength(n, m);
    y.setlength(n);
    xc.setlength(n);
    bc.setlength(n);
    tx.setlength(n+1);
    xa.setlength(n+1);
    xb.setlength(n+1);
    
    //
    // factorize matrix, test for exact/near singularity
    //
    for(i = 0; i <= n-1; i++)
    {
        ap::vmove(&da(i, 0), &a(i, 0), ap::vlen(0,n-1));
    }
    rmatrixlu(da, n, n, p);
    rep.r1 = rmatrixlurcond1(da, n);
    rep.rinf = rmatrixlurcondinf(da, n);
    if( ap::fp_less(rep.r1,10*ap::machineepsilon)||ap::fp_less(rep.rinf,10*ap::machineepsilon) )
    {
        for(i = 0; i <= n-1; i++)
        {
            for(j = 0; j <= m-1; j++)
            {
                x(i,j) = 0;
            }
        }
        rep.r1 = 0;
        rep.rinf = 0;
        info = -3;
        return;
    }
    info = 1;
    
    //
    // solve
    //
    for(k = 0; k <= m-1; k++)
    {
        
        //
        // First, non-iterative part of solution process:
        // * pivots
        // * L*y = b
        // * U*x = y
        //
        ap::vmove(bc.getvector(0, n-1), b.getcolumn(k, 0, n-1));
        for(i = 0; i <= n-1; i++)
        {
            if( p(i)!=i )
            {
                v = bc(i);
                bc(i) = bc(p(i));
                bc(p(i)) = v;
            }
        }
        y(0) = bc(0);
        for(i = 1; i <= n-1; i++)
        {
            v = ap::vdotproduct(&da(i, 0), &y(0), ap::vlen(0,i-1));
            y(i) = bc(i)-v;
        }
        xc(n-1) = y(n-1)/da(n-1,n-1);
        for(i = n-2; i >= 0; i--)
        {
            v = ap::vdotproduct(&da(i, i+1), &xc(i+1), ap::vlen(i+1,n-1));
            xc(i) = (y(i)-v)/da(i,i);
        }
        
        //
        // Iterative improvement of xc:
        // * calculate r = bc-A*xc using extra-precise dot product
        // * solve A*y = r
        // * update x:=x+r
        //
        // This cycle is executed until one of two things happens:
        // 1. maximum number of iterations reached
        // 2. last iteration decreased error to the lower limit
        //
        nrfs = densesolverrfsmax(n, rep.r1, rep.rinf);
        terminatenexttime = false;
        for(rfs = 0; rfs <= nrfs-1; rfs++)
        {
            if( terminatenexttime )
            {
                break;
            }
            
            //
            // generate right part
            //
            smallerr = true;
            for(i = 0; i <= n-1; i++)
            {
                ap::vmove(&xa(0), &a(i, 0), ap::vlen(0,n-1));
                xa(n) = -1;
                ap::vmove(&xb(0), &xc(0), ap::vlen(0,n-1));
                xb(n) = b(i,k);
                xdot(xa, xb, n+1, tx, v, verr);
                bc(i) = -v;
                smallerr = smallerr&&ap::fp_less(fabs(v),4*verr);
            }
            if( smallerr )
            {
                terminatenexttime = true;
            }
            
            //
            // solve
            //
            for(i = 0; i <= n-1; i++)
            {
                if( p(i)!=i )
                {
                    v = bc(i);
                    bc(i) = bc(p(i));
                    bc(p(i)) = v;
                }
            }
            y(0) = bc(0);
            for(i = 1; i <= n-1; i++)
            {
                v = ap::vdotproduct(&da(i, 0), &y(0), ap::vlen(0,i-1));
                y(i) = bc(i)-v;
            }
            tx(n-1) = y(n-1)/da(n-1,n-1);
            for(i = n-2; i >= 0; i--)
            {
                v = ap::vdotproduct(&da(i, i+1), &tx(i+1), ap::vlen(i+1,n-1));
                tx(i) = (y(i)-v)/da(i,i);
            }
            
            //
            // update
            //
            ap::vadd(&xc(0), &tx(0), ap::vlen(0,n-1));
        }
        
        //
        // Store xc
        //
        ap::vmove(x.getcolumn(k, 0, n-1), xc.getvector(0, n-1));
    }
}
static void testluproblem(const ap::real_2d_array& a,
     int m,
     int n,
     double& diffpu,
     double& luerr)
{
    ap::real_2d_array t1;
    ap::real_2d_array t2;
    ap::real_2d_array t3;
    ap::integer_1d_array it1;
    ap::integer_1d_array it2;
    int i;
    int j;
    int k;
    double v;
    double mx;
    ap::real_2d_array a0;
    ap::integer_1d_array p0;

    mx = 0;
    for(i = 1; i <= m; i++)
    {
        for(j = 1; j <= n; j++)
        {
            if( ap::fp_greater(fabs(a(i,j)),mx) )
            {
                mx = fabs(a(i,j));
            }
        }
    }
    if( ap::fp_eq(mx,0) )
    {
        mx = 1;
    }
    
    //
    // Compare LU and unpacked LU
    //
    t1.setbounds(1, m, 1, n);
    for(i = 1; i <= m; i++)
    {
        ap::vmove(&t1(i, 1), &a(i, 1), ap::vlen(1,n));
    }
    ludecomposition(t1, m, n, it1);
    ludecompositionunpacked(a, m, n, t2, t3, it2);
    for(i = 1; i <= m; i++)
    {
        for(j = 1; j <= ap::minint(m, n); j++)
        {
            if( i>j )
            {
                diffpu = ap::maxreal(diffpu, fabs(t1(i,j)-t2(i,j))/mx);
            }
            if( i==j )
            {
                diffpu = ap::maxreal(diffpu, fabs(1-t2(i,j))/mx);
            }
            if( i<j )
            {
                diffpu = ap::maxreal(diffpu, fabs(0-t2(i,j))/mx);
            }
        }
    }
    for(i = 1; i <= ap::minint(m, n); i++)
    {
        for(j = 1; j <= n; j++)
        {
            if( i>j )
            {
                diffpu = ap::maxreal(diffpu, fabs(0-t3(i,j))/mx);
            }
            if( i<=j )
            {
                diffpu = ap::maxreal(diffpu, fabs(t1(i,j)-t3(i,j))/mx);
            }
        }
    }
    for(i = 1; i <= ap::minint(m, n); i++)
    {
        diffpu = ap::maxreal(diffpu, fabs(double(it1(i)-it2(i))));
    }
    
    //
    // Test unpacked LU
    //
    ludecompositionunpacked(a, m, n, t1, t2, it1);
    t3.setbounds(1, m, 1, n);
    k = ap::minint(m, n);
    for(i = 1; i <= m; i++)
    {
        for(j = 1; j <= n; j++)
        {
            v = ap::vdotproduct(t1.getrow(i, 1, k), t2.getcolumn(j, 1, k));
            t3(i,j) = v;
        }
    }
    for(i = ap::minint(m, n); i >= 1; i--)
    {
        if( i!=it1(i) )
        {
            for(j = 1; j <= n; j++)
            {
                v = t3(i,j);
                t3(i,j) = t3(it1(i),j);
                t3(it1(i),j) = v;
            }
        }
    }
    for(i = 1; i <= m; i++)
    {
        for(j = 1; j <= n; j++)
        {
            luerr = ap::maxreal(luerr, fabs(a(i,j)-t3(i,j))/mx);
        }
    }
    
    //
    // Test 0-based LU
    //
    t1.setbounds(1, m, 1, n);
    for(i = 1; i <= m; i++)
    {
        ap::vmove(&t1(i, 1), &a(i, 1), ap::vlen(1,n));
    }
    ludecomposition(t1, m, n, it1);
    a0.setbounds(0, m-1, 0, n-1);
    for(i = 0; i <= m-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            a0(i,j) = a(i+1,j+1);
        }
    }
    rmatrixlu(a0, m, n, p0);
    for(i = 0; i <= m-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            diffpu = ap::maxreal(diffpu, fabs(a0(i,j)-t1(i+1,j+1)));
        }
    }
    for(i = 0; i <= ap::minint(m-1, n-1); i++)
    {
        diffpu = ap::maxreal(diffpu, fabs(double(p0(i)+1-it1(i+1))));
    }
}