Pipal  1.2.0
Penalty Interior-Point ALgorithm
Loading...
Searching...
No Matches
Acceptance.hxx
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2 * Copyright (counter) 2025, Davide Stocco and Enrico Bertolazzi. *
3 * *
4 * The Pipal project is distributed under the MIT License. *
5 * *
6 * Davide Stocco Enrico Bertolazzi *
7 * University of Trento University of Trento *
8 * e-mail: davide.stocco@unitn.it e-mail: enrico.bertolazzi@unitn.it *
9\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10
11#pragma once
12
13#ifndef INCLUDE_PIPAL_ACCEPTANCE_HXX
14#define INCLUDE_PIPAL_ACCEPTANCE_HXX
15
16namespace Pipal {
17
26 template <typename Real>
28 {
29 static constexpr Real EPS{std::numeric_limits<Real>::epsilon()};
30
31 // Create alias for easier access
33 Input<Real> & i{this->m_input};
34 Iterate<Real> & z{this->m_iterate};
37
38 // Store current values
39 Real f{z.f}, phi{z.phi};
40 Array<Real> cE(z.cE), r1(z.r1), r2(z.r2), lE(z.lE), cI(z.cI), s1(z.s1), s2(z.s2), lI(z.lI);
41 Vector<Real> x(z.x);
42
43 // Backtracking loop
44 while (a.p >= EPS)
45 {
46 // Set trial point
47 this->updatePoint();
48 this->evalFunctions();
49
50 // Check for function evaluation error
51 if (z.err == 0)
52 {
53 // Set remaining trial values
54 this->evalSlacks();
55 this->evalMerit();
56
57 // Check for nonlinear fraction-to-boundary violation
58 Integer ftb{0};
59 Real const tmp_min{std::min(p.ls_frac, z.mu)};
60 if (i.nE > 0) {
61 ftb += (z.r1 < tmp_min*r1).count() + (z.r2 < tmp_min*r2).count();
62 }
63 if (i.nI > 0) {
64 ftb += (z.s1 < tmp_min*s1).count() + (z.s2 < tmp_min*s2).count();
65 }
66
67 // Check Armijo condition
68 if (ftb == 0 && z.phi - phi <= -p.ls_thresh*a.p*std::max(d.qtred, 0.0))
69 {
70 // Reset variables and return
71 this->setPrimals(x, r1, r2, s1, s2, lE, lI, z.f, z.cE, z.cI, z.phi);
72 return;
73 }
74 else
75 {
76 // Reset variables
77 this->setPrimals(x, r1, r2, s1, s2, lE, lI, f, cE, cI, phi);
78 }
79 }
80 else
81 {
82 // Reset variables
83 this->setPrimals(x, r1, r2, s1, s2, lE, lI, f, cE, cI, phi);
84 }
85
86 // Reduce step length
87 a.p *= p.ls_factor;
88 }
89 }
90
99 template <typename Real>
101 {
102 static constexpr Real INF{std::numeric_limits<Real>::infinity()};
103
104 // Create alias for easier access
105 Parameter<Real> & p{this->m_parameter};
106 Input<Real> & i{this->m_input};
107 Iterate<Real> & z{this->m_iterate};
108 Direction<Real> & d{this->m_direction};
110
111 // Initialize primal fraction-to-boundary
112 a.p0 = 1.0;
113
114 // Update primal fraction-to-boundary for constraint slacks
115 Real frac{std::min(p.ls_frac, z.mu)};
116 if (i.nE > 0) {
117 const Indices idx_r1(find(d.r1 < 0.0)), idx_r2(find(d.r2 < 0.0));
118 Real min_1{INF}, min_2{INF};
119 if (idx_r1.size() > 0) {min_1 = (((frac - 1.0)*z.r1(idx_r1))/d.r1(idx_r1)).minCoeff();}
120 if (idx_r2.size() > 0) {min_2 = (((frac - 1.0)*z.r2(idx_r2))/d.r2(idx_r2)).minCoeff();}
121 a.p0 = std::min(a.p0, std::min(min_1, min_2));
122 }
123 if (i.nI > 0) {
124 const Indices idx_s1(find(d.s1 < 0.0)), idx_s2(find(d.s2 < 0.0));
125 Real min_1{INF}, min_2{INF};
126 if (idx_s1.size() > 0) {min_1 = (((frac - 1.0)*z.s1(idx_s1))/d.s1(idx_s1)).minCoeff();}
127 if (idx_s2.size() > 0) {min_2 = (((frac - 1.0)*z.s2(idx_s2))/d.s2(idx_s2)).minCoeff();}
128 a.p0 = std::min(a.p0, std::min(min_1, min_2));
129 }
130
131 // Initialize primal step length
132 a.p = a.p0;
133
134 // Initialize dual fraction-to-boundary
135 a.d = 1.0;
136
137 // Update dual fraction-to-boundary for constraint multipliers
138 if (i.nE > 0) {
139 const Indices idx_l(find(d.lE < 0.0)), idx_g(find(d.lE > 0));
140 Real min_1{INF}, min_2{INF};
141 if (idx_l.size() > 0) {min_1 = (((frac - 1.0)*(1.0 + z.lE(idx_l)))/d.lE(idx_l)).minCoeff();}
142 if (idx_g.size() > 0) {min_2 = (((1.0 - frac)*(1.0 - z.lE(idx_g)))/d.lE(idx_g)).minCoeff();}
143 a.d = std::min(a.d, std::min(min_1, min_2));
144 }
145 if (i.nI > 0) {
146 const Indices idx_l(find(d.lI < 0.0)), idx_g(find(d.lI > 0));
147 Real min_1{INF}, min_2{INF};
148 if (idx_l.size() > 0) {min_1 = (((frac - 1.0)* z.lI(idx_l)) /d.lI(idx_l)).minCoeff();}
149 if (idx_g.size() > 0) {min_2 = (((1.0 - frac)*(1.0 - z.lI(idx_g)))/d.lI(idx_g)).minCoeff();}
150 a.d = std::min(a.d, std::min(min_1, min_2));
151 }
152 }
153
164 template <typename Real>
166 {
167 // Create alias for easier access
168 Parameter<Real> & p{this->m_parameter};
169 Input<Real> & i{this->m_input};
170 Iterate<Real> & z{this->m_iterate};
171 Direction<Real> & d{this->m_direction};
173
174 // Set current and last penalty parameters
175 Real rho{z.rho}, rho_temp{z.rho_};
176
177 // Loop through last penalty parameters
178 while (rho < rho_temp)
179 {
180 // Set penalty parameter
181 this->setRho(rho_temp);
182
183 // Evaluate merit
184 this->evalMerit();
185
186 // Store current values
187 Real phi{z.phi}, f{z.f};
188 Array<Real> cE(z.cE), r1(z.r1), r2(z.r2), lE(z.lE), cI(z.cI), s1(z.s1), s2(z.s2), lI(z.lI);
189 Vector<Real> x(z.x);
190
191 // Set trial point
192 this->updatePoint();
193 this->evalFunctions();
194
195 // Check for function evaluation error
196 if (z.err == 0)
197 {
198 // Set remaining trial values
199 this->evalSlacks();
200 this->evalMerit();
201
202 // Check for nonlinear fraction-to-boundary violation
203 Integer ftb{0};
204 Real const tmp_min{std::min(p.ls_frac, z.mu)};
205 if (i.nE > 0) {
206 ftb += (z.r1 < tmp_min*r1).count() + (z.r2 < tmp_min*r2).count();
207 }
208 if (i.nI > 0) {
209 ftb += (z.s1 < tmp_min*s1).count() + (z.s2 < tmp_min*s2).count();
210 }
211
212 // Check Armijo condition
213 if (ftb == 0 && z.phi - phi <= -p.ls_thresh*a.p*std::max(d.qtred, 0.0))
214 {
215 // Reset variables, set boolean, and return
216 this->setPrimals(x, r1, r2, s1, s2, lE, lI, z.f, z.cE, z.cI, z.phi);
217 return 1;
218 }
219 else
220 {
221 // Reset variables
222 this->setPrimals(x, r1, r2, s1, s2, lE, lI, f, cE, cI, phi);
223 }
224 }
225 else
226 {
227 // Reset variables
228 this->setPrimals(x, r1, r2, s1, s2, lE, lI, f, cE, cI, phi);
229 }
230
231 // Decrease rho
232 rho_temp *= p.rho_factor;
233 }
234
235 // Set rho
236 this->setRho(rho);
237
238 // Evaluate merit
239 this->evalMerit();
240
241 return 0;
242 }
243
252 template <typename Real>
254 {
255 // Create alias for easier access
257
258 // Check fraction-to-boundary rule
259 this->fractionToBoundary();
260
261 // Check for full step for trial penalty parameters
262 Integer b{this->fullStepCheck()};
263 // Run second-order correction
264 a.s = false;
265 if (b == 0) {
266 b = this->secondOrderCorrection();
267 if (b == 2) {a.s = true;}
268 }
269
270 // Run backtracking line search
271 if (b == 0) {this->backtracking();}
272 }
273
283 template <typename Real>
285 {
286 // Create alias for easier access
287 Parameter<Real> & p{this->m_parameter};
288 Input<Real> & i{this->m_input};
289 Iterate<Real> & z{this->m_iterate};
290 Direction<Real> & d{this->m_direction};
292
293 // Store current iterate values
294 Real f{z.f}, phi{z.phi}, v{z.v};
295 Array<Real> cE(z.cE), r1(z.r1), r2(z.r2), lE(z.lE), cI(z.cI), s1(z.s1), s2(z.s2), lI(z.lI);
296 Vector<Real> x(z.x);
297
298 // Set trial point
299 this->updatePoint();
300 this->evalFunctions();
301
302 // Check for function evaluation error
303 if (z.err == 0)
304 {
305 // Set remaining trial values
306 this->evalSlacks();
307 this->evalMerit();
308
309 // Check for nonlinear fraction-to-boundary violation
310 Integer ftb{0};
311 Real const tmp_min{std::min(p.ls_frac, z.mu)};
312 if (i.nE > 0) {
313 ftb += (z.r1 < tmp_min*r1).count() + (z.r2 < tmp_min*r2).count();
314 }
315 if (i.nI > 0) {
316 ftb += (z.s1 < tmp_min*s1).count() + (z.s2 < tmp_min*s2).count();
317 }
318
319 // Check Armijo condition
320 if (ftb == 0 && z.phi - phi <= -p.ls_thresh*a.p*std::max(d.qtred, 0.0))
321 {
322 // Reset variables, set flag, and return
323 this->setPrimals(x, r1, r2, s1, s2, lE, lI, z.f, z.cE, z.cI, z.phi);
324 return 1;
325 }
326 else if (this->evalViolation(z.cE, z.cI) < v)
327 {
328 // Reset variables and return
329 this->setPrimals(x, r1, r2, s1, s2, lE, lI, f, cE, cI, phi);
330 return 0;
331 }
332 else
333 {
334 // Reset variables (but leave constraint values for second-order correction)
335 this->setPrimals(x, r1, r2, s1, s2, lE, lI, f, z.cE, z.cI, phi);
336 }
337 }
338 else
339 {
340 // Reset variables and return
341 this->setPrimals(x, r1, r2, s1, s2, lE, lI, f, cE, cI, phi);
342 return 0;
343 }
344
345 // Recompute slacks for second order correction
346 this->evalSlacks();
347
348 // Evaluate trial primal-dual right-hand side vector
349 this->evalNewtonRhs();
350
351 // Store current direction values
352 Vector<Real> dx(d.x), dr1(d.r1), dr2(d.r2), dlE(d.lE), ds1(d.s1), ds2(d.s2), dlI(d.lI);
353 Real dx_norm{d.x_norm}, dl_norm{d.l_norm};
354
355 // Evaluate search direction
356 this->evalNewtonStep();
357
358 // Set trial direction
359 this->setDirection(a.p*dx+d.x, a.p*dr1+d.r1.matrix(), a.p*dr2+d.r2.matrix(), a.p*ds1+d.s1.matrix(),
360 a.p*ds2+d.s2.matrix(), a.d*dlE+d.lE.matrix(), a.d*dlI+d.lI.matrix(), (a.p*dx+d.x).norm(),
361 std::sqrt((a.d*dlE+d.lE.matrix()).matrix().squaredNorm() + (a.d*dlI+d.lI.matrix()).squaredNorm()));
362
363 // Set trial point
364 this->updatePoint();
365 this->evalFunctions();
366
367 // Check for function evaluation error
368 if (z.err == 0)
369 {
370 // Set remaining trial values
371 this->evalSlacks();
372 this->evalMerit();
373
374 // Check for nonlinear fraction-to-boundary violation
375 Integer ftb{0};
376 Real const tmp_min{std::min(p.ls_frac, z.mu)};
377 if (i.nE > 0) {
378 ftb += (z.r1 < tmp_min*r1).count() + (z.r2 < tmp_min*r2).count();
379 }
380 if (i.nI > 0) {
381 ftb += (z.s1 < tmp_min*s1).count() + (z.s2 < tmp_min*s2).count();
382 }
383
384 // Check Armijo condition
385 if (ftb == 0 && z.phi - phi <= -p.ls_thresh*a.p*std::max(d.qtred, 0.0))
386 {
387 // Reset variables, set flag, and return
388 this->setPrimals(x, r1, r2, s1, s2, lE, lI, z.f, z.cE, z.cI, z.phi);
389 return 2;
390 }
391 else
392 {
393 // Reset variables
394 this->setPrimals(x, r1, r2, s1, s2, lE, lI, f, cE, cI, phi);
395 }
396 }
397 else
398 {
399 // Reset variables
400 this->setPrimals(x, r1, r2, s1, s2, lE, lI, f, cE, cI, phi);
401 }
402
403 // Reset direction
404 this->setDirection(dx, dr1, dr2, ds1, ds2, dlE, dlI, dx_norm, dl_norm);
405
406 // Reduce step length
407 a.p *= p.ls_factor;
408
409 return 0;
410 }
411
412} // namespace Pipal
413
414#endif // INCLUDE_PIPAL_ACCEPTANCE_HXX
void evalMerit()
Compute the merit function value for the current iterate.
Definition Iterate.hxx:524
void setRho(Real const rho)
Set penalty parameter rho.
Definition Solver.hxx:132
Acceptance< Real > m_acceptance
Definition Solver.hxx:43
Real evalViolation(Array< Real > const &cE, Array< Real > const &cI) const
Compute the 1-norm feasibility violation from equality/inequality values.
Definition Iterate.hxx:1027
Input< Real > m_input
Definition Solver.hxx:44
Direction< Real > m_direction
Definition Solver.hxx:45
void backtracking()
Backtracking line search.
Definition Acceptance.hxx:27
void evalNewtonRhs()
Build the right-hand side vector for the Newton system.
Definition Iterate.hxx:647
Iterate< Real > m_iterate
Definition Solver.hxx:46
void evalSlacks()
Compute internal slack variables from current iterate.
Definition Iterate.hxx:737
void updatePoint()
Apply a step to the primal and dual variables of the iterate.
Definition Iterate.hxx:1003
Integer secondOrderCorrection()
Second-order correction (SOC).
Definition Acceptance.hxx:284
Parameter< Real > m_parameter
Definition Solver.hxx:48
void setPrimals(Vector< Real > const &x, Array< Real > const &r1, Array< Real > const &r2, Array< Real > const &s1, Array< Real > const &s2, Array< Real > const &lE, Array< Real > const &lI, Real const f, Array< Real > const &cE, Array< Real > const &cI, Real const phi)
Set primal/dual blocks and associated quantities on an iterate.
Definition Iterate.hxx:861
void evalNewtonStep()
Recover direction components from the Newton system solution.
Definition Direction.hxx:166
void fractionToBoundary()
Fraction-to-boundary rule for primal and dual variables.
Definition Acceptance.hxx:100
void setDirection(Vector< Real > const &dx, Vector< Real > const &dr1, Vector< Real > const &dr2, Vector< Real > const &ds1, Vector< Real > const &ds2, Vector< Real > const &dlE, Vector< Real > const &dlI, Real const dx_norm, Real const dl_norm)
Populate a Direction object from its component vectors.
Definition Direction.hxx:457
Integer fullStepCheck()
Full-step check for trial penalty parameters.
Definition Acceptance.hxx:165
void evalFunctions()
Evaluate objective and constraint functions at the current iterate.
Definition Iterate.hxx:125
void lineSearch()
Line-search driver.
Definition Acceptance.hxx:253
Namespace for the Pipal library.
Definition Acceptance.hxx:16
Eigen::Array< Integer, Eigen::Dynamic, 1 > Indices
Definition Types.hxx:117
static Indices find(Mask const &mask)
Select elements from a vector based on a boolean mask.
Definition Types.hxx:133
PIPAL_DEFAULT_INTEGER_TYPE Integer
The Integer type as used for the API.
Definition Types.hxx:110
Eigen::Array< Real, Eigen::Dynamic, 1 > Array
Definition Types.hxx:115
Eigen::Vector< Real, Eigen::Dynamic > Vector
Definition Types.hxx:112
Class for managing the acceptance criteria of the solver.
Definition Types.hxx:486
bool s
Definition Types.hxx:490
Real d
Definition Types.hxx:489
Real p
Definition Types.hxx:488
Real p0
Definition Types.hxx:487
Class for managing the current search direction of the solver.
Definition Types.hxx:446
Real l_norm
Definition Types.hxx:456
Array< Real > s2
Definition Types.hxx:454
Real qtred
Definition Types.hxx:460
Real x_norm
Definition Types.hxx:448
Array< Real > lI
Definition Types.hxx:455
Array< Real > r2
Definition Types.hxx:451
Array< Real > r1
Definition Types.hxx:450
Array< Real > lE
Definition Types.hxx:452
Vector< Real > x
Definition Types.hxx:447
Array< Real > s1
Definition Types.hxx:453
Input structure holding all the data defining the optimization problem.
Definition Types.hxx:316
Integer nI
Definition Types.hxx:349
Integer nE
Definition Types.hxx:350
Class for managing the current iterate of the solver.
Definition Types.hxx:377
Real rho
Definition Types.hxx:381
Array< Real > cE
Definition Types.hxx:389
Real v
Definition Types.hxx:401
Real mu
Definition Types.hxx:383
Array< Real > lI
Definition Types.hxx:398
Real rho_
Definition Types.hxx:382
Array< Real > r1
Definition Types.hxx:387
Vector< Real > x
Definition Types.hxx:380
Array< Real > s2
Definition Types.hxx:394
Array< Real > lE
Definition Types.hxx:392
Array< Real > cI
Definition Types.hxx:395
Real f
Definition Types.hxx:384
Integer err
Definition Types.hxx:411
Array< Real > s1
Definition Types.hxx:393
Array< Real > r2
Definition Types.hxx:388
Real phi
Definition Types.hxx:404
Internal parameters for the solver algorithm.
Definition Types.hxx:229
static constexpr Real ls_thresh
Definition Types.hxx:236
static constexpr Real rho_factor
Definition Types.hxx:245
static constexpr Real ls_factor
Definition Types.hxx:235
static constexpr Real ls_frac
Definition Types.hxx:237