GRATchk: Verified (UN)SAT Certificate Checker
Peter Lammich
May 2, 2017
Abstract
GRATchk is a formally verified and efficient checker for satisfiability and unsatisfiability certificates for
Boolean formulas.
The verification covers the actual efficient implementation, and the semantics of a formula down to
the integer sequences that represents it.
The satisfiability certificates are non-contradictory lists of literals, as output by any standard SAT
solver. The unsatisfiability certificates are GRAT certificates, which can be generated from standard
DRAT certificates by the GRATgen tool.
Contents
1 Introduction
4
2 Basics of Boolean Formulas in CNF
2.1 Used Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Assigning Valuations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
5
6
3 Unit Propagation and RUP/RAT Checks
3.1 Partial Assignments . . . . . . . . . . . . . .
3.1.1 Models, Equivalence, and Redundancy
3.2 Unit Propagation . . . . . . . . . . . . . . . .
3.3 RUP and RAT Criteria . . . . . . . . . . . .
3.4 Old assign all negated Formulation . . . . . .
3.4.1 Properties of assign all negated . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6
6
10
12
12
13
14
4 Basic Notions for the GRAT Format
4.1 Encoding of Literals and Clauses . . . . .
4.2 Input Parser . . . . . . . . . . . . . . . . .
4.3 Implementation . . . . . . . . . . . . . . .
4.3.1 Literals . . . . . . . . . . . . . . .
4.3.2 Assignment . . . . . . . . . . . . .
4.3.3 Clause Database . . . . . . . . . .
4.3.4 Clausemap . . . . . . . . . . . . .
4.3.5 Clause Database . . . . . . . . . .
4.4 Common GRAT Stuff . . . . . . . . . . .
4.4.1 Clause Map . . . . . . . . . . . . .
4.4.2 Correctness . . . . . . . . . . . . .
4.4.3 Alternative Correctness Statement
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15
16
16
19
19
19
21
21
23
24
24
24
25
5 Unsat Checker
5.1 Abstract level . . . . . . . . . . . . . . .
5.2 Refinement — Backtracking . . . . . . .
5.3 Refinement 1 . . . . . . . . . . . . . . .
5.4 Refinement 2 . . . . . . . . . . . . . . .
5.4.1 Getting Out of Exception Monad
5.4.2 Instantiating Input Locale . . . .
5.4.3 Extraction from Locale . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
25
25
36
41
52
52
54
54
.
.
.
.
.
.
.
1
5.5
5.4.4 Synthesis of Imperative Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Correctness Theorem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6 Satisfiability Check
6.1 Abstract Specification . . . . . . . . . .
6.2 Implementation . . . . . . . . . . . . . .
6.2.1 Getting Out of Exception Monad
6.3 Extraction from Locales . . . . . . . . .
6.3.1 Synthesis of Imperative Code . .
6.4 Correctness Theorem . . . . . . . . . . .
57
62
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
62
62
63
64
64
64
65
7 Code Generation and Summary of Correctness Theorems
7.1 Code Generation . . . . . . . . . . . . . . . . . . . . . . . . .
7.2 Summary of Correctness Theorems . . . . . . . . . . . . . . .
7.2.1 Interpreting an Integer List as Formula . . . . . . . .
7.2.2 Satisfiable Formulas . . . . . . . . . . . . . . . . . . .
7.2.3 Extracting the Formula from the Input Array . . . . .
7.2.4 Hoare-Triples for our Checkers . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
66
66
66
66
67
67
68
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
[Grat_Check_Base]
SAT_Basic
Unit_Propagation
Grat_Basic
Sat_Check
Cert_Sat
Unsat_Check
Unsat_Check_Split
Grat_Check_Code_Exporter
Figure 1: Theory dependency graph
3
1
Introduction
We present an efficient verified checker for satisfiability and unsatisfiability certificates obtained from SAT
solvers.
Our sat certificates are lists of non-contradictory literals, as produced by virtually any SAT solver.
The de facto standard for unsat certificates is DRAT. Here, our checker uses a two step approach: The
unverified GRATgen tool converts the DRAT certificates into GRAT certificates, which are then checked
against the original formula by the verified GRATchk, presented in this formalization.
The GRAT certificates are engineered to admit a simple and efficient checker algorithm, which is well
suited for formal verification. We use the Isabelle Refinement Framework to verify an efficient imperative
implementation of the checker algorithm.
Our verification covers the semantics of a formula down to the integer sequence that represents it. This way,
only a simple untrusted parser is required to read the formula from a file to an integer array. In Section 7.2,
we give a complete and self-contained summary of what we actually proved.
2
Basics of Boolean Formulas in CNF
theory SAT Basic
imports Main
begin
datatype 0a literal = is pos: Pos 0a | Neg 0a
type-synonym 0a clause = 0a literal set
type-synonym 0a cnf = 0a clause set
type-synonym 0a valuation = 0a ⇒ bool
fun sem lit :: 0a literal ⇒ 0a valuation ⇒ bool where
sem lit (Pos x ) σ = σ x
| sem lit (Neg x ) σ = (¬ σ x )
lemma sem lit alt: sem lit l σ = (case l of Pos x ⇒ σ x | Neg x ⇒ ¬σ x )
hproof i
definition sem clause :: 0a clause ⇒ 0a valuation ⇒ bool where
sem clause C σ ≡ ∃ l ∈C . sem lit l σ
definition sem cnf :: 0a cnf ⇒ 0a valuation ⇒ bool where
sem cnf F σ ≡ ∀ C ∈F . sem clause C σ
definition sat :: 0a cnf ⇒ bool where
sat F ≡ ∃ σ. sem cnf F σ
definition models :: 0a cnf ⇒ 0a valuation set where
models F ≡ {σ. sem cnf F σ}
fun neg lit where
neg lit (Pos x ) = Neg x | neg lit (Neg x ) = Pos x
lemma neg neg lit[simp]: neg lit (neg lit l ) = l hproof i
lemma neg lit neq[simp]:
neg lit l 6= l
l 6= neg lit l
hproof i
definition mk lit where mk lit p x ≡ if p then Pos x else Neg x
lemma is pos mk lit[simp]: is pos (mk lit p x ) ←→ p
hproof i
4
lemma sem clause empty[simp]: sem clause {} σ = False
hproof i
lemma sem clause insert[simp]: sem clause (insert l C ) σ ←→ sem lit l σ ∨ sem clause C σ
hproof i
lemma sem clause union[simp]: sem clause (C 1 ∪C 2 ) σ ←→ sem clause C 1 σ ∨ sem clause C 2 σ
hproof i
lemma sem cnf empty[simp]: sem cnf {} σ hproof i
lemma sem cnf insert[simp]: sem cnf (insert C F ) σ ←→ sem clause C σ ∧ sem cnf F σ
hproof i
lemma sem cnf union[simp]: sem cnf (F 1 ∪ F 2 ) σ ←→ sem cnf F 1 σ ∧ sem cnf F 2 σ
hproof i
lemma sem clauseI : [[l ∈C ; sem lit l σ]] =⇒ sem clause C σ
hproof i
V
lemma sem cnfI : [[ C . C ∈F =⇒ sem clause C σ]] =⇒ sem cnf F σ
hproof i
lemma sem neg lit[simp]: sem lit (neg lit l ) σ ←→ ¬sem lit l σ
hproof i
lemma unsat empty clause: {}∈F =⇒ ¬sat F
hproof i
lemma sat empty[simp, intro!]: sat {}
hproof i
lemma unsat emptyc[simp, intro!]: ¬sat {{}}
hproof i
2.1
Used Variables
fun var of lit :: 0a literal ⇒ 0a where
var of lit (Pos x ) = x | var of lit (Neg x ) = x
lemma var of lit alt: var of lit l = (case l of Pos x ⇒ x | Neg x ⇒ x )
hproof i
definition vars of clause :: 0a clause ⇒ 0a set
where vars of clause C = var of lit ‘ C
S
definition vars of cnf :: 0a cnf ⇒ 0a set where vars of cnf F ≡ (vars of clause‘F )
lemma vars of
vars of clause
vars of clause
vars of clause
hproof i
lemma vars
vars of cnf
vars of cnf
vars of cnf
hproof i
clause simps[simp]:
{} = {}
(insert l C ) = insert (var of lit l ) (vars of clause C )
(C 1 ∪ C 2 ) = vars of clause C 1 ∪ vars of clause C 2
of cnf simps[simp]:
{} = {}
(insert C F ) = vars of clause C ∪ vars of cnf F
(F 1 ∪F 2 ) = vars of cnf F 1 ∪ vars of cnf F 2
lemma vars of clause empty iff [simp]: vars of clause C = {} ←→ C ={}
hproof i
lemma vars of cnf empty iff [simp]: vars of cnf F = {} ←→ (F ={} ∨ F ={{}})
hproof i
lemma var of lit neg eq[simp]: var of lit (neg lit l ) = var of lit l hproof i
5
lemma syn indep lit: x 6=var of lit l =⇒ sem lit l (σ(x :=v )) = sem lit l σ
hproof i
lemma syn indep clause: x ∈vars
/
of clause C =⇒ sem clause C (σ(x :=v )) = sem clause C σ
hproof i
lemma syn indep cnf : x ∈vars
/
of cnf F =⇒ sem cnf F (σ(x :=v )) = sem cnf F σ
hproof i
2.2
Assigning Valuations
definition set lit F l ≡ { C − {neg lit l } | C . C ∈F ∧ l ∈
/ C }
lemma sem clause set: sem clause C (σ(var of lit l := is pos l ))
←→ l ∈C ∨ sem clause (C − {neg lit l }) σ
hproof i
lemma sem cnf set: sem cnf F (σ(var of lit l := is pos l )) ←→ sem cnf (set lit F l ) σ
hproof i
lemma upd sigma true[simp]: σ x =⇒ σ(x :=True) = σ hproof i
lemma upd sigma false[simp]: ¬σ x =⇒ σ(x :=False) = σ hproof i
lemma set lit no var : var of lit l ∈
/ vars of cnf (set lit F l )
hproof i
lemmas indep set lit = syn indep cnf [OF set lit no var ]
end
3
Unit Propagation and RUP/RAT Checks
theory Unit Propagation
imports SAT Basic
begin
This theory formalizes the basics of unit propagation and RUP/RAT redundancy checks.
3.1
Partial Assignments
primrec sem lit 0 :: 0a literal ⇒ ( 0a*bool ) * bool where
sem lit 0 (Pos x ) A = A x
| sem lit 0 (Neg x ) A = map option Not (A x )
definition sem clause 0 :: 0a literal set ⇒ ( 0a * bool ) * bool where
sem clause 0 C A ≡
if ∃ l ∈C . sem lit 0 l A = Some True then Some True
else if ∀ l ∈C . sem lit 0 l A = Some False then Some False
else None
lemma sem neg lit 0[simp]:
sem lit 0 (neg lit l ) A = map option Not (sem lit 0 l A)
hproof i
lemma (in −) sem lit 0 empty[simp]: sem lit 0 l Map.empty = None
hproof i
We install a custom case distinction rule for bool option, which has the cases undec, false, and true.
fun boolopt cases aux where
boolopt cases aux None = ()
| boolopt cases aux (Some False) = ()
6
| boolopt cases aux (Some True) = ()
lemmas boolopt cases[case names undec false true, cases type]
= boolopt cases aux .cases
lemma not Some bool if : [[ a6=Some False; a6=Some True ]] =⇒ a=None
hproof i
Rules to trigger case distinctions on the semantics of a clause with a distinguished literal.
lemma sem clause insert eq complete:
sem clause 0 (insert l C ) A = (case sem lit 0 l A of
Some True ⇒ Some True
| Some False ⇒ sem clause 0 C A
| None ⇒ (case sem clause 0 C A of
None ⇒ None
| Some False ⇒ None
| Some True ⇒ Some True))
hproof i
lemma sem clause empty[simp]: sem clause 0 {} A = Some False
hproof i
lemma sem clause 0 insert true: sem clause 0 (insert l C ) A = Some True ←→
sem lit 0 l A = Some True ∨ sem clause 0 C A = Some True
hproof i
lemma sem clause 0 insert false[simp]:
sem clause 0 (insert l C ) A = Some False
←→ sem lit 0 l A = Some False ∧ sem clause 0 C A = Some False
hproof i
lemma sem clause 0 union false[simp]:
sem clause 0 (C1 ∪C2 ) A = Some False
←→ sem clause 0 C1 A = Some False ∧ sem clause 0 C2 A = Some False
hproof i
Assign variable such that literal becomes true
definition assign lit A l ≡ A( var of lit l 7→ is pos l )
lemma assign lit simps[simp]:
assign lit A (Pos x ) = A(x 7→True)
assign lit A (Neg x ) = A(x 7→False)
hproof i
lemma assign lit dom[simp]:
dom (assign lit A l ) = insert (var of lit l ) (dom A)
hproof i
lemma sem lit assign[simp]: sem lit 0 l (assign lit A l ) = Some True
hproof i
lemma sem lit 0 none conv : sem lit 0 l A = None ←→ A (var of lit l ) = None
hproof i
lemma assign undec pres dec lit:
[[ sem lit 0 l A = None; sem lit 0 l 0 A = Some v ]]
=⇒ sem lit 0 l 0 (assign lit A l ) = Some v
hproof i
lemma assign undec pres dec clause:
[[ sem lit 0 l A = None; sem clause 0 C A = Some v ]]
=⇒ sem clause 0 C (assign lit A l ) = Some v
7
hproof i
lemma sem lit 0 assign conv : sem lit 0 l 0 (assign lit A l ) = (
if l 0=l then Some True
else if l 0=neg lit l then Some False
else sem lit 0 l 0 A)
hproof i
Predicates for unit clauses
definition
≡ l ∈C ∧
definition
definition
is unit lit A C l
sem lit 0 l A = None ∧ (sem clause 0 (C −{l }) A = Some False)
is unit clause A C ≡ ∃ l . is unit lit A C l
the unit lit A C ≡ THE l . is unit lit A C l
abbreviation (input) is conflict clause A C ≡ sem clause 0 C A = Some False
abbreviation (input) is true clause A C ≡ sem clause 0 C A = Some True
definition compat assignment :: ( 0a * bool ) ⇒ ( 0a ⇒ bool ) ⇒ bool
where compat assignment A σ ≡ ∀ x v . A x = Some v −→ σ x = v
lemma compat assignment empty[simp]: compat assignment Map.empty σ
hproof i
lemma sem clause 0 false conv :
sem clause 0 C A = Some False ←→ (∀ l ∈C . sem lit 0 l A = Some False)
hproof i
lemma sem clause 0 true conv :
sem clause 0 C A = Some True ←→ (∃ l ∈C . sem lit 0 l A = Some True)
hproof i
lemma the unit lit eq[simp]: is unit lit A C l =⇒ the unit lit A C = l
hproof i
lemma is unit lit unique: [[is unit lit C A l1 ; is unit lit C A l2 ]] =⇒ l1 =l2
hproof i
lemma is unit clauseE :
assumes is unit clause A C
obtains l C 0 where
C =insert l C 0
l ∈C
/ 0
sem lit 0 l A = None
sem clause 0 C 0 A = Some False
the unit lit A C = l
hproof i
lemma is unit clauseE 0:
assumes is unit clause A C
obtains l C 0 where
C =insert l C 0
l ∈C
/ 0
sem lit 0 l A = None
sem clause 0 C 0 A = Some False
hproof i
lemma sem not false the unit lit:
assumes is unit lit A C l
assumes l 0∈C
assumes sem lit 0 l 0 A 6= Some False
shows l 0=l
hproof i
8
lemma sem none the unit lit:
assumes is unit lit A C l
assumes l 0∈C
assumes sem lit 0 l 0 A = None
shows l 0=l
hproof i
lemma is unit lit unique ss:
[[C 0⊆C ; is unit lit A C 0 l 0; is unit lit A C l ]] =⇒ l 0=l
hproof i
lemma is unit litI :
[[l ∈C ; sem clause 0 (C −{l }) A = Some False; sem lit 0 l A = None]]
=⇒ is unit lit A C l
hproof i
lemma is unit clauseI : is unit lit A C l =⇒ is unit clause A C
hproof i
lemma unit other false:
assumes is unit lit A C l
assumes l 0∈C l 6=l 0
shows sem lit 0 l 0 A = Some False
hproof i
lemma unit clause sem 0: is unit lit A C l =⇒ sem clause 0 C A = None
hproof i
lemma unit clause assign dec:
is unit lit A C l =⇒ sem clause 0 C (assign lit A l ) = Some True
hproof i
lemma unit clause sem: is unit clause A C =⇒ sem clause 0 C A = None
hproof i
lemma sem not unit clause: sem clause 0 C A 6= None =⇒ ¬is unit clause A C
hproof i
lemma unit contains no true:
assumes is unit clause A C
assumes l ∈C
shows sem lit 0 l A 6= Some True
hproof i
lemma two nfalse not unit:
assumes l1 ∈C and l2 ∈C and l1 6=l2
assumes sem lit 0 l1 A 6= Some False and sem lit 0 l2 A 6= Some False
shows ¬is unit clause A C
hproof i
lemma conflict clause assign indep:
assumes sem clause 0 C (assign lit A l ) = Some False
assumes neg lit l ∈
/ C
shows sem clause 0 C A = Some False
hproof i
lemma sem lit 0 assign undec conv :
sem lit 0 l 0 (assign lit A l ) = None
←→ sem lit 0 l 0 A = None ∧ var of lit l 6= var of lit l 0
hproof i
lemma unit clause assign indep:
9
assumes is unit clause (assign lit A l ) C
assumes neg lit l ∈
/ C
shows is unit clause A C
hproof i
lemma clause assign false cases[consumes 1 , case names no lit lit]:
assumes sem clause 0 C (assign lit A l ) = Some False
obtains neg lit l ∈
/ C sem clause 0 C A = Some False
| neg lit l ∈ C sem clause 0 (C −{neg lit l }) A = Some False
hproof i
lemma clause assign unit cases[consumes 1 , case names no lit lit]:
assumes is unit clause (assign lit A l ) C
obtains neg lit l ∈
/ C is unit clause A C
| neg lit l ∈ C
hproof i
lemma sem clause ins assign not false[simp]:
sem clause 0 (insert l C ) (assign lit A l ) 6= Some False
hproof i
lemma sem clause ins assign not unit[simp]:
¬is unit clause (assign lit A l ) (insert l C 0)
hproof i
context
fixes A :: 0a * bool and σ :: 0a ⇒ bool
assumes C : compat assignment A σ
begin
lemma compat lit: sem lit 0 l A = Some v =⇒ sem lit l σ = v
hproof i
lemma compat clause: sem clause 0 C A = Some v =⇒ sem clause C σ = v
hproof i
end
3.1.1
Models, Equivalence, and Redundancy
definition models 0 F A ≡ { σ. compat assignment A σ ∧ sem cnf F σ}
definition sat 0 F A ≡ models 0 F A 6= {}
definition equiv 0 F A A 0 ≡ models 0 F A = models 0 F A 0
lemma equiv 0 refl [simp]: equiv 0 F A A hproof i
lemma equiv 0 sym: equiv 0 F A A 0 =⇒ equiv 0 F A 0 A
hproof i
lemma equiv 0 trans[trans]: [[ equiv 0 F A B ; equiv 0 F B C ]] =⇒ equiv 0 F A C
hproof i
lemma models antimono: C 0⊆C =⇒ models 0 C A ⊆ models 0 C 0 A
hproof i
lemma conflict clause imp no models:
[[ C ∈F ; is conflict clause A C ]] =⇒ models 0 F A = {}
hproof i
lemma sat 0 empty iff [simp]: sat 0 F Map.empty = sat F
hproof i
lemma sat 0 antimono: F ⊆F 0 =⇒ sat 0 F 0 A =⇒ sat 0 F A
hproof i
lemma sat 0 equiv : equiv 0 F A A 0 =⇒ sat 0 F A = sat 0 F A 0
hproof i
10
definition implied clause F A C ≡ models 0 (insert C F ) A = models 0 F A
definition redundant clause F A C
≡ (models 0 (insert C F ) A = {}) ←→ (models 0 F A = {})
lemma redundant
clauseI [intro? ]:
V
assumes σ. [[compat assignment A σ; sem cnf F σ]]
=⇒ ∃ σ 0. compat assignment A σ 0 ∧ sem clause C σ 0 ∧ sem cnf F σ 0
shows redundant clause F A C
hproof i
lemma implied
V clauseI [intro? ]:
assumes σ. [[compat assignment A σ; sem cnf F σ]] =⇒ sem clause C σ
shows implied clause F A C
hproof i
lemma implied is redundant: implied clause F A C =⇒ redundant clause F A C
hproof i
lemma add redundant sat iff [simp]:
redundant clause F A C =⇒ sat 0 (insert C F ) A = sat 0 F A
hproof i
lemma true clause implied :
sem clause 0 C A = Some True =⇒ implied clause F A C
hproof i
lemma equiv 0 map empty sym:
NO MATCH Map.empty A =⇒ equiv 0 F Map.empty A ←→ equiv 0 F A Map.empty
hproof i
lemma tautology: [[l ∈C ; neg lit l ∈ C ]] =⇒ sem clause C σ
hproof i
lemma implied taut: [[l ∈C ; neg lit l ∈ C ]] =⇒ implied clause F A C
hproof i
definition is syn taut C ≡ C ∩ neg lit ‘ C 6= {}
definition is blocked A C ≡ sem clause 0 C A = Some True ∨ is syn taut C
lemma is blocked alt:
is blocked A C ←→ sem clause 0 C A = Some True ∨ C ∩ neg lit ‘ C 6= {}
hproof i
lemma is syn taut empty[simp]: ¬is syn taut {}
hproof i
lemma is syn taut conv : is syn taut C ←→ (∃ l . l ∈C ∧ neg lit l ∈ C )
hproof i
lemma empty not blocked [simp]: ¬is blocked A {}
hproof i
lemma is blocked insert iff :
is blocked A (insert l C )
←→ is blocked A C ∨ sem lit 0 l A = Some True ∨ neg lit l ∈ C
hproof i
lemma is blockedI1 : [[l ∈C ; sem lit 0 l A = Some True]] =⇒ is blocked A C
hproof i
11
lemma is blockedI2 : [[l ∈C ; neg lit l ∈ C ]] =⇒ is blocked A C
hproof i
lemma syn taut true[simp]: is syn taut C =⇒ sem clause C σ = True
hproof i
lemma syn taut imp blocked : is syn taut C =⇒ is blocked A C
hproof i
lemma blocked redundant: is blocked A C =⇒ redundant clause F A C
hproof i
lemma blocked clause true:
[[is blocked A C ; compat assignment A σ]] =⇒ sem clause C σ
hproof i
3.2
Unit Propagation
lemma unit propagation:
assumes C ∈F
assumes UNIT : is unit lit A C l
shows equiv 0 F A (assign lit A l )
hproof i
inductive-set prop unit R :: 0a cnf ⇒ (( 0a*bool ) × ( 0a*bool )) set for F
where
step: [[ C ∈F ; is unit lit A C l ]] =⇒ (A,assign lit A l )∈prop unit R F
lemma prop unit R Domain[simp]:
A ∈ Domain (prop unit R F ) ←→ (∃ C ∈F . is unit clause A C )
hproof i
lemma prop unit R equiv :
assumes (A,A 0)∈(prop unit R F )∗
shows equiv 0 F A A 0
hproof i
lemma wf prop unit R: finite F =⇒ wf ((prop unit R F )−1 )
hproof i
3.3
RUP and RAT Criteria
RAT-criterion to check for a redundant clause: Pick a resolution literal l from the clause, which is not
assigned to false, and then check that all resolvents of the clause are implied clauses.
Note: We include l in the resolvents here, as drat-trim does.
lemma abs rat criterion:
assumes LIC : l ∈C
assumes NFALSE : sem lit 0 l A 6= Some False
assumes CANDS : ∀ D∈F . neg lit l ∈ D
−→ implied clause F A (C ∪ (D − {neg lit l }))
shows redundant clause F A C
hproof i
lemma abs rat criterion 0:
assumes RAT : ∃ l ∈C .
sem lit 0 l A 6= Some False
∧ (∀ D∈F . neg lit l ∈ D −→ implied clause F A (C ∪ (D−{neg lit l })))
shows redundant clause F A C
hproof i
12
Assign all literals of clause to false.
definition and not C A C ≡ λv .
if Pos v ∈ C then Some False else if Neg v ∈ C then Some True else A v
lemma compat and not C :
assumes compat assignment A σ
assumes ¬sem clause C σ
shows compat assignment (and not C A C ) σ
hproof i
lemma and not empty[simp]: and not C A {} = A
hproof i
lemma and not insert None: sem lit 0 l (and not C A C ) = None
=⇒ and not C A (insert l C ) = assign lit (and not C A C ) (neg lit l )
hproof i
lemma and not insert False: sem lit 0 l (and not C A C ) = Some False
=⇒ and not C A (insert l C ) = and not C A C
hproof i
lemma sem lit and not C conv : sem lit 0 l (and not C A C ) = Some v ←→ (
(l ∈C
/ ∧ neg lit l ∈C
/ ∧ sem lit 0 l A = Some v )
∨ (l ∈C ∧ neg lit l ∈C
/ ∧ v =False)
∨ (l ∈C
/ ∧ neg lit l ∈C ∧ v =True)
∨ (l ∈C ∧ neg lit l ∈C ∧ v =(¬is pos l ))
)
hproof i
lemma sem lit and not C None conv : sem lit 0 l (and not C A C ) = None ←→
sem lit 0 l A = None ∧ l ∈C
/ ∧ neg lit l ∈C
/
hproof i
Check for implied clause by RUP: If the clause is not blocked, assign all literals of the clause to false, and
search for an equivalent assignment (usually by unit-propagation), which has a conflict.
lemma one step implied :
assumes RC : ¬is blocked A C =⇒
∃ A1 . equiv 0 F (and not C A C ) A1 ∧ (∃ E ∈F . is conflict clause A1 E )
shows implied clause F A C
hproof i
The unit-propagation steps of (¬ is blocked ?A ?C =⇒ ∃ A1 . equiv 0 ?F (and not C ?A ?C ) A1 ∧ (∃ E ∈?F .
sem clause 0 E A1 = Some False)) =⇒ implied clause ?F ?A ?C can also be distributed over between the
assignments of the negated literals. This is an optimization used for the RAT-check, where an initial set of
unit-propagations can be shared between all candidate checks.
lemma two step implied :
assumes ¬is blocked A C
=⇒ ∃ A1 . equiv 0 F (and not C A C ) A1 ∧ (¬is blocked A1 D
−→ (∃ A2 . equiv 0 F (and not C A1 D) A2 ∧ (∃ E ∈F . is conflict clause A2 E )))
shows implied clause F A (C ∪D)
hproof i
3.4
Old assign all negated Formulation
definition assign all negated A C ≡ let UD = {l ∈C . sem lit 0 l A = None} in
A ++ (λl .
if Pos l ∈UD then Some False
else if Neg l ∈ UD then Some True
else None)
lemma abs rup criterion:
assumes models 0 F (assign all negated A C ) = {}
13
shows implied clause F A C
hproof i
3.4.1
Properties of assign all negated
lemma sem lit assign all negated cases[consumes 1 , case names None Neg Pos]:
assumes sem lit 0 l (assign all negated A C ) = Some v
obtains sem lit 0 l A = Some v
| sem lit 0 l A = None neg lit l ∈ C v =True
| sem lit 0 l A = None l ∈ C v =False
hproof i
lemma sem lit assign all negated none iff :
sem lit 0 l (assign all negated A C ) = None
←→ (sem lit 0 l A = None ∧ l ∈C
/ ∧ neg lit l ∈
/ C)
hproof i
lemma sem lit assign all negated pres decided :
assumes sem lit 0 l A = Some v
shows sem lit 0 l (assign all negated A C ) = Some v
hproof i
lemma sem lit assign all negated assign:
assumes ∀ l ∈C . neg lit l ∈C
/ l ∈ C sem lit 0 l A = None
0
shows sem lit l (assign all negated A C ) = Some False
hproof i
lemma sem lit assign all negated neqv :
sem lit 0 l (assign all negated A C ) 6= Some v =⇒ sem lit 0 l A 6= Some v
hproof i
lemma aan idem[simp]:
assign all negated (assign all negated A C ) C = assign all negated A C
hproof i
lemma aan dbl :
assumes ∀ l ∈C ∪C 0. neg lit l ∈
/ C ∪C 0
shows assign all negated (assign all negated A C ) C 0
= assign all negated A (C ∪C 0)
hproof i
lemma aan mono2 :
[[C ⊆C 0; ∀ l ∈C 0. neg lit l ∈
/ C 0]]
=⇒ assign all negated A C ⊆m assign all negated A C 0
hproof i
lemma aan empty[simp]: assign all negated A {} = A
hproof i
lemma aan restrict:
assign all negated A C |‘ (− var of lit ‘ {l ∈ C . sem lit 0 l A = None}) = A
hproof i
lemma aan insert:
assumes ∀ l 0∈C . sem lit 0 l 0 A 6= Some True ∧ neg lit l 0 ∈
/ C
assumes sem lit 0 l A 6= Some True ∧ neg lit l ∈
/ C
shows assign lit (assign all negated A C ) (neg lit l )
= assign all negated A (insert l C )
hproof i
lemma aan insert set:
assumes sem lit 0 l A 6= None
shows assign all negated A (insert l C ) = assign all negated A C
14
hproof i
end
4
Basic Notions for the GRAT Format
theory Grat Basic
imports
Unit Propagation
DRAT Misc
$AFP /Refine Imperative HOL/Sepref ICF Bindings
Exc Nres Monad
Synth Definition
Dynamic Array
Array Map Default
Parser Iterator New
begin
code-printing
code-printing
code-printing
code-printing
code-printing
constant Array.new 0 * (SML) (fn/ ()/ =>/ Array.array/ (IntInf .toInt ,/ ( )))
constant Array.make 0 * (SML) (fn/ ()/ =>/ Array.tabulate/ (IntInf .toInt ,/ o IntInf .fromInt))
constant Array.len 0 * (SML) (fn/ ()/ =>/ IntInf .fromInt (Array.length/ ))
constant Array.nth 0 * (SML) (fn/ ()/ =>/ Array.sub/ (( ),/ IntInf .toInt ))
constant Array.upd 0 * (SML) (fn/ ()/ =>/ Array.update/ (( ),/ IntInf .toInt ,/ ( )))
code-printing code-module array blit * (SML)
hh
(∗ Locally patched version ∗)
fun array blit src si dst di len = (
src=dst andalso raise Fail (array blit: Same arrays);
ArraySlice.copy {
di = IntInf .toInt di,
src = ArraySlice.slice (src,IntInf .toInt si,SOME (IntInf .toInt len)),
dst = dst})
fun array nth oo v a i () = Array.sub(a,IntInf .toInt i) handle Subscript => v | Overflow => v
fun array upd oo f i x a () =
(Array.update(a,IntInf .toInt i,x ); a) handle Subscript => f () | Overflow => f ()
ii
code-printing constant blit 0 *
)
(SML) (fn/ ()/ => /array 0 blit
and (Scala) { ( 0 : Unit)/=>/
def safecopy(src: Array[ 0 ], srci: Int, dst: Array[ 0 ], dsti: Int, len: Int) = {
if (src eq dst)
sys.error (array 0 blit: Same arrays)
else
System.arraycopy(src, srci, dst, dsti, len)
}
safecopy( .array, .toInt, .array, .toInt, .toInt)
}
15
lemma list set assn finite[simp, intro]:
[[rdomp (list set assn (pure R)) s; single valued R]] =⇒ finite s
hproof i
lemma list set assn IS TO SORTED LIST GA 0[sepref gen algo rules]:
[[CONSTRAINT (IS PURE IS LEFT UNIQUE ) A;
CONSTRAINT (IS PURE IS RIGHT UNIQUE ) A ]]
=⇒ GEN ALGO (return) (IS TO SORTED LIST (λ . True) (list set assn A) A)
hproof i
4.1
Encoding of Literals and Clauses
type-synonym var = nat
abbreviation (input) litZ :: int where litZ ≡ 0
definition lit α :: int ⇒ nat literal
where lit α l ≡ if l <0 then Neg (nat (−l )) else Pos (nat l )
definition lit invar :: int ⇒ bool
where lit invar l ≡ l 6=0
definition clause α l ≡ lit α‘set l
lemma clause α empty[simp]: clause α [] = {}
hproof i
lemma clause α cons[simp]: clause α (x #l ) = insert (lit α x ) (clause α l )
hproof i
lemma clause α conc[simp]: clause α (l1 @l2 ) = clause α l1 ∪ clause α l2
hproof i
definition F α lst ≡ set (map clause α (tokenize litZ lst))
definition F invar lst ≡ lst6=[] −→ last lst = litZ
lemma F α empty[simp]: F α [] = {} hproof i
definition lit γ l ≡ case l of Pos l ⇒ int l | Neg l ⇒ − int l
lemma lit γ α inv [simp]: lit γ (lit α i) = i
hproof i
lemma lit α γ inv [simp]: lit invar (lit γ l ) =⇒ lit α (lit γ l ) = l
hproof i
lemma map lit γ α eq[simp]: 0 ∈set
/
l =⇒ map (lit γ ◦ lit α) l = l
hproof i
lemma
S map map lit γ α eq[simp]:
0 ∈
/ set (map set l ) =⇒ map (map (lit γ ◦ lit α)) l = l
hproof i
lemma lit invar γ iff [simp]: lit invar (lit γ l ) ←→ var of lit l 6= 0
hproof i
lemma var of lit α Z iff [simp]: var of lit (lit α x ) = 0 ←→ x =0
hproof i
4.2
Input Parser
locale input pre =
iterator it invar 0 it next it peek
16
for it invar 0 it next and it peek :: 0it::linorder ⇒ int +
fixes
it end :: 0it
begin
definition it invar it ≡ itran it it end
lemma it invar imp 0[simp, intro]: it invar it =⇒ it invar 0 it
hproof i
lemma it invar imp ran[simp, intro]: it invar it =⇒ itran it it end
hproof i
lemma itran invarD: itran it it end =⇒ it invar it
hproof i
lemma itran invarI : [[itran it it 0; it invar it 0]] =⇒ it invar it
hproof i
end
type-synonym 0it error = String.literal × int option × 0it option
locale input = input pre it invar 0 it next it peek it end
for it invar 0:: 0it::linorder ⇒ and it next it peek it end +
assumes
it end invar [simp, intro!]: it invar it end
begin
definition WF ≡ { (it next it, it) | it. it invar it ∧ it 6= it end }
lemma wf WF [simp, intro!]: wf WF
hproof i
lemmas wf WF trancl [simp, intro!] = wf trancl [OF wf WF ]
lemma it next invar [simp, intro!]:
[[ it invar it; it 6= it end ]] =⇒ it invar (it next it)
hproof i
lemma it next wf [simp, intro]:
[[ it invar it; it 6= it end ]] =⇒ (it next it, it) ∈ WF
hproof i
lemma seg wf [simp, intro]: [[seg it l it 0; it invar it 0]] =⇒ (it 0,it)∈WF ∗
hproof i
lemma lz string wf [simp, intro]:
[[lz string 0 it l ita; it invar ita]] =⇒ (ita, it) ∈ WF +
hproof i
Some abbreviations to conveniently construct error messages.
abbreviation mk err :: ⇒ 0it error
where mk err msg ≡ (STR msg, None, None)
abbreviation mk errN :: ⇒ ⇒ 0it error
where mk errN msg n ≡ (STR msg, Some (int n), None)
abbreviation mk errI :: ⇒ ⇒ 0it error
where mk errI msg i ≡ (STR msg, Some i, None)
abbreviation mk errit :: ⇒ ⇒ 0it error
where mk errit msg it ≡ (STR msg, None, Some it)
abbreviation mk errNit :: ⇒ ⇒ ⇒ 0it error
where mk errNit msg n it ≡ (STR msg, Some (int n), Some it)
abbreviation mk errIit :: ⇒ ⇒ ⇒ 0it error
where mk errIit msg i it ≡ (STR msg, Some i, Some it)
Check that iterator has not reached the end.
17
definition check not end it
≡ CHECK (it 6= it end ) (mk err
00
Parsed beyond end 00)
lemma check not end correct[THEN ESPEC trans, refine vcg]:
it invar it =⇒ check not end it ≤ ESPEC (λ . True) (λ . it 6= it end )
hproof i
Skip one element.
definition skip it ≡ doE {
EASSERT (it invar it);
check not end it;
ERETURN (it next it)
}
Read a literal
definition parse literal it ≡ doE {
EASSERT (it invar it ∧ it 6= it end ∧ it peek it 6= litZ );
ERETURN (lit α (it peek it), it next it)
}
Read an integer
definition parse int it ≡ doE {
EASSERT (it invar it);
check not end it;
ERETURN (it peek it, it next it)
}
Read a natural number
definition parse nat it 0 ≡ doE {
(x ,it) ← parse int it 0 ;
CHECK (x ≥0 ) (mk errIit 00Invalid nat 00 x it 0 );
ERETURN (nat x ,it)
}
lemma parse literal spec[THEN ESPEC trans,refine vcg]:
[[it invar it; it 6= it end ; it peek it 6= litZ ]]
=⇒ parse literal it
≤ ESPEC (λ . True) (λ(l ,it 0). it invar it 0 ∧ (it 0,it)∈WF + )
hproof i
lemma skip spec[THEN ESPEC trans,refine vcg]:
[[it invar it]]
=⇒ skip it ≤ ESPEC (λ . True) (λit 0. it invar it 0 ∧ (it 0,it)∈WF + )
hproof i
lemma parse int spec[THEN ESPEC trans,refine vcg]:
[[it invar it]]
=⇒ parse int it ≤ ESPEC (λ . True) (λ(x ,it 0). it invar it 0 ∧ (it 0,it)∈WF + )
hproof i
lemma parse nat spec[THEN ESPEC trans,refine vcg]:
[[it invar it]]
=⇒ parse nat it ≤ ESPEC (λ . True) (λ(x ,it 0). it invar it 0 ∧ (it 0,it)∈WF + )
hproof i
We inline many of the specifications on breaking down the exception monad
lemmas [enres inline] = check not end def skip def parse literal def
parse int def parse nat def
end
18
4.3
4.3.1
Implementation
Literals
definition lit rel ≡ br lit α lit invar
abbreviation lit assn ≡ pure lit rel
interpretation lit dflt option: dflt option pure lit rel 0 return oo op =
hproof i
applyS sep auto
hproof i
lemma neg lit refine[sepref import param]:
(uminus, neg lit) ∈ lit rel → lit rel
hproof i
lemma lit α refine[sepref import param]:
(λx . x , lit α) ∈ [λx . x 6=0 ]f int rel → lit rel
hproof i
4.3.2
Assignment
definition vv rel ≡ {(1 ::nat, False), (2 , True)}
definition assignment assn ≡ amd assn 0 id assn (pure vv rel )
lemmas [safe constraint rules] = CN FALSEI [of is pure assignment assn]
type-synonym i assignment = (nat,bool ) i map
lemmas [intf of assn]
= intf of assnI [where R=assignment assn and 0a=(nat,bool ) i map]
sepref-decl-op lit is true: λ(l ::nat literal ) A. sem lit 0 l A = Some True
:: (Id ::(nat literal × ) set) → hnat rel ,bool rel imap rel → bool rel hproof i
sepref-decl-op lit is false: λ(l ::nat literal ) A. sem lit 0 l A = Some False
:: (Id ::(nat literal × ) set) → hnat rel ,bool rel imap rel → bool rel hproof i
sepref-decl-op (no def )
assign lit :: ⇒ nat literal ⇒
:: hnat rel ,bool rel imap rel → (Id ::(nat literal × ) set)
→ hnat rel ,bool rel imap rel hproof i
sepref-decl-op
unset lit: λ(A::nat*bool ) l . A(var of lit l := None)
:: hnat rel ,bool rel imap rel → (Id ::(nat literal × ) set)
→ hnat rel ,bool rel imap rel hproof i
lemma [def pat rules]:
op=$(sem lit 0$l $A)$(Some$True) ≡ op lit is true$l $A
op=$(sem lit 0$l $A)$(Some$False) ≡ op lit is false$l $A
hproof i
lemma lit eq impl [sepref import param]:
(op=,op=) ∈ lit rel → lit rel → bool rel
hproof i
lemma var of lit refine[sepref import param]:
(nat o abs,var of lit) ∈ lit rel → nat rel
hproof i
lemma is pos refine[sepref import param]:
19
(λx . x >0 , is pos) ∈ lit rel → bool rel
hproof i
lemma op lit is true alt: op lit is true l A = (let
x = A (var of lit l );
p = is pos l
in
if x = None then False
else (p ∧ the x = True ∨ ¬p ∧ the x = False)
)
hproof i
lemma op lit is false alt: op lit is false l A = (let
x = A (var of lit l );
p = is pos l
in
if x = None then False
else (p ∧ the x = False ∨ ¬p ∧ the x = True)
)
hproof i
definition [simp,code unfold ]: vv eq bool x y ≡ y←→x =2
lemma [sepref opt simps]:
vv eq bool x True ←→ x =2
vv eq bool x False ←→ x 6=2
hproof i
lemma vv bool eq refine[sepref import param]:
(vv eq bool , op =) ∈ vv rel → bool rel → bool rel
hproof i
sepref-definition op lit is true impl is uncurry (RETURN oo op lit is true)
:: (pure lit rel )k ∗a assignment assn k →a bool assn
hproof i
sepref-definition op lit is false impl is uncurry (RETURN oo op lit is false)
:: (pure lit rel )k ∗a assignment assn k →a bool assn
hproof i
definition [simp]: b2vv conv b ≡ b
definition [code unfold ]: b2vv conv impl b ≡ if b then 2 else 1 ::nat
lemma b2vv conv impl refine[sepref import param]:
(b2vv conv impl ,b2vv conv ) ∈ bool rel → vv rel
hproof i
lemma vv unused0 [safe constraint rules]: (is unused elem 0 ) (pure vv rel )
hproof i
sepref-definition assign lit impl
is uncurry (RETURN oo assign lit)
:: assignment assn d ∗a (pure lit rel )k →a assignment assn
hproof i
term op unset lit
sepref-definition unset lit impl
is uncurry (RETURN oo op unset lit)
:: assignment assn d ∗a (pure lit rel )k →a assignment assn
hproof i
20
sepref-definition unset var impl
is uncurry (RETURN oo op map delete)
:: (pure nat rel )k ∗a assignment assn d →a assignment assn
hproof i
sepref-definition assignment empty impl is uncurry0 (RETURN op map empty)
:: unit assn k →a assignment assn
hproof i
lemma assignment assn id map rel fold :
hr comp assignment assn (hnat rel , bool rel imap rel ) = assignment assn
hproof i
context
notes [fcomp norm unfold ] = assignment assn id map rel fold
begin
sepref-decl-impl op lit is true impl .refine hproof i
sepref-decl-impl op lit is false impl .refine hproof i
sepref-decl-impl assign lit impl .refine hproof i
sepref-decl-impl unset lit impl .refine hproof i
sepref-decl-impl unset var impl .refine
uses op map delete.fref [where K =Id and V =Id ] hproof i
sepref-decl-impl (no register ) assignment empty: assignment empty impl .refine
uses op map empty.fref [where K =Id and V =Id ] hproof i
end
definition [simp]: op assignment empty ≡ op map empty
interpretation assignment: map custom empty op assignment empty
hproof i
lemmas [sepref fr rules] = assignment empty hnr [folded op assignment empty def ]
4.3.3
Clause Database
type-synonym clausedb2 = int list
locale DB2 def loc =
fixes DB :: clausedb2
fixes frml end :: nat
begin
lemmas amtx pats[pat rules del ]
sublocale liti: array iterator DB hproof i
lemmas liti.a assn rdompD[dest!]
abbreviation error assn
≡ id assn ×a option assn int assn ×a option assn liti.it assn
end
locale DB2 loc = DB2 def loc +
assumes DB not Nil [simp]: DB 6= []
begin
sublocale input pre liti.I liti.next liti.peek liti.end
hproof i
sublocale input liti.I liti.next liti.peek liti.end
hproof i
end
4.3.4
Clausemap
definition (in −) abs cr register
:: 0a literal ⇒ 0id ⇒ ( 0a literal * 0id list) ⇒ ( 0a literal * 0id list)
21
where abs cr register l cid cr ≡ case cr l of
None ⇒ cr | Some s ⇒ cr (l 7→ mbhd insert cid s)
type-synonym creg = (nat list option) array
term int encode term int decode
term map option
definition is creg :: (nat literal * nat list) ⇒ creg ⇒ assn where
is creg cr a ≡ ∃ A f . is nff None f a
∗ ↑(cr = f o int encode o lit γ)
lemmas [intf of assn]
= intf of assnI [where R=is creg and 0a=(nat literal ,nat list) i map]
definition creg dflt size ≡ 16 ::nat
definition creg empty :: creg Heap
where creg empty ≡ dyn array new sz None creg dflt size
lemma creg empty rule[sep heap rules]: <emp> creg empty <is creg Map.empty>
hproof i
definition [simp]: op creg empty ≡ op map empty :: nat literal * nat list
interpretation creg: map custom empty op creg empty hproof i
lemma creg empty hnr [sepref fr rules]:
(uncurry0 creg empty, uncurry0 (RETURN op creg empty))
∈ unit assn k →a is creg
hproof i
definition creg initialize :: int ⇒ creg ⇒ creg Heap where
creg initialize l cr = do {
cr ← array set dyn None cr (int encode l ) (Some []);
return cr
}
lemma creg initialize rule[sep heap rules]:
[[ (i,l )∈lit rel ]]
=⇒ <is creg cr a> creg initialize i a <λr . is creg (cr (l 7→ [])) r >t
hproof i
definition creg register l cid cr ≡ do {
x ← array get dyn None cr (int encode l );
case x of
None ⇒ return cr
| Some s ⇒ array set dyn None cr (int encode l ) (Some (mbhd insert cid s))
}
lemma creg register rule[sep heap rules]:
[[ (i,l ) ∈ lit rel ]]
=⇒ <is creg cr a>
creg register i cid a
<is creg (abs cr register l cid cr )>t
hproof i
lemma creg register hnr [sepref fr rules]:
(uncurry2 creg register , uncurry2 (RETURN ooo abs cr register ))
∈ (pure lit rel )k ∗a nat assn k ∗a is creg d →a is creg
hproof i
22
definition op creg initialize :: nat literal ⇒ (nat literal * nat list) ⇒
where [simp]: op creg initialize l cr ≡ cr (l 7→ [])
lemma creg initialize hnr [sepref fr rules]:
(uncurry creg initialize, uncurry (RETURN oo op creg initialize))
∈ (pure lit rel )k ∗a is creg d →a is creg
hproof i
sepref-register op creg initialize
:: nat literal ⇒ (nat literal ,nat list) i map
⇒ (nat literal ,nat list) i map
sepref-register abs cr register :: nat literal ⇒ nat ⇒
:: nat literal ⇒ nat ⇒ (nat literal ,nat list) i map
⇒ (nat literal ,nat list) i map
term op map lookup
definition op creg lookup i a ≡ array get dyn None a (int encode i)
lemma creg lookup rule[sep heap rules]:
[[ (i,l ) ∈ lit rel ]]
=⇒ <is creg cr a> op creg lookup i a <λr . is creg cr a ∗ ↑( r = cr l )>
hproof i
lemma creg lookup hnr [sepref fr rules]:
(uncurry op creg lookup, uncurry (RETURN oo op map lookup))
∈ (pure lit rel )k ∗a is creg k →a option assn (list assn id assn)
hproof i
4.3.5
Clause Database
context
fixes DB :: clausedb2
fixes frml end :: nat
begin
definition item next it ≡
let sz = DB !(it−1 ) in
if sz > 0 ∧ nat (sz ) + 1 < it then
Some (it − nat (sz ) − 1 )
else
None
definition at item end it ≡ it ≤ frml end
definition peek int it ≡ DB !it
end
context DB2 def loc
begin
abbreviation cm assn ≡ prod assn (amd assn 0 nat assn liti.it assn) is creg
type-synonym i cm = (nat,nat) i map × (nat literal , nat list) i map
abbreviation state assn ≡ nat assn ×a cm assn ×a assignment assn
type-synonym i state = nat × i cm × i assignment
definition item next impl a it ≡ do {
sz ← Array.nth a (it−1 );
if sz > 0 ∧ nat (sz ) + 1 < it then
return (it − nat (sz ) − 1 )
else
23
return 0
}
lemma item next hnr [sepref fr rules]:
(uncurry item next impl , uncurry (RETURN oo item next))
∈ liti.a assn k ∗a liti.it assn k →a dflt option assn 0 liti.it assn
hproof i
lemma at item end hnr [sepref fr rules]:
(uncurry (return oo at item end ), uncurry (RETURN oo at item end ))
∈ nat assn k ∗a liti.it assn k →a bool assn
hproof i
end
4.4
Common GRAT Stuff
datatype item type =
INVALID
| UNIT PROP
| DELETION
| RUP LEMMA
| RAT LEMMA
| CONFLICT
| RAT COUNTS
type-synonym id = nat
4.4.1
Clause Map
4.4.2
Correctness
We present two different correctness specifications, and show that they are equivalent.
In both cases, the input is specified by a list of integers DB, and an index F end. The formula is contained
in the list from index 1 :: 0a (inclusive) to index F end exclusive. (Index zero is not used for implementation
reasons).
Literals are represented by integers as specified by lit α and lit γ, zero is not a valid literal.
Each clause of the formula is represented by a sequence of non-zero integers, terminated by a zero. The
formula is simply the concatenation of all clause representations.
Both specifications express that F end is in range.
The first specification uses the abstraction function F α, which, in turn, uses tokenize to read the list as list
of zero-terminated lists. It also specifies that the input list is either empty, or ends with a zero.
definition formula unsat spec DB F end ≡ let lst = tl (take F end DB ) in
F end ≤ length DB ∧ F end ≥ 1
∧ (F end > 1 −→ last lst = 0 )
∧ ¬sat (F α lst)
The second specification specifies that the input can be obtained by mapping the literals to integers, and
then concatenating the clauses, appending a zero to each clause. It also specifies that the literals do not
contain a zero variable.
definition formula unsat spec 0 DB F end ≡
∃ lst.
F end ≤ length DB ∧ F end ≥ 1 ∧ 0 ∈
/ var of lit ‘ set (concat lst)
∧ concat sep 0 (map (map lit γ) lst) = tl (take F end DB )
∧ ¬sat (set (map set lst))
We show both specifications to be equivalent
lemma formula unsat spec equiv :
24
formula unsat spec 0 DB F end ←→ formula unsat spec DB F end
hproof i
4.4.3
Alternative Correctness Statement
We also specify a correctness statement that uses only elementary concepts, in order to reduce the dependencies of the correctness statement.
type-synonym assn = int ⇒ bool
definition assn consistent :: assn ⇒ bool
where assn consistent σ = (∀ x . x 6=0 −→ ¬ σ (−x ) = σ x )
definition alt sat F ≡ ∃ σ. assn consistent σ ∧ (∀ C ∈set F . ∃ l ∈set C . σ l )
lemma alt sat Nil [simp]: alt sat []
hproof i
lemma lit α uminus conv [simp]: x 6=0 =⇒ lit α (−x ) = neg lit (lit α x )
hproof i
lemma tl take Suc[simp]: tl (take (Suc 0 ) l ) = [] hproof i
lemma alt sat sat
S eq:
assumes 0 ∈
/ set (map set F )
shows sat (clause α ‘ set F ) ←→ alt sat F
hproof i
lemma formula unsat spec alt:
formula unsat spec DB F end ←→ (let lst = tl (take F end DB ) in
1 < F end ∧ F end ≤ length DB ∧ last lst = 0 ∧ ¬alt sat (tokenize 0 lst))
hproof i
lemma formula unsat spec alt 0: formula unsat spec DB F end ←→ (
let lst = tl (take F end DB ) in
1 < F end ∧ F end ≤ length DB ∧ last lst = 0
∧ (@ σ. assn consistent σ ∧ (∀ C ∈set (tokenize 0 lst). ∃ l ∈set C . σ l )))
hproof i
end
5
Unsat Checker
theory Unsat Check Split
imports Grat Basic
begin
This theory provides a formally verified unsat certificate checker.
The checker accepts an integer array whose prefix contains a cnf formula (encoded as a list of null-terminated
clauses), and the suffix contains a certificate in the GRAT format.
5.1
Abstract level
definition mkp raw err :: ⇒ ⇒ ⇒ (nat× 0prf ) error where
mkp raw err msg I p ≡ (msg, I , p)
locale unsat input = input it invar 0 for it invar 0:: 0it::linorder ⇒
fixes prf next :: 0prf ⇒ int × 0prf
begin
abbreviation mkp err :: ⇒ (nat× 0prf ) error
where mkp err msg ≡ mkp raw err (STR msg) None None
abbreviation mkp errN :: ⇒ ⇒ (nat× 0prf ) error
25
+
where mkp errN msg n ≡ mkp raw err (STR msg) (Some (int n)) None
abbreviation mkp errI :: ⇒ ⇒ (nat× 0prf ) error
where mkp errI msg i ≡ mkp raw err (STR msg) (Some i) None
abbreviation mkp errprf :: ⇒ ⇒ (nat× 0prf ) error
where mkp errprf msg prf ≡ mkp raw err (STR msg) None (Some prf )
abbreviation mkp errNprf :: ⇒ ⇒ ⇒ (nat× 0prf ) error
where mkp errNprf msg n prf ≡ mkp raw err (STR msg) (Some (int n)) (Some prf )
abbreviation mkp errIprf :: ⇒ ⇒ ⇒ (nat× 0prf ) error
where mkp errIprf msg i prf ≡ mkp raw err (STR msg) (Some i) (Some prf )
definition parse prf :: nat × 0prf ⇒ ( ,int × (nat × 0prf )) enres
where parse prf ≡ λ(fuel ,prf ). doE {
CHECK (fuel > 0 ) (mkp errprf 00Out of fuel 00 (fuel ,prf ));
let (x ,prf ) = prf next prf ;
ERETURN (x ,(fuel − 1 ,prf ))
}
definition parse id prf ≡ doE {
(x ,prf ) ← parse prf prf ;
CHECK (x >0 ) (mkp errIprf 00Invalid id 00 x prf );
ERETURN (nat x ,prf )
}
definition parse idZ prf ≡ doE {
(x ,prf ) ← parse prf prf ;
CHECK (x ≥0 ) (mkp errIprf 00Invalid idZ 00 x prf );
ERETURN (nat x ,prf )
}
definition parse type prf ≡ doE {
(v ,prf ) ← parse prf prf ;
if v =1 then ERETURN (UNIT PROP , prf )
else if v =2 then ERETURN (DELETION , prf )
else if v =3 then ERETURN (RUP LEMMA, prf )
else if v =4 then ERETURN (RAT LEMMA, prf )
else if v =5 then ERETURN (CONFLICT , prf )
else if v =6 then ERETURN (RAT COUNTS , prf )
else THROW (mkp errIprf 00Invalid item type 00 v prf )
}
definition parse prf literal prf ≡ doE {
(i,prf ) ← parse prf prf ;
CHECK (i 6= 0 ) (mkp errprf 00Expected literal but found 0 00 prf );
ERETURN (lit α i, prf )
}
definition parse prf literalZ prf ≡ doE {
(i,prf ) ← parse prf prf ;
if (i=0 ) then ERETURN (None,prf )
else ERETURN (Some (lit α i), prf )
}
abbreviation at end it ≡ it = it end
abbreviation at Z it ≡ it peek it = litZ
definition prfWF :: ((nat× 0prf ) × (nat× 0prf )) set
where prfWF ≡ measure fst
lemma wf prfWF [simp, intro!]: wf prfWF hproof i
lemma wf prfWFtrcl [simp, intro!]: wf (prfWF + )
26
hproof i
lemma parse prf spec[THEN ESPEC trans,refine vcg]:
parse prf prf ≤ ESPEC (λ . True) (λ( ,prf 0). (prf 0,prf )∈prfWF + )
hproof i
lemma parse id spec[THEN ESPEC trans,refine vcg]:
parse id prf
≤ ESPEC (λ . True) (λ(x ,prf 0). (prf 0,prf )∈prfWF + ∧ x >0 )
hproof i
lemma parse idZ spec[THEN ESPEC trans,refine vcg]:
parse idZ prf
≤ ESPEC (λ . True) (λ(x ,prf 0). (prf 0,prf )∈prfWF + )
hproof i
lemma parse type spec[THEN ESPEC trans,refine vcg]:
parse type prf
≤ ESPEC (λ . True) (λ(x ,prf 0). (prf 0,prf )∈prfWF + )
hproof i
lemma parse prf literal spec[THEN ESPEC trans,refine vcg]:
parse prf literal prf
≤ ESPEC (λ . True) (λ( ,prf 0). (prf 0,prf )∈prfWF + )
hproof i
lemma parse prf literalZ spec[THEN ESPEC trans,refine vcg]:
parse prf literalZ prf
≤ ESPEC (λ . True) (λ( ,prf 0). (prf 0,prf )∈prfWF + )
hproof i
end
type-synonym clausemap = (id * var clause) × (var literal * id set)
type-synonym state = id × clausemap × (var * bool )
definition cm invar ≡ λ(CM ,RL).
(∀ C ∈ran CM . ¬is syn taut C )
∧ (∀ l s. RL l = Some s −→ s ⊇ {i. ∃ C . CM i = Some C ∧ l ∈C })
definition cm F ≡ λ(CM ,RL). ran CM
definition cm ids ≡ λ(CM , RL). dom CM ∪
S
ran RL
context unsat input begin
definition resolve id :: clausemap ⇒ id ⇒ ( ,var clause) enres
where resolve id ≡ λ(CM ,RL) i. doE {
CHECK (i∈dom CM ) (mkp errN 00Invalid clause id 00 i);
ERETURN (the (CM i))
}
definition remove id :: id ⇒ clausemap ⇒ ( , clausemap) enres
where remove id ≡ λi (CM ,RL). ERETURN (CM (i:=None),RL)
definition remove ids CMRL0 prf ≡ doE {
(i,prf ) ← parse idZ prf ;
(CMRL,i,prf ) ← EWHILEIT
(λ(CMRL,i,it). cm invar CMRL
∧ cm F CMRL ⊆ cm F CMRL0
∧ cm ids CMRL ⊆ cm ids CMRL0 )
(λ( ,i, ). i6=0 )
27
(λ(CMRL,i,prf ). doE {
CMRL ← remove id i CMRL;
(i,prf ) ← parse idZ prf ;
ERETURN (CMRL,i,prf )
}) (CMRL0 ,i,prf );
ERETURN (CMRL,prf )
}
definition add clause
:: id ⇒ var clause ⇒ clausemap ⇒ ( , clausemap) enres
where add clause ≡ λi C (CM ,RL). doE {
EASSERT (¬is syn taut C );
EASSERT (i ∈cm
/
ids (CM ,RL));
let CM = CM (i 7→ C );
let RL = (λl . case RL l of
None ⇒ None
| Some s ⇒ if l ∈C then Some (insert i s) else Some s);
ERETURN (CM ,RL)
}
definition get rat candidates
:: clausemap ⇒ (var * bool ) ⇒ var literal ⇒ ( ,id set) enres
where
get rat candidates ≡ λ(CM ,RL) A l . doE {
let l = neg lit l ;
CHECK (RL l 6= None) (mkp err 00Resolution literal not declared 00);
(∗ Get collected candidates ∗)
let cands raw = the (RL l );
(∗ Filter out deleted , not containing l , and being blocked ∗)
let cands = { i∈cands raw .
∃ C . CM i = Some C
∧ l ∈C ∧ sem clause 0 (C − {l }) A 6= Some True };
ERETURN cands
}
lemma resolve id correct[THEN ESPEC trans,refine vcg]:
resolve id CMRL i
≤ ESPEC (λ . i ∈dom
/
(fst CMRL)) (λC . C ∈ cm F CMRL ∧ fst CMRL i = Some C )
hproof i
lemma remove id correct[THEN ESPEC trans,refine vcg]:
cm invar CMRL
=⇒ remove id i CMRL
≤ ESPEC
(λ . False)
(λCMRL 0. cm invar CMRL 0
∧ cm F CMRL 0 ⊆ cm F CMRL
∧ cm ids CMRL 0 ⊆ cm ids CMRL)
hproof i
lemma rtrancl inv image ss: (inv image R f )∗ ⊆ inv image (R ∗ ) f
hproof i
lemmas rtrancl inv image ssI = rtrancl inv image ss[THEN set mp]
lemma remove ids correct[THEN ESPEC trans,refine vcg]:
[[cm invar CMRL]]
=⇒ remove ids CMRL prf
≤ ESPEC
28
(λ . True)
(λ(CMRL 0,prf 0). cm invar CMRL 0
∧ cm F CMRL 0 ⊆ cm F CMRL
∧ cm ids CMRL 0 ⊆ cm ids CMRL
∧ (prf 0,prf )∈prfWF +
)
hproof i
lemma add clause correct[THEN ESPEC trans,refine vcg]:
[[cm invar CM ; i ∈cm
/
ids CM ; ¬is syn taut C ]] =⇒
add clause i C CM ≤ ESPEC (λ . False) (λCM 0.
cm F CM 0 = insert C (cm F CM )
∧ cm invar CM 0
∧ cm ids CM 0 = insert i (cm ids CM )
)
hproof i
definition rat candidates CM A reslit
≡ {i. ∃ C . CM i = Some C
∧ neg lit reslit ∈ C
∧ ¬is blocked A (C −{neg lit reslit})}
lemma is syn taut mono aux : is syn taut (C −X ) =⇒ is syn taut C
hproof i
lemma get rat candidates correct[THEN ESPEC trans,refine vcg]:
[[ cm invar CM ]]
=⇒ get rat candidates CM A reslit
≤ ESPEC (λ . True) (λr . r =rat candidates (fst CM ) A reslit)
hproof i
definition check unit clause A C
≡ ESPEC (λ . ¬is unit clause A C ) (λl . is unit lit A C l )
definition apply unit i CM A ≡ doE {
C ← resolve id CM i;
l ← check unit clause A C ;
EASSERT (sem lit 0 l A = None);
ERETURN (assign lit A l )
}
definition apply units CM A prf ≡ doE {
(i,prf ) ← parse idZ prf ;
(A,i,prf ) ← EWHILET
(λ(A,i,prf ). i6=0 )
(λ(A,i,prf ). doE {
A ← apply unit i CM A;
(i,prf ) ← parse idZ prf ;
ERETURN (A,i,prf )
}) (A,i,prf );
ERETURN (A,prf )
}
lemma apply unit correct[THEN ESPEC trans, refine vcg]:
apply unit i CM A ≤ ESPEC (λ . True) (λA 0. equiv 0 (cm F CM ) A A 0)
hproof i
lemma apply units correct[THEN ESPEC trans, refine vcg]:
apply units CM A prf
29
≤ ESPEC
(λ . True)
(λ(A 0,prf 0). equiv 0 (cm F CM ) A A 0 ∧ (prf 0,prf )∈prfWF + )
hproof i
Parse a clause and check that it is not blocked.
definition parse check blocked A it ≡ doE {EASSERT (it invar it); ESPEC
(λ . True)
(λ(C ,A 0,it 0). (∃ l .
lz string litZ it l it 0
∧ it invar it 0
∧ C =clause α l
∧ ¬is blocked A C
∧ A 0 = and not C A C ))}
definition parse skip listZ :: (nat× 0prf ) ⇒ ( ,nat× 0prf ) enres where
parse skip listZ prf ≡ doE {
(x ,prf ) ← parse prf prf ;
( ,prf ) ← EWHILET (λ(x ,prf ). x 6=0 ) (λ(x ,prf ). parse prf prf ) (x ,prf );
ERETURN prf
}
lemma parse skip listZ correct[THEN ESPEC trans, refine vcg]:
shows parse skip listZ prf
≤ ESPEC (λ . True) (λprf 0. (prf 0,prf )∈prfWF + )
hproof i
Too keep proofs more readable, we extract the logic used to check that a RAT-proof provides an exhaustive
list of the expected candidates.
definition check candidates candidates prf check ≡ doE {
(cand ,prf ) ← parse idZ prf ;
(candidates,cand ,prf ) ← EWHILET
(λ( ,cand , ). cand 6=0 )
(λ(candidates,cand ,prf ). doE {
if cand ∈ candidates then doE {
let candidates = candidates − {cand };
prf ← check cand prf ;
(cand ,prf ) ← parse idZ prf ;
ERETURN (candidates,cand ,prf )
} else doE {
prf ← parse skip listZ prf ; (∗ Skip over unit propagation ∗)
( ,prf ) ← parse prf prf ; (∗ Skip over conflict clause ∗)
(cand ,prf ) ← parse idZ prf ;
ERETURN (candidates,cand ,prf )
}
}) (candidates,cand ,prf );
CHECK (candidates = {}) (mkp errprf
ERETURN prf
00
Too few RAT −candidates in proof
}
lemma check candidates rule[THEN
ESPEC trans, zero var indexes]:
V
assumes check correct: cand prf .
[[ cand ∈candidates ]]
=⇒ check cand prf
≤ ESPEC (λ . True) (λprf 0. Φ cand ∧ (prf 0,prf )∈prfWF + )
shows check candidates candidates prf check
≤ ESPEC
(λ . True)
(λprf 0. (∀ cand ∈candidates. Φ cand ) ∧ (prf 0,prf )∈prfWF + )
hproof i
30
00
prf );
definition check rup proof :: state ⇒ 0it ⇒ (nat× 0prf ) ⇒ ( , state × 0it × (nat× 0prf )) enres where
check rup proof ≡ λ(last id ,CM ,A0 ) it prf . doE {
(i,prf ) ← parse id prf ;
CHECK (i>last id ) (mkp errNprf 00Ids must be strictly increasing 00 i prf );
(C ,A 0,it) ← parse check blocked A0 it;
(A 0,prf ) ← apply units CM A 0 prf ;
(confl id ,prf ) ← parse id prf ;
confl ← resolve id CM confl id ;
CHECK (is conflict clause A 0 confl )
(mkp errNprf 00Expected conflict clause 00 confl id prf );
EASSERT (redundant clause (cm F CM ) A0 C );
EASSERT (i ∈
/ cm ids CM );
CM ← add clause i C CM ;
ERETURN ((i,CM ,A0 ),it,prf )
}
lemma check rup proof correct[THEN ESPEC trans, refine vcg]:
assumes [simp]: s=(last id ,CM ,A)
assumes cm invar CM
assumes ∀ i∈cm ids CM . i≤last id
assumes it invar it
shows
check rup proof s it prf ≤ ESPEC (λ . True) (λ((last id 0,CM 0,A 0),it 0,prf 0).
cm invar CM 0
∧ (∀ i∈cm ids CM 0. i≤last id 0)
∧ (sat 0 (cm F CM ) A −→ sat 0 (cm F CM 0) A 0)
∧ (it invar it 0) ∧ (prf 0,prf )∈prfWF +
)
hproof i
definition check rat proof :: state ⇒ 0it ⇒ (nat × 0prf ) ⇒ ( , state × 0it × (nat × 0prf )) enres where
check rat proof ≡ λ(last id ,CM ,A0 ) it prf . doE {
(reslit,prf ) ← parse prf literal prf ;
CHECK (sem lit 0 reslit A0 6= Some False)
(mkp errprf 00Resolution literal is false 00 prf );
(i,prf ) ← parse id prf ;
CHECK (i>last id ) (mkp errNprf 00Ids must be strictly increasing 00 i prf );
(∗(C ,it) ← lift parser parse clause it;∗)
(C ,A 0,it) ← parse check blocked A0 it;
CHECK (reslit ∈ C ) (mkp errprf 00Resolution literal not in clause 00 prf );
(A 0,prf ) ← apply units CM A 0 prf ;
candidates ← get rat candidates CM A 0 reslit;
prf ← check candidates candidates prf (λcand id prf . doE {
cand ← resolve id CM cand id ;
EASSERT (¬is blocked A 0 (cand −{neg lit reslit}));
let A 00 = and not C A 0 (cand −{neg lit reslit});
(A 00,prf ) ← apply units CM A 00 prf ;
(confl id ,prf ) ← parse id prf ;
confl ← resolve id CM confl id ;
CHECK (is conflict clause A 00 confl )
(mkp errprf 00Expected conflict clause 00 prf );
EASSERT (implied clause (cm F CM ) A0 (C ∪ (cand −{neg lit reslit})));
ERETURN prf
});
EASSERT (redundant clause (cm F CM ) A0 C );
EASSERT (i ∈
/ cm ids CM );
31
CM ← add clause i C CM ;
ERETURN ((i,CM ,A0 ),it,prf )
}
lemma rat criterion:
assumes LIC : reslit∈C
assumes NFALSE : sem lit 0 reslit A 6= Some False
assumes EQ1 : equiv 0 (cm F (CM , RL)) (and not C A C ) A 0
assumes CANDS : ∀ cand ∈rat candidates CM A 0 reslit.
implied clause
(cm F (CM ,RL))
A
(C ∪ ((the (CM cand )) − {neg lit reslit}))
shows redundant clause (cm F (CM ,RL)) A C
hproof i
lemma check rat proof correct[THEN ESPEC trans, refine vcg]:
assumes [simp]: s=(last id ,CM ,A)
assumes cm invar CM
assumes ∀ i∈cm ids CM . i≤last id
assumes it invar it
shows
check rat proof s it prf ≤ ESPEC (λ . True) (λ((last id 0,CM 0,A 0),it 0,prf 0).
cm invar CM 0
∧ (∀ i∈cm ids CM 0. i≤last id 0)
∧ (sat 0 (cm F CM ) A −→ sat 0 (cm F CM 0) A 0)
∧ it invar it 0 ∧ (prf 0,prf )∈prfWF +
)
hproof i
applyS (auto simp: rat candidates def )
hproof i
applyS auto []
hproof i
applyS (rule CMI )
hproof i
definition check item :: state ⇒ 0it ⇒ (nat × 0prf ) ⇒ ( , (state × 0it × (nat × 0prf )) option) enres
where check item ≡ λ(last id ,CM ,A) it prf . doE {
(ty,prf ) ← parse type prf ;
case ty of
INVALID ⇒ THROW (mkp err 00Invalid item 00)
| UNIT PROP ⇒ doE {
(A,prf ) ← apply units CM A prf ;
ERETURN (Some ((last id ,CM ,A),it,prf ))
}
| DELETION ⇒ doE {
(CM ,prf ) ← remove ids CM prf ;
ERETURN (Some ((last id ,CM ,A),it,prf ))
}
| RUP LEMMA ⇒ doE {
s ← check rup proof (last id ,CM ,A) it prf ;
ERETURN (Some s)
}
| RAT LEMMA ⇒ doE {
s ← check rat proof (last id ,CM ,A) it prf ;
ERETURN (Some s)
}
| CONFLICT ⇒ doE {
(i,prf ) ← parse id prf ;
32
C ← resolve id CM i;
CHECK (is conflict clause A C )
(mkp errNprf 00Conflict clause has no conflict 00 i prf );
ERETURN None
}
| RAT COUNTS ⇒
THROW (mkp errprf
00
Not expecting rat−counts in the middle of proof
00
prf )
}
lemma check item correct pre:
assumes [simp]: s = (last id ,CM ,A)
assumes cm invar CM
assumes ∀ i∈cm ids CM . i≤last id
assumes [simp]: it invar it
shows check item s it prf ≤ ESPEC (λ . True) (λ
Some ((last id 0,CM 0,A 0),it 0,prf 0) ⇒
cm invar CM 0
∧ (∀ i∈cm ids CM 0. i≤last id 0)
∧ (sat 0 (cm F CM ) A −→ sat 0 (cm F CM 0) A 0)
∧ it invar it 0 ∧ (prf 0,prf )∈prfWF +
| None ⇒ ¬sat 0 (cm F CM ) A
)
hproof i
applyS (refine vcg; auto)
applyS (refine vcg; auto simp: sat 0 equiv )
applyS (refine vcg; auto simp: sat 0 antimono)
applyS (refine vcg; auto)
applyS (refine vcg; auto)
applyS (refine vcg; auto simp: conflict clause imp no models sat 0 def )
applyS (refine vcg; auto)
hproof i
lemma check item correct[THEN ESPEC trans, refine vcg]:
assumes case s of (last id ,CM ,A) ⇒ cm invar CM ∧ (∀ i∈cm ids CM . i≤last id )
assumes it invar it
shows check item s it prf ≤ ESPEC (λ . True) (case s of (last id ,CM ,A) ⇒ (λ
Some ((last id 0,CM 0,A 0),it 0,prf 0) ⇒
cm invar CM 0
∧ (∀ i∈cm ids CM 0. i≤last id 0)
∧ (sat 0 (cm F CM ) A −→ sat 0 (cm F CM 0) A 0)
∧ it invar it 0 ∧ (prf 0,prf )∈prfWF +
| None ⇒ ¬sat 0 (cm F CM ) A)
)
hproof i
definition cm empty :: clausemap where cm empty ≡ (Map.empty, Map.empty)
lemma cm empty invar [simp]: cm invar cm empty
hproof i
lemma cm F empty[simp]: cm F cm empty = {}
hproof i
lemma cm ids empty[simp]: cm ids cm empty = {}
hproof i
lemma cm ids empty imp F empty: cm ids CM = {} =⇒ cm F CM = {}
hproof i
definition read cnf
:: var clause list ⇒ clausemap ⇒ ( , clausemap × nat) enres
where read cnf L CM ≡ doE {
(CM , next id ) ← enfoldli L (λ . True) (λC (CM ,i). doE {
33
if (is syn taut C ) then
ERETURN (CM ,i+1 )
else doE {
CM ← add clause i C CM ;
ERETURN (CM ,i+1 )
}
}) (CM ,1 );
ERETURN (CM , next id − 1 )
}
lemma read cnf correct[THEN ESPEC trans, refine vcg]:
[[ cm invar CM ; cm ids CM = {} ]]
=⇒ read cnf F CM
≤ ESPEC
(λ . True)
(λ(CM ,last id ). cm invar CM
∧ sat (cm F CM ) = sat (set F )
∧ (∀ i∈cm ids CM . i≤last id ))
hproof i
definition read clause check taut itE it A ≡ doE {
EASSERT (A = Map.empty);
EASSERT (it invar it ∧ it invar itE ∧ itran itE it end );
(it 0,(t,A)) ← parse lz
(mkp err 00Parsed beyond end 00)
litZ itE it (λ . True) (λx (t,A). doE {
let l = lit α x ;
if (sem lit 0 l A = Some False) then ERETURN (True,A)
else ERETURN (t,assign lit A l )
}) (False,A);
A ← iterate lz litZ itE it (λ . True) (λx A. doE {
let A = A(var of lit (lit α x ) := None);
ERETURN A
}) A;
ERETURN (it 0,(t,A))
}
lemma clause assignment syn taut aux :
[[∀ l . (sem lit 0 l A = Some True) = (l ∈ C ); is syn taut C ]] =⇒ False
hproof i
lemma read clause check taut correct[THEN ESPEC trans,refine vcg]:
[[itran it itE ; it invar itE ; A = Map.empty]] =⇒
read clause check taut itE it A
≤ ESPEC
(λ . True)
(λ(it 0,(t,A)). A = Map.empty
∧ (∃ l . lz string litZ it l it 0
∧ itran it 0 itE
∧ (t = is syn taut (clause α l ))))
hproof i
applyS auto
applyS (auto simp: is syn taut def )
applyS (auto simp: assign lit def split: if splits)
applyS (auto simp: is syn taut def )
applyS (force simp: sem lit 0 assign conv split: if splits)
applyS (auto)
applyS (auto simp: itran ord )
applyS (auto)
34
applyS (auto)
applyS (auto dest: clause assignment syn taut aux )
hproof i
definition read cnf new
:: 0it ⇒ 0it ⇒ clausemap ⇒ ( , clausemap × nat) enres
where read cnf new itE it CM ≡ doE {
(CM ,next id ,A) ← tok fold itE it (λit (CM ,next id ,A). doE {
(it 0,(t,A)) ← read clause check taut itE it A;
if t then ERETURN (it 0, (CM ,next id +1 ,A))
else doE {
EASSERT (∃ l it 0. lz string litZ it l it 0 ∧ it invar it 0);
let C = clause α (the lz string litZ it);
CM ← add clause next id C CM ;
ERETURN (it 0,(CM ,next id +1 ,A))
}
}) (CM ,1 ,Map.empty);
ERETURN (CM , next id − 1 )
}
lemma read cnf new correct[THEN ESPEC trans, refine vcg]:
[[seg it lst itE ; cm invar CM ; cm ids CM = {}; it invar itE ]]
=⇒ read cnf new itE it CM
≤ ESPEC (λ . True) (λ(CM ,next id ).
(lst 6= [] −→ last lst = litZ )
∧ cm invar CM
∧ (∀ i∈cm ids CM . i≤next id )
∧ sat (cm F CM ) = sat (set (map clause α (tokenize litZ lst)))
)
hproof i
definition cm init lit
:: var literal ⇒ clausemap ⇒ ( ,clausemap) enres
where cm init lit ≡ λl (CM ,RL). ERETURN (CM ,RL(l 7→ {}))
lemma cm init lit correct[THEN ESPEC trans, refine vcg]:
[[ cm invar CMRL; cm ids CMRL = {} ]] =⇒
cm init lit l CMRL
≤ ESPEC (λ . False) (λCMRL 0. cm invar CMRL 0 ∧ cm ids CMRL 0 = {})
hproof i
definition init rat counts prf ≡ doE {
(ty,prf ) ← parse type prf ;
CHECK (ty = RAT COUNTS ) (mkp errprf
00
Expected RAT counts item 00 prf );
(l ,prf ) ← parse prf literalZ prf ;
(CM , ,prf ) ← EWHILET (λ(CM ,l ,prf ). l 6=None) (λ(CM ,l ,prf ). doE {
EASSERT (l 6=None);
let l = the l ;
( ,prf ) ← parse prf prf ; (∗ Just ignoring count, silently assuming it to be >0 . TODO: Add count−down and
stop optimization? ∗)
let l = neg lit l ;
CM ← cm init lit l CM ;
(l ,prf ) ← parse prf literalZ prf ;
ERETURN (CM ,l ,prf )
}) (cm empty,l ,prf );
ERETURN (CM ,prf )
}
lemma init rat counts correct[THEN ESPEC trans, refine vcg]:
35
init rat counts prf
≤ ESPEC (λ . True) (λ(CM ,prf 0). cm invar CM ∧ cm ids CM = {} ∧ (prf 0,prf )∈prfWF + )
hproof i
definition verify unsat F begin F end it prf ≡ doE {
let A=Map.empty;
EASSERT (it invar it);
(CM ,prf ) ← init rat counts prf ;
(CM ,last id ) ← read cnf new F end F begin CM ;
let s = (last id ,CM ,A);
s ← EWHILEIT
(λSome ( ,it, ) ⇒ it invar it | None ⇒ True)
(λs. s6=None)
(λs. doE {
EASSERT (s6=None);
let (s,it,prf ) = the s;
EASSERT (it invar it);
check item s it prf
}) (Some (s,it,prf ));
CHECK (is None s) (mkp err
00
Proof did not contain conflict declaration 00)
}
lemma verify unsat correct:
[[seg F begin lst F end ; it invar F end ; it invar it]] =⇒
verify unsat F begin F end it prf
≤ ESPEC (λ . True) (λ . F invar lst ∧ ¬sat (F α lst))
hproof i
applyS (auto)
applyS (auto simp: F α def F invar def )
applyS (clarsimp split: option.splits; auto)
applyS (auto split!: option.split asm)
applyS (auto simp: F α def F invar def )
applyS (auto split: option.split asm)
applyS (auto split: option.split asm)
hproof i
end — proof parser
5.2
Refinement — Backtracking
type-synonym bt assignment = (var * bool ) × var set
definition backtrack A T ≡ A|‘ (−T )
lemma backtrack empty[simp]: backtrack A {} = A
hproof i
definition is backtrack A 0 T 0 A ≡ T 0⊆dom A 0 ∧ A = backtrack A 0 T 0
lemma is backtrack empty[simp]: is backtrack A {} A
hproof i
lemma is backtrack not undec:
[[ is backtrack A 0 T 0 A; var of lit l ∈T 0 ]] =⇒ sem lit 0 l A 0 6= None
hproof i
lemma is backtrack assignI :
36
[[is backtrack A 0 T 0 A; sem lit 0 l A 0 = None; x = var of lit l ]]
=⇒ is backtrack (assign lit A 0 l ) (insert x T 0) A
hproof i
context unsat input begin
definition assign lit bt ≡ λA T l . doE {
EASSERT (sem lit 0 l A = None ∧ var of lit l ∈
/ T );
ERETURN (assign lit A l , insert (var of lit l ) T )
}
definition apply unit bt i CM A T ≡ doE {
C ← resolve id CM i;
l ← check unit clause A C ;
assign lit bt A T l
}
definition apply units bt CM A T prf ≡ doE {
(i,prf ) ← parse idZ prf ;
((A,T ),i,prf ) ← EWHILET
(λ((A,T ),i,prf ). i6=0 )
(λ((A,T ),i,prf ). doE {
(A,T ) ← apply unit bt i CM A T ;
(i,prf ) ← parse idZ prf ;
ERETURN ((A,T ),i,prf )
}) ((A,T ),i,prf );
ERETURN ((A,T ),prf )
}
definition parse check blocked bt A it ≡ doE {EASSERT (it invar it); ESPEC
(λ . True (∗λe. parse clause it = Inl e∗))
(λ(C ,(A 0,T 0),it 0). ∃ l .
lz string litZ it l it 0
∧ it invar it 0
∧ C =clause α l
∧ ¬is blocked A C
∧ A 0 = and not C A C
∧ T 0 = { v . v ∈var of lit‘C ∧ A v = None })}
definition and not C bt A C ≡ doE {
EASSERT (¬is blocked A C );
ERETURN (and not C A C , { v . v ∈var of lit‘C ∧ A v = None })
}
definition check candidates 0 candidates A prf check ≡ doE {
(cand ,prf ) ← parse idZ prf ;
(candidates,A,cand ,prf ) ← EWHILET
(λ( , ,cand , ). cand 6=0 )
(λ(candidates,A,cand ,prf ). doE {
if cand ∈ candidates then doE {
let candidates = candidates − {cand };
(A,prf ) ← check cand A prf ;
(cand ,prf ) ← parse idZ prf ;
ERETURN (candidates,A,cand ,prf )
} else doE {
prf ← parse skip listZ prf ;
( ,prf ) ← parse prf prf ;
(cand ,prf ) ← parse idZ prf ;
ERETURN (candidates,A,cand ,prf )
}
}) (candidates,A,cand ,prf );
37
CHECK (candidates = {}) (mkp errprf
ERETURN (A,prf )
00
Too few RAT −candidates in proof
00
prf );
}
lemma check candidates 0 refine ca[refine]:
assumes [simplified
V,simp]: (candidatesi,candidates)∈Id (prfi ,prf )∈Id
assumes [refine]: candi prfi cand prf A 0.
[[(candi,cand )∈Id ; (prfi ,prf )∈Id ; (A 0,A)∈Id ]]
=⇒ check 0 candi A 0 prfi
≤⇓E UNIV ({((A,prf ),prf ) | prf . True })
(check cand prf )
shows check candidates 0 candidatesi A prfi check 0
≤⇓E UNIV {((A,prf ),prf ) | prf . True }
(check candidates candidates prf check )
hproof i
lemma check candidates 0 refine[refine]:
assumes [simplified ,simp]:
(candidatesi,candidates)∈Id (prfi ,prf )∈Id (Ai,A)∈Id
assumes ERID: Id ⊆ ER
assumes
[refine]:
V
candi prfi cand prf A 0 A. [[(candi,cand )∈Id ; (prfi ,prf )∈Id ; (A 0,A)∈Id ]]
=⇒ check 0 candi A 0 prfi ≤⇓E ER (Id ×r Id ) (check cand A prf )
shows check candidates 0 candidatesi Ai prfi check 0
≤⇓E ER (Id ×r Id ) (check candidates 0 candidates A prf check )
hproof i
definition check rup proof bt :: state ⇒ 0it ⇒ (nat× 0prf ) ⇒ ( , state × 0it × (nat× 0prf )) enres where
check rup proof bt ≡ λ(last id ,CM ,A) it prf . doE {
(i,prf ) ← parse id prf ;
CHECK (i>last id ) (mkp errNprf 00Ids must be strictly increasing 00 i prf );
(C ,(A,T ),it) ← parse check blocked bt A it;
((A,T ),prf ) ← apply units bt CM A T prf ;
(confl id ,prf ) ← parse id prf ;
confl ← resolve id CM confl id ;
CHECK (is conflict clause A confl )
(mkp errNprf 00Expected conflict clause 00 confl id prf );
EASSERT (i ∈
/ cm ids CM );
CM ← add clause i C CM ;
ERETURN ((i,CM ,backtrack A T ),it,prf )
}
definition check rat proof bt :: state ⇒ 0it ⇒ (nat × 0prf ) ⇒ ( ,state × 0it × (nat × 0prf )) enres where
check rat proof bt ≡ λ(last id ,CM ,A) it prf . doE {
(reslit,prf ) ← parse prf literal prf ;
CHECK (sem lit 0 reslit A 6= Some False)
(mkp errprf 00Resolution literal is false 00 prf );
(i,prf ) ← parse id prf ;
CHECK (i>last id ) (mkp errNprf 00Ids must be strictly increasing 00 i prf );
(C ,(A,T ),it) ← parse check blocked bt A it;
CHECK (reslit ∈ C ) (mkp errprf 00Resolution literal not in clause 00 prf );
((A,T ),prf ) ← apply units bt CM A T prf ;
candidates ← get rat candidates CM A reslit;
(A,prf ) ← check candidates 0 candidates A prf (λcand id A prf . doE {
cand ← resolve id CM cand id ;
(A,T2 ) ← and not C bt A (cand −{neg lit reslit});
((A,T2 ),prf ) ← apply units bt CM A T2 prf ;
(confl id ,prf ) ← parse id prf ;
confl ← resolve id CM confl id ;
38
CHECK (is conflict clause A confl )
(mkp errprf 00Expected conflict clause 00 prf );
ERETURN (backtrack A T2 ,prf )
});
EASSERT (i ∈
/ cm ids CM );
CM ← add clause i C CM ;
ERETURN ((i,CM ,backtrack A T ),it,prf )
}
definition bt assign rel A
≡ { ((A 0,T ),A 0) | A 0 T . T ⊆ dom A 0 ∧ A = A 0|‘ (−T ) }
definition bt need bt rel A0
≡ br (λ . A0 ) (λ(A 0,T 0). T 0⊆dom A 0 ∧ backtrack A 0 T 0 = A0 )
lemma bt rel simps:
((Ai,T ),A)∈bt assign rel A0 =⇒ Ai=A ∧ backtrack A T = A0 ∧ T ⊆dom A
((Ai,T ),A)∈bt need bt rel A0 =⇒ A=A0 ∧ backtrack Ai T = A0 ∧ T ⊆dom Ai
hproof i
lemma bt in bta rel : T ⊆ dom A =⇒ ((A,T ),A)∈bt assign rel (backtrack A T )
hproof i
lemma and not C bt refine[refine]: [[ ¬is blocked A C ; (Ai,A)∈Id ; (Ci,C )∈Id ]]
=⇒ and not C bt Ai Ci ≤⇓E UNIV (bt assign rel A) (ERETURN (and not C A C ))
hproof i
lemma parse check blocked bt refine[refine]: [[ (Ai,A)∈Id ; (iti,it)∈Id ]]
=⇒ parse check blocked bt Ai iti
≤ ⇓E UNIV (Id ×r bt assign rel A ×r Id ) (parse check blocked A it)
hproof i
lemma assign lit bt refine[refine]:
[[ sem lit 0 l A = None; ((Ai,Ti),A)∈bt assign rel A0 ; (li,l )∈Id ]]
=⇒ assign lit bt Ai Ti li
≤⇓E UNIV (bt assign rel A0 ) (ERETURN (assign lit A l ))
hproof i
applyS simp
hproof i
lemma apply unit bt refine[refine]:
[[ (ii,i)∈Id ; (CMi,CM )∈Id ; ((Ai,Ti),A)∈bt assign rel A0 ]]
=⇒ apply unit bt ii CMi Ai Ti
≤⇓E UNIV (bt assign rel A0 ) (apply unit i CM A)
hproof i
lemma apply units bt refine[refine]:
[[ (CMi,CM )∈Id ; ((Ai,Ti),A)∈bt assign rel A0 ; (iti,it)∈Id ]]
=⇒ apply units bt CMi Ai Ti iti
≤⇓E UNIV (bt assign rel A0 ×r Id ) (apply units CM A it)
hproof i
term check rup proof
lemma check rup proof bt refine[refine]:
[[ (si,s)∈Id ; (iti,it)∈Id ; (prfi ,prf )∈Id ]]
=⇒ check rup proof bt si iti prfi ≤⇓E UNIV Id (check rup proof s it prf )
hproof i
lemma check rat proof bt refine[refine]:
[[ (si,s)∈Id ; (iti,it)∈Id ; (prfi ,prf )∈Id ]]
39
=⇒ check rat proof bt si iti prfi ≤⇓E UNIV Id (check rat proof s it prf )
hproof i
definition check item bt :: state ⇒ 0it ⇒ (nat × 0prf ) ⇒ ( , (state × 0it × (nat × 0prf )) option) enres
where check item bt ≡ λ(last id ,CM ,A) it prf . doE {
(ty,prf ) ← parse type prf ;
case ty of
INVALID ⇒ THROW (mkp err 00Invalid item 00)
| UNIT PROP ⇒ doE {
(A,prf ) ← apply units CM A prf ;
ERETURN (Some ((last id ,CM ,A),it,prf ))
}
| DELETION ⇒ doE {
(CM ,prf ) ← remove ids CM prf ;
ERETURN (Some ((last id ,CM ,A),it,prf ))
}
| RUP LEMMA ⇒ doE {
s ← check rup proof bt (last id ,CM ,A) it prf ;
ERETURN (Some s)
}
| RAT LEMMA ⇒ doE {
s ← check rat proof bt (last id ,CM ,A) it prf ;
ERETURN (Some s)
}
| CONFLICT ⇒ doE {
(i,prf ) ← parse id prf ;
C ← resolve id CM i;
CHECK (is conflict clause A C )
(mkp errNprf 00Conflict clause has no conflict 00 i prf );
ERETURN None
}
| RAT COUNTS ⇒
THROW (mkp errprf 00Not expecting rat−counts in the middle of proof 00 prf )
}
lemma check item bt refine[refine]: [[(si,s)∈Id ; (iti,it)∈Id ; (prfi ,prf )∈Id ]]
=⇒ check item bt si iti prfi ≤⇓E UNIV Id (check item s it prf )
hproof i
applyS simp
hproof i
definition verify unsat bt F begin F end it prf ≡ doE {
let A=Map.empty;
EASSERT (it invar it);
(CM ,prf ) ← init rat counts prf ;
(CM ,last id ) ← read cnf new F end F begin CM ;
let s = (last id ,CM ,A);
s ← EWHILEIT
(λSome ( ,it, ) ⇒ it invar it | None ⇒ True)
(λs. s6=None)
(λs.
doE {
EASSERT (s6=None);
let (s,it,prf ) = the s;
EASSERT (it invar it);
40
check item bt s it prf
}) (Some (s,it,prf ));
CHECK (is None s) (mkp err
00
Proof did not contain conflict declaration 00)
}
lemma verify unsat bt refine[refine]:
[[ (F begini,F begin)∈Id ; (F endi,F end )∈Id ; (iti,it)∈Id ; (prfi ,prf )∈Id ]]
=⇒ verify unsat bt F begini F endi iti prfi
≤⇓E UNIV Id (verify unsat F begin F end it prf )
hproof i
end — proof parser
5.3
Refinement 1
Model clauses by iterators to their starting position
type-synonym ( 0it) clausemap1 = (id * 0it) × (var literal * id list)
type-synonym ( 0it) state1 = id × ( 0it) clausemap1 × (var * bool )
context unsat input begin
definition cref rel
≡ { (cref ,C ). ∃ l it 0. lz string litZ cref l it 0
∧ it invar it 0
∧ C = clause α l }
definition next it rel
≡ { (cref ,it 0). ∃ l . lz string litZ cref l it 0 ∧ it invar it 0}
definition clausemap1 rel
≡ (Id → hcref rel ioption rel ) ×r (Id → hbr set distinctioption rel )
abbreviation state1 rel ≡ Id ×r clausemap1 rel ×r Id
definition parse check clause cref c f s ≡ doE {
(it,s) ← parse lz (mkp err 00Parsed beyond end 00) litZ it end cref c (λx s. doE {
EASSERT (x 6= litZ );
let l = lit α x ;
fls
}) s;
ERETURN (s,it)
}
lemma parse check clause rule aux :
assumes I [simp]: I {} s
assumes
F RL:
V
C l s. [[I C s; c s]] =⇒ f l s ≤ ESPEC (λ . True) (I (insert l C ))
assumes [simp]: it invar cref
shows parse check clause cref c f s ≤ ESPEC
((∗ TODO: Spec that parsing failed ∗) λ . True)
(λ(s,it 0). ∃ C .
ICs
∧ (c s −→ it invar it 0
∧ (cref ,C ) ∈ cref rel
∧ (cref ,it 0) ∈ next it rel )
)
hproof i
lemma parse check clause rule:
assumes I0 : I {} s
assumes [simp]: it invar cref
assumes
F RL:
V
C l s. [[I
V C s; c s]] =⇒ f l s ≤ ESPEC (λ . True) (I (insert l C ))
assumes C s it 0. [[I C s; ¬c s ]] =⇒ Q (s,it 0)
41
V
assumes C s it 0.
[[ I C s; c s; (cref ,it 0)∈next it rel ; (cref ,C )∈cref rel ]] =⇒ Q (s,it 0)
shows parse check clause cref c f s ≤ ESPEC (λ . True) Q
hproof i
definition iterate clause cref c f s ≡
iterate lz litZ it end cref c (λx s. f (lit α x ) s) s
lemma iterate clause rule:
assumes CR: (cref ,C )∈cref rel
assumes I0 : I {}
Vs
assumes F RL: C1 l s.
[[ I C1 s; C1 ⊆C ;Vl ∈C ; c s ]] =⇒ f l s ≤ ESPEC E (I (insert l C1 ))
assumes T IMP : Vs. [[ c s; I C s ]] =⇒ P s
assumes C IMP : s C1 . [[ ¬c s; C1 ⊆C ; I C1 s ]] =⇒ P s
shows iterate clause cref c f s ≤ ESPEC E P
hproof i
applyS (simp add : INV itran ord )
applyS (simp add : I0 )
applyS (rule F RL; auto)
applyS (erule C IMP ; assumption? ; auto)
applyS (auto intro: T IMP )
hproof i
definition check unit clause1 A cref ≡ doE {
ul ← iterate clause cref (λul . True) (λl ul . doE {
CHECK (sem lit 0 l A 6= Some True)
(mkp err 00True literal in clause assumed to be unit 00);
if (sem lit 0 l A = Some False) then ERETURN ul
else doE {
CHECK (ul = None ∨ ul = Some l )
(mkp err 002 −undec in clause assumed to be unit 00);
ERETURN (Some l )
}
}) None;
CHECK (ul 6= None) (mkp err 00Conflict in clause assumed to be unit 00);
EASSERT (ul 6= None);
ERETURN (the ul )
}
lemma check unit clause1 refine[refine]:
assumes [simplified , simp]: (Ai,A)∈Id
assumes CR: (cref ,C )∈cref rel
shows check unit clause1 Ai cref ≤⇓E UNIV Id (check unit clause A C )
hproof i
definition resolve id1 ≡ λ(CM , ) i. doE {
CHECK (i∈dom CM ) (mkp errN 00Invalid clause id 00 i);
ERETURN (the (CM i))
}
lemma resolve id1 refine[refine]:
[[ (CMi,CM )∈clausemap1 rel ; (ii,i)∈Id ]]
=⇒ resolve id1 CMi ii ≤⇓E UNIV cref rel (resolve id CM i)
hproof i
definition apply unit1 bt i CM A T ≡ doE {
C ← resolve id1 CM i;
l ← check unit clause1 A C ;
assign lit bt A T l
42
}
lemma apply unit1 bt refine[refine]:
[[ (ii,i)∈Id ; (CMi,CM )∈clausemap1 rel ; (Ai,A)∈Id ; (Ti,T )∈Id ]]
=⇒ apply unit1 bt ii CMi Ai Ti ≤ ⇓E UNIV Id (apply unit bt i CM A T )
hproof i
definition apply units1 bt CM A T prf ≡ doE {
(i,prf ) ← parse idZ prf ;
((A,T ),i,prf ) ← EWHILET
(λ((A,T ),i,prf ). i6=0 )
(λ((A,T ),i,prf ). doE {
(A,T ) ← apply unit1 bt i CM A T ;
(i,prf ) ← parse idZ prf ;
ERETURN ((A,T ),i,prf )
}) ((A,T ),i,prf );
ERETURN ((A,T ),prf )
}
lemma apply units1 bt refine[refine]:
[[ (CMi,CM )∈clausemap1 rel ; (Ai,A)∈Id ; (Ti,T )∈Id ; (iti,it)∈Id ]]
=⇒ apply units1 bt CMi Ai Ti iti ≤ ⇓E UNIV Id (apply units bt CM A T it)
hproof i
definition apply unit1 i CM A ≡ doE {
C ← resolve id1 CM i;
l ← check unit clause1 A C ;
ERETURN (assign lit A l )
}
lemma apply unit1 refine[refine]:
[[ (ii,i)∈Id ; (CMi,CM )∈clausemap1 rel ; (Ai,A)∈Id ]]
=⇒ apply unit1 ii CMi Ai ≤ ⇓E UNIV Id (apply unit i CM A)
hproof i
definition apply units1 CM A prf ≡ doE {
(i,prf ) ← parse idZ prf ;
(A,i,prf ) ← EWHILET
(λ(A,i,prf ). i6=0 )
(λ(A,i,prf ). doE {
A ← apply unit1 i CM A;
(i,prf ) ← parse idZ prf ;
ERETURN (A,i,prf )
}) (A,i,prf );
ERETURN (A,prf )
}
lemma apply units1 refine[refine]:
[[ (CMi,CM )∈clausemap1 rel ; (Ai,A)∈Id ; (iti,it)∈Id ]]
=⇒ apply units1 CMi Ai iti ≤ ⇓E UNIV Id (apply units CM A it)
hproof i
lemma dom and not C diff aux : [[¬is blocked A C ]]
=⇒ dom (and not C A C ) − dom A = {v ∈ var of lit ‘ C . A v = None}
hproof i
lemma dom and not C eq: dom (and not C A C ) = dom A ∪ var of lit‘C
hproof i
lemma backtrack and not C trail eq: [[ is backtrack (and not C A C ) T A]]
=⇒ T = {v ∈ var of lit ‘ C . A v = None}
hproof i
43
definition parse check blocked1 A0 cref ≡ doE {
((A,T ),it 0) ← parse check clause cref (λ . True) (λl (A,T ). doE {
CHECK (sem lit 0 l A 6= Some True) (mkp err 00Blocked lemma clause 00);
if (sem lit 0 l A = Some False) then ERETURN (A,T )
else doE {
EASSERT (sem lit 0 l A = None);
EASSERT (var of lit l ∈
/ T );
ERETURN (assign lit A (neg lit l ),insert (var of lit l ) T )
}
}) (A0 ,{});
ERETURN (cref ,(A,T ),it 0)
}
lemma parse check blocked1 refine[refine]:
assumes [simplified , simp]: (Ai,A)∈Id (iti,it)∈Id
shows parse check blocked1 Ai iti
≤ ⇓E UNIV (cref rel ×r Id ×r Id ) (parse check blocked bt A it)
hproof i
definition check conflict clause1 prf 0 A cref
≡ iterate clause cref (λ . True) (λl . doE {
CHECK (sem lit 0 l A = Some False)
(mkp errprf 00Expected conflict clause 00 prf 0 )
}) ()
lemma check conflict clause1 refine[refine]:
assumes [simplified ,simp]: (Ai,A)∈Id
assumes CR: (cref ,C )∈cref rel
shows check conflict clause1 it 0 Ai cref
≤⇓E UNIV Id (CHECK (is conflict clause A C ) msg)
hproof i
definition lit in clause1 cref l ≡ doE {
iterate clause cref (λf . ¬f ) (λlx . doE {
ERETURN (l =lx )
}) False
}
lemma lit in clause1 correct[THEN ESPEC trans, refine vcg]:
assumes CR: (cref ,C ) ∈ cref rel
shows lit in clause1 cref lc ≤ ESPEC (λ . False) (λr . r ←→ lc∈C )
hproof i
definition lit in clause and not true A cref lc ≡ doE {
f ← iterate clause cref (λf . f 6=2 ) (λl f . doE {
if (l =lc) then ERETURN 1
else if (sem lit 0 l A = Some True) then ERETURN 2
else ERETURN f
}) (0 ::nat);
ERETURN (f =1 )
}
lemma lit in clause and not true correct[THEN ESPEC trans, refine vcg]:
assumes CR: (cref ,C ) ∈ cref rel
shows lit in clause and not true A cref lc
≤ ESPEC (λ . False)
(λr . r ←→ lc∈C ∧ sem clause 0 (C −{lc}) A 6= Some True)
hproof i
definition and not C excl A cref exl ≡ doE {
44
iterate clause cref (λ . True) (λl (A,T ). doE {
if (l 6= exl ) then doE {
EASSERT (sem lit 0 l A 6= Some True);
if (sem lit 0 l A 6= Some False) then doE {
EASSERT (var of lit l ∈
/ T );
ERETURN (assign lit A (neg lit l ), insert (var of lit l ) T )
} else
ERETURN (A,T )
} else
ERETURN (A,T )
}) (A,{})
}
lemma and not C excl refine[refine]:
assumes [simplified ,simp]: (Ai,A)∈Id
assumes CR: (cref ,C ) ∈ cref rel
assumes [simplified ,simp]: (exli,exl )∈Id
shows and not C excl Ai cref exli
≤⇓E UNIV (Id ×r Id ) (and not C bt A (C −{exl }))
hproof i
definition get rat candidates1
:: ( 0it) clausemap1 ⇒ (var * bool ) ⇒ var literal ⇒ ( ,id set) enres
where
get rat candidates1 ≡ λ(CM ,RL) A l . doE {
let l = neg lit l ;
let cands raw = RL l ;
CHECK (¬is None cands raw ) (mkp err 00Resolution literal not declared 00);
(∗ Get collected candidates ∗)
let cands raw = the cands raw ;
EASSERT (distinct cands raw );
(∗ Filter deleted , blocked , and those not containing resolution literal ∗)
cands ← enfoldli cands raw (λ . True) (λi s. doE {
let cref = CM i;
if ¬is None cref then doE {
let cref = the cref ;
lant ← lit in clause and not true A cref l ;
if lant then doE {
EASSERT (i ∈
/ s);
ERETURN (insert i s)
} else ERETURN s
} else ERETURN s
}) {};
ERETURN cands
}
lemma get rat candidates1 refine[refine]:
assumes CMR: (CMi,CM )∈clausemap1 rel
assumes [simplified , simp]: (Ai,A)∈Id (resliti,reslit)∈Id
shows get rat candidates1 CMi Ai resliti
≤⇓E UNIV (Id ) (get rat candidates CM A reslit)
hproof i
focus hproof i
solved
hproof i
definition backtrack1 A T ≡ do {
ASSUME (finite T );
FOREACH T (λx A. RETURN (A(x :=None))) A
}
45
lemma backtrack1 correct[THEN SPEC trans, refine vcg]:
backtrack1 A T ≤ SPEC (λr . r = backtrack A T )
hproof i
definition register clause1 cid cref RL ≡ doE {
iterate clause cref (λ . True) (λl RL. doE {
ERETURN (abs cr register l cid RL)
}) RL
}
definition RL upd cid C RL ≡ (λl . case RL l of
None ⇒ None
| Some s ⇒ if l ∈C then Some (insert cid s) else Some s)
lemma RL upd empty[simp]: RL upd cid {} RL = RL
hproof i
lemma RL upd insert eff :
RL upd cid C RL l = Some s
=⇒ RL upd cid (insert l C ) RL = (RL upd cid C RL)(l 7→ insert cid s)
hproof i
lemma RL upd insert noeff :
RL upd cid C RL l = None =⇒ RL upd cid (insert l C ) RL = RL upd cid C RL
hproof i
lemma register clause1 correct[THEN ESPEC trans, refine vcg]:
assumes CR: (cref ,C )∈cref rel
assumes RL: (RLi,RL)∈Id
S → hbr set distinctioption rel
assumes fresh id : cid ∈
/ ran RL
shows register clause1 cid cref RLi
≤ ESPEC (λ . False)
(λRLi 0. (RLi 0, RL upd cid C RL) ∈ Id → hbr set distinctioption rel )
hproof i
apply1 (cases RLi l ; cases RL l ; simp)
hproof i
applyS (auto simp: mbhd invar init in br conv ran def )
hproof i
apply1 (frule fun relD[OF IdI [of l ]])
apply1 (frule fun relD[OF IdI [of l 0]])
apply1 (erule option relE ;
simp add : RL upd insert eff RL upd insert noeff )
applyS (auto simp: in br conv mbhd insert correct mbhd insert invar ) []
hproof i
apply1 (drule fun relD[OF IdI [of l 0]])
apply1 (erule set rev mp[OF option rel mono])
applyS (auto simp: in br conv mbhd invar exit)
hproof i
definition add clause1
:: id ⇒ 0it ⇒ ( 0it) clausemap1 ⇒ ( ,( 0it) clausemap1 ) enres
where add clause1 ≡ λi cref (CM ,RL). doE {
let CM = CM (i 7→ cref );
RL ← register clause1 i cref RL;
ERETURN (CM ,RL)
}
lemma add clause1 refine[refine]:
[[ (ii,i)∈Id ; (cref ,C )∈cref rel ; (CMi,CM )∈clausemap1 rel ]] =⇒
add clause1 ii cref CMi ≤⇓E UNIV clausemap1 rel (add clause i C CM )
hproof i
46
applyS assumption
applyS (erule fun relD[rotated , where f =RLi and f 0=RL];
auto simp: clausemap1 rel def )
applyS (auto simp: cm ids def )
apply1 clarsimp hproof i
applyS (auto simp: RL upd def split: if split asm) []
applyS (auto simp: RL upd def split: if split asm) []
applyS (auto
simp: RL upd def cref rel def in br conv
split: if split asm)
hproof i
definition check rup proof1
:: ( 0it) state1 ⇒ 0it ⇒ (nat× 0prf ) ⇒ ( ,( 0it) state1 × 0it × (nat× 0prf )) enres
where
check rup proof1 ≡ λ(last id ,CM ,A) it prf . doE {
(i,prf ) ← parse id prf ;
CHECK (i>last id ) (mkp errNprf 00Ids must be strictly increasing 00 i prf );
(cref ,(A,T ),it) ← parse check blocked1 A it;
((A,T ),prf ) ← apply units1 bt CM A T prf ;
(confl id ,prf ) ← parse id prf ;
confl ← resolve id1 CM confl id ;
check conflict clause1 prf A confl ;
CM ← add clause1 i cref CM ;
A ← enres lift (backtrack1 A T );
ERETURN ((i,CM ,A),it,prf )
}
lemma check rup proof1 refine[refine]:
assumes SR: (si,s)∈state1 rel
assumes [simplified , simp]: (iti,it)∈Id (prfi ,prf )∈Id
shows check rup proof1 si iti prfi
≤⇓E UNIV (state1 rel ×r Id ×r Id ) (check rup proof bt s it prf )
hproof i
definition check rat candidates part1 CM reslit candidates A prf ≡
check candidates 0 candidates A prf (λcand id A prf . doE {
cand ← resolve id1 CM cand id ;
(A,T2 ) ← and not C excl A cand (neg lit reslit);
((A,T2 ),prf ) ← apply units1 bt CM A T2 prf ;
(confl id ,prf ) ← parse id prf ;
confl ← resolve id1 CM confl id ;
check conflict clause1 prf A confl ;
A ← enres lift (backtrack1 A T2 );
ERETURN (A,prf )
})
definition check rat proof1
:: ( 0it) state1 ⇒ 0it ⇒ (nat × 0prf ) ⇒ ( ,( 0it) state1 × 0it × (nat × 0prf )) enres
where
check rat proof1 ≡ λ(last id ,CM ,A) it prf . doE {
(reslit,prf ) ← parse prf literal prf ;
CHECK (sem lit 0 reslit A 6= Some False)
(mkp errprf 00Resolution literal is false 00 prf );
(i,prf ) ← parse id prf ;
CHECK (i>last id ) (mkp errNprf 00Ids must be strictly increasing 00 i prf );
(cref ,(A,T ),it) ← parse check blocked1 A it;
CHECK monadic (lit in clause1 cref reslit)
(mkp errprf 00Resolution literal not in clause 00 prf );
47
((A,T ),prf ) ← apply units1 bt CM A T prf ;
candidates ← get rat candidates1 CM A reslit;
(A,prf ) ← check rat candidates part1 CM reslit candidates A prf ;
CM ← add clause1 i cref CM ;
A ← enres lift (backtrack1 A T );
ERETURN ((i,CM ,A),it,prf )
}
lemma check rat proof1 refine[refine]:
assumes SR: (si,s)∈state1 rel
assumes [simplified , simp]: (iti,it)∈Id (prfi ,prf )∈Id
shows check rat proof1 si iti prfi
≤⇓E UNIV (state1 rel ×r Id ×r Id ) (check rat proof bt s it prf )
hproof i
definition remove id1
:: id ⇒ ( 0cref ) clausemap1 ⇒ ( ,( 0cref ) clausemap1 ) enres
where remove id1 ≡ λi (CM ,RL). ERETURN (CM (i:=None),RL)
lemma remove id1 refine[refine]:
[[ (ii,i)∈Id ; (CMi,CM )∈clausemap1 rel ]]
=⇒ remove id1 ii CMi ≤⇓E UNIV clausemap1 rel (remove id i CM )
hproof i
definition remove ids1
:: ( 0cref ) clausemap1 ⇒ (nat × 0prf ) ⇒ ( ,( 0cref ) clausemap1 × (nat × 0prf )) enres
where
remove ids1 CM prf ≡ doE {
(i,prf ) ← parse idZ prf ;
(CM ,i,prf ) ← EWHILET
(λ( ,i, ). i6=0 )
(λ(CM ,i,prf ). doE {
CM ← remove id1 i CM ;
(i,prf ) ← parse idZ prf ;
ERETURN (CM ,i,prf )
}) (CM ,i,prf );
ERETURN (CM ,prf )
}
lemma remove ids1 refine[refine]:
[[ (CMi,CM )∈clausemap1 rel ; (prfi ,prf )∈Id ]]
=⇒ remove ids1 CMi prfi ≤⇓E UNIV (clausemap1 rel ×r Id ) (remove ids CM prf )
hproof i
definition check item1
:: ( 0it) state1 ⇒ 0it ⇒ (nat × 0prf ) ⇒ ( ,(( 0it) state1 × 0it × (nat × 0prf )) option) enres
where check item1 ≡ λ(last id ,CM ,A) it prf . doE {
(ty,prf ) ← parse type prf ;
case ty of
INVALID ⇒ THROW (mkp err 00Invalid item 00)
| UNIT PROP ⇒ doE {
(A,prf ) ← apply units1 CM A prf ;
ERETURN (Some ((last id ,CM ,A),it,prf ))
}
| DELETION ⇒ doE {
(CM ,prf ) ← remove ids1 CM prf ;
ERETURN (Some ((last id ,CM ,A),it,prf ))
}
| RUP LEMMA ⇒ doE {
s ← check rup proof1 (last id ,CM ,A) it prf ;
ERETURN (Some s)
}
48
| RAT LEMMA ⇒ doE {
s ← check rat proof1 (last id ,CM ,A) it prf ;
ERETURN (Some s)
}
| CONFLICT ⇒ doE {
(i,prf ) ← parse id prf ;
cref ← resolve id1 CM i;
check conflict clause1 prf A cref ;
ERETURN None
}
| RAT COUNTS ⇒ THROW (mkp errprf
00
Not expecting rat−counts in the middle of proof
00
prf )
}
lemma check item1 refine[refine]:
assumes SR: (si,s)∈state1 rel
assumes [simplified , simp]: (iti,it)∈Id (prfi ,prf )∈Id
shows check item1 si iti prfi
≤⇓E UNIV (hstate1 rel ×r Id ×r Id ioption rel ) (check item bt s it prf )
hproof i
applyS simp
hproof i
lemma check item1 deforest: check item1 = (λ(last id ,CM ,A) it prf . doE {
(ty,prf ) ← parse prf prf ;
if ty=1 then doE {
(A,prf ) ← apply units1 CM A prf ;
ERETURN (Some ((last id ,CM ,A),it,prf ))
}
else if ty=2 then doE {
(CM ,prf ) ← remove ids1 CM prf ;
ERETURN (Some ((last id ,CM ,A),it,prf ))
}
else if ty=3 then doE {
s ← check rup proof1 (last id ,CM ,A) it prf ;
ERETURN (Some s)
}
else if ty=4 then doE {
s ← check rat proof1 (last id ,CM ,A) it prf ;
ERETURN (Some s)
}
else if ty=5 then doE {
(i,prf ) ← parse id prf ;
cref ← resolve id1 CM i;
check conflict clause1 prf A cref ;
ERETURN None
}
else if ty=6 then
THROW (mkp errprf 00Not expecting rat−counts in the middle of proof
else
THROW (mkp errIprf 00Invalid item type 00 ty prf )
})
hproof i
definition (in −) cm empty1 :: ( 0cref ) clausemap1
where cm empty1 ≡ (Map.empty, Map.empty)
lemma cm empty refine[refine]: (cm empty1 , cm empty) ∈ clausemap1 rel
hproof i
definition is syn taut1 cref A ≡ doE {
EASSERT (A = Map.empty);
49
00
prf )
(t,A) ← iterate clause cref (λ(t,A). ¬t) (λl (t,A). doE {
if (sem lit 0 l A = Some False) then ERETURN (True,A)
else if sem lit 0 l A = Some True then ERETURN (False,A) (∗ DUP literal . Perhaps check for it? ∗)
else doE {
EASSERT (sem lit 0 l A = None);
ERETURN (False,assign lit A l )
}
}) (False,A);
(∗ Iterate again over clause to reset assignment ∗)
A ← iterate clause cref (λ . True) (λl A. doE {
let A = A(var of lit l := None);
ERETURN A
}) A;
ERETURN (t,A)
}
lemma is syn taut1 correct[THEN ESPEC trans, refine vcg]:
assumes CR: (cref ,C )∈cref rel
assumes [simp]: A = Map.empty
shows is syn taut1 cref A
≤ ESPEC (λ . False) (λ(t,A). (t ←→ is syn taut C ) ∧ A=Map.empty)
hproof i
definition read cnf1
:: 0it list ⇒ ( 0it) clausemap1 ⇒ ( ,( 0it) clausemap1 × nat) enres
where read cnf1 L CM ≡ doE {
(CM ,next id ,A) ← enfoldli L (λ . True) (λC (CM ,i,A). doE {
(ist,A) ← is syn taut1 C A;
if ist then
ERETURN (CM ,i+1 ,A)
else doE {
CM ← add clause1 i C CM ;
ERETURN (CM ,i+1 ,A)
}
}) (CM ,1 ,Map.empty);
ERETURN (CM , next id − 1 )
}
lemma read cnf1 refine[refine]:
assumes [simp]: (Fi,F )∈hcref rel ilist rel
assumes [simp]: (CMi,CM )∈clausemap1 rel
shows read cnf1 Fi CMi
≤ ⇓E UNIV (clausemap1 rel ×r nat rel ) (read cnf F CM )
hproof i
definition read cnf new1
:: 0it ⇒ 0it ⇒ 0it clausemap1 ⇒ ( , 0it clausemap1 × nat) enres
where read cnf new1 itE it CM ≡ doE {
(CM ,next id ,A) ← tok fold itE it (λit (CM ,next id ,A). doE {
(it 0,(t,A)) ← read clause check taut itE it A;
if t then ERETURN (it 0, (CM ,next id +1 ,A))
else doE {
EASSERT (∃ l it 0. lz string litZ it l it 0);
let C = it;
CM ← add clause1 next id C CM ;
ERETURN (it 0,(CM ,next id +1 ,A))
}
}) (CM ,1 ,Map.empty);
ERETURN (CM , next id − 1 )
}
50
lemma read cnf new1 refine[refine]:
assumes [simplified ,simp]: (F begini, F begin)∈Id (F endi,F end )∈Id
assumes [simp]: (CMi,CM )∈clausemap1 rel
shows read cnf new1 F endi F begini CMi
≤ ⇓E UNIV (clausemap1 rel ×r nat rel )
(read cnf new F end F begin CM )
hproof i
applyS auto
hproof i
definition cm init lit1
:: var literal ⇒ ( 0it) clausemap1 ⇒ ( ,( 0it) clausemap1 ) enres
where cm init lit1 ≡ λl (CM ,RL). ERETURN (CM ,RL(l 7→ []))
definition init rat counts1 prf ≡ doE {
(ty,prf ) ← parse type prf ;
CHECK (ty = RAT COUNTS ) (mkp errprf
00
Expected RAT counts item 00 prf );
(l ,prf ) ← parse prf literalZ prf ;
(CM , ,prf ) ← EWHILET (λ(CM ,l ,prf ). l 6=None) (λ(CM ,l ,prf ). doE {
EASSERT (l 6=None);
let l = the l ;
( ,prf ) ← parse prf prf ;
let l = neg lit l ;
CM ← cm init lit1 l CM ;
(l ,prf ) ← parse prf literalZ prf ;
ERETURN (CM ,l ,prf )
}) (cm empty1 ,l ,prf );
ERETURN (CM ,prf )
}
lemma init rat counts1 refine[refine]:
assumes [simplified ,simp]: (prfi ,prf )∈Id
shows init rat counts1 prfi ≤⇓E UNIV (clausemap1 rel ×r Id ) (init rat counts prf )
hproof i
lemma init rat counts1 deforest: init rat counts1 prf = doE {
(ty,prf ) ← parse prf prf ;
CHECK (ty = 1 ∨ ty = 2 ∨ ty = 3 ∨ ty = 4 ∨ ty = 5 ∨ ty = 6 )
(mkp errIprf 00Invalid item type 00 ty prf );
CHECK (ty = 6 ) (mkp errprf 00Expected RAT counts item 00 prf );
(l ,prf ) ← parse prf literalZ prf ;
(CM ,l ,prf ) ← EWHILET
(λ(CM ,l ,prf ). l 6=None)
(λ(CM ,l ,prf ). doE {
EASSERT (l 6=None);
let l = the l ;
( ,prf ) ← parse prf prf ;
let l = neg lit l ;
CM ← cm init lit1 l CM ;
(l ,prf ) ← parse prf literalZ prf ;
ERETURN (CM ,l ,prf )
}) (cm empty1 ,l ,prf );
ERETURN (CM ,prf )
}
hproof i
51
definition verify unsat1 F begin F end it prf ≡ doE {
let A=Map.empty;
EASSERT (it invar it);
(CM ,prf ) ← init rat counts1 prf ;
(CM ,last id ) ← read cnf new1 F end F begin CM ;
let s = (last id ,CM ,A);
s ← EWHILEIT
(λSome ( ,it, ) ⇒ it invar it | None ⇒ True)
(λs. s6=None)
(λs. doE {
EASSERT (s6=None);
let (s,it,prf ) = the s;
EASSERT (it invar it);
check item1 s it prf
}) (Some (s,it,prf ));
CHECK (is None s) (mkp err
00
Proof did not contain conflict declaration 00)
}
lemma verify unsat1 refine[refine]:
[[ (F begini,F begin)∈Id ; (F endi,F end )∈Id ; (iti,it)∈Id ; (prfi ,prf )∈Id ]]
=⇒ verify unsat1 F begini F endi iti prfi
≤⇓E UNIV Id (verify unsat bt F begin F end it prf )
hproof i
end
5.4
5.4.1
Refinement 2
Getting Out of Exception Monad
context unsat input
begin
lemmas [enres inline] = parse id def parse idZ def parse prf literal def parse prf literalZ def
synth-definition parse prf bd is [enres unfolds]: parse prf prf = ◊
hproof i
synth-definition check unit clause1 bd
is [enres unfolds]: check unit clause1 A cref = ◊
hproof i
lemma resolve id1 alt: resolve id1 = (λ(CM , ) i. doE {
let x = CM i;
if (x =None) then THROW (mkp errN 00Invalid clause id 00 i)
else ERETURN (the x )
})
hproof i
synth-definition resolve id1 bd is [enres unfolds]: resolve id1 CM cid = ◊
hproof i
synth-definition apply unit1 bt bd
is [enres unfolds]: apply unit1 bt i CM A T = ◊
hproof i
synth-definition apply units1 bt bd
52
is [enres unfolds]: apply units1 bt CM A T units = ◊
hproof i
synth-definition apply unit1 bd is [enres unfolds]: apply unit1 i CM A = ◊
hproof i
synth-definition apply units1 bd
is [enres unfolds]: apply units1 CM A units = ◊
hproof i
synth-definition remove ids1 bd
is [enres unfolds]: remove ids1 CM prf = ◊
hproof i
synth-definition parse check blocked1 bd
is [enres unfolds]: parse check blocked1 A cref = ◊
hproof i
synth-definition check conflict clause1 bd
is [enres unfolds]: check conflict clause1 prf 0 A cref = ◊
hproof i
synth-definition and not C excl bd
is [enres breakdown]: and not C excl A cref exl = enres lift ◊
hproof i
synth-definition lit in clause and not true bd
is [enres breakdown]: lit in clause and not true A cref lc = enres lift ◊
hproof i
synth-definition lit in clause bd
is [enres breakdown]: lit in clause1 cref lc = enres lift ◊
hproof i
synth-definition get rat candidates1 bd
is [enres unfolds]: get rat candidates1 CM A l = ◊
hproof i
synth-definition add clause1 bd
is [enres breakdown]: add clause1 i it CM = enres lift ◊
hproof i
synth-definition check rup proof1 bd
is [enres unfolds]: check rup proof1 s it prf = ◊
hproof i
term check rat candidates part1
synth-definition check rat candidates part1 bd
is [enres unfolds]:
check rat candidates part1 CM reslit candidates A prf = ◊
hproof i
synth-definition check rat proof1 bd
is [enres unfolds]: check rat proof1 s it prf = ◊
hproof i
synth-definition check item1 bd is [enres unfolds]: check item1 s it prf = ◊
hproof i
synth-definition is syn taut1 bd
is [enres breakdown]: is syn taut1 cref A = enres lift ◊
53
hproof i
synth-definition read cnf1 bd
is [enres breakdown]: read cnf1 F CM = enres lift ◊
hproof i
synth-definition read clause check taut bd
is [enres unfolds]: read clause check taut F end F begin A = ◊
hproof i
synth-definition read cnf new1 bd
is [enres unfolds]: read cnf new1 F begin F end CM = ◊
hproof i
synth-definition init rat counts1 bd
is [enres unfolds]: init rat counts1 prf = ◊
hproof i
synth-definition verify unsat1 bd
is [enres unfolds]: verify unsat1 F begin F end it prf = ◊
hproof i
end
5.4.2
Instantiating Input Locale
locale GRAT def loc = DB2 def loc +
fixes prf next :: 0prf ⇒ int × 0prf
locale GRAT loc = DB2 loc DB frml end + GRAT def loc DB frml end prf next
for DB frml end and prf next :: 0prf ⇒ int × 0prf
context GRAT loc
begin
sublocale unsat input liti.next liti.peek liti.end liti.I prf next
hproof i
end
5.4.3
Extraction from Locale
named-theorems extrloc unfolds
concrete-definition (in GRAT loc) parse prf2 loc
uses parse prf bd def [unfolded extrloc unfolds]
declare (in GRAT loc) parse prf2 loc.refine[extrloc unfolds]
concrete-definition parse prf2
uses GRAT loc.parse prf2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) parse prf2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) parse check blocked2 loc
uses parse check blocked1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) parse check blocked2 loc.refine[extrloc unfolds]
concrete-definition parse check blocked2
uses GRAT loc.parse check blocked2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) parse check blocked2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) check unit clause2 loc
54
uses check unit clause1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) check unit clause2 loc.refine[extrloc unfolds]
concrete-definition check unit clause2 uses GRAT loc.check unit clause2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) check unit clause2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) resolve id2 loc
uses resolve id1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) resolve id2 loc.refine[extrloc unfolds]
concrete-definition resolve id2 uses GRAT loc.resolve id2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) resolve id2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) apply units2 loc
uses apply units1 bd def [unfolded apply unit1 bd def extrloc unfolds]
declare (in GRAT loc) apply units2 loc.refine[extrloc unfolds]
concrete-definition apply units2 uses GRAT loc.apply units2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) apply units2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) apply units2 bt loc
uses apply units1 bt bd def [unfolded apply unit1 bt bd def extrloc unfolds]
declare (in GRAT loc) apply units2 bt loc.refine[extrloc unfolds]
concrete-definition apply units2 bt uses GRAT loc.apply units2 bt loc def [unfolded extrloc unfolds]
declare (in GRAT loc) apply units2 bt.refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) remove ids2 loc
uses remove ids1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) remove ids2 loc.refine[extrloc unfolds]
concrete-definition remove ids2 uses GRAT loc.remove ids2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) remove ids2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) check conflict clause2 loc
uses check conflict clause1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) check conflict clause2 loc.refine[extrloc unfolds]
concrete-definition check conflict clause2 uses GRAT loc.check conflict clause2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) check conflict clause2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) and not C excl2 loc
uses and not C excl bd def [unfolded extrloc unfolds]
declare (in GRAT loc) and not C excl2 loc.refine[extrloc unfolds]
concrete-definition and not C excl2 uses GRAT loc.and not C excl2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) and not C excl2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) lit in clause and not true2 loc
uses lit in clause and not true bd def [unfolded extrloc unfolds]
declare (in GRAT loc) lit in clause and not true2 loc.refine[extrloc unfolds]
concrete-definition lit in clause and not true2 uses GRAT loc.lit in clause and not true2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) lit in clause and not true2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) get rat candidates2 loc
uses get rat candidates1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) get rat candidates2 loc.refine[extrloc unfolds]
concrete-definition get rat candidates2 uses GRAT loc.get rat candidates2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) get rat candidates2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) backtrack2 loc
uses backtrack1 def [unfolded extrloc unfolds]
declare (in GRAT loc) backtrack2 loc.refine[extrloc unfolds]
concrete-definition backtrack2 uses GRAT loc.backtrack2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) backtrack2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) add clause2 loc
55
uses add clause1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) add clause2 loc.refine[extrloc unfolds]
concrete-definition add clause2 uses GRAT loc.add clause2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) add clause2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) check rup proof2 loc
uses check rup proof1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) check rup proof2 loc.refine[extrloc unfolds]
concrete-definition check rup proof2 uses GRAT loc.check rup proof2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) check rup proof2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) lit in clause2 loc
uses lit in clause bd def [unfolded extrloc unfolds]
declare (in GRAT loc) lit in clause2 loc.refine[extrloc unfolds]
concrete-definition lit in clause2 uses GRAT loc.lit in clause2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) lit in clause2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) check rat candidates part2 loc
uses check rat candidates part1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) check rat candidates part2 loc.refine[extrloc unfolds]
concrete-definition check rat candidates part2 uses GRAT loc.check rat candidates part2 loc def [unfolded extrloc unfolds]
declare(in GRAT loc) check rat candidates part2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) check rat proof2 loc
uses check rat proof1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) check rat proof2 loc.refine[extrloc unfolds]
concrete-definition check rat proof2 uses GRAT loc.check rat proof2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) check rat proof2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) check item2 loc
uses check item1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) check item2 loc.refine[extrloc unfolds]
concrete-definition check item2 uses GRAT loc.check item2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) check item2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) is syn taut2 loc
uses is syn taut1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) is syn taut2 loc.refine[extrloc unfolds]
concrete-definition is syn taut2 uses GRAT loc.is syn taut2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) is syn taut2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) read cnf2 loc
uses read cnf1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) read cnf2 loc.refine[extrloc unfolds]
concrete-definition read cnf2 uses GRAT loc.read cnf2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) read cnf2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) read clause check taut2 loc
uses read clause check taut bd def [unfolded extrloc unfolds]
declare (in GRAT loc) read clause check taut2 loc.refine[extrloc unfolds]
concrete-definition read clause check taut2 uses GRAT loc.read clause check taut2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) read clause check taut2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) read cnf new2 loc
uses read cnf new1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) read cnf new2 loc.refine[extrloc unfolds]
concrete-definition read cnf new2 uses GRAT loc.read cnf new2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) read cnf new2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) init rat counts2 loc
56
uses init rat counts1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) init rat counts2 loc.refine[extrloc unfolds]
concrete-definition init rat counts2 uses GRAT loc.init rat counts2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) init rat counts2 .refine[OF GRAT loc axioms, extrloc unfolds]
concrete-definition (in GRAT loc) verify unsat2 loc
uses verify unsat1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) verify unsat2 loc.refine[extrloc unfolds]
concrete-definition verify unsat2 uses GRAT loc.verify unsat2 loc def [unfolded extrloc unfolds]
declare (in GRAT loc) verify unsat2 .refine[OF GRAT loc axioms, extrloc unfolds]
5.4.4
Synthesis of Imperative Code
context GRAT def loc
begin
lemma pr next hnr [sepref import param]: (prf next,prf next) ∈ Id → Id ×r Id
hproof i
definition prfi assn :: nat × 0prf ⇒
where prfi assn ≡ id assn
definition prfn assn :: ( 0prf ⇒ int × 0prf ) ⇒
where prfn assn ≡ id assn
abbreviation errorp assn
≡ (id assn :: String.literal ⇒ ) ×a option assn int assn ×a option assn prfi assn
lemma prfi assn pure[safe constraint rules]: is pure prfi assn hproof i
term prf next
end
sepref-decl-intf 0prf i prfi is nat × 0prf
sepref-decl-intf 0prf i prfn is 0prf ⇒ int × 0prf
context
fixes DB :: clausedb2
fixes frml end :: nat
fixes prf next :: 0prf ⇒ int × 0prf
begin
interpretation GRAT def loc DB frml end prf next hproof i
term parse prf2 thm
parse prf2 def
lemmas [intf of assn] =
intf of assnI [where R=prfi assn and 0a= 0prf i prfi ]
intf of assnI [where R=prfn assn and 0a= 0prf i prfn]
term mkp raw err
lemma mkp raw err hnr [sepref fr rules]:
(uncurry2 (return ooo mkp raw err ), uncurry2 (RETURN ooo mkp raw err ))
∈ id assn k ∗a (option assn int assn)k ∗a (option assn prfi assn)k →a errorp assn
hproof i
sepref-register mkp raw err ::
String.literal ⇒ int option ⇒ 0prf i prfi option
⇒ String.literal × int option × 0prf i prfi option
definition parse prf impl (prfn :: 0prf ⇒ int × 0prf ) ≡ λ(fuel ::nat,prf ).
if fuel > 0 then do {
let (x ,prf ) = prfn prf ;
return (Inr (x ,(fuel −1 ,prf )))
57
} else
return (Inl (mkp raw err (STR
00
Out of fuel 00) None (Some (fuel , prf ))))
lemma parse prf impl hnr [sepref fr rules]:
(uncurry parse prf impl , uncurry parse prf2 ) ∈ prfn assn k ∗a prfi assn d
→a errorp assn +a int assn ×a prfi assn
hproof i
sepref-register parse prf2
:: 0prf i prfn ⇒ 0prf i prfi ⇒ ( 0prf i prfi error + int × 0prf i prfi ) nres
term read clause check taut2
sepref-definition read clause check taut3 is uncurry3 read clause check taut2
:: liti.a assn k ∗a liti.it assn k ∗a liti.it assn k ∗a assignment assn d
→a errorp assn +a liti.it assn ×a bool assn ×a assignment assn
hproof i
lemmas [sepref fr rules] = read clause check taut3 .refine
sepref-register read clause check taut2
:: int list ⇒ nat ⇒ nat ⇒ i assignment
⇒ ( 0prf i prfi error + nat × bool × i assignment) nres
sepref-definition add clause3 is uncurry3 add clause2
:: liti.a assn k ∗a nat assn k ∗a liti.it assn k ∗a cm assn d →a cm assn
hproof i
sepref-register add clause2 :: int list ⇒ nat ⇒ nat ⇒ i cm ⇒ i cm nres
lemmas [sepref fr rules] = add clause3 .refine
sepref-definition read cnf new3 is uncurry3 read cnf new2
:: liti.a assn k ∗a liti.it assn k ∗a liti.it assn k ∗a cm assn d
→a errorp assn +a cm assn ×a nat assn
hproof i
sepref-register read cnf new2
:: int list ⇒ nat ⇒ nat ⇒ i cm ⇒ ( 0prf i prfi error + i cm × nat) nres
lemmas [sepref fr rules] = read cnf new3 .refine
sepref-definition parse check blocked3 is uncurry2 parse check blocked2
:: liti.a assn k ∗a assignment assn d ∗a liti.it assn k
→a errorp assn +a
liti.it assn
×a (assignment assn ×a list set assn id assn)
×a liti.it assn
hproof i
term parse check blocked2
sepref-register parse check blocked2
:: int list ⇒ i assignment ⇒ nat
⇒ ( 0prf i prfi error + nat × (i assignment × nat set) × nat) nres
lemmas [sepref fr rules] = parse check blocked3 .refine
sepref-definition check unit clause3 is uncurry2 check unit clause2
:: liti.a assn k ∗a assignment assn k ∗a (liti.it assn)k
→a sum assn errorp assn (pure lit rel )
hproof i
lemmas [sepref fr rules] = check unit clause3 .refine
sepref-register check unit clause2
:: int list ⇒ i assignment ⇒ nat ⇒ ( 0prf i prfi error + nat literal ) nres
sepref-definition resolve id3 is uncurry resolve id2
:: cm assn k ∗a nat assn k →a sum assn errorp assn liti.it assn
58
hproof i
term resolve id2
sepref-register resolve id2
:: (nat) clausemap1 ⇒ nat ⇒ :: i cm ⇒ nat ⇒ ( 0prf i prfi error + nat) nres
lemmas [sepref fr rules] = resolve id3 .refine
term apply units2
sepref-definition apply units3 is uncurry4 apply units2
:: liti.a assn k ∗a prfn assn k ∗a cm assn k ∗a (assignment assn)d ∗a prfi assn d
→a errorp assn +a assignment assn ×a prfi assn
hproof i
sepref-register apply units2 :: ⇒ ⇒ (nat) clausemap1 ⇒
:: int list ⇒ 0prf i prfn ⇒ i cm ⇒ i assignment ⇒ 0prf i prfi
⇒ ( 0prf i prfi error + i assignment × 0prf i prfi ) nres
lemmas [sepref fr rules] = apply units3 .refine
sepref-definition apply units3 bt is uncurry5 apply units2 bt
:: liti.a assn k
∗a prfn assn k
∗a cm assn k
∗a (assignment assn)d
∗a (list set assn nat assn)d
∗a prfi assn d
→a errorp assn +a
(assignment assn ×a list set assn nat assn) ×a prfi assn
hproof i
sepref-register apply units2 bt :: ⇒ ⇒ (nat) clausemap1 ⇒
:: int list ⇒ 0prf i prfn ⇒ i cm ⇒ i assignment ⇒ nat set ⇒ 0prf i prfi
⇒ ( 0prf i prfi error + (i assignment × nat set) × 0prf i prfi ) nres
lemmas [sepref fr rules] = apply units3 bt.refine
term remove ids2
sepref-definition remove ids3 is uncurry2 remove ids2
:: prfn assn k ∗a cm assn d ∗a prfi assn d
→a errorp assn +a cm assn ×a prfi assn
hproof i
sepref-register remove ids2 :: ⇒ (nat) clausemap1 ⇒
:: 0prf i prfn ⇒ i cm ⇒ 0prf i prfi ⇒ ( 0prf i prfi error + i cm × 0prf i prfi ) nres
lemmas [sepref fr rules] = remove ids3 .refine
term check conflict clause2
sepref-definition check conflict clause3 is uncurry3 check conflict clause2
:: liti.a assn k ∗a prfi assn k ∗a assignment assn k ∗a liti.it assn k
→a sum assn errorp assn unit assn
hproof i
sepref-register check conflict clause2
:: int list ⇒ 0prf i prfi ⇒ i assignment ⇒ nat ⇒ ( 0prf i prfi error + unit) nres
lemmas [sepref fr rules] = check conflict clause3 .refine
term and not C excl2
sepref-definition and not C excl3 is uncurry3 and not C excl2
:: liti.a assn k ∗a (assignment assn)d ∗a (liti.it assn)k ∗a (pure lit rel )k
→a prod assn assignment assn (list set assn nat assn)
hproof i
sepref-register and not C excl2
:: int list ⇒ i assignment ⇒ nat ⇒ nat literal
⇒ (i assignment × nat set) nres
lemmas [sepref fr rules] = and not C excl3 .refine
59
sepref-definition lit in clause and not true3
is uncurry3 lit in clause and not true2
:: liti.a assn k ∗a (assignment assn)k ∗a liti.it assn k ∗a (pure lit rel )k
→a bool assn
hproof i
lemmas [sepref fr rules] = lit in clause and not true3 .refine
sepref-register lit in clause and not true2
:: int list ⇒ (nat,bool ) i map ⇒ nat ⇒ nat literal ⇒ bool nres
sepref-definition get rat candidates3 is uncurry3 get rat candidates2
:: liti.a assn k ∗a cm assn k ∗a (assignment assn)k ∗a (pure lit rel )k
→a sum assn errorp assn (list set assn nat assn)
hproof i
sepref-register get rat candidates2
:: int list ⇒ i cm ⇒ i assignment ⇒ nat literal
⇒ ( 0prf i prfi error + nat set) nres
lemmas [sepref fr rules] = get rat candidates3 .refine
sepref-definition backtrack3 is uncurry backtrack2
:: (assignment assn)d ∗a (list set assn nat assn)k →a assignment assn
hproof i
sepref-register backtrack2 :: (nat*bool ) ⇒
:: i assignment ⇒ nat set ⇒ i assignment nres
lemmas [sepref fr rules] = backtrack3 .refine
term check rup proof2
sepref-definition check rup proof3 is uncurry4 check rup proof2
:: liti.a assn k ∗a prfn assn k ∗a (state assn)d ∗a liti.it assn k ∗a prfi assn d
→a errorp assn +a state assn ×a liti.it assn ×a prfi assn
hproof i
sepref-register check rup proof2
:: int list ⇒ 0prf i prfn ⇒ i state ⇒ nat ⇒ 0prf i prfi
⇒ ( 0prf i prfi error + i state × nat × 0prf i prfi ) nres
lemmas [sepref fr rules] = check rup proof3 .refine
term lit in clause2
sepref-definition lit in clause3 is uncurry2 lit in clause2
:: liti.a assn k ∗a liti.it assn k ∗a lit assn k →a bool assn
hproof i
sepref-register lit in clause2 :: int list ⇒ nat ⇒ nat literal ⇒ bool nres
lemmas [sepref fr rules] = lit in clause3 .refine
term check rat candidates part2
sepref-definition check rat candidates part3
is uncurry6 check rat candidates part2 ::
liti.a assn k
∗a prfn assn k
∗a cm assn k
∗a lit assn k
∗a (list set assn nat assn)d
∗a assignment assn d
∗a prfi assn d
→a errorp assn +a (assignment assn ×a prfi assn)
hproof i
sepref-register check rat candidates part2 :: ⇒ ⇒ (nat) clausemap1 ⇒
:: int list ⇒ 0prf i prfn ⇒ i cm ⇒ nat literal ⇒ nat set ⇒ i assignment ⇒ 0prf i prfi
⇒ ( 0prf i prfi error + i assignment × 0prf i prfi ) nres
lemmas [sepref fr rules] = check rat candidates part3 .refine
term check rat proof2
sepref-definition check rat proof3 is uncurry4 check rat proof2
:: liti.a assn k ∗a prfn assn k ∗a (state assn)d ∗a liti.it assn k ∗a prfi assn d
60
→a errorp assn +a state assn ×a liti.it assn ×a prfi assn
hproof i
sepref-register check rat proof2
:: int list ⇒ 0prf i prfn ⇒ i state ⇒ nat ⇒ 0prf i prfi
⇒ ( 0prf i prfi error + i state × nat × 0prf i prfi ) nres
lemmas [sepref fr rules] = check rat proof3 .refine
term check item2
sepref-definition check item3 is uncurry4 check item2
:: liti.a assn k ∗a prfn assn k ∗a (state assn)d ∗a liti.it assn k ∗a prfi assn d
→a errorp assn +a option assn (state assn ×a liti.it assn ×a prfi assn)
hproof i
sepref-register check item2
:: int list ⇒ 0prf i prfn ⇒ i state ⇒ nat ⇒ 0prf i prfi
⇒ ( 0prf i prfi error + (i state × nat × 0prf i prfi ) option) nres
lemmas [sepref fr rules] = check item3 .refine
term is syn taut2
sepref-definition is syn taut3 is uncurry2 is syn taut2
:: liti.a assn k ∗a liti.it assn k ∗a assignment assn d
→a bool assn ×a assignment assn
hproof i
sepref-register is syn taut2
:: int list ⇒ nat ⇒ i assignment ⇒ (bool × i assignment) nres
lemmas [sepref fr rules] = is syn taut3 .refine
term read cnf2
sepref-definition read cnf3 is uncurry2 read cnf2
:: liti.a assn k ∗a (list assn liti.it assn)k ∗a cm assn d
→a cm assn ×a nat assn
hproof i
sepref-register read cnf2
:: int list ⇒ nat list ⇒ i cm ⇒ (i cm × nat) nres
lemmas [sepref fr rules] = read cnf3 .refine
term init rat counts2
sepref-definition init rat counts3 is uncurry init rat counts2
:: prfn assn k ∗a prfi assn d →a errorp assn +a (cm assn ×a prfi assn)
hproof i
sepref-register init rat counts2
:: 0prf i prfn ⇒ 0prf i prfi ⇒ ( 0prf i prfi error + i cm × 0prf i prfi ) nres
lemmas [sepref fr rules] = init rat counts3 .refine
term verify unsat2
sepref-definition verify unsat3 is uncurry5 verify unsat2
:: liti.a assn k
∗a prfn assn k
∗a liti.it assn k
∗a liti.it assn k
∗a liti.it assn k
∗a prfi assn d
→a errorp assn +a unit assn
hproof i
end
definition verify unsat split impl wrapper DBi prf next F end it prf ≡ do {
lenDBi ← Array.len DBi;
if (0 < F end ∧ F end ≤ lenDBi ∧ 0 < it ∧ it ≤ lenDBi) then
61
verify unsat3 DBi prf next 1 F end it prf
else
return (Inl (STR 00Invalid arguments 00,None,None))
}
lemmas [code] = DB2 def loc.item next impl def
export-code verify unsat split impl wrapper checking SML imp
5.5
Correctness Theorem
context GRAT loc begin
lemma verify unsat3 correct aux [sep heap rules]:
assumes SEG: liti.seg F begin lst F end
assumes itI [simp]: it invar F end it invar it
shows
<DBi 7→a DB >
verify unsat3 DBi prf next F begin F end it prf
<λr . DBi 7→a DB ∗ ↑(¬isl r −→ F invar lst ∧ ¬sat (F α lst))>t
hproof i
applyS (sep auto simp: prfi assn def prfn assn def pure def )
applyS (sep auto dest!: 1 simp: sum.disc eq case split: sum.splits)
applyS (simp add : I begin)
hproof i
end
Main correctness theorem: Given an array DBi that contains the integers DB, the verification algorithm does
not change the array, and if it returns a non-Inl value, the formula in the array is unsatisfiable, as specified
by formula unsat spec.
theorem verify unsat split impl wrapper correct[sep heap rules]:
shows
<DBi 7→a DB >
verify unsat split impl wrapper DBi prf next F end it prf
<λresult. DBi 7→a DB ∗ ↑(¬isl result −→ formula unsat spec DB F end )>t
hproof i
end
6
Satisfiability Check
theory Sat Check
imports Grat Basic
begin
6.1
Abstract Specification
locale sat input = input it invar 0 it next it peek it end for it invar 0 :: 0it::linorder ⇒ bool
and it next it peek it end
context sat input begin
definition read assignment it ≡ doE {
let A = Map.empty;
check not end it;
(A, ) ← EWHILEIT (λ( ,it). it invar it ∧ it6=it end ) (λ( ,it). it peek it 6= litZ ) (λ(A,it). doE {
(l ,it) ← parse literal it;
check not end it;
CHECK (sem lit 0 l A 6= Some False) (mk errit 00Contradictory assignment 00 it);
let A = assign lit A l ;
ERETURN (A,it)
}) (A,it);
ERETURN A
62
}
We merely specify that this does not fail, i.e. termination and assertions.
lemma read assignment correct[THEN ESPEC trans, refine vcg]:
it invar it =⇒ read assignment it ≤ ESPEC (λ . True) (λ . True)
hproof i
definition read clause check sat itE it A ≡ doE {
EASSERT (it invar it ∧ it invar itE ∧ itran itE it end );
parse lz
(mk errit 00Parsed beyond end 00 it)
litZ itE it (λ . True) (λx r . doE {
let l = lit α x ;
ERETURN (r ∨ (sem lit 0 l A = Some True))
}) False
}
lemma read clause check sat correct[THEN ESPEC trans, refine vcg]:
[[itran it itE ; it invar itE ]] =⇒
read clause check sat itE it A
≤ ESPEC
(λ . True)
(λ(it 0,r ). ∃ l . lz string litZ it l it 0 ∧ itran it 0 itE
∧ (r ←→ sem clause 0 (clause α l ) A = Some True))
hproof i
definition check sat it itE A ≡ doE {
tok fold itE it (λit . doE {
(it 0,r ) ← read clause check sat itE it A;
CHECK (r ) (mk errit 00Clause not satisfied by given assignment 00 it);
ERETURN (it 0,())
}) ()
}
term sem cnf
lemma obtain compat assignment: obtains σ where compat assignment A σ
hproof i
lemma check sat correct[THEN ESPEC trans, refine vcg]:
[[seg it lst itE ; it invar itE ]] =⇒ check sat it itE A
≤ ESPEC (λ . True) (λ . F invar lst ∧ sat (F α lst))
hproof i
definition verify sat F begin F end it ≡ doE {
A ← read assignment it;
check sat F begin F end A
}
lemma verify sat correct[THEN ESPEC trans, refine vcg]:
[[seg F begin lst F end ; it invar F end ; it invar it]]
=⇒ verify sat F begin F end it ≤ ESPEC (λ . True) (λ . F invar lst ∧ sat (F α lst))
hproof i
end
6.2
Implementation
context sat input begin
63
6.2.1
Getting Out of Exception Monad
synth-definition read assignment bd is [enres unfolds]: read assignment it = ◊
hproof i
synth-definition read clause check sat bd is [enres unfolds]: read clause check sat itE it A = ◊
hproof i
synth-definition check sat bd is [enres unfolds]: check sat it itE = ◊
hproof i
synth-definition verify sat bd is [enres unfolds]: verify sat F begin F end it = ◊
hproof i
end
6.3
Extraction from Locales
named-theorems extrloc unfolds
context DB2 loc begin
sublocale sat input liti.I liti.next liti.peek liti.end
hproof i
end
concrete-definition (in DB2 loc) read assignment2 loc
uses read assignment bd def [unfolded extrloc unfolds]
declare (in DB2 loc) read assignment2 loc.refine[extrloc unfolds]
concrete-definition read assignment2 uses DB2 loc.read assignment2 loc def [unfolded extrloc unfolds]
declare (in DB2 loc) read assignment2 .refine[OF DB2 loc axioms, extrloc unfolds]
concrete-definition (in DB2 loc) read clause check sat2 loc
uses read clause check sat bd def [unfolded extrloc unfolds]
declare (in DB2 loc) read clause check sat2 loc.refine[extrloc unfolds]
concrete-definition read clause check sat2 uses DB2 loc.read clause check sat2 loc def [unfolded extrloc unfolds]
declare (in DB2 loc) read clause check sat2 .refine[OF DB2 loc axioms, extrloc unfolds]
concrete-definition (in DB2 loc) check sat2 loc
uses check sat bd def [unfolded extrloc unfolds]
declare (in DB2 loc) check sat2 loc.refine[extrloc unfolds]
concrete-definition check sat2 uses DB2 loc.check sat2 loc def [unfolded extrloc unfolds]
declare (in DB2 loc) check sat2 .refine[OF DB2 loc axioms, extrloc unfolds]
concrete-definition (in DB2 loc) verify sat2 loc
uses verify sat bd def [unfolded extrloc unfolds]
declare (in DB2 loc) verify sat2 loc.refine[extrloc unfolds]
concrete-definition verify sat2 uses DB2 loc.verify sat2 loc def [unfolded extrloc unfolds]
declare (in DB2 loc) verify sat2 .refine[OF DB2 loc axioms, extrloc unfolds]
6.3.1
Synthesis of Imperative Code
context
fixes DB :: clausedb2
fixes frml end :: nat
begin
interpretation DB2 def loc DB frml end hproof i
term read assignment2
sepref-definition read assignment3 is uncurry read assignment2
:: liti.a assn k ∗a liti.it assn k →a error assn +a assignment assn
hproof i
sepref-register read assignment2 :: int list ⇒ nat ⇒ (nat error + i assignment) nres
64
lemmas [sepref fr rules] = read assignment3 .refine
term read clause check sat2
sepref-definition read clause check sat3 is uncurry3 read clause check sat2
:: liti.a assn k ∗a liti.it assn k ∗a liti.it assn k ∗a assignment assn k →a error assn +a liti.it assn ×a bool assn
hproof i
sepref-register read clause check sat2 :: int list ⇒ nat ⇒ nat ⇒ i assignment ⇒ (nat error + nat×bool ) nres
lemmas [sepref fr rules] = read clause check sat3 .refine
term check sat2
sepref-definition check sat3 is uncurry3 check sat2
:: liti.a assn k ∗a liti.it assn k ∗a liti.it assn k ∗a assignment assn k →a error assn +a unit assn
hproof i
sepref-register check sat2 :: int list ⇒ nat ⇒ nat ⇒ i assignment ⇒ (nat error + unit) nres
lemmas [sepref fr rules] = check sat3 .refine
term verify sat2
sepref-definition verify sat3 is uncurry3 verify sat2
:: liti.a assn k ∗a liti.it assn k ∗a liti.it assn k ∗a liti.it assn k →a error assn +a unit assn
hproof i
sepref-register verify sat2 :: int list ⇒ nat ⇒ nat ⇒ nat ⇒ (nat error + unit) nres
lemmas [sepref fr rules] = verify sat3 .refine
end
definition verify sat impl wrapper DBi F end ≡ do {
lenDBi ← Array.len DBi;
if (0 <F end ∧ F end ≤ lenDBi) then
verify sat3 DBi 1 F end F end
else
return (Inl (STR 00Invalid arguments 00,None,None))
}
export-code verify sat impl wrapper checking SML imp
6.4
Correctness Theorem
context DB2 loc begin
lemma verify sat3 correct:
assumes SEG: liti.seg F begin lst F end
assumes itI [simp]: it invar F end it invar it
shows <DBi 7→a DB > verify sat3 DBi F begin F end it <λr . DBi 7→a DB ∗ ↑(¬isl r −→ F invar lst ∧ sat (F α
lst)) >t
hproof i
applyS sep auto
applyS (sep auto dest!: 1 simp: sum.disc eq case split: sum.splits)
applyS (simp add : I begin)
hproof i
end
definition formula sat spec DB F end ≡ let lst = tl (take F end DB ) in
F end ≤ length DB ∧ F end ≥ 1
∧ (F end > 1 −→ last lst = 0 )
∧ sat (F α lst)
theorem verify sat impl wrapper correct[sep heap rules]:
shows
<DBi 7→a DB >
verify sat impl wrapper DBi F end
<λresult. DBi 7→a DB ∗ ↑(¬isl result −→ formula sat spec DB F end )>t
hproof i
65
end
7
Code Generation and Summary of Correctness Theorems
theory Grat Check Code Exporter
imports Unsat Check Unsat Check Split Sat Check
begin
7.1
Code Generation
We generate code for verify unsat impl wrapper and verify sat impl wrapper.
The first statement is a sanity check, that will make our automated regression tests fail if the generated code
does not compile.
The second statement actually exports the two main functions, and some auxiliary functions to convert
between SML and Isabelle integers, and to access the sum data type of Isabelle, which is used to encode the
checker’s result.
export-code
verify unsat impl wrapper
verify unsat split impl wrapper
verify sat impl wrapper
checking SML imp
export-code
verify sat impl wrapper
verify unsat impl wrapper
verify unsat split impl wrapper
int of integer
integer of int
integer of nat
nat of integer
isl projl projr Inr Inl Pair
in SML imp module-name Grat Check file code/gratchk export.sml
7.2
Summary of Correctness Theorems
In this section, we re-prove the correctness theorems that are proved elsewhere, slightly adapting them for
optimal presentation.
The goal of this section is to provide a step-by-step justification of the trusted base of our specification, only
building on well-known standard functions.
As we only prove soundness, our lemmas do not mention the structure of the certificate at all. However, in
order not to fail, we expect a non-contradictory list of literals that satisfy the formula, or a GRAT unsat
certificate, respectively.
7.2.1
Interpreting an Integer List as Formula
First, we show how to interpret a formula. A formula is represented according to the de facto standard
for encoding CNF formulas: Variables are identified by positive integers. Negative integers encode negated
variables. A clause is a null-terminated string of integers, and the formula is simply the concatenation of its
clauses.
Any list that is empty, or ends with a null, can be interpreted as formula. To this end, we define:
definition intlist invar :: int list ⇒ bool
where intlist invar lst ≡ lst6=[] −→ last lst = 0
Next, we have to define how to split the list into clauses. As splitting is harder to define than composition,
we simply define splitting as the (unique) inverse of concatenating the lists again.
66
For a flat list lst, and a list of lists ll, the following predicate states that ll contains no nulls, and lst can be
constructed by concatenating ll, terminating each part with a null.
definition is concatenation :: int list ⇒ int list list ⇒ bool
where is concatenation lst ll
≡ (∀ l ∈set ll . 0 ∈set
/
l ) ∧ concat (map (λl . l @[0 ]) ll ) = lst
We show that for each valid flat lst, there is exactly one list of lists ll with is concatenation lst ll. We call
this list of lists tokenize 0 lst.
lemma
assumes intlist invar lst
shows ∃ !ll . is concatenation lst ll
and tokenize 0 lst = (THE ll . is concatenation lst ll )
hproof i
As last step, we convert the list of lists to a set of sets, i.e., we identify equal literals in clauses, and equal
clauses in the formula. Obviously, this does not affect satisfiability.
definition parse intlist :: int list ⇒ int set set
where parse intlist lst ≡ set ‘ set (tokenize 0 lst)
7.2.2
Satisfiable Formulas
Next, we define satisfiable formulas. A concise way is to use a mapping σ from literals (i.e. integers) to
Booleans, which is required to be consistent, i.e., opposite literals are mapped to opposite values. Then, the
formula is satisfiable iff there exists a consistent mapping, such that every clause has a literal mapped to
True.
lemma assn consistent σ ←→ (∀ l . l 6=0 −→ σ l = (¬ σ (−l )))
hproof i
definition intset sat :: int set set ⇒ bool
where intset sat F ≡ ∃ σ. assn consistent σ ∧ (∀ C ∈F . ∃ l ∈C . σ l )
Finally, we get predicates that state that an integer list represents a valid (un)satisfiable formula
definition intlist repr sat :: int list ⇒ bool
where intlist repr sat lst
≡ intlist invar lst ∧ intset sat (parse intlist lst)
definition intlist repr unsat :: int list ⇒ bool
where intlist repr unsat lst
≡ intlist invar lst ∧ ¬intset sat (parse intlist lst)
We choose the type int set set to represent formulas. However, this type does not prevent us from having a
null in a clause.
The motivation for this choice was to avoid the introduction of an additional literal data type in the specification, which would add another level of indirection, and thus make it harder to read.
Considering the possible null in a clause, we remark that, first, our notion of satisfiability still makes sense,
as it treats a null like any other positive literal. Second, formulas that have been parsed from integer lists
contain no nulls anyway:
lemma parse intlist contains no null :
intlist invar lst =⇒ ∀ C ∈parse intlist lst. 0 ∈C
/
hproof i
7.2.3
Extracting the Formula from the Input Array
Having defined predicates for an integer list representing a satisfiable/unsatisfiable formula, we extend them
to the actual input expected by our checker functions.
These functions expect an integer array DBi (clause database) and an index F end (formula end). The first
element of the array is unused (to have index 0 as a special value). The elements [1 ..<F end ] contain the
formula, and the remaining array contains the certificate.
In order to extract the elements [1 ..<F end ] from a list, we use the term tl (take F end DB ), i.e., take
the first F end elements, and then throw away the first one. This is a concise specification only using the
standard list functions of Isabelle/HOL.
67
Thus, we get:
definition DBF sat :: int list ⇒ nat ⇒ bool
where DBF sat DB F end
≡ F end ≤ length DB ∧ intlist repr sat (tl (take F end DB ))
definition DBF unsat :: int list ⇒ nat ⇒ bool
where DBF unsat DB F end
≡ F end ≤ length DB ∧ intlist repr unsat (tl (take F end DB ))
Note, that there are other, equivalent, ways to specify the elements [1 ..<F end ] of a list, e.g.:
lemma formula sublist by map nth upt:
F end ≤ length DB =⇒ map (nth DB ) [1 ..<F end ] = tl (take F end DB )
hproof i
7.2.4
Hoare-Triples for our Checkers
Finally, we prove Hoare-triples for the checker functions. The precondition just states that DBi points to
an array containing the elements DB :
theorem verify sat impl wrapper sound :
shows
<DBi 7→a DB >
verify sat impl wrapper DBi F end
<λresult. DBi 7→a DB ∗ ↑(¬isl result −→ DBF sat DB F end ) >t
hproof i
apply1 (cases F end = 1 ; clarsimp)
apply1 (clarsimp simp: F α def alt sat sat eq[OF tokenize complete])
hproof i
theorem verify unsat impl wrapper sound :
shows
<DBi 7→a DB >
verify unsat impl wrapper DBi F end it
<λresult. DBi 7→a DB ∗ ↑(¬isl result −→ DBF unsat DB F end ) >t
hproof i
theorem verify unsat split impl wrapper sound :
shows
<DBi 7→a DB >
verify unsat split impl wrapper DBi prf next F end it prf
<λresult. DBi 7→a DB ∗ ↑(¬isl result −→ DBF unsat DB F end ) >t
hproof i
end
68
© Copyright 2026 Paperzz