MaxCondition( const DistMatrix<F,U,V>& A ) { #ifndef RELEASE CallStackEntry entry("MaxCondition"); #endif typedef BASE(F) Real; DistMatrix<F> B( A ); const Real maxNorm = MaxNorm( B ); try { Inverse( B ); } catch( SingularMatrixException& e ) { return std::numeric_limits<Real>::infinity(); } const Real maxNormInv = MaxNorm( B ); return maxNorm*maxNormInv; }
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 ); }
pair<Base<F>,Base<F>> HermitianHelper( const DistSparseMatrix<F>& A, Int basisSize ) { typedef Base<F> Real; Grid grid( A.Comm() ); DistMatrix<Real,STAR,STAR> T(grid); Lanczos( A, T, basisSize ); const Int k = T.Height(); if( k == 0 ) return pair<Real,Real>(0,0); auto d = GetDiagonal( T.Matrix() ); auto dSub = GetDiagonal( T.Matrix(), -1 ); Matrix<Real> w; HermitianTridiagEig( d, dSub, w ); pair<Real,Real> extremal; extremal.second = MaxNorm(w); extremal.first = extremal.second; for( Int i=0; i<k; ++i ) extremal.first = Min(extremal.first,Abs(w.Get(i,0))); return extremal; }
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 ); }
Base<F> Norm( const Matrix<F>& A, NormType type ) { DEBUG_ONLY(CSE cse("Norm")) Base<F> norm = 0; switch( type ) { // The following norms are rather cheap to compute case ENTRYWISE_ONE_NORM: norm = EntrywiseNorm( A, Base<F>(1) ); break; case FROBENIUS_NORM: norm = FrobeniusNorm( A ); break; case INFINITY_NORM: norm = InfinityNorm( A ); break; case MAX_NORM: norm = MaxNorm( A ); break; case ONE_NORM: norm = OneNorm( A ); break; // The following two norms make use of an SVD case NUCLEAR_NORM: norm = NuclearNorm( A ); break; case TWO_NORM: norm = TwoNorm( A ); break; } return norm; }
pair<Base<F>,Base<F>> HermitianExtremalSingValEst( const SparseMatrix<F>& A, Int basisSize ) { EL_DEBUG_CSE typedef Base<F> Real; Matrix<Real> T; Lanczos( A, T, basisSize ); const Int k = T.Height(); if( k == 0 ) return pair<Real,Real>(0,0); Matrix<Real> d, dSub; d = GetDiagonal( T ); dSub = GetDiagonal( T, -1 ); Matrix<Real> w; HermitianTridiagEig( d, dSub, w ); pair<Real,Real> extremal; extremal.second = MaxNorm(w); extremal.first = extremal.second; for( Int i=0; i<k; ++i ) extremal.first = Min(extremal.first,Abs(w(i))); return extremal; }
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 ); }
Base<F> SymmetricTwoNorm( UpperOrLower uplo, const Matrix<F>& A ) { DEBUG_ONLY(CSE cse("SymmetricTwoNorm")) Matrix<F> B( A ); Matrix<Base<F>> s; MakeSymmetric( uplo, B ); SVD( B, s ); return MaxNorm( s ); }
Base<F> SymmetricTwoNorm( UpperOrLower uplo, const AbstractDistMatrix<F>& A ) { DEBUG_ONLY(CSE cse("SymmetricTwoNorm")) DistMatrix<F> B( A ); DistMatrix<Base<F>,VR,STAR> s( A.Grid() ); MakeSymmetric( uplo, B ); SVD( B, s ); return MaxNorm( s ); }
Base<F> SymmetricTwoNorm( UpperOrLower uplo, const Matrix<F>& A ) { DEBUG_ONLY(CSE cse("SymmetricTwoNorm")) Matrix<F> B( A ); Matrix<Base<F>> s; MakeSymmetric( uplo, B ); SVDCtrl<Base<F>> ctrl; ctrl.overwrite = true; SVD( B, s, ctrl ); return MaxNorm( s ); }
Base<F> SymmetricTwoNorm( UpperOrLower uplo, const ElementalMatrix<F>& A ) { DEBUG_ONLY(CSE cse("SymmetricTwoNorm")) DistMatrix<F> B( A ); DistMatrix<Base<F>,VR,STAR> s( A.Grid() ); MakeSymmetric( uplo, B ); SVDCtrl<Base<F>> ctrl; ctrl.overwrite = true; SVD( B, s, ctrl ); return MaxNorm( s ); }
SymmetricTwoNorm( UpperOrLower uplo, const DistMatrix<F,U,V>& A ) { #ifndef RELEASE CallStackEntry entry("SymmetricTwoNorm"); #endif typedef BASE(F) R; DistMatrix<F,U,V> B( A ); DistMatrix<R,VR,STAR> s( A.Grid() ); MakeSymmetric( uplo, B ); SVD( B, s ); return MaxNorm( s ); }
SymmetricTwoNorm( UpperOrLower uplo, const Matrix<F>& A ) { #ifndef RELEASE CallStackEntry entry("SymmetricTwoNorm"); #endif typedef BASE(F) R; Matrix<F> B( A ); Matrix<R> s; MakeSymmetric( uplo, B ); SVD( B, s ); return MaxNorm( s ); }
TwoNormUpperBound( const DistMatrix<F>& A ) { #ifndef RELEASE CallStackEntry entry("TwoNormUpperBound"); #endif typedef BASE(F) R; const R m = A.Height(); const R n = A.Width(); const R maxNorm = MaxNorm( A ); const R oneNorm = OneNorm( A ); const R infNorm = InfinityNorm( A ); R upperBound = std::min( Sqrt(m*n)*maxNorm, Sqrt(m)*infNorm ); upperBound = std::min( upperBound, Sqrt(n)*oneNorm ); upperBound = std::min( upperBound, Sqrt( oneNorm*infNorm ) ); return upperBound; }
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 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; const int numLocalEigs = w.LocalHeight(); 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 }
namespace El { namespace kmeans { template<typename F> void AssignClusters ( const Matrix<F>& D, Matrix<Int>& cluster, Matrix<Base<F>>& dist ) { DEBUG_ONLY(CallStackEntry cse("kmeans::AssignClusters")) typedef Base<F> Real; const Int numPoints = D.Height(); const Int numClusters = D.Width(); cluster.Resize( numPoints, 1 ); dist.Resize( numPoints, 1 ); const Base<F> maxNorm = MaxNorm( D ); vector<ValueInt<Real>> choices(numPoints); for( Int i=0; i<numPoints; ++i ) { ValueInt<Real> choice; choice.value = 2*maxNorm; choice.index = -1; for( Int j=0; j<numClusters; ++j ) { const Real rho = RealPart(D.Get(i,j)); if( rho < choice.value ) { choice.value = rho; choice.index = j; }
int main( int argc, char* argv[] ) { El::Environment env( argc, argv ); try { El::Int gridHeight = El::Input("--gridHeight","process grid height",0); const bool colMajor = El::Input("--colMajor","column-major ordering?",true); const El::Int matType = El::Input("--matType","0:uniform,\n" "1:Haar,\n" "2:Lotkin,\n" "3:Grcar,\n" "4:FoxLi,\n" "5:HelmholtzPML1D,\n" "6:HelmholtzPML2D,\n" "7:TrefethenEmbree,\n" "8:Bull's head,\n" "9:Triangle,\n" "10:Whale,\n" "11:UniformHelmholtzGreen's,\n" "12:HatanoNelson,\n" "13:EhrenfestDecay,\n" "14:RiffleDecay\n" "15:Jordan\n",4); const El::Int normInt = El::Input("--norm","0:two norm,1:one norm",0); const El::Int n = El::Input("--size","height of matrix",100); const El::Int nbAlg = El::Input("--nbAlg","algorithmic blocksize",96); // QR algorithm options const El::Int nbDist = El::Input("--nbDist","distribution blocksize",32); // Spectral Divide and Conquer options const bool sdc = El::Input("--sdc","use Spectral D&C?",false); const El::Int cutoff = El::Input("--cutoff","problem size for QR",256); const El::Int maxInnerIts = El::Input("--maxInnerIts","SDC limit",2); const El::Int maxOuterIts = El::Input("--maxOuterIts","SDC limit",10); const bool random = El::Input("--random","Random RRQR in SDC",true); const double sdcTol = El::Input("--sdcTol","Rel. tol. for SDC",1e-6); const double spreadFactor = El::Input("--spreadFactor","median pert.",1e-6); const double signTol = El::Input("--signTol","Sign tolerance for SDC",1e-9); const double realCenter = El::Input("--realCenter","real center",0.); const double imagCenter = El::Input("--imagCenter","imag center",0.); double realWidth = El::Input("--realWidth","x width of image",0.); double imagWidth = El::Input("--imagWidth","y width of image",0.); const El::Int numReal = El::Input("--numReal","num real chunks",2); const El::Int numImag = El::Input("--numImag","num imag chunks",2); const El::Int realSize = El::Input("--realSize","number of x samples",100); const El::Int imagSize = El::Input("--imagSize","number of y samples",100); const bool arnoldi = El::Input("--arnoldi","use Arnoldi?",true); const El::Int basisSize = El::Input("--basisSize","num basis vectors",10); const El::Int maxIts = El::Input("--maxIts","maximum pseudospec iter's",200); const double psTol = El::Input("--psTol","tolerance for pseudospectra",1e-6); // Uniform options const double uniformRealCenter = El::Input("--uniformRealCenter","real center of uniform dist",0.); const double uniformImagCenter = El::Input("--uniformImagCenter","imag center of uniform dist",0.); const double uniformRadius = El::Input("--uniformRadius","radius of uniform dist",1.); // Grcar options const El::Int numBands = El::Input("--numBands","num bands for Grcar",3); // Fox-Li options const double omega = El::Input("--omega","frequency for Fox-Li/Helm",16*M_PI); // Helmholtz-PML options [also uses omega from Fox-Li] const El::Int mx = El::Input("--mx","number of x points for HelmholtzPML",30); const El::Int my = El::Input("--my","number of y points for HelmholtzPML",30); const El::Int numPmlPoints = El::Input("--numPml","num PML points for Helm",5); const double sigma = El::Input("--sigma","PML amplitude",1.5); const double pmlExp = El::Input("--pmlExp","PML takeoff exponent",3.); // Uniform Helmholtz Green's options const double lambda = El::Input("--lambda","wavelength of U.H.Green's",0.1); // Hatano-Nelson options const double gHatano = El::Input("--gHatano","g in Hatano-Nelson",0.5); const bool periodic = El::Input("--periodic","periodic HatanoNelson?",true); // Input/Output options const bool progress = El::Input("--progress","print progress?",true); const bool deflate = El::Input("--deflate","deflate?",true); const bool display = El::Input("--display","display matrices?",false); const bool write = El::Input("--write","write matrices?",false); const bool saveSchur = El::Input("--saveSchur","save Schur factor?",true); const El::Int numSaveFreq = El::Input("--numSaveFreq","numerical save frequency",-1); const El::Int imgSaveFreq = El::Input("--imgSaveFreq","image save frequency",-1); const El::Int imgDispFreq = El::Input("--imgDispFreq","image display frequency",-1); const std::string numBase = El::Input("--numBase","numerical save basename",std::string("num")); const std::string imgBase = El::Input("--imgBase","image save basename",std::string("img")); const El::Int numFormatInt = El::Input("--numFormat","numerical format",2); const El::Int imgFormatInt = El::Input("--imgFormat","image format",8); const El::Int colorMapInt = El::Input("--colorMap","color map",0); const bool itCounts = El::Input("--itCounts","display iter. counts?",true); El::ProcessInput(); El::PrintInputReport(); El::mpi::Comm comm = El::mpi::COMM_WORLD; if( gridHeight == 0 ) gridHeight = El::Grid::DefaultHeight( El::mpi::Size(comm) ); const El::GridOrder order = colMajor ? El::COLUMN_MAJOR : El::ROW_MAJOR; const El::Grid grid( comm, gridHeight, order ); El::SetBlocksize( nbAlg ); if( normInt < 0 || normInt > 1 ) El::LogicError("Invalid pseudospec norm type"); if( numFormatInt < 1 || numFormatInt >= El::FileFormat_MAX ) El::LogicError ("Invalid numerical format integer, should be in [1,", El::FileFormat_MAX,")"); if( imgFormatInt < 1 || imgFormatInt >= El::FileFormat_MAX ) El::LogicError ("Invalid image format integer, should be in [1,", El::FileFormat_MAX,")"); const auto psNorm = static_cast<El::PseudospecNorm>(normInt); const auto numFormat = static_cast<El::FileFormat>(numFormatInt); const auto imgFormat = static_cast<El::FileFormat>(imgFormatInt); const auto colorMap = static_cast<El::ColorMap>(colorMapInt); El::SetColorMap( colorMap ); const El::Complex<double> center(realCenter,imagCenter), uniformCenter(uniformRealCenter,uniformImagCenter); bool isReal = true; std::string matName; El::DistMatrix<double> AReal(grid); El::DistMatrix<El::Complex<double>> ACpx(grid); switch( matType ) { case 0: matName="uniform"; El::Uniform( ACpx, n, n, uniformCenter, uniformRadius ); isReal = false; break; case 1: matName="Haar"; El::Haar( ACpx, n ); isReal = false; break; case 2: matName="Lotkin"; El::Lotkin( AReal, n ); isReal = true; break; case 3: matName="Grcar"; El::Grcar( AReal, n, numBands ); isReal = true; break; case 4: matName="FoxLi"; El::FoxLi( ACpx, n, omega ); isReal = false; break; case 5: matName="HelmholtzPML"; El::HelmholtzPML ( ACpx, n, El::Complex<double>(omega), numPmlPoints, sigma, pmlExp ); isReal = false; break; case 6: matName="HelmholtzPML2D"; El::HelmholtzPML ( ACpx, mx, my, El::Complex<double>(omega), numPmlPoints, sigma, pmlExp ); isReal = false; break; case 7: matName="TrefethenEmbree"; El::TrefethenEmbree( ACpx, n ); isReal = false; break; case 8: matName="BullsHead"; El::BullsHead( ACpx, n ); isReal = false; break; case 9: matName="Triangle"; El::Triangle( AReal, n ); isReal = true; break; case 10: matName="Whale"; El::Whale( ACpx, n ); isReal = false; break; case 11: matName="UniformHelmholtzGreens"; El::UniformHelmholtzGreens( ACpx, n, lambda ); isReal = false; break; case 12: matName="HatanoNelson"; El::HatanoNelson ( AReal, n, realCenter, uniformRadius, gHatano, periodic ); isReal = true; break; case 13: matName="EhrenfestDecay"; // Force the complex matrix to allow for one-norm pseudospectra El::EhrenfestDecay( ACpx, n ); isReal = false; break; case 14: matName="RiffleDecay"; // Force the complex matrix to allow for one-norm pseudospectra El::RiffleDecay( ACpx, n ); isReal = false; break; case 15: matName="Jordan"; El::Jordan( AReal, n, 0. ); isReal = true; break; default: El::LogicError("Invalid matrix type"); } if( display ) { if( isReal ) El::Display( AReal, "A" ); else El::Display( ACpx, "A" ); } if( write ) { if( isReal ) { El::Write( AReal, "A", numFormat ); El::Write( AReal, "A", imgFormat ); } else { El::Write( ACpx, "A", numFormat ); El::Write( ACpx, "A", imgFormat ); } } // Begin by computing the Schur decomposition El::Timer timer; El::DistMatrix<El::Complex<double>> w(grid); El::mpi::Barrier( comm ); const bool formATR = true; El::DistMatrix<double> QReal(grid); El::DistMatrix<El::Complex<double>> QCpx(grid); El::SchurCtrl<double> ctrl; ctrl.hessSchurCtrl.fullTriangle = formATR; ctrl.hessSchurCtrl.blockHeight = nbDist; ctrl.hessSchurCtrl.scalapack = false; ctrl.useSDC = sdc; // Spectral D&C options (only relevant if 'sdc' is true) ctrl.sdcCtrl.cutoff = cutoff; ctrl.sdcCtrl.maxInnerIts = maxInnerIts; ctrl.sdcCtrl.maxOuterIts = maxOuterIts; ctrl.sdcCtrl.tol = sdcTol; ctrl.sdcCtrl.spreadFactor = spreadFactor; ctrl.sdcCtrl.random = random; ctrl.sdcCtrl.progress = progress; ctrl.sdcCtrl.signCtrl.tol = signTol; ctrl.sdcCtrl.signCtrl.progress = progress; timer.Start(); if( isReal ) { if( psNorm == El::PS_TWO_NORM ) El::Schur( AReal, w, ctrl ); else El::Schur( AReal, w, QReal, ctrl ); } else { if( psNorm == El::PS_TWO_NORM ) El::Schur( ACpx, w, ctrl ); else El::Schur( ACpx, w, QCpx, ctrl ); } El::mpi::Barrier( comm ); const double schurTime = timer.Stop(); if( El::mpi::Rank(comm) == 0 ) El::Output("Schur decomposition took ",schurTime," seconds"); if( saveSchur ) { if( El::mpi::Rank(comm) == 0 ) El::Output("Writing Schur decomposition to file..."); timer.Start(); if( isReal ) { auto schurTitle = El::BuildString (matName,"_",AReal.ColStride(),"x",AReal.RowStride(), "_",AReal.DistRank()); El::Write( AReal.LockedMatrix(), schurTitle, El::BINARY ); if( psNorm == El::PS_ONE_NORM ) { auto QTitle = El::BuildString (matName,"_Q_",QReal.ColStride(),"x",QReal.RowStride(), "_",QReal.DistRank()); El::Write( QReal.LockedMatrix(), QTitle, El::BINARY ); } } else { auto schurTitle = El::BuildString (matName,"_",ACpx.ColStride(),"x",ACpx.RowStride(), "_",ACpx.DistRank()); El::Write( ACpx.LockedMatrix(), schurTitle, El::BINARY ); if( psNorm == El::PS_ONE_NORM ) { auto QTitle = El::BuildString (matName,"_Q_",QCpx.ColStride(),"x",QCpx.RowStride(), "_",QCpx.DistRank()); El::Write( QCpx.LockedMatrix(), QTitle, El::BINARY ); } } El::mpi::Barrier( comm ); const double saveSchurTime = timer.Stop(); if( El::mpi::Rank(comm) == 0 ) El::Output("Saving took ",saveSchurTime," seconds"); } // Find a window if none is specified if( realWidth == 0. || imagWidth == 0. ) { const double radius = El::MaxNorm( w ); const double oneNorm = isReal ? El::OneNorm(AReal) : El::OneNorm(ACpx); double width; if( oneNorm == 0. && radius == 0. ) { width = 1; if( El::mpi::Rank(comm) == 0 ) El::Output("Setting width to 1 to handle zero matrix"); } else if( radius >= 0.2*oneNorm ) { width = 2.5*radius; if( El::mpi::Rank(comm) == 0 ) El::Output ("Setting width to ",width, " based on the spectral radius, ",radius); } else { width = 0.8*oneNorm; if( El::mpi::Rank(comm) == 0 ) El::Output ("Setting width to ",width," based on the one norm, ", oneNorm); } realWidth = width; imagWidth = width; } El::PseudospecCtrl<double> psCtrl; psCtrl.norm = psNorm; psCtrl.schur = true; psCtrl.maxIts = maxIts; psCtrl.tol = psTol; psCtrl.deflate = deflate; psCtrl.arnoldi = arnoldi; psCtrl.basisSize = basisSize; psCtrl.progress = progress; psCtrl.snapCtrl.imgSaveFreq = imgSaveFreq; psCtrl.snapCtrl.numSaveFreq = numSaveFreq; psCtrl.snapCtrl.imgDispFreq = imgDispFreq; psCtrl.snapCtrl.imgFormat = imgFormat; psCtrl.snapCtrl.numFormat = numFormat; psCtrl.snapCtrl.itCounts = itCounts; // Visualize/write the pseudospectra within each window El::DistMatrix<double> invNormMap(grid); El::DistMatrix<El::Int> itCountMap(grid); const El::Int xBlock = realSize / numReal; const El::Int yBlock = imagSize / numImag; const El::Int xLeftover = realSize - (numReal-1)*xBlock; const El::Int yLeftover = imagSize - (numImag-1)*yBlock; const double realStep = realWidth/realSize; const double imagStep = imagWidth/imagSize; const El::Complex<double> corner = center - El::Complex<double>(realWidth/2,imagWidth/2); for( El::Int realChunk=0; realChunk<numReal; ++realChunk ) { const El::Int realChunkSize = ( realChunk==numReal-1 ? xLeftover : xBlock ); const double realChunkWidth = realStep*realChunkSize; for( El::Int imagChunk=0; imagChunk<numImag; ++imagChunk ) { auto chunkTag = El::BuildString("_",realChunk,"_",imagChunk); const El::Int imagChunkSize = ( imagChunk==numImag-1 ? yLeftover : yBlock ); const double imagChunkWidth = imagStep*imagChunkSize; const El::Complex<double> chunkCorner = corner + El::Complex<double> (realStep*realChunk*xBlock,imagStep*imagChunk*yBlock); const El::Complex<double> chunkCenter = chunkCorner + El::Complex<double> (realStep*realChunkSize,imagStep*imagChunkSize)/2.; if( El::mpi::Rank(comm) == 0 ) El::Output ("Starting computation for chunk centered at ",chunkCenter); El::mpi::Barrier( comm ); timer.Start(); psCtrl.snapCtrl.numBase = matName+"_"+numBase+chunkTag; psCtrl.snapCtrl.imgBase = matName+"_"+imgBase+chunkTag; if( isReal ) { itCountMap = El::QuasiTriangularSpectralWindow ( AReal, QReal, invNormMap, chunkCenter, realChunkWidth, imagChunkWidth, realChunkSize, imagChunkSize, psCtrl ); } else { itCountMap = El::TriangularSpectralWindow ( ACpx, QCpx, invNormMap, chunkCenter, realChunkWidth, imagChunkWidth, realChunkSize, imagChunkSize, psCtrl ); } El::mpi::Barrier( comm ); const double pseudoTime = timer.Stop(); const El::Int numIts = MaxNorm( itCountMap ); if( El::mpi::Rank() == 0 ) El::Output ("num seconds=",pseudoTime,"\n", "num iterations=",numIts); } } } catch( std::exception& e ) { El::ReportException(e); } return 0; }
This file is part of Elemental and is under the BSD 2-Clause License, which can be found in the LICENSE file in the root directory, or at http://opensource.org/licenses/BSD-2-Clause */ #include "El.hpp" namespace El { template<typename F> Base<F> MaxCondition( const Matrix<F>& A ) { DEBUG_ONLY(CSE cse("MaxCondition")) typedef Base<F> Real; Matrix<F> B( A ); const Real maxNorm = MaxNorm( B ); try { Inverse( B ); } catch( SingularMatrixException& e ) { return std::numeric_limits<Real>::infinity(); } const Real maxNormInv = MaxNorm( B ); return maxNorm*maxNormInv; } template<typename F> Base<F> MaxCondition( const ElementalMatrix<F>& A ) { DEBUG_ONLY(CSE cse("MaxCondition")) typedef Base<F> Real; DistMatrix<F> B( A ); const Real maxNorm = MaxNorm( B ); try { Inverse( B ); }
inline void ADMM ( const AbstractDistMatrix<F>& MPre, AbstractDistMatrix<F>& LPre, AbstractDistMatrix<F>& SPre, const RPCACtrl<Base<F>>& ctrl ) { auto MPtr = ReadProxy<F,MC,MR>( &MPre ); auto& M = *MPtr; auto LPtr = WriteProxy<F,MC,MR>( &LPre ); auto& L = *LPtr; auto SPtr = WriteProxy<F,MC,MR>( &SPre ); auto& S = *SPtr; typedef Base<F> Real; const Int m = M.Height(); const Int n = M.Width(); const Int commRank = mpi::Rank( M.Grid().Comm() ); // If tau is not specified, then set it to 1/sqrt(max(m,n)) const Base<F> tau = ( ctrl.tau <= Real(0) ? Real(1)/sqrt(Real(Max(m,n))) : ctrl.tau ); if( ctrl.beta <= Real(0) ) LogicError("beta cannot be non-positive"); if( ctrl.tol <= Real(0) ) LogicError("tol cannot be non-positive"); const Base<F> beta = ctrl.beta; const Base<F> tol = ctrl.tol; const double startTime = mpi::Time(); DistMatrix<F> E( M.Grid() ), Y( M.Grid() ); Zeros( Y, m, n ); const Real frobM = FrobeniusNorm( M ); const Real maxM = MaxNorm( M ); if( ctrl.progress && commRank == 0 ) cout << "|| M ||_F = " << frobM << "\n" << "|| M ||_max = " << maxM << endl; Zeros( L, m, n ); Zeros( S, m, n ); Int numIts = 0; while( true ) { ++numIts; // ST_{tau/beta}(M - L + Y/beta) S = M; Axpy( F(-1), L, S ); Axpy( F(1)/beta, Y, S ); SoftThreshold( S, tau/beta ); const Int numNonzeros = ZeroNorm( S ); // SVT_{1/beta}(M - S + Y/beta) L = M; Axpy( F(-1), S, L ); Axpy( F(1)/beta, Y, L ); Int rank; if( ctrl.usePivQR ) rank = SVT( L, Real(1)/beta, ctrl.numPivSteps ); else rank = SVT( L, Real(1)/beta ); // E := M - (L + S) E = M; Axpy( F(-1), L, E ); Axpy( F(-1), S, E ); const Real frobE = FrobeniusNorm( E ); if( frobE/frobM <= tol ) { if( ctrl.progress && commRank == 0 ) cout << "Converged after " << numIts << " iterations " << " with rank=" << rank << ", numNonzeros=" << numNonzeros << " and " << "|| E ||_F / || M ||_F = " << frobE/frobM << ", and " << mpi::Time()-startTime << " total secs" << endl; break; } else if( numIts >= ctrl.maxIts ) { if( ctrl.progress && commRank == 0 ) cout << "Aborting after " << numIts << " iterations and " << mpi::Time()-startTime << " total secs" << endl; break; } else { if( ctrl.progress && commRank == 0 ) cout << numIts << ": || E ||_F / || M ||_F = " << frobE/frobM << ", rank=" << rank << ", numNonzeros=" << numNonzeros << ", " << mpi::Time()-startTime << " total secs" << endl; } // Y := Y + beta E Axpy( beta, E, Y ); } }
inline void ALM ( const ElementalMatrix<F>& MPre, ElementalMatrix<F>& LPre, ElementalMatrix<F>& SPre, const RPCACtrl<Base<F>>& ctrl ) { DistMatrixReadProxy<F,F,MC,MR> MProx( MPre ); DistMatrixWriteProxy<F,F,MC,MR> LProx( LPre ), SProx( SPre ); auto& M = MProx.GetLocked(); auto& L = LProx.Get(); auto& S = SProx.Get(); typedef Base<F> Real; const Int m = M.Height(); const Int n = M.Width(); const int commRank = mpi::Rank( M.Grid().Comm() ); // If tau is unspecified, set it to 1/sqrt(max(m,n)) const Base<F> tau = ( ctrl.tau <= Real(0) ? Real(1) / sqrt(Real(Max(m,n))) : ctrl.tau ); if( ctrl.tol <= Real(0) ) LogicError("tol cannot be non-positive"); const Base<F> tol = ctrl.tol; const double startTime = mpi::Time(); DistMatrix<F> Y( M ); NormalizeEntries( Y ); const Real twoNorm = TwoNorm( Y ); const Real maxNorm = MaxNorm( Y ); const Real infNorm = maxNorm / tau; const Real dualNorm = Max( twoNorm, infNorm ); Y *= F(1)/dualNorm; // If beta is unspecified, set it to 1 / 2 || sign(M) ||_2 Base<F> beta = ( ctrl.beta <= Real(0) ? Real(1) / (2*twoNorm) : ctrl.beta ); const Real frobM = FrobeniusNorm( M ); const Real maxM = MaxNorm( M ); if( ctrl.progress && commRank == 0 ) cout << "|| M ||_F = " << frobM << "\n" << "|| M ||_max = " << maxM << endl; Zeros( L, m, n ); Zeros( S, m, n ); Int numIts=0, numPrimalIts=0; DistMatrix<F> LLast( M.Grid() ), SLast( M.Grid() ), E( M.Grid() ); while( true ) { ++numIts; Int rank, numNonzeros; while( true ) { ++numPrimalIts; LLast = L; SLast = S; // ST_{tau/beta}(M - L + Y/beta) S = M; S -= L; Axpy( F(1)/beta, Y, S ); SoftThreshold( S, tau/beta ); numNonzeros = ZeroNorm( S ); // SVT_{1/beta}(M - S + Y/beta) L = M; L -= S; Axpy( F(1)/beta, Y, L ); if( ctrl.usePivQR ) rank = SVT( L, Real(1)/beta, ctrl.numPivSteps ); else rank = SVT( L, Real(1)/beta ); LLast -= L; SLast -= S; const Real frobLDiff = FrobeniusNorm( LLast ); const Real frobSDiff = FrobeniusNorm( SLast ); if( frobLDiff/frobM < tol && frobSDiff/frobM < tol ) { if( ctrl.progress && commRank == 0 ) cout << "Primal loop converged: " << mpi::Time()-startTime << " total secs" << endl; break; } else { if( ctrl.progress && commRank == 0 ) cout << " " << numPrimalIts << ": \n" << " || Delta L ||_F / || M ||_F = " << frobLDiff/frobM << "\n" << " || Delta S ||_F / || M ||_F = " << frobSDiff/frobM << "\n" << " rank=" << rank << ", numNonzeros=" << numNonzeros << ", " << mpi::Time()-startTime << " total secs" << endl; } } // E := M - (L + S) E = M; E -= L; E -= S; const Real frobE = FrobeniusNorm( E ); if( frobE/frobM <= tol ) { if( ctrl.progress && commRank == 0 ) cout << "Converged after " << numIts << " iterations and " << numPrimalIts << " primal iterations with rank=" << rank << ", numNonzeros=" << numNonzeros << " and " << "|| E ||_F / || M ||_F = " << frobE/frobM << ", " << mpi::Time()-startTime << " total secs" << endl; break; } else if( numIts >= ctrl.maxIts ) { if( ctrl.progress && commRank == 0 ) cout << "Aborting after " << numIts << " iterations and " << mpi::Time()-startTime << " total secs" << endl; break; } else { if( ctrl.progress && commRank == 0 ) cout << numPrimalIts << ": || E ||_F / || M ||_F = " << frobE/frobM << ", rank=" << rank << ", numNonzeros=" << numNonzeros << ", " << mpi::Time()-startTime << " total secs" << endl; } // Y := Y + beta E Axpy( beta, E, Y ); beta *= ctrl.rho; } }
inline void ADMM ( const Matrix<F>& M, Matrix<F>& L, Matrix<F>& S, const RPCACtrl<Base<F>>& ctrl ) { typedef Base<F> Real; const Int m = M.Height(); const Int n = M.Width(); // If tau is not specified, then set it to 1/sqrt(max(m,n)) const Base<F> tau = ( ctrl.tau <= Real(0) ? Real(1)/sqrt(Real(Max(m,n))) : ctrl.tau ); if( ctrl.beta <= Real(0) ) LogicError("beta cannot be non-positive"); if( ctrl.tol <= Real(0) ) LogicError("tol cannot be non-positive"); const Base<F> beta = ctrl.beta; const Base<F> tol = ctrl.tol; const double startTime = mpi::Time(); Matrix<F> E, Y; Zeros( Y, m, n ); const Real frobM = FrobeniusNorm( M ); const Real maxM = MaxNorm( M ); if( ctrl.progress ) cout << "|| M ||_F = " << frobM << "\n" << "|| M ||_max = " << maxM << endl; Zeros( L, m, n ); Zeros( S, m, n ); Int numIts = 0; while( true ) { ++numIts; // ST_{tau/beta}(M - L + Y/beta) S = M; S -= L; Axpy( F(1)/beta, Y, S ); SoftThreshold( S, tau/beta ); const Int numNonzeros = ZeroNorm( S ); // SVT_{1/beta}(M - S + Y/beta) L = M; L -= S; Axpy( F(1)/beta, Y, L ); Int rank; if( ctrl.usePivQR ) rank = SVT( L, Real(1)/beta, ctrl.numPivSteps ); else rank = SVT( L, Real(1)/beta ); // E := M - (L + S) E = M; E -= L; E -= S; const Real frobE = FrobeniusNorm( E ); if( frobE/frobM <= tol ) { if( ctrl.progress ) cout << "Converged after " << numIts << " iterations " << " with rank=" << rank << ", numNonzeros=" << numNonzeros << " and " << "|| E ||_F / || M ||_F = " << frobE/frobM << ", and " << mpi::Time()-startTime << " total secs" << endl; break; } else if( numIts >= ctrl.maxIts ) { if( ctrl.progress ) cout << "Aborting after " << numIts << " iterations and " << mpi::Time()-startTime << " total secs" << endl; break; } else { if( ctrl.progress ) cout << numIts << ": || E ||_F / || M ||_F = " << frobE/frobM << ", rank=" << rank << ", numNonzeros=" << numNonzeros << ", " << mpi::Time()-startTime << " total secs" << endl; } // Y := Y + beta E Axpy( beta, E, Y ); } }