[mlpack-git] master: implement the mehrotra's predictor-corrector rule (159d581)

gitdub at big.cc.gt.atl.ga.us gitdub at big.cc.gt.atl.ga.us
Mon Feb 2 15:16:20 EST 2015


Repository : https://github.com/mlpack/mlpack

On branch  : master
Link       : https://github.com/mlpack/mlpack/compare/bb6e5c56aab07e6449d86021246b52a9e323f3a0...bd6cb33f8d8270b02a84e81e38727679bb6c319a

>---------------------------------------------------------------

commit 159d58177a829ec4bbea6c18102f3501040cd47f
Author: Stephen Tu <tu.stephenl at gmail.com>
Date:   Wed Jan 21 00:23:26 2015 -0800

    implement the mehrotra's predictor-corrector rule
    
    still need to remove the code duplication


>---------------------------------------------------------------

159d58177a829ec4bbea6c18102f3501040cd47f
 src/mlpack/core/optimizers/sdp/primal_dual.cpp | 73 +++++++++++++++++++++-----
 src/mlpack/core/optimizers/sdp/primal_dual.hpp |  2 -
 2 files changed, 61 insertions(+), 14 deletions(-)

diff --git a/src/mlpack/core/optimizers/sdp/primal_dual.cpp b/src/mlpack/core/optimizers/sdp/primal_dual.cpp
index 062b875..abaebc0 100644
--- a/src/mlpack/core/optimizers/sdp/primal_dual.cpp
+++ b/src/mlpack/core/optimizers/sdp/primal_dual.cpp
@@ -28,8 +28,7 @@ PrimalDualSolver::PrimalDualSolver(const SDP& sdp)
     ysparse0(arma::ones<arma::vec>(sdp.NumSparseConstraints())),
     ydense0(arma::ones<arma::vec>(sdp.NumDenseConstraints())),
     Z0(arma::eye<arma::mat>(sdp.N(), sdp.N())),
-    sigma(0.5),
-    tau(0.5),
+    tau(0.99),
     normXzTol(1e-7),
     primalInfeasTol(1e-7),
     dualInfeasTol(1e-7),
@@ -48,8 +47,7 @@ PrimalDualSolver::PrimalDualSolver(const SDP& sdp,
     ysparse0(ysparse0),
     ydense0(ydense0),
     Z0(Z0),
-    sigma(0.5),
-    tau(0.5),
+    tau(0.99),
     normXzTol(1e-7),
     primalInfeasTol(1e-7),
     dualInfeasTol(1e-7),
@@ -191,7 +189,7 @@ PrimalDualSolver::Optimize(arma::mat& X,
   for (size_t iteration = 0; iteration < maxIterations; iteration++)
   {
 
-    const double mu = sigma * arma::dot(sx, sz) / n;
+
 
     if (sdp.NumSparseConstraints())
       rp(arma::span(0, sdp.NumSparseConstraints() - 1)) =
@@ -206,8 +204,7 @@ PrimalDualSolver::Optimize(arma::mat& X,
     if (sdp.HasDenseObjective())
       rd += scdense;
 
-    Rc = mu*arma::eye<arma::mat>(n, n) - 0.5*(X*Z + Z*X);
-    math::Svec(Rc, rc);
+
 
     math::SymKronId(Z, E);
     math::SymKronId(X, F);
@@ -259,6 +256,63 @@ PrimalDualSolver::Optimize(arma::mat& X,
         Adense * Einv_F_AdenseT;
     }
 
+    const double sxdotsz = arma::dot(sx, sz);
+    double sigma = 0.;
+    {
+      Rc = -0.5*(X*Z + Z*X);
+      math::Svec(Rc, rc);
+      math::Smat(F * rd - rc, Frd_rc_Mat);
+      SolveLyapunov(Einv_Frd_rc_Mat, Z, 2. * Frd_rc_Mat);
+      math::Svec(Einv_Frd_rc_Mat, Einv_Frd_rc);
+
+      rhs = rp;
+      if (sdp.NumSparseConstraints())
+        rhs(arma::span(0, sdp.NumSparseConstraints() - 1)) += Asparse * Einv_Frd_rc;
+      if (sdp.NumDenseConstraints())
+        rhs(arma::span(sdp.NumSparseConstraints(), sdp.NumConstraints() - 1)) += Adense * Einv_Frd_rc;
+
+      // TODO(stephentu): use a more efficient method (e.g. LU decomposition)
+      if (!arma::solve(dy, M, rhs))
+        Log::Fatal << "PrimalDualSolver::Optimize(): Could not solve KKT system" << std::endl;
+
+      if (sdp.NumSparseConstraints())
+        dysparse = dy(arma::span(0, sdp.NumSparseConstraints() - 1));
+      if (sdp.NumDenseConstraints())
+        dydense = dy(arma::span(sdp.NumSparseConstraints(), sdp.NumConstraints() - 1));
+
+      math::Smat(F * (rd - Asparse.t() * dysparse - Adense.t() * dydense) - rc, Frd_ATdy_rc_Mat);
+      SolveLyapunov(Einv_Frd_ATdy_rc_Mat, Z, 2. * Frd_ATdy_rc_Mat);
+      math::Svec(Einv_Frd_ATdy_rc_Mat, Einv_Frd_ATdy_rc);
+      dsx = -Einv_Frd_ATdy_rc;
+      dsz = rd - Asparse.t() * dysparse - Adense.t() * dydense;
+
+      math::Smat(dsx, dX);
+      math::Smat(dsz, dZ);
+
+      // TODO(stephentu): computing these alphahats should take advantage of
+      // the cholesky decomposition of X and Z which we should have available
+      // when we use more efficient methods above.
+
+      double alphahatX = AlphaHat(X, dX);
+      if (alphahatX < 0.)
+        // dX is PSD
+        alphahatX = 1.;
+
+      double alphahatZ = AlphaHat(Z, dZ);
+      if (alphahatZ < 0.)
+        // dZ is PSD
+        alphahatZ = 1.;
+
+      const double alpha = std::min(1., tau * alphahatX);
+      const double beta = std::min(1., tau * alphahatZ);
+
+      sigma = std::pow(arma::dot(X + alpha * dX, Z + beta * dZ) / sxdotsz, 3);
+    }
+
+    const double mu = sigma * sxdotsz / n;
+
+    Rc = mu*arma::eye<arma::mat>(n, n) - 0.5*(X*Z + Z*X + dX*dZ + dZ*dX);
+    math::Svec(Rc, rc);
     math::Smat(F * rd - rc, Frd_rc_Mat);
     SolveLyapunov(Einv_Frd_rc_Mat, Z, 2. * Frd_rc_Mat);
     math::Svec(Einv_Frd_rc_Mat, Einv_Frd_rc);
@@ -304,11 +358,6 @@ PrimalDualSolver::Optimize(arma::mat& X,
     const double alpha = std::min(1., tau * alphahatX);
     const double beta = std::min(1., tau * alphahatZ);
 
-    // TODO(stephentu): Implement the Mehrotra's predictor-corrector rule.  See
-    // Section 7 of [AHO98]. This will require making the above KKT system
-    // solver more modular (since we'll have to solve another similar KKT
-    // system).
-
     X += alpha * dX;
     math::Svec(X, sx);
     ysparse += beta * dysparse;
diff --git a/src/mlpack/core/optimizers/sdp/primal_dual.hpp b/src/mlpack/core/optimizers/sdp/primal_dual.hpp
index 8c3b863..9480b20 100644
--- a/src/mlpack/core/optimizers/sdp/primal_dual.hpp
+++ b/src/mlpack/core/optimizers/sdp/primal_dual.hpp
@@ -37,7 +37,6 @@ class PrimalDualSolver {
     return Optimize(X, ysparse, ydense, Z);
   }
 
-  double& Sigma() { return sigma; }
   double& Tau() { return tau; }
   double& NormXzTol() { return normXzTol; }
   double& PrimalInfeasTol() { return primalInfeasTol; }
@@ -52,7 +51,6 @@ class PrimalDualSolver {
   arma::vec ydense0;
   arma::mat Z0;
 
-  double sigma;
   double tau;
   double normXzTol;
   double primalInfeasTol;



More information about the mlpack-git mailing list