Use Boost-Python to compute a derived function defined in python

I want to write a Boost-Python program to use a symbolic python function in a user and evaluate its derivative in my program.

For example, the User provides a python file (Function.py) that defines a function such as F = sin (x) * cos (x).

Then I want to have access to F '(x) (derived from F (x)) using the Sympy symbolic differentiation ability. I do not want to use numerical differentiation.

Is there a way to make such a F '(x) function available in C ++ using Boost-Python.

+7
source share
2 answers

I'm not a sympy expert, but maybe this can help you:

You can define a Python method, for example:

def f(x): return sin(x)*cos(x) 

You can create an evaluation function f1 as a derivative of f using:

 from sympy import * x = symbols('x') f1 = lambdify(x, diff(f(x))) 

This f1 function can be called from C ++ using boost :: python. You can create an object for the f1 function, call the function using the () operator, and convert the result to double using extract <>.

Here is an example:

  namespace py = boost::python; Py_Initialize(); py::object main_module = py::import("__main__"); py::object main_dict = main_module.attr("__dict__"); py::exec( "def f(x):\n" " return sin(x)*cos(x)\n", main_dict ); py::exec( "from sympy import *\n" "x = symbols('x')\n" "f1 = lambdify(x, diff(f(x)))\n", main_dict ); py::object f1 = main_dict["f1"]; std::cout << py::extract<double>(f1(0.0)) << std::endl; std::cout << py::extract<double>(f1(1.0)) << std::endl; return 0; 
+3
source

Here is some code to help you get started.

main.cpp:

 #include <boost/python.hpp> #include <iostream> using namespace boost::python; int main(void) { Py_Initialize(); object main_module = import("__main__"); object main_namespace = main_module.attr("__dict__"); exec("from __future__ import division\n" "from sympy import *\n" "x = symbols('x')\n" "f = symbols('f', cls=Function)\n" "f = cos(x) * sin(x)\n" "f1 = lambda u: diff(f).subs(x, u);\n", main_namespace); exec("result = f1(1.0)", main_namespace); double res = extract<double>(main_namespace["result"]); std::cout << "Out: " << res << std::endl; return 0; } 

Compile the command, replace your path and compiler:

 $ clang++ -I"/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/Current/Headers/" -L"/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/Current/lib/" -lpython2.7 main.cpp 

It compiles, but does not work for me right now. Hope this helped.

+4
source

All Articles