这更像是一个工程设计问题。 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?
答案 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++文档以获取示例。