在 z3py 中声明外部函数
Declare External Functions in z3py
场景
在数学优化领域,需要对不等式 g_k(...)
约束进行建模。 g_k(...)
有时可以是对外部程序的函数调用,就所有意图和目的而言,它是一个黑盒子。简单地找到满意的答案对于某些工程分析可能是有益的。
例子
上述场景的示例应用程序,但也可以是整数或布尔值:
min f(x,y)
g1(x,y) <= 25
g2(x,y) >= 7.7
x,y ε Real
x >= 0
x <= 50.0
y >= 0
y <= 5.0
g1和g2是调用外部程序的Python函数。函数 return 一个实数。按照 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)
问题
- 我明白Code1和Code2编辑的return类型需要是Z3
数据类型。如何将 Python 类型转换为第 1 条中提到的 Z3 类型
comment
- 当可能需要约束时,如何使用 Z3 查找 sat 模型
在外部代码中评估,即声明函数?我明白
可能效率低下,我会放松启发式等,因为它是不可判定的,
但对于某些工程应用,枚举一个 sat 解决方案,如果它
存在,比从一开始就使用优化器更有优势。
相关回答
z3python: using math library
-不完全相同的应用程序。我很好奇,4年后,这个答案是否仍然如此,但这不是我的问题。
Can Z3 call an externally defined function?
-本质上,同一个问题。 Z3Py 没有答案,不幸的是,Rise4fun link 坏了。我也无法在 Github repo
中找到提到的 F#/.NET 示例
您正在寻找未解释的函数。
在 http://ericpony.github.io/z3py-tutorial/advanced-examples.htm
中搜索字词 "uninterpreted functions"
您的问题似乎对如何使用 SMT 求解器做出了一些假设;这并不能完全反映当前的最新技术水平。阅读有关 SMT 求解器的使用的一个很好的资源是:https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/nbjorner-smt-application-chapter.pdf 花时间仔细阅读它以了解它在实践中的应用是非常值得的。
一些一般性评论:
Z3py
Z3py 不是 用于推理 Python 程序的系统。 Z3py 是库的集合,因此您可以以更清晰、更简单的方式编写 Z3 脚本。许多语言都有许多这样的绑定:C/C++/Java/Haskell/Scala,随你便。 Z3py的优点是更容易学习和使用。但是您不应该将其视为推理 Python 本身的系统。它只是一种以轻量级形式编写 Z3 脚本的方法。
求解器逻辑
SMT 求解器主要处理各种理论的(主要是无量词的)多分类逻辑的可判定片段。您可以在以下位置找到详细信息:http://smtlib.cs.uiowa.edu/logics.shtml
SMTLib
大多数求解器接受所谓的 SMT-Lib 格式的输入,详情请见此处:http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf
请注意,C/Python/Java 等级别的任何 "binding" 只是为了方便程序员。虽然许多求解器还提供扩展功能,但您应该想到 SMTLib 语言。在您的特定情况下,上述文档中详细描述了未解释的函数。
类型
SMTLib 理解一组类型:整数、实数、位向量(机器整数)、浮点数等。它还允许复合类型,例如代数数据类型,甚至可以递归。 (尽管求解器支持各不相同。)您必须 "map" 您的外部函数类型为这些类型:希望有足够接近的东西。如果没有,请随时提出有关您感兴趣的类型的具体问题。
"Importing" 函数
不可能将用其他语言(Python/C/C++等)编写的函数导入到 SMTLib 中并对其进行推理。没有这样做的机制,也永远不会有。这不是 SMT 求解器的目标。如果您想对用特定语言编写的程序进行推理,那么您应该寻找专门设计用于这些语言的工具。 (例如 Dafny 用于一般命令式程序,Klee/CBMC 用于 C 程序,LiquidHaskell 用于 Haskell 程序等)这些工具的功能各不相同,它们允许您指定和证明。请注意,这些工具本身可以使用下面的 SMT 求解器来完成它们的任务——它们经常这样做,而不是相反。
坚持使用 SMTLib
如果没有其他工具可用(不幸的是,大多数语言都可能是这种情况,尤其是传统语言),您基本上只能使用 SMTLib 语言提供的任何工具。在您的情况下,使用 SMTLib 对此类 "external" 函数建模的最佳方法是使用未解释的函数以及公理。通常,您需要公理来限制未解释函数本身的行为,以便为您的外部函数建模。另一方面,如果公理被量化(通常它们会被量化),求解器可能 return unknown
.
总结
虽然 SMT 求解器是很棒的工具,但您应该始终记住,它们运行的语言是 SMTLib,而不是 Python/C 或其他任何语言。这些绑定只是访问求解器的方式,因为您可能会将其合并到更大的项目中。我希望清除预期的用例。
询问有关您已尝试过的内容和您想要实现的内容(代码示例)的具体问题是从该论坛中获取更多信息的最佳方式!
场景
在数学优化领域,需要对不等式 g_k(...)
约束进行建模。 g_k(...)
有时可以是对外部程序的函数调用,就所有意图和目的而言,它是一个黑盒子。简单地找到满意的答案对于某些工程分析可能是有益的。
例子
上述场景的示例应用程序,但也可以是整数或布尔值:
min f(x,y)
g1(x,y) <= 25
g2(x,y) >= 7.7
x,y ε Real
x >= 0
x <= 50.0
y >= 0
y <= 5.0
g1和g2是调用外部程序的Python函数。函数 return 一个实数。按照 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)
问题
- 我明白Code1和Code2编辑的return类型需要是Z3 数据类型。如何将 Python 类型转换为第 1 条中提到的 Z3 类型 comment
- 当可能需要约束时,如何使用 Z3 查找 sat 模型 在外部代码中评估,即声明函数?我明白 可能效率低下,我会放松启发式等,因为它是不可判定的, 但对于某些工程应用,枚举一个 sat 解决方案,如果它 存在,比从一开始就使用优化器更有优势。
相关回答
z3python: using math library
-不完全相同的应用程序。我很好奇,4年后,这个答案是否仍然如此,但这不是我的问题。
Can Z3 call an externally defined function?
-本质上,同一个问题。 Z3Py 没有答案,不幸的是,Rise4fun link 坏了。我也无法在 Github repo
中找到提到的 F#/.NET 示例
您正在寻找未解释的函数。
在 http://ericpony.github.io/z3py-tutorial/advanced-examples.htm
中搜索字词 "uninterpreted functions"您的问题似乎对如何使用 SMT 求解器做出了一些假设;这并不能完全反映当前的最新技术水平。阅读有关 SMT 求解器的使用的一个很好的资源是:https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/nbjorner-smt-application-chapter.pdf 花时间仔细阅读它以了解它在实践中的应用是非常值得的。
一些一般性评论:
Z3py
Z3py 不是 用于推理 Python 程序的系统。 Z3py 是库的集合,因此您可以以更清晰、更简单的方式编写 Z3 脚本。许多语言都有许多这样的绑定:C/C++/Java/Haskell/Scala,随你便。 Z3py的优点是更容易学习和使用。但是您不应该将其视为推理 Python 本身的系统。它只是一种以轻量级形式编写 Z3 脚本的方法。
求解器逻辑
SMT 求解器主要处理各种理论的(主要是无量词的)多分类逻辑的可判定片段。您可以在以下位置找到详细信息:http://smtlib.cs.uiowa.edu/logics.shtml
SMTLib
大多数求解器接受所谓的 SMT-Lib 格式的输入,详情请见此处:http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf
请注意,C/Python/Java 等级别的任何 "binding" 只是为了方便程序员。虽然许多求解器还提供扩展功能,但您应该想到 SMTLib 语言。在您的特定情况下,上述文档中详细描述了未解释的函数。
类型
SMTLib 理解一组类型:整数、实数、位向量(机器整数)、浮点数等。它还允许复合类型,例如代数数据类型,甚至可以递归。 (尽管求解器支持各不相同。)您必须 "map" 您的外部函数类型为这些类型:希望有足够接近的东西。如果没有,请随时提出有关您感兴趣的类型的具体问题。
"Importing" 函数
不可能将用其他语言(Python/C/C++等)编写的函数导入到 SMTLib 中并对其进行推理。没有这样做的机制,也永远不会有。这不是 SMT 求解器的目标。如果您想对用特定语言编写的程序进行推理,那么您应该寻找专门设计用于这些语言的工具。 (例如 Dafny 用于一般命令式程序,Klee/CBMC 用于 C 程序,LiquidHaskell 用于 Haskell 程序等)这些工具的功能各不相同,它们允许您指定和证明。请注意,这些工具本身可以使用下面的 SMT 求解器来完成它们的任务——它们经常这样做,而不是相反。
坚持使用 SMTLib
如果没有其他工具可用(不幸的是,大多数语言都可能是这种情况,尤其是传统语言),您基本上只能使用 SMTLib 语言提供的任何工具。在您的情况下,使用 SMTLib 对此类 "external" 函数建模的最佳方法是使用未解释的函数以及公理。通常,您需要公理来限制未解释函数本身的行为,以便为您的外部函数建模。另一方面,如果公理被量化(通常它们会被量化),求解器可能 return unknown
.
总结
虽然 SMT 求解器是很棒的工具,但您应该始终记住,它们运行的语言是 SMTLib,而不是 Python/C 或其他任何语言。这些绑定只是访问求解器的方式,因为您可能会将其合并到更大的项目中。我希望清除预期的用例。
询问有关您已尝试过的内容和您想要实现的内容(代码示例)的具体问题是从该论坛中获取更多信息的最佳方式!