13#include <gsl/gsl_multimin.h>
28double FTOL_ABS = 1e-10;
30double FTOL_REL = 1e-10;
32double XTOL_ABS = 1e-8;
34double XTOL_REL = 1e-8;
36double CONSTRAINT_TOL = 1e-08;
38int MAX_SUBOPT_ITER = 100;
47 const std::vector<double> *
mu;
61double evaluateConstraint(
const DblMatrix &cmatrix,
const size_t index,
const size_t ,
const double *
x) {
62 assert(
index < cmatrix.numRows());
63 const double *row = cmatrix[
index];
66 for (
size_t j = 0; j < cmatrix.numCols(); ++j) {
80int relstop(
double vold,
double vnew,
double reltol,
double abstol) {
83 return (
fabs(vnew - vold) < abstol ||
fabs(vnew - vold) < reltol * (
fabs(vnew) +
fabs(vold)) * 0.5 ||
84 (reltol > 0 && vnew == vold));
95int relstopX(
const std::vector<double> &xvOld,
const std::vector<double> &xvNew,
double reltol,
double abstol) {
96 for (
size_t i = 0; i < xvOld.size(); ++i) {
97 if (!relstop(xvOld[i], xvNew[i], reltol, abstol))
110int relstopX(
const std::vector<double> &xvOld,
const gsl_vector *xvNew,
double reltol,
double abstol) {
111 for (
size_t i = 0; i < xvOld.size(); ++i) {
112 if (std::isnan(gsl_vector_get(xvNew, i)))
114 if (!relstop(xvOld[i], gsl_vector_get(xvNew, i), reltol, abstol))
133 double ICM(HUGE_VAL), minf_penalty(HUGE_VAL),
rho(0.0);
134 double minf(HUGE_VAL), penalty(0.0);
136 int minfIsFeasible = 0;
140 const double tau = 0.5, gam = 10;
141 const double lam_min = -1e20, lam_max = 1e20, mu_max = 1e20;
150 feasible = (feasible &&
fabs(hi) <= CONSTRAINT_TOL);
155 penalty += fci > 0 ? fci : 0;
156 feasible = feasible && fci <= CONSTRAINT_TOL;
161 minf_penalty = penalty;
162 minfIsFeasible = feasible;
163 rho = max(1e-6, min(10.0, 2.0 *
fabs(minf) / con2));
169 double prevICM = ICM;
181 feasible = feasible && (
fabs(hi) <= CONSTRAINT_TOL);
182 ICM = max(ICM,
fabs(hi));
183 lambda[i] = min(max(lam_min, newlam), lam_max);
187 double newmu =
mu[i] +
rho * fci;
188 penalty += fci > 0 ? fci : 0;
189 feasible = feasible && fci <= CONSTRAINT_TOL;
190 ICM = max(ICM,
fabs(max(fci, -
mu[i] /
rho)));
191 mu[i] = min(max(0.0, newmu), mu_max);
194 if (ICM > tau * prevICM) {
199 if ((feasible && (!minfIsFeasible || penalty <= minf_penalty || fcur < minf)) ||
200 (!minfIsFeasible && penalty <= minf_penalty)) {
203 if (relstop(minf, fcur, FTOL_REL, FTOL_ABS))
205 else if (relstopX(xv, xcur, XTOL_REL, XTOL_ABS))
209 minf_penalty = penalty;
210 minfIsFeasible = feasible;
211 std::copy(xcur.begin(), xcur.end(), xv.begin());
232double costf(
const gsl_vector *v,
void *params) {
233 auto *
d =
static_cast<FunctionData *
>(params);
235 double lagrangian = (*
d->userfunc)(
d->n, v->data);
236 for (
size_t i = 0; i <
d->eqmatrix->numRows(); ++i) {
237 double h = evaluateConstraint(*
d->eqmatrix, i,
d->n, v->data) + ((*
d->lambda)[i] /
d->rho);
238 lagrangian += 0.5 *
d->rho * h * h;
240 for (
size_t i = 0; i <
d->ineqmatrix->numRows(); ++i) {
241 double fc = evaluateConstraint(*
d->ineqmatrix, i,
d->n, v->data) + ((*
d->mu)[i] /
d->rho);
243 lagrangian += 0.5 *
d->rho * fc * fc;
254void costdf(
const gsl_vector *v,
void *params, gsl_vector *df) {
255 auto *
d =
static_cast<FunctionData *
>(params);
256 double f0 = costf(v, params);
257 gsl_vector *
tmp =
d->tmp;
258 std::copy(v->data, v->data +
d->n,
tmp->data);
260 const double epsilon(1e-08);
261 for (
size_t i = 0; i <
d->n; ++i) {
262 const double curx = gsl_vector_get(
tmp, i);
263 gsl_vector_set(
tmp, i, curx + epsilon);
264 gsl_vector_set(df, i, (costf(
tmp, params) - f0) / epsilon);
265 gsl_vector_set(
tmp, i, curx);
276void costfdf(
const gsl_vector *
x,
void *params,
double *f, gsl_vector *df) {
277 *f = costf(
x, params);
278 costdf(
x, params, df);
291 const std::vector<double> &
mu,
const double rho,
292 std::vector<double> &xcur)
const {
303 gsl_vector *
x = gsl_vector_alloc(
d.n);
304 std::copy(xcur.begin(), xcur.end(),
x->data);
305 gsl_vector *
tmp = gsl_vector_alloc(
d.n);
309 gsl_multimin_function_fdf costFunc;
312 costFunc.df = costdf;
313 costFunc.fdf = costfdf;
314 costFunc.params =
static_cast<void *
>(&
d);
317 const gsl_multimin_fdfminimizer_type *T = gsl_multimin_fdfminimizer_conjugate_pr;
318 gsl_multimin_fdfminimizer *s = gsl_multimin_fdfminimizer_alloc(T, costFunc.n);
319 double tol = (xcur[0] > 1e-3 ? 1e-4 : 1e-3);
320 gsl_multimin_fdfminimizer_set(s, &costFunc,
x, 0.01, tol);
327 status = gsl_multimin_fdfminimizer_iterate(s);
330 status = gsl_multimin_test_gradient(s->gradient, 1e-3);
332 if (relstopX(xcur, s->x, XTOL_REL, XTOL_ABS))
334 std::copy(s->x->data, s->x->data +
d.n, xcur.begin());
335 }
while (status == GSL_CONTINUE && iter < MAX_SUBOPT_ITER);
337 std::copy(s->x->data, s->x->data +
d.n, xcur.begin());
339 gsl_multimin_fdfminimizer_free(s);
341 gsl_vector_free(
tmp);
354 if (totalNumConstr == 0)
358 for (
size_t i = 0; i < 2; ++i) {
366 matrix =
"inequality";
370 std::ostringstream os;
371 os <<
"AugmentedLagrangianOptimizer::initializeConstraints - Invalid " << matrix
372 <<
" constraint matrix. Number of columns must match number "
373 "of parameters. ncols="
375 throw std::invalid_argument(os.str());
const DblMatrix * ineqmatrix
const std::vector< double > * lambda
const DblMatrix * eqmatrix
const AugmentedLagrangianOptimizer::ObjFunction * userfunc
std::map< DeltaEMode::Type, std::string > index
Kernel::DblMatrix m_eq
Defines the equality constraints.
void checkConstraints(const Kernel::DblMatrix &equality, const Kernel::DblMatrix &inequality)
Sanity check for constraint inputs.
void unconstrainedOptimization(const std::vector< double > &lambda, const std::vector< double > &mu, const double rho, std::vector< double > &xcur) const
Using gradient optimizer to perform limited optimization of current set.
int m_maxIter
Maximum number of iterations.
size_t numParameters() const
size_t numEqualityConstraints() const
boost::function< double(const size_t, const double *)> ObjFunction
Function type.
void minimize(std::vector< double > &xv) const
Perform the minimization.
ObjFunction m_userfunc
User-defined function.
Kernel::DblMatrix m_ineq
Defines the inequality constraints.
size_t numInequalityConstraints() const
size_t numCols() const
Return the number of columns in the matrix.
OptimizerResult
The results of the optimization.
Mantid::Kernel::Matrix< double > DblMatrix