z3模型返回值的控件首选项
问题:是否可以控制z3中模型返回值的某种偏好 示例:给定以下命题逻辑公式,有两种可能的模型z3模型返回值的控件首选项,z3,boolean-logic,boolean-expression,z3py,optimathsat,Z3,Boolean Logic,Boolean Expression,Z3py,Optimathsat,问题:是否可以控制z3中模型返回值的某种偏好 示例:给定以下命题逻辑公式,有两种可能的模型 a:True,b:True,c:False(首选) a:True,b:False,c:True(仍然有效,只是“第二选择”) 我想通过布尔公式/断言本身来控制a和b为True的模型应该优先于a和c为True的模型。但是如果由于添加了附加约束,b不能True,则应返回a和c为True的模型 SMT2公式: 以下是SMT2示例公式,可通过以下方式进行测试 (声明常量为布尔) (宣布常数b布尔) (声明常数
(首选)a:True,b:True,c:False
(仍然有效,只是“第二选择”)a:True,b:False,c:True
a
和b
为True
的模型应该优先于a
和c
为True
的模型。但是如果由于添加了附加约束,b
不能True
,则应返回a
和c
为True
的模型
SMT2公式:
以下是SMT2示例公式,可通过以下方式进行测试
(声明常量为布尔)
(宣布常数b布尔)
(声明常数c布尔)
(断言
(断言)
(和(=b正确)(非(=c正确)))
(和(=c正确)(非(=b正确)))
))
(检查sat)
(获取模型)
观察:我注意到,通过实际切换
或子句中和子句的顺序,似乎实际上可以控制返回模型中b
或c
是否为True
。对于这个微不足道的例子,这在某种程度上是可靠的还是偶然发生的?给定一个顺序a
,b
,c
。。。一个可能的想法是用优化模理论对玩具示例进行编码,并使用字典优化引擎:
(set-option :produce-models true)
(set-option :opt.priority lex)
(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert (= a true))
(assert (or
(and (= b true) (not (= c true)))
(and (= c true) (not (= b true)))
))
(maximize (ite a 1 0)) ; highest priority
(maximize (ite b 1 0))
(maximize (ite c 1 0)) ; lowest priority
(check-sat)
(get-objectives)
(get-model)
您可以使用z3或OptiMathSAT解决此问题,因为它们接受相同的语法:
~$ optimathsat test.smt2
sat
(objectives
((ite a 1 0) 1)
((ite b 1 0) 1)
((ite c 1 0) 0)
)
( (a true)
(b true)
(c false) )
~$ z3 test.smt2
sat
(objectives
((ite a 1 0) 1)
((ite b 1 0) 1)
((ite c 1 0) 0)
)
(model
(define-fun b () Bool
true)
(define-fun c () Bool
false)
(define-fun a () Bool
true)
)
如果要添加禁止组合a/\b
的约束,如下所示:
(set-option :produce-models true)
(set-option :opt.priority lex)
(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert (= a true))
(assert (or
(and (= b true) (not (= c true)))
(and (= c true) (not (= b true)))
))
(assert (not (and a b)))
(maximize (ite a 1 0))
(maximize (ite b 1 0))
(maximize (ite c 1 0))
(check-sat)
(get-objectives)
(get-model)
(set-option :produce-models true)
(set-option :opt.priority lex)
(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert (= a true))
(assert (or
(and (= b true) (not (= c true)))
(and (= c true) (not (= b true)))
))
(assert-soft a :weight 1 :id highest_priority)
(assert-soft b :weight 1 :id medium_priority)
(assert-soft c :weight 1 :id lowest_priority)
(minimize highest_priority)
(minimize medium_priority)
(minimize lowest_priority)
; First Solution
(check-sat)
(get-objectives)
(get-model)
; Second Solution
(push 1)
(assert (not (and a b)))
(check-sat)
(get-objectives)
(get-model)
(pop 1)
(exit)
然后,解算器将找到另一个解决方案:
~$ optimathsat test.smt2
sat
(objectives
((ite a 1 0) 1)
((ite b 1 0) 0)
((ite c 1 0) 1)
)
( (a true)
(b false)
(c true) )
~$ z3 test.smt2
sat
(objectives
((ite a 1 0) 1)
((ite b 1 0) 0)
((ite c 1 0) 1)
)
(model
(define-fun b () Bool
false)
(define-fun c () Bool
true)
(define-fun a () Bool
true)
)
注1。请注意,我以最简单的方式对目标进行编码,但这不一定是实现所需目标的最佳方式。根据问题包含多少个变量,以及问题本身的结构,则应该考虑其他可能的编码(例如,对于目标函数使用不同的公式,仅使用API的特征,例如在某些变量上设置分支偏好,用位向量编码问题)。此外,除非您需要一些SMT特定的功能,否则您可能需要寻找一些具有字典优化功能的SAT/MaxSAT解算器
注2。如果您对模型的偏好概念比我从您的玩具示例中推断的“词典偏好”更普遍,那么您仍然可以使用优化模理论和替代成本函数定义,这更适合您的需要
注3。(从注释中)如果两个变量a1
和a2
需要共享相同的优先级,则必须将它们放在相同的最小化/最大化
指令中,例如(最大化(+ite a1 10)(ite a2 10))
这是一个替代答案,它使用assert soft
命令
替代编码#1
我首先为OptiMathSAT提供编码,然后解释如何修改这些公式以在z3中获得相同的结果与另一种方法相比,当有许多布尔变量共享相同的优先级时,这种编码更适合,因为它允许OMT解算器在字典搜索的每一步使用专用的MaxSAT引擎或基数网络来增强基于OMT的标准搜索
我将另一个答案中显示的两个玩具示例合并到一个增量公式中,如下所示:
(set-option :produce-models true)
(set-option :opt.priority lex)
(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert (= a true))
(assert (or
(and (= b true) (not (= c true)))
(and (= c true) (not (= b true)))
))
(assert (not (and a b)))
(maximize (ite a 1 0))
(maximize (ite b 1 0))
(maximize (ite c 1 0))
(check-sat)
(get-objectives)
(get-model)
(set-option :produce-models true)
(set-option :opt.priority lex)
(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert (= a true))
(assert (or
(and (= b true) (not (= c true)))
(and (= c true) (not (= b true)))
))
(assert-soft a :weight 1 :id highest_priority)
(assert-soft b :weight 1 :id medium_priority)
(assert-soft c :weight 1 :id lowest_priority)
(minimize highest_priority)
(minimize medium_priority)
(minimize lowest_priority)
; First Solution
(check-sat)
(get-objectives)
(get-model)
; Second Solution
(push 1)
(assert (not (and a b)))
(check-sat)
(get-objectives)
(get-model)
(pop 1)
(exit)
这是输出:
~$ optimathsat test.smt2
sat
(objectives
(highest_priority 0)
(medium_priority 0)
(lowest_priority 1)
)
( (a true)
(b true)
(c false)
(highest_priority 0)
(medium_priority 0)
(lowest_priority 1) )
sat
(objectives
(highest_priority 0)
(medium_priority 1)
(lowest_priority 0)
)
( (a true)
(b false)
(c true)
(highest_priority 0)
(medium_priority 1)
(lowest_priority 0) )
~$ optimathsat test.smt2
sat
(objectives
(obj 1)
)
( (a true)
(b true)
(c false)
(obj 1) )
sat
(objectives
(obj 2)
)
( (a true)
(b false)
(c true)
(obj 2) )
要将此编码与z3一起使用,只需注释掉以下三行即可:
;(minimize highest_priority)
;(minimize medium_priority)
;(minimize lowest_priority)
原因是z3隐式定义了assert-soft
命令的目标,并隐式将其最小化。其产出是:
~$ z3 test.smt2
sat
(objectives
(highest_priority 0)
(medium_priority 0)
(lowest_priority 1)
)
(model
(define-fun b () Bool
true)
(define-fun c () Bool
false)
(define-fun a () Bool
true)
)
sat
(objectives
(highest_priority 0)
(medium_priority 1)
(lowest_priority 0)
)
(model
(define-fun b () Bool
false)
(define-fun c () Bool
true)
(define-fun a () Bool
true)
)
请注意,由于z3为您隐式声明了最小化目标,因此assert soft
命令应按您希望分配给其相关目标函数的相同优先级顺序出现
正如我在引言中提到的,在某些变量共享相同优先级的情况下,这种编码比另一个答案中的编码要好得多。要将两个变量a1
和a2
置于相同的优先级,可以对它们的断言软
命令使用相同的id
例如:
(set-option :produce-models true)
(set-option :opt.priority lex)
(declare-const a1 Bool)
(declare-const a2 Bool)
(declare-const a3 Bool)
(declare-const b1 Bool)
(declare-const b2 Bool)
(declare-const c Bool)
(assert (= a1 true))
(assert (or
(and (= b1 true) (not (= c true)))
(and (= c true) (not (= b1 true)))
))
(assert (or (not a1) (not a2) (not a3) ))
(assert (or (not b1) (not b2) ))
(assert-soft a1 :weight 1 :id highest_priority)
(assert-soft a2 :weight 1 :id highest_priority)
(assert-soft a3 :weight 1 :id highest_priority)
(assert-soft b1 :weight 1 :id medium_priority)
(assert-soft b2 :weight 1 :id medium_priority)
(assert-soft c :weight 1 :id lowest_priority)
(minimize highest_priority)
(minimize medium_priority)
(minimize lowest_priority)
; First Solution
(check-sat)
(get-objectives)
(get-model)
; Second Solution
(push 1)
(assert (not (and a1 b1)))
(check-sat)
(get-objectives)
(get-model)
(pop 1)
(exit)
与输出
~$ optimathsat test.smt2
sat
(objectives
(highest_priority 1)
(medium_priority 1)
(lowest_priority 0)
)
( (a1 true)
(a2 true)
(a3 false)
(b1 false)
(b2 true)
(c true)
(highest_priority 1)
(medium_priority 1)
(lowest_priority 0) )
sat
(objectives
(highest_priority 1)
(medium_priority 1)
(lowest_priority 0)
)
( (a1 true)
(a2 true)
(a3 false)
(b1 false)
(b2 true)
(c true)
(highest_priority 1)
(medium_priority 1)
(lowest_priority 0) )
替代编码#2
assert soft
的一个有趣的事实是,它可以在没有任何词典优化引擎的情况下用于解决词典优化问题:只需稍微调整一下权重就可以获得相同的结果。这是SAT/MaxSAT求解的传统做法。唯一需要注意的是,需要小心放置砝码。除此之外,这种方法可能比上述编码更有效,因为整个优化问题都是通过对内部单目标引擎的一次调用来解决的
(set-option :produce-models true)
(set-option :opt.priority lex)
(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert (= a true))
(assert (or
(and (= b true) (not (= c true)))
(and (= c true) (not (= b true)))
))
(assert-soft a :weight 4 :id obj) ; highest priority
(assert-soft b :weight 2 :id obj)
(assert-soft c :weight 1 :id obj) ; lowest priority
(minimize obj)
; First Solution
(check-sat)
(get-objectives)
(get-model)
; Second Solution
(push 1)
(assert (not (and a b)))
(check-sat)
(get-objectives)
(get-model)
(pop 1)
(exit)
这是输出:
~$ optimathsat test.smt2
sat
(objectives
(highest_priority 0)
(medium_priority 0)
(lowest_priority 1)
)
( (a true)
(b true)
(c false)
(highest_priority 0)
(medium_priority 0)
(lowest_priority 1) )
sat
(objectives
(highest_priority 0)
(medium_priority 1)
(lowest_priority 0)
)
( (a true)
(b false)
(c true)
(highest_priority 0)
(medium_priority 1)
(lowest_priority 0) )
~$ optimathsat test.smt2
sat
(objectives
(obj 1)
)
( (a true)
(b true)
(c false)
(obj 1) )
sat
(objectives
(obj 2)
)
( (a true)
(b false)
(c true)
(obj 2) )
我在对另一个答案的评论中提到了这一点,但另一个可能有趣的解决方案可能是尝试对公式进行位向量编码,然后使用OBVBS(请参阅)引擎对最重要位表示的向量进行BV优化