使用 Z3 SMT 解决谓词演算问题

2024-02-16

我想使用 Z3 来解决最自然地用原子(符号)、集合、谓词和一阶逻辑表达的问题。例如(伪代码):

A = {a1, a2, a3, ...} # A is a set
B = {b1, b2, b3...}
C  = {c1, c2, c3...}

def p = (a:A, b:B, c:C) -> Bool # p is unspecified predicate
def q = (a:A, b:B, c:C) -> Bool

# Predicates can be defined in terms of other predicates:
def teaches = (a:A, b:B) -> there_exists c:C 
                            such_that [ p(a, b, c) OR q(a, b, c)  ]

constraint1 = forall b:B there_exists a:A
                         such_that teaches(a, b)

solve(constraint1)

在 Z3(或其他 SMT)中表达原子、集合、谓词、关系和一阶量词的好方法是什么?

这有标准的习语吗?必须手动完成吗?是否有一个翻译库(不一定特定于 Z3)可以转换它们?

我相信 Alloy 使用 SMT 来实现谓词逻辑和关系,但 Alloy 似乎更多是为了交互式使用而设计的,以探索模型的一致性,而不是寻找问题的具体解决方案。


在 SMTLib 中对谓词逻辑进行建模确实是可能的;尽管与 Isabelle/HOL 等常规定理证明器相比,它可能有点麻烦。并且解释结果可能需要相当多的眯眼。

话虽如此,这里是使用 SMTLib 对示例问题的直接编码:

(declare-sort A)
(declare-sort B)
(declare-sort C)

(declare-fun q (A B C) Bool)
(declare-fun p (A B C) Bool)

(assert (forall ((b B))
  (exists ((a A))
    (exists ((c C)) (or (p a b c) (q a b c))))))

(check-sat)
(get-model)

一些注意事项:

  • declare-sort创建未解释的排序。它本质上是一组非空值。 (也可以是无限的,除了它不为空的事实之外,没有做出任何基数假设。)对于您的具体问题,这种类型实际上是什么并不重要,因为您没有使用它的任何直接元素。如果这样做,您可能还想尝试“声明”排序,即数据类型声明。这可以是一个枚举,或者更复杂的东西;取决于问题。对于当前提出的问题,未解释的排序就可以了。

  • declare-fun告诉求解器有一个具有该名称和签名的未解释函数。但除此之外,它既不定义它,也不以任何方式限制它。您可以添加有关它们的“公理”,以更具体地说明它们的行为方式。

  • 支持量词,如您所见forall and exists在如何你的constraint1被编码。请注意,SMTLib 不太适合代码重用,通常在更高级别的绑定中进行编程。 (提供了来自 C/C++/Java/Python/Scala/O'Caml/Haskell 等的绑定,具有类似但不同程度的支持和功能。)否则,它应该易于阅读。

  • 我们终于发出check-sat and get-model,要求求解器创建一个满足所有断言约束的宇宙。如果是这样,它将打印sat并且会有一个模型。否则,它会打印unsat如果没有这样的宇宙;或者它也可以打印unknown(或永远循环!)如果它无法决定。量词的使用对于 SMT 求解器来说是很难处理的,大量使用量词无疑会导致unknown作为答案。这是一阶谓词演算的半可判定性的固有限制。

当我通过 z3 运行此规范时,我得到:

sat
(
  ;; universe for A:
  ;;   A!val!1 A!val!0
  ;; -----------
  ;; definitions for universe elements:
  (declare-fun A!val!1 () A)
  (declare-fun A!val!0 () A)
  ;; cardinality constraint:
  (forall ((x A)) (or (= x A!val!1) (= x A!val!0)))
  ;; -----------
  ;; universe for B:
  ;;   B!val!0
  ;; -----------
  ;; definitions for universe elements:
  (declare-fun B!val!0 () B)
  ;; cardinality constraint:
  (forall ((x B)) (= x B!val!0))
  ;; -----------
  ;; universe for C:
  ;;   C!val!0 C!val!1
  ;; -----------
  ;; definitions for universe elements:
  (declare-fun C!val!0 () C)
  (declare-fun C!val!1 () C)
  ;; cardinality constraint:
  (forall ((x C)) (or (= x C!val!0) (= x C!val!1)))
  ;; -----------
  (define-fun q ((x!0 A) (x!1 B) (x!2 C)) Bool
    (and (= x!0 A!val!0) (= x!2 C!val!0)))
  (define-fun p ((x!0 A) (x!1 B) (x!2 C)) Bool
    false)
)

这需要眯起眼睛才能完全理解。第一组值告诉您求解器如何为未解释的排序构建模型A, B, and C;具有见证元素和基数约束。尽管它确实包含有用的信息,但大多数情况下您可以忽略这部分。例如,它告诉我们A是一个包含两个元素的集合(名为A!val!0 and A!val!1),也是如此C, and B只有一个元素。根据您的限制,您将获得不同的元素集。

For p, 我们看:

  (define-fun p ((x!0 A) (x!1 B) (x!2 C)) Bool
    false)

这意味着p总是False;即,无论传递给它的参数是什么,它都是空集。

For q we get:

 (define-fun q ((x!0 A) (x!1 B) (x!2 C)) Bool
    (and (= x!0 A!val!0) (= x!2 C!val!0)))

让我们更简单地重写一下:

 q (a, b, c) = a == A0 && c == C0

where A0 and C0是这样的成员A and C分别;请参阅上面的排序声明。所以,它说q is True每当a is A0, c is C0,并且什么都不重要b is.

您可以让自己相信这个模型确实满足您想要的约束。

总结;在 z3 中对这些问题进行建模确实是可能的,尽管有点笨拙和大量使用量词可能会使求解器永远循环或返回unknown。解释输出可能有点麻烦,尽管您会意识到模型将遵循类似的模式:首先是未解释的排序,然后是谓词的定义。

边注

正如我提到的,在 SMTLib 中对 z3 进行编程既麻烦又容易出错。这是使用 Python 接口完成的相同程序:

from z3 import *

A = DeclareSort('A')
B = DeclareSort('B')
C = DeclareSort('C')

p = Function('p', A, B, C, BoolSort())
q = Function('q', A, B, C, BoolSort())

dummyA = Const('dummyA', A)
dummyB = Const('dummyB', B)
dummyC = Const('dummyC', C)

def teaches(a, b):
    return Exists([dummyC], Or(p(a, b, dummyC), q(a, b, dummyC)))

constraint1 = ForAll([dummyB], Exists([dummyA], teaches(dummyA, dummyB)))

s = Solver()
s.add(constraint1)
print(s.check())
print(s.model())

这也有一些特性,但如果您选择在 Python 中对 z3 进行编程,希望它能为您的探索提供一个起点。这是输出:

sat
[p = [else -> And(Var(0) == A!val!0, Var(2) == C!val!0)],
 q = [else -> False]]

它具有与 SMTLib 输出完全相同的信息,但编写方式略有不同。

函数定义风格

请注意,我们定义了teaches作为常规 Python 函数。这是 z3py 编程中的常见风格,因为它生成的表达式会在调用时被替换。您还可以创建一个 z3 函数,如下所示:

teaches = Function('teaches', A, B, BoolSort())
s.add(ForAll([dummyA, dummyB],
       teaches(dummyA, dummyB) == Exists([dummyC], Or(p(dummyA, dummyB, dummyC), q(dummyA, dummyB, dummyC)))))

请注意,这种定义风格将依赖于内部量词实例化,而不是 SMTLib 的通用函数定义工具。因此,您通常应该更喜欢 python 函数风格,因为它可以转换为“更简单”的内部结构。一般来说,它的定义和使用也更容易。

您需要 z3 函数定义样式的一种情况是,如果您定义的函数是递归的并且其终止依赖于符号参数。有关此问题的讨论,请参阅:https://stackoverflow.com/a/68457868/936310 https://stackoverflow.com/a/68457868/936310

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Z3 SMT 解决谓词演算问题 的相关文章

  • Z3 -smt2 -in:获取Z3版本

    使用选项启动后可以获得Z3的版本吗 smt2 in 就像是 get z3 version Z3 4 3 2 x64 Desired reply 在SMT LIB 2 0前端 我们可以使用命令 get info version 该命令是标准的
  • z3 中如何定义 Int 排序(SMT-LIB 2.0 Ints 理论)和动态声明排序?

    这是我使用 z3 执行的 SMT LIB 2 0 基准测试 set logic AUFLIA declare sort PZ 0 declare fun MS Int PZ Bool assert forall x Int exists X
  • Z3Py 中最大值的模型不正确

    我想找到一个表达式的最大间隔e对于所有 x 都成立 编写这样的公式的方法应该是 Exists d ForAll x in d d e and ForAll x not in d d e 为了得到这样一个d 公式f在 Z3 中 看上面的 可能
  • 为什么0=0.5?

    我注意到 Z3 4 3 1 在处理 smt2 文件时出现一些奇怪的行为 If I do assert 0 0 5 就会得到满足 但是 如果我改变顺序并执行 assert 0 5 0 这是不能令人满意的 我对发生的情况的猜测是 如果第一个参数
  • z3 是否支持有理算术的输入约束?

    事实上 SMT LIB标准是否有理性的 不仅仅是真实的 排序 按其website http smtlib cs uiowa edu theories shtml 它不是 如果 x 是有理数并且我们有约束 x 2 2 那么我们应该返回 不可满
  • 以字段名称作为参数的表达式谓词

    我使用这段代码 在 stackoverflow 上找到 来生成谓词 static class BuilderPredicate public static Expression
  • 为什么 Z3 中的运算符“/”和“div”给出不同的结果?

    我试图用两个整数来表示一个实数 并将它们用作实数的分子和分母 我写了以下程序 declare const a Int declare const b Int declare const f Real assert f a b assert
  • 了解 z3 模型

    Z3Py 片段 x Int x fun Function fun IntSort IntSort IntSort phi ForAll x fun x x x print phi solve phi 永久链接 http rise4fun c
  • 目标没有战术支持

    我有一些代码 我想在一些策略的帮助下检查它们 因为我有很多if then else声明 我要申请elim term ite tactic 我使用了以下策略 check sat using then simplify arith lhs tr
  • SMT中量化算术推理的局限性是什么?

    我在以下看似微不足道的基准测试中尝试了几种 SMT 求解器 CVC3 CVC4 和 Z3 set logic LIA set info smt lib version 2 0 assert forall x Int forall y Int
  • 如何组合 List> 中的所有谓词

    我有一个问题 我相信你能帮助我解决我的皱纹 I have List
  • Prolog 变量查询中的“\+”问题

    我正在读 七周七种语言 atm 我对一些 Prolog 查询感到困惑 我不明白对 否 的回答 The friends pl文件看起来像这样 likes wallace cheese likes grommit cheese likes we
  • 使用 Java 8 谓词的 JPA 存储库过滤器

    我在使用 Spring Boot 的一次面试测试中有一个要求 我必须创建一个端点 该端点接受一堆可选请求参数 然后根据这些参数 如汽车型号 车牌 发动机类型 制造商 返回汽车列表 司机 租赁公司等 汽车 司机和制造商都是独立的实体 我在 J
  • 如何实现 not_all_equal/1 谓词

    如何实施not all equal 1谓词 如果给定列表包含至少 2 个不同的元素 则该谓词成功 否则失败 这是我的尝试 不是很纯粹的尝试 not all equal L member H1 L member H2 L H1 H2 gt t
  • C++ 中谓词是什么? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 您能举一些例子或主题链接吗 谓词是一
  • (Z3Py) 声明函数

    我想在简单的 result x t c 公式中找到一些给定结果 x 对的 c 和 t 系数 from z3 import x Int x c Int c t Int t s Solver f Function f IntSort IntSo
  • Z3统计中内存使用量的单位是什么?

    z3 统计中测量内存使用情况的单位是什么 是MB还是KB 记忆到底意味着什么 是执行期间的最大内存使用量还是所有分配的总和 它是执行期间最大堆大小的近似值 并通过 cmd context cpp 中的以下函数将其添加到统计对象中 void
  • 如何用 Java 或 C# 等语言实现统一算法?

    我正在读我拿到的人工智能教科书 我已经解决了我的部分的最后一个作业问题 以您选择的任何语言实施第 69 页概述的统一算法 在第 69 页 您有以下统一算法的伪代码 function unify E1 E2 begin case both E
  • 如何将谓词作为参数传递#

    如何将谓词传递到方法中 但在没有传递谓词的情况下仍使其工作 我想也许是这样的 但似乎并不正确 private bool NoFilter return true private List
  • 如何将表达式> 转换为谓词

    我有一个方法接受Expression

随机推荐