用Z3中的表达式替换函数

时间:2019-05-24 16:34:15

标签: python z3 smt z3py

我正在使用Z3 Python API,我想获取一个表达式,并将其替换为已声明的函数。也就是说,我想执行以下操作:

from z3 import *

x, y = Ints('x y')

# In practice, this could be a dynamically
# generated expression
expr = x + y * 2

f = Function('f', IntSort(), IntSort(), IntSort())

# Not sure how to implement this
function_substitute(f(x, y) == f(y, x) + f(4,0), (f, [x,y], expr))
# Results in x + y * 2 == y + x * 2 + 4

最初,我以为我想要一个包装expr的函数(Levent为其提供了一个很好的答案),但是考虑了一下,这对于替代方法并不是特别有用,并且肯定有点怪异

任何帮助或建议将不胜感激!

1 个答案:

答案 0 :(得分:1)

这是不寻常的事情,但这是一个解决方案:

from z3 import *

def functionFromExpr(args, expr):
    return lambda *fargs: substitute(expr, zip (args, fargs))

x, y = Ints ('x y')
expr = x + y

f = functionFromExpr([x, y], expr)

print (f (x, y))
print (f (x, IntVal(4)))
print (f (IntVal(3), IntVal(4)))

此打印:

x + y
x + 4
3 + 4

请注意,您需要显式传递表达式,方法是自己在调用站点进行适当的转换。如果要避免这种情况,可以改为执行以下操作:


def mkExpr(a):
    if is_expr(a):
        return a
    elif isinstance(a, int):
        return IntVal(a)
    elif isinstance(a, float):
        return FPVal(a)
    else:
        raise Exception("Don't know how to convert: %s"  % a.__repr__())

def functionFromExpr(args, expr):
    return lambda *fargs: substitute(expr, zip (args, [mkExpr(e) for  e in fargs]))

x, y = Ints ('x y')
expr = x + y

f = functionFromExpr([x, y], expr)

print (f (x, y))
print (f (x, 4))
print (f (3, 4))

显然,您必须适当地修改mkExpr才能处理可能要传递的各种常量。