Python 与z3并行求解公式

Python 与z3并行求解公式,python,parallel-processing,z3,smt,z3py,Python,Parallel Processing,Z3,Smt,Z3py,假设我有一个z3解算器,它具有一定数量的可满足的断言约束。假设我们是一组约束,我想验证S中的每个约束在将约束添加到解算器时公式是否仍然可满足。这可以通过以下方式轻松地按顺序完成: results=[] 对于S中的约束: 解算器 添加(约束) results.append(solver.check()==z3.sat) solver.pop() 打印全部(结果) 现在,我想将其并行化以加快速度,但我不确定如何正确使用z3 这是一个尝试。考虑下面的简单例子。所有变量都是非负整数,且总和必须为1。现

假设我有一个z3解算器,它具有一定数量的可满足的断言约束。假设我们是一组约束,我想验证S中的每个约束在将约束添加到解算器时公式是否仍然可满足。这可以通过以下方式轻松地按顺序完成:

results=[]
对于S中的约束:
解算器
添加(约束)
results.append(solver.check()==z3.sat)
solver.pop()
打印全部(结果)
现在,我想将其并行化以加快速度,但我不确定如何正确使用z3

这是一个尝试。考虑下面的简单例子。所有变量都是非负整数,且总和必须为1。现在我想验证是否每个变量x都可以独立地设置为>0。显然是这样,;设x=1,并将0分配给其他变量。以下是一种可能的并行实现:

来自多处理导入池的

从functools导入部分
进口z3
def并行_功能(f):
def简易并行(f,顺序):
池=池(进程=4)
结果=pool.map(f,序列)
pool.close()
pool.join()
返回结果
返回部分(易于并行化,f)
def检查(v):
全局优化求解器
全局变量
解算器
添加(变量[v]>0)
结果=solver.check()==z3.sat
solver.pop()
返回结果
范围=范围(1000)
solver=z3.solver()
变量=[z3.Int('x_{}.format(i))表示范围内的i]
添加([var>=0表示变量中的变量])
求解器添加(z3.Sum(变量)==1)
check.parallel=并行函数(检查)
结果=检查。平行(范围)
打印全部(结果)

令人惊讶的是,这在我的机器上运行得很好:结果很好,而且速度快得多。然而,我怀疑它是否安全,因为我正在处理一个全局解算器,我可以很容易地想象推/弹出同时发生。使用z3py是否有任何干净/安全的方法来实现这一点?

的确,这可能适用于第一次测试,但一般来说不适用。不支持在单个上下文上并行求解,以后肯定会出现数据争用和分段故障

在Python中,上下文对象是隐藏的,因此大多数用户不必处理它,但要并行运行,我们需要为每个线程设置一个上下文,然后将正确的上下文传递给所有其他函数(之前隐式使用了隐藏上下文)。请注意,所有表达式、解算器、策略等都依赖于一个特定的上下文,因此如果对象需要跨越该边界,我们需要对其进行翻译(请参见AstRef中的translate(…)和类似内容)


另请参见和

,如果我理解正确,我可以(1)为每个线程I初始化一个解算器s(2)在上下文c_I中创建一个解算器s_I(3)使用s_I.add(s.assertions().translate(c_I))(4)通过首先确保将附加约束转换到适当的上下文,并行执行测试。对吗?每个线程都需要一个上下文,即Z3上下文对象。只有当我们有了一个上下文,我们才能构造一个解算器(确保每个解算器都使用了正确的上下文对象)。然后,所有约束都可以转换为这些上下文中的每一个。