Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Boost-Python to calculate derivative of function defined in python

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

For example the User provide a python file (Function.py) which defines a function like F = sin(x)*cos(x).

Then I want to have access to F'(x) (derivative of F(x)) using symbolic differentiation ability of Sympy. I don't want to use numerical differentiation.

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

like image 406
Roy Avatar asked Dec 23 '12 03:12

Roy


2 Answers

Here is some code that should 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 command, replace with 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 it helped.

like image 147
xol Avatar answered Oct 16 '22 04:10

xol


I am not a SymPy expert but maybe this can help you:

You can define a Python method like:

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

You can create an evaluable function f1 as the derivative of f using:

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

This function f1 can be called from C++ using boost::python. You may create an object to function f1, 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;
like image 21
J. Calleja Avatar answered Oct 16 '22 04:10

J. Calleja