用其他类型替换 SymPy 符号 (Z3Py)

Substitute SymPy Symbols with other types (Z3Py)

我正在使用 SymPy 表达式来计算 a + 3 * b 等表达式,然后我想用 Z3 进行验证(例如,a + 3 * b > 0 用于所有正 a, b)。

我找不到用 Z3 对象替换 a, b 和一般 SymPy 符号的方法。

import sympy
from z3 import *

a = sympy.Symbol('a')
b = sympy.Symbol('b')

t = Real('t')
w = Real('w')

e = a + 3 * b
e = e.subs({a:t, b:w})  # does nothing?
e = e.replace(a, t).replace(b, w)  # e = t + 3 * w

And(True, e > 0)  # raises z3.z3types.Z3Exception

3 替换为 RealVal('3') 也会引发异常。

我目前正在对字符串进行操作,最后使用 exec 如上所述更改类型和表达式,但我打算停止使用 exec

您不能将 sympy 表达式与 z3py 表达式混合搭配。它们是不同的内部数据结构。但是,您可以遍历 sympy 表达式并创建相应的 z3 表达式,但必须单独完成。请注意,对 subs 的调用正在 sympy 世界中进行替换:替换正在进行,但生成的表达式仍然是 sympy 表达式。 (而且很可能是非法的:如果您确实尝试在其上使用任何 sympy 函数,您很可能会从 sympy 本身获得类似的异常。)

您需要开发一个接受 sympy 表达式并为您提供 z3py 表达式的函数。

据我所知,没有 "official" 函数可以执行此操作,但请参阅此(有点过时)答案了解详细信息:How to use Z3py and Sympy together 您也许可以使用那里的代码来服务于您的目的。 (一个粗略的猜测:由于 sympy 的丰富性和不可避免的不匹配,从 sympy 到 z3py 的完整转换器很可能是不可能的,但你很可能得到一个处理你的用例的转换器。)