5#ifndef LINE_UTIL_AUGLAG_H
6#define LINE_UTIL_AUGLAG_H
109 std::vector<T>
operator()(
const std::vector<T>&)
const {
return std::vector<T>(); }
116T violation_of(
const std::vector<T>& h,
const std::vector<T>& g) {
117 const T zero = num_traits<T>::from_int(0);
119 for (std::size_t i = 0; i < h.size(); ++i) {
123 for (std::size_t j = 0; j < g.size(); ++j)
124 if (g[j] > v) v = g[j];
140template <
class T,
class F,
class H,
class G>
144 "auglag requires transcendental arithmetic");
147 const std::size_t n = x0.size();
148 if (n == 0)
throw InputError(
"auglag: no variables");
149 if (bounds.size() != n)
throw InputError(
"auglag: one bound per variable is required");
151 const std::size_t ne = h(x0).size();
152 const std::size_t ni = g(x0).size();
156 res.
lambda.assign(ne, zero);
157 res.
mu.assign(ni, zero);
163 bool inner_ok =
false;
165 for (
unsigned outer = 0; outer <
opt.max_outer; ++outer) {
167 const std::vector<T> lam = res.
lambda;
168 const std::vector<T> mu = res.
mu;
171 auto L = [f, h, g, lam, mu, rho_c, zero, two](
const std::vector<T>& x) {
173 const std::vector<T> hv = h(x);
174 for (std::size_t i = 0; i < hv.size(); ++i)
175 val += lam[i] * hv[i] + rho_c / two * hv[i] * hv[i];
176 const std::vector<T> gv = g(x);
177 for (std::size_t j = 0; j < gv.size(); ++j) {
178 const T s = mu[j] + rho_c * gv[j];
179 if (s > zero) val += (s * s - mu[j] * mu[j]) / (two * rho_c);
180 else val -= mu[j] * mu[j] / (two * rho_c);
189 const std::vector<T> hv = h(res.
x);
190 const std::vector<T> gv = g(res.
x);
191 const T viol = agldetail::violation_of(hv, gv);
194 for (std::size_t i = 0; i < ne; ++i) res.
lambda[i] = res.
lambda[i] + rho * hv[i];
195 for (std::size_t j = 0; j < ni; ++j) {
196 const T s = res.
mu[j] + rho * gv[j];
197 res.
mu[j] = s > zero ? s : zero;
200 if (viol <=
opt.ctol) {
204 if (prev_viol >= zero && viol >
opt.shrink * prev_viol && rho <
opt.rho_max)
205 rho *=
opt.rho_factor;
214template <
class T,
class F,
class H,
class G>
216 const std::vector<
Bound<T>>& bounds) {
245template <
class T,
class R,
class H,
class G>
249 "auglag_ls requires transcendental arithmetic");
253 const std::size_t n = x0.size();
254 if (n == 0)
throw InputError(
"auglag_ls: no variables");
256 const std::size_t ne = h(x0).size();
257 const std::size_t ni = g(x0).size();
261 res.
lambda.assign(ne, zero);
262 res.
mu.assign(ni, zero);
268 bool inner_ok =
false;
270 for (
unsigned outer = 0; outer <
opt.max_outer; ++outer) {
272 const std::vector<T> lam = res.
lambda;
273 const std::vector<T> mu = res.
mu;
275 const T w = sqrt(T(rho_c / two));
277 auto Raug = [r, h, g, lam, mu, rho_c, w, zero](
const std::vector<T>& x) {
278 std::vector<T> out = r(x);
279 const std::vector<T> hv = h(x);
280 for (std::size_t i = 0; i < hv.size(); ++i)
281 out.push_back(T(w * (hv[i] + lam[i] / rho_c)));
282 const std::vector<T> gv = g(x);
283 for (std::size_t j = 0; j < gv.size(); ++j) {
284 const T s = gv[j] + mu[j] / rho_c;
285 out.push_back(s > zero ? T(w * s) : zero);
294 const std::vector<T> hv = h(res.
x);
295 const std::vector<T> gv = g(res.
x);
296 const T viol = agldetail::violation_of(hv, gv);
299 for (std::size_t i = 0; i < ne; ++i) res.
lambda[i] = res.
lambda[i] + rho * hv[i];
300 for (std::size_t j = 0; j < ni; ++j) {
301 const T s = res.
mu[j] + rho * gv[j];
302 res.
mu[j] = s > zero ? s : zero;
305 if (viol <=
opt.ctol) {
309 if (prev_viol >= zero && viol >
opt.shrink * prev_viol && rho <
opt.rho_max)
310 rho *=
opt.rho_factor;
314 res.
fval = levmardetail::sum_squares(r(res.
x));
319template <
class T,
class R,
class H,
class G>
The exception types the port throws.
Levenberg-Marquardt for nonlinear least squares.
AugLagResult< T > auglag(F f, H h, G g, const std::vector< T > &x0, const std::vector< Bound< T > > &bounds, const AugLagOptions< T > &opt)
Augmented Lagrangian with a scalar objective and a simplex inner solver.
LevmarResult< T > levmar(F f, const std::vector< T > &x0, std::size_t m, const LevmarOptions< T > &opt)
Levenberg-Marquardt with a central-difference Jacobian.
NelderMeadResult< T > nelder_mead_box(F f, const std::vector< T > &x0, const std::vector< Bound< T > > &bounds, const NelderMeadOptions< T > &opt)
Box-constrained simplex minimization by the transformation described in the header comment.
AugLagOptions< T > auglag_defaults()
Defaults: rho0 = 10, growth 10, feasibility 1e-10, 50 outer iterations.
AugLagResult< T > auglag_ls(R r, std::size_t m, H h, G g, const std::vector< T > &x0, const AugLagOptions< T > &opt)
Augmented Lagrangian with a least-squares objective and levmar as the inner solver.
NelderMeadOptions< T > nelder_mead_defaults()
fminsearch's coefficients and initial simplex, with tighter tolerances.
LevmarOptions< T > levmar_defaults()
MINPACK-like defaults, with a central-difference step of eps^(1/3).
Derivative-free simplex minimization (Nelder and Mead, 1965), with optional box bounds imposed by a c...
Number-type abstraction for the templated API port.
Tuning of the outer multiplier iteration.
T ctol
constraint violation accepted as feasible
T rho0
initial penalty parameter
LevmarOptions< T > inner_lm
tuning of the least-squares inner solver
NelderMeadOptions< T > inner_nm
tuning of the simplex inner solver
T rho_factor
growth factor applied to rho when needed
T shrink
required violation reduction to leave rho alone
unsigned max_outer
cap on outer iterations
Outcome of a constrained solve.
bool converged
feasible to ctol and the last inner solve converged
std::vector< T > mu
final inequality multipliers, all >= 0
std::vector< T > x
best point found
T violation
max(|h_i|, max(0, g_j)) at x
std::vector< T > lambda
final equality multipliers
T fval
the ORIGINAL objective f(x), not the augmented one
unsigned outer_iterations
Box constraint on one variable.
Tuning of the Levenberg-Marquardt iteration.
Outcome of a least-squares solve.
std::vector< T > x
best point found
bool converged
a tolerance was met before the caps
Tuning of the simplex iteration.
Outcome of a simplex minimization.
std::vector< T > x
best point found
bool converged
both tolerances met before the caps
A constraint map that returns no constraints; the default for h or g.
std::vector< T > operator()(const std::vector< T > &) const