C++ Boost using newton_raphson_iterate on a class member function - c++

My code below doesn't compile and can't get it why. Is it because I'm using the newton_raphson_iterate in a wrong way?
Do I need to use binding ? Any examples of how using the newton raphson on a member class function is welcome.
class MyB{
struct funct{
double target;
double DerivativePrecision;
int mo;
bool isG;
MyB* bond;
public:
funct(double target_, double DerivativePrecision_, int mo_, bool isG_, MyB* bond_ ) :
target(target_), DerivativePrecision(DerivativePrecision_), mo(mo_), isG(isG_), bond(bond_)
{}
std::tr1::tuple<double,double> operator()(const double& x) const {
double localYtP = bond->yTp(x, mo, isG);
return std::tr1::make_tuple (
localYtP - target,
(bond->yTp(x+DerivativePrecision,mo, isG)-localYtP)/DerivativePrecision
);
}
};
public:
/*
.....
*/
double yTp(double x, int mo, int isG);
double pty(double p, int mo, int isG){
funct localFunc(p, 0.000001, mo, isG, this);
double y = boost::math::tools::newton_raphson_iterate(localFunc(p),
0.1,
-0.1,
0.4,
std::numeric_limits<double>::digits
);
return y;
}
}
int main()
{
system("pause");
return 0;
}
I get two error messages :
First :
\boost/math/tools/roots.hpp(202) : error C2064: term does not evaluate to a function taking 1 arguments
pointing to the last line of this code (BOOST):
template <class F, class T>
T newton_raphson_iterate(F f, T guess, T min, T max, int digits, boost::uintmax_t& max_iter)
{
BOOST_MATH_STD_USING
T f0(0), f1, last_f0(0);
T result = guess;
T factor = static_cast<T>(ldexp(1.0, 1 - digits));
T delta = 1;
T delta1 = tools::max_value<T>();
T delta2 = tools::max_value<T>();
boost::uintmax_t count(max_iter);
do{
last_f0 = f0;
delta2 = delta1;
delta1 = delta;
boost::math::tie(f0, f1) = f(result);
...
The second :
see reference to function template instantiation 'T boost::math::tools::newton_raphson_iterate<std::tr1::tuple<_Arg0,_Arg1>,double>(F,T,T,T,int)' being compiled
pointing (in my class ) to
double y = boost::math::tools::newton_raphson_iterate(localFunc(p),
0.1,
-0.1,
0.4,
std::numeric_limits<double>::digits
);

The problem is you're calling localFunc when trying to invoke newton_raphson_iterate so end up passing a funct as the first template parameter, which is not callable. You should just pass localFunc directly:
newton_raphson_iterate(localFunc, 0.1, -0.1, 0.4, std::numeric_limits<double>::digits);

Related

boost error: expression cannot be used as a function

I am trying to use the boost RK4 integration together with the rigid body dynamics library.
I am getting a strange error I dont recognize, that I think has to do with the operator() override but I am not sure based on this post.
My code is similar to this example. Which makes me think that either I am missing something obvious. I think that it may be a compiler problem.
This is my class I use to convert from RBDL to boost.
class rbdlToBoost {
public:
rbdlToBoost(Model* model) : model(model)
{
q = VectorNd::Zero(model->dof_count);
qd = VectorNd::Zero(model->dof_count);
qdd = VectorNd::Zero(model->dof_count);
tau = VectorNd::Zero(model->dof_count);
}
//3c. Boost uses this 'operator()' function to evaluate the state
// derivative of the pendulum.
void operator() (const state_type &x, state_type &dxdt, const double t)
{
//do stuff
}
private:
Model* model;
VectorNd q, qd, qdd, tau;
};
This is my main I am using to test the integration. This is a minimal example I put together.
#include "rbdl/Model.h"
#include "rbdl/Dynamics.h"
#include "rbdl_model_tests/DynamicTesting.h"
int main(int argc, char const *argv[])
{
int nPts = 100;
double t0 = 0;
double t1 = 3;
double t = 0; //time
double ts = 0; //scaled time
double dtsdt = M_PI/(t1-t0); //dertivative scaled time
double tp = 0;
double dt = (t1-t0)/((double)nPts);
//Integration settings
double absTolVal = 1e-10;
double relTolVal = 1e-6;
double a_x = 1.0 , a_dxdt = 1.0;
Model* model = NULL;
model = new Model();
rbdlToBoost rbdlBoostModel(model);
state_type xState(2);
int steps = 0;
xState[0] = -M_PI/4.0;
xState[1] = 0;
controlled_stepper_type controlled_stepper(
default_error_checker< double , range_algebra , default_operations >
( absTolVal , relTolVal , a_x , a_dxdt )
);
integrate_adaptive(
controlled_stepper ,
model , xState , tp , t , (t-tp)/10 );//This seems to be the problem
tp = t;
return 0;
}
I am getting this error:
~/catkin_ws/src/ambf_control_system/rbdl_model_tests/src/tempDyn.cpp:37:47: required from here
/usr/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:481:12: error: expression cannot be used as a function
sys( x , m_dxdt.m_v ,t );
It turns out it was a simple fix
I just had to change.
I was passing in the wrong variable into the function. I had to pass in my custom class variable (rbdlBoostModel) not my RBDL model (model).
integrate_adaptive(
controlled_stepper ,
model , xState , tp , t , (t-tp)/10 );//This seems to be the problem
to
integrate_adaptive(
controlled_stepper ,
rbdlBoostModel , xState , tp , t , (t-tp)/10 );

GSL ODE solver returns -nan although same ODE with same parameters is being solved in python

I use python to solve ODEs using scipy.integrate.odeint. Currently, I am working on a small project where I am using gsl in C++ to solve ODEs. I am trying to solve an ODE but the solver is returning -nan for each time point. Following is my code:
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv2.h>
struct param_type {
double k;
double n;
double m;
double s;
};
int func (double t, const double y[], double f[], void *params)
{
(void)(t); /* avoid unused parameter warning */
struct param_type *my_params_pointer = (param_type *)params;
double k = my_params_pointer->k;
double n = my_params_pointer->n;
double m = my_params_pointer->m;
double s = my_params_pointer->s;
f[0] = m*k*pow(s,n)*pow((y[0]/(k*pow(s,n))),(m-1)/m);
return GSL_SUCCESS;
}
int * jac;
int main ()
{
struct param_type mu = {1e-07, 1.5, 0.3, 250};
gsl_odeiv2_system sys = {func, NULL, 1, &mu};
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rk8pd, 1e-6, 1e-6, 0.0);
int i;
double t = 0.0, t1 = 10.0;
double step_size = 0.1;
double y[1] = { 1e-06 };
gsl_vector *time = gsl_vector_alloc ((t1 / step_size) + 1);
gsl_vector *fun_val = gsl_vector_alloc ((t1 / step_size) + 1);
for (i = 1; i <= t1/step_size; i++)
{
double ti = i * t1 / (t1 / step_size);
int status = gsl_odeiv2_driver_apply (d, &t, ti, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
printf ("%.5e %.5e\n", t, y[0]);
gsl_vector_set (time, i, t);
gsl_vector_set (fun_val, i, y[0]);
}
gsl_vector_add(time, fun_val);
{
FILE * f = fopen ("test.dat", "w");
gsl_vector_fprintf (f, time, "%.5g");
fclose (f);
}
gsl_odeiv2_driver_free (d);
gsl_vector_free (time);
gsl_vector_free (fun_val);
return 0;
}
As mentioned here, I don't need jacobian for an explicit solver that's why I passed NULL pointer for the jac function.
When I run the above code, I get -nan values at all time points.
To cross-check, I wrote the program in python which has the same function and same parameters, solved using scipy.integrate.odeint. It runs and provides a plausible answer.
Following my python code:
import numpy as np
from scipy.integrate import odeint
def nb(y, t, *args):
k = args[0]
n = args[1]
m = args[2]
s = args[3]
return m*k*s**n*(y/(k*s**n))**((m-1)/m)
t = np.linspace(0,10,int(10/0.1))
y0 = 1e-06
k = 1e-07
n = 1.5
m = 0.3
s = 250
res = odeint(nb, y0, t, args=(k,n,m,s)).flatten()
print(res)
Could anyone please help me figure out, what I am doing wrong in the C++ code using GSL for solving the ODE?
Your problem is here:
f[0] = m*k*pow(s,n)*pow((y[0]/(k*pow(s,n))),(m-1)/m);
As the solver proceeds, it may want to sample negative values of y[0]. In Python this makes no problem, in C++ it produces NANs.
To handle this, you can mimic Python's behavior:
auto sign = (y[0] < 0) ? -1.0 : 1.0;
f[0] = sign*m*k*pow(s,n)*pow((std::abs(y[0])/(k*pow(s,n))),(m-1)/m);
or even set sign effectively to 1:
f[0] = m*k*pow(s,n)*pow((std::abs(y[0])/(k*pow(s,n))),(m-1)/m);
After all, raising negative values to noninteger powers is an error unless one considers complex numbers, which is not the case.
Please notice that y[0] was secured with std::abs.

Using boost::numeric::odeint to integrate a non-linear function f'(x, y, z) = a + b*I

I would like to integrate a function that maps a 3D point (parametrized by t) to a 2D point (complex plane) using an adaptative step scheme. There is no closed-form for the derivative of my function and it is non-linear.
I've tried the following to see if the code would work. It compiles but the result is wrong. The test function being integrated (t from 0 to 1; i is the complex number) is
Exp[ -Norm[ {1.1, 2.4, 3.6}*t ] * i ]
The expected result is
-0.217141 - 0.279002 i
#include <iostream>
#include <complex>
#include <boost/numeric/ublas/vector.hpp>
namespace ublas = boost::numeric::ublas;
#include <boost/numeric/odeint.hpp>
namespace odeint = boost::numeric::odeint;
typedef std::complex<double> state_type;
class Integrand {
ublas::vector<double> point_;
public:
Integrand(ublas::vector<double> point){
point_ = point;
}
void operator () (const state_type &x, state_type &dxdt, const double t){
point_ *= t;
const std::complex<double> I(0.0, 1.0);
dxdt = std::exp( -norm_2(point_)*I );
}
};
std::complex<double> integral(ublas::vector<double> pt) {
typedef odeint::runge_kutta_cash_karp54< state_type > error_stepper_type;
double err_abs = 1.0e-10;
double err_rel = 1.0e-6;
state_type x = std::complex<double>(1.0, 0.0);
return odeint::integrate_adaptive(
odeint::make_controlled<error_stepper_type>(err_abs, err_rel),
Integrand(pt), x, 0.0, 1.0, 0.001);
}
int main() {
ublas::vector<double> pt(3);
pt(0) = 1.1;
pt(1) = 2.4;
pt(2) = 3.6;
std::cout << integral(pt) << std::endl;
return 0;
}
The code outputs
5051 + 0 i
I suspect the problem is in my definition of x, the state vector. I don't know what it should be.
I suspect your problem is because you are modifying point_ everytime you call Integrand::operator().
Instead of:
point_ *= t;
dxdt = exp(-norm_2(point_)*I);
You probably meant:
dxdt = exp(-norm_2(point_ * t) * I);
Your Integrand::operator() should be marked as a const function when you don't member variables to change, that would help catch these errors in the future.
After looking at the docs for odeint, integrate_adaptive returns the number of steps performed. The input parameter x actually holds the final result so you want to do:
odeint::integrate_adaptive(
odeint::make_controlled<error_stepper_type>(err_abs, err_rel),
Integrand(pt), x, 0.0, 1.0, 0.001);
return x;
Running this prints (0.782859,-0.279002), which is still not the answer you're looking for. The answer you're looking for comes as a result of starting x at 0 instead of 1.
state_type x = std::complex<double>(0.0, 0.0);
odeint::integrate_adaptive(
odeint::make_controlled<error_stepper_type>(err_abs, err_rel),
Integrand(pt), x, 0.0, 1.0, 0.001);
return x;

C++ Using default values for parameters

I am new to C++ (from C# background) and I have a function with the following signature
void AddBenchNode(ref_ptr<Group> root ,ref_ptr<Node> benches, bool setAttitude = false, float scale_x =.15, float scale_y =15, float scale_z = 15, int positionx = 250, int positiony = 100, int positionz =0 )
{
}
But when I try to call the code as below, I get an error which says function does not take 4 arguments.
//then I try to call my function like so
AddBenchNode(root, benches, false, 250);
but I instead get the following error message
error C2660: 'AddBenchNode' : function does not take 3 arguments
Would appreciate an explanation of how C++ does this instead?
Check the prototype in your .hpp file. It's probably declared as
void AddBenchNode(ref_ptr<Group> root ,ref_ptr<Node> benches, bool setAttitude,
float scale_x, float scale_y, float scale_z, int positionx,
int positiony, int positionz);
EDIT: The prototype in the header should be
void AddBenchNode(ref_ptr<Group> root ,ref_ptr<Node> benches, bool setAttitude = false, float scale_x =.15, float scale_y =15, float scale_z = 15, int positionx = 250, int positiony = 100, int positionz =0 );
And your cpp file should then only have
void AddBenchNode(ref_ptr<Group> root ,ref_ptr<Node> benches, bool setAttitude, float scale_x, float scale_y, float scale_z, int positionx, int positiony, int positionz)
{
}
That is, the default parameters are in the prototype, not in the actual definition.

Error Passing `const` as `this` argument of `const double` discards qualifiers

I have to work within some libraries and no matter what i do i keep getting the following error with this code.
passing `const amko::problem::launch' as 'this'argument of 'const double amko::problem::launch::ratio(double, double)' discards qualifiers
namespace amko { namespace problem {
launch::launch():base( 0.0, 20.0, 1 ) {}
base_ptr launch::clone() const
{
return base_ptr(new launch(*this));
}
const double launch::ratio( const double a, const double b)
{
const double area = a*b;
const double circumference = 2*a+2*b;
const double ratio = circumference/area;
return ratio;
}
void launch::objfun_impl(fitness_vector &f, const decision_vector &xv) const
{
amko_assert(f.size() == 1 && xv.size() == get_dimension());
const double x = xv[0];
const double y = launch::ratio(x,5);
f[0] = y;
}
while the following piece of code worked just fine.
namespace amko { namespace problem {
initialValueProblem::initialValueProblem():base( 0.0, 20.0, 1 ) {}
base_ptr initialValueProblem::clone() const
{
return base_ptr(new initialValueProblem(*this));
}
Eigen::VectorXd initialValueProblem::computeDerivative( const double time, const Eigen::VectorXd& state )
{
Eigen::VectorXd stateDerivative( 1 );
stateDerivative( 0 ) = state( 0 ) - std::pow( time, 2.0 ) + 1.0;
return stateDerivative;
}
void initialValueProblem::objfun_impl(fitness_vector &f, const decision_vector &xv) const
{
amko_assert(f.size() == 1 && xv.size() == get_dimension());
const double x = xv[0];
double intervalStart = 0.0;
double intervalEnd = 10.0;
double stepSize = 0.1;
Eigen::VectorXd initialState_;
initialState_.setZero( 1 );
initialState_( 0 ) = x;
numerical_integrators::EulerIntegratorXd integrator( boost::bind( &initialValueProblem::computeDerivative,
const_cast<initialValueProblem*>( this ), _1, _2 ), intervalStart, initialState_ );
Eigen::VectorXd finalState = integrator.integrateTo( intervalEnd, stepSize );
f[0] = fabs( finalState( 0 ) - 11009.9937484598 );
}
Thank you!
launch::objfun_impl is a const member function, it cannot change members or call other functions that do. That means it can't call non-const non-static member functions such as launch::ratio.
Because launch::ratio doesn't appear to access members at all, just its arguments, the simplest fix is to make it a static member function by changing the prototype inside the class definition:
static /* <- ADDED static HERE */ double launch::ratio(const double a, const double b);
The problem is that your ratio member function is not const, even though you are not modifying any member of the object (why is it a member function at all?). Inside objfun_impl you are calling ratio. Now, objfun_impl is const, and thus promises not to modify the object, but calling ratio would break that promise.