使用 Boost-Python 计算 python 中定义的函数的导数

Posted

技术标签:

【中文标题】使用 Boost-Python 计算 python 中定义的函数的导数【英文标题】:Use Boost-Python to calculate derivative of function defined in python 【发布时间】:2012-12-23 03:08:48 【问题描述】:

我想编写一个 Boost-Python 程序来从用户那里获取一个符号 python 函数并在我的程序中评估它的导数。

例如,用户提供了一个 python 文件 (Function.py),它定义了一个类似的函数 F = sin(x)*cos(x)。

然后我想使用 Sympy 的符号微分能力访问 F'(x)(F(x) 的导数)。我不想使用数值微分。

有没有办法使用 Boost-Python 在 C++ 中使这样的函数 F'(x) 可访问。

【问题讨论】:

你可以和lambdify一起玩,看看它是否能把你带到某个地方。 【参考方案1】:

这里有一些可以帮助您入门的代码。

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;

编译命令,替换为你的路径和编译器:

$ 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

它可以编译,但现在对我不起作用。希望对您有所帮助。

【讨论】:

谢谢,但我想要 c++ 中的函数 f1(x) 在每个点上对其进行评估。 好吧,您可以将调用 f1 的两行代码包装在另一个 c++ 函数中,这样就可以了。【参考方案2】:

我不是 SymPy 专家,但也许这可以帮助你:

您可以定义一个 Python 方法,如:

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

您可以使用以下方法创建一个可评估函数 f1 作为 f 的导数:

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

这个函数 f1 可以从 C++ 中使用 boost::python 调用。您可以为函数 f1 创建一个对象,使用 () 运算符 调用该函数并使用 extract 将结果转换为双精度。

这是一个例子:

  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;

【讨论】:

再次感谢!这样,我可以定义一个多变量函数f(x,y)并得到df/dx和df/dy吗? @Calleja:我可以在没有 py::extract(...) 的情况下直接使用 f1(0,0) 吗? 我现在无法测试,但应该可以调用 fx=diff(f(x, y), x) 和 fy=diff(f(x, y), y) f1(0.0) 返回一个 Python 对象。需要调用extract来获取double值。

以上是关于使用 Boost-Python 计算 python 中定义的函数的导数的主要内容,如果未能解决你的问题,请参考以下文章

Boost-Python C++ 项目构建,如何使用 Python 中的新库?

结合 CMakeLists.txt、boost-python 和 python setuptools

在 Linux 中将 boost-python 与 C++ 一起使用

如何将 kwargs 传递给 boost-python 包装函数?

通过 Boost Python 将 Python 函数转换为 C++,用作回调

Boost python getter/setter 同名