diff --git a/src/micpsolver/micpprog.hpp b/src/micpsolver/micpprog.hpp
index 3f46db2..d5e0651 100644
--- a/src/micpsolver/micpprog.hpp
+++ b/src/micpsolver/micpprog.hpp
@@ -1,56 +1,58 @@
 /*-------------------------------------------------------
 
  - Module : micpsolver
  - File : micpprog.hpp
  - Author : Fabien Georget
 
  Copyright (c) 2014, Fabien Georget, Princeton University
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_MICPSOLVER_MICPPROG_HPP
 #define SPECMICP_MICPSOLVER_MICPPROG_HPP
 
 //! \file micpprog.hpp The static interface of a MiCP solver
 
 namespace specmicp {
 namespace micpsolver {
 
 
 struct traits_MiCPProg
 {
     using scalar_t = double;
     using vector_t = Eigen::Matrix<double, Eigen::Dynamic, 1>;
     using matrix_t = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>;
 
 };
 
 //! A MiCP program
 template <class Derived>
 class MiCPProg
 {
 public:
     using types = traits_MiCPProg;
 
     static double infinity() {return HUGE_VAL;}
 
     Derived& derived() {return static_cast<Derived*>(*this);}
 
     //! Return the number of variables
     int total_variables();
     int nb_free_variables();
     int nb_complementarity_variables() {return total_variables() - nb_free_variables();}
 
     //! Return the residual (R(X))
     void get_residuals(const types::vector_t& x,
                        types::vector_t& residual);
 
     //! Return the jacobian (J(x))
     void get_jacobian(const types::vector_t& x,
                       types::matrix_t& jacobian);
+
+    void hook_start_iteration(const types::vector_t& x) {}
 };
 
 } // end namespace micpsolver
 } // end namespace specmicp
 
 #endif // SPECMICP_MICPSOLVER_MICPPROG_HPP
diff --git a/src/micpsolver/micpsolver.inl b/src/micpsolver/micpsolver.inl
index 254b426..a866a72 100644
--- a/src/micpsolver/micpsolver.inl
+++ b/src/micpsolver/micpsolver.inl
@@ -1,514 +1,515 @@
 /*-------------------------------------------------------
 
  - Module : micpsolver
  - File : micpsolver.inl
  - Author : Fabien Georget
 
  Copyright (c) 2014, Fabien Georget, Princeton University
 
 ---------------------------------------------------------*/
 
 #include "micpsolver.hpp" // for syntaxic coloration...
 
 #include "estimate_cond_number.hpp"
 
 namespace specmicp {
 namespace micpsolver {
 
 // Main algorithm
 // ##############
 
 template <class Program>
 MiCPSolverReturnCode MiCPSolver<Program>::solve(Eigen::VectorXd &x)
 {
     int cnt = 0;
     crashing(x);
     MiCPSolverReturnCode retcode = MiCPSolverReturnCode::NotConvergedYet;
     Eigen::VectorXd update(get_neq());
     while (retcode == MiCPSolverReturnCode::NotConvergedYet)
     {
         std::cout << "Iteration : " << cnt << std::endl;
+        m_program->hook_start_iteration(x);
         setup_residuals(x);
         //std::cout << "Residuals \n ------- \n " << m_residuals << "\n ---- \n" << m_phi_residuals << std::endl;
         retcode = check_convergence(cnt, update, x);
         m_max_taken = false;
         if (retcode != MiCPSolverReturnCode::NotConvergedYet) break;
         setup_jacobian(x);
         std::cout << "Solve system " << std::endl;
         search_direction_calculation(update);
         //x += update;
         int retcode = linesearch(update, x);
         std::cout << " Return linesearch : " << retcode << std::endl;
 
 
         std::cout << "Solution : \n ------ \n" <<  x << std::endl;
         ++cnt;
     }
     return retcode;
 }
 
 template <class Program>
 MiCPSolverReturnCode MiCPSolver<Program>::check_convergence(int nb_iterations,
                                             Eigen::VectorXd& update,
                                             Eigen::VectorXd& solution)
 {
     MiCPSolverReturnCode termcode = MiCPSolverReturnCode::NotConvergedYet;
     std::cout << "Residuals : " << m_phi_residuals.lpNorm<Eigen::Infinity>() << std::endl;
     //<< " -------- \n" << m_phi_residuals << std::endl;
     if (m_phi_residuals.lpNorm<Eigen::Infinity>() < get_options().fvectol)
     {
          termcode = MiCPSolverReturnCode::ResidualMinimized;
     }
     else if (nb_iterations >0 and norm_update<Eigen::Infinity>(update, solution) < get_options().steptol)
     {
         termcode = MiCPSolverReturnCode::ErrorMinimized;
     }
     else if (nb_iterations >  get_options().max_iter)
     {
         termcode = MiCPSolverReturnCode::MaxIterations;
     }
     else if (m_max_taken)
     {
         ++m_consec_max;
         if (m_consec_max == get_options().maxiter_maxstep) {
             termcode = MiCPSolverReturnCode::MaxStepTakenTooManyTimes;
         }
     }
     else
     {
         m_consec_max = 0;
     }
     return termcode;
 }
 
 
 template <class Program>
 MiCPSolverReturnCode MiCPSolver<Program>::search_direction_calculation(Eigen::VectorXd& update)
 {
     Eigen::VectorXd rscaler(Eigen::VectorXd::Ones(get_neq()));
     Eigen::VectorXd cscaler(Eigen::VectorXd::Ones(get_neq()));
     scaling_jacobian(m_jacobian, m_phi_residuals, rscaler, cscaler);
     //std::cout << m_jacobian << std::endl;
     m_jacobian = rscaler.asDiagonal() * m_jacobian * cscaler.asDiagonal();
     //m_jacobian += 1e-5*Eigen::MatrixXd::Identity(get_neq(), get_neq());
     //std::cout << m_jacobian << std::endl;
     //m_phi_residuals = - rscaler.cwiseProduct(m_phi_residuals);
 
     double descent_cond = 0;
     Eigen::ColPivHouseholderQR<Eigen::MatrixXd> solver = m_jacobian.colPivHouseholderQr();
     if (solver.info() != Eigen::Success)
     {
         throw std::runtime_error("Error when computing decomposition");
     }
     //solver.compute(m_jacobian);
 
     if (solver.isInvertible())
     {
        double cond = estimate_condition_number(solver.matrixR().triangularView<Eigen::Upper>());
         int cnt = 0;
         while (cond > get_options().condition_limit and cnt < 10)
         {
             std::cout << "Bad conditionning : " << cond << std::endl;
             //std::cout << m_jacobian << std::endl;
             //throw std::runtime_error("bummer");
             double delta = m_phi_residuals.norm();
             m_jacobian += delta*Eigen::MatrixXd::Identity(get_neq(), get_neq());
             solver.compute(m_jacobian);
             cond = estimate_condition_number(solver.matrixR().triangularView<Eigen::Upper>());
             ++cnt;
         }
         update = solver.solve(-rscaler.cwiseProduct(m_phi_residuals));
         update  = cscaler.cwiseProduct(update);
-        std::cout << "update : \n" << update << std::endl;
+        //std::cout << "update : \n" << update << std::endl;
         descent_cond = m_grad_phi.dot(update)
                 + get_options().factor_descent_condition * std::pow(update.norm(), get_options().power_descent_condition);
     }
     std::cout << "Descent condition : " << descent_cond << std::endl;
     if (   (not solver.isInvertible())
         or (solver.info() != Eigen::Success)
         or (descent_cond > 0)
        )
     {
         std::cout << "Gradient step " << std::endl;
         update = -m_grad_phi;
     }
     return MiCPSolverReturnCode::NotConvergedYet;
 }
 
 
 //template <class Program>
 //int MiCPSolver<Program>::linesearch(Eigen::VectorXd& update, Eigen::VectorXd& x)
 //{
 
 //    double beta = 0.5;
 //    double sigma = 1e-4;
 //    double prev_test = HUGE_VAL;
 //    Eigen::VectorXd xp(get_neq());
 //    int l = 0;
 
 
 //    // non monotone linesearch
 //    double merit_value = 0.5*m_phi_residuals.squaredNorm();
 //    std::cout << "Merit value : " << merit_value << std::endl;
 //    double mmax = merit_value;
 //    if (m_max_merits.size() > 0)
 //    {
 //        mmax = m_max_merits[m_max_merits.size()-1];
 //    }
 //    if (m_max_merits.size() < 4)
 //    {
 //        m_max_merits.push_back(merit_value);
 //        if (merit_value < mmax) merit_value = (3*merit_value + mmax)/4;
 //    }
 //    else if (merit_value < mmax)
 //    {
 //        m_max_merits[3] = merit_value;
 //        merit_value = mmax;
 //    }
 //    std::cout << "Merit value used : " << merit_value << std::endl;
 //    std::sort(m_max_merits.begin(), m_max_merits.end());
 //    const double gphidupdate = m_grad_phi.dot(update);
 //    while (l<20)
 //    {
 //        xp = x + std::pow(beta, l)*update;
 //        // projection
 ////        for (int i=0; i<m_program->nb_complementarity_variables(); ++i)
 ////        {
 ////            if (xp(i+m_program->nb_free_variables()) < 0)
 ////            {
 ////                xp(i+m_program->nb_free_variables()) = 0;
 ////            }
 ////        }
 //        Eigen::VectorXd new_res(get_neq());
 //        m_program->get_residuals(xp, new_res);
 //        reformulate_residuals_inplace(xp, new_res);
 //        double test = 0.5*new_res.squaredNorm() - merit_value - sigma*std::pow(beta, l)*gphidupdate;
 //        if (test > prev_test) {
 //            xp = x + std::pow(beta, l-1)*update;
 //            std::cout << "Failed Global Method ! -- too short" << std::endl;
 //            // projection
 ////            for (int i=0; i<m_program->nb_complementarity_variables(); ++i)
 ////            {
 ////                if (xp(i+m_program->nb_free_variables()) < 0)
 ////                {
 ////                    xp(i+m_program->nb_free_variables()) = 0;
 ////                }
 ////            }
 //            break;
 //        }
 //        if (test <= 0)
 //        {
 //            break;
 //        }
 //        prev_test = test;
 //        ++l;
 //    }
 //    x = xp;
 //    if (l == 20) {
 //        std::cout << "Failed Global Method !" << std::endl;
 //        //x -= m_grad_phi / (10*m_grad_phi.norm());
 //    }
 
 //    return 0;
 //}
 
 template <class Program>
 void MiCPSolver<Program>::crashing(Eigen::VectorXd &x)
 {
     std::cout << "Crashing " << std::endl;
     const double beta = 0.5;
     const double sigma = 1e-5;
     int cnt = 0;
     while (cnt < 10)
     {
         setup_residuals(x);
         setup_jacobian(x);
         m_grad_phi = m_jacobian.transpose()*m_phi_residuals;
         std::cout << m_grad_phi << std::endl;
         Eigen::VectorXd xp(get_neq());
         int l=0;
         while (l<20)
         {
             xp = x - std::pow(beta, l)*m_grad_phi;
             for (int i=get_neq_free(); i<get_neq(); ++i)
             {
                 if (xp(i) < 0) xp(i) = 0;
             }
             Eigen::VectorXd new_res(get_neq());
             compute_residuals(x, new_res);
             reformulate_residuals_inplace(x, new_res);
             double test = 0.5*(new_res.squaredNorm() - m_phi_residuals.squaredNorm())  + sigma*m_grad_phi.dot(x - xp);
             if (test <= 0) break;
             ++l;
         }
         if (l == 20) break;
         x = xp;
 
         ++cnt;
     }
     std::cout << "Crashing iterations : " << cnt << std::endl;
     std::cout << "Merit function after crashing " <<  0.5*m_grad_phi.squaredNorm() << std::endl;
     m_max_merits.reserve(4);
     std::cout << "Solution after crashing \n ------ \n " << x << std::endl;
     //m_max_merits.push_back(0.5*m_grad_phi.squaredNorm());
 }
 
 // Others
 // ######
 
 template <class Program>
 void MiCPSolver<Program>::reformulate_residuals(const Eigen::VectorXd& x,
                                                 const Eigen::VectorXd& r,
                                                 Eigen::VectorXd& r_phi)
 {
     r_phi.block(0, 0, get_neq_free(), 1) = r.block(0, 0, get_neq_free(), 1);
     for (int i =  get_neq_free(); i<get_neq(); ++i)
     {
         r_phi(i) = phi_lower_bounded(x(i), r(i), 0);
     }
-    std::cout << "Residuals \n-----\n" << r << "\n -----\n Reformulation \n ---- \n" << r_phi << "\n ---- \n";
+   //std::cout << "Residuals \n-----\n" << r << "\n -----\n Reformulation \n ---- \n" << r_phi << "\n ---- \n";
 }
 
 template <class Program>
 void MiCPSolver<Program>::reformulate_residuals_inplace(const Eigen::VectorXd& x,
                                                 Eigen::VectorXd& r)
 {
     for (int i =  get_neq_free(); i<get_neq(); ++i)
     {
         r(i) = phi_lower_bounded(x(i), r(i), 0);
     }
 }
 
 double dz(double z) {
     if (z > 0)
     {
         return 1.0;
     }
     else if (z < 0)
     {
         return 0;
     }
     else // z ==0
         return 0.0;
 
 }
 
 // page 808 Facchinei and Pang(2003) (vol 2, chap 9)
 template <class Program>
 void MiCPSolver<Program>::reformulate_jacobian(const Eigen::VectorXd& x,
                           const Eigen::VectorXd& r,
                           Eigen::MatrixXd& jacobian
                           )
 {
     // set the z vector : contains 1 for degenerate points
     Eigen::VectorXd z(Eigen::VectorXd::Zero(get_neq()));
     for (int i=get_neq_free(); i<get_neq(); ++i)
     {
         if (x(i) == 0 and r(i) == 0)
             z(i) = 1.0;
     }
     // modify the jacobian
     const double lambda = get_options().penalization_factor;
     for (int i=get_neq_free(); i<get_neq(); ++i)
     {
         const auto ei = unit_vector(get_neq(), i);
         Eigen::VectorXd grad_fi = jacobian.block(i, 0, 1, get_neq()).transpose();
         if (z(i) != 0)
         {
             double gpdotz = grad_fi.dot(z);
             double s = std::abs(z(i)) + std::abs(gpdotz);
             s = s * std::sqrt(z(i)*z(i)/(s*s) + gpdotz*gpdotz/(s*s));
             const double c = lambda*(z(i)/s - 1);
             const double d = lambda*(gpdotz/s -1);
             grad_fi = c*ei + d*grad_fi;
         }
         else
         {
             double s = std::abs(x(i)) + std::abs(r(i));
             s = s * std::sqrt(x(i)*x(i)/(s*s) + r(i)*r(i)/(s*s));
             //double s = std::sqrt(x(i)*x(i) + r(i)*r(i));
             //const double c = (x(i)/s -1);
             //const double d = (r(i)/s -1);
-            const double c = lambda*(x(i)/s - 1) - (1-lambda)*(std::min(0.0, r(i)*dz(x(i))));
-            const double d = lambda*(r(i)/s - 1)  - (1-lambda)*(std::min(0.0, x(i))*dz(r(i)));
+            const double c = lambda*(x(i)/s - 1) - (1-lambda)*(std::max(0.0, r(i)*dz(x(i))));
+            const double d = lambda*(r(i)/s - 1)  - (1-lambda)*(std::max(0.0, x(i))*dz(r(i)));
 
             grad_fi = c*ei + d*grad_fi;
         }
         jacobian.block(i, 0, 1, get_neq()) = grad_fi.transpose();
     }
 }
 
 // ref : Munson et al. (2001)
 template <class Program>
 void MiCPSolver<Program>:: scaling_jacobian(
         const Eigen::MatrixXd& jacobian,
         const Eigen::VectorXd& r_phi,
         Eigen::VectorXd& rscaler,
         Eigen::VectorXd& cscaler)
 {
     //rscaler = Eigen::VectorXd::Ones(get_neq());
     //cscaler = Eigen::VectorXd::Ones(get_neq());
     for (int i=0; i<get_neq(); ++i)
     {
         const double sumhsq = jacobian.block(i, 0, 1, get_neq()).array().square().sum();
         double s = std::sqrt(r_phi(i)*r_phi(i) + sumhsq);
         rscaler(i) = 1.0/std::max(s, 1e-10);
     }
     for (int i=0; i<get_neq(); ++i)
     {
         const double sumhsq = (rscaler.asDiagonal()*jacobian).block(0, i, get_neq(), 1).array().square().sum();
         double s = std::sqrt(sumhsq);
         cscaler(i) = 1.0/std::max(s, 1e-10);
     }
 
 }
 
 
 template <class Program>
 int MiCPSolver<Program>::linesearch(Eigen::VectorXd& p, Eigen::VectorXd& x)
 {
     Eigen::VectorXd xp(get_neq());
     Eigen::VectorXd new_res(get_neq());
     double fcp;
 
     m_max_taken = false;
     int retcode = 2;
     const double alpha = 1e-6;
     double newtlen = is_step_too_long(p);
     double init_slope = m_grad_phi.dot(p);
     std::cout << "Init slope : " << init_slope << std::endl;
     double rellength = std::abs(p(0));
     for (int i=1; i<get_neq(); ++i)
     {
         rellength = std::max(rellength, std::abs(p(i)));
     }
     double minlambda = get_options().steptol / rellength;
     double lambda = 1.0;
     double lambda_prev = 1.0;
 
     // non monotone linesearch
     double merit_value = 0.5*m_phi_residuals.squaredNorm();
     xp = x + lambda*p;
     projection(xp);
     //std::cout << xp << std::endl;
     compute_residuals(xp, new_res);
     reformulate_residuals_inplace(xp, new_res);
     fcp = 0.5*new_res.squaredNorm();
     if (fcp < 0.95 *merit_value)
     {
         x = xp;
         return 0;
     }
 
     std::cout << "Merit value : " << merit_value << std::endl;
     double mmax = merit_value;
     if (m_max_merits.size() > 0)
     {
         mmax = m_max_merits[m_max_merits.size()-1];
     }
     if (m_max_merits.size() < 4)
     {
         m_max_merits.push_back(merit_value);
         if (merit_value < mmax) merit_value = (3*merit_value + mmax)/4;
     }
     else if (merit_value < mmax)
     {
         m_max_merits[3] = merit_value;
         merit_value = mmax;
     }
     std::cout << "Merit value used : " << merit_value << std::endl;
     double fc = merit_value;
     double fcp_prev;
     do
     {
         fcp = 0.5*new_res.squaredNorm();
         std::cout << "lambda : " << lambda << std::endl;
         //std::cout << "fcp : " << fcp << "\n fc+alin : " << fc+alpha*lambda*init_slope << " # fc : " << fc << std::endl;
         if (fcp <= fc - std::min(-alpha*lambda*init_slope,(1-alpha)*fc)) //pg760 Fachinei2003
         {
             retcode = 0;
             if (lambda ==1 and (newtlen > 0.99 * get_options().maxstep)) {
                 m_max_taken = true;
             }
             break;
         }
         else if (lambda < minlambda)
         {
             retcode = 1;
             break;
         }
         else
         {
             double lambdatmp;
             if (lambda == 1.0) {
                 lambdatmp = - init_slope / (2*(fcp - fc -init_slope));
             }
             else
             {
                 const double factor = 1 /(lambda - lambda_prev);
                 const double x1 = fcp - fc - lambda*init_slope;
                 const double x2 = fcp_prev - fc - lambda_prev*init_slope;
 
                 const double a = factor * ( x1/(lambda*lambda) - x2/(lambda_prev*lambda_prev));
                 const double b = factor * ( -x1*lambda_prev/(lambda*lambda) + x2*lambda/(lambda_prev*lambda_prev));
 
                 if (a == 0)
                 { // cubic is quadratic
                     lambdatmp = - init_slope/(2*b);
                 }
                 else
                 {
                     const double disc = b*b-3*a*init_slope;
                     lambdatmp = (-b+std::sqrt(disc))/(3*a);
                 }
                 if (lambdatmp > 0.5 ) lambdatmp = 0.5*lambda;
             }
             lambda_prev = lambda;
             fcp_prev = fcp;
             if (lambdatmp < 0.1*lambda) {
                 lambda = 0.1 * lambda;
             } else {
                 lambda = lambdatmp;
             }
         }
         xp = x + lambda*p;
         projection(xp);
         //std::cout << xp << std::endl;
         compute_residuals(xp, new_res);
         reformulate_residuals_inplace(xp, new_res);
     } while(retcode == 2);
     //projection(xp);
     x = xp;
     p = lambda*p;
     return retcode;
 
 }
 
 // Projection of the variables onto the feasible set
 template <class Program>
 void MiCPSolver<Program>::projection(Eigen::VectorXd &x)
 {
     for (int i=0; i<m_program->nb_complementarity_variables(); ++i)
     {
         if (x(i+m_program->nb_free_variables()) < 0)
         {
             x(i+m_program->nb_free_variables()) = 0;
         }
     }
 }
 
 template <class Program>
 double MiCPSolver<Program>::is_step_too_long(Eigen::VectorXd& update)
 {
     double steplength = update.norm();
     if (steplength > get_options().maxstep)
     {
         m_max_taken = true;
         update  = get_options().maxstep / steplength * update;
         steplength = get_options().maxstep;
     }
     return steplength;
 }
 
 } // end namespace micpsolver
 } // end namespace specmicp
diff --git a/tests/micpsolver/test_micpsolver.hpp b/tests/micpsolver/test_micpsolver.hpp
index d44e12a..74277ee 100644
--- a/tests/micpsolver/test_micpsolver.hpp
+++ b/tests/micpsolver/test_micpsolver.hpp
@@ -1,202 +1,208 @@
 /*-------------------------------------------------------
 
  - Module : tests/micpsolver
  - File : test_micpsolver.hpp
  - Author : Fabien Georget
 
  Copyright (c) 2014, Fabien Georget, Princeton University
 
 ---------------------------------------------------------*/
 
 #include "cxxtest/TestSuite.h"
 
 #include "micpsolver/micpsolver.hpp"
 #include "micpsolver/micpprog.hpp"
 
 using namespace specmicp::micpsolver;
 
 
 class TestLinearProgram: public MiCPProg<TestLinearProgram>
 {
 public:
     //! Return the number of variables
     int total_variables() {return 3;}
     int nb_free_variables() {return 2;}
     int nb_complementarity_variables() {return 1;}
 
     //! Return the residual (R(X))
     void get_residuals(const types::vector_t& x,
                        types::vector_t& residual) {
         assert(residual.rows() == 3);
         residual << 1 + x(0) + x(2), 1 + 1*x(1) + x(2), -x(0) - x(1) +x(2);
     }
 
     //! Return the jacobian (J(x))
     void get_jacobian(const types::vector_t& x,
                       types::matrix_t& jacobian)
     {
         assert(jacobian.cols() == 3);
         assert(jacobian.rows() == 3);
         jacobian << 1, 0, 1, 0, 1, 1, -1, -1, 1;
     }
 };
 
 class TestNonLinearProgram: public MiCPProg<TestNonLinearProgram>
 {
 public:
     //! Return the number of variables
     int total_variables() {return 3;}
     int nb_free_variables() {return 2;}
     int nb_complementarity_variables() {return 1;}
 
     //! Return the residual (R(X))
     void get_residuals(const types::vector_t& x,
                        types::vector_t& residual) {
         assert(residual.rows() == 3);
         residual << -1 + x(0)*x(0) + x(2), 1 + 1*x(1) + x(2)*x(2), -x(0) - x(1) +x(2);
     }
 
     //! Return the jacobian (J(x))
     void get_jacobian(const types::vector_t& x,
                       types::matrix_t& jacobian)
     {
         assert(jacobian.cols() == 3);
         assert(jacobian.rows() == 3);
         jacobian << 2*x(0), 0, 1, 0, 1, 2*x(2), -1, -1, 1;
     }
 };
 
+/*
+ * S. P. Dirkse and M. C. Ferris.
+ *  MCPLIB: a collection of nonlinear mixed complementarity problems.
+ * Optimization Methods and Software, 5(4):319-345, 1995.
+ *
+ */
 class TestKojimaProgram: public MiCPProg<TestKojimaProgram>
 {
 public:
     //! Return the number of variables
     int total_variables() {return 4;}
     int nb_free_variables() {return 0;}
     int nb_complementarity_variables() {return 4;}
 
     //! Return the residual (R(X))
     void get_residuals(const types::vector_t& x,
                        types::vector_t& residual) {
         assert(residual.rows() == 4);
         residual << 3*x(0)*x(0)+2*x(0)*x(1)+2*x(1)*x(1)+x(2)+3*x(3)-6,
                 2*x(0)*x(0)+x(1)*x(1)+x(0)+10*x(2) +2*x(3)-2,
                 3*x(0)+x(0)*x(1)+2*x(1)*x(1)+2*x(2)+9*x(3)-9,
                 x(0)*x(0)+3*x(1)*x(1)+2*x(2)+3*x(3)-3
                 ;
     }
 
     //! Return the jacobian (J(x))
     void get_jacobian(types::vector_t& x,
                       types::matrix_t& jacobian)
     {
         assert(jacobian.cols() == 4);
         assert(jacobian.rows() == 4);
         const int neq = total_variables();
         Eigen::VectorXd res(total_variables());
         Eigen::VectorXd perturbed_res(total_variables());
 
         get_residuals(x, res);
         for (int j=0; j<neq; ++j)
         {
             double h = 1e-8*std::abs(x(j));
             //h = std::copysign(h, x(j));
             if (h==0) h = 1e-8;
             double tmp = x(j);
             x(j) += h;
             h = x(j) - tmp;
             get_residuals(x, perturbed_res);
             for (int i=0; i<neq; ++i)
             {
                 jacobian(i, j) = (perturbed_res(i) - res(i))/h;
             }
             x(j) = tmp;
         }
         return;
     }
 };
 
 
 class Test_Micp : public CxxTest::TestSuite
 {
 public:
 
     void test_compiletest()
     {
     }
 
     void test_linear_program_0()
     {
         std::shared_ptr<TestLinearProgram> ptrprog  = std::make_shared<TestLinearProgram>();
         MiCPSolver<TestLinearProgram> solver(ptrprog);
 
         Eigen::VectorXd x(3);
         x << -1.5, -2 , 0;
         MiCPSolverReturnCode ret = solver.solve(x);
         TS_ASSERT_EQUALS(ret, MiCPSolverReturnCode::ResidualMinimized);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(0)+1), 1e-8);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(1)+1), 1e-8);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(2)), 1e-8);
     }
 
     void test_linear_program_10()
     {
         std::shared_ptr<TestLinearProgram> ptrprog  = std::make_shared<TestLinearProgram>();
         MiCPSolver<TestLinearProgram> solver(ptrprog);
 
         Eigen::VectorXd x(3);
         x << -1.5, -2 , 10;
         MiCPSolverReturnCode ret = solver.solve(x);
         TS_ASSERT_EQUALS(ret, MiCPSolverReturnCode::ResidualMinimized);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(0)+1), 1e-8);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(1)+1), 1e-8);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(2)), 1e-8);
     }
 
     void test_nonlinear_program_0()
     {
         std::shared_ptr<TestNonLinearProgram> ptrprog  = std::make_shared<TestNonLinearProgram>();
         MiCPSolver<TestNonLinearProgram> solver(ptrprog);
 
         Eigen::VectorXd x(3);
         x << -1.5, -2 , 0;
         MiCPSolverReturnCode ret = solver.solve(x);
         std::cout << x << std::endl;
         TS_ASSERT_EQUALS(ret, MiCPSolverReturnCode::ResidualMinimized);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(0)+1), 1e-8);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(1)+1), 1e-8);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(2)), 1e-8);
 
     }
 
     void test_nonlinear_program_5()
     {
         std::shared_ptr<TestNonLinearProgram> ptrprog  = std::make_shared<TestNonLinearProgram>();
         MiCPSolver<TestNonLinearProgram> solver(ptrprog);
 
         Eigen::VectorXd x(3);
         x << -1.5, -2 , 5;
         MiCPSolverReturnCode ret = solver.solve(x);
         std::cout << x << std::endl;
         TS_ASSERT_EQUALS(ret, MiCPSolverReturnCode::ResidualMinimized);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(0)+1), 1e-8);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(1)+1), 1e-8);
         TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(2)), 1e-8);
 
     }
 
     void test_kojima_program()
     {
         std::shared_ptr<TestKojimaProgram> ptrprog  = std::make_shared<TestKojimaProgram>();
         MiCPSolver<TestKojimaProgram> solver(ptrprog);
 
         Eigen::VectorXd x(4);
         x << 0.9, 0.1 , 2.9, 0.1;
         MiCPSolverReturnCode ret = solver.solve(x);
         std::cout << x << std::endl;
         TS_ASSERT_EQUALS(ret, MiCPSolverReturnCode::ResidualMinimized);
         //TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(0)+1), 1e-8);
         //TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(1)+1), 1e-8);
         //TS_ASSERT_LESS_THAN_EQUALS(std::abs(x(2)), 1e-8);
 
     }
 };