c++ - 使 C++ 使用 Python 函数的输出

标签 c++ python-2.7 cython wrapper software-design

这更像是一个工程设计问题。 MiniSAT 是解决 SAT 问题的基础库。它已经内置了许多优化。我目前正在努力加速该代码的一部分。但是,我的代码是用 Python 编写的,我希望 C++ 代码使用我的代码的输出来执行它。

我一直在考虑在 MiniSAT 中编写一个 C++ 代码的包装器,以便从 python 中调用。

这是我关心的代码:https://github.com/niklasso/minisat/blob/master/minisat/core/Solver.cc

Lit Solver::pickBranchLit()
{
Var next = var_Undef;

// Random decision:
if (drand(random_seed) < random_var_freq && !order_heap.empty()){
    next = order_heap[irand(random_seed,order_heap.size())];
    if (value(next) == l_Undef && decision[next])
        rnd_decisions++; }

// Activity based decision:
while (next == var_Undef || value(next) != l_Undef || !decision[next])
    if (order_heap.empty()){
        next = var_Undef;
        break;
    }else
        next = order_heap.removeMin();

// Choose polarity based on different polarity modes (global or per-variable):
if (next == var_Undef)
    return lit_Undef;
else if (user_pol[next] != l_Undef)
    return mkLit(next, user_pol[next] == l_True);
else if (rnd_pol)
    return mkLit(next, drand(random_seed) < 0.5);
else
    return mkLit(next, polarity[next]);
}

我希望在 C++ 中调用 pickBranchLit() 时在 C++ 中使用 Python 函数。我还希望 Python 从 C++ 代码中获取有关变量当前状态的返回值。当使用我在 Python 中设计的启发式算法时,我想测试求解器的性能。

这是我第一次处理围绕 C++ 的 Python 包装器,所以我对我的解决方案没有信心。以下是我一直在想的:

C++ 函数:

Lit Solver::pickBranchLit()
{
 // wait for python to return (variable, value) to assign
 // update the order_heap
 // return mkLit(variable, value)
}

Python 函数:

CNF = get_cnf(filename)
c_solver.solve(filename) # loads up CNF in C++
while True:
  # python function to decide variable and the value to assign
  variable, value = python_decide_variable(CNF) 

  # this one calls C++ pickBranchLit 
  result, new_variables, values = python_sat_solver.assign_value(variable, value) 

  if result == "SATISFIABLE":
     break

我是一个 C++ 菜鸟,但是,我对 Python 有很好的掌握。我的设计正确吗?如何更改 C++ pickBranchLit 代码以听取 Python?

最佳答案

在 C++ 中使用 Python 变量是不可能的,它们需要转换为适当的 C++ 类型。对于 native 类型,Cython 通过复制值自动执行此操作。

在您的情况下,您希望 C++ 函数接受 Python 参数。这意味着修改 Solver::pickBranchLit接受它使用的变量的参数。

另一种选择是实现pickBranchLit在 Python 中返回 Lit C++ 返回的 C++ 结构 pickBranchLit .然后可以按原样在其余 C++ 函数中使用它。

此选项可能是最简单的 - 因为您已经在使用 Python 生成 pickBranchLit 使用的值,修改其 C++ 代码以接受这些值作为参数不会产生任何性能优势。

能够返回Lit来自 Python 的结构,将需要为该结构编写一个 Cython 包装器,例如:

cdef extern from "SolverTypes.h" namespace "Minisat":
    ctypedef int Var
    struct Lit:
        int     x
        # Use this as a constructor:
        Lit mkLit(Var, bool)

然后在Cython代码中可以使用mkLit(int_from_py, <True/False>)创建一个 Lit可用于调用 C++ 代码的结构。

您需要从 Cython 代码调用哪些 C++ 函数也需要编写包装器 - 参见 Wrapping C++示例文档。

关于c++ - 使 C++ 使用 Python 函数的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48324335/

相关文章:

c++ - 如何不在 curl_easy_perform() 上重新使用现有连接,在互联网连接更改时挂起

python - 如何为 python 包 bintrees 安装 C 函数?

vector - 问题包括 std::vector 到 cython

python - 使用 Cython 生成 C 代码时出现“未知类型名称”错误

c++ - 如何使用 GNU Make 从同一源代码编译程序的第二个版本?

c++ - 表达式 "b=(b-x)&x"是什么意思?

c++ - 使用 placement new 正确分配数组

python - .pyw 和 pythonw 不能在 Windows 7 下运行

python - 在字典中存储逻辑条件并将它们传递给 if 语句

python - Cython/numpy 与纯 numpy 的最小二乘拟合