Nikolaj Bjørner
Microsoft Research
nbjorner@microsoft.com |
An Introduction to Satisfiability Modulo Theories and Z3
Theory Solvers
SAT and SMT Algorithms
Optimization with MaxSAT
Quantifier Reasoning
An Introduction to Satisfiability Modulo Theories and Z3
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()
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()
Is formula satisfiable under theory ?
SMT solvers use specialized algorithms for .
|
|
Sorts -
- signature of sorted constant, functions
Predicates are functions with range
Terms and predicates are built from functions over
Connectives and Quantifiers
Slide is by Joao Marques-Silva
sat unsat
model (clausal) proof
correction set core
local min correction set local min core
min correction set min core
Theory Solvers
(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)
Variants of union-find are effective to decide equality.
Congruence rule
A satisfiable version:
(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
Logic | Fragment | Solver | Example |
---|---|---|---|
LRA | Linear Real Arithmetic | Dual Simplex | |
LIA | Linear Integer Arithmetic | CutSat | |
LIRA | Mixed Real/Integer | Cuts + Branch | |
IDL | Integer Difference Logic | Floyd-Warshall | |
RDL | Real Difference Logic | Bellman-Ford | |
UTVPI | Unit two-variable per inequality | ||
NRA | Polynomial Real Arithmetic | Model based CAD | |
NIA - There is no decision procedure for integer polynomial constraints
Other theories that admit custom solvers:
Bi-linear real arithmetic
Non-unit two-variable per inequality
At most one unit positive variable per inequality (Horn)
(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
Solve difference logic using graph Bellman-Ford network flow algorithm. Negative cycle unsat.
General form and
Only bounds (e.g., ) are asserted during search.
- are basic (dependent)
- are non-basic
- are basic (dependent)
- are non-basic
Initial values:
Bounds :
, make non-basic.
- are basic (dependent)
- are non-basic
(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)
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)
Example Store(a, i, v)
Store(a, i, v)
and b[j]
,
Store(a, i, v)[j] == If(i == j, v, a[j])
Assert Store(a, i, v)[i] == v
Example Store(a, i, v)
Store(a, i, v)
and b[j]
,
Store(a, i, v)[j] == If(i == j, v, a[j])
Assert Store(a, i, v)[i] == v
Assert .
Store
axioms.
Use current partial interpretation to guide axiom instantiation.
Rough sketch:
Also important to limit set of pairs.
(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)
(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)
(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)
(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))
)
; 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)
Strings: Decidability and efficiency.
Certificates: Modular, Clausal
New, non-disjoint, theories
SAT and SMT Algorithms
Anatomy of conflict directed clause learning SAT solving.
Efficient indexing (two-watch literal)
Non-chronological backtracking (backjumping)
Lemma learning
Variable and phase selection
Garbage collection, restarts
- atomic predicates.
- literals over atoms.
- partial consistent assignment.
- a clause - disjunction of literals.
- a decision literal.
- () - a literal with explanation .
- a set of clauses.
Theorem 1.
For every , exactly one of the two conditions hold:
Corollary 1.
CDCL realizes the dichotomy by interleaving model and consequence finding:
Corollary 2.
If , then for every
where : .
Corollary 3.
If , i.e., for some , then
for every consequence from using forced literals in it is the case
that and there is no
such that .
Main invariants preserved by CDCL:
if
CDCL searches for local inferences.
Significant progress in SAT has been around global inferences.
Blocked Clause Elimination
Asymmetric Literal Addition
Asymmetric Covered Clause Elimination
Blocked Clause Addition
is blocked on literal in set of clauses if
for every clause in :
is a tautology.
Blocked clauses can be eliminated from without changing Satisfiability.
A model for may not satisfy .
Models can be fixed by swapping truth assignment of .
Asymmetric Tautology Elimination
Asymmetric Blocked Clause Elimination
Claim: adding to does not change satisfiability of .
Clauses that become blocked after adding Resolution Intersection can be removed.
ACCE: expand clause using
A theory is a set (potentially infinite) of first-order sentences.
Main questions:
Two theories are disjoint if they do not share function/constant and predicate symbols. is the only exception.
Example:
The theories of arithmetic and arrays are disjoint.
Arithmetic symbols: .
Array symbols:
It is a different name for our naming subterms procedure.
becomes
becomes
A theory is stably infinite if every satisfiable QFF is satisfiable in an infinite model.
EUF and arithmetic are stably infinite.
Bit-vectors are not
The union of two consistent, disjoint, stably infinite theories is consistent.
A theory is convex iff:
Every convex theory with non trivial models is stably infinite.
Horn equational theories are convex.
Integer arithmetic is not convex.
Real non-linear arithmetic
EUF is convex
IDL is non-convex
is NP-complete
purify
Optimization and MaxSAT
Optimization as SMT with preferred models
An introduction to cores and correction sets
Show examples of algorithms on top of SMT/Z3
Three main SMT extensions
|
|
Equilvalent formulations
|
|
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()
MaxSAT solver
Primal simplex optimization
Box | |
Lex | |
Pareto | |
(M)US (Minimal) unsatisfiable subset
(M)SS (Maximal) satisfiable subset
(M)CS (Minimal) correction set
(Prime) implicant
|
|
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
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
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})
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
Find all satisfying subsets among :
Typical definition: Minimize the number of violated soft assertions.
Is built-in, based on MaxSAT algorithms.
(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)
(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)
- hard constraints
- soft constraints
A:
A':
Lemma: for any model of ,
Proof: min:
A:
A':
Lemma: for any model of ,
Proof: min:
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) }
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 [11] we combine MUS and MCS steps.
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)])
Quantifier Reasoning
Formulas are ground unsatisfiable.
Takes
Let be a set of terms and set of equalities over .
A congruence closure over modulo is the finest a partition of , cc, such that:
if , then are in the same partition in cc.
for ,
Convention: , maps term to its equivalence class.
def match(pattern, term, , cc):
pattern = pattern
if pattern == term:
yield
elif is_var(pattern):
yield pattern term
else:
f(patterns) = pattern
for f(terms) in cc(term):
# e.g., with same head function symbol f
for in matches(patterns, terms, , cc):
yield
def matches(patterns, terms, , cc):
if not patterns:
yield
return
for in match(patterns[0], terms[0], , cc):
for in matches(patterns[1:], terms[1:], , cc):
yield
PC | Instruction | |
---|---|---|
init(f, ) | add arguments of to registers 1-4 | |
check(4,,) | check if is congruent to | |
bind(2, , 5, ) | bind terms in with to | |
compare(1, 5, ) | check if equals | |
check(6, , ) | check if is congruent to | |
bind(3, , 7, ) | bind terms in with to | |
yield(1,7) | output binding from | |
PC | Instruction | ||
---|---|---|---|
init(f, ) | |||
check(4,,) | |||
bind(2, , 5, ) | |||
compare(1, 5, ) | |||
check(6, , ) | |||
bind(3, , 7, ) | |||
yield(1,7) | |||
PC | Instruction | ||
---|---|---|---|
init(f, ) | |||
check(4,,) | |||
bind(2, , 5, ) | |||
compare(1, 5, ) | |||
check(6, , ) | |||
bind(3, , 7, ) | |||
yield(1,7) | |||
Patterns that share common (top-down) term structure can share code sequences.
This saves on common work.
Use the choice instruction to branch when patterns end up having different sub-terms.
Other instructions are possible,
forward pruning: lookahead multiple function symbols in immediate subterms before diving into any subterm.
to deal with multi-patterns, when maching more than one pattern at a time.
During search, congruence classes are merged.
Q: Which merges could enable pattern to be matched?
A: When pattern contains term , and
a node is in in the same class as a node labeled by ,
a node is an argument of in the same position as ,
, are merged
Idea: Build an index of all pairs from patterns.
Check
while is SAT with model :
if is UNSAT return SAT
model for
find , such that .
return UNSAT
where is partially evaluated using interpretation .
Example:
Quite powerful when search space for instantiation terms is finite
Also known as Bernays-Schoenfinkel-Ramsey class.
Same complexity as DQBF.
(declare-sort T)
(declare-fun subtype (T T) Bool)
;; subtype is reflexive
(assert (forall ((x T)) (subtype x x)))
;; subtype is antisymmetric
(assert (forall ((x T) (y T)) (=> (and (subtype x y) (subtype y x)) (= x y))))
;; subtype is transitive
; ...
;; subtype has the tree-property
(assert (forall ((x T) (y T) (z T))
(=> (and (subtype x z) (subtype y z)) (or (subtype x y) (subtype y x)))))
;; we have an additional axiom: every type is a subtype of obj-type
(declare-const obj-type T) ....
(assert (forall ((x T)) (subtype x obj-type)))
(assert (subtype int-type real-type))
(assert (subtype real-type complex-type))
(assert (not (subtype string-type real-type)))
Skolemize
Models for bind variables to free constants
The number of possible such models is bounded by .
(set-option :smt.mbqi true)
(define-sort Char () (_ BitVec 8))
(declare-fun f (Char) Char)
(declare-fun f1 (Char) Char)
(declare-const a Char)
(assert (bvugt a #x00))
(assert (= (f1 (bvadd a #x01)) #x00))
(assert (forall ((x Char)) (or (= x (bvadd a #x01)) (= (f1 x) (f x)))))
(check-sat)
(get-model)
is equal to except at index .
can only have two values, or .
(set-option :smt.mbqi true)
(set-option :model.compact true)
;; A0, A1, A2, A3, A4 are "arrays" from Integers to Integers.
(declare-fun A0 (Int) Int) (declare-fun A1 (Int) Int)
(declare-fun A2 (Int) Int) (declare-fun A3 (Int) Int)
(declare-fun A4 (Int) Int)
(declare-const n Int) (declare-const l Int)
(declare-const k Int) (declare-const x Int)
(declare-const y Int) (declare-const w Int)
(declare-const z Int)
;; A1 = A0[k <- w]
(assert (= (A1 k) w))
(assert (forall ((x Int)) (or (= x k) (= (A1 x) (A0 x)))))
;; A2 = A1[l <- x] = A0[k <- w][l <- x]
(assert (= (A2 l) x))
(assert (forall ((x Int)) (or (= x l) (= (A2 x) (A1 x)))))
;; A3 = A0[k <- y]
(assert (= (A3 k) y))
(assert (forall ((x Int)) (or (= x k) (= (A3 x) (A0 x)))))
;; A4 = A3[l <- z] = A0[k <- y][l <- z]
(assert (= (A3 l) z))
(assert (forall ((x Int)) (or (= x l) (= (A4 x) (A3 x)))))
(assert (and (< w x) (< x y) (< y z)))
(assert (and (< 0 k) (< k l) (< l n)))
(assert (> (- l k) 1))
;; A2 is sorted in the interval [0,n-1]
(assert (forall ((i Int) (j Int))
(=> (and (<= 0 i) (<= i j) (<= j (- n 1)))
(<= (A2 i) (A2 j)))))
(check-sat)
(get-model)
;; A4 is sorted in the interval [0,n-1]
(assert (forall ((i Int) (j Int))
(=> (and (<= 0 i) (<= i j) (<= j (- n 1)))
(<= (A4 i) (A4 j)))))
(check-sat)
Given formula with free.
Let be set of a set of from .
Definition 1.
The set is a sufficient set of instances for , if
Proposition 1.
If admits a finite sufficient set of instances , it can be evaluated using those.
Proposition 2.
Formulas in the array and map property fragments admit a sufficient set of instantiations.
Proposition 3.
MBQI is a decision procedure the array and map property fragments by using the
instantiation sets computed from the formulas.
Synthesize generalized instantiation sets using grammar rules.
Applies to winder range of formulas than the syntactic array property fragment.
(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)
As pursued in [55]
The notion of instantiation set can be extended along a different dimension of virtual substitutions.
Several theories admit quantifier elimination by virtual substitutions.
Example .
Tricky part: ensure that set of virtual substitutions does not grow unbounded.
|
|
Goal: To find a quantifier free , such that
Tool: project that eliminates from a conjunction
that is, project() .
Initialize:
Repeatedly: find conjunctions that imply
Update: project().
def qe():
e, a = Solver(), Solver()
e.add()
a.add()
= False
while sat == e.check():
= e.model()
= # assume is in negation normal form
assert unsat == a.check()
= a.unsat_core()
= project(, )
=
e.add()
return
Two players try to find values
Players control their variables
Some player loses at round .
Projections are added to learn from mistakes.
Strategies prune moves from opponent.
Player has lost at round
Player found a model at round , .
induces an evaluation on a subset of literals in , such that .
is an unsatisfiable core for .
Model Based Projection
Find a , such that .
Then can block .
Idea: Use to find a sufficient .
def level(j,a): return max level of bound variable in atom a of parity j
def strategy(M,j): return
def tailv(j): return
j = 1
M = null
while True:
if strategy(M, j) is unsat:
if j == 1:
return F is unsat
if j == 2:
return F is sat
C = Core(, strategy(M, j))
J = Mbp(tailv(j), C)
j = index of max variable in J of same parity as j
= J
M = null
else:
M = current model
j = j + 1
Projections learn from mistakes, avoids similar mistakes in future rounds.
Strategies prune moves from opponent.
Want to compute small .
Note
Say
So
Eliminate from conjunction of literals :
Trick: Use to turn into .
Can now assume occurs only as upper or lower bounds:
def sign(M,a): if M(a) return a else return a
For LIA, cannot just assume equalities are of the form or .
Generally, has a coefficient, that we cannot remove.
Example: .
What could go wrong if we just reduce to ?
Suppose , . So .
Cross-multiplying gives , which is feasible, but is infeasible.
Solution: Combine inequalities using resolution
if
else if
otherwise,
satisfies , and …
Resolution introduced divisibility constraints.
So now we also have to eliminate under divisions.
where
S-expressions: A generic term algebra
An s-expression is either a nil or a cons.
Access arguments of cons using car and cdr.
Test terms using cons?(), or nil?()
amounts to unification
Case for is symmetric.
Since there is an infinite number of cons-terms.
New terms are created during
but they are of the form following shape of original constructor terms.
and they occur in conjunctions with .
so produces finite set of projections.
Theory: Non-linear polynomial arithmetic
Partial CAD - model-based projection [34]
CAD decomposes into sign-invariant cylinders.
Choose the cylinder where is a member.
Sat based MBP [37]:
Given:
Find: , free for
Such that:
Contrast this with Core-based MBP [48]:
Given: .
Find: , free for
Such that:
Claim: (Roughly) The same projection operator can be used in both cases if occurs in all literals and the operator is stable under changes to the value of .
Other main ingredient of QSAT is option for players to narrow options of opponents by revealing a strategy
Developing practical strategies is work in progress
For QBF can use Q-resolution proofs as guide [9]
Method by Markus Rabe can be seen as a strategy.
|
|
Fixedpoint methods
|
|
~ Begin Vertical
are state variables.
is a monome (a conjunction of literals).
is a clause (a disjunction of literals).
Convention: is a monome over variables , is a renaming of the same monome to variables .
repeat until ∞
Candidate If for some , , then add to .
Unfold If , then set .
repeat until ∞
Unreachable For , if , return Unreachable.
Reachable If , return Reachable.
repeat until ∞
repeat until ∞
Conflict Let : given a candidate model and clause , such that
Leaf If , and is unsatisfiable,
then add to .
repeat until ∞
Decide Add to if , .
Pssst: I am replacing by greek letters.
Conflict Let : given a candidate model and clause , such that , if , then conjoin to , for .
Conflict Let : given a candidate model and a formula , such that , , then conjoin to , for .
Recall predicate transformer for McCarthy91:
Decide now spawns two children.
Decide If and there are consistent such that and , then add , to .
We also have to take DAG unfolding into acount.
Base Mark if or if there is a consistent
such that and .
Close Mark if all children are marked.
Reachable If is marked, return Reachable.
Decide and Conflict pushing a goal over
Reachable If is satisfiable, then return Reachable.
Decide For for , add to if:
- .
- .
-
- is disjoint from for every .
Decide For for , add to if:
- .
- .
-
- is disjoint from for every .
Close For for , if is satisfiable, but is unsatsifiable,
then update , where .
def sign(s, x):
if tt(s, x):
return x
return Not(x)
def cute(A,B,xs):
sA = Solver()
sB = Solver()
sA.add(A)
sB.add(B)
I = []
while sat == sB.check():
if unsat == sA.check([ sign(sB, x) for x in xs ]):
I1 = Not(And(sA.unsat_core()))
sB.add(I1)
I += [I1]
else:
return None
return And(I)
Can also be viewed as an iteration of IC3 steps. Generalization to EPR [6].
Option 1: use BDDs to represent tables.
Option 2: build tables from ternary bit-vectors.
Option 3,4,..: Use hash tables, B-trees, bit-maps
Solver methods
|
|
Solver methods
|
Unsatisfiable cores contain tracked literals. |
Solver methods
|
Assertions added within a scope are removed when the scope is popped. |
Solver methods
|
Is the solver state satisfiable modulo the assumption literals . The solver state is the conjunction of assumption literals and assertions that have been added to the solver in the current scope. |
Methods
|
|
We looked at:
Applications: configuration, model checking, scheduling
Queries: MaxSAT, backbones
Theories: a rough overview
Algorithms: as extensions or layers over SAT/SMT