我想知道为什么Z3能够通过在某些情况下应用关联性和交换性(AC)公理来证明一些微不足道的平等,但在其他情况下却不能。例如,
(simplify (= (bvadd x (bvadd y z)) (bvadd z (bvadd y x))))
(simplify (= (bvxor x (bvxor y z)) (bvxor z (bvxor y x))))
does not(Z3只会使bvxor应用程序变平)。
我看了一下源代码(src / ast / bv_decl_plugin.cpp),并且bvadd和bvxor都被声明为AC符号。它是否与应用于每个符号的重写规则相关?特别是,mk_bv_add(src / ast / rewriter / bv_rewriter.cpp)调用mk_add_core(src / ast / simplifier / poly_simplifier_plugin.cpp),它将bvadd术语处理为单项式的总和。
答案 0 :(得分:4)
是的,它与应用于符号的重写规则有关。
Z3有两个表达式简化:src/ast/rewriter
和src/ast/simplifier
。 src/ast/simplifier
是遗留的,不会在新代码中使用。 SMT-LIB前端中的simplify
命令基于src/ast/rewriter
。 mk_bv_add
实际上在mk_add_core
中使用src/ast/rewriter/poly_rewriter.h
。
更改代码以强制Z3将问题中的bvxor
表达式简化为true
并不难。我们只需在src/ast/rewriter/bv_rewriter.h
添加以下代码行。
新行只是对bvxor
参数进行排序。这是任何AC操作员的正确重写。
br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & result) {
SASSERT(num > 0);
...
default:
// NEW LINE
std::sort(new_args.begin(), new_args.end(), ast_to_lt());
//
result = m_util.mk_bv_xor(new_args.size(), new_args.c_ptr());
return BR_DONE;
}
}
话虽这么说,Z3重写器不应该应用所有可能的简化和/或产生规范的正规形式。他们的主要目标是生成可能更容易求解的公式。规则基于需求而增长(例如,Z3在示例X中太慢,并且性能问题可以通过应用新的预处理规则来“固定”),或者基于用户请求。因此,如果您认为这是一个有用的功能,我们可以添加一个选项来对每个AC运算符的参数进行排序。
修改强>
更正:我们还必须修改以下声明
if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (rational::power_of_two(sz) - numeral(1))))
return BR_FAILED;
当没有现有的重写规则适用时,此语句会中断mk_bv_xor
的执行。我们还必须修改它。我实施了这些修改here。我们可以使用新选项:bv-sort-ac
激活它们。默认情况下,此选项未启用 。新选项在unstable
(正在进行中)分支中可用。设置为true时,它将对位向量AC运算符进行排序。
请注意,unstable
分支使用将在下一个正式版本中提供的新参数设置框架。 Here是有关如何构建unstable
分支的说明。
这些修改也将于本周在nightly builds上提供。
以下是一些使用新选项的示例:
(declare-const a (_ BitVec 8))
(declare-const b (_ BitVec 8))
(declare-const c (_ BitVec 8))
(declare-const d (_ BitVec 8))
(simplify (= (bvxor a b c) (bvxor b a c)))
(simplify (= (bvxor a b c) (bvxor b a c)) :bv-sort-ac true)
(simplify (= (bvxor a (bvxor b c)) (bvxor b a c)) :bv-sort-ac true)
(simplify (= (bvor a b c) (bvor b a c)))
(simplify (= (bvor a b c) (bvor b a c)) :bv-sort-ac true)
(simplify (= (bvor a (bvor b c)) (bvor b a c)) :bv-sort-ac true)
(simplify (= (bvand a b c) (bvand b a c)))
(simplify (= (bvand a b c) (bvand b a c)) :bv-sort-ac true)
(simplify (= (bvand a (bvand b c)) (bvand b a c)) :bv-sort-ac true)
; In the new parameter setting framework, each module has its own parameters.
; The bv-sort-ac is a parameter of the "rewriter" framework.
(set-option :rewriter.bv-sort-ac true)
; Now, Z3 will rewrite the following formula to true even when we do not provide
; the option :bv-sort-ac true
(simplify (= (bvand a b c) (bvand b a c)))
; It will also simplify the following assertion.
(assert (= (bvand a b c) (bvand b a c)))
(check-sat)
结束编辑