Python-Z3:如何访问 And 的元素
Python-Z3: How can I access the elements of an And
我可以使用列表表示连词。例如,让
x_1 = Int('x_1')
the_list = [Not(500 <= x_1), Not(x_1 <= 500), Not(x_1 <= 300)]
phi_1 = And(the_list)
(即 phi_1 = And([Not(500 <= x_1), Not(x_1 <= 500), Not(x_1 <= 300)])
)
然后,我可以执行 the_list[0]
并得到 Not(500 <= x_1)
。
但是,假设我得到的连词没有列表:
phi_2 = And(Not(500 <= x_1), Not(x_1 <= 500), Not(x_1 <= 300))
如何像访问列表一样访问 And
的元素?
使用decl
和arg
调用:
from z3 import *
x_1 = Int('x_1')
phi_2 = And(Not(500 <= x_1), Not(x_1 <= 500), Not(x_1 <= 300))
print(phi_2.decl())
for i in range(phi_2.num_args()):
print(phi_2.arg(i))
这会打印:
And
Not(x_1 >= 500)
Not(x_1 <= 500)
Not(x_1 <= 300)
decl
returns 您正在应用的函数,arg
获取相应的子项。请注意 z3 如何在内部重新排列您的表达式;它倾向于在比较中把变量放在一边,常量放在另一边,而不改变意思。
请注意,如果将其应用于不是应用程序的表达式,上述操作将会失败。还有一些谓词可以识别您正在处理的节点类型,但它们更适合 advanced/internal 使用。(is_app
是最明显的,如果表达式是函数对参数的应用。)
检查应用程序是否为 AND
如果给定一个表达式并想知道它是否是 And
的应用,请使用 is_and
函数:
print(is_and(phi_2))
为上述 phi_2
的定义打印 True
。参见 https://z3prover.github.io/api/html/namespacez3py.html#a29dab09fc48e1eaa661cc9366194cb29 for documentation. There are recognizers for many of the constructors you might need. And if any is missing, look at the definition of is_and
itself in the linked documentation to find out the robust way of adding new ones. (i.e., by comparing to the official enumeration of all operations, as given by: https://z3prover.github.io/api/html/group__capi.html#ga1fe4399e5468621e2a799a680c6667cd)。
为什么与字符串比较不是一个好主意
造成这种情况的原因有很多,最明显的原因是针对打字错误的可维护性、未来 z3 打印方式的改变等。但更重要的是,与字符串的比较可能会以下列方式失败:
from z3 import *
MyBadFunction = Function('And', IntSort(), IntSort())
print(str(MyBadFunction(IntVal(1)).decl()) == 'And')
如果你 运行 这个,你会看到它愉快地打印 True
,这不是你想要的。如果您改用 is_and
,它将正确打印 False
。因此,永远不要相信任何东西的名称,并始终使用为此目的定义的内部常量。
我可以使用列表表示连词。例如,让
x_1 = Int('x_1')
the_list = [Not(500 <= x_1), Not(x_1 <= 500), Not(x_1 <= 300)]
phi_1 = And(the_list)
(即 phi_1 = And([Not(500 <= x_1), Not(x_1 <= 500), Not(x_1 <= 300)])
)
然后,我可以执行 the_list[0]
并得到 Not(500 <= x_1)
。
但是,假设我得到的连词没有列表:
phi_2 = And(Not(500 <= x_1), Not(x_1 <= 500), Not(x_1 <= 300))
如何像访问列表一样访问 And
的元素?
使用decl
和arg
调用:
from z3 import *
x_1 = Int('x_1')
phi_2 = And(Not(500 <= x_1), Not(x_1 <= 500), Not(x_1 <= 300))
print(phi_2.decl())
for i in range(phi_2.num_args()):
print(phi_2.arg(i))
这会打印:
And
Not(x_1 >= 500)
Not(x_1 <= 500)
Not(x_1 <= 300)
decl
returns 您正在应用的函数,arg
获取相应的子项。请注意 z3 如何在内部重新排列您的表达式;它倾向于在比较中把变量放在一边,常量放在另一边,而不改变意思。
请注意,如果将其应用于不是应用程序的表达式,上述操作将会失败。还有一些谓词可以识别您正在处理的节点类型,但它们更适合 advanced/internal 使用。(is_app
是最明显的,如果表达式是函数对参数的应用。)
检查应用程序是否为 AND
如果给定一个表达式并想知道它是否是 And
的应用,请使用 is_and
函数:
print(is_and(phi_2))
为上述 phi_2
的定义打印 True
。参见 https://z3prover.github.io/api/html/namespacez3py.html#a29dab09fc48e1eaa661cc9366194cb29 for documentation. There are recognizers for many of the constructors you might need. And if any is missing, look at the definition of is_and
itself in the linked documentation to find out the robust way of adding new ones. (i.e., by comparing to the official enumeration of all operations, as given by: https://z3prover.github.io/api/html/group__capi.html#ga1fe4399e5468621e2a799a680c6667cd)。
为什么与字符串比较不是一个好主意
造成这种情况的原因有很多,最明显的原因是针对打字错误的可维护性、未来 z3 打印方式的改变等。但更重要的是,与字符串的比较可能会以下列方式失败:
from z3 import *
MyBadFunction = Function('And', IntSort(), IntSort())
print(str(MyBadFunction(IntVal(1)).decl()) == 'And')
如果你 运行 这个,你会看到它愉快地打印 True
,这不是你想要的。如果您改用 is_and
,它将正确打印 False
。因此,永远不要相信任何东西的名称,并始终使用为此目的定义的内部常量。