Пример #1
0
void NNLSOptimizer::scannls(const Mat& A, const Mat& b,Mat &x)
{
    int iter = 0;
    int m = A.size().height;
    int n = A.size().width;
    Mat_<double> AT = A.t();
    double error = 1e-8;
    Mat_<double> H = AT*A;
    Mat_<double> f = -AT*b;

    Mat_<double> x_old = Mat_<double>::zeros(n,1);
    Mat_<double> x_new = Mat_<double>::zeros(n,1);

    Mat_<double> mu_old = Mat_<double>::zeros(n,1);
    Mat_<double> mu_new = Mat_<double>::zeros(n,1);
    Mat_<double> r = Mat_<double>::zeros(n,1);
    f.copyTo(mu_old);

    while(iter < NNLS_MAX_ITER)
    {
        iter++;
        for(int k=0;k<n;k++)
        {
            x_old.copyTo(x_new);
            x_new(k,0) = std::max(0.0, x_old(k,0) - (mu_old(k,0)/H(k,k)) );

            if(x_new(k,0) != x_old(k,0))
            {
                r = mu_old + (x_new(k,0) - x_old(k,0))*H.col(k);
                r.copyTo(mu_new);
            }
            x_new.copyTo(x_old);
            mu_new.copyTo(mu_old);
        }

        if(eKKT(H,f,x_new,error) == true)
        {            
            break;
        }
    }
    x_new.copyTo(x);
}
Пример #2
0
void LcpSolverGaussSeidel<T>::Solve()
{
  
  //MatrixNxN<T> &A=*m_matM;
  MatrixCSR<T> &A = *m_matMCSR;

  VectorN<T>   &b=*m_vQ;
  VectorN<T>   &x=*m_vZ;    
  int n = A.m_iN;
  VectorN<T>   x_old(n);

  T delta;
  int i;

  for(iterationsUsed_=0; iterationsUsed_<m_iMaxIterations; ++iterationsUsed_)
  {
    //loop over the rows
    for(i=0; i<n; ++i)
    {
      T inv_aii=1.0;
      delta = 0.0;
      //loop over column
      for(int j(0); j<A.m_iRowPtr[i+1]-A.m_iRowPtr[i]; ++j)
      {
        //get the index into the values array
        int index = A.m_iRowPtr[i]+j;

        //get the column index
        int col = A.m_iColInd[index];

        //if this is the diagonal element
        if(col==i)
          inv_aii/=A.m_dValues[index];
        else
        { 
          delta += A.m_dValues[index] * x(col);
        }
      }
      
      //compute the update
      delta=inv_aii*(b(i)-delta);

      //backup the old solution
      x_old(i)=x(i);
      
      //update the solution
      x(i)=x(i) + m_dOmega*(delta - x(i));
      
      //projection step
      if(x(i) < 0.0)x(i)=0.0;    
    }
    //check the residual
    m_dResidual = VectorN<T>::CompNorm(x,x_old);
    //T dResidual_inf = VectorN<T>::CompMaxNorm(x, x_old);
    //std::cout << "Residual L2: " << m_dResidual << std:endl;
    //if (iterationsUsed_ == 0)
    //{
    //  printf("Initial Residual L2: %E\n", m_dResidual);
    //  printf("Initial Residual L-inf: %E\n", dResidual_inf);
    //  printf("Desired Residual L2: %E\n", m_dResidual*0.0001);
    //}
    //std::cout << "Residual L2: " << std::endl;
    //std::cout << "Residual MaxNorm: " << x.CompMaxNorm() << std:endl;
    //if(m_dResidual < 1e-8 || iterationsUsed_ == m_iMaxIterations-1)
    if (m_dResidual < 1e-8)
    {
      //printf("Final Residual L2: %E\n", m_dResidual);
      //printf("Final Residual L-inf: %E\n", dResidual_inf);
      //A.outputToFile("meshes/matrix.dat");
      //return;
      break;
    }
  }
  printf("Final Residual L2: %E\n", m_dResidual);
}
Пример #3
0
double QuadProg::solve_quadprog(Matrix<double>& G, Vector<double>& g0, 
                      const Matrix<double>& CE, const Vector<double>& ce0,  
                      const Matrix<double>& CI, const Vector<double>& ci0, 
                      Vector<double>& x)
{
  std::ostringstream msg;
  {
    //Ensure that the dimensions of the matrices and vectors can be
    //safely converted from unsigned int into to int without overflow.
    unsigned mx = std::numeric_limits<int>::max();
    if(G.ncols() >= mx || G.nrows() >= mx || 
       CE.nrows() >= mx || CE.ncols() >= mx ||
       CI.nrows() >= mx || CI.ncols() >= mx || 
       ci0.size() >= mx || ce0.size() >= mx || g0.size() >= mx){
      msg << "The dimensions of one of the input matrices or vectors were "
	  << "too large." << std::endl
	  << "The maximum allowable size for inputs to solve_quadprog is:"
	  << mx << std::endl;
      throw std::logic_error(msg.str());
    }
  }
  int n = G.ncols(), p = CE.ncols(), m = CI.ncols();
  if ((int)G.nrows() != n)
  {
    msg << "The matrix G is not a square matrix (" << G.nrows() << " x " 
	<< G.ncols() << ")";
    throw std::logic_error(msg.str());
  }
  if ((int)CE.nrows() != n)
  {
    msg << "The matrix CE is incompatible (incorrect number of rows " 
	<< CE.nrows() << " , expecting " << n << ")";
    throw std::logic_error(msg.str());
  }
  if ((int)ce0.size() != p)
  {
    msg << "The vector ce0 is incompatible (incorrect dimension " 
	<< ce0.size() << ", expecting " << p << ")";
    throw std::logic_error(msg.str());
  }
  if ((int)CI.nrows() != n)
  {
    msg << "The matrix CI is incompatible (incorrect number of rows " 
	<< CI.nrows() << " , expecting " << n << ")";
    throw std::logic_error(msg.str());
  }
  if ((int)ci0.size() != m)
  {
    msg << "The vector ci0 is incompatible (incorrect dimension " 
	<< ci0.size() << ", expecting " << m << ")";
    throw std::logic_error(msg.str());
  }
  x.resize(n);
  register int i, j, k, l; /* indices */
  int ip; // this is the index of the constraint to be added to the active set
  Matrix<double> R(n, n), J(n, n);
  Vector<double> s(m + p), z(n), r(m + p), d(n), np(n), u(m + p), x_old(n), u_old(m + p);
  double f_value, psi, c1, c2, sum, ss, R_norm;
  double inf;
  if (std::numeric_limits<double>::has_infinity)
    inf = std::numeric_limits<double>::infinity();
  else
    inf = 1.0E300;
  double t, t1, t2; /* t is the step lenght, which is the minimum of the partial step length t1 
    * and the full step length t2 */
  Vector<int> A(m + p), A_old(m + p), iai(m + p);
  int q, iq, iter = 0;
  Vector<bool> iaexcl(m + p);
	
  /* p is the number of equality constraints */
  /* m is the number of inequality constraints */
  q = 0;  /* size of the active set A (containing the indices of the active constraints) */
#ifdef TRACE_SOLVER
  std::cout << std::endl << "Starting solve_quadprog" << std::endl;
  print_matrix("G", G);
  print_vector("g0", g0);
  print_matrix("CE", CE);
  print_vector("ce0", ce0);
  print_matrix("CI", CI);
  print_vector("ci0", ci0);
#endif  
  
  /*
   * Preprocessing phase
   */
	
  /* compute the trace of the original matrix G */
  c1 = 0.0;
  for (i = 0; i < n; i++)
  {
    c1 += G[i][i];
  }
  /* decompose the matrix G in the form L^T L */
  cholesky_decomposition(G);
#ifdef TRACE_SOLVER
  print_matrix("G", G);
#endif
  /* initialize the matrix R */
  for (i = 0; i < n; i++)
  {
    d[i] = 0.0;
    for (j = 0; j < n; j++)
      R[i][j] = 0.0;
  }
  R_norm = 1.0; /* this variable will hold the norm of the matrix R */
  
  /* compute the inverse of the factorized matrix G^-1, this is the initial value for H */
  c2 = 0.0;
  for (i = 0; i < n; i++) 
  {
    d[i] = 1.0;
    forward_elimination(G, z, d);
    for (j = 0; j < n; j++)
      J[i][j] = z[j];
    c2 += z[i];
    d[i] = 0.0;
  }
#ifdef TRACE_SOLVER
  print_matrix("J", J);
#endif
  
  /* c1 * c2 is an estimate for cond(G) */
  
  /* 
    * Find the unconstrained minimizer of the quadratic form 0.5 * x G x + g0 x 
   * this is a feasible point in the dual space
   * x = G^-1 * g0
   */
  cholesky_solve(G, x, g0);
  for (i = 0; i < n; i++)
    x[i] = -x[i];
  /* and compute the current solution value */ 
  f_value = 0.5 * scalar_product(g0, x);
#ifdef TRACE_SOLVER
  std::cout << "Unconstrained solution: " << f_value << std::endl;
  print_vector("x", x);
#endif
  
  /* Add equality constraints to the working set A */
  iq = 0;
  for (i = 0; i < p; i++)
  {
    for (j = 0; j < n; j++)
      np[j] = CE[j][i];
    compute_d(d, J, np);
    update_z(z, J, d, iq);
    update_r(R, r, d, iq);
#ifdef TRACE_SOLVER
    print_matrix("R", R, n, iq);
    print_vector("z", z);
    print_vector("r", r, iq);
    print_vector("d", d);
#endif
    
    /* compute full step length t2: i.e., the minimum step in primal space s.t. the contraint 
      becomes feasible */
    t2 = 0.0;
    if (fabs(scalar_product(z, z)) > std::numeric_limits<double>::epsilon()) // i.e. z != 0
      t2 = (-scalar_product(np, x) - ce0[i]) / scalar_product(z, np);
    
    /* set x = x + t2 * z */
    for (k = 0; k < n; k++)
      x[k] += t2 * z[k];
    
    /* set u = u+ */
    u[iq] = t2;
    for (k = 0; k < iq; k++)
      u[k] -= t2 * r[k];
    
    /* compute the new solution value */
    f_value += 0.5 * (t2 * t2) * scalar_product(z, np);
    A[i] = -i - 1;
    
    if (!add_constraint(R, J, d, iq, R_norm))
    {	  
      // Equality constraints are linearly dependent
      throw std::runtime_error("Constraints are linearly dependent");
      return f_value;
    }
  }
  
  /* set iai = K \ A */
  for (i = 0; i < m; i++)
    iai[i] = i;
  
l1:	iter++;
#ifdef TRACE_SOLVER
  print_vector("x", x);
#endif
  /* step 1: choose a violated constraint */
  for (i = p; i < iq; i++)
  {
    ip = A[i];
    iai[ip] = -1;
  }
	
  /* compute s[x] = ci^T * x + ci0 for all elements of K \ A */
  ss = 0.0;
  psi = 0.0; /* this value will contain the sum of all infeasibilities */
  ip = 0; /* ip will be the index of the chosen violated constraint */
  for (i = 0; i < m; i++)
  {
    iaexcl[i] = true;
    sum = 0.0;
    for (j = 0; j < n; j++)
      sum += CI[j][i] * x[j];
    sum += ci0[i];
    s[i] = sum;
    psi += std::min(0.0, sum);
  }
#ifdef TRACE_SOLVER
  print_vector("s", s, m);
#endif
  
  
  if (fabs(psi) <= m * std::numeric_limits<double>::epsilon() * c1 * c2* 100.0)
  {
    /* numerically there are not infeasibilities anymore */
    q = iq;
    
    return f_value;
  }
  
  /* save old values for u and A */
  for (i = 0; i < iq; i++)
  {
    u_old[i] = u[i];
    A_old[i] = A[i];
  }
  /* and for x */
  for (i = 0; i < n; i++)
    x_old[i] = x[i];
  
l2: /* Step 2: check for feasibility and determine a new S-pair */
    for (i = 0; i < m; i++)
    {
      if (s[i] < ss && iai[i] != -1 && iaexcl[i])
      {
        ss = s[i];
        ip = i;
      }
    }
  if (ss >= 0.0)
  {
    q = iq;
    
    return f_value;
  }
  
  /* set np = n[ip] */
  for (i = 0; i < n; i++)
    np[i] = CI[i][ip];
  /* set u = [u 0]^T */
  u[iq] = 0.0;
  /* add ip to the active set A */
  A[iq] = ip;
  
#ifdef TRACE_SOLVER
  std::cout << "Trying with constraint " << ip << std::endl;
  print_vector("np", np);
#endif
  
l2a:/* Step 2a: determine step direction */
    /* compute z = H np: the step direction in the primal space (through J, see the paper) */
    compute_d(d, J, np);
  update_z(z, J, d, iq);
  /* compute N* np (if q > 0): the negative of the step direction in the dual space */
  update_r(R, r, d, iq);
#ifdef TRACE_SOLVER
  std::cout << "Step direction z" << std::endl;
  print_vector("z", z);
  print_vector("r", r, iq + 1);
  print_vector("u", u, iq + 1);
  print_vector("d", d);
  print_vector("A", A, iq + 1);
#endif
  
  /* Step 2b: compute step length */
  l = 0;
  /* Compute t1: partial step length (maximum step in dual space without violating dual feasibility */
  t1 = inf; /* +inf */
  /* find the index l s.t. it reaches the minimum of u+[x] / r */
  for (k = p; k < iq; k++)
  {
    if (r[k] > 0.0)
    {
      if (u[k] / r[k] < t1)
	    {
	      t1 = u[k] / r[k];
	      l = A[k];
	    }
    }
  }
  /* Compute t2: full step length (minimum step in primal space such that the constraint ip becomes feasible */
  if (fabs(scalar_product(z, z))  > std::numeric_limits<double>::epsilon()) // i.e. z != 0
    t2 = -s[ip] / scalar_product(z, np);
  else
    t2 = inf; /* +inf */
  
  /* the step is chosen as the minimum of t1 and t2 */
  t = std::min(t1, t2);
#ifdef TRACE_SOLVER
  std::cout << "Step sizes: " << t << " (t1 = " << t1 << ", t2 = " << t2 << ") ";
#endif
  
  /* Step 2c: determine new S-pair and take step: */
  
  /* case (i): no step in primal or dual space */
  if (t >= inf)
  {
    /* QPP is infeasible */
    // FIXME: unbounded to raise
    q = iq;
    return inf;
  }
  /* case (ii): step in dual space */
  if (t2 >= inf)
  {
    /* set u = u +  t * [-r 1] and drop constraint l from the active set A */
    for (k = 0; k < iq; k++)
      u[k] -= t * r[k];
    u[iq] += t;
    iai[l] = l;
    delete_constraint(R, J, A, u, n, p, iq, l);
#ifdef TRACE_SOLVER
    std::cout << " in dual space: " 
      << f_value << std::endl;
    print_vector("x", x);
    print_vector("z", z);
    print_vector("A", A, iq + 1);
#endif
    goto l2a;
  }
  
  /* case (iii): step in primal and dual space */
  
  /* set x = x + t * z */
  for (k = 0; k < n; k++)
    x[k] += t * z[k];
  /* update the solution value */
  f_value += t * scalar_product(z, np) * (0.5 * t + u[iq]);
  /* u = u + t * [-r 1] */
  for (k = 0; k < iq; k++)
    u[k] -= t * r[k];
  u[iq] += t;
#ifdef TRACE_SOLVER
  std::cout << " in both spaces: " 
    << f_value << std::endl;
  print_vector("x", x);
  print_vector("u", u, iq + 1);
  print_vector("r", r, iq + 1);
  print_vector("A", A, iq + 1);
#endif
  
  if (fabs(t - t2) < std::numeric_limits<double>::epsilon())
  {
#ifdef TRACE_SOLVER
    std::cout << "Full step has taken " << t << std::endl;
    print_vector("x", x);
#endif
    /* full step has taken */
    /* add constraint ip to the active set*/
    if (!add_constraint(R, J, d, iq, R_norm))
    {
      iaexcl[ip] = false;
      delete_constraint(R, J, A, u, n, p, iq, ip);
#ifdef TRACE_SOLVER
      print_matrix("R", R);
      print_vector("A", A, iq);
			print_vector("iai", iai);
#endif
      for (i = 0; i < m; i++)
        iai[i] = i;
      for (i = p; i < iq; i++)
	    {
	      A[i] = A_old[i];
	      u[i] = u_old[i];
				iai[A[i]] = -1;
	    }
      for (i = 0; i < n; i++)
        x[i] = x_old[i];
      goto l2; /* go to step 2 */
    }    
    else
      iai[ip] = -1;
#ifdef TRACE_SOLVER
    print_matrix("R", R);
    print_vector("A", A, iq);
		print_vector("iai", iai);
#endif
    goto l1;
  }
  
  /* a patial step has taken */
#ifdef TRACE_SOLVER
  std::cout << "Partial step has taken " << t << std::endl;
  print_vector("x", x);
#endif
  /* drop constraint l */
  iai[l] = l;
  delete_constraint(R, J, A, u, n, p, iq, l);
#ifdef TRACE_SOLVER
  print_matrix("R", R);
  print_vector("A", A, iq);
#endif
  
  /* update s[ip] = CI * x + ci0 */
  sum = 0.0;
  for (k = 0; k < n; k++)
    sum += CI[k][ip] * x[k];
  s[ip] = sum + ci0[ip];
  
#ifdef TRACE_SOLVER
  print_vector("s", s, m);
#endif
  goto l2a;
}
Пример #4
0
void mover( Matrix& x, Matrix& v, int npart, double L,
		    double mpv, double vwall, double tau,
			Matrix& strikes, Matrix& delv, long& seed ) {

// mover - Function to move particles by free flight
//         Also handles collisions with walls
// Inputs
//    x        Positions of the particles
//    v        Velocities of the particles
//    npart    Number of particles in the system
//    L        System length
//    mpv      Most probable velocity off the wall
//    vwall    Wall velocities
//    tau      Time step
//    seed     Random number seed
// Outputs
//    x,v      Updated positions and velocities
//    strikes  Number of particles striking each wall
//    delv     Change of y-velocity at each wall     
//    seed     Random number seed

  //* Move all particles pretending walls are absent
  Matrix x_old(npart);
  x_old = x;            // Remember original position
  int i;
  for( i=1; i<= npart; i++ )
    x(i) = x_old(i) + v(i,1)*tau;  

  //* Check each particle to see if it strikes a wall
  strikes.set(0.0);   delv.set(0.0);
  Matrix xwall(2), vw(2), direction(2);
  xwall(1) = 0;    xwall(2) = L;   // Positions of walls
  vw(1) = -vwall;  vw(2) = vwall;  // Velocities of walls
  double stdev = mpv/sqrt(2.);
  // Direction of particle leaving wall
  direction(1) = 1;  direction(2) = -1;
  for( i=1; i<=npart; i++ ) {

    //* Test if particle strikes either wall
	int flag = 0;
    if( x(i) <= 0 )
      flag=1;       // Particle strikes left wall
    else if( x(i) >= L )
      flag=2;       // Particle strikes right wall

    //* If particle strikes a wall, reset its position
    //  and velocity. Record velocity change.
    if( flag > 0 )	{
      strikes(flag)++;
      double vyInitial = v(i,2);
      //* Reset velocity components as biased Maxwellian,
      //  Exponential dist. in x; Gaussian in y and z
      v(i,1) = direction(flag)*sqrt(-log(1.-rand(seed))) * mpv;
      v(i,2) = stdev*randn(seed) + vw(flag); // Add wall velocity
      v(i,3) = stdev*randn(seed);
      // Time of flight after leaving wall
      double dtr = tau*(x(i)-xwall(flag))/(x(i)-x_old(i));   
      //* Reset position after leaving wall
      x(i) = xwall(flag) + v(i,1)*dtr;
      //* Record velocity change for force measurement
      delv(flag) += (v(i,2) - vyInitial);
    }
  }
}
Пример #5
0
void TV::IterativeReconstruction(CVector &data_gpu, CVector &x, CVector &b1_gpu)
{
  unsigned N = width * height * frames;

  ComputeTimeSpaceWeights(params.timeSpaceWeight, params.ds, params.dt);
  Log("Setting ds: %.3e, dt: %.3e\n", params.ds, params.dt);
  Log("Setting Primal-Dual Gap of %.3e  as stopping criterion \n", params.stopPDGap);

  // primal
  CVector x_old(N);
  CVector ext(N);

  agile::copy(x, ext);

  // dual
  std::vector<CVector> y;
  y.push_back(CVector(N));
  y.push_back(CVector(N));
  y.push_back(CVector(N));
  y[0].assign(N, 0);
  y[1].assign(N, 0);
  y[2].assign(N, 0);

  std::vector<CVector> tempGradient;
  tempGradient.push_back(CVector(N));
  tempGradient.push_back(CVector(N));
  tempGradient.push_back(CVector(N));

  CVector z(data_gpu.size());
  zTemp.resize(data_gpu.size(), 0.0);
  z.assign(z.size(), 0.0);

  CVector norm(N);

  unsigned loopCnt = 0; 
  // loop 
  Log("Starting iteration\n"); 
  while ( loopCnt < params.maxIt )
  {
    // dual ascent step
    utils::Gradient(ext, tempGradient, width, height, params.ds, params.ds,
                    params.dt);
    agile::addScaledVector(y[0], params.sigma, tempGradient[0], y[0]);
    agile::addScaledVector(y[1], params.sigma, tempGradient[1], y[1]);
    agile::addScaledVector(y[2], params.sigma, tempGradient[2], y[2]);

    mrOp->BackwardOperation(ext, zTemp, b1_gpu);
    agile::addScaledVector(z, params.sigma, zTemp, z);

    // Proximal mapping
    utils::ProximalMap3(y, 1.0);

    agile::subScaledVector(z, params.sigma, data_gpu, z);
    agile::scale((float)(1.0 / (1.0 + params.sigma / params.lambda)), z, z);
    // primal descent
    mrOp->ForwardOperation(z, imgTemp, b1_gpu);
    utils::Divergence(y, divTemp, width, height, frames, params.ds, params.ds,
                      params.dt);
    agile::subVector(imgTemp, divTemp, divTemp);
    agile::subScaledVector(x, params.tau, divTemp, ext);

    // save x_n+1
    agile::copy(ext, x_old);

    // extra gradient
    agile::scale(2.0f, ext, ext);
    agile::subVector(ext, x, ext);

    // x_n = x_n+1
    agile::copy(x_old, x);

    // adapt step size
    if (loopCnt < 10 || (loopCnt % 50 == 0))
    {
      CVector temp(N);
      agile::subVector(ext, x, temp);
      AdaptStepSize(temp, b1_gpu);
    }
    
    // compute PD Gap (export,verbose,stopping)
    if ( (verbose && (loopCnt < 10 || (loopCnt % 50 == 0)) ) ||
         ((debug) && (loopCnt % debugstep == 0)) || 
         ((params.stopPDGap > 0) && (loopCnt % 20 == 0)) )
    {
      RType pdGap =
            ComputePDGap(x, y, z, data_gpu, b1_gpu);
      pdGap=pdGap/N;
 
      pdGapExport.push_back( pdGap );
      Log("Normalized Primal-Dual Gap after %d iterations: %.4e\n", loopCnt, pdGap);     
      
      if ( pdGap < params.stopPDGap )
        return;
    }

    loopCnt++;
    if (loopCnt % 10 == 0)
      std::cout << "." << std::flush;
  }
  std::cout << std::endl;
}
Пример #6
0
inline double solve_quadprog(MatrixXd & G,  VectorXd & g0,  
                      const MatrixXd & CE, const VectorXd & ce0,  
                      const MatrixXd & CI, const VectorXd & ci0, 
                      VectorXd& x)
{
  int i, j, k, l; /* indices */
  int ip, me, mi;
  int n=g0.size();  int p=ce0.size();  int m=ci0.size();  
  MatrixXd R(G.rows(),G.cols()), J(G.rows(),G.cols());
  
  LLT<MatrixXd,Lower> chol(G.cols());
 
  VectorXd s(m+p), z(n), r(m + p), d(n),  np(n), u(m + p);
  VectorXd x_old(n), u_old(m + p);
  double f_value, psi, c1, c2, sum, ss, R_norm;
  const double inf = std::numeric_limits<double>::infinity();
  double t, t1, t2; /* t is the step length, which is the minimum of the partial step length t1 
    * and the full step length t2 */
  VectorXi A(m + p), A_old(m + p), iai(m + p);
  int q;
  int iq, iter = 0;
  bool iaexcl[m + p];
 	
  me = p; /* number of equality constraints */
  mi = m; /* number of inequality constraints */
  q = 0;  /* size of the active set A (containing the indices of the active constraints) */
  
  /*
   * Preprocessing phase
   */
	
  /* compute the trace of the original matrix G */
  c1 = G.trace();
	
	/* decompose the matrix G in the form LL^T */
  chol.compute(G);
 
  /* initialize the matrix R */
  d.setZero();
  R.setZero();
	R_norm = 1.0; /* this variable will hold the norm of the matrix R */
  
	/* compute the inverse of the factorized matrix G^-1, this is the initial value for H */
  // J = L^-T
  J.setIdentity();
  J = chol.matrixU().solve(J);
	c2 = J.trace();
#ifdef TRACE_SOLVER
 print_matrix("J", J, n);
#endif
  
	/* c1 * c2 is an estimate for cond(G) */
  
	/* 
   * Find the unconstrained minimizer of the quadratic form 0.5 * x G x + g0 x 
   * this is a feasible point in the dual space
	 * x = G^-1 * g0
   */
  x = chol.solve(g0);
  x = -x;
	/* and compute the current solution value */ 
	f_value = 0.5 * g0.dot(x);
#ifdef TRACE_SOLVER
  std::cerr << "Unconstrained solution: " << f_value << std::endl;
  print_vector("x", x, n);
#endif
  
	/* Add equality constraints to the working set A */
  iq = 0;
	for (i = 0; i < me; i++)
	{
    np = CE.col(i);
    compute_d(d, J, np);
		update_z(z, J, d,  iq);
		update_r(R, r, d,  iq);
#ifdef TRACE_SOLVER
		print_matrix("R", R, iq);
		print_vector("z", z, n);
		print_vector("r", r, iq);
		print_vector("d", d, n);
#endif
    
    /* compute full step length t2: i.e., the minimum step in primal space s.t. the contraint 
      becomes feasible */
    t2 = 0.0;
    if (internal::abs(z.dot(z)) > std::numeric_limits<double>::epsilon()) // i.e. z != 0
      t2 = (-np.dot(x) - ce0(i)) / z.dot(np);
    
    x += t2 * z;

    /* set u = u+ */
    u(iq) = t2;
    u.head(iq) -= t2 * r.head(iq);
    
    /* compute the new solution value */
    f_value += 0.5 * (t2 * t2) * z.dot(np);
    A(i) = -i - 1;
    
    if (!add_constraint(R, J, d, iq, R_norm))
    {
      // FIXME: it should raise an error
      // Equality constraints are linearly dependent
      return f_value;
    }
  }
  
	/* set iai = K \ A */
	for (i = 0; i < mi; i++)
		iai(i) = i;
  
l1:	iter++;
#ifdef TRACE_SOLVER
  print_vector("x", x, n);
#endif
  /* step 1: choose a violated constraint */
	for (i = me; i < iq; i++)
	{
	  ip = A(i);
		iai(ip) = -1;
	}
	
	/* compute s(x) = ci^T * x + ci0 for all elements of K \ A */
	ss = 0.0;
	psi = 0.0; /* this value will contain the sum of all infeasibilities */
	ip = 0; /* ip will be the index of the chosen violated constraint */
	for (i = 0; i < mi; i++)
	{
		iaexcl[i] = true;
		sum = CI.col(i).dot(x) + ci0(i);
		s(i) = sum;
		psi += std::min(0.0, sum);
	}
#ifdef TRACE_SOLVER
  print_vector("s", s, mi);
#endif

    
	if (internal::abs(psi) <= mi * std::numeric_limits<double>::epsilon() * c1 * c2* 100.0)
	{
    /* numerically there are not infeasibilities anymore */
    q = iq;
		return f_value;
  }
    
  /* save old values for u, x and A */
   u_old.head(iq) = u.head(iq);
   A_old.head(iq) = A.head(iq);
   x_old = x;
    
l2: /* Step 2: check for feasibility and determine a new S-pair */
	for (i = 0; i < mi; i++)
	{
		if (s(i) < ss && iai(i) != -1 && iaexcl[i])
		{
			ss = s(i);
			ip = i;
		}
	}
  if (ss >= 0.0)
  {
    q = iq;
    return f_value;
  }
    
  /* set np = n(ip) */
  np = CI.col(ip);
  /* set u = (u 0)^T */
  u(iq) = 0.0;
  /* add ip to the active set A */
  A(iq) = ip;

#ifdef TRACE_SOLVER
	std::cerr << "Trying with constraint " << ip << std::endl;
	print_vector("np", np, n);
#endif
    
l2a:/* Step 2a: determine step direction */
  /* compute z = H np: the step direction in the primal space (through J, see the paper) */
  compute_d(d, J, np);
  update_z(z, J, d, iq);
  /* compute N* np (if q > 0): the negative of the step direction in the dual space */
  update_r(R, r, d, iq);
#ifdef TRACE_SOLVER
  std::cerr << "Step direction z" << std::endl;
		print_vector("z", z, n);
		print_vector("r", r, iq + 1);
    print_vector("u", u, iq + 1);
    print_vector("d", d, n);
    print_ivector("A", A, iq + 1);
#endif
    
  /* Step 2b: compute step length */
  l = 0;
  /* Compute t1: partial step length (maximum step in dual space without violating dual feasibility */
  t1 = inf; /* +inf */
  /* find the index l s.t. it reaches the minimum of u+(x) / r */
  for (k = me; k < iq; k++)
  {
    double tmp;
    if (r(k) > 0.0 && ((tmp = u(k) / r(k)) < t1) )
    {
      t1 = tmp;
      l = A(k);
    }
  }
  /* Compute t2: full step length (minimum step in primal space such that the constraint ip becomes feasible */
  if (internal::abs(z.dot(z))  > std::numeric_limits<double>::epsilon()) // i.e. z != 0
    t2 = -s(ip) / z.dot(np);
  else
    t2 = inf; /* +inf */

  /* the step is chosen as the minimum of t1 and t2 */
  t = std::min(t1, t2);
#ifdef TRACE_SOLVER
  std::cerr << "Step sizes: " << t << " (t1 = " << t1 << ", t2 = " << t2 << ") ";
#endif
  
  /* Step 2c: determine new S-pair and take step: */
  
  /* case (i): no step in primal or dual space */
  if (t >= inf)
  {
    /* QPP is infeasible */
    // FIXME: unbounded to raise
    q = iq;
    return inf;
  }
  /* case (ii): step in dual space */
  if (t2 >= inf)
  {
    /* set u = u +  t * [-r 1) and drop constraint l from the active set A */
    u.head(iq) -= t * r.head(iq);
    u(iq) += t;
    iai(l) = l;
    delete_constraint(R, J, A, u, p, iq, l);
#ifdef TRACE_SOLVER
    std::cerr << " in dual space: " 
      << f_value << std::endl;
    print_vector("x", x, n);
    print_vector("z", z, n);
		print_ivector("A", A, iq + 1);
#endif
    goto l2a;
  }
  
  /* case (iii): step in primal and dual space */
  
  x += t * z;
  /* update the solution value */
  f_value += t * z.dot(np) * (0.5 * t + u(iq));
  
  u.head(iq) -= t * r.head(iq);
  u(iq) += t;
#ifdef TRACE_SOLVER
  std::cerr << " in both spaces: " 
    << f_value << std::endl;
	print_vector("x", x, n);
	print_vector("u", u, iq + 1);
	print_vector("r", r, iq + 1);
	print_ivector("A", A, iq + 1);
#endif
  
  if (t == t2)
  {
#ifdef TRACE_SOLVER
    std::cerr << "Full step has taken " << t << std::endl;
    print_vector("x", x, n);
#endif
    /* full step has taken */
    /* add constraint ip to the active set*/
		if (!add_constraint(R, J, d, iq, R_norm))
		{
			iaexcl[ip] = false;
			delete_constraint(R, J, A, u, p, iq, ip);
#ifdef TRACE_SOLVER
      print_matrix("R", R, n);
      print_ivector("A", A, iq);
#endif
			for (i = 0; i < m; i++)
				iai(i) = i;
			for (i = 0; i < iq; i++)
			{
				A(i) = A_old(i);
				iai(A(i)) = -1;
				u(i) = u_old(i);
			}
			x = x_old;
      goto l2; /* go to step 2 */
		}    
    else
      iai(ip) = -1;
#ifdef TRACE_SOLVER
    print_matrix("R", R, n);
    print_ivector("A", A, iq);
#endif
    goto l1;
  }
  
  /* a patial step has taken */
#ifdef TRACE_SOLVER
  std::cerr << "Partial step has taken " << t << std::endl;
  print_vector("x", x, n);
#endif
  /* drop constraint l */
	iai(l) = l;
	delete_constraint(R, J, A, u, p, iq, l);
#ifdef TRACE_SOLVER
  print_matrix("R", R, n);
  print_ivector("A", A, iq);
#endif
  
  s(ip) = CI.col(ip).dot(x) + ci0(ip);

#ifdef TRACE_SOLVER
  print_vector("s", s, mi);
#endif
  goto l2a;
}