Skip to content

Commit 1caeb33

Browse files
committed
IPM alg nlp errors
1 parent 46c055f commit 1caeb33

7 files changed

+174
-71
lines changed

src/Optimization/InnerProduct.cpp

+42-14
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ InnerProduct::~InnerProduct()
7777
delete vec_n_;
7878
}
7979

80-
bool InnerProduct::apply_M(const hiopVector& x, hiopVector& y)
80+
bool InnerProduct::apply_M(const hiopVector& x, hiopVector& y) const
8181
{
8282
if(nlp_->useWeightedInnerProd()) {
8383
return nlp_->eval_M(x, y);
@@ -88,7 +88,7 @@ bool InnerProduct::apply_M(const hiopVector& x, hiopVector& y)
8888
}
8989

9090
// Computes ||x||_M
91-
double InnerProduct::norm_M(const hiopVector& x)
91+
double InnerProduct::norm_M(const hiopVector& x) const
9292
{
9393
if(nlp_->useWeightedInnerProd()) {
9494
nlp_->eval_M(x, *vec_n_);
@@ -98,19 +98,19 @@ double InnerProduct::norm_M(const hiopVector& x)
9898
return x.twonorm();
9999
}
100100
}
101-
// Computes H primal norm
102-
double InnerProduct::norm_H_primal(const hiopVector& x)
103-
{
104-
if(nlp_->useWeightedInnerProd()) {
105-
nlp_->eval_H(x, *vec_n_);
106-
auto dp = x.dotProductWith(*vec_n_);
101+
// Computes H primal norm
102+
double InnerProduct::norm_H_primal(const hiopVector& x) const
103+
{
104+
if(nlp_->useWeightedInnerProd()) {
105+
nlp_->eval_H(x, *vec_n_);
106+
auto dp = x.dotProductWith(*vec_n_);
107107
return ::std::sqrt(dp);
108-
} else {
109-
return x.twonorm();
110-
}
108+
} else {
109+
return x.twonorm();
111110
}
111+
}
112112
// Computes H dual norm
113-
double InnerProduct::norm_H_dual(const hiopVector& x)
113+
double InnerProduct::norm_H_dual(const hiopVector& x) const
114114
{
115115
if(nlp_->useWeightedInnerProd()) {
116116
nlp_->eval_H_inv(x, *vec_n_);
@@ -121,7 +121,7 @@ double InnerProduct::norm_H_dual(const hiopVector& x)
121121
}
122122
}
123123

124-
double InnerProduct::norm_stationarity(const hiopVector& x)
124+
double InnerProduct::norm_stationarity(const hiopVector& x) const
125125
{
126126
if(nlp_->useWeightedInnerProd()) {
127127
nlp_->eval_H_inv(x, *vec_n_);
@@ -133,9 +133,10 @@ double InnerProduct::norm_stationarity(const hiopVector& x)
133133
}
134134

135135
// Compute norm one weighted by M, i.e., 1^T*M*|x|
136-
double InnerProduct::norm_M_one(const hiopVector&x)
136+
double InnerProduct::norm_M_one(const hiopVector&x) const
137137
{
138138
if(nlp_->useWeightedInnerProd()) {
139+
//opt! pre-compute M*1
139140
vec_n_->copyFrom(x);
140141
vec_n_->component_abs();
141142
nlp_->eval_M(*vec_n_, *vec_n2_);
@@ -146,4 +147,31 @@ double InnerProduct::norm_M_one(const hiopVector&x)
146147
}
147148
}
148149

150+
double InnerProduct::norm_complementarity(const hiopVector& x) const
151+
{
152+
if(nlp_->useWeightedInnerProd()) {
153+
//opt! pre-compute M*1
154+
vec_n_->copyFrom(x);
155+
vec_n_->component_abs();
156+
nlp_->eval_M(*vec_n_, *vec_n2_);
157+
vec_n_->setToConstant(1.);
158+
return vec_n_->dotProductWith(*vec_n2_);
159+
} else {
160+
return x.infnorm();
161+
}
162+
}
163+
164+
// Computes the "volume" of the space, 1^T M*1
165+
double InnerProduct::volume() const
166+
{
167+
if(nlp_->useWeightedInnerProd()) {
168+
//opt! pre-compute M*1
169+
vec_n_->setToConstant(1.);
170+
nlp_->eval_M(*vec_n_, *vec_n2_);
171+
return vec_n2_->dotProductWith(*vec_n_);
172+
} else {
173+
return nlp_->n_complem();
174+
}
175+
}
176+
149177
} // end namespace

src/Optimization/InnerProduct.hpp

+15-9
Original file line numberDiff line numberDiff line change
@@ -87,30 +87,36 @@ class InnerProduct
8787
virtual ~InnerProduct();
8888

8989
// Compute y=M*x
90-
bool apply_M(const hiopVector& x, hiopVector& y);
90+
bool apply_M(const hiopVector& x, hiopVector& y) const;
9191

9292
// Computes ||x||_M
93-
double norm_M(const hiopVector& x);
93+
double norm_M(const hiopVector& x) const;
9494

9595
// Computes H primal norm
96-
double norm_H_primal(const hiopVector& x);
96+
double norm_H_primal(const hiopVector& x) const;
9797

9898
// Computes H dual norm
99-
double norm_H_dual(const hiopVector& x);
99+
double norm_H_dual(const hiopVector& x) const;
100100

101101
// Computes norm of stationarity residual, using inf-norm for Euclidean spaces, H-inverse norm for Hilbert spaces
102-
double norm_stationarity(const hiopVector& x);
102+
double norm_stationarity(const hiopVector& x) const;
103103

104-
// Compute norm one weighted by M, i.e., 1^T*M*|x|
105-
double norm_M_one(const hiopVector&x);
104+
// Computes norm of complementarity, using inf-norm for Euclidean spaces, 1M norm for Hilbert spaces
105+
double norm_complementarity(const hiopVector& x) const;
106+
107+
// Computes 1M norm, i.e., ||x|| = 1^T*M*|x|
108+
double norm_M_one(const hiopVector&x) const;
109+
110+
// Computes the "volume" of the space, norm of 1 function
111+
double volume() const;
106112
private:
107113
// Pointer to "client" NLP
108114
hiopNlpFormulation* nlp_;
109115

110116
// Working vector in the size n of the variables, allocated only when for the weighted case
111-
hiopVector* vec_n_;
117+
mutable hiopVector* vec_n_;
112118
// Working vector in the size n of the variables, allocated only when for the weighted case
113-
hiopVector* vec_n2_;
119+
mutable hiopVector* vec_n2_;
114120
};
115121

116122
} //end namespace

src/Optimization/hiopAlgFilterIPM.cpp

+34-21
Original file line numberDiff line numberDiff line change
@@ -656,10 +656,15 @@ bool hiopAlgFilterIPMBase::evalNlpAndLogErrors(const hiopIterate& it,
656656
// the one norms
657657
// double nrmDualBou=it.normOneOfBoundDuals();
658658
// double nrmDualEqu=it.normOneOfEqualityDuals();
659-
double nrmDualBou, nrmDualEqu;
660-
it.normOneOfDuals(nrmDualEqu, nrmDualBou);
659+
double sc;
660+
double sd;
661+
double nrmDualBou;
662+
double nrmDualEqu;
663+
if(!it.compute_sc_sd(sc, sd, nrmDualEqu, nrmDualBou)) {
664+
return false;
665+
}
661666

662-
nlp->log->printf(hovScalars, "nrmOneDualEqu %g nrmOneDualBo %g\n", nrmDualEqu, nrmDualBou);
667+
nlp->log->printf(hovWarning, "nrmOneDualEqu %g nrmOneDualBo %g\n", nrmDualEqu, nrmDualBou);
663668
if(nrmDualBou > 1e+10) {
664669
nlp->log->printf(hovWarning,
665670
"Unusually large bound dual variables (norm1=%g) occured, "
@@ -684,8 +689,11 @@ bool hiopAlgFilterIPMBase::evalNlpAndLogErrors(const hiopIterate& it,
684689
}
685690

686691
// scaling factors
687-
double sd = fmax(p_smax, (nrmDualBou + nrmDualEqu) / (n + m)) / p_smax;
688-
double sc = n == 0 ? 0 : fmax(p_smax, nrmDualBou / n) / p_smax;
692+
//double sd = fmax(p_smax, (nrmDualBou + nrmDualEqu) / (n + m)) / p_smax;
693+
//double sc = n == 0 ? 0 : fmax(p_smax, nrmDualBou / n) / p_smax;
694+
695+
sd = fmax(p_smax, sd) / p_smax;
696+
sc = n == 0 ? 0 : fmax(p_smax, sc) / p_smax;
689697

690698
sd = fmin(sd, 1e+8);
691699
sc = fmin(sc, 1e+8);
@@ -696,7 +704,7 @@ bool hiopAlgFilterIPMBase::evalNlpAndLogErrors(const hiopIterate& it,
696704
// finally, the scaled nlp error
697705
nlpoverall = fmax(nlpoptim / sd, fmax(cons_violation, nlpcomplem / sc));
698706

699-
nlp->log->printf(hovScalars,
707+
nlp->log->printf(hovWarning,
700708
"nlpoverall %g nloptim %g sd %g nlpfeas %g nlpcomplem %g sc %g cons_violation %g\n",
701709
nlpoverall,
702710
nlpoptim,
@@ -731,13 +739,15 @@ bool hiopAlgFilterIPMBase::evalNlpAndLogErrors2(const hiopIterate& it,
731739
nlp->runStats.tmSolverInternal.start();
732740

733741
size_type n = nlp->n_complem(), m = nlp->m();
734-
// the one norms
735-
// double nrmDualBou=it.normOneOfBoundDuals();
736-
// double nrmDualEqu=it.normOneOfEqualityDuals();
737-
double nrmDualBou, nrmDualEqu;
738-
it.normOneOfDuals(nrmDualEqu, nrmDualBou);
742+
double sc;
743+
double sd;
744+
double nrmDualBou;
745+
double nrmDualEqu;
746+
if(!it.compute_sc_sd(sc, sd, nrmDualEqu, nrmDualBou)) {
747+
return false;
748+
}
739749

740-
nlp->log->printf(hovScalars, "nrmOneDualEqu %g nrmOneDualBo %g\n", nrmDualEqu, nrmDualBou);
750+
nlp->log->printf(hovWarning, "nrmOneDualEqu %g nrmOneDualBo %g\n", nrmDualEqu, nrmDualBou);
741751
if(nrmDualBou > 1e+10) {
742752
nlp->log->printf(hovWarning,
743753
"Unusually large bound dual variables (norm1=%g) occured, "
@@ -762,18 +772,21 @@ bool hiopAlgFilterIPMBase::evalNlpAndLogErrors2(const hiopIterate& it,
762772
}
763773

764774
// scaling factors
765-
//sd = max { p_smax, ||zl||_H + ||zu||_H + (||vl||_1 + ||vu||_1)/m } /p_smax
766-
//sc = max { p_smax, ||zl||_H + ||zu||_H } /p_smax
775+
//sd = max { p_smax, ||zl||_M + ||zu||_M + (||vl||_1 + ||vu||_1)/m } /p_smax
776+
//sc = max { p_smax, ||zl||_M + ||zu||_M } /p_smax
767777
//nlpoptim = ||gradf + Jc'*yc + Jd'*Jd - M*zl - M*zu||_Hinv
768778
// ||yd+vl-vu||_inf
769779
//nlpfeas = ||crhs- c||_inf
770780
// ||drs- d||_inf
771-
// ||x-sxl-xl||_H
772-
// ||x-sxu+xu||_H
781+
// ||x-sxl-xl||_inf
782+
// ||x-sxu+xu||_inf
773783
// ||d-sdl-dl||
774784
//
775-
double sd = fmax(p_smax, (nrmDualBou + nrmDualEqu) / (n + m)) / p_smax;
776-
double sc = n == 0 ? 0 : fmax(p_smax, nrmDualBou / n) / p_smax;
785+
//double sd = fmax(p_smax, (nrmDualBou + nrmDualEqu) / (n + m)) / p_smax;
786+
//double sc = n == 0 ? 0 : fmax(p_smax, nrmDualBou / n) / p_smax;
787+
788+
sd = fmax(p_smax, sd) / p_smax;
789+
sc = n == 0 ? 0 : fmax(p_smax, sc) / p_smax;
777790

778791
sd = fmin(sd, 1e+8);
779792
sc = fmin(sc, 1e+8);
@@ -784,7 +797,7 @@ bool hiopAlgFilterIPMBase::evalNlpAndLogErrors2(const hiopIterate& it,
784797
// finally, the scaled nlp error
785798
nlpoverall = fmax(nlpoptim / sd, fmax(cons_violation, nlpcomplem / sc));
786799

787-
nlp->log->printf(hovScalars,
800+
nlp->log->printf(hovWarning,
788801
"nlpoverall %g nloptim %g sd %g nlpfeas %g nlpcomplem %g sc %g cons_violation %g\n",
789802
nlpoverall,
790803
nlpoptim,
@@ -1159,7 +1172,7 @@ hiopSolveStatus hiopAlgFilterIPMQuasiNewton::run()
11591172
solver_status_ = NlpSolve_Pending;
11601173

11611174
while(true) {
1162-
bret = evalNlpAndLogErrors(*it_curr,
1175+
bret = evalNlpAndLogErrors2(*it_curr,
11631176
*resid,
11641177
_mu,
11651178
_err_nlp_optim,
@@ -1252,7 +1265,7 @@ hiopSolveStatus hiopAlgFilterIPMQuasiNewton::run()
12521265

12531266
//! should perform only a partial update since NLP didn't change
12541267
resid->update(*it_curr, _f_nlp, *_c, *_d, *_grad_f, *_Jac_c, *_Jac_d, *logbar);
1255-
bret = evalNlpAndLogErrors(*it_curr,
1268+
bret = evalNlpAndLogErrors2(*it_curr,
12561269
*resid,
12571270
_mu,
12581271
_err_nlp_optim,

src/Optimization/hiopIterate.cpp

+46-17
Original file line numberDiff line numberDiff line change
@@ -236,26 +236,55 @@ double hiopIterate::normOneOfEqualityDuals() const
236236
return nrm1;
237237
}
238238

239-
void hiopIterate::normOneOfDuals(double& nrm1Eq, double& nrm1Bnd) const
239+
// void hiopIterate::normOneOfDuals(double& nrm1Eq, double& nrm1Bnd) const
240+
// {
241+
// #ifdef HIOP_DEEPCHECKS
242+
// assert(zl->matchesPattern(nlp->get_ixl()));
243+
// assert(zu->matchesPattern(nlp->get_ixu()));
244+
// assert(vl->matchesPattern(nlp->get_idl()));
245+
// assert(vu->matchesPattern(nlp->get_idu()));
246+
// #endif
247+
// // work locally with all the vectors. This will result in only one MPI_Allreduce call
248+
// nrm1Bnd = zl->onenorm_local() + zu->onenorm_local();
249+
// #ifdef HIOP_USE_MPI
250+
// double nrm1_global;
251+
// int ierr = MPI_Allreduce(&nrm1Bnd, &nrm1_global, 1, MPI_DOUBLE, MPI_SUM, nlp->get_comm());
252+
// assert(MPI_SUCCESS == ierr);
253+
// nrm1Bnd = nrm1_global;
254+
// #endif
255+
// nrm1Bnd += vl->onenorm_local() + vu->onenorm_local();
256+
// nrm1Eq = yc->onenorm_local() + yd->onenorm_local();
257+
258+
// nlp->log->printf(hovWarning,
259+
// "sc=--- sd=--- volume_n=--- nrm zl=%12.5e zu=%12.5e vl=%12.5e vu=%12.5e yc=%12.5e yd=%12.5e\n",
260+
// zl->onenorm(), zu->onenorm(), vl->onenorm(), vu->onenorm(), yc->onenorm(), yd->onenorm());
261+
262+
// }
263+
264+
/// @brief Computes scaling factors sc and sd; also returns the "norms" of duals
265+
bool hiopIterate::compute_sc_sd(double& sc, double& sd, double& nrmDualsEq, double& nrmDualsBou) const
240266
{
241-
#ifdef HIOP_DEEPCHECKS
242-
assert(zl->matchesPattern(nlp->get_ixl()));
243-
assert(zu->matchesPattern(nlp->get_ixu()));
244-
assert(vl->matchesPattern(nlp->get_idl()));
245-
assert(vu->matchesPattern(nlp->get_idu()));
246-
#endif
247-
// work locally with all the vectors. This will result in only one MPI_Allreduce call
248-
nrm1Bnd = zl->onenorm_local() + zu->onenorm_local();
249-
#ifdef HIOP_USE_MPI
250-
double nrm1_global;
251-
int ierr = MPI_Allreduce(&nrm1Bnd, &nrm1_global, 1, MPI_DOUBLE, MPI_SUM, nlp->get_comm());
252-
assert(MPI_SUCCESS == ierr);
253-
nrm1Bnd = nrm1_global;
254-
#endif
255-
nrm1Bnd += vl->onenorm_local() + vu->onenorm_local();
256-
nrm1Eq = yc->onenorm_local() + yd->onenorm_local();
267+
const auto nrmzl = nlp->inner_prod()->norm_M_one(*zl);
268+
const auto nrmzu = nlp->inner_prod()->norm_M_one(*zu);
269+
const auto volume_n = nlp->inner_prod()->volume();
270+
const auto nrmvl = vl->onenorm_local();
271+
const auto nrmvu = vu->onenorm_local();
272+
nrmDualsBou = nrmzl + nrmzu + nrmvl + nrmvu;
273+
sc = nrmDualsBou / volume_n;
274+
275+
const auto volume_m = nlp->m();
276+
const auto nrmyc = yc->onenorm_local();
277+
const auto nrmyd = yd->onenorm_local();
278+
nrmDualsEq = nrmyc+nrmyd;
279+
sd = (nrmDualsBou+nrmDualsEq)/(volume_n+volume_m);
280+
281+
nlp->log->printf(hovWarning,
282+
"sc=%g sd=%g volume_n=%12.5e norms zl=%12.5e zu=%12.5e vl=%12.5e vu=%12.5e yc=%12.5e yd=%12.5e\n",
283+
sc, sd, volume_n, nrmzl, nrmzu, nrmvl, nrmvu, nrmyc, nrmyd);
284+
return true;
257285
}
258286

287+
259288
void hiopIterate::selectPattern()
260289
{
261290
sxl->selectPattern(nlp->get_ixl());

src/Optimization/hiopIterate.hpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,10 @@ class hiopIterate
142142
virtual double normOneOfBoundDuals() const;
143143
virtual double normOneOfEqualityDuals() const;
144144
/* same as above but computed in one shot to save on communication and computation */
145-
virtual void normOneOfDuals(double& nrm1Eq, double& nrm1Bnd) const;
145+
//virtual void normOneOfDuals(double& nrm1Eq, double& nrm1Bnd) const;
146+
147+
/// @brief Computes scaling factors sc and sd; also returns the "norms" of duals
148+
bool compute_sc_sd(double& sc, double& sd, double& nrmDualsEq, double& nrmDualsBou) const;
146149

147150
/// @brief Entries corresponding to zeros in ix are set to zero
148151
virtual void selectPattern();

src/Optimization/hiopNlpFormulation.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,11 @@ class hiopNlpFormulation
129129
/* Wrapper over user-defined inverse of H apply that also applies the NLP transformations. */
130130
bool eval_H_inv(const hiopVector& x, hiopVector& y);
131131

132-
InnerProduct* inner_prod()
132+
InnerProduct const* inner_prod() const
133133
{
134134
return inner_prod_;
135135
}
136+
136137
protected:
137138
// calls specific hiopInterfaceXXX::eval_Jac_cons and deals with specializations of hiopMatrix arguments
138139
virtual bool eval_Jac_c_d_interface_impl(hiopVector& x, bool new_x, hiopMatrix& Jac_c, hiopMatrix& Jac_d) = 0;

0 commit comments

Comments
 (0)