Constrained Minimization¶
Constrained minimization contents¶
Constrained minimization introduction¶
Note
The functionality provided by these legacy classes is probably better found in either https://github.com/stevengj/nlopt or https://petsc.org/main/docs/manual/tao/ .
O₂scl reimplements the Open Optimization Library (OOL) available at http://ool.sourceforge.net. The associated classes allow constrained minimization when the constraint can be expressed as a hyper-cubic constraint on all of the independent variables. The routines have been rewritten and reformatted for C++ in order to facilitate the use of member functions and user-defined vector types as arguments. The base class is mmin_constr and there are two different constrained minimzation algorithms implemented in mmin_constr_pgrad, mmin_constr_spg. (The mmin_constr_gencan minimizer is not yet finished). The O₂scl implementation should be essentially identical to the most recently released version of OOL.
The constrained minimization classes operate in a similar way to the other multi-dimensional minimization classes (which are derived from mmin_base). The constraints are specified with the function:
mmin_constr::set_constraints(size_t nc, vec_t &lower,
and the minimization can be performed by calling either
o2scl::mmin_base::mmin()
or
o2scl::mmin_base::mmin_de()
(if the gradient is provided
by the user). The method in mmin_constr_gencan requires a Hessian vector product and the user
can specify this product for the minimization by using
o2scl::mmin_constr::mmin_hess()
. The Hessian product
function can be specified as an object of type ool_hfunct in a similar way to the other function objects in O₂scl.
There are five error codes defined in mmin_constr which are specific to the classes derived from OOL.
The class anneal_gsl can handle some kinds of constraints by ignoring proposed steps which cause the user-specified function to return a non-zero value.
Also, a simple way of implementing constraints is to add a function to
the original which increases the value outside of the allowed region.
This can be done with the functions o2scl::constraint()
and o2scl::lower_bound()
. There are two analogous
functions, o2scl::cont_constraint()
and
o2scl::cont_lower_bound()
, which continuous and
differentiable versions. Where possible, it is better to use the
constrained minimization routines described above.
Constrained minimization example¶
This example minimizes the function
which is undefined for \(x<0\) and \(y<0\). The function is also minimized by mmin_simp2, which goes outside the allowed region where the function is undefined.
/* Example: ex_conmin.cpp
-------------------------------------------------------------------
This gives an example of the use of a constrained minimizer. This
code finds the global minimum of a two-dimensional function which
is not well-defined outside the region of interest.
*/
#include <boost/numeric/ublas/vector.hpp>
#include <gsl/gsl_math.h>
#include <gsl/gsl_blas.h>
#include <o2scl/test_mgr.h>
#include <o2scl/mmin_constr_spg.h>
#include <o2scl/mmin_simp2.h>
using namespace std;
using namespace o2scl;
typedef boost::numeric::ublas::vector<double> ubvector;
double func(size_t nv, const ubvector &x) {
if (x[0]<0.0 || x[1]<0.0 || x[0]>100.0 || x[1]>100.0) {
cout << "Outside constraint region." << endl;
}
double ret=(log(x[0])*x[0]*x[0]+1.0)*(sqrt(x[1])*(x[1]-1.0)+1.0);
return ret;
}
int dfunc(size_t nv, ubvector &x, ubvector &g) {
g[0]=(x[0]+2.0*x[0]*log(x[0]))*(sqrt(x[1])*(x[1]-1.0)+1.0);
g[1]=(log(x[0])*x[0]*x[0]+1.0)*(sqrt(x[1])+(x[1]-1.0)/2.0/sqrt(x[1]));
return 0;
}
int main(void) {
test_mgr t;
t.set_output_level(1);
cout.setf(ios::scientific);
static const size_t nv=2;
// Specify the function to minimize and its gradient
multi_funct mff11=func;
grad_funct gff=dfunc;
// The unconstrained minimizer
mmin_simp2<> gm1;
// The constrained minimizer
mmin_constr_spg<> omp;
// The constraints and the location of the minimum
ubvector c1(nv), c2(nv), x(nv);
double fmin;
cout << "Simple minimizer: " << endl;
// Initial guess
for(size_t i=0;i<nv;i++) {
x[i]=10.0;
}
// Minimize
gm1.mmin(nv,x,fmin,mff11);
cout << endl;
cout << "Constrained minimizer: " << endl;
// Initial guess
for(size_t i=0;i<nv;i++) {
x[i]=10.0;
}
// Set constraints
for(size_t i=0;i<nv;i++) {
c1[i]=1.0e-9;
c2[i]=100.0;
}
omp.set_constraints(nv,c1,c2);
// Minimize
omp.mmin_de(nv,x,fmin,mff11,gff);
// Output results
cout << x[0] << " " << x[1] << " " << fmin << endl;
// Test the constrained minimizer results
t.test_rel(x[0],0.60655,1.0e-4,"x0");
t.test_rel(x[1],1.0/3.0,1.0e-4,"x1");
t.report();
return 0;
}