예제 #1
0
void HermitianPseudoinverse
( UpperOrLower uplo, ElementalMatrix<F>& APre, Base<F> tolerance )
{
    DEBUG_CSE
    typedef Base<F> Real;

    DistMatrixReadWriteProxy<F,F,MC,MR> AProx( APre );
    auto& A = AProx.Get();
    const Grid& g = A.Grid();

    // Get the EVD of A
    // TODO: Use a relative eigenvalue lower-bound
    DistMatrix<Real,VR,STAR> w(g);
    DistMatrix<F> Z(g);
    HermitianEig( uplo, A, w, Z );

    if( tolerance == Real(0) )
    {
        // Set the tolerance equal to n ||A||_2 eps
        const Int n = Z.Height();
        const Real eps = limits::Epsilon<Real>();
        const Real twoNorm = MaxNorm( w );
        tolerance = n*twoNorm*eps;
    }
    // Invert above the tolerance
    auto omegaMap = 
      [=]( Real omega ) { return ( omega < tolerance ? Real(0) : 1/omega ); };
    EntrywiseMap( w, function<Real(Real)>(omegaMap) );

    // Form the pseudoinverse
    HermitianFromEVD( uplo, A, w, Z );
}
예제 #2
0
void HermitianSign
( UpperOrLower uplo, Matrix<Field>& A, const HermitianEigCtrl<Field>& ctrl )
{
    EL_DEBUG_CSE
    typedef Base<Field> Real;

    // Get the EVD of A
    Matrix<Real> w;
    Matrix<Field> Q;
    auto ctrlMod( ctrl );
    ctrlMod.tridiagEigCtrl.sort = UNSORTED;
    HermitianEig( uplo, A, w, Q, ctrlMod );

    const Int n = A.Height();
    for( Int i=0; i<n; ++i )
    {
        const Real omega = w(i);
        if( omega >= 0 )
            w(i) = Real(1);
        else
            w(i) = Real(-1);
    }

    // Reform the Hermitian matrix with the modified eigenvalues
    HermitianFromEVD( uplo, A, w, Q );
}
예제 #3
0
void HermitianPseudoinverse
( UpperOrLower uplo, Matrix<F>& A, Base<F> tolerance )
{
    DEBUG_CSE
    typedef Base<F> Real;

    // Get the EVD of A
    // TODO: Use a relative eigenvalue lower bound
    Matrix<Real> w;
    Matrix<F> Z;
    HermitianEig( uplo, A, w, Z );

    if( tolerance == Real(0) )
    {
        // Set the tolerance equal to n ||A||_2 eps
        const Int n = Z.Height();
        const Real eps = limits::Epsilon<Real>();
        const Real twoNorm = MaxNorm( w );
        tolerance = n*twoNorm*eps;
    }
    // Invert above the tolerance
    auto omegaMap = 
      [=]( Real omega ) { return ( omega < tolerance ? Real(0) : 1/omega ); };
    EntrywiseMap( w, function<Real(Real)>(omegaMap) );

    // Form the pseudoinverse
    HermitianFromEVD( uplo, A, w, Z );
}
예제 #4
0
inline void
HermitianSign( UpperOrLower uplo, Matrix<F>& A )
{
#ifndef RELEASE
    CallStackEntry entry("HermitianSign");
#endif
    typedef BASE(F) R;

    // Get the EVD of A
    Matrix<R> w;
    Matrix<F> Z;
    HermitianEig( uplo, A, w, Z );

    // Compute the two-norm of A as the maximum absolute value of its eigvals
    const R twoNorm = MaxNorm( w );

    // Set the tolerance equal to n ||A||_2 eps, and invert values above it
    const int n = A.Height();
    const R eps = lapack::MachineEpsilon<R>();
    const R tolerance = n*twoNorm*eps;
    for( int i=0; i<n; ++i )
    {
        const R omega = w.Get(i,0);
        if( Abs(omega) < tolerance )
            w.Set(i,0,0);
        else if( omega > 0 )
            w.Set(i,0,R(1));
        else
            w.Set(i,0,R(-1));
    }

    // Reform the Hermitian matrix with the modified eigenvalues
    hermitian_function::ReformHermitianMatrix( uplo, A, w, Z );
}
예제 #5
0
void HermitianSign
( UpperOrLower uplo,
  AbstractDistMatrix<Field>& APre,
  const HermitianEigCtrl<Field>& ctrl )
{
    EL_DEBUG_CSE

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

    // Get the EVD of A
    typedef Base<Field> Real;
    const Grid& g = A.Grid();
    DistMatrix<Real,VR,STAR> w(g);
    DistMatrix<Field> Q(g);
    auto ctrlMod( ctrl );
    ctrlMod.tridiagEigCtrl.sort = UNSORTED;
    HermitianEig( uplo, A, w, Q, ctrlMod );

    const Int numLocalEigs = w.LocalHeight();
    for( Int iLoc=0; iLoc<numLocalEigs; ++iLoc )
    {
        const Real omega = w.GetLocal(iLoc,0);
        if( omega >= 0 )
            w.SetLocal(iLoc,0,Real(1));
        else
            w.SetLocal(iLoc,0,Real(-1));
    }

    // Reform the Hermitian matrix with the modified eigenvalues
    HermitianFromEVD( uplo, A, w, Q );
}
예제 #6
0
inline void
HermitianPseudoinverse
( UpperOrLower uplo, DistMatrix<Complex<R>,MC,MR>& A )
{
#ifndef RELEASE
    PushCallStack("HermitianPseudoinverse");
#endif
    // Get the EVD of A
    const Grid& g = A.Grid();
    DistMatrix<R,VR,STAR> w(g);
    DistMatrix<Complex<R>,MC,MR> Z(g);
    HermitianEig( uplo, A, w, Z );

    // Compute the two-norm of A as the maximum absolute value of its
    // eigenvalues
    R maxLocalAbsEig = 0;
    const int localHeight = w.LocalHeight();
    for( int iLocal=0; iLocal<localHeight; ++iLocal )
        maxLocalAbsEig = 
            std::max(maxLocalAbsEig,Abs(w.GetLocalEntry(iLocal,0)));
    R twoNorm;
    mpi::AllReduce( &maxLocalAbsEig, &twoNorm, 1, mpi::MAX, g.VCComm() );

    // Set the tolerance equal to n ||A||_2 eps
    const int n = A.Height();
    const R eps = lapack::MachineEpsilon<R>();
    const R tolerance = n*twoNorm*eps;

    // Form the pseudoinverse
    hermitian_pseudoinverse::Functor<R> f( tolerance );
    hermitian_function::ReformHermitianMatrix( uplo, A, w, Z, f );
#ifndef RELEASE
    PopCallStack();
#endif
}
예제 #7
0
void SkewHermitianEig
( UpperOrLower uplo, const Matrix<F>& G, Matrix<Base<F>>& wImag, SortType sort, 
  const HermitianEigSubset<Base<F>>& subset,
  const HermitianEigCtrl<Complex<Base<F>>>& ctrl )
{
    DEBUG_ONLY(CSE cse("SkewHermitianEig"))
    Matrix<Complex<Base<F>>> A;
    Copy( G, A );
    ScaleTrapezoid( Complex<Base<F>>(0,-1), uplo, A );
    HermitianEig( uplo, A, wImag, sort, subset, ctrl );
}
예제 #8
0
void SkewHermitianEig
( UpperOrLower uplo, const AbstractDistMatrix<F>& G,
  AbstractDistMatrix<Base<F>>& wImag, SortType sort,
  const HermitianEigSubset<Base<F>>& subset,
  const HermitianEigCtrl<Complex<Base<F>>>& ctrl )
{
    DEBUG_ONLY(CallStackEntry cse("SkewHermitianEig"))
    DistMatrix<Complex<Base<F>>> A(G.Grid());
    Copy( G, A );
    ScaleTrapezoid( Complex<Base<F>>(0,-1), uplo, A );
    HermitianEig( uplo, A, wImag, sort, subset, ctrl );
}
예제 #9
0
inline void HermitianSVD
( UpperOrLower uplo, DistMatrix<F>& A, 
  DistMatrix<BASE(F),VR,STAR>& s, DistMatrix<F>& U, DistMatrix<F>& V )
{
#ifndef RELEASE
    CallStackEntry entry("HermitianSVD");
#endif
#ifdef HAVE_PMRRR
    typedef BASE(F) R;

    // Grab an eigenvalue decomposition of A
    HermitianEig( uplo, A, s, V );

    // Redistribute the singular values into an [MR,* ] distribution
    const Grid& grid = A.Grid();
    DistMatrix<R,MR,STAR> s_MR_STAR( grid );
    s_MR_STAR.AlignWith( V.DistData() );
    s_MR_STAR = s;

    // Set the singular values to the absolute value of the eigenvalues
    const Int numLocalVals = s.LocalHeight();
    for( Int iLoc=0; iLoc<numLocalVals; ++iLoc )
    {
        const R sigma = s.GetLocal(iLoc,0);
        s.SetLocal(iLoc,0,Abs(sigma));
    }

    // Copy V into U (flipping the sign as necessary)
    U.AlignWith( V );
    U.ResizeTo( V.Height(), V.Width() );
    const Int localHeight = V.LocalHeight();
    const Int localWidth = V.LocalWidth();
    for( Int jLoc=0; jLoc<localWidth; ++jLoc )
    {
        const R sigma = s_MR_STAR.GetLocal( jLoc, 0 );
        F* UCol = U.Buffer( 0, jLoc );
        const F* VCol = V.LockedBuffer( 0, jLoc );
        if( sigma >= 0 )
            for( Int iLoc=0; iLoc<localHeight; ++iLoc )
                UCol[iLoc] = VCol[iLoc];
        else
            for( Int iLoc=0; iLoc<localHeight; ++iLoc )
                UCol[iLoc] = -VCol[iLoc];
    }
#else
    U = A;
    MakeHermitian( uplo, U );
    SVD( U, s, V );
#endif // ifdef HAVE_PMRRR
}
예제 #10
0
inline void HermitianSVD
( UpperOrLower uplo, 
  DistMatrix<F>& A, DistMatrix<typename Base<F>::type,VR,STAR>& s, 
  DistMatrix<F>& U, DistMatrix<F>& V )
{
#ifndef RELEASE
    PushCallStack("HermitianSVD");
#endif
    typedef typename Base<F>::type R;

    // Grab an eigenvalue decomposition of A
    HermitianEig( uplo, A, s, V ); 
    
    // Redistribute the singular values into an [MR,* ] distribution
    const Grid& grid = A.Grid();
    DistMatrix<R,MR,STAR> s_MR_STAR( grid );
    s_MR_STAR.AlignWith( V );
    s_MR_STAR = s;

    // Set the singular values to the absolute value of the eigenvalues
    const int numLocalVals = s.LocalHeight();
    for( int iLocal=0; iLocal<numLocalVals; ++iLocal )
    {
        const R sigma = s.GetLocal(iLocal,0);
        s.SetLocal(iLocal,0,Abs(sigma));
    }

    // Copy V into U (flipping the sign as necessary)
    U.AlignWith( V );
    U.ResizeTo( V.Height(), V.Width() );
    const int localHeight = V.LocalHeight();
    const int localWidth = V.LocalWidth();
    for( int jLocal=0; jLocal<localWidth; ++jLocal )
    {
        const R sigma = s_MR_STAR.GetLocal( jLocal, 0 );
        F* UCol = U.LocalBuffer( 0, jLocal );
        const F* VCol = V.LockedLocalBuffer( 0, jLocal );
        if( sigma >= 0 )
            for( int iLocal=0; iLocal<localHeight; ++iLocal )
                UCol[iLocal] = VCol[iLocal];
        else
            for( int iLocal=0; iLocal<localHeight; ++iLocal )
                UCol[iLocal] = -VCol[iLocal];
    }
#ifndef RELEASE
    PopCallStack();
#endif
}
예제 #11
0
void HermitianSign
( UpperOrLower uplo,
  ElementalMatrix<F>& APre,
  ElementalMatrix<F>& NPre,
  const HermitianEigCtrl<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();

    // Get the EVD of A
    typedef Base<F> Real;
    const Grid& g = A.Grid();
    DistMatrix<Real,VR,STAR> w(g);
    DistMatrix<F> Q(g);
    auto ctrlMod( ctrl );
    ctrlMod.tridiagEigCtrl.sort = UNSORTED;
    HermitianEig( uplo, A, w, Q, ctrlMod );

    const Int n = A.Height();
    const Int numLocalEigs = w.LocalHeight();
    DistMatrix<Real,VR,STAR> wSgn(g), wAbs(g);
    wSgn.AlignWith( w );
    wAbs.AlignWith( w );
    wSgn.Resize( n, 1 );
    wAbs.Resize( n, 1 );
    for( Int iLoc=0; iLoc<numLocalEigs; ++iLoc )
    {
        const Real omega = w.GetLocal(iLoc,0);
        if( omega >= 0 )
        {
            wSgn.SetLocal(iLoc,0,Real(1));
            wAbs.SetLocal(iLoc,0,omega);
        }
        else
        {
            wSgn.SetLocal(iLoc,0,Real(-1));
            wAbs.SetLocal(iLoc,0,-omega);
        }
    }

    // Form the Hermitian matrix with the modified eigenvalues
    HermitianFromEVD( uplo, A, wSgn, Q );
    HermitianFromEVD( uplo, N, wAbs, Q );
}
예제 #12
0
inline void
HermitianPseudoinverse
( UpperOrLower uplo, DistMatrix<F>& A )
{
#ifndef RELEASE
    PushCallStack("HermitianPseudoinverse");
#endif
    typedef typename Base<F>::type R;

    // Get the EVD of A
    const Grid& g = A.Grid();
    DistMatrix<R,VR,STAR> w(g);
    DistMatrix<F> Z(g);
    HermitianEig( uplo, A, w, Z );

    // Compute the two-norm of A as the maximum absolute value of its
    // eigenvalues
    R maxLocalAbsEig = 0;
    const int numLocalEigs = w.LocalHeight();
    for( int iLocal=0; iLocal<numLocalEigs; ++iLocal )
    {
        const R omega = w.GetLocal(iLocal,0);
        maxLocalAbsEig = std::max(maxLocalAbsEig,Abs(omega));
    }
    R twoNorm;
    mpi::AllReduce( &maxLocalAbsEig, &twoNorm, 1, mpi::MAX, g.VCComm() );

    // Set the tolerance equal to n ||A||_2 eps, and invert values above it
    const int n = A.Height();
    const R eps = lapack::MachineEpsilon<R>();
    const R tolerance = n*twoNorm*eps;
    for( int iLocal=0; iLocal<numLocalEigs; ++iLocal )
    {
        const R omega = w.GetLocal(iLocal,0);
        if( Abs(omega) < tolerance )
            w.SetLocal(iLocal,0,0);
        else
            w.SetLocal(iLocal,0,1/omega);
    }

    // Form the pseudoinverse
    hermitian_function::ReformHermitianMatrix( uplo, A, w, Z );
#ifndef RELEASE
    PopCallStack();
#endif
}
예제 #13
0
inline void
HPSDSquareRoot( UpperOrLower uplo, DistMatrix<R,MC,MR>& A )
{
#ifndef RELEASE
    PushCallStack("HPSDSquareRoot");
#endif
    // Get the EVD of A
    const Grid& g = A.Grid();
    DistMatrix<R,VR,STAR> w(g);
    DistMatrix<R,MC,MR> Z(g);
    HermitianEig( uplo, A, w, Z );

    // Compute the two-norm of A as the maximum absolute value 
    // of its eigenvalues
    R maxLocalAbsEig = 0;
    const int localHeight = w.LocalHeight();
    for( int iLocal=0; iLocal<localHeight; ++iLocal )
        maxLocalAbsEig = 
            std::max(maxLocalAbsEig,Abs(w.GetLocalEntry(iLocal,0)));
    R twoNorm;
    mpi::AllReduce( &maxLocalAbsEig, &twoNorm, 1, mpi::MAX, g.VCComm() );

    // Compute the smallest eigenvalue of A
    R minLocalEig = twoNorm;
    for( int iLocal=0; iLocal<localHeight; ++iLocal )
        minLocalEig = std::min(minLocalEig,w.GetLocalEntry(iLocal,0));
    R minEig;
    mpi::AllReduce( &minLocalEig, &minEig, 1, mpi::MIN, g.VCComm() );

    // Set the tolerance equal to n ||A||_2 eps
    const int n = A.Height();
    const R eps = lapack::MachineEpsilon<R>();
    const R tolerance = n*twoNorm*eps;

    // Ensure that the minimum eigenvalue is not less than - n ||A||_2 eps
    if( minEig < -tolerance )
        throw NonHPSDMatrixException();

    // Form the pseudoinverse
    square_root::Functor<R> f( tolerance );
    hermitian_function::ReformHermitianMatrix( uplo, A, w, Z, f );
#ifndef RELEASE
    PopCallStack();
#endif
}
예제 #14
0
inline void HermitianSVD
( UpperOrLower uplo, Matrix<F>& A, Matrix<BASE(F)>& s )
{
#ifndef RELEASE
    CallStackEntry entry("HermitianSVD");
#endif
#if 1
    // Grab the eigenvalues of A
    HermitianEig( uplo, A, s );

    // Set the singular values to the absolute value of the eigenvalues
    for( Int i=0; i<s.Height(); ++i )
        s.Set(i,0,Abs(s.Get(i,0)));
#else
    MakeHermitian( uplo, A );
    SVD( A, s );
#endif 
}
예제 #15
0
inline void
RealHermitianFunction
( UpperOrLower uplo, DistMatrix<R,MC,MR>& A, const RealFunctor& f )
{
#ifndef RELEASE
    PushCallStack("RealHermitianFunction");
#endif
    if( A.Height() != A.Width() )
        throw std::logic_error("Hermitian matrices must be square");

    // Get the EVD of A
    const Grid& g = A.Grid();
    DistMatrix<R,VR,STAR> w(g);
    DistMatrix<R,MC,MR> Z(g);
    HermitianEig( uplo, A, w, Z );

    // Form the custom outer product, Z f(Omega) Z^T
    hermitian_function::ReformHermitianMatrix( uplo, A, w, Z, f );
#ifndef RELEASE
    PopCallStack();
#endif
}
예제 #16
0
inline void HermitianSVD
( UpperOrLower uplo,
  Matrix<F>& A, Matrix<BASE(F)>& s, Matrix<F>& U, Matrix<F>& V )
{
#ifndef RELEASE
    CallStackEntry entry("HermitianSVD");
#endif
#if 1
    typedef BASE(F) R;

    // Grab an eigenvalue decomposition of A
    HermitianEig( uplo, A, s, V );

    // Set the singular values to the absolute value of the eigenvalues
    for( Int i=0; i<s.Height(); ++i )
        s.Set(i,0,Abs(s.Get(i,0)));

    // Copy V into U (flipping the sign as necessary)
    const Int n = A.Height();
    U.ResizeTo( n, n );
    for( Int j=0; j<n; ++j )
    {
        const R sigma = s.Get( j, 0 );
        F* UCol = U.Buffer( 0, j );
        const F* VCol = V.LockedBuffer( 0, j );
        if( sigma >= 0 )
            for( Int i=0; i<n; ++i )
                UCol[i] = VCol[i];
        else
            for( Int i=0; i<n; ++i )
                UCol[i] = -VCol[i];
    }
#else
    U = A;
    MakeHermitian( uplo, U );
    SVD( U, s, V );
#endif 
}
예제 #17
0
inline void HermitianSingularValues
( UpperOrLower uplo, 
  DistMatrix<F>& A, DistMatrix<typename Base<F>::type,VR,STAR>& s )
{
#ifndef RELEASE
    PushCallStack("HermitianSingularValues");
#endif
    typedef typename Base<F>::type R;

    // Grab an eigenvalue decomposition of A
    HermitianEig( uplo, A, s ); 
    
    // Replace the eigenvalues with their absolute values
    const int numLocalVals = s.LocalHeight();
    for( int iLocal=0; iLocal<numLocalVals; ++iLocal )
    {
        const R sigma = s.GetLocal(iLocal,0);
        s.SetLocal(iLocal,0,Abs(sigma));
    }
#ifndef RELEASE
    PopCallStack();
#endif
}
예제 #18
0
void HermitianSVD
( UpperOrLower uplo, AbstractDistMatrix<F>& A, AbstractDistMatrix<Base<F>>& s, 
  AbstractDistMatrix<F>& U, AbstractDistMatrix<F>& V )
{
    DEBUG_ONLY(CallStackEntry cse("HermitianSVD"))

    // Grab an eigenvalue decomposition of A
    HermitianEig( uplo, A, s, V );

    // Copy V into U (flipping the sign as necessary)
    Copy( U, V );
    typedef Base<F> Real;
    DistMatrix<Real,VR,STAR> sSgn( s );
    auto sgnLambda = []( Real sigma ) { return Sgn(sigma,false); };
    EntrywiseMap( sSgn, function<Real(Real)>(sgnLambda) );
    DiagonalScale( RIGHT, NORMAL, sSgn, U );

    // Set the singular values to the absolute value of the eigenvalues
    auto absLambda = []( Real sigma ) { return Abs(sigma); };
    EntrywiseMap( s, function<Real(Real)>(absLambda) );

    // TODO: Descending sort of triplets
}
예제 #19
0
void HermitianSign
( UpperOrLower uplo,
  Matrix<Field>& A,
  Matrix<Field>& N,
  const HermitianEigCtrl<Field>& ctrl )
{
    EL_DEBUG_CSE
    typedef Base<Field> Real;

    // Get the EVD of A
    Matrix<Real> w;
    Matrix<Field> Q;
    auto ctrlMod( ctrl );
    ctrlMod.tridiagEigCtrl.sort = UNSORTED;
    HermitianEig( uplo, A, w, Q, ctrlMod );

    const Int n = A.Height();
    Matrix<Real> wSgn( n, 1 ), wAbs( n, 1 );
    for( Int i=0; i<n; ++i )
    {
        const Real omega = w(i);
        if( omega >= 0 )
        {
            wSgn(i) = Real(1);
            wAbs(i) = omega;
        }
        else
        {
            wSgn(i) = Real(-1);
            wAbs(i) = -omega;
        }
    }

    // Form the Hermitian matrices with modified eigenvalues
    HermitianFromEVD( uplo, A, wSgn, Q );
    HermitianFromEVD( uplo, N, wAbs, Q );
}
예제 #20
0
void HermitianSVD
( UpperOrLower uplo,
  Matrix<F>& A, Matrix<Base<F>>& s, Matrix<F>& U, Matrix<F>& V )
{
    DEBUG_ONLY(CallStackEntry cse("HermitianSVD"))
#if 1
    // Grab an eigenvalue decomposition of A
    HermitianEig( uplo, A, s, V );

    // Copy V into U (flipping the sign as necessary)
    const Int n = A.Height();
    U.Resize( n, n );
    for( Int j=0; j<n; ++j )
    {
        const Base<F> sigma = s.Get( j, 0 );
        F* UCol = U.Buffer( 0, j );
        const F* VCol = V.LockedBuffer( 0, j );
        if( sigma >= 0 )
        {
            for( Int i=0; i<n; ++i )
                UCol[i] = VCol[i];
        }
        else
        {
            for( Int i=0; i<n; ++i )
                UCol[i] = -VCol[i];
            s.Set( j, 0, -sigma );
        }
    }

    // TODO: Descending sort of triplets
#else
    U = A;
    MakeHermitian( uplo, U );
    SVD( U, s, V );
#endif 
}
예제 #21
0
inline void HermitianSVD
( UpperOrLower uplo, DistMatrix<F>& A, DistMatrix<BASE(F),VR,STAR>& s )
{
#ifndef RELEASE
    CallStackEntry entry("HermitianSVD");
#endif
#ifdef HAVE_PMRRR
    typedef BASE(F) R;

    // Grab the eigenvalues of A
    HermitianEig( uplo, A, s );

    // Replace the eigenvalues with their absolute values
    const Int numLocalVals = s.LocalHeight();
    for( Int iLoc=0; iLoc<numLocalVals; ++iLoc )
    {
        const R sigma = s.GetLocal(iLoc,0);
        s.SetLocal(iLoc,0,Abs(sigma));
    }
#else
    MakeHermitian( uplo, A );
    SVD( A, s );
#endif // ifdef HAVE_PMRRR
}