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布尔) (声明常数

问题:是否可以控制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布尔)
(声明常数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)
您可以使用z3OptiMathSAT解决此问题,因为它们接受相同的语法:

~$ 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优化