[英]Z3Py: Parsing expressions using eval or z3.parse_smt2_string
我正在編寫一個python程序,除其他外,該程序必須將大型命題公式轉換為z3實例。 例如,可以由我的程序通過以下公式創建的公式f
a = my_atomic_proposition("a") # Bool
b = my_atomic_proposition("b", operator.ge, 42) # Real: c >= 42
c = my_atomic_proposition("c") # Bool
f = my_and(a, my_or(b, my_not(c)))
應該轉換為z3實例g
a = z3.Bool("a")
b = z3.Real("b")
c = z3.Bool("c")
g = z3.And(a, z3.Or(b >= 42, z3.Not(c)))
請記住,我所說的公式主要包含100多個術語。
在發布帶有字符串表達式的Z3之后,我首先嘗試構建自己的解析器(帖子中Leornardo de Moura建議的選項1),該解析器只是遞歸地遍歷了所有公式的操作數,並在此過程中構建了z3實例。 這個選項很慢,所以我改為嘗試遞歸地構建字符串,這要快得多,然后對它們調用eval
(上面帖子中描述的選項3)。 但是,只要我的公式太大(拋出MemoryError
),此解決方案就無法正常工作。
因此,現在我將嘗試第三個選項:使用z3.parse_smt2_string
從字符串創建z3實例(不是我上面在eval
使用的那個,它必須具有不同的語法)。 我將以與Z3_parse_smtlib_string使用問題中相同的方式進行處理 。 不過,我想知道我是否會遇到使用類似的內存問題z3.parse_smt2_string
為我做eval
? 從那時起,我可能會在嘗試過多方法之前尋找另一種方法。
另外,如果有人對我如何實現目標有另一個(希望是更明智的想法),我會很樂意提出任何意見。 謝謝你的幫助!
編輯-MemoryError的示例:
我將舉例說明拋出MemoryError
情況:假設我有以下公式作為字符串:
f = 'z3.Or(a___0,z3.And(True,z3.Or(a___1,z3.And(True,z3.Or(a___2,z3.And(True,z3.Or(a___3,z3.And(True,z3.Or(a___4,z3.And(True,z3.Or(a___5,z3.And(True,z3.Or(a___6,z3.And(True,z3.Or(a___7,z3.And(True,z3.Or(a___8,z3.And(True,z3.Or(a___9,z3.And(True,z3.Or(a___10,z3.And(True,z3.Or(a___11,z3.And(True,z3.Or(a___12,z3.And(True,z3.Or(a___13,z3.And(True,z3.Or(a___14,z3.And(True,z3.Or(a___15,z3.And(True,z3.Or(a___16,z3.And(True,z3.Or(a___17,z3.And(True,z3.Or(a___18,z3.And(True,z3.Or(a___19,z3.And(True,z3.Or(a___20,z3.And(True,z3.Or(a___21,z3.And(True,z3.Or(a___22,z3.And(True,z3.Or(a___23,z3.And(True,z3.Or(a___24,z3.And(True,z3.Or(a___25,z3.And(True,z3.Or(a___26,z3.And(True,z3.Or(a___27,z3.And(True,z3.Or(a___28,z3.And(True,z3.Or(a___29,z3.And(True,z3.Or(a___30,z3.And(True,z3.Or(a___31,z3.And(True,z3.Or(a___32,z3.And(True,z3.Or(a___33,z3.And(True,z3.Or(a___34,z3.And(True,z3.Or(a___35,z3.And(True,z3.Or(a___36,z3.And(True,z3.Or(a___37,z3.And(True,z3.Or(a___38,z3.And(True,z3.Or(a___39,z3.And(True,z3.Or(a___40,z3.And(True,z3.Or(a___41,z3.And(True,z3.Or(a___42,z3.And(True,z3.Or(a___43,z3.And(True,z3.Or(a___44,z3.And(True,z3.Or(a___45,z3.And(True,z3.Or(a___46,z3.And(True,z3.Or(a___47,z3.And(True,z3.Or(a___48,z3.And(True,z3.Or(a___49,z3.And(True,a___50))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))'
以及以下表示f
變量的字符串列表:
variables = ['a___2', 'a___31', 'a___34', 'a___46', 'a___29', 'a___12', 'a___9', 'a___32', 'a___41', 'a___24', 'a___38', 'a___23', 'a___19', 'a___50', 'a___3', 'a___6', 'a___35', 'a___28', 'a___13', 'a___16', 'a___0', 'a___33', 'a___36', 'a___40', 'a___45', 'a___10', 'a___39', 'a___43', 'a___22', 'a___27', 'a___7', 'a___49', 'a___21', 'a___17', 'a___1', 'a___4', 'a___37', 'a___44', 'a___11', 'a___14', 'a___30', 'a___42', 'a___47', 'a___8', 'a___26', 'a___48', 'a___20', 'a___25', 'a___5', 'a___15', 'a___18']
然后我通過以下方式使用eval
:
# Declare z3 variables for all strings in my list 'variables'
for x in variables:
globals()[x] = z3.Bool(x)
# Create z3 object from string 'f'
z3f = eval(f)
並收到錯誤:
---------------------------------------------------------------------------
MemoryError Traceback (most recent call last)
<ipython-input-71-b7421db475e5> in <module>()
3 globals()[x] = z3.Bool(x)
4 # Create z3 object from string 'f'
----> 5 z3f = eval(f)
MemoryError:
對於類似但較短的f
,上面的代碼可以正常工作。 例如:
f = 'z3.Or(a___0,z3.And(True,z3.Or(a___1,z3.And(True,z3.Or(a___2,z3.And(True,z3.Or(a___3,z3.And(True,z3.Or(a___4,z3.And(True,z3.Or(a___5,z3.And(True,z3.Or(a___6,z3.And(True,z3.Or(a___7,z3.And(True,z3.Or(a___8,z3.And(True,z3.Or(a___9,z3.And(True,z3.Or(a___10,z3.And(True,z3.Or(a___11,z3.And(True,z3.Or(a___12,z3.And(True,z3.Or(a___13,z3.And(True,z3.Or(a___14,z3.And(True,z3.Or(a___15,z3.And(True,z3.Or(a___16,z3.And(True,z3.Or(a___17,z3.And(True,z3.Or(a___18,z3.And(True,z3.Or(a___19,z3.And(True,z3.Or(a___20,z3.And(True,z3.Or(a___21,z3.And(True,z3.Or(a___22,z3.And(True,z3.Or(a___23,z3.And(True,z3.Or(a___24,z3.And(True,z3.Or(a___25,z3.And(True,z3.Or(a___26,z3.And(True,z3.Or(a___27,z3.And(True,z3.Or(a___28,z3.And(True,z3.Or(a___29,z3.And(True,z3.Or(a___30,z3.And(True,z3.Or(a___31,z3.And(True,z3.Or(a___32,z3.And(True,z3.Or(a___33,z3.And(True,z3.Or(a___34,z3.And(True,z3.Or(a___35,z3.And(True,z3.Or(a___36,z3.And(True,z3.Or(a___37,z3.And(True,z3.Or(a___38,z3.And(True,z3.Or(a___39,z3.And(True,a___40))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))'
variables = ['a___2', 'a___31', 'a___34', 'a___29', 'a___12', 'a___9', 'a___32', 'a___24', 'a___38', 'a___23', 'a___19', 'a___3', 'a___6', 'a___35', 'a___28', 'a___13', 'a___16', 'a___0', 'a___33', 'a___36', 'a___40', 'a___10', 'a___39', 'a___22', 'a___27', 'a___7', 'a___21', 'a___17', 'a___1', 'a___4', 'a___37', 'a___11', 'a___14', 'a___30', 'a___8', 'a___26', 'a___20', 'a___25', 'a___5', 'a___15', 'a___18']
我收到:
z3f = Or(a___0,
And(True,
Or(a___1,
And(True,
Or(a___2,
And(True,
Or(a___3,
And(True,
Or(a___4,
And(True,
Or(a___5,
And(True,
Or(a___6,
And(True,
Or(a___7,
And(True,
Or(a___8,
And(True,
Or(a___9,
And(True,
Or(..., ...)))))))))))))))))))))
感謝您添加示例ec-m!
實際上,這是Python方面的問題。 Python非常保守地限制了eval(...)
的堆棧,顯然,在某些版本中,它只能處理35個作用域(如Parser在深度嵌套列表顯示時崩潰所聲稱的)。 深度嵌套的lambda存在類似的問題(請參閱Python:嵌套的lambdas — s_push:解析器堆棧溢出Memory Error )。
絕對可以通過切換到Z3的parse_smt2_string
來避免此類問題,該方法允許更大的堆棧。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.