我正在使用Z3来检查一些量化的公式 . 如果我通过Z3的Java API断言公式,如果公式不合格,MBQI引擎可能不会收敛 . 我知道我的公式不是FOL的片段,已知它是可判定的,但是如果我通过Z3的smt-lib接口输入相同的公式,它会很快产生答案 . 我怀疑某些选项不是通过通常使用正常SMTLIB输入激活的API设置的,或者我没有通过API向公式添加重要的元信息 .
以下SMTLIB会话中的断言直接来自BoolExpr的toString,我通过API断言:
(set-option :smt.mbqi true)
(set-option :smt.pull-nested-quantifiers true)
(set-option :smt.mbqi.trace true)
(declare-fun R (Int Int) Bool)
(declare-const |'x| Int)
(declare-const |'y| Int)
(assert
(let ((a!1 (forall ((|'x0| Int) (|'y0| Int))
(= (R |'x0| |'y0|)
(and (forall ((|'y1| Int) (a Int))
(let ((a!1 (not (or (and (= |'y0| 0) (= |'y1| 1))
(and (= |'y0| 1) (= |'y1| 3))
(and (= |'y0| 2) (= |'y1| 3))
(and (= |'y0| 0) (= |'y1| 2)))))
(a!2 (exists ((|'x1| Int))
(and (or (and (= |'x0| 3) (= |'x1| 0))
(and (= |'x0| 1) (= |'x1| 3))
(and (= |'x0| 1) (= |'x1| 2))
(and (= |'x0| 2) (= |'x1| 0))
(and (= |'x0| 0) (= |'x1| 1)))
(R |'x1| |'y1|)))))
(or a!1 a!2)))
(forall ((|'x1| Int) (a Int))
(let ((a!1 (not (or (and (= |'x0| 3) (= |'x1| 0))
(and (= |'x0| 1) (= |'x1| 3))
(and (= |'x0| 1) (= |'x1| 2))
(and (= |'x0| 2) (= |'x1| 0))
(and (= |'x0| 0) (= |'x1| 1)))))
(a!2 (exists ((|'y1| Int))
(and (or (and (= |'y0| 0) (= |'y1| 1))
(and (= |'y0| 1) (= |'y1| 3))
(and (= |'y0| 2) (= |'y1| 3))
(and (= |'y0| 0) (= |'y1| 2)))
(R |'x1| |'y1|)))))
(or a!1 a!2))))))))
(and (= |'x| 0) (= |'y| 0) (R |'x| |'y|) a!1)))
(check-sat)
有趣的是,当我通过Z3的SMTLIB接口运行上述内容时,MBQI跟踪很短,看起来像这样:
(smt.mbqi "started")
(smt.mbqi :checking k!37)
(smt.mbqi :failed k!37)
(smt.mbqi :num-failures 1)
...
(smt.mbqi "started")
(smt.mbqi :checking k!37)
(smt.mbqi :failed k!37)
(smt.mbqi :num-failures 1)
unsat
但是,通过API运行时的跟踪(以及相同的求解器选项)如下所示:
(smt.mbqi "started")
(smt.mbqi :failed null)
(smt.mbqi :num-failures 1)
(smt.mbqi "started")
(smt.mbqi :failed null)
(smt.mbqi :num-failures 1)
“null”引用是否表明我在API方面做错了什么?
1 回答
我在复制失败行为方面遇到了一些麻烦 . 以下是我如何模拟API行为:
在我的情况下,Z3迅速返回,答案不满意 . 与行为相关的主要方法是使用详细跟踪 . 详细描述将显示调用的策略 . 您可以使用SMT-LIB中的详细跟踪(从命令行传递选项-v:10或类似的数字) .