9template <
typename Scalar>
 
   10ALMeritFunctionTpl<Scalar>::ALMeritFunctionTpl(
const Problem &prob,
 
   12    : beta_(beta), problem_(prob) {}
 
   14template <
typename Scalar>
 
   15Scalar ALMeritFunctionTpl<Scalar>::evaluate(
const ConstVectorRef & ,
 
   16                                            const std::vector<VectorRef> &lams,
 
   17                                            Workspace &workspace)
 const {
 
   18  Scalar res = workspace.objective_value;
 
   20  const auto &pd_scv = workspace.shift_cstr_pdal;
 
   21  for (std::size_t i = 0; i < workspace.numblocks; i++) {
 
   22    const ConstraintObject &cstr = problem_.getConstraint(i);
 
   23    Scalar mu = cstr.set_->mu();
 
   24    VectorXs scv_tmp = pd_scv[i];
 
   25    res += 2.0 * cstr.set_->computeMoreauEnvelope(pd_scv[i], scv_tmp);
 
   26    res += mu * lams[i].squaredNorm() / 4.0;
 
   31template <
typename Scalar>
 
   32void ALMeritFunctionTpl<Scalar>::computeGradient(
 
   33    const std::vector<VectorRef> &lams, Workspace &workspace)
 const {
 
   34  workspace.merit_gradient = workspace.objective_gradient;
 
   35  workspace.merit_gradient.noalias() +=
 
   36      workspace.data_jacobians.transpose() * workspace.data_lams_pdal;
 
   37  workspace.merit_dual_gradient.setZero();
 
   38  for (std::size_t i = 0; i < workspace.numblocks; i++) {
 
   39    const ConstraintObject &cstr = problem_.getConstraint(i);
 
   40    Scalar mu = cstr.set_->mu();
 
   41    problem_.getSegment(workspace.merit_dual_gradient, i).noalias() +=
 
   42        beta_ * mu * (lams[i] - workspace.lams_pdal[i]);