Example #1
0
bool generalizedsymmetricdefiniteevdreduce(ap::real_2d_array& a,
        int n,
        bool isuppera,
        const ap::real_2d_array& b,
        bool isupperb,
        int problemtype,
        ap::real_2d_array& r,
        bool& isupperr)
{
    bool result;
    ap::real_2d_array t;
    ap::real_1d_array w1;
    ap::real_1d_array w2;
    ap::real_1d_array w3;
    int i;
    int j;
    double v;

    ap::ap_error::make_assertion(n>0, "GeneralizedSymmetricDefiniteEVDReduce: N<=0!");
    ap::ap_error::make_assertion(problemtype==1||problemtype==2||problemtype==3, "GeneralizedSymmetricDefiniteEVDReduce: incorrect ProblemType!");
    result = true;

    //
    // Problem 1:  A*x = lambda*B*x
    //
    // Reducing to:
    //     C*y = lambda*y
    //     C = L^(-1) * A * L^(-T)
    //     x = L^(-T) * y
    //
    if( problemtype==1 )
    {

        //
        // Factorize B in T: B = LL'
        //
        t.setbounds(1, n, 1, n);
        if( isupperb )
        {
            for(i = 1; i <= n; i++)
            {
                ap::vmove(t.getcolumn(i, i, n), b.getrow(i, i, n));
            }
        }
        else
        {
            for(i = 1; i <= n; i++)
            {
                ap::vmove(&t(i, 1), &b(i, 1), ap::vlen(1,i));
            }
        }
        if( !choleskydecomposition(t, n, false) )
        {
            result = false;
            return result;
        }

        //
        // Invert L in T
        //
        if( !invtriangular(t, n, false, false) )
        {
            result = false;
            return result;
        }

        //
        // Build L^(-1) * A * L^(-T) in R
        //
        w1.setbounds(1, n);
        w2.setbounds(1, n);
        r.setbounds(1, n, 1, n);
        for(j = 1; j <= n; j++)
        {

            //
            // Form w2 = A * l'(j) (here l'(j) is j-th column of L^(-T))
            //
            ap::vmove(&w1(1), &t(j, 1), ap::vlen(1,j));
            symmetricmatrixvectormultiply(a, isuppera, 1, j, w1, 1.0, w2);
            if( isuppera )
            {
                matrixvectormultiply(a, 1, j, j+1, n, true, w1, 1, j, 1.0, w2, j+1, n, 0.0);
            }
            else
            {
                matrixvectormultiply(a, j+1, n, 1, j, false, w1, 1, j, 1.0, w2, j+1, n, 0.0);
            }

            //
            // Form l(i)*w2 (here l(i) is i-th row of L^(-1))
            //
            for(i = 1; i <= n; i++)
            {
                v = ap::vdotproduct(&t(i, 1), &w2(1), ap::vlen(1,i));
                r(i,j) = v;
            }
        }

        //
        // Copy R to A
        //
        for(i = 1; i <= n; i++)
        {
            ap::vmove(&a(i, 1), &r(i, 1), ap::vlen(1,n));
        }

        //
        // Copy L^(-1) from T to R and transpose
        //
        isupperr = true;
        for(i = 1; i <= n; i++)
        {
            for(j = 1; j <= i-1; j++)
            {
                r(i,j) = 0;
            }
        }
        for(i = 1; i <= n; i++)
        {
            ap::vmove(r.getrow(i, i, n), t.getcolumn(i, i, n));
        }
        return result;
    }

    //
    // Problem 2:  A*B*x = lambda*x
    // or
    // problem 3:  B*A*x = lambda*x
    //
    // Reducing to:
    //     C*y = lambda*y
    //     C = U * A * U'
    //     B = U'* U
    //
    if( problemtype==2||problemtype==3 )
    {

        //
        // Factorize B in T: B = U'*U
        //
        t.setbounds(1, n, 1, n);
        if( isupperb )
        {
            for(i = 1; i <= n; i++)
            {
                ap::vmove(&t(i, i), &b(i, i), ap::vlen(i,n));
            }
        }
        else
        {
            for(i = 1; i <= n; i++)
            {
                ap::vmove(t.getrow(i, i, n), b.getcolumn(i, i, n));
            }
        }
        if( !choleskydecomposition(t, n, true) )
        {
            result = false;
            return result;
        }

        //
        // Build U * A * U' in R
        //
        w1.setbounds(1, n);
        w2.setbounds(1, n);
        w3.setbounds(1, n);
        r.setbounds(1, n, 1, n);
        for(j = 1; j <= n; j++)
        {

            //
            // Form w2 = A * u'(j) (here u'(j) is j-th column of U')
            //
            ap::vmove(&w1(1), &t(j, j), ap::vlen(1,n-j+1));
            symmetricmatrixvectormultiply(a, isuppera, j, n, w1, 1.0, w3);
            ap::vmove(&w2(j), &w3(1), ap::vlen(j,n));
            ap::vmove(&w1(j), &t(j, j), ap::vlen(j,n));
            if( isuppera )
            {
                matrixvectormultiply(a, 1, j-1, j, n, false, w1, j, n, 1.0, w2, 1, j-1, 0.0);
            }
            else
            {
                matrixvectormultiply(a, j, n, 1, j-1, true, w1, j, n, 1.0, w2, 1, j-1, 0.0);
            }

            //
            // Form u(i)*w2 (here u(i) is i-th row of U)
            //
            for(i = 1; i <= n; i++)
            {
                v = ap::vdotproduct(&t(i, i), &w2(i), ap::vlen(i,n));
                r(i,j) = v;
            }
        }

        //
        // Copy R to A
        //
        for(i = 1; i <= n; i++)
        {
            ap::vmove(&a(i, 1), &r(i, 1), ap::vlen(1,n));
        }
        if( problemtype==2 )
        {

            //
            // Invert U in T
            //
            if( !invtriangular(t, n, true, false) )
            {
                result = false;
                return result;
            }

            //
            // Copy U^-1 from T to R
            //
            isupperr = true;
            for(i = 1; i <= n; i++)
            {
                for(j = 1; j <= i-1; j++)
                {
                    r(i,j) = 0;
                }
            }
            for(i = 1; i <= n; i++)
            {
                ap::vmove(&r(i, i), &t(i, i), ap::vlen(i,n));
            }
        }
        else
        {

            //
            // Copy U from T to R and transpose
            //
            isupperr = false;
            for(i = 1; i <= n; i++)
            {
                for(j = i+1; j <= n; j++)
                {
                    r(i,j) = 0;
                }
            }
            for(i = 1; i <= n; i++)
            {
                ap::vmove(r.getcolumn(i, i, n), t.getrow(i, i, n));
            }
        }
    }
    return result;
}
Example #2
0
//************************************************************************
//Обращение матрицы, заданной LU-разложением
//
//Входные параметры:
//    A       -   LU-разложение  матрицы   (результат   работы  подпрограммы
//                LUDecomposition).
//    Pivots  -   таблица перестановок,  произведенных в ходе LU-разложения.
//                (результат работы подпрограммы LUDecomposition).
//    N       -   размерность матрицы
//
//Выходные параметры:
//    A       -   матрица, обратная к исходной. Массив с нумерацией
//                элементов [1..N, 1..N]
//
//Результат:
//    True,  если исходная матрица невырожденная.
//    False, если исходная матрица вырожденная.
//
//  -- LAPACK routine (version 3.0) --
//     Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
//     Courant Institute, Argonne National Lab, and Rice University
//     February 29, 1992
//************************************************************************
bool inverselu(ap::real_2d_array& a,
               const ap::integer_1d_array& pivots,
               int n)
{
    bool result;
    ap::real_1d_array work;
    int i;
    int iws;
    int j;
    int jb;
    int jj;
    int jp;
    int jp1;
    double v;

    result = true;

    //
    // Quick return if possible
    //
    if( n==0 )
    {
        return result;
    }
    work.setbounds(1, n);

    //
    // Form inv(U)
    //
    if( !invtriangular(a, n, true, false) )
    {
        result = false;
        return result;
    }

    //
    // Solve the equation inv(A)*L = inv(U) for inv(A).
    //
    for(j = n; j >= 1; j--)
    {
        //
        // Copy current column of L to WORK and replace with zeros.
        //
        for(i = j+1; i <= n; i++)
        {
            work(i) = a(i,j);
            a(i,j) = 0;
        }

        //
        // Compute current column of inv(A).
        //
        if( j<n )
        {
            jp1 = j+1;
            for(i = 1; i <= n; i++)
            {
                v = ap::vdotproduct(a.getrow(i, jp1, n), work.getvector(jp1, n));
                a(i,j) = a(i,j)-v;
            }
        }
    }

    //
    // Apply column interchanges.
    //
    for(j = n-1; j >= 1; j--)
    {
        jp = pivots(j);
        if( jp!=j )
        {
            ap::vmove(work.getvector(1, n), a.getcolumn(j, 1, n));
            ap::vmove(a.getcolumn(j, 1, n), a.getcolumn(jp, 1, n));
            ap::vmove(a.getcolumn(jp, 1, n), work.getvector(1, n));
        }
    }
    return result;
}