Recent Trends in SMT and Z3

An interactive taste of SMT with Z3

Nikolaj Bjørner
Microsoft Research

Contents

Plan

  1. SMT and Z3

  2. Theories

  3. Programming Solvers with an application to MaxSAT

Z3

  • A state-of-art Satisfiability Modulo Theories (SMT) solver



  • On GitHub: https://github.com/Z3prover/z3.git
    • MIT open source license
    • Developments: Scalable simplex solver, Strings, Horn clauses, floating points, SAT extensions

Some Z3 Applications

  • Program Verification
    • VCC, Everest, Dafny, Havoc, Leon

  • Symbolic Execution
    • SAGE, Pex, KLEE

  • Software Model Checking
    • Static Driver Verifier, Smash, SeaHorn

  • Configurations
    • Network Verification with SecGuru
    • Dynamics Product Configuration

Microsoft Tools using Z3

MicrosoftToolsBasedOnZ3

SAT/SMT examples

Basic SAT

  Tie, Shirt = Bools('Tie Shirt')
  s = Solver()
  s.add(Or(Tie, Shirt), Or(Not(Tie), Shirt), Or(Not(Tie), Not(Shirt)))
  print s.check()
  print s.model()

Basic SMT

I = IntSort()
f = Function('f', I, I)
x, y, z = Ints('x y z')
A = Array('A',I,I)

fml = Implies(x + 2 == y, f(Select(Store(A, x, 3), y - 2)) == f(y - x + 1))

s = Solver()
s.add(Not(fml))
print s.check()

Logical Queries - SAT+



$\hspace{2cm}$ sat $\hspace{1.3cm}$ $\varphi$ $\hspace{1.3cm}$ unsat


$\hspace{1.6cm}$ model $\hspace{1.3cm}$ $\varphi$ $\hspace{1.3cm}$ (clausal) proof


$\hspace{0.6cm}$ correction set $\hspace{0.3cm}$ $\subseteq \varphi_1, \ldots, \varphi_n \supseteq $ $\hspace{0.2cm}$ core


local min correction set $\hspace{0.05cm}$ $ \subseteq \varphi_1, \ldots, \varphi_n \supseteq$ $\hspace{0.2cm}$ local min core


min correction set $\hspace{0.35cm}$ $ \subseteq \varphi_1, \ldots, \varphi_n \supseteq$ $\hspace{0.2cm}$ min core


$\hspace{3.2cm}$ $\max x \varphi(x)$

Logical Queries

\[\begin{mdmathpre}%mdk \mathrm{Satisfiability}~~~&~\varphi \rightsquigarrow \mathid{sat},~\mathid{unsat},~\mathid{timeout}~\smallskip \\ \mathrm{Certificates}~~~~~&~\varphi \rightsquigarrow \mathid{model},~\mathid{proof},~\mathid{unsat}~\mathid{core}~\smallskip\\ \mathrm{Interpolation}~~~~&~\varphi[\mathid{x},\mathid{y}]~\rightarrow \mathid{I}[\mathid{x}]~\rightarrow \psi[\mathid{x},\mathid{z}]~\smallskip\\ \mathrm{Optimization}~~~~~&~\max \mathid{x}~\mid \varphi \smallskip \\ \mathrm{Consequences}~~~~~&~\varphi \rightarrow \varphi_1~\wedge \ldots \wedge \varphi_\mathid{n}\smallskip\\ \mathrm{Sat\ subsets}~~~~~&~\psi_1~\wedge \psi_2,\ \psi_1~\wedge \psi_3\smallskip\\ \mathrm{Unsat\ cores}~~~~~&~\neg(\psi_1~\wedge \psi_2),\ \neg(\psi_1~\wedge \psi_3)\medskip\\ \mathrm{Model\ counting}~~&~|\{~\mathid{x}~\mid \varphi\}|~\medskip\\ \mathrm{All\ models}~~~~~~&~\mathid{Ideal}(\varphi),~\mathid{M}_1~\models \varphi,~\mathid{M}_2~\models \varphi,~\ldots \medskip\\ \mathrm{Model\ probability}~&~\ldots \end{mdmathpre}%mdk \]

Section 2

Theory Solvers

Equality and Uninterpreted functions

EUF

  (declare-sort A)
  (declare-fun f (A) A)
  (declare-const x A)
  (assert (= (f (f x)) x))
  (assert (= (f (f (f x))) x))
  (check-sat)
  
  (assert (not (= (f x) x)))
  (check-sat)

A linear arithmetic conjecture

liraconjecture

A linear arithmetic conjecture in SMT

(declare-const xR Real)
(declare-const yR Real)
(declare-const x Int)
(declare-const y Int)
(declare-const a Int)

(assert (< (+ xR yR) a))
(assert (> (+ x y) a))
(assert (or (= x xR) (< x xR (+ x 1)) (< (- x 1) xR x)))
(assert (or (= y yR) (< y yR (+ y 1)) (< (- y 1) yR y)))
(check-sat)
(get-model)

A linear arithmetic conjecture online

A revised conjecture

levmiddle

A revised conjecture online

Jobshop scheduling

jobshop

Jobshop constraints

jobconstraints

Jobshop constraints in logic

jobconstraints2

Jobshop constraints encoding

jobencoding

Jobshop solving

jobshopsolving

Linear Arithmetic - Jobshop

(set-logic QF_IDL) ; optional in Z3
(declare-fun t11 () Int)
(declare-fun t12 () Int)
(declare-fun t21 () Int)
(declare-fun t22 () Int)
(declare-fun t31 () Int)
(declare-fun t32 () Int)

(assert (and (>= t11 0) (>= t12 (+ t11 2)) (<= (+ t12 1) 8)))
(assert (and (>= t21 0) (>= t22 (+ t21 3)) (<= (+ t22 1) 8)))
(assert (and (>= t31 0) (>= t32 (+ t31 2)) (<= (+ t32 3) 8)))
(assert (or (>= t11 (+ t21 3)) (>= t21 (+ t11 2))))
(assert (or (>= t11 (+ t31 2)) (>= t31 (+ t11 2))))
(assert (or (>= t21 (+ t31 2)) (>= t31 (+ t21 3))))
(assert (or (>= t12 (+ t22 1)) (>= t22 (+ t12 1))))
(assert (or (>= t12 (+ t32 3)) (>= t32 (+ t12 1))))
(assert (or (>= t22 (+ t32 3)) (>= t32 (+ t22 1))))
(check-sat)
(get-model) ; display the model  

Linear Arithmetic Example

Algorithmic Fragments of Arithmetic

Logic Fragment Solver Example
LRA Linear Real Arithmetic Dual Simplex $x + \frac{1}{2}y \leq 3$
LIA Linear Integer Arithmetic CutSat $a + 3b \leq 3$
LIRA Mixed Real/Integer Cuts + Branch $x + a \geq 4$
IDL Integer Difference Logic Floyd-Warshall $a - b \leq 4$
RDL Real Difference Logic Bellman-Ford
UTVPI Unit two-variable per inequality $x + y \leq 4$
NRA Polynomial Real Arithmetic Model based CAD $x^2 + y^2 < 1$

Other Fragments of Arithmetic

  • NIA - There is no decision procedure for integer polynomial constraints

    • Z3 falls back to incomplete heuristics
    • NIA over bounded integers may get translated to bit-vector constraints


    Other theories that admit custom solvers:

  • Bi-linear real arithmetic $\vec{x}A\vec{y} \leq \vec{b}$

  • Non-unit two-variable per inequality $ax + by \leq c$

  • At most one unit positive variable per inequality (Horn)

An Overview of Arithmetic Theories

ArithmeticTheories

Bellman-Ford - a selection

(set-logic QF_IDL) ; optional in Z3
(declare-fun t11 () Int)
(declare-fun t12 () Int)
(declare-fun t21 () Int)
(declare-fun t22 () Int)
(declare-fun t31 () Int)
(declare-fun t32 () Int)

(assert (and (>= t11 0) ...))
(assert (and (>= t21 0) ...))
(assert (and (>= t31 0) (>= t32 (+ t31 2)) (<= (+ t32 3) 8)))
(assert (or ... (>= t21 (+ t11 2))))
(assert (or (>= t21 (+ t31 2)) ...))
(check-sat)
(get-model) ; display the model  

Bellman-Ford

Solve difference logic using graph $O(m\cdot n)$ Bellman-Ford network flow algorithm. Negative cycle $\Rightarrow$ unsat.

BellmanFord

General form Simplex [4]

General form $Ax = 0$ and $lo_j \leq x_j \leq hi_j$

\[ x \geq 0, (x + y \leq 2 \vee x + 2y \geq 6), (x + y \geq 2 \vee x + 2y > 4) \]

$\leadsto$

\[\begin{mdmathpre}%mdk \mdmathindent{2}\mathid{s}_1~:=~\mathid{x}~+~\mathid{y},~\mathid{s}_2~:=~\mathid{x}~+~2\mathid{y},\\ \mdmathindent{2}\mathid{x}~\geq 0,~(\mathid{s}_1~\leq 2~\vee \mathid{s}_2~\geq 6),~(\mathid{s}_1~\geq 2~\vee \mathid{s}_2~>~4) \end{mdmathpre}%mdk \]

Only bounds (e.g., $s_1 \leq 2$) are asserted during search.

From Definitions to a Tableau

${\color{red}s_1} := x + y, {\color{red}s_2} := x + 2y$



${\color{red}s_1} = x + y$
${\color{red}s_2} = x + 2y$



${\color{red}s_1} - x - y = 0$ - ${\color{red}s_1, s_2}$ are basic (dependent)
${\color{red}s_2} - x - 2y = 0$ - $x, y$ are non-basic

Pivoting

  • Value of non-basic variable $x_j$ can be chosen between $lo_j$ and $hi_j$.
  • Value of basic variable is a function of non-basic variable values.
  • Pivoting swaps basic and non-basic variables.
    • used to get values of basic variables within bounds.

Pivoting example

${\color{red}s_1} - x - y = 0$ - ${\color{red}s_1, s_2}$ are basic (dependent)
${\color{red}s_2} - x - 2y = 0$ - $x, y$ are non-basic $x \geq 0, (s_1 \leq 2 \vee s_2 \geq 6), (s_1 \geq 2 \vee s_2 > 4)$


Initial values: $x = y = s_1 = s_2 = 0$


Bounds $x \geq 0, s_1 \leq 2, s_1 \geq 2$:


$s_1 := 2$, make $s_1$ non-basic.
${\color{red}y} + x - s_1 = 0$ - ${\color{red}y, s_2}$ are basic (dependent)
${\color{red}s_2} + x - 2s_1 = 0$ - $s_1, y$ are non-basic

Arrays

(define-sort A () (Array Int Int))
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun a1 () A)

(push)
(assert (= (select a1 x) x))
(assert (= (store a1 x y) a1))
(check-sat)
(get-model)
(assert (not (= x y)))
(check-sat)
(pop)

(define-fun all1_array () A ((as const A) 1))
(simplify (select all1_array x))

(define-sort IntSet () (Array Int Bool))
(declare-fun a () IntSet)
(declare-fun b () IntSet)
(declare-fun c () IntSet)
(push) ; illustrate map
(assert (not (= ((_ map and) a b) ((_ map not) ((_ map or) ((_ map not) b) ((_ map not) a))))))
(check-sat)
(pop)    

Arrays

Arrays as Combinators [12]

  A = Array(Index, Elem) # array sort 
  
  a[i]             # index array 'a' at index 'i'
                   # Select(a, i)
  
  Store(a, i, v)   # update array 'a' with value 'v' at index 'i'
                   # = lambda j: If(i == j, v, a[j])
    
  Const(v, A)      # constant array
                   # = lambda j: v
  
  Map(f, a)        # map function 'f' on values of 'a'
                   # = lambda j: f(a[j])

  Ext(a, b)        # Extensionality
                   # Implies(a[Ext(a, b)] == b[Ext(a, b)], a == b)

Bit-Vectors

(define-fun is-power-of-two ((x (_ BitVec 4))) Bool 
  (= #x0 (bvand x (bvsub x #x1))))
(declare-const a (_ BitVec 4))
(assert 
 (not (= (is-power-of-two a) 
         (or (= a #x0) 
             (= a #x1) 
             (= a #x2) 
             (= a #x4) 
             (= a #x8)))))
(check-sat)

Bit-Vector demo

Bit-Vector Adder Encoding

BitVectorAdder

Bit-Vector Multiplier Encoding

BitVectorMul

Floating point example

(declare-fun X () (_ FloatingPoint 11 53))

(assert (fp.isNormal X))
(assert (not (fp.isSubnormal X)))
(assert (not (fp.isZero X)))
(assert (not (fp.isInfinite X)))
(assert (not (fp.isNaN X)))
(assert (not (fp.isNegative X)))
(assert (fp.isPositive X))

(check-sat)
(get-model)

Floating Points demo

Sequence Example

(declare-const a String)
(declare-const b String)
(declare-const c String)
(assert (str.prefixof b a))
(assert (str.suffixof c a))
(assert (= (str.len a) (+ (str.len b) (str.len c))))
(assert (not (= a (str.++ b c))))
(check-sat)  

Sequences and Strings

Algebraic Data-types

   (declare-datatypes () ((Tree Empty (Node (left Tree) (data Int) (right Tree)))))

   (declare-const t Tree)
   (assert (not (= t Empty)))
   (check-sat)
   (get-model)
sat
(model 
  (define-fun t () Tree
    (Node Empty 0 Empty))
)

Another Algebraic Data-types demo

Another Algebraic Data-types demo

Non-linear Arithmetic [7]

nlsat

Non-linear arithmetic - Basic examples

from z3 import *

x, y, z = Reals('x y z')

solve(x**2 + y**2 < 1, x*y > 1) 

solve(x**2 + y**2 < 1, x*y > 0.4)

solve(x**2 + y**2 < 1, x*y > 0.4, x < 0)

solve(x**5 - x - y == 0, Or(y == 1, y == -1))

NLSAT example

; Code written by TheoryGuru
(declare-fun v1 () Real)
(declare-fun v2 () Real)
(declare-fun v3 () Real)
(declare-fun v4 () Real)
(declare-fun v5 () Real)
(declare-fun v6 () Real)
(declare-fun v7 () Real)
(declare-fun v8 () Real)
(declare-fun v9 () Real)
(declare-fun v10 () Real)
(declare-fun v11 () Real)
(declare-fun v12 () Real)

; define true assumption
(assert (and 
(> (* 2 v11 v6 v9) (+ (* v12 (^ v6 2)) (* v8 (^ v9 2))))
(> (+ (* 2 v10 v11 v4 v6) (* v12 v5 (^ v6 2)) (* -2 v12 v4 v6 v7) (* v12 (^ v4 2) v8) (* -2 v11 v5 v6 v9) (* 2 v11 v4 v7 v9) (* 2 v10 v6 v7 v9) (* v5 v8 (^ v9 2))) (+ (* (^ v11 2) (^ v4 2)) (* (^ v10 2) (^ v6 2)) (* 2 v10 v4 v8 v9) (* (^ v7 2) (^ v9 2))))
(> v1 0)
(> v2 0)
(> v3 0)
(> v4 0)
(> v6 0)
(> v9 0)
(= (+ (* v1 v11) (* v3 v7) (* v2 v8)) 0)
(= (+ (* v1 v12) (* v11 v2) (* v10 v3)) 0)
(= (+ (* v1 v10) (* v3 v5) (* v2 v7)) 0)
))

; define negative of the hypothesis
(assert (not (>= (* v5 v8) (^ v7 2))))

(check-sat)
(exit)

NLSAT demo

Quantifiers

How can I sepecify $f$ to be injective?

    (declare-sort A)
    (declare-sort B)
    (declare-fun f (A) B)
    (assert (forall ((x A) (y A)) (=> (= (f x) (f y)) (= x y))))

Instantiation based reasoning

    (assert (forall ((x A) (y A)) 
         (! (=> (= (f x) (f y)) (= x y)) :pattern ((f x) (f y)))))
  • E-matching instantiates quantifier for every occurrence $f(s), f(t)$ for terms $s, t$ produced during search.

  • Some formulations are better than others

Fewer instances

    (declare-fun g (B) A)
    (assert (forall ((x A)) (! (= (g (f x)) x) :pattern ((f x)))))

Essentially Uninterpreted Fragment [5]

Synthesize generalized instantiation sets using grammar rules.

Applies to wide range of classes.

  • array property fragment by Bradley, Manna, Sipma.
  • list property fragment by McPeak and Necula.
  • several locally finite theories - Stokkermans et. al.

Essentially Uninterpreted Example

(set-option :smt.mbqi true)
;; f an g are "streams"
(declare-fun f (Int) Int)
(declare-fun g (Int) Int)

;; the segment [a, n + a] of stream f is equal to the segment [0, n] of stream g.
(declare-const n Int)
(declare-const a Int)
(assert (forall ((x Int)) (=> (and (<= 0 x) (<= x n))
                              (= (f (+ x a)) (g x)))))

;; adding some constraints to a
(assert (> a 10))
(assert (>= (f a) 2))
(assert (<= (g 3) (- 10)))

(check-sat)
(get-model)

Essentially Uninterpreted Example - Online

Quantifier Elimination

from z3 import *

x, u, v = Ints('x u v')
stamp = ForAll([x],
           Implies(x >= 25,
               Exists([u,v],
                  And(u >= 0, v >= 0, x == 3*u + 5*v))))

print stamp

print Tactic('qe').apply(stamp)

Quantifier Elimination (2)

badstamp = ForAll([u,v], Implies(And(u >= 0, v >= 0), x != 3*u + 5*v))

x1 = Int('x1')
last_bad = ForAll([x1],
           Implies(x1 > x,
               Exists([u,v],
                  And(u >= 0, v >= 0, x1 == 3*u + 5*v))))


qe_solver = Then('qe','smt').solver()
qe_solver.add(last_bad)
qe_solver.add(badstamp)
print qe_solver.check()
print qe_solver.model()

Horn Clauses

def mc(x):
    if x > 100:
       return x - 10
    else:
       return mc(mc(x + 11))

def contract(x):
    assert(x > 101 or mc(x) == 91)
   (set-logic HORN)
   (declare-fun mc (Int Int) Bool)
   (assert 
     (forall ((x Int)) 
          (=> (> x 100) 
              (mc x (- x 10)))))
   (assert 
     (forall ((x Int) (y Int) (z Int)) 
          (=> (and (<= x 100) (mc (+ x 11) y) (mc y z)) 
              (mc x z))))
   (assert 
     (forall ((x Int) (y Int)) 
          (=> (and (<= x 101) (mc x y)) 
              (= y 91))))
   (check-sat)
   (get-model)

Horn Clauses online

Open Challenges

  • Strings: Decidability and efficiency.

  • Certificates: Modular, Clausal

  • New, non-disjoint, theories

Section 3

Programming Solvers with an application to MaxSAT

Objectives

  • Optimization as SMT with preferred models

  • An introduction to cores and correction sets

  • Show examples of algorithms on top of SMT/Z3

Optimization $\nu{Z}$

Three main SMT extensions


    (maximize (+ x (* 2 y)))


    (minimize (bvadd u v))




    (assert-soft (> x y) :weight 4)


  • Maximize objective

    • linear arithmetic
  • Minimize objective

    • bit-vector
  • Add a soft constraint

    • optional weight

Soft constraints as 0-1 optimization

Equilvalent formulations

   (assert-soft $\varphi$ :weight 3)
   (assert-soft $\psi$ :weight 4)
   (minimize (+ (if $\varphi$ 0 3) (if $\psi$ 0 4)))

Optimization Queries

x, y = Ints('x y')
opt = Optimize()
opt.set(priority='pareto')
opt.add(x + y == 10, x >= 0, y >= 0)
mx = opt.maximize(x)
my = opt.maximize(y)
while opt.check() == sat:
    print mx.value(), my.value()

Optimization MaxSMT

(declare-const x11 Bool) .... (declare-const y3 Bool)
(define-fun b2i ((b Bool)) Int (ite b 1 0))

; A VM is on exactly one server.
(assert (= (+ (b2i x11) (b2i x12) (b2i x13)) 1))
(assert (= (+ (b2i x21) (b2i x22) (b2i x23)) 1))
(assert (= (+ (b2i x31) (b2i x32) (b2i x33)) 1))

; A server is used if it contains a VM
(assert (=> (y1 (and x11 x21 x31)))
(assert (=> (y2 (and x12 x22 x32)))
(assert (=> (y3 (and x13 x23 x33)))

; Capability constraints
(assert (<= (+ (* 100 (b2i x11)) (* 50 (b2i x21)) (* 15 (b2i x31))) (* 100 (b2i y1))))
(assert (<= (+ (* 100 (b2i x12)) (* 50 (b2i x22)) (* 15 (b2i x32))) (* 75 (b2i y2))))             
(assert (<= (+ (* 100 (b2i x13)) (* 50 (b2i x23)) (* 15 (b2i x33))) (* 200 (b2i y3))))

; Optimization goals are expressed via assert-soft.
(assert-soft (not y1) :id num_servers)     (assert-soft (not y2) :id num_servers)
(assert-soft (not y3) :id num_servers)     (assert-soft (not y1) :id costs :weight 10) 
(assert-soft (not y2) :id costs :weight 5) (assert-soft (not y3) :id costs :weight 20)

(set-option :verbose 10)
(check-sat)
(get-objectives)

Optimization MaxSMT online

Cores, Correction Sets, Satisfying Assignments

  • (M)US (Minimal) unsatisfiable subset

    • (minimal) subset of assertions that are unsatisfiable. Also known as a core
  • (M)SS (Maximal) satisfiable subset

    • (maximal) subset of assertions that are satisfiable.
  • (M)CS (Minimal) correction set

    • complement of an (M)SS.
  • (Prime) implicant

    • $m \Rightarrow \phi$ iff $m$ is a core for $\neg \phi$.

A Duality: MUS $\sim$ MCS [14]

Reiter

All Cores and Correction Sets [9]


  • Given $\varphi_1, \ldots, \varphi_n$
    • Find all min unsat cores
    • Find all max satisfying subsets
  • Generate subset $S \subseteq \{1,\ldots, n\}$
    • Not a superset of old core
    • Not a subset of old sat subset
  • Is $\bigwedge_{j \in S} \varphi_j$ satisfiable?
    • If yes, find max sat $S' \supseteq S$
    • If no, find min unsat $S' \subseteq S$
  • Block $S'$ from next iteration


def ff(s, p): 
    return is_false(s.model().eval(p))

def marco(s, ps):
    map = Solver()
    while map.check() == sat:
        seed = {p for p in ps if not ff(map, p)}
        if s.check(seed) == sat:
           mss = get_mss(s, seed, ps)
           map.add(Or(ps - mss))
           yield "MSS", mss
        else:
           mus = get_mus(s, seed)
           map.add(Not(And(mus)))
           yield "MUS", mus

Cores and Correction sets Algorithm

def ff(s, p): 
    return is_false(s.model().eval(p))

def marco(s, ps):
    map = Solver()
    while map.check() == sat:
        seed = {p for p in ps if not ff(map, p)}
        if s.check(seed) == sat:
           mss = get_mss(s, seed, ps)
           map.add(Or(ps - mss))
           yield "MSS", mss
        else:
           mus = get_mus(s, seed)
           map.add(Not(And(mus)))
           yield "MUS", mus

Maximizing Satisfying Assignments [11]

def tt(s, f): 
    return is_true(s.model().eval(f))

def get_mss(s, mss, ps):
    ps = ps - mss
    backbones = set([])
    while len(ps) > 0:
       p = ps.pop()
       if sat == s.check(mss | backbones | { p }):
          mss = mss | { p } | { q for q in ps if tt(s, q) }
          ps  = ps - mss
       else:
          backbones = backbones | { Not(p) }
    return mss
          

Minimizing Cores [1, 3, 8, 10]

Use built-in core minimization:

s.set("sat.core.minimize","true")  # For Bit-vector theories
s.set("smt.core.minimize","true")  # For general SMT 

Or roll your own:


def quick_explain(test, sub):
    return qx(test, set([]), set([]), sub)

def qx(test, B, D, C):
    if {} != D:
       if test(B):
          return set([])
    if len(C) == 1:
       return C
    C1, C2 = split(C)
    D1 = qx(test, B | C1, C1, C2)
    D2 = qx(test, B | D1, D1, C1)
    return D1 | D2
    
def test(s):
    return lambda S: s.check([f for f in S]) == unsat


s = Solver()
a, b, c, d, e = Bools('a b c d e')
s.add(Or(a, b))
s.add(Or(Not(a), Not(b)))
s.add(Or(b, c))
s.add(Or(Not(c), Not(a)))

print s.check([a,b,c,d,e])
print s.unsat_core()

mus = quick_explain(test(s), {a,b,c,d})

All maximal satisfying sets (basic)

def all_mss(s, ps):
    while sat == s.check():
        mss = get_mss(s, { p for p in ps if tt(s, p) }, ps)
        s.add(Or(ps - mss))
        yield "MSS", mss
  • Inefficiency: Same unsat cores may be revisited.

All Correction Sets

Find all satisfying subsets among $\varphi_1, \ldots, \varphi_n$:

  • Initialize: $F_1 \leftarrow \varphi_1, \ldots, F_n \leftarrow \varphi_n$, $F \leftarrow \top$.
  • While $F$ is sat:
    • If $F \wedge F_1\wedge \ldots\wedge F_n$ is sat with model $M$
      • $\{ \varphi_j \mid M(\varphi_j) = \top \}$ is mss.
      • $F \leftarrow F \wedge \bigvee \{ \varphi_j \;\mid\; M(\varphi_j) = \bot \}$ add mcs
    • Else suppose $F_1,\ldots, F_k$ is a core
      • Replace by $F'_1, \ldots, F'_{k-1}$:
      • $F'_1 \leftarrow F_1 \vee F_2$, $F'_2 \leftarrow F_3 \vee (F_2 \wedge F_1)$,
        $\ldots$, $F'_{k-1} \leftarrow F_k \vee (F_{k-1} \wedge \ldots)$.

MaxSMT

  • Typical definition: Minimize the number of violated soft assertions.

  • Is built-in, based on MaxSAT algorithms.

MaxSAT example

(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert-soft a :weight 1)
(assert-soft b :weight 2)
(assert-soft c :weight 3)
(assert (= a c))
(assert (not (and a b)))
(check-sat)
(get-model)

MaxSAT flattened

(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert-soft a :weight 1)
(assert-soft b :weight 1) (assert-soft b :weight 1)
(assert-soft c :weight 1) (assert-soft c :weight 1) (assert-soft c :weight 1) 
(assert (= a c))
(assert (not (and a b)))
(check-sat)
(get-model)
  • NB. Implementations of MaxSAT typically flatten weights on demand.

MaxSAT flat form

\[ \underbrace{(a \equiv c) \wedge \neg (a \wedge b)}_{F}, \underbrace{a}_{F_1} \underbrace{b}_{F_2} \underbrace{b}_{F_3} \underbrace{c}_{F_4} \underbrace{c}_{F_5} \underbrace{c}_{F_6} \]
  • $F$ - hard constraints

  • $F_1, F_2, \ldots, F_6$ - soft constraints

MaxSAT with Cores [13]

A: $F, \underbrace{F_1, F_2, F_3, F_4 }_{core}, F_5$

A': $F, \ F_2 \vee F_1, F_3 \vee (F_2 \wedge F_1), F_4 \vee (F_3 \wedge (F_2 \wedge F_1)), F_5$

Lemma: for any model $M$ of $F$, $cost(M, A) = 1 + cost(M, A')$

Proof: $M(F_j) = \bot, j$ min: $ M(F'_i) = M(F_{i+1}) \vee i = j + 1, \forall i$

MaxSAT with Cores - example



\[ \underbrace{(a \equiv c) \wedge \neg (a \wedge b)}_{F}, \underbrace{a,b}_{core} \underbrace{b}_{F_3} \underbrace{c}_{F_4} \underbrace{c}_{F_5} \underbrace{c}_{F_6} \]



\[ \underbrace{(a \equiv c) \wedge \neg (a \wedge b)}_{F}, \underbrace{a \vee b}_{F_1'} \underbrace{b}_{F_3} \underbrace{c}_{F_4} \underbrace{c}_{F_5} \underbrace{c}_{F_6} \]

MaxSAT with Cores - example (2)



\[ \underbrace{(a \equiv c) \wedge \neg (a \wedge b)}_{F}, \underbrace{a \vee b, b, c}_{core} \underbrace{c}_{F_5} \underbrace{c}_{F_6} \]



\[ \underbrace{(a \equiv c) \wedge \neg (a \wedge b)}_{F}, \underbrace{(a \vee b \vee b)}_{F_1''} \underbrace{c \vee ((a \vee b) \wedge b)}_{F_2''} \underbrace{c}_{F_5} \underbrace{c}_{F_6} \]

MaxSAT with MCS [2]

A: $F, \underbrace{F_1, F_2, F_3, F_4 }_{\mbox{correction set}}, F_5$

A': $\underbrace{ F \wedge (F_1 \vee F_2 \vee F_3 \vee F_4) }_{F`},$
$F_2 \wedge F_1,\ F_3 \wedge (F_2 \vee F_1), \ F_4 \wedge (F_3 \vee (F_2 \vee F_1)), \ F_5$

Lemma: for any model $M$ of $F'$, $cost(M, A) = cost(M, A')$

Proof: $M(F_j) = \top, j$ min:     $ M(F'_i) = M(F_{i+1}) \wedge (i \neq j \vee j = 1), \forall i$

MaxSAT with Cores (python)

def add_def(s, fml):
    name = Bool("%s" % fml)
    s.add(name == fml)
    return name

def relax_core(s, core, Fs):
    prefix = BoolVal(True)
    Fs -= { f for f in core }
    for i in range(len(core)-1):
        prefix = add_def(s, And(core[i], prefix))
        Fs |= { add_def(s, Or(prefix, core[i+1])) }

def maxsat(s, Fs):
    cost = 0
    Fs0 = Fs.copy()
    while unsat == s.check(Fs):
        cost += 1
        relax_core(s, s.unsat_core(), Fs)    
    return cost, { f for f in Fs0 if tt(s, f) }

MaxSAT with MCS (python)

def relax_mcs(s, mcs, Fs):
    prefix = BoolVal(False)
    Fs -= { f for f in mcs }
    s.add(Or(mcs))
    for i in range(len(mcs)-1):
        prefix = add_def(s, Or(mcs[i], prefix))
        Fs |= { add_def(s, And(prefix, mcs[i+1])) }

def maxsat(s, Fs0):
    Fs = Fs0.copy()
    cost = len(Fs)
    while s.check() == sat:
        mss = { f for f in Fs if tt(s, f) }
        model1 = get_mss(s, mss, Fs)
        mcs = Fs - mss
        if cost > len(mcs):
           cost = len(mcs)
           model = model1
        relax_mcs(s, [ f for f in mcs ], Fs)
    return cost, [ f for f in Fs0 if is_true(model.eval(f)) ]

MCS alone is inefficient. In [2] we combine MUS and MCS steps.

Application: Product Configuration

ProductConfig

Query

  • Find all unit literals - with explanations
  • Useful for finding fixed parameters [6]
a, b, c, d = Bools('a b c d')

s = Solver()
s.add(Implies(a, b), Implies(c, d))   # background formula
print s.consequences([a, c],          # assumptions
                     [b, c, d])       # what is implied?
(sat, [Implies(c, c), Implies(a, b), Implies(c, d)])

Algorithm

  1. Assert hard constraints $\varphi$
  2. Add assumptions $\mathcal{A}$ at $level = 1$
  3. Let $M = $ model of $\varphi \wedge \mathcal{A}$
  4. Case splits: $\{ \neg v \mid v \in V, M(v) \} \cup \{ v \mid v \in V, \neg M(v) \}$
  5. Unit propagation
    • if conflict, remove fixed variable with explanation from $V$
  6. Run CDCL until next restart or sat
    • if sat: use resulting model to remove non-fixed from $V$
    • if $V = \emptyset$, exit, else goto 4

Programming Z3

Solver methods

s = Solver()


s.add($\varphi$)
s.assert_and_track($\varphi, \ell$)

s.push()
s.pop()

s.check()
s.check($[\ell_1,\ldots, \ell_n]$)

s.model()
s.proof()
s.unsat_core()   

s.statistics()     


  • Create a solver

  • Add assertion to solver state

  • Create local scopes

  • Check satisfiability

  • Retrieve models, proofs, cores

  • Additional information

Assertions

Solver methods

s.add($\varphi$)
s.assert_and_track($\varphi, \ell$)



Assert $\varphi$ to the solver state. Optionally, track the assertion $\varphi$ by a literal $\ell$.

Unsatisfiable cores contain tracked literals.

Scopes

Solver methods

s.push()

s.pop()



Add or remove a scope from the solver.

Assertions added within a scope are removed when the scope is popped.

Check Satisfiability

Solver methods

s.check()

s.check($[\ell_1,\ldots, \ell_n]$)


Is the solver state satisfiable?

Is the solver state satisfiable modulo the assumption literals $\ell_1, \ldots, \ell_n$.

The solver state is the conjunction of assumption literals and assertions that have been added to the solver in the current scope.

Certificates

Methods


s.model()

s.proof()

s.unsat_core()   


An interpretation satisfying current constraints.

A proof term certifying unsatisfiability of constraints.

A subset of assumptions/tracked assertions that suffice to establish unsatisfiability.

Summary

We looked at:

Applications: configuration, model checking, scheduling



Queries: MaxSAT, backbones



Theories: a rough overview



Algorithms: as extensions or layers over SAT/SMT

Madoko

  • Madoko is a A Fast Scholarly Markdown Processor,
  • intuitive and powerful integration of markdown and LaTeX,
  • browser and Azure based - no installation,
  • immediate preview,
  • real-time collaborative editing,
  • is written in Koka,
  • is by Daan Leijen, Microsoft Research daan

References

[1]Fahiem Bacchus, and George Katsirelos. “Using Minimal Correction Sets to More Efficiently Compute Minimal   Unsatisfiable Sets.” In Computer Aided Verification - 27th International Conference, CAV   2015, San Francisco, CA, USA, July 18-24, 2015, Proceedings, Part II, 70–86. 2015. doi:10.1007/978-3-319-21668-3_5🔎
[2]Nikolaj Bjørner, and Nina Narodytska. “Maximum Satisfiability Using Cores and Correction Sets.” In Proceedings of the Twenty-Fourth International Joint Conference on   Artificial Intelligence, IJCAI 2015, Buenos Aires, Argentina, July 25-31, 2015, 246–252. 2015. http://​ijcai.​org/​Abstract/​15/​041🔎
[3]Aaron R. Bradley, and Zohar Manna. “Checking Safety by Inductive Generalization of Counterexamples to   Induction.” In Formal Methods in Computer-Aided Design, 7th International Conference,   FMCAD 2007, Austin, Texas, USA, November 11-14, 2007, Proceedings, 173–180. 2007. doi:10.1109/FAMCAD.2007.15🔎
[4]B. Dutertre, and L. de Moura. “A Fast Linear-Arithmetic Solver for DPLL(T).” In CAV. 2006. 🔎
[5]Yeting Ge, and Leonardo Mendonça de Moura. “Complete Instantiation for Quantified Formulas in Satisfiabiliby   Modulo Theories.” In CAV, 306–320. 2009. 🔎
[6]Mikolás Janota, Inês Lynce, and Joao Marques-Silva. “Algorithms for Computing Backbones of Propositional Formulae.” AI Commun. 28 (2): 161–177. 2015. doi:10.3233/AIC-140640🔎
[7]Dejan Jovanovic, and Leonardo Mendonça de Moura. “Solving Non-Linear Arithmetic.” In Automated Reasoning - 6th International Joint Conference, IJCAR   2012, Manchester, UK, June 26-29, 2012. Proceedings, 339–354. 2012. doi:10.1007/978-3-642-31365-3_27🔎
[8]Ulrich Junker. “QUICKXPLAIN: Preferred Explanations and Relaxations for Over-Constrained   Problems.” In Proceedings of the Nineteenth National Conference on Artificial Intelligence,   Sixteenth Conference on Innovative Applications of Artificial Intelligence, July 25-29, 2004, San Jose, California, USA, 167–172. 2004. http://​www.​aaai.​org/​Library/​AAAI/​2004/​aaai04-​027.​php🔎
[9]Mark H Liffiton, Alessandro Previti, Ammar Malik, and Joao Marques-Silva. “Fast, Flexible MUS Enumeration.” Constraints 21 (2). Springer US: 223–250. 2016. 🔎
[10]João Marques-Silva, Mikolás Janota, and Anton Belov. “Minimal Sets over Monotone Predicates in Boolean Formulae.” In Computer Aided Verification - 25th International Conference, CAV   2013, Saint Petersburg, Russia, July 13-19, 2013. Proceedings, 592–607. 2013. doi:10.1007/978-3-642-39799-8_39🔎
[11]Carlos Mencía, Alessandro Previti, and João Marques-Silva. “Literal-Based MCS Extraction.” In Proceedings of the Twenty-Fourth International Joint Conference on   Artificial Intelligence, IJCAI 2015, Buenos Aires, Argentina, July 25-31, 2015, 1973–1979. 2015. http://​ijcai.​org/​Abstract/​15/​280🔎
[12]Leonardo Mendonça de Moura, and Nikolaj Bjørner. “Generalized, Efficient Array Decision Procedures.” In Proceedings of 9th International Conference on Formal Methods in Computer-Aided   Design, FMCAD 2009, 15-18 November 2009, Austin, Texas, USA, 45–52. 2009. doi:10.1109/FMCAD.2009.5351142🔎
[13]Nina Narodytska, and Fahiem Bacchus. “Maximum Satisfiability Using Core-Guided MaxSAT Resolution.” In AAAI 2014, 2717–2723. 2014. 🔎
[14]Raymond Reiter. “A Theory of Diagnosis from First Principles.” Artif. Intell. 32 (1): 57–95. 1987. doi:10.1016/0004-3702(87)90062-2🔎