Python 在z3py中声明外部函数 脚本

Python 在z3py中声明外部函数 脚本,python,z3,z3py,Python,Z3,Z3py,在数学优化领域,需要对不等式g_k(…)约束进行建模g_k(…)有时可以是对外部程序的函数调用,无论出于何种目的,它都是一个黑盒。简单地找到满意的答案对某些工程分析是有益的 例子 上述场景的一个示例应用程序是Reals,但也可以是int或boolean: 最小f(x,y) g1(x,y)=7.7 x、 yεReal x>=0 x=0 y您正在寻找未解释的函数 在中搜索术语“未解释的函数” 您的问题似乎对如何使用SMT解决方案做出了一些假设;这并不能完全反映当前的技术水平。了解SMT解算器使用的一

在数学优化领域,需要对不等式
g_k(…)
约束进行建模
g_k(…)
有时可以是对外部程序的函数调用,无论出于何种目的,它都是一个黑盒。简单地找到满意的答案对某些工程分析是有益的

例子 上述场景的一个示例应用程序是Reals,但也可以是int或boolean:

最小f(x,y)
g1(x,y)=7.7
x、 yεReal
x>=0
x=0

y您正在寻找未解释的函数

在中搜索术语“未解释的函数”

您的问题似乎对如何使用SMT解决方案做出了一些假设;这并不能完全反映当前的技术水平。了解SMT解算器使用的一个很好的资源是:花时间仔细研究一下它在实践中的应用是非常值得的

一些一般性意见:

Z3py Z3py不是一个用于对Python程序进行推理的系统。Z3py是一个库集合,因此您可以以更清晰、更简单的方式编写Z3脚本。许多语言中都有许多这样的绑定:C/C++/Java/Haskell/Scala,随便你说。Z3py的优点是它更易于学习和使用。但你不应该把它看作是一个系统,用来对Python本身进行推理。这只是以轻量级形式编写Z3脚本的一种方式

解算器逻辑 SMT解算器基本上处理各种理论的许多排序逻辑的可判定片段(大部分是无量词的)。您可以在以下网址找到这些详细信息:

SMTLib 大多数解算器接受所谓SMT Lib格式的输入,详情如下:

请注意,C/Python/Java等级别的任何“绑定”都只是程序员的便利。虽然许多解算器也提供扩展功能,但您应该考虑使用SMTLib语言。在您的特定情况下,上述文档中详细描述了未解释的函数

类型 SMTLib理解一组类型:整数、实数、位向量(机器整数)、浮点等。它还允许复合类型,例如代数数据类型,甚至可以是递归的。(尽管解算器支持各不相同。)您必须将外部函数类型“映射”到这些类型:希望有足够接近的东西。如果没有,请随意询问有关您感兴趣的类型的具体问题

“导入”功能 无法将用其他语言(Python/C/C++等)编写的函数导入SMTLib并对其进行解释。没有这样做的机制,将来也不会有。这不是SMT解决方案的目标。如果您想对用特定语言编写的程序进行推理,那么您应该寻找专门设计用于这些语言的工具。(例如,Dafny适用于通用命令式程序、Klee/CBMC适用于C程序、LiquidHaskell适用于Haskell程序等)这些工具的功能各不相同,它们允许您指定和证明什么。请注意,这些工具本身可以使用下面的SMT解算器来完成它们的任务,而且它们通常是这样做的,而不是相反

坚持SMTLib 如果没有其他可用的工具(不幸的是,对于大多数语言,尤其是传统语言来说,情况可能就是这样),那么您基本上只能使用SMTLib语言提供的任何工具。在您的例子中,使用SMTLib对此类“外部”函数建模的最佳方法是使用未解释的函数以及公理。通常,您需要公理来限制未解释函数本身的行为,并对外部函数进行建模。另一方面,如果公理被量化(通常是量化的),那么解算器可能会返回
未知

总结 虽然SMT解算器是很好的工具,但您应该始终记住,它们所使用的语言是SMTLib,而不是Python/C或其他任何语言。这些绑定只是访问解算器的一种方式,因为您可以将其合并到更大的项目中。我希望这会清除预期的用例


问一些关于你尝试过什么和你想要实现什么的具体问题(代码示例)是从这个论坛中获得收益的最好方式

对不起,你能详细说明一下吗?我不清楚这是如何完全回答我的问题的。我可以看出,未解释的函数是朝着正确方向迈出的一步,因为它们没有包含在理论的签名中,但我仍然遗漏了一些东西。参见我的扩展答案。谢谢,Levent。至于你最后的评论,我尝试了我的小例子来尝试维基百科的例子,通过一个外部程序来评估一个超越函数,但它不起作用,因此问题的起源:-)。
from z3 import *
from ExternalCodes import Code1, Code2 #For example, these could be Python wrappers to C++ codes

def g_1(x, y):
    return Code1(x, y) #isinstance(Code1(x,y), float) == True

def g_2(x, y):
    return Code2(x, y) #isinstance(Code2(x,y), float) == True

s = Solver()

x, y = Reals('x y')
s.add(g_1(x, y) <= 25.0)
s.add(g_2(x, y) >= 7.7)
s.add(x <= 0)
s.add(50.0 <= x)
s.add(y <= 0)
s.add(5.0 <= y)

m = s.model()
print(m)