30 #ifndef EXOTICA_CORE_BOX_QP_OLD_H_
31 #define EXOTICA_CORE_BOX_QP_OLD_H_
33 #include <Eigen/Dense>
41 const Eigen::VectorXd& b_low,
const Eigen::VectorXd& b_high,
42 const Eigen::VectorXd& x_init,
const double gamma,
43 const int max_iterations,
const double epsilon,
const double lambda,
44 bool use_polynomial_linesearch =
false,
45 bool use_cholesky_factorization =
false)
48 Eigen::VectorXd delta_xf, x = x_init;
49 std::vector<size_t> clamped_idx, free_idx;
50 Eigen::VectorXd grad = q + H * x_init;
51 Eigen::MatrixXd Hff, Hfc, Hff_inv;
53 std::vector<double> alphas_;
54 const std::size_t& n_alphas_ = 10;
55 alphas_.resize(n_alphas_);
56 const Eigen::VectorXd alphas_linear = Eigen::VectorXd::LinSpaced(10, 1.0, 0.1);
57 for (std::size_t n = 0; n < n_alphas_; ++n)
59 if (use_polynomial_linesearch)
61 alphas_[n] = 1. / pow(2.,
static_cast<double>(n));
65 alphas_[n] = alphas_linear(n);
70 for (
int i = 0; i < x.size(); ++i)
72 x(i) = std::max(std::min(x_init(i), b_high(i)), b_low(i));
75 if (use_cholesky_factorization)
77 Hff_inv = (Eigen::MatrixXd::Identity(H.rows(), H.cols()) * lambda + H).llt().solve(Eigen::MatrixXd::Identity(H.rows(), H.cols()));
81 Hff_inv = (Eigen::MatrixXd::Identity(H.rows(), H.cols()) * lambda + H).inverse();
84 if (grad.norm() <= epsilon)
86 for (
int i = 0; i < x.size(); ++i) free_idx.push_back(i);
87 return {Hff_inv, x_init, free_idx, clamped_idx};
90 while (grad.norm() > epsilon && it < max_iterations)
97 for (
int i = 0; i < grad.size(); ++i)
99 if ((x(i) == b_low(i) && grad(i) > 0) || (x(i) == b_high(i) && grad(i) < 0))
100 clamped_idx.push_back(i);
102 free_idx.push_back(i);
105 if (free_idx.size() == 0)
108 Hff.resize(free_idx.size(), free_idx.size());
109 Hfc.resize(free_idx.size(), clamped_idx.size());
111 if (clamped_idx.size() == 0)
115 for (
size_t i = 0; i < free_idx.size(); ++i)
116 for (
size_t j = 0; j < free_idx.size(); ++j)
117 Hff(i, j) = H(free_idx[i], free_idx[j]);
119 for (
size_t i = 0; i < free_idx.size(); ++i)
120 for (
size_t j = 0; j < clamped_idx.size(); ++j)
121 Hfc(i, j) = H(free_idx[i], clamped_idx[j]);
125 Eigen::VectorXd q_free(free_idx.size()), x_free(free_idx.size()), x_clamped(clamped_idx.size());
126 for (
size_t i = 0; i < free_idx.size(); ++i)
128 q_free(i) = q(free_idx[i]);
129 x_free(i) = x(free_idx[i]);
132 for (
size_t j = 0; j < clamped_idx.size(); ++j)
133 x_clamped(j) = x(clamped_idx[j]);
136 Hff.diagonal().array() += lambda;
137 if (use_cholesky_factorization)
139 Hff_inv = Hff.llt().solve(Eigen::MatrixXd::Identity(Hff.rows(), Hff.cols()));
143 Hff_inv = Hff.inverse();
146 if (clamped_idx.size() == 0)
147 delta_xf = -Hff_inv * (q_free)-x_free;
149 delta_xf = -Hff_inv * (q_free + Hfc * x_clamped) - x_free;
151 double f_old = (0.5 * x.transpose() * H * x + q.transpose() * x)(0);
153 bool armijo_reached =
false;
154 Eigen::VectorXd x_new;
155 for (std::size_t ai = 0; ai < alphas_.size(); ++ai)
157 const double& alpha = alphas_[ai];
160 for (
size_t i = 0; i < free_idx.size(); ++i)
161 x_new(free_idx[i]) = std::max(std::min(
162 x(free_idx[i]) + alpha * delta_xf(i), b_high(i)),
165 double f_new = (0.5 * x_new.transpose() * H * x_new + q.transpose() * x_new)(0);
166 Eigen::VectorXd x_diff = x - x_new;
169 double armijo_coef = (f_old - f_new) / (grad.transpose() * x_diff + 1e-5);
170 if (armijo_coef > gamma)
172 armijo_reached =
true;
179 if (!armijo_reached)
break;
182 return {Hff_inv, x, free_idx, clamped_idx};
186 const Eigen::VectorXd& b_low,
const Eigen::VectorXd& b_high,
187 const Eigen::VectorXd& x_init)
189 constexpr
double epsilon = 1e-5;
190 constexpr
double gamma = 0.1;
191 constexpr
int max_iterations = 100;
192 constexpr
double lambda = 1e-5;
193 return ExoticaBoxQP(H, q, b_low, b_high, x_init, gamma, max_iterations, epsilon, lambda,
false,
false);
197 #endif // EXOTICA_CORE_BOX_QP_OLD_H_