2015-05-04 74 views
1

對於使用pow()函數的以下簡單問題,Z3py返回未知數。Z3py使用pow()函數爲方程返回未知數

import z3; 

goal = z3.Goal(); 
goal = z3.Then('purify-arith','nlsat'); 
solver = goal.solver(); 

x = z3.Real('x'); 
solver.add(x <= 1.8); 
solver.add(x >= 0); 

z = 10**x; 
#z = pow(10,x) returns same result 

solver.add(z >= 0, z <= 1.8); 
print solver.check() 

返回

unknown 

顯然x = 0, z = 1是一個令人滿意的解決方案。任何改變方程式構建方式或修改策略的建議都值得讚賞。

+0

當你寫10 ** X你指定一個指數函數。你打算寫x ** 10嗎?在這種情況下,Z3返回[x = 1] –

+0

@NikolajBjorner感謝您的評論Nikolaj,我打算寫'10^x',指數函數。 –

回答

1

可能有一些錯誤,但以下返回的模型爲x = 0z = 1,即使它給出未知。假設Python API也顯示這個模型,你可以創建一個簡單的黑客來提取模型並將其添加到斷言來檢查,類似於如何防止未來模型重用舊模型值:Z3: finding all satisfying models

下面是示例rise4fun鏈接:http://rise4fun.com/Z3/dPnI):

(declare-const x Real) 
(declare-const z Real) 

(assert (>= x 0.0)) 
(assert (<= x 1.8)) 
(assert (= z (^ 10.0 x))) 
(assert (<= z 1.8)) 
(assert (>= z 0.0)) 

(apply (repeat (then purify-arith simplify ctx-simplify ctx-solver-simplify nlsat qfnra-nlsat))) ; gives: 
; (goals 
;(goal 
; (>= x 0.0) 
; (<= x (/ 9.0 5.0)) 
; (<= (^ 10.0 x) (/ 9.0 5.0)) 
; (>= (^ 10.0 x) 0.0) 
; :precision precise :depth 44) 
;) 

; (apply (repeat (then (repeat purify-arith) (repeat simplify) (repeat ctx-simplify) (repeat ctx-solver-simplify) (repeat nlsat) (repeat qfnra-nlsat)))) 

(check-sat) ; unknown 
;(check-sat-using qfnra-nlsat) ; unknown 

(get-model) ; gives x = 0.0 and z = 1.0 even though unknown from check-sat 

; could extract 0 and 1 in python API and check whether it's sat: 
(assert (= x 0)) 
(assert (= z 1)) 

(check-sat) ; sat 

您可能也有興趣在此相關的職位:Z3 support for square root

爲了完整起見,這裏是在Python的模型提取的想法,似乎工作(使用4.3.3,大概從不穩定的建立,但不久前可能):

import z3; 

print z3.get_version_string(); 

goal = z3.Goal(); 
goal = z3.Then('purify-arith','nlsat'); 
#solver = goal.solver(); 

solver = z3.Solver(); 

x = z3.Real('x'); 
z = z3.Real('z'); 
solver.add(x <= 1.8); 
solver.add(x >= 0); 
solver.add(z == 10.0 ** x); 

# z = 10**x; 
#z = pow(10,x) returns same result 

solver.add(z >= 0, z <= 1.8); 

print solver 

print solver.check() 
print solver.model() 

m = solver.model() 

solver.add(x == m[x]) 
solver.add(z == m[z]) 

print solver 

print solver.check() 

這給:

D:\>python exponent.py 
4.3.3 
[x <= 9/5, x >= 0, z == 10**x, z >= 0, z <= 9/5] 
unknown 
[x = 0, z = 1] 
[x <= 9/5, 
x >= 0, 
z == 10**x, 
z >= 0, 
z <= 9/5, 
x == 0, 
z == 1] 
sat 
+0

基於其他一些奇怪的行爲(例如,在平方根中)並且不能在SMT-LIB文檔中找到'^',那麼'^'是否意味着取冪?其他的東西像pow和**似乎沒有被定義。 – Taylor

+0

謝謝你的幫助約翰遜教授。你的答案解決了我的問題。作爲一個方面說明,在你的SMT代碼中,你使用了戰術應用(重複(然後(重複purify-arith)(重複簡化)(重複ctx-simplification)(重複ctx-solver-simplification)(重複nlsat)(重複qfnra -nlsat))))。你是否建議把它作爲一個非線性問題的「默認」策略?你的「日常」戰術環境是什麼?謝謝! –

+0

樂意幫忙!我不認爲簡化的東西有很大幫助:如果'qfnra-nlsat'不能解決非線性的實數(或強制整數)問題,那麼簡化器可能無濟於事。我更多地包含了這個內容,因爲發現了一個模型有點奇怪,但結果是未知的(但是Z3有一些選項用於部分模型構建並返回最後一個模型,只是有趣的是它沒有嘗試什麼黑客攻擊正在插入它找到的模型並檢查它,我希望簡化器可以嘗試)。 – Taylor