在数学优化的世界中,需要对不等式g_k(...)
约束进行建模。 g_k(...)
有时可以是对外部程序的函数调用,对于所有意图和目的,它都是一个黑盒子。简单地找到满意的答案对某些工程分析是有益的。
上述Reals场景的示例应用,但也可能是Ints或Booleans:
min f(x,y)
g 1 (x,y)< = 25
g 2 (x,y)> = 7.7
x,yε实际
x> = 0
x <= 50.0
y&gt; = 0
y&lt; = 5.0
g 1 和g 2 是调用外部程序的Python函数。这些函数返回一个实数。遵循this Z3格式来查找简单地满足约束的模型将表示为:
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)
- 完全相同的应用程序。我很好奇4年后,这个答案是否仍然如此,但这不是我的问题。
Can Z3 call an externally defined function?
- 本质上,同样的问题。没有Z3Py回答,不幸的是,Rise4fun链接被破坏了。我也找不到Github repo中提到的F#/ .NET示例
答案 0 :(得分:1)
您正在寻找未解释的功能。
在http://ericpony.github.io/z3py-tutorial/advanced-examples.htm
中搜索“未解释的函数”一词您的问题似乎对如何使用SMT求解器做出了一些假设;这并不完全反映当前最先进的技术。阅读有关使用SMT求解器的一个很好的资源是:https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/nbjorner-smt-application-chapter.pdf值得花些时间去研究它在实践中的应用。
一些一般性意见:
Z3py 不是用于推理Python程序的系统。 Z3py是一个库的集合,因此您可以更清晰,更简单的方式编写Z3脚本。许多语言都有很多这样的绑定:C / C ++ / Java / Haskell / Scala,你可以命名。 Z3py的优势在于它更易于学习和使用。但你不应该把它当作一个推理Python本身的系统。它只是一种以轻量级形式编写Z3脚本的方法。
SMT求解器基本上处理各种理论的可判断片段(主要是无量词的)许多分类逻辑。您可以在http://smtlib.cs.uiowa.edu/logics.shtml
中详细了解这些内容大多数求解器接受所谓的SMT-Lib格式的输入,详见:http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf
请注意,C / Python / Java等级别的任何“绑定”仅仅是程序员的便利。虽然许多求解器也提供扩展功能,但您应该想到SMTLib语言。在您的特定情况下,上述文档中详细描述了未解释的函数。
SMTLib理解一组类型:整数,实数,位向量(机器整数),浮点等。它还允许复合类型,如代数数据类型,甚至可以递归。 (虽然解算器支持有所不同。)你必须将你的外部函数类型“映射”到这些类型:希望有足够接近的东西。如果没有,请随时询问您感兴趣的类型的具体问题。
不可能将用其他语言编写的函数(Python / C / C ++等)导入SMTLib并对其进行推理。没有这样做的机制,也不会有。这不是SMT求解器的目标。如果您想推理用特定语言编写的程序,那么您应该寻找专门用于处理这些语言的工具。 (例如Dafny用于一般命令式程序,Klee / CBMC用于C程序,LiquidHaskell用于Haskell程序等)这些工具的功能各不相同,它们允许您指定和证明。请注意,这些工具本身可以使用下面的SMT求解器来完成他们的任务 - 而且他们经常这样做,而不是相反。
如果没有其他工具可用(不幸的是,大多数语言可能就是这种情况,特别是遗留的那些),你基本上都会遇到SMTLib语言所提供的问题。在您的情况下,使用SMTLib对这种“外部”函数进行建模的最佳方法是使用未解释的函数以及公理。通常,您需要公理来限制未解释函数本身的行为,以模拟外部函数。另一方面,如果公理是量化的(通常它们将是),求解器可能会返回unknown
。
虽然SMT求解器是很好的工具,但您应该始终牢记它们所使用的语言是SMTLib,而不是Python / C或其他任何东西。这些绑定只是访问解算器的方法,因为您可以将其合并到一个更大的项目中。我希望能够清除预期的用例。
询问有关您尝试过的具体问题以及您尝试实现的目标(代码示例)是获取此论坛的最佳方式!