编码返回“未知”

时间:2013-02-11 22:00:47

标签: z3 cvc4

对于这个例子:http://pastebin.com/QyebfD1p z3和cvc4返回"未知"由于检查 - 坐。两者对原因都不是很冗长,有没有办法让z3对它的执行更加冗长?

1 个答案:

答案 0 :(得分:2)

您的脚本使用策略

s = Then('simplify','smt').solver()

这种策略应用Z3简化器,然后执行"通用" Z3中提供SMT求解器。对于非线性算法,此解算器完整。它基于以下组合:Simplex,Interval Arithmetic和Grobner Basis。该模块的一大缺点是它无法找到包含无理数的模型/解决方案。将来,我们将使用Z3中提供的新的非线性求解器替换此模块。

对于非线性算法,我们通常建议在Z3中使用nlsat求解器。这是一个完整的过程,通常对不可满足和可满足的实例非常有效。您可以在this article中找到有关nlsat的更多信息。 要使用nlsat,我们必须使用

s = Tactic('qfnra-nlsat').solver()

不幸的是,nlsat会陷入你的榜样。它会在计算过程中产生非常大的多项式计算Subresultants

Z3还有另一个处理非线性算法的引擎。该引擎将问题减少到了SAT。它仅对具有a + b sqrt(2)形式的解决方案的可满足问题有效,其中ab是有理数。使用此引擎,我们可以在很短的时间内解决您的问题。我将结果附在帖子的末尾。要使用此引擎,我们必须使用

s = Then('simplify', 'nla2bv', 'smt').solver()

编辑此外,策略nla2bv将有理数ab编码为一对位向量。默认情况下,它使用大小为4的位向量。但是,可以使用选项nlsat_bv_size指定此值。这不是一个全局选项,而是提供给策略nla2bv的选项。因此,nla2bv只能找到a + b sqrt(2)形式的解决方案,其中ab可以使用少量位进行编码。如果一个可满足的问题没有这种形式的解决方案,这种策略将失败并返回unknown结束编辑

您的示例还表明,我们必须改进nlsat,并使其作为模型/解决方案查找过程更有效。 当试图表明问题没有解决方案时,当前版本卡住了。 我们意识到这些限制,并正在制定新的程序来解决这些问题。

BTW,在Python前端,Z3以十进制表示法显示模型/解决方案。但是,一切都是精确计算的。获得解决方案的精确表示。我们可以使用方法sexpr()。例如,我将循环更改为

for d in m.decls():
    print "%s = %s = %s" % (d.name(), m[d], m[d].sexpr())

在新循环中,我以十进制表示法显示结果,并以内部精确表示。 (root-obj (+ (* 2 (^ x 2)) (* 12 x) (- 7)) 2)的含义是多项式2*x^2 + 12x - 7的第二个根。

修改 Z3提供combinators来创建非平凡的求解器。在上面的示例中,我们使用Then来执行不同策略的顺序组合。我们也可以使用OrElse来尝试不同的策略。和TryFor(t, ms)t毫秒内尝试战术ms,如果问题无法在给定时间内解决,则会失败。这些组合器可用于创建使用不同策略来解决问题的策略。 结束编辑

sat
Presenting results
traversing model...
s_2_p_p = 0.5355339059? = (root-obj (+ (* 2 (^ x 2)) (* 12 x) (- 7)) 2)
s_1_p_p = 0 = 0.0
s_init_p_p = 0.2928932188? = (root-obj (+ (* 2 (^ x 2)) (* (- 4) x) 1) 1)
s_2_p = 0.7071067811? = (root-obj (+ (* 2 (^ x 2)) (- 1)) 2)
s_1_p = 0 = 0.0
s_init_p = 0.2928932188? = (root-obj (+ (* 2 (^ x 2)) (* (- 4) x) 1) 1)
epsilon = 0 = 0.0
p_b2_s2_s_sink = 0.9142135623? = (root-obj (+ (* 4 (^ x 2)) (* 4 x) (- 7)) 2)
p_b2_s2_s_target = 0.0857864376? = (root-obj (+ (* 4 (^ x 2)) (* (- 12) x) 1) 1)
p_b2_s2_s_2 = 0 = 0.0
p_b2_s2_s_1 = 0 = 0.0
p_a2_s2_s_sink = 0 = 0.0
p_a2_s2_s_target = 0.8284271247? = (root-obj (+ (^ x 2) (* 4 x) (- 4)) 2)
p_a2_s2_s_2 = 0.1715728752? = (root-obj (+ (^ x 2) (* (- 6) x) 1) 1)
p_a2_s2_s_1 = 0 = 0.0
sigma_s2_b2 = 1 = 1.0
sigma_s2_a2 = 0 = 0.0
p_b1_s1_s_sink = 1 = 1.0
p_b1_s1_s_target = 0 = 0.0
p_b1_s1_s_2 = 0 = 0.0
p_b1_s1_s_1 = 0 = 0.0
p_a1_s1_s_sink = 1 = 1.0
p_a1_s1_s_target = 0 = 0.0
p_a1_s1_s_2 = 0 = 0.0
p_a1_s1_s_1 = 0 = 0.0
sigma_s1_b1 = 0 = 0.0
sigma_s1_a1 = 1 = 1.0
p_sinit_sink = 0.7071067811? = (root-obj (+ (* 2 (^ x 2)) (- 1)) 2)
p_sinit_target = 0.2928932188? = (root-obj (+ (* 2 (^ x 2)) (* (- 4) x) 1) 1)
p_sinit_2 = 0 = 0.0
p_sinit_1 = 0 = 0.0
s_sink = 0 = 0.0
s_target = 1 = 1.0
s_2 = 0.0857864376? = (root-obj (+ (* 4 (^ x 2)) (* (- 12) x) 1) 1)
s_1 = 0 = 0.0
s_init = 0.2928932188? = (root-obj (+ (* 2 (^ x 2)) (* (- 4) x) 1) 1)

修改 您可以使用策略

解决评论中的问题
s = Then('simplify', 'nlsat').solver()

这种策略将在几秒钟内解决问题,并在帖子结束时产生解决方案。如上所述,nlsat已完成,但可能需要很长时间。 您的问题是当前版本的Z3可以自动决定/解决的问题。我们可以将不同的策略与OrElseTryFor结合使用,以使其更加稳定。例如:

s = OrElse(TryFor(Then('simplify', 'nla2bv', 'smt', 'fail-if-undecided'), 1000),
           TryFor(Then('simplify', 'nlsat'), 1000),
           TryFor(Then('simplify', 'nla2bv', 'smt', 'fail-if-undecided'), 10000),
           Then('simplify', 'nlsat')).solver()

上面的策略尝试nla2bv方法1秒,然后nlsat 1秒,然后nla2bv 10秒,最后nlsat没有超时。< / p>

我知道这不是一个理想的解决方案,但是这样的变化可能是有用的解决方法,直到非线性算法的下一个求解器准备就绪。此外,在我们调用nlsat之前,Z3还有许多其他策略可用于简化/预处理问题。 结束编辑

s_init = 15/32
s_1 = 7/16
s_2 = 1/2
s_target = 1
s_sink = 0
p_sinit_1 = 1/2
p_sinit_2 = 1/4
p_sinit_target = 1/8
p_sinit_sink = 1/8
sigma_s1_a1 = 1/2
sigma_s1_b1 = 1/2
p_a1_s1_s_1 = 1/2
p_a1_s1_s_2 = 1/4
p_a1_s1_s_target = 1/8
p_a1_s1_s_sink = 1/8
p_b1_s1_s_1 = 1/2
p_b1_s1_s_2 = 1/4
p_b1_s1_s_target = 1/16
p_b1_s1_s_sink = 3/16
sigma_s2_a2 = 1/2
sigma_s2_b2 = 1/2
p_a2_s2_s_1 = 1/2
p_a2_s2_s_2 = 1/4
p_a2_s2_s_target = 11/64
p_a2_s2_s_sink = 5/64
p_b2_s2_s_1 = 3/4
p_b2_s2_s_2 = 1/32
p_b2_s2_s_target = 9/64
p_b2_s2_s_sink = 5/64
epsilon = 1/4
s_init_p = 1649/3520
s_1_p = 797/1760
s_2_p = 103/220
s_init_p_p = 1809/3904
s_1_p_p = 813/1952
s_2_p_p = 127/244

编辑2 你的问题正处于Z3在合理的时间内可以做的事情的边缘。非线性实数算术是可判定的,但是非常昂贵。关于调试/跟踪Z3中发生的事情。以下是一些可能性:

  • 我们可以使用以下命令启用详细消息:set_option("verbose", 10)。 数字是详细级别:0 ==&#34;没有消息&#34;和更高的数字==&#34;更多消息&#34;。

  • 编译Z3并支持跟踪。有关详细信息,请参阅this post

  • 使用命令open_log("z3.log")创建Python程序调用的Z3 API的日志。应在任何其他Z3 API调用之前调用此命令。然后使用z3内的gdb可执行文件执行日志。 因此,您将能够停止执行并找到Z3卡在哪里。 nlsat解算器通常会卡在两个不同的位置:

    1. 计算子顾问(程序psc_chain将在堆栈上),

    2. 用代数系数隔离多项式的根(过程isolate_roots将在堆栈上)。

在我们用更有效的new one替换旧的代数数字包之后,问题2将很快修复。不幸的是,似乎你的问题陷入了subresultant步骤。

另一个评论:虽然nla2bv对您的原始基准有效,但您的新基准不太可能有a + b sqrt(2)形式的解决方案ab有理数。因此,使用nla2bv只是开销。策略nlsat假定问题出现在CNF中。因此,对于pastebin.com/QRCUQE10,我们必须在调用tseitin-cnf之前调用nlsat。另一个选择是使用&#34; big&#34;策略qfnra-nlsat。它在调用nlsat之前调用许多预处理步骤。但是,其中一些步骤可能会使一些问题难以解决。

END EDIT 2