简化z3位向量表达,但避免提取和合并

时间:2019-06-26 22:26:06

标签: python z3 xor smt bitvector

我想知道当对带有位向量的表达式应用Extract时,是否有可能让z3在输出表达式中不使用Concatsimplify

例如,代替

>>> 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,但是找不到这样的“选项”。

1 个答案:

答案 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并进行深入研究,那么使用相对简单的编程就可以实现很多目标。

祝你好运!