Ejemplo n.º 1
0
void Sign( Matrix<F>& A, Matrix<F>& N, const SignCtrl<Base<F>> ctrl )
{
    DEBUG_CSE
    Matrix<F> ACopy( A );
    sign::Newton( A, ctrl );
    Gemm( NORMAL, NORMAL, F(1), A, ACopy, N );
}
Ejemplo n.º 2
0
inline typename Base<F>::type 
LogDetDivergence
( UpperOrLower uplo, const DistMatrix<F>& A, const DistMatrix<F>& B )
{
#ifndef RELEASE
    PushCallStack("LogDetDivergence");
#endif
    if( A.Grid() != B.Grid() )
        throw std::logic_error("A and B must use the same grid");
    if( A.Height() != A.Width() || B.Height() != B.Width() ||
        A.Height() != B.Height() )
        throw std::logic_error
        ("A and B must be square matrices of the same size");

    typedef typename Base<F>::type R;
    const int n = A.Height();
    const Grid& g = A.Grid();

    DistMatrix<F> ACopy( A );
    DistMatrix<F> BCopy( B );

    Cholesky( uplo, ACopy );
    Cholesky( uplo, BCopy );

    if( uplo == LOWER )
    {
        Trtrsm( LEFT, uplo, NORMAL, NON_UNIT, F(1), BCopy, ACopy );
    }
    else
    {
        MakeTrapezoidal( LEFT, uplo, 0, ACopy );
        Trsm( LEFT, uplo, NORMAL, NON_UNIT, F(1), BCopy, ACopy );
    }

    MakeTrapezoidal( LEFT, uplo, 0, ACopy );
    const R frobNorm = Norm( ACopy, FROBENIUS_NORM );

    R logDet;
    R localLogDet(0);
    DistMatrix<F,MD,STAR> d(g);
    ACopy.GetDiagonal( d );
    if( d.InDiagonal() )
    {
        const int nLocalDiag = d.LocalHeight();
        for( int iLocal=0; iLocal<nLocalDiag; ++iLocal )
        {
            const R delta = RealPart(d.GetLocal(iLocal,0));
            localLogDet += 2*Log(delta);
        }
    }
    mpi::AllReduce( &localLogDet, &logDet, 1, mpi::SUM, g.VCComm() );

    const R logDetDiv = frobNorm*frobNorm - logDet - R(n);
#ifndef RELEASE
    PopCallStack();
#endif
    return logDetDiv;
}
Ejemplo n.º 3
0
void TransformRows
( const Matrix<F>& V,
        Matrix<F>& A )
{
    DEBUG_CSE
    // TODO(poulson): Consider forming chunk-by-chunk to save memory
    Matrix<F> ACopy( A );
    Gemm( ADJOINT, NORMAL, F(1), V, ACopy, A );
}
Ejemplo n.º 4
0
QDWHInfo QDWH( Matrix<F>& A, Matrix<F>& P, const QDWHCtrl& ctrl )
{
    EL_DEBUG_CSE
    Matrix<F> ACopy( A );
    auto info = QDWH( A, ctrl );
    Zeros( P, A.Height(), A.Height() );
    Trrk( LOWER, NORMAL, NORMAL, F(1), A, ACopy, F(0), P );
    MakeHermitian( LOWER, P );
    return info;
}
Ejemplo n.º 5
0
void Sign
( AbstractDistMatrix<Field>& APre,
  AbstractDistMatrix<Field>& NPre,
  const SignCtrl<Base<Field>> ctrl )
{
    EL_DEBUG_CSE

    DistMatrixReadWriteProxy<Field,Field,MC,MR> AProx( APre );
    DistMatrixWriteProxy<Field,Field,MC,MR> NProx( NPre );
    auto& A = AProx.Get();
    auto& N = NProx.Get();

    DistMatrix<Field> ACopy( A );
    sign::Newton( A, ctrl );
    Gemm( NORMAL, NORMAL, Field(1), A, ACopy, N );
}
Ejemplo n.º 6
0
void Sign
( ElementalMatrix<F>& APre,
  ElementalMatrix<F>& NPre, 
  const SignCtrl<Base<F>> ctrl )
{
    DEBUG_CSE

    DistMatrixReadWriteProxy<F,F,MC,MR> AProx( APre );
    DistMatrixWriteProxy<F,F,MC,MR> NProx( NPre );
    auto& A = AProx.Get();
    auto& N = NProx.Get();

    DistMatrix<F> ACopy( A );
    sign::Newton( A, ctrl );
    Gemm( NORMAL, NORMAL, F(1), A, ACopy, N );
}
Ejemplo n.º 7
0
ValueInt<Base<F>> InverseFreeSignDivide( ElementalMatrix<F>& XPre )
{
    DEBUG_CSE

    DistMatrixReadWriteProxy<F,F,MC,MR> XProx( XPre );
    auto& X = XProx.Get();

    typedef Base<F> Real;
    const Grid& g = X.Grid();
    const Int n = X.Width();
    if( X.Height() != 2*n )
        LogicError("Matrix should be 2n x n");
   
    // Expose A and B, and then copy A
    auto B = X( IR(0,n  ), ALL );
    auto A = X( IR(n,2*n), ALL );
    DistMatrix<F> ACopy( A );

    // Run the inverse-free alternative to Sign
    InverseFreeSign( X );

    // Compute the pivoted QR decomp of inv(A + B) A [See LAWN91]
    // 1) B := A + B 
    // 2) [Q,R,Pi] := QRP(A)
    // 3) B := Q^H B
    // 4) [R,Q] := RQ(B)
    B += A;
    DistMatrix<F,MD,STAR> t(g);
    DistMatrix<Base<F>,MD,STAR> d(g);
    DistMatrix<Int,VR,STAR> p(g);
    QR( A, t, d, p );
    qr::ApplyQ( LEFT, ADJOINT, A, t, d, B );
    RQ( B, t, d );

    // A := Q^H A Q
    A = ACopy;
    rq::ApplyQ( LEFT, ADJOINT, B, t, d, A );
    rq::ApplyQ( RIGHT, NORMAL, B, t, d, A );

    // Return || E21 ||1 / || A ||1
    // Return || E21 ||1 / || A ||1
    ValueInt<Real> part = ComputePartition( A );
    part.value /= OneNorm(ACopy);
    return part;
}
Ejemplo n.º 8
0
inline typename Base<F>::type 
LogDetDivergence( UpperOrLower uplo, const Matrix<F>& A, const Matrix<F>& B )
{
#ifndef RELEASE
    PushCallStack("LogDetDivergence");
#endif
    if( A.Height() != A.Width() || B.Height() != B.Width() ||
        A.Height() != B.Height() )
        throw std::logic_error
        ("A and B must be square matrices of the same size");

    typedef typename Base<F>::type R;
    const int n = A.Height();

    Matrix<F> ACopy( A );
    Matrix<F> BCopy( B );

    Cholesky( uplo, ACopy );
    Cholesky( uplo, BCopy );

    if( uplo == LOWER )
    {
        Trtrsm( LEFT, uplo, NORMAL, NON_UNIT, F(1), BCopy, ACopy );
    }
    else
    {
        MakeTrapezoidal( LEFT, uplo, 0, ACopy );
        Trsm( LEFT, uplo, NORMAL, NON_UNIT, F(1), BCopy, ACopy );
    }

    MakeTrapezoidal( LEFT, uplo, 0, ACopy );
    const R frobNorm = Norm( ACopy, FROBENIUS_NORM );

    Matrix<F> d;
    ACopy.GetDiagonal( d );
    R logDet(0);
    for( int i=0; i<n; ++i )
        logDet += 2*Log( RealPart(d.Get(i,0)) );

    const R logDetDiv = frobNorm*frobNorm - logDet - R(n);
#ifndef RELEASE
    PopCallStack();
#endif
    return logDetDiv;
}
Ejemplo n.º 9
0
QDWHInfo
QDWH
( AbstractDistMatrix<F>& APre,
  AbstractDistMatrix<F>& PPre,
  const QDWHCtrl& ctrl )
{
    EL_DEBUG_CSE

    DistMatrixReadWriteProxy<F,F,MC,MR> AProx( APre );
    DistMatrixWriteProxy<F,F,MC,MR> PProx( PPre );
    auto& A = AProx.Get();
    auto& P = PProx.Get();

    DistMatrix<F> ACopy( A );
    auto info = QDWH( A, ctrl );
    Zeros( P, A.Height(), A.Height() );
    Trrk( LOWER, NORMAL, NORMAL, F(1), A, ACopy, F(0), P );
    MakeHermitian( LOWER, P );
    return info;
}
Ejemplo n.º 10
0
Base<F> InverseFreeSignDivide( Matrix<F>& X )
{
    DEBUG_CSE
    typedef Base<F> Real;
    const Int n = X.Width();
    if( X.Height() != 2*n )
        LogicError("Matrix should be 2n x n");
   
    // Expose A and B, and then copy A
    auto B = X( IR(0,n  ), ALL );
    auto A = X( IR(n,2*n), ALL );
    Matrix<F> ACopy( A );

    // Run the inverse-free alternative to Sign
    InverseFreeSign( X );

    // Compute the pivoted QR decomp of inv(A + B) A [See LAWN91]
    // 1) B := A + B 
    // 2) [Q,R,Pi] := QRP(A)
    // 3) B := Q^H B
    // 4) [R,Q] := RQ(B)
    B += A;
    Matrix<F> t;
    Matrix<Base<F>> d;
    Matrix<Int> p;
    QR( A, t, d, p );
    qr::ApplyQ( LEFT, ADJOINT, A, t, d, B );
    RQ( B, t, d );

    // A := Q^H A Q
    A = ACopy;
    rq::ApplyQ( LEFT, ADJOINT, B, t, d, A );
    rq::ApplyQ( RIGHT, NORMAL, B, t, d, A );

    // Return || E21 ||1 / || A ||1
    ValueInt<Real> part = ComputePartition( A );
    part.value /= OneNorm(ACopy);
    return part;
}
Ejemplo n.º 11
0
inline void
SVDUpper
( DistMatrix<F>& A,
  DistMatrix<typename Base<F>::type,VR,STAR>& s,
  DistMatrix<F>& V,
  double heightRatio=1.5 )
{
#ifndef RELEASE
    PushCallStack("svd::SVDUpper");
    if( A.Height() < A.Width() )
        throw std::logic_error("A must be at least as tall as it is wide");
    if( heightRatio <= 1.0 )
        throw std::logic_error("Nonsensical switchpoint for SVD");
#endif
    const Grid& g = A.Grid();
    const int m = A.Height();
    const int n = A.Width();
    if( m > heightRatio*n )
    {
        DistMatrix<F> R(g);
        ExplicitQR( A, R );
        svd::SimpleSVDUpper( R, s, V );
        // Unfortunately, extra memory is used in forming A := A R,
        // where A has been overwritten with the Q from the QR factorization
        // of the original state of A, and R has been overwritten with the U 
        // from the SVD of the R from the QR factorization of A
        //
        // Perhaps this should be broken into pieces.
        DistMatrix<F> ACopy( A );
        Gemm( NORMAL, NORMAL, F(1), ACopy, R, F(0), A );
    }
    else
    {
        svd::SimpleSVDUpper( A, s, V );
    }
#ifndef RELEASE
    PopCallStack();
#endif
}
Ejemplo n.º 12
0
std::tuple<bool, CMatrix2D const, std::vector<double> >
LinearSolver::GaussElim(CMatrix2D const & A, std::vector<double> const & f) {
    // Solve the equation A x = f using Gauss' elimination method with
    // row pivoting.
    // Description of algorithm: First, search for the largest element
    // in all following row and use it as the pivot element. This is to
    // reduce round-off errors. The matrix ACopy will be transformed
    // into the identity matrix, while the identity matrix, AInv, will
    // be transformed into the inverse.
    // A x =  Id y is successively transformed into A^{-1} A x = A^{-1} Id f,
    // where ACopy = Id and A^{-1} = AInv.
    boost::uint64_t max_col = A.getCols();
    boost::uint64_t max_row = A.getRows();
    bool success = false;
    CMatrix2D ACopy(A);
    CMatrix2D AInv(CMatrix2D::identity(max_col));
    std::vector<double> rhs(f);

    bool assert_cond = max_col == max_row;
    BOOST_ASSERT_MSG(assert_cond, "LinearSolver::GaussElim: Matrix must be quadratic");
    if (!assert_cond)
        throw std::out_of_range("LinearSolver::GaussElim: Matrix must be quadratic");

    // Create row-row map (because of pivoting)
    std::vector<int> row_row_map(max_row);
    for (int i = 0; i < max_row; ++i)
        row_row_map[i] = i;

    for (int col = 0; col < max_col; ++col) {
        // Find pivot element row index
        int pivot_index = findPivotIndex(ACopy, col, row_row_map);

        // Arrange rows due to row pivoting
        if (col != row_row_map[pivot_index]) {
            row_row_map[pivot_index] = col;
            row_row_map[row_row_map[col]] = pivot_index;
        }

        BOOST_ASSERT_MSG(row_row_map[pivot_index] == col, "LinearSolver::GaussElim: Pivoting error");
        double pivot_element = ACopy(pivot_index, col);

        // Matrix is singular
        if (pivot_element == 0.0)
            return std::make_tuple(false, AInv, rhs);

        // Divide pivot row by pivot element to set element to 1
        for (int i = 0; i < max_col; ++i) {
            // ACopy(pivot_index, i) = 0 for i < col
            if (i >= col) {
                double& val1 = ACopy(pivot_index, i);
                val1 /= pivot_element;
            }

            double& val2 = AInv(pivot_index, i);
            val2 /= pivot_element;
        }

        // Do same transformation on the rhs
        rhs[pivot_index] /= pivot_element;

        // Add pivot row to all other rows to reduce column col
        // to the corresponding identity matrix column.
        for (int current_row = 0; current_row < max_row; ++current_row) {
            if (current_row == pivot_index)
                continue;

            double val = - ACopy(current_row, col) / ACopy(pivot_index, col);

            for (int j = 0; j < max_col; ++j) {
                ACopy(current_row, j) += val * ACopy(pivot_index, j);
                AInv(current_row, j) += val * AInv(pivot_index, j);
            }

            // Do same transformation on the rhs
            rhs[current_row] += val * rhs[pivot_index];
        }
    }

    // Rearrange the rows in AInv due to pivoting
    for (int i = 0; i < max_row; ++i) {
        int row = row_row_map[i];

        if (row == i)
            continue;

        // Swap rows
        for (int j = 0; j < max_col; ++j) {
            double tmp = AInv(i, j);
            AInv(i, j) = AInv(row, j);
            AInv(row, j) = tmp;

            tmp = ACopy(i, j);
            ACopy(i, j) = ACopy(row, j);
            ACopy(row, j) = tmp;
        }

        // Swap rows on the rhs
        double tmp = rhs[i];
        rhs[i] = rhs[row];
        rhs[row] = tmp;

        row_row_map[i] = row_row_map[row];
        row_row_map[row] = row;
    }

    return std::make_tuple(success, AInv, rhs);
}
GaussJordan::Return_t
GaussJordan::solve(Matrix2D const & A, Vector const & f) const {
    // Solve the equation A x = f using Gauss-Jordan elimination with row pivoting.
    // Description of algorithm: First, search for the largest element in the current
    // column use it as the pivot element. This is to reduce round-off errors. The
    // matrix ACopy will be transformed into the identity matrix, while the identity
    // matrix, AInvwerse, will be transformed into the inverse.
    // A x =  Id y is successively transformed into A^{-1} A x = A^{-1} Id f,
    // where ACopy = Id and A^{-1} = AInverse.

    BOOST_ASSERT_MSG(A.cols() == A.rows(), "Gauss::solve: Matrix must be quadratic");
    BOOST_ASSERT_MSG(A.cols() == f.size(), "Gauss::solve: r.h.s. vector size mismatch");

    IMatrix2D::size_type max_col = A.cols();
    IMatrix2D::size_type max_row = A.rows();
    bool success = false;
    Matrix2D ACopy(A);
    Matrix2D AInverse(Matrix2D::identity(max_col));
    Vector rhs(f);

    initializePivoting(max_row);

    /* This is a column index, rather than a row index.
     * Obviously, this makes no difference for a square
     * matrix, but if #columns > #rows, the problem is
     * overspecified and then least-squares could be used.
     * The other extreme is an underspecified problem, which
     * we do not bother with at all here.
     */
    for (IMatrix2D::size_type col = 0; col < max_col; ++col) {
//         ACopy.print();
//         print(ACopy);
//         AInverse.print();
//         print(AInverse);

        auto physical_pivot_row_index = getPivotElementsRowIndex(ACopy, col);

        // "swap" rows 'col' and 'row_with_pivot_element' due to row pivoting
        adjustPivotingMap(col, physical_pivot_row_index);
        double pivot_element = ACopy(physical_pivot_row_index, col);
        if (pivot_element == 0.0)
            // Matrix is singular
            return std::make_tuple(false, AInverse, rhs);

        // Divide pivot row by pivot element to set pivot element to 1
        // as part of the reduction of ACopy to the identity matrix.
        // Note: Start column is 'col', as all elements with column
        // index (0, ..., col - 1) are 0 already.
        for (IMatrix2D::size_type i = 0; i < max_col; ++i) {
            if (i >= col) {
                double & val1 = ACopy(physical_pivot_row_index, i);
                val1 /= pivot_element;
            }
            double & val2 = AInverse(physical_pivot_row_index, i);
            val2 /= pivot_element;
        }

//         ACopy.print();
//         print(ACopy);
//         AInverse.print();
//         print(AInverse);

        // Do same transformation on the rhs
        rhs(physical_pivot_row_index) /= pivot_element;

        // Add pivot row to all later rows such that all elements
        // in those rows become 0, i.e. we set the column to the
        // column of the identity matrix.
        for (IMatrix2D::size_type i = 0; i < max_row; ++i) {
            auto mapped_i = logicalToPhysicalRowIndex(i);
            if (mapped_i == physical_pivot_row_index)
                // skip pivot row
                continue;
            double val = - ACopy(mapped_i, col) / ACopy(physical_pivot_row_index, col);

            // subtract the pivot row from row 'mapped_i'
            for (IMatrix2D::size_type j = 0; j < max_col; ++j) {
                if (j >= col)
                    ACopy(mapped_i, j) += val * ACopy(physical_pivot_row_index, j);
                AInverse(mapped_i, j) += val * AInverse(physical_pivot_row_index, j);
            }

            // do same transformation on the rhs
            rhs(mapped_i) += val * rhs(physical_pivot_row_index);

//             ACopy.print();
//             print(ACopy);
//             AInverse.print();
//             print(AInverse);
        }

//         ACopy.print();
//         print(ACopy);
//         AInverse.print();
//         print(AInverse);
    }

//     AInverse.print();
//     print(AInverse);

    // Rearrange the rows in AInverse due to pivoting
    rearrangeDueToPivoting(ACopy, AInverse, rhs);

//     ACopy.print();
//     AInverse.print();

    return std::make_tuple(success, AInverse, rhs);
}