18             const double th_acceptstep, 
const double th_grad, 
const double reg)
 
   21      th_acceptstep_(th_acceptstep),
 
   35  if (0. >= th_acceptstep && th_acceptstep >= 0.5) {
 
   36    std::cerr << 
"Warning: th_acceptstep value should between 0 and 0.5" 
   40    std::cerr << 
"Warning: th_grad value has to be positive." << std::endl;
 
   43    std::cerr << 
"Warning: reg value has to be positive." << std::endl;
 
   57  solution_.
x = Eigen::VectorXd::Zero(nx);
 
   60  const std::size_t n_alphas_ = 10;
 
   61  alphas_.resize(n_alphas_);
 
   62  for (std::size_t n = 0; n < n_alphas_; ++n) {
 
   63    alphas_[n] = 1. / pow(2., 
static_cast<double>(n));
 
 
   70                                  const Eigen::VectorXd& q,
 
   71                                  const Eigen::VectorXd& lb,
 
   72                                  const Eigen::VectorXd& ub,
 
   73                                  const Eigen::VectorXd& xinit) {
 
   74  if (
static_cast<std::size_t
>(H.rows()) != nx_ ||
 
   75      static_cast<std::size_t
>(H.cols()) != nx_) {
 
   76    throw_pretty(
"Invalid argument: " 
   77                 << 
"H has wrong dimension (it should be " +
 
   78                        std::to_string(nx_) + 
"," + std::to_string(nx_) + 
")");
 
   80  if (
static_cast<std::size_t
>(q.size()) != nx_) {
 
   82        "Invalid argument: " << 
"q has wrong dimension (it should be " +
 
   83                                    std::to_string(nx_) + 
")");
 
   85  if (
static_cast<std::size_t
>(lb.size()) != nx_) {
 
   87        "Invalid argument: " << 
"lb has wrong dimension (it should be " +
 
   88                                    std::to_string(nx_) + 
")");
 
   90  if (
static_cast<std::size_t
>(ub.size()) != nx_) {
 
   92        "Invalid argument: " << 
"ub has wrong dimension (it should be " +
 
   93                                    std::to_string(nx_) + 
")");
 
   95  if (
static_cast<std::size_t
>(xinit.size()) != nx_) {
 
   97        "Invalid argument: " << 
"xinit has wrong dimension (it should be " +
 
   98                                    std::to_string(nx_) + 
")");
 
  102  for (std::size_t i = 0; i < nx_; ++i) {
 
  103    x_(i) = std::max(std::min(xinit(i), ub(i)), lb(i));
 
  107  for (std::size_t k = 0; k < maxiter_; ++k) {
 
  112    g_.noalias() += H * x_;
 
  113    for (std::size_t j = 0; j < nx_; ++j) {
 
  114      const double gj = g_(j);
 
  115      const double xj = x_(j);
 
  116      const double lbj = lb(j);
 
  117      const double ubj = ub(j);
 
  118      if ((xj == lbj && gj > 0.) || (xj == ubj && gj < 0.)) {
 
  128    Eigen::VectorBlock<Eigen::VectorXd> xf = xo_.head(nf_);
 
  129    Eigen::VectorBlock<Eigen::VectorXd> xc = xo_.tail(nc_);
 
  130    Eigen::VectorBlock<Eigen::VectorXd> dxf = dxo_.head(nf_);
 
  131    Eigen::VectorBlock<Eigen::VectorXd> qf = qo_.head(nf_);
 
  132    Eigen::Block<Eigen::MatrixXd> Hff = Ho_.topLeftCorner(nf_, nf_);
 
  133    Eigen::Block<Eigen::MatrixXd> Hfc = Ho_.topRightCorner(nf_, nc_);
 
  134    for (std::size_t i = 0; i < nf_; ++i) {
 
  135      const std::size_t fi = solution_.
free_idx[i];
 
  138      for (std::size_t j = 0; j < nf_; ++j) {
 
  139        Hff(i, j) = H(fi, solution_.
free_idx[j]);
 
  141      for (std::size_t j = 0; j < nc_; ++j) {
 
  144        Hfc(i, j) = H(fi, cj);
 
  148      Hff.diagonal().array() += reg_;
 
  150    Hff_inv_llt_.compute(Hff);
 
  151    const Eigen::ComputationInfo& info = Hff_inv_llt_.info();
 
  152    if (info != Eigen::Success) {
 
  153      throw_pretty(
"backward_error");
 
  155    solution_.
Hff_inv.setIdentity(nf_, nf_);
 
  156    Hff_inv_llt_.solveInPlace(solution_.
Hff_inv);
 
  157    qf.noalias() += Hff * xf;
 
  159      qf.noalias() += Hfc * xc;
 
  162    Hff_inv_llt_.solveInPlace(dxf);
 
  164    for (std::size_t i = 0; i < nf_; ++i) {
 
  165      dx_(solution_.
free_idx[i]) = dxf(i);
 
  170    fold_ = 0.5 * x_.dot(H * x_) + q.dot(x_);
 
  171    for (std::vector<double>::const_iterator it = alphas_.begin();
 
  172         it != alphas_.end(); ++it) {
 
  173      double steplength = *it;
 
  174      for (std::size_t i = 0; i < nx_; ++i) {
 
  176            std::max(std::min(x_(i) + steplength * dx_(i), ub(i)), lb(i));
 
  178      fnew_ = 0.5 * xnew_.dot(H * xnew_) + q.dot(xnew_);
 
  179      if (fold_ - fnew_ > th_acceptstep_ * g_.dot(x_ - xnew_)) {
 
  186    if (qf.lpNorm<Eigen::Infinity>() <= th_grad_) {
 
 
  211  x_.conservativeResize(nx);
 
  212  xnew_.conservativeResize(nx);
 
  213  g_.conservativeResize(nx);
 
  214  dx_.conservativeResize(nx);
 
  215  xo_.conservativeResize(nx);
 
  216  dxo_.conservativeResize(nx);
 
  217  qo_.conservativeResize(nx);
 
  218  Ho_.conservativeResize(nx, nx);
 
 
const BoxQPSolution & solve(const Eigen::MatrixXd &H, const Eigen::VectorXd &q, const Eigen::VectorXd &lb, const Eigen::VectorXd &ub, const Eigen::VectorXd &xinit)
Compute the solution of bound-constrained QP based on Newton projection.
EIGEN_MAKE_ALIGNED_OPERATOR_NEW BoxQP(const std::size_t nx, const std::size_t maxiter=100, const double th_acceptstep=0.1, const double th_grad=1e-9, const double reg=1e-9)
Initialize the Projected-Newton QP for bound constraints.