我正在实现一个用户理论插件。我想测试用户理论中的不一致性来修剪一些模型。
更具体地说,在我的理论中,x
是用户类集的变量,f
是返回集合大小的函数。我有两个断言:x = set1 OR x = set2
和f x > 2
。假设set1
的大小为1,set2
的大小为3.
在搜索中,Z3首先使用x = set1
。所以我可以添加另一个断言f x = 1
,它在INT部分中会不一致。我想测试不一致性,以便我可以否定当前的赋值,让Z3回溯并尝试其他选项。
我的问题是如何做到这一点。
我尝试了3种方法:
(1)使用f x = 1
直接添加断言Z3_theory_assert_axiom()
。然后搜索终止,立即返回UNSAT。
(2)我尝试使用Z3_check_assumptions()
和f x = 1
作为假设来检查当前上下文。但是Z3_check_assumptions()
不允许这样的复合公式。所以,它不可能是解决方案。
(3)我首先推送上下文,使用f x = 1
添加断言Z3_assert_cnstr()
,使用Z3_check_and_get_model()
测试一致性,然后弹出刚刚推送的上下文。在测试中,如果它不一致,我将获得Z3_get_context_assignment(ctx)
的当前赋值并断言否定赋值以触发回溯。我观察到的是Z3确实发现了不一致性,但是当前的赋值仅包含有关像(= 1 (f x))
这样的大小部分的断言。换句话说,缺少关于用户理论的断言,如(= x set1) and not (= x set2)
。因此,即使我否定当前的分配,在回溯之后,Z3仍然会尝试x = set1
而不是其他选项x = set2
。
我哪里错了?谢谢!
答案 0 :(得分:2)
您应该在回调中仅使用来自用户理论插件的第一个选项Z3_theory_assert_axiom()。你也应该只断言重言式,即与当前任务无关的公理。因此,而不是断言
f x = 1
你应该断言
x = set1 => f x = 1
(假设我理解)因为这个公式无论如何都是正确的。 你也可以断言:
f set1 = 1
(假设,我再次理解),这也会关闭y = set1&的分支。 f y> 1用于其他变量保持。更一般地说,你想要断言最强的理论公理来修剪出许多相关的分支。但理论公理必须是真实的,而不仅仅是在搜索的本地分支内。