void HermitianPseudoinverse ( UpperOrLower uplo, AbstractDistMatrix<Field>& APre, Base<Field> tolerance ) { EL_DEBUG_CSE typedef Base<Field> Real; DistMatrixReadWriteProxy<Field,Field,MC,MR> AProx( APre ); auto& A = AProx.Get(); const Grid& g = A.Grid(); // Get the EVD of A // TODO(poulson): Use a relative eigenvalue lower-bound DistMatrix<Real,VR,STAR> w(g); DistMatrix<Field> 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 = [=]( const Real& omega ) { return ( omega < tolerance ? Real(0) : 1/omega ); }; EntrywiseMap( w, MakeFunction(omegaMap) ); // Form the pseudoinverse HermitianFromEVD( uplo, A, w, Z ); }
void HingeLossProx( AbstractDistMatrix<Real>& A, Real tau ) { DEBUG_CSE auto hingeProx = [=]( Real alpha ) -> Real { if( alpha < 1 ) { return Min(alpha+1/tau,Real(1)); } else { return alpha; } }; EntrywiseMap( A, function<Real(Real)>(hingeProx) ); }
inline void FinalSnapshot ( const Matrix<Real>& estimates, const Matrix<Int>& itCounts, SnapshotCtrl& snapCtrl ) { DEBUG_ONLY(CSE cse("pspec::FinalSnapshot")); auto logMap = []( Real alpha ) { return Log(alpha); }; if( snapCtrl.realSize != 0 && snapCtrl.imagSize != 0 ) { const bool numSave = ( snapCtrl.numSaveFreq >= 0 ); const bool imgSave = ( snapCtrl.imgSaveFreq >= 0 ); const bool imgDisp = ( snapCtrl.imgDispFreq >= 0 ); Matrix<Real> estMap; Matrix<Int> itCountMap; if( numSave || imgSave || imgDisp ) { ReshapeIntoGrid ( snapCtrl.realSize, snapCtrl.imagSize, estimates, estMap ); if( snapCtrl.itCounts ) ReshapeIntoGrid ( snapCtrl.realSize, snapCtrl.imagSize, itCounts, itCountMap ); } if( numSave ) { string base = snapCtrl.numBase; Write( estMap, base, snapCtrl.numFormat ); if( snapCtrl.itCounts ) Write( itCountMap, base+"_counts", snapCtrl.numFormat ); } if( imgSave || imgDisp ) EntrywiseMap( estMap, function<Real(Real)>(logMap) ); if( imgSave ) { string base = snapCtrl.imgBase; Write( estMap, base, snapCtrl.imgFormat ); if( snapCtrl.itCounts ) Write( itCountMap, base+"_counts", snapCtrl.imgFormat ); auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Write( estMap, base+"_discrete", snapCtrl.imgFormat ); SetColorMap( colorMap ); } if( imgDisp ) { string base = snapCtrl.imgBase; Display( estMap, base ); if( snapCtrl.itCounts ) Display( itCountMap, base+"_counts" ); auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Display( estMap, base+"_discrete" ); SetColorMap( colorMap ); } } }
void EntrywiseMap ( const DistMultiVec<S>& A, DistMultiVec<T>& B, function<T(S)> func ) { DEBUG_CSE B.SetComm( A.Comm() ); B.Resize( A.Height(), A.Width() ); EntrywiseMap( A.LockedMatrix(), B.Matrix(), func ); }
void PanelHouseholder ( Matrix<F>& A, Matrix<F>& householderScalars, Matrix<Base<F>>& signature ) { DEBUG_CSE typedef Base<F> Real; const Int m = A.Height(); const Int n = A.Width(); const Int minDim = Min(m,n); householderScalars.Resize( minDim, 1 ); signature.Resize( minDim, 1 ); Matrix<F> z21; for( Int k=0; k<minDim; ++k ) { const Range<Int> ind1( k ), ind2( k+1, END ), indR( k, n ); F& alpha11 = A(k,k); auto a12 = A( ind1, ind2 ); auto a1R = A( ind1, indR ); auto A2R = A( ind2, indR ); // Find tau and v such that // |alpha11 a12| /I - tau |1 | |1 conj(v)|\ = |beta 0| // \ |v^T| / const F tau = RightReflector( alpha11, a12 ); householderScalars(k) = tau; // Temporarily set a1R = | 1 v | const F alpha = alpha11; alpha11 = 1; // A2R := A2R Hous(a1R^T,tau) // = A2R (I - tau a1R^T conj(a1R)) // = A2R - tau (A2R a1R^T) conj(a1R) Zeros( z21, A2R.Height(), 1 ); Gemv( NORMAL, F(1), A2R, a1R, F(0), z21 ); Ger( -tau, z21, a1R, A2R ); // Reset alpha11's value alpha11 = alpha; } // Form d and rescale L auto L = A( ALL, IR(0,minDim) ); GetRealPartOfDiagonal(L,signature); auto sgn = []( const Real& delta ) { return delta >= Real(0) ? Real(1) : Real(-1); }; EntrywiseMap( signature, function<Real(Real)>(sgn) ); DiagonalScaleTrapezoid( RIGHT, LOWER, NORMAL, signature, L ); }
void FinalSnapshot ( const DistMatrix<Real,VR,STAR>& estimates, const DistMatrix<Int, VR,STAR>& itCounts, SnapshotCtrl& snapCtrl ) { EL_DEBUG_CSE auto logMap = []( const Real& alpha ) { return Log(alpha); }; if( snapCtrl.realSize != 0 && snapCtrl.imagSize != 0 ) { const bool numSave = ( snapCtrl.numSaveFreq >= 0 ); const bool imgSave = ( snapCtrl.imgSaveFreq >= 0 ); const bool imgDisp = ( snapCtrl.imgDispFreq >= 0 ); DistMatrix<Real> estMap(estimates.Grid()); DistMatrix<Int> itCountMap(itCounts.Grid()); if( numSave || imgSave || imgDisp ) { ReshapeIntoGrid ( snapCtrl.realSize, snapCtrl.imagSize, estimates, estMap ); if( snapCtrl.itCounts ) ReshapeIntoGrid ( snapCtrl.realSize, snapCtrl.imagSize, itCounts, itCountMap ); } if( numSave ) { string base = snapCtrl.numBase; Write( estMap, base, snapCtrl.numFormat ); if( snapCtrl.itCounts ) Write( itCountMap, base+"_counts", snapCtrl.numFormat ); } if( imgSave || imgDisp ) EntrywiseMap( estMap, MakeFunction(logMap) ); if( imgSave ) { string base = snapCtrl.imgBase; Write( estMap, base, snapCtrl.imgFormat ); if( snapCtrl.itCounts ) Write( itCountMap, base+"_counts", snapCtrl.imgFormat ); auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Write( estMap, base+"_discrete", snapCtrl.imgFormat ); SetColorMap( colorMap ); } if( imgDisp ) { string base = snapCtrl.imgBase; Display( estMap, base ); if( snapCtrl.itCounts ) Display( itCountMap, base+"_counts" ); auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Display( estMap, base+"_discrete" ); SetColorMap( colorMap ); } } }
void RuizEquil ( DistSparseMatrix<Field>& A, DistMultiVec<Base<Field>>& dRow, DistMultiVec<Base<Field>>& dCol, bool progress ) { EL_DEBUG_CSE typedef Base<Field> Real; const Int m = A.Height(); const Int n = A.Width(); mpi::Comm comm = A.Comm(); dRow.SetComm( comm ); dCol.SetComm( comm ); Ones( dRow, m, 1 ); Ones( dCol, n, 1 ); // TODO(poulson): Expose to control structure // For, simply hard-code a small number of iterations const Int maxIter = 4; DistMultiVec<Real> scales(comm); const Int indent = PushIndent(); for( Int iter=0; iter<maxIter; ++iter ) { // Rescale the columns // ------------------- ColumnMaxNorms( A, scales ); EntrywiseMap( scales, MakeFunction(DampScaling<Real>) ); DiagonalScale( LEFT, NORMAL, scales, dCol ); DiagonalSolve( RIGHT, NORMAL, scales, A ); // Rescale the rows // ---------------- RowMaxNorms( A, scales ); EntrywiseMap( scales, MakeFunction(DampScaling<Real>) ); DiagonalScale( LEFT, NORMAL, scales, dRow ); DiagonalSolve( LEFT, NORMAL, scales, A ); } SetIndent( indent ); }
void SymmetricRuizEquil ( ElementalMatrix<F>& APre, ElementalMatrix<Base<F>>& dPre, Int maxIter, bool progress ) { DEBUG_CSE typedef Base<F> Real; ElementalProxyCtrl control; control.colConstrain = true; control.rowConstrain = true; control.colAlign = 0; control.rowAlign = 0; DistMatrixReadWriteProxy<F,F,MC,MR> AProx( APre, control ); DistMatrixWriteProxy<Real,Real,MC,STAR> dProx( dPre, control ); auto& A = AProx.Get(); auto& d = dProx.Get(); const Int n = A.Height(); Ones( d, n, 1 ); DistMatrix<Real,MR,STAR> scales(A.Grid()); const Int indent = PushIndent(); for( Int iter=0; iter<maxIter; ++iter ) { // Rescale the columns (and rows) // ------------------------------ ColumnMaxNorms( A, scales ); EntrywiseMap( scales, function<Real(Real)>(DampScaling<Real>) ); EntrywiseMap( scales, function<Real(Real)>(SquareRootScaling<Real>) ); DiagonalScale( LEFT, NORMAL, scales, d ); // TODO: Replace with SymmetricDiagonalSolve DiagonalSolve( RIGHT, NORMAL, scales, A ); DiagonalSolve( LEFT, NORMAL, scales, A ); } SetIndent( indent ); }
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 }
void RuizEquil ( Matrix<Field>& A, Matrix<Base<Field>>& dRow, Matrix<Base<Field>>& dCol, bool progress ) { EL_DEBUG_CSE typedef Base<Field> Real; const Int m = A.Height(); const Int n = A.Width(); Ones( dRow, m, 1 ); Ones( dCol, n, 1 ); // TODO(poulson): Expose these as control parameters // For now, simply hard-code the number of iterations const Int maxIter = 4; Matrix<Real> rowScale, colScale; const Int indent = PushIndent(); for( Int iter=0; iter<maxIter; ++iter ) { // Rescale the columns // ------------------- ColumnMaxNorms( A, colScale ); EntrywiseMap( colScale, MakeFunction(DampScaling<Real>) ); DiagonalScale( LEFT, NORMAL, colScale, dCol ); DiagonalSolve( RIGHT, NORMAL, colScale, A ); // Rescale the rows // ---------------- RowMaxNorms( A, rowScale ); EntrywiseMap( rowScale, MakeFunction(DampScaling<Real>) ); DiagonalScale( LEFT, NORMAL, rowScale, dRow ); DiagonalSolve( LEFT, NORMAL, rowScale, A ); } SetIndent( indent ); }
void SymmetricRuizEquil ( SparseMatrix<F>& A, Matrix<Base<F>>& d, Int maxIter, bool progress ) { DEBUG_CSE typedef Base<F> Real; const Int n = A.Height(); Ones( d, n, 1 ); Matrix<Real> scales; const Int indent = PushIndent(); for( Int iter=0; iter<maxIter; ++iter ) { // Rescale the columns (and rows) // ------------------------------ ColumnMaxNorms( A, scales ); EntrywiseMap( scales, function<Real(Real)>(DampScaling<Real>) ); EntrywiseMap( scales, function<Real(Real)>(SquareRootScaling<Real>) ); DiagonalScale( LEFT, NORMAL, scales, d ); SymmetricDiagonalSolve( scales, A ); } SetIndent( indent ); }
void Inverse ( const Matrix<Real>& x, Matrix<Real>& xInv, const Matrix<Int>& orders, const Matrix<Int>& firstInds ) { DEBUG_CSE Matrix<Real> dInv; soc::Dets( x, dInv, orders, firstInds ); cone::Broadcast( dInv, orders, firstInds ); auto entryInv = [=]( Real alpha ) { return Real(1)/alpha; }; EntrywiseMap( dInv, function<Real(Real)>(entryInv) ); auto Rx = x; soc::Reflect( Rx, orders, firstInds ); Hadamard( dInv, Rx, xInv ); }
void Inverse ( const DistMultiVec<Real>& x, DistMultiVec<Real>& xInv, const DistMultiVec<Int>& orders, const DistMultiVec<Int>& firstInds, Int cutoff ) { DEBUG_CSE DistMultiVec<Real> dInv(x.Comm()); soc::Dets( x, dInv, orders, firstInds, cutoff ); cone::Broadcast( dInv, orders, firstInds ); auto entryInv = [=]( Real alpha ) { return Real(1)/alpha; }; EntrywiseMap( dInv, function<Real(Real)>(entryInv) ); auto Rx = x; soc::Reflect( Rx, orders, firstInds ); Hadamard( dInv, Rx, xInv ); }
void Inverse ( const ElementalMatrix<Real>& xPre, ElementalMatrix<Real>& xInvPre, const ElementalMatrix<Int>& ordersPre, const ElementalMatrix<Int>& firstIndsPre, Int cutoff ) { DEBUG_CSE AssertSameGrids( xPre, xInvPre, ordersPre, firstIndsPre ); ElementalProxyCtrl ctrl; ctrl.colConstrain = true; ctrl.colAlign = 0; DistMatrixReadProxy<Real,Real,VC,STAR> xProx( xPre, ctrl ); DistMatrixWriteProxy<Real,Real,VC,STAR> xInvProx( xInvPre, ctrl ); DistMatrixReadProxy<Int,Int,VC,STAR> ordersProx( ordersPre, ctrl ), firstIndsProx( firstIndsPre, ctrl ); auto& x = xProx.GetLocked(); auto& xInv = xInvProx.Get(); auto& orders = ordersProx.GetLocked(); auto& firstInds = firstIndsProx.GetLocked(); DistMatrix<Real,VC,STAR> dInv(x.Grid()); soc::Dets( x, dInv, orders, firstInds, cutoff ); cone::Broadcast( dInv, orders, firstInds ); auto entryInv = [=]( Real alpha ) { return Real(1)/alpha; }; EntrywiseMap( dInv, function<Real(Real)>(entryInv) ); auto Rx = x; soc::Reflect( Rx, orders, firstInds ); Hadamard( dInv, Rx, xInv ); }
void Ridge ( Orientation orientation, const Matrix<Field>& A, const Matrix<Field>& B, Base<Field> gamma, Matrix<Field>& X, RidgeAlg alg ) { EL_DEBUG_CSE const bool normal = ( orientation==NORMAL ); const Int m = ( normal ? A.Height() : A.Width() ); const Int n = ( normal ? A.Width() : A.Height() ); if( orientation == TRANSPOSE && IsComplex<Field>::value ) LogicError("Transpose version of complex Ridge not yet supported"); if( m >= n ) { Matrix<Field> Z; if( alg == RIDGE_CHOLESKY ) { if( orientation == NORMAL ) Herk( LOWER, ADJOINT, Base<Field>(1), A, Z ); else Herk( LOWER, NORMAL, Base<Field>(1), A, Z ); ShiftDiagonal( Z, Field(gamma*gamma) ); Cholesky( LOWER, Z ); if( orientation == NORMAL ) Gemm( ADJOINT, NORMAL, Field(1), A, B, X ); else Gemm( NORMAL, NORMAL, Field(1), A, B, X ); cholesky::SolveAfter( LOWER, NORMAL, Z, X ); } else if( alg == RIDGE_QR ) { Zeros( Z, m+n, n ); auto ZT = Z( IR(0,m), IR(0,n) ); auto ZB = Z( IR(m,m+n), IR(0,n) ); if( orientation == NORMAL ) ZT = A; else Adjoint( A, ZT ); FillDiagonal( ZB, Field(gamma) ); // NOTE: This QR factorization could exploit the upper-triangular // structure of the diagonal matrix ZB qr::ExplicitTriang( Z ); if( orientation == NORMAL ) Gemm( ADJOINT, NORMAL, Field(1), A, B, X ); else Gemm( NORMAL, NORMAL, Field(1), A, B, X ); cholesky::SolveAfter( LOWER, NORMAL, Z, X ); } else { Matrix<Field> U, V; Matrix<Base<Field>> s; if( orientation == NORMAL ) { SVDCtrl<Base<Field>> ctrl; ctrl.overwrite = false; SVD( A, U, s, V, ctrl ); } else { Matrix<Field> AAdj; Adjoint( A, AAdj ); SVDCtrl<Base<Field>> ctrl; ctrl.overwrite = true; SVD( AAdj, U, s, V, ctrl ); } auto sigmaMap = [=]( const Base<Field>& sigma ) { return sigma / (sigma*sigma + gamma*gamma); }; EntrywiseMap( s, MakeFunction(sigmaMap) ); Gemm( ADJOINT, NORMAL, Field(1), U, B, X ); DiagonalScale( LEFT, NORMAL, s, X ); U = X; Gemm( NORMAL, NORMAL, Field(1), V, U, X ); } } else { LogicError("This case not yet supported"); } }
void Snapshot ( const Matrix<Int>& preimage, const Matrix<Real>& estimates, const Matrix<Int>& itCounts, Int numIts, bool deflate, SnapshotCtrl& snapCtrl ) { EL_DEBUG_CSE auto logMap = []( const Real& alpha ) { return Log(alpha); }; if( snapCtrl.realSize != 0 && snapCtrl.imagSize != 0 ) { const bool numSave = ( snapCtrl.numSaveFreq > 0 && snapCtrl.numSaveCount >= snapCtrl.numSaveFreq ); const bool imgSave = ( snapCtrl.imgSaveFreq > 0 && snapCtrl.imgSaveCount >= snapCtrl.imgSaveFreq ); const bool imgDisp = ( snapCtrl.imgDispFreq > 0 && snapCtrl.imgDispCount >= snapCtrl.imgDispFreq ); Matrix<Real> invNorms, estMap; Matrix<Int> itCountsReord, itCountMap; if( numSave || imgSave || imgDisp ) { invNorms = estimates; if( deflate ) RestoreOrdering( preimage, invNorms ); ReshapeIntoGrid ( snapCtrl.realSize, snapCtrl.imagSize, invNorms, estMap ); if( snapCtrl.itCounts ) { itCountsReord = itCounts; if( deflate ) RestoreOrdering( preimage, itCountsReord ); ReshapeIntoGrid ( snapCtrl.realSize, snapCtrl.imagSize, itCountsReord, itCountMap ); } } if( numSave ) { auto title = BuildString( snapCtrl.numBase, "_", numIts ); Write( estMap, title, snapCtrl.numFormat ); if( snapCtrl.itCounts ) Write( itCountMap, title+"_counts", snapCtrl.numFormat ); snapCtrl.numSaveCount = 0; } if( imgSave || imgDisp ) EntrywiseMap( estMap, MakeFunction(logMap) ); if( imgSave ) { auto title = BuildString( snapCtrl.imgBase, "_", numIts ); Write( estMap, title, snapCtrl.imgFormat ); if( snapCtrl.itCounts ) Write( itCountMap, title+"_counts", snapCtrl.imgFormat ); auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Write( estMap, title+"_discrete", snapCtrl.imgFormat ); SetColorMap( colorMap ); snapCtrl.imgSaveCount = 0; } if( imgDisp ) { auto title = BuildString( snapCtrl.imgBase, "_", numIts ); Display( estMap, title ); if( snapCtrl.itCounts ) Display( itCountMap, title+"_counts" ); auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Display( estMap, title+"_discrete" ); SetColorMap( colorMap ); snapCtrl.imgDispCount = 0; } } }
inline void Snapshot ( const Matrix<Int>& preimage, const Matrix<Real>& estimates, const Matrix<Int>& itCounts, Int numIts, bool deflate, SnapshotCtrl& snapCtrl ) { DEBUG_ONLY(CallStackEntry cse("pspec::Snapshot")); if( snapCtrl.realSize != 0 && snapCtrl.imagSize != 0 ) { const bool numSave = ( snapCtrl.numSaveFreq > 0 && snapCtrl.numSaveCount >= snapCtrl.numSaveFreq ); const bool imgSave = ( snapCtrl.imgSaveFreq > 0 && snapCtrl.imgSaveCount >= snapCtrl.imgSaveFreq ); const bool imgDisp = ( snapCtrl.imgDispFreq > 0 && snapCtrl.imgDispCount >= snapCtrl.imgDispFreq ); Matrix<Real> invNorms, estMap; Matrix<Int> itCountsReord, itCountMap; if( numSave || imgSave || imgDisp ) { invNorms = estimates; if( deflate ) RestoreOrdering( preimage, invNorms ); ReshapeIntoGrid ( snapCtrl.realSize, snapCtrl.imagSize, invNorms, estMap ); if( snapCtrl.itCounts ) { itCountsReord = itCounts; if( deflate ) RestoreOrdering( preimage, itCountsReord ); ReshapeIntoGrid ( snapCtrl.realSize, snapCtrl.imagSize, itCountsReord, itCountMap ); } } if( numSave ) { std::ostringstream os; os << snapCtrl.numBase << "-" << numIts; Write( estMap, os.str(), snapCtrl.numFormat ); if( snapCtrl.itCounts ) Write( itCountMap, os.str()+"-counts", snapCtrl.numFormat ); snapCtrl.numSaveCount = 0; } if( imgSave || imgDisp ) EntrywiseMap( estMap, []( Real alpha ) { return Log(alpha); } ); if( imgSave ) { std::ostringstream os; os << snapCtrl.imgBase << "-" << numIts; Write( estMap, os.str(), snapCtrl.imgFormat ); if( snapCtrl.itCounts ) Write( itCountMap, os.str()+"-counts", snapCtrl.imgFormat ); auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Write( estMap, os.str()+"-discrete", snapCtrl.imgFormat ); SetColorMap( colorMap ); snapCtrl.imgSaveCount = 0; } if( imgDisp ) { std::ostringstream os; os << snapCtrl.imgBase << "-" << numIts; Display( estMap, os.str() ); if( snapCtrl.itCounts ) Display( itCountMap, os.str()+"-counts" ); auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Display( estMap, os.str()+"-discrete" ); SetColorMap( colorMap ); snapCtrl.imgDispCount = 0; } } }
void EntrywiseMap( AbstractDistMatrix<T>& A, function<T(T)> func ) { EntrywiseMap( A.Matrix(), func ); }
void StackedRuizEquil ( AbstractDistMatrix<Field>& APre, AbstractDistMatrix<Field>& BPre, AbstractDistMatrix<Base<Field>>& dRowAPre, AbstractDistMatrix<Base<Field>>& dRowBPre, AbstractDistMatrix<Base<Field>>& dColPre, bool progress ) { EL_DEBUG_CSE typedef Base<Field> Real; ElementalProxyCtrl control; control.colConstrain = true; control.rowConstrain = true; control.colAlign = 0; control.rowAlign = 0; DistMatrixReadWriteProxy<Field,Field,MC,MR> AProx( APre, control ); DistMatrixReadWriteProxy<Field,Field,MC,MR> BProx( BPre, control ); DistMatrixWriteProxy<Real,Real,MC,STAR> dRowAProx( dRowAPre, control ); DistMatrixWriteProxy<Real,Real,MC,STAR> dRowBProx( dRowBPre, control ); DistMatrixWriteProxy<Real,Real,MR,STAR> dColProx( dColPre, control ); auto& A = AProx.Get(); auto& B = BProx.Get(); auto& dRowA = dRowAProx.Get(); auto& dRowB = dRowBProx.Get(); auto& dCol = dColProx.Get(); const Int mA = A.Height(); const Int mB = B.Height(); const Int n = A.Width(); const Int nLocal = A.LocalWidth(); Ones( dRowA, mA, 1 ); Ones( dRowB, mB, 1 ); Ones( dCol, n, 1 ); // TODO(poulson): Expose these as control parameters // For now, simply hard-code the number of iterations const Int maxIter = 4; DistMatrix<Real,MC,STAR> rowScale(A.Grid()); DistMatrix<Real,MR,STAR> colScale(A.Grid()), colScaleB(B.Grid()); auto& colScaleLoc = colScale.Matrix(); auto& colScaleBLoc = colScaleB.Matrix(); const Int indent = PushIndent(); for( Int iter=0; iter<maxIter; ++iter ) { // Rescale the columns // ------------------- ColumnMaxNorms( A, colScale ); ColumnMaxNorms( B, colScaleB ); for( Int jLoc=0; jLoc<nLocal; ++jLoc ) colScaleLoc(jLoc) = Max(colScaleLoc(jLoc),colScaleBLoc(jLoc)); EntrywiseMap( colScale, MakeFunction(DampScaling<Real>) ); DiagonalScale( LEFT, NORMAL, colScale, dCol ); DiagonalSolve( RIGHT, NORMAL, colScale, A ); DiagonalSolve( RIGHT, NORMAL, colScale, B ); // Rescale the rows // ---------------- RowMaxNorms( A, rowScale ); EntrywiseMap( rowScale, MakeFunction(DampScaling<Real>) ); DiagonalScale( LEFT, NORMAL, rowScale, dRowA ); DiagonalSolve( LEFT, NORMAL, rowScale, A ); RowMaxNorms( B, rowScale ); EntrywiseMap( rowScale, MakeFunction(DampScaling<Real>) ); DiagonalScale( LEFT, NORMAL, rowScale, dRowB ); DiagonalSolve( LEFT, NORMAL, rowScale, B ); } SetIndent( indent ); }
void EntrywiseMap( DistMultiVec<T>& A, function<T(T)> func ) { EntrywiseMap( A.Matrix(), func ); }
void ImagPart ( const AbstractDistMatrix<T>& A, AbstractDistMatrix<Base<T>>& AImag ) { auto imagPart = []( const T& alpha ) { return ImagPart(alpha); }; EntrywiseMap( A, AImag, MakeFunction(imagPart) ); }
inline void NormalizeEntries( ElementalMatrix<F>& A ) { auto unitMap = []( F alpha ) { return alpha==F(0) ? F(1) : alpha/Abs(alpha); }; EntrywiseMap( A, function<F(F)>(unitMap) ); }