24 m_J.setZero(nVars, nVars);
26 R.resize(nVars, nVars);
28 r.resize(nIneqCon + nEqCon);
29 u.resize(nIneqCon + nEqCon);
33 A.resize(nIneqCon + nEqCon);
37 u_old.resize(nIneqCon + nEqCon);
38 A_old.resize(nIneqCon + nEqCon);
40 #ifdef OPTIMIZE_ADD_CONSTRAINT
46 size_t &iq,
double &R_norm) {
47 size_t nVars = J.rows();
48 #ifdef EIQGUADPROG_TRACE_SOLVER
49 std::cerr <<
"Add constraint " << iq <<
'/';
52 double cc, ss, h, t1, t2, xny;
54 #ifdef OPTIMIZE_ADD_CONSTRAINT
55 Eigen::Vector2d cc_ss;
62 for (j =
d.size() - 1; j >= iq + 1; j--) {
72 h = utils::distance(cc, ss);
73 if (h == 0.0)
continue;
83 xny = ss / (1.0 + cc);
86 #ifdef OPTIMIZE_ADD_CONSTRAINT // the optimized code is actually slower than
91 J.col(j - 1).noalias() = J.middleCols<2>(j - 1) * cc_ss;
92 J.col(j) = xny * (T1 + J.col(j - 1)) - J.col(j);
95 for (k = 0; k < nVars; k++) {
98 J(k, j - 1) = t1 * cc + t2 * ss;
99 J(k, j) = xny * (t1 + J(k, j - 1)) - t2;
108 R.col(iq - 1).head(iq) =
d.head(iq);
109 #ifdef EIQGUADPROG_TRACE_SOLVER
110 std::cerr << iq << std::endl;
113 if (std::abs(
d(iq - 1)) <= std::numeric_limits<double>::epsilon() * R_norm)
116 R_norm = std::max<double>(R_norm, std::abs(
d(iq - 1)));
121 VectorXd &u,
size_t nEqCon,
size_t &iq,
123 size_t nVars =
R.rows();
124 #ifdef EIQGUADPROG_TRACE_SOLVER
125 std::cerr <<
"Delete constraint " << l <<
' ' << iq;
129 double cc, ss, h, xny, t1, t2;
132 for (i = nEqCon; i < iq; i++)
133 if (
A(i) ==
static_cast<VectorXi::Scalar
>(l)) {
139 for (i = qq; i < iq - 1; i++) {
142 R.col(i) =
R.col(i + 1);
149 for (j = 0; j < iq; j++)
R(j, iq - 1) = 0.0;
152 #ifdef EIQGUADPROG_TRACE_SOLVER
153 std::cerr <<
'/' << iq << std::endl;
158 for (j = qq; j < iq; j++) {
161 h = utils::distance(cc, ss);
162 if (h == 0.0)
continue;
173 xny = ss / (1.0 + cc);
174 for (k = j + 1; k < iq; k++) {
177 R(j, k) = t1 * cc + t2 * ss;
178 R(j + 1, k) = xny * (t1 +
R(j, k)) - t2;
180 for (k = 0; k < nVars; k++) {
183 J(k, j) = t1 * cc + t2 * ss;
184 J(k, j + 1) = xny * (J(k, j) + t1) - t2;
192 const size_t nVars = g0.size();
193 const size_t nEqCon = ce0.size();
194 const size_t nIneqCon = ci0.size();
197 reset(nVars, nEqCon, nIneqCon);
199 assert(
static_cast<size_t>(Hess.rows()) ==
m_nVars &&
200 static_cast<size_t>(Hess.cols()) ==
m_nVars);
201 assert(
static_cast<size_t>(g0.size()) ==
m_nVars);
202 assert(
static_cast<size_t>(CE.rows()) ==
m_nEqCon &&
203 static_cast<size_t>(CE.cols()) ==
m_nVars);
204 assert(
static_cast<size_t>(ce0.size()) ==
m_nEqCon);
205 assert(
static_cast<size_t>(CI.rows()) ==
m_nIneqCon &&
206 static_cast<size_t>(CI.cols()) ==
m_nVars);
207 assert(
static_cast<size_t>(ci0.size()) ==
m_nIneqCon);
217 const double inf = std::numeric_limits<double>::infinity();
239 R.setZero(nVars, nVars);
247 m_J.setIdentity(nVars, nVars);
248 #ifdef OPTIMIZE_HESSIAN_INVERSE
257 #ifdef EIQGUADPROG_TRACE_SOLVER
258 utils::print_matrix(
"m_J",
m_J);
271 x =
m_J * (
m_J.transpose() * g0);
273 #ifdef OPTIMIZE_UNCONSTR_MINIM
275 chol_.solveInPlace(x);
283 f_value = 0.5 * g0.dot(x);
284 #ifdef EIQGUADPROG_TRACE_SOLVER
285 std::cerr <<
"Unconstrained solution: " << f_value << std::endl;
286 utils::print_vector(
"x", x);
294 for (i = 0; i < nEqCon; i++) {
301 #ifdef EIQGUADPROG_TRACE_SOLVER
302 utils::print_matrix(
"R", R);
303 utils::print_vector(
"z", z);
304 utils::print_vector(
"r", r);
305 utils::print_vector(
"d", d);
312 if (std::abs(z.dot(z)) > std::numeric_limits<double>::epsilon())
314 t2 = (-np.dot(x) - ce0(i)) / z.dot(np);
320 u.head(iq) -= t2 * r.head(iq);
323 f_value += 0.5 * (t2 * t2) * z.dot(np);
324 A(i) =
static_cast<VectorXi::Scalar
>(-i - 1);
337 for (i = 0; i < nIneqCon; i++) iai(i) = static_cast<VectorXi::Scalar>(i);
339 #ifdef USE_WARM_START
342 for (i = nEqCon; i < q; i++) {
343 iai(i - nEqCon) = -1;
354 if (std::abs(z.dot(z)) >
355 std::numeric_limits<double>::epsilon())
356 t2 = (-np.dot(x) - ci0(ip)) / z.dot(np);
364 u.head(iq) -= t2 * r.head(iq);
367 f_value += 0.5 * (t2 * t2) * z.dot(np);
371 std::cerr <<
"[WARM START] Constraints are linearly dependent\n";
381 if (iter >= m_maxIter) {
388 #ifdef EIQGUADPROG_TRACE_SOLVER
389 utils::print_vector(
"x", x);
392 for (i = nEqCon; i < iq; i++) {
402 #ifdef OPTIMIZE_STEP_1_2
404 s.noalias() += CI * x;
406 psi = (s.cwiseMin(VectorXd::Zero(nIneqCon))).sum();
409 for (i = 0; i < nIneqCon; i++) {
411 s(i) = CI.row(i).dot(x) + ci0(i);
412 psi += std::min(0.0, s(i));
416 #ifdef EIQGUADPROG_TRACE_SOLVER
417 utils::print_vector(
"s", s);
422 if (std::abs(psi) <=
static_cast<double>(nIneqCon) *
423 std::numeric_limits<double>::epsilon() * c1 * c2 *
433 u_old.head(iq) = u.head(iq);
434 A_old.head(iq) = A.head(iq);
441 for (i = 0; i < nIneqCon; i++) {
442 if (s(i) < ss && iai(i) != -1 && iaexcl(i)) {
458 A(iq) =
static_cast<VectorXi::Scalar
>(ip);
462 #ifdef EIQGUADPROG_TRACE_SOLVER
463 std::cerr <<
"Trying with constraint " << ip << std::endl;
464 utils::print_vector(
"np", np);
483 #ifdef EIQGUADPROG_TRACE_SOLVER
484 std::cerr <<
"Step direction z" << std::endl;
485 utils::print_vector(
"z", z);
486 utils::print_vector(
"r", r);
487 utils::print_vector(
"u", u);
488 utils::print_vector(
"d", d);
489 utils::print_vector(
"A", A);
501 for (k = nEqCon; k < iq; k++) {
503 if (r(k) > 0.0 && ((tmp = u(k) / r(k)) < t1)) {
510 if (std::abs(z.dot(z)) > std::numeric_limits<double>::epsilon())
512 t2 = -s(ip) / z.dot(np);
517 t = std::min(t1, t2);
518 #ifdef EIQGUADPROG_TRACE_SOLVER
519 std::cerr <<
"Step sizes: " << t <<
" (t1 = " << t1 <<
", t2 = " << t2
536 u.head(iq) -= t * r.head(iq);
538 iai(l) =
static_cast<VectorXi::Scalar
>(l);
540 #ifdef EIQGUADPROG_TRACE_SOLVER
541 std::cerr <<
" in dual space: " << f_value << std::endl;
542 utils::print_vector(
"x", x);
543 utils::print_vector(
"z", z);
544 utils::print_vector(
"A", A);
553 f_value += t * z.dot(np) * (0.5 * t + u(iq));
555 u.head(iq) -= t * r.head(iq);
558 #ifdef EIQGUADPROG_TRACE_SOLVER
559 std::cerr <<
" in both spaces: " << f_value << std::endl;
560 utils::print_vector(
"x", x);
561 utils::print_vector(
"u", u);
562 utils::print_vector(
"r", r);
563 utils::print_vector(
"A", A);
567 #ifdef EIQGUADPROG_TRACE_SOLVER
568 std::cerr <<
"Full step has taken " << t << std::endl;
569 utils::print_vector(
"x", x);
576 #ifdef EIQGUADPROG_TRACE_SOLVER
577 utils::print_matrix(
"R", R);
578 utils::print_vector(
"A", A);
580 for (i = 0; i < nIneqCon; i++) iai(i) = static_cast<VectorXi::Scalar>(i);
581 for (i = 0; i < iq; i++) {
591 #ifdef EIQGUADPROG_TRACE_SOLVER
592 utils::print_matrix(
"R", R);
593 utils::print_vector(
"A", A);
600 iai(l) =
static_cast<VectorXi::Scalar
>(l);
602 s(ip) = CI.row(ip).dot(x) + ci0(ip);
604 #ifdef EIQGUADPROG_TRACE_SOLVER
605 std::cerr <<
"Partial step has taken " << t << std::endl;
606 utils::print_vector(
"x", x);
607 utils::print_matrix(
"R", R);
608 utils::print_vector(
"A", A);
609 utils::print_vector(
"s", s);