並行求解公式比方說,我有一定數量的斷言約束是滿足的一個Z3求解。設S是一組約束,我想驗證S中的每個約束是否在將約束添加到求解器時公式仍然可滿足。這可以很容易地以這樣的方式順序進行:與Z3
results = []
for constraint in S:
solver.push()
solver.add(constraint)
results.append(solver.check() == z3.sat)
solver.pop()
print all(results)
現在,我想這個並行加快速度,但我不知道如何與Z3做正確。
這是一種嘗試。考慮下面的簡單例子。所有變量都是非負整數,並必須總和爲1。現在我想驗證是否每個變量x可以獨立地由> 0。顯然,這是如此;讓x = 1並將0賦值給其他變量。這裏是一個可能的並行實現:
from multiprocessing import Pool
from functools import partial
import z3
def parallel_function(f):
def easy_parallize(f, sequence):
pool = Pool(processes=4)
result = pool.map(f, sequence)
pool.close()
pool.join()
return result
return partial(easy_parallize, f)
def check(v):
global solver
global variables
solver.push()
solver.add(variables[v] > 0)
result = solver.check() == z3.sat
solver.pop()
return result
RANGE = range(1000)
solver = z3.Solver()
variables = [z3.Int('x_{}'.format(i)) for i in RANGE]
solver.add([var >= 0 for var in variables])
solver.add(z3.Sum(variables) == 1)
check.parallel = parallel_function(check)
results = check.parallel(RANGE)
print all(results)
令人驚訝的這個完美的作品在我的機器上:結果是健全的,它的速度要快得多。然而,我懷疑這是安全的,因爲我正在研究一個單一的全局求解器,並且我可以很容易想象push/pops會同時發生。有沒有任何干淨/安全的方式來實現這與z3py?
所以如果正確地明白,我可以(1)初始化一個解算器S(2)爲每個線程I,創建上下文C_I內的一個解算器S_I(3)複製s轉換各S_I與s_i.add(s.assertions()。平移(C_I))(4)由第一確保向附加約束翻譯成合適的上下文執行並行測試。是對的嗎? –
您需要一個上下文,即每個線程的Z3上下文對象。只有我們擁有一個Context,我們才能構建一個求解器(確保每個對象都使用正確的Context對象)。然後,所有的約束條件都可以被轉換成這些上下文的每一個 –
太好了,謝謝你的回答! –