我想知道当对带有位向量的表达式应用Extract
时,是否有可能让z3在输出表达式中不使用Concat
和simplify
。
例如,代替
>>> x = BitVector("x", 32)
>>> simplify(x ^ 7 ^ 6)
Concat(Extract(31, 1, x), ~Extract(0, 0, x))
我想拥有
>>> x = BitVector("x", 32)
>>> simplify(x ^ 7 ^ 6)
x ^ 1
我看过help_simplify
,但是找不到这样的“选项”。
答案 0 :(得分:2)
不容易。 z3
在重写器中相当早的时候将带有数字的XOR
转换为掩码,似乎没有简单的方法可以控制该行为。看到这里:https://github.com/Z3Prover/z3/blob/master/src/ast/rewriter/bv_rewriter.cpp#L1817-L1823
话虽这么说,可编程API的优点是z3为您提供了用于自己编写此类转换的所有工具。这不是说很容易,但至少会暴露所有必要的点点滴滴。在完全完成您想要的重写的完整工作可能是一项艰巨的任务时,您可以摆脱像这样的简单事情:
def constFold(e):
try:
if is_app(e) and all([is_bv_value(c) for c in e.children()]):
return simplify(e)
else:
return e
except:
return e
这非常简单;实际上它甚至无法解决您提出的问题:
>>> constFold(x^6^7)
x ^ 6 ^ 7
但是它确实可以处理:
>>> constFold(x^(6^7))
x ^ 1
但是对于8行代码来说,还算不错!关键是您可以改进表达式结构,识别关联性/可交换性等,并在可编程API公开的情况下对AST进行所需的任何转换。
请记住,如果要在求解器上下文中使用此函数,则必须维护一堆不变式,并且如果执行“错误”转换,则可以轻松地使求解器不清晰。拥有权利的同时也被赋予了重大的责任!但是,如果您愿意学习API并进行深入研究,那么使用相对简单的编程就可以实现很多目标。
祝你好运!