Ejemplo n.º 1
0
Real ComplementRatio
( const ElementalMatrix<Real>& sPre,
  const ElementalMatrix<Real>& zPre )
{
    DEBUG_CSE

    ElementalProxyCtrl ctrl;
    ctrl.colConstrain = true;
    ctrl.colAlign = 0;

    DistMatrixReadProxy<Real,Real,VC,STAR>
    sProx( sPre, ctrl ),
           zProx( zPre, ctrl );
    auto& s = sProx.GetLocked();
    auto& z = zProx.GetLocked();

    const Int localHeight = s.LocalHeight();
    const Real* sBuf = s.LockedBuffer();
    const Real* zBuf = z.LockedBuffer();

    Real maxLocProd = 0;
    for( Int iLoc=0; iLoc<localHeight; ++iLoc )
        maxLocProd = Max( sBuf[iLoc]*zBuf[iLoc], maxLocProd );
    const Real maxProd = mpi::AllReduce( maxLocProd, mpi::MAX, s.DistComm() );

    Real minLocProd = maxProd;
    for( Int iLoc=0; iLoc<localHeight; ++iLoc )
        minLocProd = Min( sBuf[iLoc]*zBuf[iLoc], minLocProd );
    const Real minProd = mpi::AllReduce( minLocProd, mpi::MIN, s.DistComm() );

    return maxProd/minProd;
}
Ejemplo n.º 2
0
void NesterovTodd
( const ElementalMatrix<Real>& sPre, 
  const ElementalMatrix<Real>& zPre,
        ElementalMatrix<Real>& wPre )
{
    DEBUG_CSE

    ElementalProxyCtrl ctrl;
    ctrl.colConstrain = true;
    ctrl.colAlign = 0;

    DistMatrixReadProxy<Real,Real,VC,STAR>
      sProx( sPre, ctrl ),
      zProx( zPre, ctrl );
    DistMatrixWriteProxy<Real,Real,VC,STAR>
      wProx( wPre, ctrl );
    auto& s = sProx.GetLocked();
    auto& z = zProx.GetLocked();
    auto& w = wProx.Get();

    w.Resize( s.Height(), 1 );
    const Int localHeight = w.LocalHeight();
    const Real* sBuf = s.LockedBuffer();
    const Real* zBuf = z.LockedBuffer();
          Real* wBuf = w.Buffer();

    for( Int iLoc=0; iLoc<localHeight; ++iLoc )
        wBuf[iLoc] = Sqrt(sBuf[iLoc]/zBuf[iLoc]);
}
Ejemplo n.º 3
0
void Apply
( const ElementalMatrix<Real>& xPre, 
  const ElementalMatrix<Real>& yPre,
        ElementalMatrix<Real>& zPre,
  const ElementalMatrix<Int>& ordersPre, 
  const ElementalMatrix<Int>& firstIndsPre,
  Int cutoff )
{
    DEBUG_ONLY(CSE cse("soc::Apply"))
    AssertSameGrids( xPre, yPre, zPre, ordersPre, firstIndsPre );

    ElementalProxyCtrl ctrl;
    ctrl.colConstrain = true;
    ctrl.colAlign = 0;

    DistMatrixReadProxy<Real,Real,VC,STAR>
      xProx( xPre, ctrl ),
      yProx( yPre, ctrl );
    DistMatrixWriteProxy<Real,Real,VC,STAR>
      zProx( zPre, ctrl );
    DistMatrixReadProxy<Int,Int,VC,STAR>
      ordersProx( ordersPre, ctrl ),
      firstIndsProx( firstIndsPre, ctrl );
    auto& x = xProx.GetLocked();
    auto& y = yProx.GetLocked();
    auto& z = zProx.Get();
    auto& orders = ordersProx.GetLocked();
    auto& firstInds = firstIndsProx.GetLocked();

    soc::Dots( x, y, z, orders, firstInds );
    auto xRoots = x;
    auto yRoots = y;
    cone::Broadcast( xRoots, orders, firstInds );
    cone::Broadcast( yRoots, orders, firstInds );

    const Int localHeight = x.LocalHeight();
    const Real* xBuf     = x.LockedBuffer();
    const Real* xRootBuf = xRoots.LockedBuffer();
    const Real* yBuf     = y.LockedBuffer();
    const Real* yRootBuf = yRoots.LockedBuffer();
          Real* zBuf     = z.Buffer();
    const Int* firstIndBuf = firstInds.LockedBuffer();

    for( Int iLoc=0; iLoc<localHeight; ++iLoc )
    {
        const Int i = x.GlobalRow(iLoc);
        const Int firstInd = firstIndBuf[iLoc];
        if( i != firstInd )
            zBuf[iLoc] += xRootBuf[iLoc]*yBuf[iLoc] + yRootBuf[iLoc]*xBuf[iLoc];
    }
}
Ejemplo n.º 4
0
void PushPairInto
(       ElementalMatrix<Real>& sPre, 
        ElementalMatrix<Real>& zPre,
  const ElementalMatrix<Real>& wPre,
  const ElementalMatrix<Int>& ordersPre, 
  const ElementalMatrix<Int>& firstIndsPre,
  Real wMaxNormLimit, Int cutoff )
{
    DEBUG_ONLY(CSE cse("soc::PushPairInto"))
    AssertSameGrids( sPre, zPre, wPre, ordersPre, firstIndsPre );

    ElementalProxyCtrl ctrl;
    ctrl.colConstrain = true;
    ctrl.colAlign = 0;

    DistMatrixReadWriteProxy<Real,Real,VC,STAR>
      sProx( sPre, ctrl ),
      zProx( zPre, ctrl );
    DistMatrixReadProxy<Real,Real,VC,STAR>
      wProx( wPre, ctrl );
    DistMatrixReadProxy<Int,Int,VC,STAR>
      ordersProx( ordersPre, ctrl ),
      firstIndsProx( firstIndsPre, ctrl );
    auto& s = sProx.Get();
    auto& z = zProx.Get();
    auto& w = wProx.GetLocked();
    auto& orders = ordersProx.GetLocked();
    auto& firstInds = firstIndsProx.GetLocked();

    DistMatrix<Real,VC,STAR> sLower(s.Grid()), zLower(z.Grid());
    soc::LowerNorms( s, sLower, orders, firstInds, cutoff );
    soc::LowerNorms( z, zLower, orders, firstInds, cutoff );

    const Int localHeight = s.LocalHeight();
    for( Int iLoc=0; iLoc<localHeight; ++iLoc )
    {
        const Int i = s.GlobalRow(iLoc);
        const Real w0 = w.GetLocal(iLoc,0);
        if( i == firstInds.GetLocal(iLoc,0) && w0 > wMaxNormLimit )
        {
            // TODO: Switch to a non-adhoc modification     
            s.UpdateLocal( iLoc, 0, Real(1)/wMaxNormLimit );
            z.UpdateLocal( iLoc, 0, Real(1)/wMaxNormLimit );
        }
    }
}
Ejemplo n.º 5
0
Int ADMM
( const AbstractDistMatrix<Real>& APre,
  const AbstractDistMatrix<Real>& bPre,
  const AbstractDistMatrix<Real>& cPre,
        AbstractDistMatrix<Real>& zPre,
  const ADMMCtrl<Real>& ctrl )
{
    EL_DEBUG_CSE

    DistMatrixReadProxy<Real,Real,MC,MR>
      AProx( APre ),
      bProx( bPre ),
      cProx( cPre );
    DistMatrixWriteProxy<Real,Real,MC,MR>
      zProx( zPre );
    auto& A = AProx.GetLocked();
    auto& b = bProx.GetLocked();
    auto& c = cProx.GetLocked();
    auto& z = zProx.Get();

    // Cache a custom partially-pivoted LU factorization of
    //    |  rho*I   A^H | = | B11  B12 |
    //    |  A       0   |   | B21  B22 |
    // by (justifiably) avoiding pivoting in the first n steps of
    // the factorization, so that
    //    [I,rho*I] = lu(rho*I).
    // The factorization would then proceed with
    //    B21 := B21 U11^{-1} = A (rho*I)^{-1} = A/rho
    //    B12 := L11^{-1} B12 = I A^H = A^H.
    // The Schur complement would then be
    //    B22 := B22 - B21 B12 = 0 - (A*A^H)/rho.
    // We then factor said matrix with LU with partial pivoting and
    // swap the necessary rows of B21 in order to implicitly commute
    // the row pivots with the Gauss transforms in the manner standard
    // for GEPP. Unless A A' is singular, pivoting should not be needed,
    // as Cholesky factorization of the negative matrix should be valid.
    //
    // The result is the factorization
    //   | I 0   | | rho*I A^H | = | I   0   | | rho*I U12 |,
    //   | 0 P22 | | A     0   |   | L21 L22 | | 0     U22 |
    // where [L22,U22] are stored within B22.
    const Int m = A.Height();
    const Int n = A.Width();
    const Grid& grid = A.Grid();
    DistMatrix<Real> U12(grid), L21(grid), B22(grid), bPiv(grid);
    U12.Align( 0,                 n%U12.RowStride() );
    L21.Align( n%L21.ColStride(), 0                 );
    B22.Align( n%B22.ColStride(), n%B22.RowStride() );
    Adjoint( A, U12 );
    L21 = A;
    L21 *= 1/ctrl.rho;
    Herk( LOWER, NORMAL, -1/ctrl.rho, A, B22 );
    MakeHermitian( LOWER, B22 );
    DistPermutation P2(grid);
    LU( B22, P2 );
    P2.PermuteRows( L21 );
    bPiv = b;
    P2.PermuteRows( bPiv );

    // Possibly form the inverse of L22 U22
    DistMatrix<Real> X22(grid);
    if( ctrl.inv )
    {
        X22 = B22;
        MakeTrapezoidal( LOWER, X22 );
        FillDiagonal( X22, Real(1) );
        TriangularInverse( LOWER, UNIT, X22 );
        Trsm( LEFT, UPPER, NORMAL, NON_UNIT, Real(1), B22, X22 );
    }

    Int numIter=0;
    DistMatrix<Real> g(grid), xTmp(grid), y(grid), t(grid);
    Zeros( g, m+n, 1 );
    PartitionDown( g, xTmp, y, n );
    DistMatrix<Real> x(grid), u(grid), zOld(grid), xHat(grid);
    Zeros( z, n, 1 );
    Zeros( u, n, 1 );
    Zeros( t, n, 1 );
    while( numIter < ctrl.maxIter )
    {
        zOld = z;

        // Find x from
        //  | rho*I  A^H | | x | = | rho*(z-u)-c |
        //  | A      0   | | y |   | b           |
        // via our cached custom factorization:
        //
        // |x| = inv(U) inv(L) P' |rho*(z-u)-c|
        // |y|                    |b          |
        //     = |rho*I U12|^{-1} |I   0  | |I 0   | |rho*(z-u)-c|
        //     = |0     U22|      |L21 L22| |0 P22'| |b          |
        //     = "                        " |rho*(z-u)-c|
        //                                  | P22' b    |
        xTmp = z;
        xTmp -= u;
        xTmp *= ctrl.rho;
        xTmp -= c;
        y = bPiv;
        Gemv( NORMAL, Real(-1), L21, xTmp, Real(1), y );
        if( ctrl.inv )
        {
            Gemv( NORMAL, Real(1), X22, y, t );
            y = t;
        }
        else
        {
            Trsv( LOWER, NORMAL, UNIT, B22, y );
            Trsv( UPPER, NORMAL, NON_UNIT, B22, y );
        }
        Gemv( NORMAL, Real(-1), U12, y, Real(1), xTmp );
        xTmp *= 1/ctrl.rho;

        // xHat := alpha*x + (1-alpha)*zOld
        xHat = xTmp;
        xHat *= ctrl.alpha;
        Axpy( 1-ctrl.alpha, zOld, xHat );

        // z := pos(xHat+u)
        z = xHat;
        z += u;
        LowerClip( z, Real(0) );

        // u := u + (xHat-z)
        u += xHat;
        u -= z;

        const Real objective = Dot( c, xTmp );

        // rNorm := || x - z ||_2
        t = xTmp;
        t -= z;
        const Real rNorm = FrobeniusNorm( t );
        // sNorm := |rho| || z - zOld ||_2
        t = z;
        t -= zOld;
        const Real sNorm = Abs(ctrl.rho)*FrobeniusNorm( t );

        const Real epsPri = Sqrt(Real(n))*ctrl.absTol +
            ctrl.relTol*Max(FrobeniusNorm(xTmp),FrobeniusNorm(z));
        const Real epsDual = Sqrt(Real(n))*ctrl.absTol +
            ctrl.relTol*Abs(ctrl.rho)*FrobeniusNorm(u);

        if( ctrl.print )
        {
            t = xTmp;
            LowerClip( t, Real(0) );
            t -= xTmp;
            const Real clipDist = FrobeniusNorm( t );
            if( grid.Rank() == 0 )
                cout << numIter << ": "
                  << "||x-z||_2=" << rNorm << ", "
                  << "epsPri=" << epsPri << ", "
                  << "|rho| ||z-zOld||_2=" << sNorm << ", "
                  << "epsDual=" << epsDual << ", "
                  << "||x-Pos(x)||_2=" << clipDist << ", "
                  << "c'x=" << objective << endl;
        }
        if( rNorm < epsPri && sNorm < epsDual )
            break;
        ++numIter;
    }
    if( ctrl.maxIter == numIter && grid.Rank() == 0 )
        cout << "ADMM failed to converge" << endl;
    x = xTmp;
    return numIter;
}