10 #ifndef ROL_PRIMALDUALINTERIORPOINTSTEP_H
11 #define ROL_PRIMALDUALINTERIORPOINTSTEP_H
13 #include "ROL_VectorsNorms.hpp"
78 namespace InteriorPoint {
80 class PrimalDualInteriorPointStep :
public Step<Real> {
82 typedef Vector<Real>
V;
83 typedef PartitionedVector<Real>
PV;
84 typedef Objective<Real> OBJ;
85 typedef BoundConstraint<Real> BND;
86 typedef Krylov<Real> KRYLOV;
87 typedef LinearOperator<Real> LINOP;
88 typedef LinearOperatorFromConstraint<Real> LOPEC;
89 typedef Constraint<Real> EQCON;
90 typedef StepState<Real> STATE;
91 typedef InteriorPointPenalty<Real> PENALTY;
92 typedef PrimalDualInteriorPointResidual<Real> RESIDUAL;
96 ROL::Ptr<KRYLOV> krylov_;
97 ROL::Ptr<LINOP> precond_;
111 ROL::Ptr<V> xscratch_;
112 ROL::Ptr<V> lscratch_;
114 ROL::Ptr<V> zlscratch_;
115 ROL::Ptr<V> zuscratch_;
125 Elementwise::Multiply<Real> mult_;
153 void updateState(
const V& x,
const V &l, OBJ &obj,
154 EQCON &con, BND &bnd, ALGO &algo_state ) {
156 Real tol = std::sqrt(ROL_EPSILON<Real>());
159 obj.update(x,
true,algo_state.iter);
160 con.update(x,
true,algo_state.iter);
162 algo_state.value = obj.value(tol);
163 con.value(*(state->constraintVec),x,tol);
165 obj.gradient(*(state->gradientVec),x,tol);
166 con.applyAdjointJacobian(*g_,l,x,tol);
168 state->gradientVec->plus(*g_);
170 state->gradientVec->axpy(-1.0,*zl_);
171 state->gradientVec->axpy(-1.0,*zu_);
174 algo_state.gnorm =
normLinf(*(state->gradientVec))/sd_;
177 algo_state.cnorm =
normLinf(*(state->constraintVec));
179 Elementwise::Multiply<Real> mult;
186 xscratch_->applyBinary(mult,*zl_);
188 exactLowerViolation =
normLinf(*xscratch_)/scl_;
191 xscratch_->applyBunary(mult,*zu_);
193 exactUpperBound =
normLinf(*xscratch_)/scu_;
196 algo_state.aggregateModelError = std::max(exactLowerViolation,
197 exactUpperViolation);
207 void updateScalingParameters(
void) {
213 sd_ = (nl+nzl+nzu)/(diml_+2*dimx);
214 sd_ = std::max(smax_,sd_)
219 scl_ = std::max(smax_,scl_);
223 scu_ = std::max(smax_,scu_);
229 using Step<Real>::initialize;
230 using Step<Real>::compute;
233 PrimalDualInteriorPointStep( ROL::ParameterList &parlist,
234 const ROL::Ptr<Krylov<Real> > &krylov = ROL::nullPtr,
235 const ROL::Ptr<LinearOperator<Real> > &precond = ROL::nullPtr ) :
236 Step<Real>(), krylov_(krylov), precond_(precond), iterKrylov_(0), flagKrylov_(0) {
238 typedef ROL::ParameterList PL;
240 PL &iplist = parlist.sublist(
"Step").sublist(
"Primal Dual Interior Point");
242 kappa1_ = iplist.get(
"Bound Perturbation Coefficient 1", 1.e-2);
243 kappa2_ = iplist.get(
"Bound Perturbation Coefficient 2", 1.e-2);
244 lambda_max_ = iplist.get(
" Multiplier Maximum Value", 1.e3 );
245 smax_ = iplist.get(
"Maximum Scaling Parameter", 1.e2 );
246 tau_min_ = iplist.get(
"Minimum Fraction-to-Boundary Parameter", 0.99 );
247 kappa_mu_ = iplist.get(
"Multiplicative Penalty Reduction Factor", 0.2 );
248 theta_mu_ = iplist.get(
"Penalty Update Power", 1.5 );
249 eps_tol_ = iplist.get(
"Error Tolerance", 1.e-8);
250 symmetrize_ = iplist.get(
"Symmetrize Primal Dual System",
true );
252 PL &filter = iplist.sublist(
"Filter Parameters");
254 if(krylov_ == ROL::nullPtr) {
255 krylov_ = KrylovFactory<Real>(parlist);
258 if( precond_ == ROL::nullPtr) {
261 apply(
V& Hv,
const V &v, Real tol )
const {
266 precond_ = ROL::makePtr<IdentityOperator<Real>>();
273 ~PrimalDualInteriorPointStep() {
276 void initialize( Vector<Real> &x,
const Vector<Real> &g, Vector<Real> &l,
const Vector<Real> &c,
277 Objective<Real> &obj, Constraint<Real> &con, BoundConstraint<Real> &bnd,
278 AlgorithmState<Real> &algo_state ) {
281 using Elementwise::ValueSet;
283 ROL::Ptr<PENALTY> &ipPen =
dynamic_cast<PENALTY&
>(obj);
287 state->descentVec = x.clone();
288 state->gradientVec = g.clone();
289 state->constaintVec = c.clone();
291 diml_ = l.dimension();
292 dimx_ = x.dimension();
296 Real tol = std::sqrt(ROL_EPSILON<Real>());
303 xscratch_ = x.clone();
304 lscratch_ = l.clone();
306 zlscratch_ = x.clone();
307 zuscratch_ = x.clone();
317 xl_ = bnd.getLowerBound();
318 xu_ = bnd.getUpperBound();
320 maskl_ = ipPen.getLowerMask();
321 masku_ = ipPen.getUpperMask();
331 ROL::Ptr<V> xdiff = xu_->clone();
333 xdiff->axpy(-1.0,*xl_);
334 xdiff->scale(kappa2_);
336 class Max1X :
public Elementwise::UnaryFunction<Real> {
338 Real
apply(
const Real &x )
const {
339 return std::max(1.0,x);
344 Elementwise::AbsoluteValue<Real> absval;
345 Elementwise::Min min;
348 ROL::Ptr<V> pl = xl_->clone();
349 pl->applyUnary(absval);
350 pl->applyUnary(max1x);
352 pl->applyBinary(min,xdiff);
355 ROL::Ptr<V> pu = xu_->clone();
356 pu->applyUnary(absval);
357 pu->applyUnary(max1x);
359 pu->applyBinary(min,xdiff);
366 pbnd_ = ROL::makePtr<BoundConstraint<Real>>(pl,pu)
383 con.solveAugmentedSystem(*xscratch_,*l_,*g_,*lscratch_,x,tol);
388 if( normInf(l_) > lambda_max_ ) {
393 algo_state.nfval = 0;
394 algo_state.ncval = 0;
395 algo_state.ngrad = 0;
397 updateState(x,l,obj,con,bnd,algo_state);
402 void compute( Vector<Real> &s,
const Vector<Real> &x,
const Vector<Real> &l,
403 Objective<Real> &obj, Constraint<Real> &con,
404 BoundConstraint<Real> &bnd, AlgorithmState<Real> &algo_state ) {
409 Elementwise::Fill<Real> minus_mu(-mu_);
410 Elementwise::Divide<Real> div;
411 Elementwise::Multiply<Real> mult;
415 ROL::Ptr<OBJ> obj_ptr = ROL::makePtrFromRef(obj);
416 ROL::Ptr<EQCON> con_ptr = ROL::makePtrFromRef(con);
417 ROL::Ptr<BND> bnd_ptr = ROL::makePtrFromRef(bnd);
426 state->constraintVec,
433 ROL::Ptr<RESIDUAL> residual = ROL::makePtr<RESIDUAL>(obj,con,bnd,*sol,maskL_,maskU_,w_,mu_,symmetrize_);
435 residual->value(*rhs,*sysvec,tol);
439 LOPEC jacobian( sysvec, residual );
442 krylov_->run(*sol,jacobian,*residual,*precond_,iterKrylov_,flagKrylov_);
454 void update( Vector<Real> &x, Vector<Real> &l,
const Vector<Real> &s,
455 Objective<Real> &obj, Constraint<Real> &con,
456 BoundConstraint<Real> &bnd, AlgorithmState<Real> &algo_state ) {
459 Elementwise::Shift<Real> minus_mu(-mu_);
462 xscratch_->applyBinary(mult,*zl_);
463 xscratch_->applyUnary(minus_mu);
465 lowerViolation =
normLinf(*xscratch_)/scl_;
468 xscratch_->applyBinary(mult,*zu_);
469 xscratch_->applyUnary(minus_mu);
471 upperBound =
normLinf(*xscratch_)/scu_;
474 Real Emu = algo_state.gnorm;
475 Emu = std::max(Emu,algo_state.cnorm);
476 Emu = std::max(Emu,upperBound);
477 Emu = std::max(Emu,lowerBound);
480 if(Emu < (kappa_epsilon_*mu_) ) {
486 mu_ = std::min(kappa_mu_*mu_old,std::pow(mu_old,theta_mu_));
487 mu_ = std::max(eps_tol_/10.0,mu_);
490 tau_ = std::max(tau_min_,1.0-mu_);
502 std::string printHeader(
void )
const {
503 std::string head(
"");
508 std::string printName(
void )
const {
509 std::string name(
"");
520 #endif // ROL_PRIMALDUALINTERIORPOINTSTEP_H
PartitionedVector< Real > PV
Real normLinf(const Vector< Real > &x)
ROL::Ptr< Vector< Real > > CreatePartitionedVector(const ROL::Ptr< Vector< Real >> &a)
virtual void update(const Vector< Real > &u, const Vector< Real > &z, bool flag=true, int iter=-1) override
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
Real normL1(const Vector< Real > &x)
ROL::Ptr< StepState< Real > > getState(void)
ROL::DiagonalOperator apply