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

时间:2018-01-18 15:05:14

标签: 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 ++ noob,但是,我很好地掌握了Python。我的设计是否正确?如何更改C ++ pickBranchLit代码以侦听Python?

1 个答案:

答案 0 :(得分:2)

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

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

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

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

为了能够从Python返回Lit结构,需要为结构编写一个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>)创建一个可用于调用C ++代码的Lit结构。

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