什么是 z3 中的 `root-object` with Real theory?

What is `root-object` in z3 with Real theory?

我在 z3 中尝试了 QF_NRA,它给了我一个关于 root-obj 的抽象值。

(set-logic QF_NRA)
(declare-const x Real)
(assert (= 2 (* x x)))
(check-sat)
sat
(get-model)
(
  (define-fun x () Real
    (root-obj (+ (^ x 2) (- 2)) 1))
)

我不太明白它的意思

此外,x 似乎是在递归中定义的,而不是由 define-fun-rec 定义的。

谢谢。

代数实数

Z3 的真实理论支持所谓的 algebraic reals。也就是说,它可以根据具有有理(等效,整数)值系数的多项式的根来表示解决方案。请注意,这样的多项式可以有复根。 Z3 仅支持实根,即虚部为 0 的根。代数实数本质上是具有整数系数的单变量多项式的实根。

处理根对象

在您发布的示例中,您要求 z3 为 x*x == 2 找到一个令人满意的模型。它告诉您解决方案是多项式的“一个”零 (+ (^ x 2) (- 2)),或者用更熟悉的符号 P(x) = x^2 -2 编写。您获得的索引是 1root-obj 的第二个参数),表示它是此多项式的“第一个”实根。如果你要求 z3 给你另一个解决方案,它会给你下一个:

(set-logic QF_NRA)
(declare-const x Real)
(assert (= 2 (* x x)))
(assert (distinct x (root-obj (+ (^ x 2) (- 2)) 1)))
(check-sat)
(get-model)

这会打印:

sat
(
  (define-fun x () Real
    (root-obj (+ (^ x 2) (- 2)) 2))
)

如您所见,“下一个”解是二阶根。如果我们断言我们需要另一个解决方案怎么办?

(set-logic QF_NRA)
(declare-const x Real)
(assert (= 2 (* x x)))
(assert (distinct x (root-obj (+ (^ x 2) (- 2)) 1)))
(assert (distinct x (root-obj (+ (^ x 2) (- 2)) 2)))
(check-sat)

这会打印:

unsat

符合预期。

请注意,代数实数 包括 pie 等数字,即它们不包括先验数。只有那些可以表示为具有整数系数的多项式的根的实数。 2012 年莱昂纳多 paper 对此进行了非常详细的解释。

获取近似值

z3 还允许您以您喜欢的任意精度获得此类根对象解决方案的近似值。为此,请使用咒语:

(set-option :pp.decimal true)
(set-option :pp.decimal_precision 20)

其中第二行的 20 是您想要的精度位数,您可以根据需要更改它。如果将这两行添加到您的原始脚本中,z3 将响应:

sat
(
  (define-fun x () Real
    (- 1.4142135623730950?))
)

注意数字末尾的 ?。这是 z3 告诉您它打印的数字是该值的“近似值”的方式,即它不是精确结果。

关于“递归”的注释

您的问题表明 x 可能是递归定义的。事实并非如此。碰巧您选择了变量名称 x 并且 z3 也始终使用字母 x 作为多项式。如果您选择 y 作为变量,您仍然会得到完全相同的答案;多项式的参数与程序中的变量无关。