Hi,
I'm trying to link a molecular dynamics code (LAMMPS) with an optimization library (NLopt,
http://ab-initio.mit.edu/wiki/index.php/NLopt_C-plus-plus_Reference) to extend the available algorithms for optimization. To do this I think it suffices to create two files: min_nlopt.cpp and min_nlopt.h. Here is the basic structure I think I need.
min_nlopt.h looks like this
1 2 3 4 5 6 7 8
|
class MinNLOPT : public MinLineSearch {
public:
MinNLOPT(class LAMMPS *);
int iterate(int);
double objective_function(const std::vector<double>&, std::vector<double>&, void*);
double minf;
std::vector<double> x;
};
|
It defines the (obligatory) iterator (which is what will be called eventually), and creates an objective_function which is necessary for NLopt.
And min_nlopt.cpp fills in these two functions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
double MinNLOPT::objective_function(const std::vector<double> &x, std::vector<double> &grad, void *data) {
/* objective function :
this will be evaluated by nlopt to see how good we are doing
@param x, || array with x_1,x_2,x_3,..,x_n as parameters that
have to be optimized under the objective function o(x)
@param grad, || array to store gradient
@param my_func_data || possible parameters required to evaluate the o(x)
@return f, || the function value (energy)
*/
eprevious = ecurrent;
// ... update x and compute grad and f ... //
printf("@@ obj. func. e=%f\nm",ecurrent);
return ecurrent;
}
int MinNLOPT::iterate(int maxiter) {
nlopt::opt opt(nlopt::LD_LBFGS, nvec);
opt.set_min_objective(objective_function, NULL);
opt.set_maxeval(maxiter);
opt.optimize(x, minf);
printf("# found minimum at f = %0.10g\n", minf);
return 0;
}
|
My problem is that NLopt requires a function reference as input and I am not sure how to handle this since its inside a class. If I compile this I get an error like
1 2 3 4 5
|
min_nlopt.cpp: In member function ‘virtual int LAMMPS_NS::MinNLOPT::iterate(int)’:
min_nlopt.cpp:68: error: no matching function for call to ‘nlopt::opt::set_min_objective(<unresolved overloaded function type>, NULL)’
/usr/local/include/nlopt.hpp:334: note: candidates are: void nlopt::opt::set_min_objective(double (*)(unsigned int, const double*, double*, void*), void*)
/usr/local/include/nlopt.hpp:341: note: void nlopt::opt::set_min_objective(double (*)(const std::vector<double, std::allocator<double> >&, std::vector<double, std::allocator<double> >&, void*), void*)
/usr/local/include/nlopt.hpp:367: note: void nlopt::opt::set_min_objective(double (*)(unsigned int, const double*, double*, void*), void*, void* (*)(void*), void* (*)(void*))
|
I have no what to do with this. I think I cannot leave the objective_function outside of the class because it needs some of the inherited properties.
I have a C code which works in much the same way, but without the classes (the C syntax is bit different mainly because of the arrays vs. vectors).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
double objective(unsigned n, const double *x, double *grad, void *data) {
// ... compute some stuff
return 1.234
}
int main(int argc, char *argv[]) {
int nsteps = 500;
int method = 11;
double x[2] = {-0.2, 5. };
double minf;
nlopt_opt opt = nlopt_create(method, 2);
nlopt_set_min_objective(opt, objective, NULL);
nlopt_set_maxeval(opt, nsteps);
int return_value = nlopt_optimize(opt, x, &minf);
}
|
Could somebody please help me on this? Any solution will do, ugly or beautiful!
Maybe I can make the entire namespace or class static or global?? Or maybe I should just add something with (*this), but I can't figure it out..
Thanks.