- #1
davidfur
- 18
- 2
Hey guys,
I have written a C++ code which is based on two main classes: Particle and Group. Each Group contains a set of Particle(s), each Particle is defined by a set of coordinates, and has an associated energy and force (the energy/force evaluation is done by calling an external program). I would like to implement a local minimization algorithm that takes the coordinates, energy and gradient of a given Particle, and outputs a new set of coordinates which correspond to the zero gradient solution (i.e. a local minimum).
I have found this library, which looks pretty neat, however it has a somewhat fixed way of how the objective function should be defined. In short, the LBFGS minimization algorithm from that library is called with:
and an example usage is the following:
All of the above is nice and works smoothly, HOWEVER, in my code the objective function, gradients and coordinates are implemented a bit differently, and I'm not sure what is the easiest way of "interfacing" the two (i.e. using the above library to do what it's supposed to do with the Particle(s) in my code).
This is the definition of the cost function I want to be minimized with the library.
So, this cost function takes more arguments which are needed to calculate the cost.
A separate member function calculates the derivatives of the cost function at the coordinates:
Again, the eval_numgrad function takes the same 4 arguments to evaluate and return the numerical derivatives vector.
So, my question is with the above implementation of eval_cost and eval_numgrad, how should one go about using the library LBFGS function?
I'd be grateful for some guidelines, since I'm not very familiar with passing member functions to non-member functions, etc.
Thanks!
I have written a C++ code which is based on two main classes: Particle and Group. Each Group contains a set of Particle(s), each Particle is defined by a set of coordinates, and has an associated energy and force (the energy/force evaluation is done by calling an external program). I would like to implement a local minimization algorithm that takes the coordinates, energy and gradient of a given Particle, and outputs a new set of coordinates which correspond to the zero gradient solution (i.e. a local minimum).
I have found this library, which looks pretty neat, however it has a somewhat fixed way of how the objective function should be defined. In short, the LBFGS minimization algorithm from that library is called with:
C++:
bool bfgs(arma::vec& init_out_vals, std::function<double (const arma::vec& vals_inp, arma::vec* grad_out, void* opt_data)> opt_objfn, void* opt_data);
C++:
#include "optim.hpp"
double sphere_fn(const arma::vec& vals_inp, arma::vec* grad_out, void* opt_data)
{
double obj_val = arma::dot(vals_inp,vals_inp);
//
if (grad_out) {
*grad_out = 2.0*vals_inp;
}
//
return obj_val;
}int main()
{
//
// sphere function
const int test_dim = 5;
arma::vec x = arma::ones(test_dim,1); // initial values (1,1,...,1)
bool success = optim::lbfgs(x,sphere_fn,nullptr);
if (success) {
std::cout << "lbfgs: sphere test completed successfully." << std::endl;
} else {
std::cout << "lbfgs: sphere test completed unsuccessfully." << std::endl;
}
arma::cout << "lbfgs: solution to sphere test:\n" << x << arma::endl;
return 0;
}
All of the above is nice and works smoothly, HOWEVER, in my code the objective function, gradients and coordinates are implemented a bit differently, and I'm not sure what is the easiest way of "interfacing" the two (i.e. using the above library to do what it's supposed to do with the Particle(s) in my code).
This is the definition of the cost function I want to be minimized with the library.
C++:
double Par::eval_cost(const arma::vec &active_params, int cycle, int iter, int parid) {... evaluate cost function based on the coordinates specified by active_params
return cost
};
So, this cost function takes more arguments which are needed to calculate the cost.
A separate member function calculates the derivatives of the cost function at the coordinates:
C++:
arma::vec Par::eval_numgrad(arma::vec active_params, int cycle, int iter, int parid) {
evaluate numerical derivatives with respect to active_params by calling eval_cost for different values of active_params (i.e. central finite-difference)
return numgrad;
};
Again, the eval_numgrad function takes the same 4 arguments to evaluate and return the numerical derivatives vector.
So, my question is with the above implementation of eval_cost and eval_numgrad, how should one go about using the library LBFGS function?
I'd be grateful for some guidelines, since I'm not very familiar with passing member functions to non-member functions, etc.
Thanks!