GRATchk: Verified (UN)SAT Certificate Checker Peter Lammich December 25, 2018 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 4 2.1 Used Variables ............................................ 5 2.2 Assigning Valuations ......................................... 6 3 Unit Propagation and RUP/RAT Checks 6 3.1 Partial Assignments ......................................... 6 3.1.1 Models, Equivalence, and Redundancy ........................... 11 3.2 Unit Propagation ........................................... 13 3.3 RUP and RAT Criteria ....................................... 15 3.4 Old assign all negated Formulation ................................. 18 3.4.1 Properties of assign all negated ............................... 18 3.5 Maybe-Head Insertion into Distinct List .............................. 20 4 Exception Monad for Refine-Monadic 20 4.1 Data Refinement ........................................... 25 4.1.1 Refine2- heuristics ...................................... 28 4.2 More Combinators .......................................... 31 4.2.1 CHECK-Monadic ....................................... 31 5 Arrays with Dynamic Resizing 33 6 Options and Maps with Default Value for None 34 6.1 Function-Level Map Operations ................................... 35 6.2 Map Operations, array-level ..................................... 35 6.3 Operations on Options ........................................ 37 7 Tokenization 39 8 Parsing to Formulas 40 8.1 Pretty-Printing Literals ....................................... 41 9 Direct Representation of Satisfiable Formulas 41 1
120
Embed
· GRATchk: Veri ed (UN)SAT Certi cate Checker Peter Lammich December 25, 2018 Abstract GRATchk is a formally veri ed and e cient checker for satis ability and unsatis ability certi
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
GRATchk: Verified (UN)SAT Certificate Checker
Peter Lammich
December 25, 2018
Abstract
GRATchk is a formally verified and efficient checker for satisfiability and unsatisfiability certificates forBoolean formulas.
The verification covers the actual efficient implementation, and the semantics of a formula down tothe integer sequences that represents it.
The satisfiability certificates are non-contradictory lists of literals, as output by any standard SATsolver. The unsatisfiability certificates are GRAT certificates, which can be generated from standardDRAT certificates by the GRATgen tool.
We present an efficient verified checker for satisfiability and unsatisfiability certificates obtained from SATsolvers.
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: Theunverified GRATgen tool converts the DRAT certificates into GRAT certificates, which are then checkedagainst 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 wellsuited for formal verification. We use the Isabelle Refinement Framework to verify an efficient imperativeimplementation 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 14.2,we give a complete and self-contained summary of what we actually proved.
2 Basics of Boolean Formulas in CNF
theory SAT Basicimports Mainbegin
datatype ′a literal = is pos: Pos ′a | Neg ′a
type-synonym ′a clause = ′a literal set
type-synonym ′a cnf = ′a clause set
type-synonym ′a valuation = ′a ⇒ bool
fun sem lit :: ′a literal ⇒ ′a valuation ⇒ bool wheresem 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 )by (auto split : literal .split)
definition sem clause :: ′a clause ⇒ ′a valuation ⇒ bool wheresem clause C σ ≡ ∃ l∈C . sem lit l σ
definition sem cnf :: ′a cnf ⇒ ′a valuation ⇒ bool wheresem cnf F σ ≡ ∀C∈F . sem clause C σ
definition sat :: ′a cnf ⇒ bool wheresat F ≡ ∃σ. sem cnf F σ
definition models :: ′a cnf ⇒ ′a valuation set wheremodels F ≡ {σ. sem cnf F σ}
lemma sat iff has models:sat F ←→ models F 6= {}unfolding sat def models def by auto
fun neg lit whereneg lit (Pos x ) = Neg x | neg lit (Neg x ) = Pos x
lemma neg neg lit [simp]: neg lit (neg lit l) = l by (cases l) autolemma neg lit neq [simp]:
neg lit l 6= ll 6= neg lit lby (cases l ; auto)+
4
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 ) ←→ punfolding mk lit def by auto
lemma sem clause empty [simp]: sem clause {} σ = Falseunfolding sem clause def by auto
lemma sem clause insert [simp]: sem clause (insert l C ) σ ←→ sem lit l σ ∨ sem clause C σby (auto simp: sem clause def )
lemma sem clause union[simp]: sem clause (C 1∪C 2) σ ←→ sem clause C 1 σ ∨ sem clause C 2 σby (auto simp: sem clause def )
lemma sem cnf empty [simp]: sem cnf {} σ by (auto simp: sem cnf def )lemma sem cnf insert [simp]: sem cnf (insert C F ) σ ←→ sem clause C σ ∧ sem cnf F σ
by (auto simp: sem cnf def )lemma sem cnf union[simp]: sem cnf (F 1 ∪ F 2) σ ←→ sem cnf F 1 σ ∧ sem cnf F 2 σ
by (auto simp: sem cnf def )
lemma sem clauseI : [[l∈C ; sem lit l σ]] =⇒ sem clause C σby (auto simp: sem clause def )
lemma sem cnfI : [[∧
C . C∈F =⇒ sem clause C σ]] =⇒ sem cnf F σby (auto simp: sem cnf def )
lemma sem neg lit [simp]: sem lit (neg lit l) σ ←→ ¬sem lit l σby (cases l) auto
lemma unsat empty clause: {}∈F =⇒ ¬sat Funfolding sat def sem cnf defby fastforce
lemma sat empty [simp, intro!]: sat {}unfolding sat def sem cnf def by auto
fun var of lit :: ′a literal ⇒ ′a wherevar 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 )by (cases l) auto
definition vars of clause :: ′a clause ⇒ ′a setwhere vars of clause C = var of lit ‘ C
definition vars of cnf :: ′a cnf ⇒ ′a set where vars of cnf F ≡⋃
(vars of clause‘F )
lemma vars of clause simps[simp]:vars of clause {} = {}vars of clause (insert l C ) = insert (var of lit l) (vars of clause C )vars of clause (C 1 ∪ C 2) = vars of clause C 1 ∪ vars of clause C 2
by (auto simp: vars of clause def )
lemma vars of cnf simps[simp]:vars of cnf {} = {}vars of cnf (insert C F ) = vars of clause C ∪ vars of cnf Fvars of cnf (F 1∪F 2) = vars of cnf F 1 ∪ vars of cnf F 2
by (auto simp: vars of cnf def )
lemma vars of clause empty iff [simp]: vars of clause C = {} ←→ C ={}by (auto simp: vars of clause def )
5
lemma vars of cnf empty iff [simp]: vars of cnf F = {} ←→ (F={} ∨ F={{}})by (auto simp: vars of cnf def )
lemma var of lit neg eq [simp]: var of lit (neg lit l) = var of lit l by (cases l) auto
lemma syn indep lit : x 6=var of lit l =⇒ sem lit l (σ(x :=v)) = sem lit l σby (cases l) auto
lemma syn indep clause: x /∈vars of clause C =⇒ sem clause C (σ(x :=v)) = sem clause C σunfolding sem clause def vars of clause defby (force simp: syn indep lit)
lemma syn indep cnf : x /∈vars of cnf F =⇒ sem cnf F (σ(x :=v)) = sem cnf F σunfolding sem cnf def vars of cnf defby (auto simp: syn indep clause)
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}) σunfolding sem clause defapply (cases l)apply safeapply (auto simp: sem lit alt split : literal .splits if split asm)done
lemma sem cnf set : sem cnf F (σ(var of lit l := is pos l)) ←→ sem cnf (set lit F l) σunfolding sem cnf def set lit def mk lit defby (auto simp: sem clause set)
lemma upd sigma true[simp]: σ x =⇒ σ(x :=True) = σ by (auto simp: fun upd def )lemma upd sigma false[simp]: ¬σ x =⇒ σ(x :=False) = σ by (auto simp: fun upd def )
lemma set lit no var : var of lit l /∈ vars of cnf (set lit F l)unfolding set lit def vars of cnf defby (auto simp: vars of clause def var of lit alt split : literal .splits)
lemmas indep set lit = syn indep cnf [OF set lit no var ]
end
3 Unit Propagation and RUP/RAT Checks
theory Unit Propagationimports SAT Basicbegin
This theory formalizes the basics of unit propagation and RUP/RAT redundancy checks.
3.1 Partial Assignments
primrec sem lit ′ :: ′a literal ⇒ ( ′a⇀bool) ⇀ bool wheresem lit ′ (Pos x ) A = A x| sem lit ′ (Neg x ) A = map option Not (A x )
definition sem clause ′ :: ′a literal set ⇒ ( ′a ⇀ bool) ⇀ bool wheresem clause ′ C A ≡
if ∃ l∈C . sem lit ′ l A = Some True then Some Trueelse if ∀ l∈C . sem lit ′ l A = Some False then Some Falseelse None
6
definition compat assignment :: ( ′a ⇀ bool) ⇒ ( ′a ⇒ bool) ⇒ boolwhere compat assignment A σ ≡ ∀ x v . A x = Some v −→ σ x = v
lemma sem neg lit ′[simp]:sem lit ′ (neg lit l) A = map option Not (sem lit ′ l A)by (cases l) (auto simp: option.map comp o def option.map ident)
lemma (in −) sem lit ′ empty [simp]: sem lit ′ l Map.empty = Noneby (cases l) auto
We install a custom case distinction rule for bool option, which has the cases undec, false, and true.
fun boolopt cases aux whereboolopt cases aux None = ()| boolopt cases aux (Some False) = ()| boolopt cases aux (Some True) = ()
lemma not Some bool if : [[ a 6=Some False; a 6=Some True ]] =⇒ a=Noneby (cases a) auto
Rules to trigger case distinctions on the semantics of a clause with a distinguished literal.
lemma sem clause insert eq complete:sem clause ′ (insert l C ) A = (case sem lit ′ l A of
Some True ⇒ Some True| Some False ⇒ sem clause ′ C A| None ⇒ (case sem clause ′ C A of
None ⇒ None| Some False ⇒ None| Some True ⇒ Some True))
by (auto simp: sem clause ′ def split : option.split bool .split)
lemma sem clause empty [simp]: sem clause ′ {} A = Some Falseunfolding sem clause ′ def by auto
lemma sem clause ′ insert true: sem clause ′ (insert l C ) A = Some True ←→sem lit ′ l A = Some True ∨ sem clause ′ C A = Some Trueby (auto simp: sem clause insert eq complete split : option.split bool .split)
lemma sem clause ′ insert false[simp]:sem clause ′ (insert l C ) A = Some False←→ sem lit ′ l A = Some False ∧ sem clause ′ C A = Some Falseunfolding sem clause ′ def by auto
lemma sem clause ′ union false[simp]:sem clause ′ (C1∪C2 ) A = Some False←→ sem clause ′ C1 A = Some False ∧ sem clause ′ C2 A = Some Falseunfolding sem clause ′ def by auto
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)unfolding assign lit def by auto
7
lemma assign lit dom[simp]:dom (assign lit A l) = insert (var of lit l) (dom A)unfolding assign lit def by auto
lemma sem lit assign[simp]: sem lit ′ l (assign lit A l) = Some Trueunfolding assign lit def by (cases l) auto
lemma sem lit ′ none conv : sem lit ′ l A = None ←→ A (var of lit l) = Noneby (cases l) auto
lemma assign undec pres dec lit :[[ sem lit ′ l A = None; sem lit ′ l ′ A = Some v ]]=⇒ sem lit ′ l ′ (assign lit A l) = Some vunfolding assign lit defapply (cases l)apply autoapply (cases l ′; auto)apply (cases l ′; clarsimp)done
lemma assign undec pres dec clause:[[ sem lit ′ l A = None; sem clause ′ C A = Some v ]]=⇒ sem clause ′ C (assign lit A l) = Some vunfolding sem clause ′ defby (force split : if split asm simp: assign undec pres dec lit)
lemma sem lit ′ assign conv : sem lit ′ l ′ (assign lit A l) = (if l ′=l then Some Trueelse if l ′=neg lit l then Some Falseelse sem lit ′ l ′ A)unfolding assign lit defby (cases l ; cases l ′; auto)
Predicates for unit clauses
definition is unit lit A C l≡ l∈C ∧ sem lit ′ l A = None ∧ (sem clause ′ (C−{l}) A = Some False)
definition is unit clause A C ≡ ∃ l . is unit lit A C ldefinition the unit lit A C ≡ THE l . is unit lit A C l
abbreviation (input) is conflict clause A C ≡ sem clause ′ C A = Some Falseabbreviation (input) is true clause A C ≡ sem clause ′ C A = Some True
lemma sem clause ′ false conv :sem clause ′ C A = Some False ←→ (∀ l∈C . sem lit ′ l A = Some False)unfolding sem clause ′ def by auto
lemma sem clause ′ true conv :sem clause ′ C A = Some True ←→ (∃ l∈C . sem lit ′ l A = Some True)unfolding sem clause ′ def by auto
lemma the unit lit eq [simp]: is unit lit A C l =⇒ the unit lit A C = lunfolding is unit lit def the unit lit def sem clause ′ false convby force
lemma is unit lit unique: [[is unit lit C A l1 ; is unit lit C A l2 ]] =⇒ l1=l2using the unit lit eq by blast
lemma is unit clauseE :assumes is unit clause A Cobtains l C ′ where
C =insert l C ′
l /∈C ′
sem lit ′ l A = None
8
sem clause ′ C ′ A = Some Falsethe unit lit A C = l
using assmsproof −
from assms obtain l where IUL: is unit lit A C lunfolding is unit clause def by blast
note [simp] = the unit lit eq [OF IUL]
from IULhave 1 : l∈C sem lit ′ l A = None sem clause ′ (C−{l}) A = Some Falseunfolding is unit lit def by blast+
show thesisapply (rule that [of l C−{l}])using 1by auto
qed
lemma is unit clauseE ′:assumes is unit clause A Cobtains l C ′ where
C =insert l C ′
l /∈C ′
sem lit ′ l A = Nonesem clause ′ C ′ A = Some False
by (rule is unit clauseE [OF assms])
lemma sem not false the unit lit :assumes is unit lit A C lassumes l ′∈Cassumes sem lit ′ l ′ A 6= Some Falseshows l ′=lby (metis assms insert Diff insert iff
is unit lit def sem clause ′ insert false)
lemma sem none the unit lit :assumes is unit lit A C lassumes l ′∈Cassumes sem lit ′ l ′ A = Noneshows l ′=lusing sem not false the unit lit [OF assms(1 ,2 )] assms(3 ) by auto
lemma is unit lit unique ss:[[C ′⊆C ; is unit lit A C ′ l ′; is unit lit A C l ]] =⇒ l ′=lby (simp add : is unit lit def sem none the unit lit subsetD)
lemma is unit litI :[[l∈C ; sem clause ′ (C−{l}) A = Some False; sem lit ′ l A = None]]=⇒ is unit lit A C lby (auto simp: is unit lit def )
lemma is unit clauseI : is unit lit A C l =⇒ is unit clause A Cby (auto simp: is unit clause def )
lemma unit other false:assumes is unit lit A C lassumes l ′∈C l 6=l ′
shows sem lit ′ l ′ A = Some Falseusing assms by (auto simp: is unit lit def sem clause ′ false conv)
lemma unit clause sem ′: is unit lit A C l =⇒ sem clause ′ C A = Noneunfolding is unit lit def sem clause ′ defusing mk disjoint insert by (fastforce split : if split asm)
9
lemma unit clause assign dec:is unit lit A C l =⇒ sem clause ′ C (assign lit A l) = Some Trueunfolding is unit lit def sem clause ′ defby (force split : if split asm simp: sem lit ′ assign conv)
lemma unit clause sem: is unit clause A C =⇒ sem clause ′ C A = Noneby (auto simp: is unit clause def unit clause sem ′)
lemma sem not unit clause: sem clause ′ C A 6= None =⇒ ¬is unit clause A Cby (auto simp: is unit clause def unit clause sem ′)
lemma unit contains no true:assumes is unit clause A Cassumes l∈Cshows sem lit ′ l A 6= Some Trueusing assms unfolding is unit clause def is unit lit defby (force simp: sem clause ′ false conv)
lemma two nfalse not unit :assumes l1∈C and l2∈C and l1 6=l2assumes sem lit ′ l1 A 6= Some False and sem lit ′ l2 A 6= Some Falseshows ¬is unit clause A Cusing assmsunfolding is unit clause def is unit lit defby (auto simp: sem clause ′ false conv)
lemma conflict clause assign indep:assumes sem clause ′ C (assign lit A l) = Some Falseassumes neg lit l /∈ Cshows sem clause ′ C A = Some Falseusing assmsby (auto simp: sem clause ′ def sem lit ′ assign conv split : if split asm)
lemma sem lit ′ assign undec conv :sem lit ′ l ′ (assign lit A l) = None←→ sem lit ′ l ′ A = None ∧ var of lit l 6= var of lit l ′
by (cases l ; cases l ′; auto)
lemma unit clause assign indep:assumes is unit clause (assign lit A l) Cassumes neg lit l /∈ Cshows is unit clause A Cusing assmsunfolding is unit clause def is unit lit defby (auto
dest !: conflict clause assign indepsimp: sem lit ′ assign undec conv)
lemma clause assign false cases[consumes 1 , case names no lit lit ]:assumes sem clause ′ C (assign lit A l) = Some Falseobtains neg lit l /∈ C sem clause ′ C A = Some False
| neg lit l ∈ C sem clause ′ (C−{neg lit l}) A = Some Falseproof (cases)
assume A: neg lit l ∈ Cwith assms have sem clause ′ (C−{neg lit l}) A = Some False
by (auto simp: sem clause ′ def sem lit ′ assign conv split : if split asm)with A show ?thesis by (rule that)
nextassume A: neg lit l /∈ Cwith assms have sem clause ′ C A = Some False
by (auto simp: sem clause ′ def sem lit ′ assign conv split : if split asm)with A show ?thesis by (rule that)
10
qed
lemma clause assign unit cases[consumes 1 , case names no lit lit ]:assumes is unit clause (assign lit A l) Cobtains neg lit l /∈ C is unit clause A C
| neg lit l ∈ Cproof (cases)
assume neg lit l ∈ C thus ?thesis by (rule that)next
assume A: neg lit l /∈ Cfrom assms obtain lu C ′ where
[simp]: C = insert lu C ′ lu /∈C ′
and LUN : sem lit ′ lu (assign lit A l) = Noneand SCF : sem clause ′ C ′ (assign lit A l) = Some Falseby (blast elim: is unit clauseE)
from clause assign false cases[OF SCF ] Ahave sem clause ′ C ′ A = Some False by automoreover from LUN have sem lit ′ lu A = None
by (simp add : sem lit ′ assign undec conv)ultimately have is unit clause A C
by (auto simp: is unit clause def is unit lit def )with A show ?thesis by (rule that)
qed
lemma sem clause ins assign not false[simp]:sem clause ′ (insert l C ) (assign lit A l) 6= Some Falseunfolding sem clause ′ def by auto
lemma sem clause ins assign not unit [simp]:¬is unit clause (assign lit A l) (insert l C ′)apply (clarsimp simp: is unit clause def is unit lit def sem lit ′ assign undec conv sem clause ′ false conv)apply forcedone
contextfixes A :: ′a ⇀ bool and σ :: ′a ⇒ boolassumes C : compat assignment A σ
beginlemma compat lit : sem lit ′ l A = Some v =⇒ sem lit l σ = v
using Cby (cases l) (auto simp: compat assignment def )
lemma compat clause: sem clause ′ C A = Some v =⇒ sem clause C σ = vunfolding sem clause def sem clause ′ defby (force simp: compat lit split : if split asm)
end
3.1.1 Models, Equivalence, and Redundancy
definition models ′ F A ≡ { σ. compat assignment A σ ∧ sem cnf F σ}definition sat ′ F A ≡ models ′ F A 6= {}definition equiv ′ F A A ′ ≡ models ′ F A = models ′ F A ′
Alternative definition of models’, which may be suited for presentation in paper.
lemma models ′ F A = models F ∩ Collect (compat assignment A)unfolding models ′ def models def by auto
lemma equiv ′ refl [simp]: equiv ′ F A A unfolding equiv ′ def by simplemma equiv ′ sym: equiv ′ F A A ′ =⇒ equiv ′ F A ′ A
unfolding equiv ′ def by simplemma equiv ′ trans[trans]: [[ equiv ′ F A B ; equiv ′ F B C ]] =⇒ equiv ′ F A C
unfolding equiv ′ def by simp
11
lemma models antimono: C ′⊆C =⇒ models ′ C A ⊆ models ′ C ′ Aunfolding models ′ def by (auto simp: sem cnf def )
lemma conflict clause imp no models:[[ C∈F ; is conflict clause A C ]] =⇒ models ′ F A = {}by (auto simp: models ′ def sem cnf def dest : compat clause)
lemma sat ′ empty iff [simp]: sat ′ F Map.empty = sat Funfolding sat ′ def sat def models ′ defby auto
lemma sat ′ antimono: F⊆F ′ =⇒ sat ′ F ′ A =⇒ sat ′ F Aunfolding sat ′ def using models antimono by blast
lemma sat ′ equiv : equiv ′ F A A ′ =⇒ sat ′ F A = sat ′ F A ′
unfolding equiv ′ def sat ′ def by blast
lemma sat iff sat ′: sat F ←→ (∃A. sat ′ F A)by (metis (no types, lifting) Collect empty eq models ′ def models def
sat ′ def sat ′ empty iff sat iff has models)
definition implied clause F A C ≡ models ′ (insert C F ) A = models ′ F Adefinition redundant clause F A C≡ (models ′ (insert C F ) A = {}) ←→ (models ′ F A = {})
lemma redundant clause alt : redundant clause F A C ←→ sat ′ (insert C F ) A = sat ′ F Aunfolding redundant clause def sat ′ def by blast
lemma redundant clauseI [intro? ]:assumes
∧σ. [[compat assignment A σ; sem cnf F σ]]
=⇒ ∃σ ′. compat assignment A σ ′ ∧ sem clause C σ ′ ∧ sem cnf F σ ′
shows redundant clause F A Cusing assms unfolding redundant clause def models ′ defby auto
lemma implied clauseI [intro? ]:assumes
∧σ. [[compat assignment A σ; sem cnf F σ]] =⇒ sem clause C σ
shows implied clause F A Cusing assms unfolding implied clause def models ′ defby auto
lemma implied is redundant : implied clause F A C =⇒ redundant clause F A Cunfolding implied clause def redundant clause def by blast
lemma add redundant sat iff [simp]:redundant clause F A C =⇒ sat ′ (insert C F ) A = sat ′ F Aunfolding redundant clause def sat ′ def by auto
lemma true clause implied :sem clause ′ C A = Some True =⇒ implied clause F A Cunfolding implied clause def models ′ defby (auto simp: compat clause)
lemma equiv ′ map empty sym:NO MATCH Map.empty A =⇒ equiv ′ F Map.empty A ←→ equiv ′ F A Map.emptyusing equiv ′ sym by auto
lemma tautology : [[l∈C ; neg lit l ∈ C ]] =⇒ sem clause C σ
12
by (cases sem lit l σ; cases l ; force simp: sem clause def )
lemma implied taut : [[l∈C ; neg lit l ∈ C ]] =⇒ implied clause F A Cunfolding implied clause def models ′ def using tautology [of l C ]by auto
definition is syn taut C ≡ C ∩ neg lit ‘ C 6= {}definition is blocked A C ≡ sem clause ′ C A = Some True ∨ is syn taut Clemma is blocked alt :
is blocked A C ←→ sem clause ′ C A = Some True ∨ C ∩ neg lit ‘ C 6= {}unfolding is syn taut def is blocked def by auto
lemma is syn taut empty [simp]: ¬is syn taut {}by (auto simp: is syn taut def )
lemma is syn taut conv : is syn taut C ←→ (∃ l . l∈C ∧ neg lit l ∈ C )unfolding is syn taut def by auto
lemma empty not blocked [simp]: ¬is blocked A {}unfolding is blocked alt by (auto simp: sem clause ′ true conv)
lemma is blocked insert iff :is blocked A (insert l C )←→ is blocked A C ∨ sem lit ′ l A = Some True ∨ neg lit l ∈ Cby (auto simp: is blocked alt sem clause ′ true conv)
lemma is blockedI1 : [[l∈C ; sem lit ′ l A = Some True]] =⇒ is blocked A Cby (auto simp: is blocked def sem clause ′ true conv)
lemma is blockedI2 : [[l∈C ; neg lit l ∈ C ]] =⇒ is blocked A Cby (auto simp: is blocked def is syn taut def )
lemma syn taut true[simp]: is syn taut C =⇒ sem clause C σ = Trueapply (auto simp: sem clause def is syn taut def )using sem neg lit by blast
lemma syn taut imp blocked : is syn taut C =⇒ is blocked A Cunfolding is blocked def by auto
lemma blocked redundant : is blocked A C =⇒ redundant clause F A Cunfolding is blocked altusing implied is redundant implied taut true clause implied by fastforce
lemma blocked clause true:[[is blocked A C ; compat assignment A σ]] =⇒ sem clause C σ
proof −assume a1 : compat assignment A σassume is blocked A Cthen have f2 : sem clause ′ C A = Some True ∨ C ∩ neg lit ‘ C 6= {}
by (simp add : is blocked alt)have f3 : ∀ l L p. ((l :: ′a literal) /∈ L ∨ neg lit l /∈ L) ∨ sem clause L p
by (simp add : tautology)have sem clause ′ C A = Some True −→ sem clause C σ
using a1 by (simp add : compat clause)then show ?thesis
using f3 f2 by fastforceqed
3.2 Unit Propagation
lemma unit propagation:assumes C∈F
13
assumes UNIT : is unit lit A C lshows equiv ′ F A (assign lit A l)unfolding equiv ′ def models ′ def
proof safefrom UNIT have l∈C
and UNDEC : sem lit ′ l A = Noneand OTHER FALSE ′: sem clause ′ (C−{l}) A = Some Falseunfolding is unit lit def by auto
{fix σassume COMPAT : compat assignment A σhave OTHER FALSE : sem clause (C−{l}) σ = False
using compat clause[OF COMPAT OTHER FALSE ′] .
assume sem cnf F σwith 〈C∈F 〉 〈l∈C 〉 OTHER FALSE have sem lit l σ
unfolding sem cnf def sem clause def by auto
with COMPAT show compat assignment (assign lit A l) σunfolding compat assignment defby (cases l) auto
}{
fix σassume compat assignment (assign lit A l) σwith UNDEC show compat assignment A σ
inductive-set prop unit R :: ′a cnf ⇒ (( ′a⇀bool) × ( ′a⇀bool)) set for Fwherestep: [[ 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 )by (auto
elim!: prop unit R.casessimp: is unit clause defdest : prop unit R.intros)
lemma prop unit R equiv :assumes (A,A ′)∈(prop unit R F )∗
shows equiv ′ F A A ′
using assmsapply inductionapply simpapply (erule prop unit R.cases)using equiv ′ trans unit propagation by blast
lemma wf prop unit R: finite F =⇒ wf ((prop unit R F )−1)apply (rule wf subset [OF
wf measure[where f =λA. card { C∈F . sem clause ′ C A = None }]])apply safeapply (erule prop unit R.cases)apply simpapply (rule psubset card mono)
14
subgoal by auto []apply safesubgoal
apply (auto simp: is unit lit def )apply (metis assign undec pres dec clause boolopt cases aux .cases)done
subgoal for C A lproof −
assume a1 : C ∈ Fassume a2 : is unit lit A C lassume a3 : {C ∈ F . sem clause ′ C (assign lit A l) = None}
= {C ∈ F . sem clause ′ C A = None}have sem clause ′ C A = None
using a2 by (metis unit clause sem ′)then show ?thesis
using a3 a2 a1 unit clause assign dec by forceqed
done
3.3 RUP and RAT Criteria
RAT-criterion to check for a redundant clause: Pick a resolution literal l from the clause, which is notassigned 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∈Cassumes NFALSE : sem lit ′ l A 6= Some Falseassumes CANDS : ∀D∈F . neg lit l ∈ D
−→ implied clause F A (C ∪ (D − {neg lit l}))shows redundant clause F A C
proof (cases is blocked A C )case True thus ?thesis using blocked redundant by blast
nextcase NBLOCKED : Falseshow ?thesisproof
fix σassume COMPAT : compat assignment A σ and MODELS : sem cnf F σshow ∃σ ′. compat assignment A σ ′ ∧ sem clause C σ ′ ∧ sem cnf F σ ′
proof (cases sem clause C σ)case True with COMPAT MODELS show ?thesis by blast
nextcase False
let ?σ ′ = σ(var of lit l := is pos l)from NFALSE COMPAT have compat assignment A ?σ ′
by (cases l) (auto simp: compat assignment def )moreover from LIC have sem clause C ?σ ′
unfolding sem clause def by (cases l ; force)moreover {
fix E assume E∈F neg lit l /∈ Ewith MODELS have sem clause E ?σ ′
unfolding sem cnf def sem clause defapply (cases l ; clarsimp)apply (metis sem lit .simps(1 ) syn indep lit
upd sigma true var of lit .elims)by (metis sem lit .simps(2 ) syn indep lit
upd sigma false var of lit .elims)} moreover {
fix D assume D∈F neg lit l ∈ Dwith CANDS have implied clause F A (C ∪ (D − {neg lit l})) by blastwith MODELS COMPAT have sem clause (C ∪ (D − {neg lit l})) σ
by (metis (no types, lifting) implied clause def
15
mem Collect eq models ′ def sem cnf insert)with False have sem clause (D − {neg lit l}) σ
by (auto simp: sem clause def )hence sem clause D ?σ ′ by (simp add : sem clause set)
} ultimately show ?thesis unfolding sem cnf def by blastqed
qedqed
lemma abs rat criterion ′:assumes RAT : ∃ l∈C .
sem lit ′ 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 Cusing assms abs rat criterion by blast
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 ) σby (smt SAT Basic.sem neg lit and not C def assms(1 ) assms(2 )
lemma and not empty [simp]: and not C A {} = Aunfolding and not C def by auto
lemma and not insert None: sem lit ′ l (and not C A C ) = None=⇒ and not C A (insert l C ) = assign lit (and not C A C ) (neg lit l)apply (cases l)apply (auto simp: and not C def split : if split asm)done
lemma and not insert False: sem lit ′ l (and not C A C ) = Some False=⇒ and not C A (insert l C ) = and not C A Capply (cases l)apply (auto simp: and not C def split : if split asm)done
lemma sem lit and not C conv : sem lit ′ l (and not C A C ) = Some v ←→ ((l /∈C ∧ neg lit l /∈C ∧ sem lit ′ 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)))by (cases l) (auto simp: and not C def )
lemma sem lit and not C None conv : sem lit ′ l (and not C A C ) = None ←→sem lit ′ l A = None ∧ l /∈C ∧ neg lit l /∈Cby (cases l) (auto simp: and not C def )
Check for implied clause by RUP: If the clause is not blocked, assign all literals of the clause to false, andsearch for an equivalent assignment (usually by unit-propagation), which has a conflict.
lemma one step implied :assumes RC : ¬is blocked A C =⇒∃A1. equiv ′ F (and not C A C ) A1 ∧ (∃E∈F . is conflict clause A1 E)
shows implied clause F A Cproof
fix σ
16
assume COMPAT : compat assignment A σassume MODELS : sem cnf F σ
show sem clause (C ) σproof (cases is blocked A C )
case Truethus ?thesis using blocked clause true COMPAT by auto
nextcase Falsefrom RC [OF False] obtain A1 E where
EQ : equiv ′ F (and not C A C ) A1
and CONFL: E ∈ F sem clause ′ E A1 = Some Falseby auto
show ?thesisproof (rule ccontr)
assume ¬sem clause C σwith compat and not C [OF COMPAT ]have compat assignment (and not C A C ) σ by autowith EQ have COMPAT1 : compat assignment A1 σ
with MODELS CONFL show False using compat clause sem cnf def by blastqed
qedqed
The unit-propagation steps of (¬ is blocked ?A ?C =⇒ ∃A1. equiv′ ?F (and not C ?A ?C ) A1 ∧ (∃E∈?F .
sem clause ′ E A1 = Some False)) =⇒ implied clause ?F ?A ?C can also be distributed over between theassignments of the negated literals. This is an optimization used for the RAT-check, where an initial set ofunit-propagations can be shared between all candidate checks.
lemma two step implied :assumes ¬is blocked A C
=⇒ ∃A1. equiv ′ F (and not C A C ) A1 ∧ (¬is blocked A1 D−→ (∃A2. equiv ′ F (and not C A1 D) A2 ∧ (∃E∈F . is conflict clause A2 E)))
shows implied clause F A (C∪D)proof
fix σassume COMPAT : compat assignment A σassume MODELS : sem cnf F σ
show sem clause (C∪D) σproof (cases is blocked A C )
case Truethus ?thesis using blocked clause true COMPAT by auto
nextcase Falsefrom assms[OF False] obtain A1 where
EQ1 : equiv ′ F (and not C A C ) A1
and RC2 : (¬is blocked A1 D−→ (∃A2. equiv ′ F (and not C A1 D) A2
∧ (∃E∈F . is conflict clause A2 E)))by auto
show ?thesisproof (rule ccontr ; clarsimp)
assume ¬sem clause C σ ¬sem clause D σwith compat and not C [OF COMPAT ]have compat assignment (and not C A C ) σ by autowith EQ1 have COMPAT1 : compat assignment A1 σ
from compat and not C [OF COMPAT1 ] 〈¬ sem clause D σ〉 have
17
1 : compat assignment (and not C A1 D) σ by autohave ¬is blocked A1 D
using COMPAT1 〈¬ sem clause D σ〉 blocked clause true by autowith RC2 obtain A2 E where
EQ2 : equiv ′ F (and not C A1 D) A2
and CONFL: E∈F is conflict clause A2 Eby auto
from EQ2 1 have COMPAT2 : compat assignment A2 σby (metis (mono tags, lifting) MODELS equiv ′ def
mem Collect eq models ′ def )with MODELS CONFL show False using compat clause sem cnf def by blast
qedqed
qed
3.4 Old assign all negated Formulation
definition assign all negated A C ≡ let UD = {l∈C . sem lit ′ l A = None} inA ++ (λl . if Pos l∈UD then Some False
else if Neg l ∈ UD then Some Trueelse None)
lemma abs rup criterion:assumes models ′ F (assign all negated A C ) = {}shows implied clause F A Cusing assmsunfolding models ′ def implied clause defapply (safe; simp)
proof (rule ccontr)fix σassume COMPAT : compat assignment A σassume S : sem cnf F σassume CD : ∀σ. compat assignment (assign all negated A C ) σ
−→ ¬ sem cnf F σassume NS : ¬ sem clause C σ
from NS have ∀ l∈C . sem lit l σ = False by (auto simp: sem clause def )
with COMPAT have compat assignment (assign all negated A C ) σby (clarsimp simp: compat assignment def assign all negated def
split : if split asm) autowith S CD show False by blast
qed
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 ′ l (assign all negated A C ) = Some vobtains sem lit ′ l A = Some v
| sem lit ′ l A = None neg lit l ∈ C v=True| sem lit ′ l A = None l ∈ C v=False
using assms unfolding assign all negated defapply (cases l)apply (auto simp: map add def split : if split asm)done
lemma sem lit assign all negated none iff :sem lit ′ l (assign all negated A C ) = None←→ (sem lit ′ l A = None ∧ l /∈C ∧ neg lit l /∈ C )unfolding assign all negated defapply (cases l)apply (auto simp: map add def split : if split asm)done
18
lemma sem lit assign all negated pres decided :assumes sem lit ′ l A = Some vshows sem lit ′ l (assign all negated A C ) = Some vusing assms unfolding assign all negated defapply (cases l)apply (fastforce simp: map add def split : if split asm)+done
lemma sem lit assign all negated assign:assumes ∀ l∈C . neg lit l /∈C l ∈ C sem lit ′ l A = Noneshows sem lit ′ l (assign all negated A C ) = Some Falseusing assms unfolding assign all negated defapply (cases l)apply (auto simp: map add def split : if split asm)done
lemma sem lit assign all negated neqv :sem lit ′ l (assign all negated A C ) 6= Some v =⇒ sem lit ′ l A 6= Some vby (auto simp: sem lit assign all negated pres decided)
lemma aan idem[simp]:assign all negated (assign all negated A C ) C = assign all negated A Cby (auto intro!: ext simp: assign all negated def map add def )
lemma aan dbl :assumes ∀ l∈C∪C ′. neg lit l /∈ C∪C ′
shows assign all negated (assign all negated A C ) C ′
= assign all negated A (C∪C ′)using assms by (force intro!: ext simp: assign all negated def map add def )
lemma aan mono2 :[[C⊆C ′; ∀ l∈C ′. neg lit l /∈ C ′]]=⇒ assign all negated A C ⊆m assign all negated A C ′
by (auto simp: assign all negated def map add def map le def )
lemma aan empty [simp]: assign all negated A {} = Aby (auto simp: assign all negated def )
lemma aan restrict :assign all negated A C |‘ (− var of lit ‘ {l ∈ C . sem lit ′ l A = None}) = Aapply (rule ext)unfolding assign all negated defapply (clarsimp simp: map add def restrict map def ; safe)apply simp allapply forceapply forcesubgoal for l by (cases l) autosubgoal for l v by (cases l) autosubgoal for v l by (cases l) autosubgoal for v l by (cases l) autodone
lemma aan insert :assumes ∀ l ′∈C . sem lit ′ l ′ A 6= Some True ∧ neg lit l ′ /∈ Cassumes sem lit ′ l A 6= Some True ∧ neg lit l /∈ Cshows assign lit (assign all negated A C ) (neg lit l)
= assign all negated A (insert l C )apply (rule ext)using assmsapply (cases l)apply (auto simp: assign all negated def map add def )done
19
lemma aan insert set :assumes sem lit ′ l A 6= Noneshows assign all negated A (insert l C ) = assign all negated A Capply (rule ext)using assmsapply (cases l)apply (auto simp: assign all negated def map add def )done
Insertion into distinct list, where the inserted element is either the head of the list, or not contained into thelist. Useful to avoid duplicate insertions into the literal-¿clause map.
definition mbhd invar x l ≡ distinct l ∧ x /∈set (tl l)definition (in −) mbhd insert x l ≡ if l=[] then [x ] else if (x = hd l) then l else x#l
lemma mbhd insert invar : mbhd invar x l =⇒ mbhd invar x (mbhd insert x l)unfolding mbhd invar def mbhd insert def by (cases l) auto
lemma mbhd insert correct : set (mbhd insert x l) = insert x (set l)unfolding mbhd insert def by auto
lemma mbhd invar init : distinct l ∧ x /∈set l =⇒ mbhd invar x lunfolding mbhd invar def by (cases l) auto
lemma mbhd invar exit : mbhd invar x l =⇒ distinct lunfolding mbhd invar def by (cases l) auto
end
4 Exception Monad for Refine-Monadic
theory Exc Nres Monadimports Refine Monadic.Refine Monadic DRAT Miscbegin
declare TrueI [refine vcg ]
type-synonym ( ′e, ′a) enres = ( ′e + ′a) nres
named-theorems enres unfolds 〈Unfolding theorems from enres to nres〉
lemma pw ERETURN [simp, refine pw simps]:nofail (ERETURN x )¬inres (ERETURN x ) (Inl e)inres (ERETURN x ) (Inr y) ←→ x=yunfolding enres unfoldsby auto
lemma pw ebind [refine pw simps]:nofail (ebind m f ) ←→ nofail m ∧ (∀ x . inres m (Inr x ) −→ nofail (f x ))inres (ebind m f ) (Inl e) ←→ inres m (Inl e) ∨ (∃ x . inres m (Inr x ) ∧ inres (f x ) (Inl e))inres (ebind m f ) (Inr x ) ←→ nofail m −→ (∃ y . inres m (Inr y) ∧ inres (f y) (Inr x ))unfolding enres unfoldsapply (auto simp: refine pw simps split : sum.split)using sum.exhaust sel apply blastusing sum.exhaust sel apply blastdone
lemma pw THROW [simp,refine pw simps]:nofail (THROW e)inres (THROW e) (Inl f ) ←→ f =e¬inres (THROW e) (Inr x )unfolding enres unfoldsby (auto simp: refine pw simps)
lemma pw ele iff : m ≤ n ←→ (nofail n −→nofail m∧ (∀ e. inres m (Inl e) −→ inres n (Inl e))∧ (∀ x . inres m (Inr x ) −→ inres n (Inr x )))apply (auto simp: pw le iff )by (metis sum.exhaust sel)
lemma pw eeq iff : m = n ←→(nofail m ←→ nofail n)∧ (∀ e. inres m (Inl e) ←→ inres n (Inl e))∧ (∀ x . inres m (Inr x ) ←→ inres n (Inr x ))
lemma enres monad laws[simp]:ebind (ERETURN x ) f = f xebind m (ERETURN ) = mebind (ebind m f ) g = ebind m (λx . ebind (f x ) g)by (auto simp: pw eeq iff refine pw simps)
=⇒ case option S1 f2 v ≤ ESPEC Φ Ψby (auto split : option.split)
lemma eLet rule[refine vcg ]: f v ≤ ESPEC Φ Ψ =⇒ (let x=v in f x ) ≤ ESPEC Φ Ψ by simp
lemma eLet rule ′:assumes
∧x . x=v =⇒ f x ≤ ESPEC Φ Ψ
shows Let v (λx . f x ) ≤ ESPEC Φ Ψusing assms by simp
definition [enres unfolds]: EWHILEIT I c f s ≡ WHILEIT(λInl ⇒ True | Inr s ⇒ I s)(λInl ⇒ False | Inr s ⇒ c s)(λs. ASSERT (¬isl s) >> (let s = projr s in f s))(Inr s)
lemma EWHILEIT rule[refine vcg ]:assumes WF : wf R
and I0 : I s0
and IS :∧
s. [[I s; b s; (s,s0)∈R∗]] =⇒ f s ≤ ESPEC E (λs ′. I s ′ ∧ (s ′, s) ∈ R)and IMP :
∧s. [[I s; ¬ b s; (s,s0)∈R∗]] =⇒ Φ s
shows EWHILEIT I b f s0 ≤ ESPEC E Φunfolding EWHILEIT def ESPEC defapply (rule order trans[OF WHILEIT weaken[where I =λInl e ⇒ E e | Inr s ⇒ I s ∧ (s,s0)∈R∗]])apply (auto split : sum.splits) []apply (rule WHILEIT rule[where R=inv image (less than <∗lex∗> R) (λInl e ⇒ (0 ,undefined) | Inr s ⇒ (1 ,s))])subgoal using WF by autosubgoal using I0 by autosubgoal
apply (clarsimp split : sum.splits simp: ESPEC def )apply (rule order trans[OF IS ])apply (auto simp: ESPEC def )done
subgoal using IMP by (auto split : sum.splits)done
lemma EWHILET rule:assumes WF : wf R
and I0 : I s0
and IS :∧
s. [[I s; b s; (s,s0)∈R∗]] =⇒ f s ≤ ESPEC E (λs ′. I s ′ ∧ (s ′, s) ∈ R)and IMP :
∧s. [[I s; ¬ b s; (s,s0)∈R∗]] =⇒ Φ s
shows EWHILET b f s0 ≤ ESPEC E Φunfolding EWHILET def EWHILEIT def ESPEC defapply (rule order trans[OF WHILEIT weaken[where I =λInl e ⇒ E e | Inr s ⇒ I s ∧ (s,s0)∈R∗]])apply (auto split : sum.splits) []apply (rule WHILEIT rule[where R=inv image (less than <∗lex∗> R) (λInl e ⇒ (0 ,undefined) | Inr s ⇒ (1 ,s))])
24
subgoal using WF by autosubgoal using I0 by autosubgoal
apply (clarsimp split : sum.splits simp: ESPEC def )apply (rule order trans[OF IS ])apply (auto simp: ESPEC def )done
subgoal using IMP by (auto split : sum.splits)done
lemma EWHILEIT weaken:assumes
∧x . I x =⇒ I ′ x
shows EWHILEIT I ′ b f x ≤ EWHILEIT I b f xunfolding enres unfoldsapply (rule WHILEIT weaken)using assms by (auto split : sum.split)
Explicitly specify a different invariant.
lemma EWHILEIT expinv rule:assumes WF : wf R
and I0 : I s0
and IS :∧
s. [[I s; b s; (s,s0)∈R∗]] =⇒ f s ≤ ESPEC E (λs ′. I s ′ ∧ (s ′, s) ∈ R)and IMP :
∧s. [[I s; ¬ b s; (s,s0)∈R∗]] =⇒ Φ s
and INVIMP :∧
s. I s =⇒ I ′ sshows EWHILEIT I ′ b f s0 ≤ ESPEC E Φapply (rule order trans[OF EWHILEIT weaken])using INVIMP apply assumptionapply (rule EWHILEIT rule; fact+)done
definition [enres unfolds]: enfoldli l c f s ≡nfoldli l (λInl e⇒False | Inr x ⇒ c x ) (λx s. do {ASSERT (¬isl s); let s=projr s; f x s}) (Inr s)
lemma enfoldli simps[simp]:enfoldli [] c f s = ERETURN senfoldli (x#ls) c f s =
(if c s then doE { s←f x s; enfoldli ls c f s} else ERETURN s)unfolding enres unfoldsby (auto split : sum.split intro!: arg cong [where f = Refine Basic.bind ] ext)
lemma enfoldli rule:assumes I0 : I [] l0 σ0assumes IS :
∧x l1 l2 σ. [[ l0=l1@x#l2 ; I l1 (x#l2 ) σ; c σ ]] =⇒ f x σ ≤ ESPEC E (I (l1@[x ]) l2 )
assumes FNC :∧
l1 l2 σ. [[ l0=l1@l2 ; I l1 l2 σ; ¬c σ ]] =⇒ P σassumes FC :
∧σ. [[ I l0 [] σ; c σ ]] =⇒ P σ
shows enfoldli l0 c f σ0 ≤ ESPEC E Punfolding enfoldli def ESPEC defapply (rule nfoldli rule[where I =λl1 l2 . λInl e ⇒ E e | Inr σ ⇒ I l1 l2 σ])subgoal by (auto simp: I0 )subgoal
apply (simp split : sum.splits)apply (erule (2 ) order trans[OF IS ])apply (auto simp: ESPEC def )done
subgoal using FNC by (auto split : sum.split)subgoal using FC by (auto split : sum.split)done
4.1 Data Refinement
lemma sum rel conv :(Inl l , s ′) ∈ 〈L,R〉sum rel ←→ (∃ l ′. s ′=Inl l ′ ∧ (l ,l ′)∈L)(Inr r , s ′) ∈ 〈L,R〉sum rel ←→ (∃ r ′. s ′=Inr r ′ ∧ (r ,r ′)∈R)
25
(s, Inl l ′) ∈ 〈L,R〉sum rel ←→ (∃ l . s=Inl l ∧ (l ,l ′)∈L)(s, Inr r ′) ∈ 〈L,R〉sum rel ←→ (∃ r . s=Inr r ∧ (r ,r ′)∈R)(∀ l . s 6= Inl l) ←→ (∃ r . s=Inr r)(∀ r . s 6= Inr r) ←→ (∃ l . s=Inl l)apply −subgoal by (cases s ′; auto)subgoal by (cases s ′; auto)subgoal by (cases s; auto)subgoal by (cases s; auto)subgoal by (cases s; auto)subgoal by (cases s; auto)done
definition econc fun (⇓E) where [enres unfolds]: econc fun E R ≡ ⇓(〈E ,R〉sum rel)
lemma RELATES pat erefine[refine dref pattern]: [[RELATES R; mi ≤⇓E E R m ]] =⇒ mi ≤⇓E E R m .
lemma pw econc iff [refine pw simps]:inres (⇓E E R m) (Inl ei) ←→ (nofail m −→ (∃ e. inres m (Inl e) ∧ (ei ,e)∈E))inres (⇓E E R m) (Inr xi) ←→ (nofail m −→ (∃ x . inres m (Inr x ) ∧ (xi ,x )∈R))nofail (⇓E E R m) ←→ nofail mby (auto simp: refine pw simps econc fun def sum rel conv)
lemma econc fun id [simp]: ⇓E Id Id = (λx . x )by (auto simp: pw eeq iff refine pw simps intro!: ext)
lemma econc fun ESPEC : ⇓E E R (ESPEC Φ Ψ) = ESPEC (λei . ∃ e. (ei ,e)∈E ∧ Φ e) (λri . ∃ r . (ri ,r)∈R ∧ Ψ r)by (auto simp: pw eeq iff refine pw simps)
lemma econc fun ERETURN : ⇓E E R (ERETURN x ) = ESPEC (λ . False) (λxi . (xi ,x )∈R)by (auto simp: pw eeq iff refine pw simps)
lemma econc fun univ id [simp]: ⇓E UNIV Id (ESPEC Φ Ψ) = ESPEC (λ . Ex Φ) Ψby (auto simp: pw eeq iff refine pw simps)
lemma erefine same sup Id [simp]: [[ Id⊆E ; Id⊆R ]] =⇒ m ≤⇓E E R m by (auto simp: pw ele iff refine pw simps)
lemma econc mono3 : m≤m ′ =⇒ ⇓E E R m ≤ ⇓E E R m ′
by (auto simp: pw ele iff refine pw simps)
lemma econc x trans[trans]:x ≤ ⇓E E R y =⇒ y ≤ z =⇒ x ≤ ⇓E E R zby (force simp: pw ele iff refine pw simps)
lemma econc econc trans[trans]:x ≤⇓E E1 R1 y =⇒ y ≤ ⇓E E2 R2 z =⇒ x ≤ ⇓E (E1 O E2 ) (R1 O R2 ) zby (force simp: pw ele iff refine pw simps)
lemma ERETURN refine[refine]:assumes (xi ,x )∈Rshows ERETURN xi ≤ ⇓EE R (ERETURN x )using assmsby (auto simp: pw ele iff refine pw simps)
lemma EASSERT bind refine right :assumes Φ =⇒ mi ≤⇓E E R mshows mi ≤⇓E E R (doE {EASSERT Φ; m})using assmsby (simp add : pw ele iff refine pw simps)
lemma EASSERT bind refine left :
26
assumes Φassumes mi ≤⇓E E R mshows (doE {EASSERT Φ; mi}) ≤⇓E E R musing assmsby simp
lemma EASSUME bind refine right :assumes Φassumes mi ≤⇓E E R mshows mi ≤⇓E E R (doE {EASSUME Φ; m})using assmsby (simp)
lemma EASSUME bind refine left :assumes Φ =⇒ mi ≤⇓E E R mshows (doE {EASSUME Φ; mi}) ≤⇓E E R musing assmsby (simp add : pw ele iff refine pw simps)
lemma ebind refine:assumes mi ≤⇓E E R ′ massumes
∧xi x . (xi ,x )∈R ′ =⇒ fi xi ≤⇓E E R (f x )
shows doE { xi ← mi ; fi xi } ≤ ⇓E E R (doE { x ← m; f x })using assmsby (simp add : pw ele iff refine pw simps) blast
Order of this lemmas matters!
lemmas [refine] =ebind refineEASSERT bind refine left EASSUME bind refine rightEASSUME bind refine left EASSERT bind refine right
thm refine(1−10 )
lemma ebind refine ′:assumes mi ≤⇓E E R ′ massumes
∧xi x . [[(xi ,x )∈R ′; inres mi (Inr xi); inres m (Inr x ); nofail mi ; nofail m]] =⇒ fi xi ≤⇓E E R (f x )
shows doE { xi ← mi ; fi xi } ≤ ⇓E E R (doE { x ← m; f x })using assmsby (simp add : pw ele iff refine pw simps) blast
lemma THROW refine[refine]: (ei ,e)∈E =⇒ THROW ei ≤⇓E E R (THROW e)by (auto simp: pw ele iff refine pw simps)
lemma CHECK refine[refine]:assumes Φi ←→ Φassumes ¬Φ =⇒ (msgi ,msg)∈Eshows CHECK Φi msgi ≤⇓E E Id (CHECK Φ msg)using assms by (auto simp: pw ele iff refine pw simps)
This must be declared after [[?Φi = ?Φ; ¬ ?Φ =⇒ (?msgi , ?msg) ∈ ?E ]] =⇒ CHECK ?Φi ?msgi ≤ ⇓E ?Eunit rel (CHECK ?Φ ?msg)!
lemma CHECK bind refine[refine]:assumes Φi ←→ Φassumes ¬Φ =⇒ (msgi ,msg)∈Eassumes Φ =⇒ mi ≤⇓E E R mshows doE {CHECK Φi msgi ;mi} ≤⇓E E R (doE {CHECK Φ msg ; m})using assms by (auto simp: pw ele iff refine pw simps)
lemma Let unfold refine[refine]:assumes f x ≤ ⇓E E R (f ′ x ′)shows Let x f ≤ ⇓E E R (Let x ′ f ′)using assms by auto
27
lemma Let refine:assumes (m,m ′)∈R ′
assumes∧
x x ′. (x ,x ′)∈R ′ =⇒ f x ≤ ⇓E E R (f ′ x ′)shows Let m (λx . f x ) ≤⇓E E R (Let m ′ (λx ′. f ′ x ′))using assms by auto
lemma eif refine[refine]:assumes (b,b ′)∈bool relassumes [[b;b ′]] =⇒ S1 ≤ ⇓E E R S1 ′
assumes [[¬b;¬b ′]] =⇒ S2 ≤ ⇓E E R S2 ′
shows (if b then S1 else S2 ) ≤ ⇓E E R (if b ′ then S1 ′ else S2 ′)using assms by auto
lemma enfoldli refine[refine]:assumes (li , l) ∈ 〈S〉list rel
and (si , s) ∈ Rand CR: (ci , c) ∈ R → bool reland FR:
∧xi x si s. [[ (xi ,x )∈S ; (si ,s)∈R; c s ]] =⇒ fi xi si ≤ ⇓E E R (f x s)
shows enfoldli li ci fi si ≤ ⇓E E R (enfoldli l c f s)unfolding enres unfoldsapply (rule nfoldli refine)apply (rule assms(1 ))apply (simp add : assms(2 ))subgoal using CR[param fo] by (auto split : sum.split simp: sum rel conv)subgoal
assumes STEP REF :∧x x ′. [[ (x ,x ′)∈R; b x ; b ′ x ′ ]] =⇒ f x ≤ ⇓E E R (f ′ x ′)
shows EWHILET b f x ≤⇓E E R (EWHILET b ′ f ′ x ′)unfolding enres unfoldsapply refine rcgusing assmsby (auto split : sum.splits simp: econc fun def )
thm WHILEIT refine
lemma EWHILEIT refine[refine]:assumes R0 : I ′ x ′ =⇒ (x ,x ′)∈Rassumes I REF :
∧x x ′. [[ (x ,x ′)∈R; I ′ x ′ ]] =⇒ I x
assumes COND REF :∧
x x ′. [[ (x ,x ′)∈R; I x ; I ′ x ′ ]] =⇒ b x = b ′ x ′
assumes STEP REF :∧x x ′. [[ (x ,x ′)∈R; b x ; b ′ x ′; I x ; I ′ x ′ ]] =⇒ f x ≤ ⇓E E R (f ′ x ′)
shows EWHILEIT I b f x ≤⇓E E R (EWHILEIT I ′ b ′ f ′ x ′)unfolding enres unfoldsapply refine rcgusing assmsby (auto split : sum.splits simp: econc fun def )
4.1.1 Refine2- heuristics
lemma remove eLet refine:
28
assumes M ≤ ⇓E E R (f x )shows M ≤ ⇓E E R (Let x f ) using assms by auto
lemma intro eLet refine:assumes f x ≤ ⇓E E R M ′
shows Let x f ≤ ⇓E E R M ′ using assms by auto
lemma ebind2let refine[refine2 ]:assumes ERETURN x ≤ ⇓E E R ′ M ′
assumes∧
x ′. (x ,x ′)∈R ′ =⇒ f x ≤ ⇓E E R (f ′ x ′)shows Let x f ≤ ⇓E E R (ebind M ′ (λx ′. f ′ x ′))using assmsapply (simp add : pw ele iff refine pw simps)apply fastdone
lemma ebind Let refine2 [refine2 ]: [[m ′ ≤⇓E E R ′ (ERETURN x );∧
x ′. [[inres m ′ (Inr x ′); (x ′,x )∈R ′]] =⇒ f ′ x ′ ≤ ⇓E E R (f x )]] =⇒ ebind m ′ (λx ′. f ′ x ′) ≤ ⇓E E R (Let x (λx . f x ))apply (simp add : pw ele iff refine pw simps)apply blastdone
lemma ebind2letRETURN refine[refine2 ]:assumes ERETURN x ≤ ⇓E E R ′ M ′
assumes∧
x ′. (x ,x ′)∈R ′ =⇒ ERETURN (f x ) ≤ ⇓E E R (f ′ x ′)shows ERETURN (Let x f ) ≤ ⇓E E R (ebind M ′ (λx ′. f ′ x ′))using assmsapply (simp add : pw ele iff refine pw simps)apply fastdone
lemma ERETURN as SPEC refine[refine2 ]:assumes RELATES Rassumes M ≤ ESPEC (λ . False) (λc. (c,a)∈R)shows M ≤ ⇓E E R (ERETURN a)using assmsby (simp add : pw ele iff refine pw simps)
lemma if ERETURN refine[refine2 ]:assumes b ←→ b ′
assumes [[b;b ′]] =⇒ ERETURN S1 ≤ ⇓E E R S1 ′
assumes [[¬b;¬b ′]] =⇒ ERETURN S2 ≤ ⇓E E R S2 ′
shows ERETURN (if b then S1 else S2 ) ≤ ⇓E E R (if b ′ then S1 ′ else S2 ′)
using assmsby (simp add : pw le iff refine pw simps)
Breaking down enres-monad
definition enres lift :: ′a nres ⇒ ( , ′a) enres whereenres lift m ≡ do { x ← m; RETURN (Inr x ) }
lemma enres lift rule[refine vcg ]: m≤SPEC Φ =⇒ enres lift m ≤ ESPEC E Φby (auto simp: pw ele iff pw le iff refine pw simps enres lift def )
lemma [enres breakdown]:do { x ← m; enres lift (f x ) } = enres lift (do { x ← m; f x })do { let x = v ; enres lift (f x ) } = enres lift (do { let x=v ; f x })unfolding enres unfolds enres lift defapply (auto split : sum.splits simp: pw eq iff refine pw simps)done
lemma enres lift fail [simp]: enres lift FAIL = FAILunfolding enres lift def by auto
lemma [enres breakdown]: EWHILEIT I c (λs. enres lift (f s)) s = enres lift (WHILEIT I c f s)(is ?lhs = ?rhs)
proof (rule antisym)show ?lhs ≤ ?rhs
unfolding enres unfolds WHILEIT def WHILET defapply (rule RECT transfer rel ′[where P=λc a. c = Inr a])apply (simp add : while.WHILEI body trimono)apply (simp add : while.WHILEI body trimono)apply simpapply simpby (auto simp: WHILEI body def enres lift def pw le iff refine pw simps)
show ?rhs ≤ ?lhsunfolding enres unfolds WHILEIT def WHILET defapply (rule RECT transfer rel ′[where P=λa c. c = Inr a])apply (simp add : while.WHILEI body trimono)apply (simp add : while.WHILEI body trimono)apply simpapply simpby (auto simp: WHILEI body def enres lift def pw le iff refine pw simps)
qed
lemma [enres breakdown]: EWHILET c (λs. enres lift (f s)) s = enres lift (WHILET c f s)unfolding EWHILET def WHILET def enres breakdown ..
lemma [enres breakdown]: enfoldli l c (λx s. enres lift (f x s)) s = enres lift (nfoldli l c f s)apply (induction l arbitrary : s)by (auto simp: enres breakdown)
lemma [enres breakdown]:(λ(a,b). enres lift (f a b)) = (λx . enres lift (case x of (a,b) ⇒ f a b)) by auto
lemmas [enres breakdown] = nres monad laws nres bind let law
lemma [enres breakdown]:doE { CHECK Φ e; m } = (if Φ then m else THROW e)by (auto simp: enres unfolds)
lemma [enres breakdown]: (if b then enres lift m else enres lift n) = enres lift (if b then m else n)by simp
definition [enres unfolds]: CHECK monadic c e ≡ doE { b ← c; CHECK b e }
lemma CHECK monadic rule iff :(CHECK monadic c e ≤ ESPEC E P) ←→ (c ≤ ESPEC E (λr . (r −→ P ()) ∧ (¬r −→ E e)))by (auto simp: pw ele iff CHECK monadic def refine pw simps)
lemma CHECK monadic pw [refine pw simps]:nofail (CHECK monadic c e) ←→ nofail cinres (CHECK monadic c e) (Inl ee) ←→ (inres c (Inl ee) ∨ inres c (Inr False) ∧ ee=e)inres (CHECK monadic c e) (Inr x ) ←→ (inres c (Inr True))unfolding CHECK monadic defby (auto simp: refine pw simps)
lemma CHECK monadic rule[refine vcg ]:assumes c ≤ ESPEC E (λr . (r −→ P ()) ∧ (¬r −→ E e))shows CHECK monadic c e ≤ ESPEC E Pusing assms by (simp add : CHECK monadic rule iff )
lemma CHECK monadic refine[refine]:assumes ci ≤ ⇓E ER bool rel cassumes (ei ,e)∈ERshows CHECK monadic ci ei ≤⇓E ER unit rel (CHECK monadic c e)using assmsby (auto simp: pw ele iff refine pw simps)
lemma CHECK monadic CHECK refine[refine]:assumes ci ≤ ESPEC (λe ′. (e ′,e)∈ER ∧ ¬c) (λr . r ←→ c)assumes (ei ,e)∈ERshows CHECK monadic ci ei ≤⇓E ER unit rel (CHECK c e)using assmsby (auto simp: pw ele iff refine pw simps)
lemma CHECK monadic endb[enres breakdown]: CHECK monadic (enres lift c) e =do {b ← c; CHECK b e}by (auto simp: enres unfolds enres lift def )
Provides the command synth definition, which proves a schematic goal with a hole, and definesthe hole as a constant .∗)structure Synth Definition = struct
fun prep term t = letval nidx = maxidx of term t + 1
val t = map aterms (fn@{mpat (typs) ◊::? ′v T} => Var ((HOLE ,nidx ),T )| v as Var ((name, ),T ) => if String .isPrefix name then v else Var (( ˆname,nidx ),T )| t => t
) t|> Term Subst .zero var indexes
int
end
fun sd cmd (((name,attribs raw),attribs2 raw),t raw) lthy = letlocal
lemma array set dyn rule[sep heap rules]:< is nff dflt f a >
array set dyn dflt a i v<λr . is nff dflt (f (i :=v)) r >t
unfolding array set dyn def is nff def upd oo defby (sep auto simp: nff α upd nff α append default)
end
6 Options and Maps with Default Value for None
theory Array Map Defaultimports Dynamic Array DRAT Miscbegin
Implements maps from natural numbers to any value type that has an unused default value in its implemen-tation type. Internally, uses a dynamic array.
definition is unused elem dflt A ≡ ∀ x . A x dflt = falselemma is unused elem pure[simp]:
is unused elem dflt (pure R) ←→ dflt /∈ Domain Runfolding is unused elem defby (auto simp: pure rel eq false iff )
definition dflt option rel aux dflt≡ { (dflt ,None) } ∪ { (x , Some x ) | x . x 6=dflt }
definition [to relAPP ]: dflt option assn dflt A≡ pure (dflt option rel aux dflt O 〈the pure A〉option rel)
34
6.1 Function-Level Map Operations
We justify the map operations implemented by a function
lemma amd1 empty refine:(uncurry0 (λ . dflt), uncurry0 op map empty)∈ Id →f (Id → dflt option rel aux dflt)by (auto simp: dflt option rel aux def fref def )
lemma amd1 lookup refine:(λx f . f x , op map lookup)∈ Id → (Id → dflt option rel aux dflt) → dflt option rel aux dfltapply simp by parametricity
lemma amd1 update refine:(uncurry2 (λk v f . f (k :=v)), uncurry2 op map update)∈ [λ((k ,v),m). v 6=dflt ]f
((Id ×r Id) ×r (Id → dflt option rel aux dflt))→ (Id → dflt option rel aux dflt)
unfolding op map update defapply (rule frefI )apply autoapplyS (auto simp: dflt option rel aux def )applyS (parametricity ; simp)done
definition [simp]: amd1 delete dflt k f ≡ fun upd f k dfltlemma amd1 delete refine:
(uncurry (amd1 delete dflt), uncurry op map delete)∈ Id ×r (Id → dflt option rel aux dflt) →f (Id → dflt option rel aux dflt)unfolding op map delete def PR CONST def amd1 delete defapply (rule frefI )apply parametricityapply (auto simp: dflt option rel aux def )done
6.2 Map Operations, array-level
We use dynamic arrays to implement the function, and combine both to implement the map interface.
definition [code unfold ]: amd empty dflt ≡ dyn array new sz dflt 16definition [code unfold ]: amd lookup dflt k a ≡ array get dyn dflt a kdefinition [code unfold ]: amd update dflt k v a ≡ array set dyn dflt a k vdefinition [code unfold ]: amd delete dflt k a ≡ array set dyn dflt a k dflt
definition amd assn dflt K V≡ hr comp (hr comp
(is nff dflt)(nat rel →f dflt option rel aux dflt))(〈the pure K , the pure V 〉map rel)
lemma amd assn fold2 : hr comp (hr comp(is nff dflt)(nat rel → dflt option rel aux dflt))(〈the pure K , the pure V 〉map rel)
= amd assn dflt K Vunfolding amd assn defapply (fo rule fun cong arg cong)+unfolding fref def fun rel def by auto
lemmas [intf of assn]= intf of assnI [where R=amd assn dflt K V
and ′a=(nat , ′vv) i map for dflt K V ]
35
lemmas [safe constraint rules]= CN FALSEI [of is pure amd assn dflt K V for dflt K V ]
(uncurry0 (amd empty dflt), uncurry0 (RETURN (λ . dflt)))∈ unit assnk →a is nff dfltby (sep auto simp: amd empty def )
lemma amd2 lookup refine:(uncurry (amd lookup dflt), uncurry (RETURN oo (λx f . f x )))∈ id assnk∗a(is nff dflt)k →a id assnby (sep auto simp: amd lookup def )
lemma amd2 update refine:(uncurry2 (amd update dflt), uncurry2 (RETURN ooo (λk v f . f (k :=v))))∈ id assnk∗aid assnk∗a(is nff dflt)d →a is nff dfltby (sep auto simp: amd update def )
lemma amd2 delete refine:(uncurry (amd delete dflt), uncurry (RETURN oo (amd1 delete dflt)))∈ id assnk∗a(is nff dflt)d →a is nff dfltby (sep auto simp: amd delete def )
The only complication arises for the update operation, where we have to use the fact that the default elementis invalid, which forces us to do a manual composition proof.
lemma amd2 update hnr aux :assumes CONSTRAINT (IS PURE single valued) K
and CONSTRAINT (IS PURE IS LEFT UNIQUE) Kand CONSTRAINT is pure Vand CONSTRAINT (is unused elem dflt) V
shows (uncurry2 (amd update dflt), uncurry2 (RETURN ◦◦◦ op map update))∈ K k ∗a V k ∗a (amd assn dflt K V )d →a amd assn dflt K V
apply (rulehfref cons[
OF amd2 update refine[FCOMP amd1 update refine[where dflt=dflt ],FCOMP (no prenorm) op map update.fref , of K V ]])
subgoal using assms by (simp add : IS PURE def )subgoal using assms by (simp add : IS PURE def )subgoal using assms by (simp add : IS PURE def )subgoal using assms by (simp add : IS PURE def IS LEFT UNIQUE def )subgoal
using assmsby (auto
simp del : pure def
36
simp: comp PRE def IS PURE def is unused elem def is pure convsimp: pure rel eq false iffelim!: prod relE)
applyS simpapplyS simpapplyS simpdone
private lemma op map update id param:(uncurry2 (RETURN ◦◦◦ op map update), uncurry2 (RETURN ◦◦◦ op map update))∈ (Id×rId)×rId →f 〈Id〉nres relby (simp add : fref def nres rel def )
sepref-decl-impl amd2 update hnr aux uses op map update id param .
end
interpretation amd : map custom empty op amd empty apply unfold locales by autolemmas [sepref fr rules] = amd empty hnr [folded op amd empty def ]
6.3 Operations on Options
We give own names to constructors, otherwise, we will get confusions with the default option refinement.
definition [simp]: dflt None ≡ Nonedefinition [simp]: dflt Some ≡ Somesepref-register dflt None dflt Some
lemma doa None hnr :(uncurry0 (return dflt), uncurry0 (RETURN dflt None))∈ unit assnk →a dflt option assn dflt Aapply (sepref to hoare)apply (sep auto simp: pure def dflt option rel aux def dflt option assn def )done
lemma doa Some hnr : [[CONSTRAINT (is unused elem dflt) A; CONSTRAINT is pure A]]=⇒ (return o (λx . x ), RETURN o dflt Some) ∈ Ak →a dflt option assn dflt Aapply (sepref to hoare)apply (clarsimp simp: is pure conv dflt option assn def )apply (sep auto simp: pure def )apply (fastforce simp: dflt option rel aux def )done
lemma doa is None hnr [sepref fr rules]:(return o ((=) dflt), RETURN o is None)∈ (dflt option assn dflt A)k →a bool assnapply (sepref to hoare)by (sep auto
simp: dflt option assn def pure def dflt option rel aux defsplit : option.split)
lemma doa the hnr [sepref fr rules]: [[CONSTRAINT is pure A]]=⇒ (return o (λx . x ), RETURN o the)∈ [λx . x 6=None]a (dflt option assn dflt A)k → A
apply (sepref to hoare)apply (clarsimp simp: is pure conv dflt option assn def )apply (sep auto simp: pure def dflt option rel aux def )done
lemma cnv option case 2 if : (case x of None ⇒ fn | Some v ⇒ fv v)
37
←→ (if is None x then fn else fv (the x )) by (cases x ) auto
We first define a function that joins a list of lists, terminating each sublist by a zero.
primrec concat sep :: ′a ⇒ ′a list list ⇒ ′a list whereconcat sep Z [] = []| concat sep Z (l#ls) = l @ Z # concat sep Z ls
lemma concat sep empty iff [simp]: concat sep Z ls = [] ←→ ls=[]by (cases ls) auto
lemma concat sep by concat map:concat sep Z ll = concat (map (λl . l@[Z ]) ll)by (induction ll) auto
Then, we first define the tokenization function operationally. Later, we will characterize it as the uniqueinverse of concatenation.
fun tokenize :: ′a ⇒ ′a list ⇒ ′a list list wheretokenize Z [] = []| tokenize Z ([x ]) = (if x=Z then [[]] else undefined)| tokenize Z (x#xs) = (
if x=Z then []#tokenize Z xselse case tokenize Z xs of l#ls ⇒ (x#l)#ls | ⇒ undefined
)
lemma tokenize ZZ [simp]:tokenize Z (Z #l) = (if l=[] then [[]] else []#tokenize Z l)by (auto simp: neq Nil conv)
lemma tokenize NZZ : [[Z /∈ set l ]] =⇒tokenize Z (l @ Z # l ′) = (if l ′ = [] then [l ] else l#tokenize Z l ′)by (induction l rule: tokenize.induct) auto
lemma tokenize NZZE [simp]: Z /∈ set l =⇒ tokenize Z (l @ [Z ]) = [l ]by (simp add : tokenize NZZ )
lemma concat tokenize id :[[ l 6=[] −→ last l = Z ]] =⇒ concat sep Z (tokenize Z l) = lapply (induction l rule: tokenize.induct)apply (auto split : list .split)done
lemma tok eq prefixD : [[l@Z #m = l ′@Z #m ′; Z /∈set l ; Z /∈set l ′]] =⇒ l ′=l ∧ m ′=mby (metis in set conv decomp list match lel lel)
lemma concat sep unique:assumes Z /∈
⋃set (map set ls1 )
assumes Z /∈⋃
set (map set ls2 )assumes concat sep Z ls1 = concat sep Z ls2shows ls1 = ls2using assmsapply (induction ls1 arbitrary : ls2 )subgoal for ls2 by (cases ls2 ) autosubgoal for l ls1 ls2 by (cases ls2 ) (auto dest : tok eq prefixD)done
39
lemma tokenize not empty [simp]: [[l 6=[]; last l = Z ]] =⇒ tokenize Z l 6= []by (induction l rule: tokenize.induct) (auto split : list .splits)
lemma tokenize complete:[[l 6=[] −→ last l = Z ]] =⇒ Z /∈
⋃set (map set (tokenize Z l))
by (induction l rule: tokenize.induct) (auto split : list .splits)
lemma tokenize complete set :[[ ll 6=[] −→ last ll = Z ; l ∈ set (tokenize Z ll); x∈set l ]] =⇒ x 6=Zby (drule tokenize complete) auto
lemma unique tokenization:[[ l 6=[] −→ last l = Z ]]=⇒ ∃ !ls. (Z /∈
⋃set (map set ls) ∧ concat sep Z ls = l)
apply (frule concat tokenize id)apply (frule tokenize complete)apply (rule ex1I [where a=tokenize Z l ])subgoal by autosubgoal using concat sep unique by fastforcedone
lemma tokenize append :[[ l 6=[] −→ last l=Z ]] =⇒ tokenize Z (l@l ′) = tokenize Z l @ tokenize Z l ′
by (induction Z≡Z l rule: tokenize.induct) (auto split : list .split)
lemma concat sep last sep: [[concat sep Z ll = l ; l 6= []]] =⇒ last l = Zby (induction ll arbitrary : l) (auto split : if splits)
We specify the result of tokenize to be the unique list of lists, which, when joined, yields the original listagain. To believe this characterization, you have to believe that concat sep does the right thing (e.g. look atconcat sep by concat map), and have a look at unique tokenization to persuade yourself that the right-handside is well-defined.
theorem tokenize spec: [[ l 6=[] −→ last l = Z ]]=⇒ tokenize Z l = (THE ls. Z /∈
⋃set (map set ls) ∧ concat sep Z ls = l)
apply (frule theI ′[OF unique tokenization])by (metis (no types, lifting) concat sep unique concat tokenize id
tokenize complete)
lemma unique tokenize presentation:assumes l 6=[] −→ last l = Zshows ∃ !ls. (Z /∈
⋃set (map set ls) ∧ concat sep Z ls = l)
and tokenize Z l = (THE ls. Z /∈⋃
set (map set ls) ∧ concat sep Z ls = l)using unique tokenization[OF assms] tokenize spec[OF assms] .
lemma tokenize concat id :[[ Z /∈
⋃set (map set ls) ]] =⇒ tokenize Z (concat sep Z ls) = ls
by (induction ls) (auto simp: tokenize NZZ )
endtheory Dimacs Formatimports SAT Basic Tokenizationbegin
8 Parsing to Formulas
A formula is represented according to DIMACS, the de facto standard for encoding CNF formulas: Variablesare identified by positive integers. Negative integers encode negated variables. A clause is a null-terminatedstring of integers, and the formula is simply the concatenation of its clauses.
40
type-synonym var = nat
abbreviation (input) litZ :: int where litZ ≡ 0
Interpreting an integer as literal
definition lit invar :: int ⇒ boolwhere lit invar l ≡ l 6=0
definition lit α :: int ⇒ nat literalwhere lit α l ≡ if l<0 then Neg (nat (−l)) else Pos (nat l)
Interpreting a list of integers (without terminating zero) as clause
definition clause invar l ≡ ∀ x∈set l . lit invar xdefinition clause α l ≡ lit α‘set l
Interpreting a list of integers as formula
definition F invar lst ≡ lst 6=[] −→ last lst = litZdefinition F α lst ≡ set (map clause α (tokenize litZ lst))
lemma map lit γ α eq [simp]: 0 /∈set l =⇒ map (lit γ ◦ lit α) l = lby (induction l) auto
lemma map map lit γ α eq [simp]:0 /∈
⋃set (map set l) =⇒ map (map (lit γ ◦ lit α)) l = l
by (induction l) auto
lemma lit invar γ iff [simp]: lit invar (lit γ l) ←→ var of lit l 6= 0by (cases l) (auto simp: lit invar def lit γ def )
9 Direct Representation of Satisfiable Formulas
Instead of parsing a DIMACS formatted list to a formula, and then stating that the formula is satisfiable,there is a more direct equivalent characterization of satisfiability: The formula is tokenized to a set of setsof integers, and we have to find an assignment from integers to Booleans that is consistent, i.e., a negative
41
integer is assigned the negation of what is assigned to the positive integer, such that each clause contains atleast one integer assigned to true.
This gives a concise semantic reference point within a few lines of code.
definition direct invar :: int list ⇒ boolwhere direct invar lst ≡ lst 6=[] −→ last lst = 0
definition parse direct :: int list ⇒ int set setwhere parse direct lst ≡ set ‘ set (tokenize 0 lst)
definition assn consistent :: (int ⇒ bool) ⇒ boolwhere assn consistent σ ←→ (∀ l . l 6=0 −→ σ l = (¬ σ (−l)))
definition direct sat :: int set set ⇒ boolwhere direct sat F ≡ ∃σ. assn consistent σ ∧ (∀C∈F . ∃ l∈C . σ l)
definition direct valid sat l ≡ direct invar l ∧ direct sat (parse direct l)definition direct valid unsat l ≡ direct invar l ∧ ¬direct sat (parse direct l)
We show equivalence to the standard semantics
theorem direct invar eq : direct invar l = F invar lunfolding direct invar def F invar def by simp
lemma ex assn consistent [intro,simp]: ¬(∀ x . ¬assn consistent x )apply (clarsimp)apply (rule exI [where x=(<) 0 ])by (auto simp: assn consistent def )
theorem direct sat iff sat :
shows direct sat (parse direct l) ←→ sat (F α l)proof −
have F α alt : F α l = (λx . lit α‘x )‘set‘set (tokenize 0 l)unfolding F α def clause α defby auto
have X1 : ∃σ. ∀ l . l 6= (0 ::int) −→ σ l = (¬ σ (− l))by (rule exI [where x=(<) 0 ]) auto
show ?thesisproof
assume direct sat (parse direct l)then obtain σ where CONS : assn consistent σ and SAT : ∀C∈set‘set (tokenize 0 l). ∃ x∈C . σ x
unfolding direct sat def parse direct def by blast
from CONS have X2 : σ (−x ) ←→ ¬(σ x ) if x 6=0 for xunfolding assn consistent def using thatapply (cases x=0 )apply simpapply blastdone
let ?σ ′ = σ o int
have sem cnf (F α l) ?σ ′
unfolding sem cnf def F α def clause α defproof
fix Cassume C ∈ set (map (λl . lit α ‘ set l) (tokenize 0 l))then obtain C ′ where C ′ ∈ set‘set (tokenize 0 l) and [simp]: C = lit α ‘ C ′
by autowith SAT obtain x where x∈C ′ σ x by autothen show sem clause C (σ ◦ int)
unfolding sem clause def sem lit altby (auto simp: X2 lit α def elim!: bexI [rotated ])
qed
42
then show sat (F α l)unfolding sat def by blast
nextassume sat (F α l)then obtain σ where SAT : sem cnf (F α l) σ unfolding sat def by auto
let ?σ ′ = λi . if i<0 then ¬σ (nat (−i)) else σ (nat i)
have assn consistent ?σ ′
unfolding assn consistent def by automoreover have ∃ l∈C . ?σ ′ l if C∈set ‘ set (tokenize 0 l) for C
using SAT thatunfolding sem cnf def F α alt sem clause def clause α def sem lit alt lit α defby (fastforce split : literal .splits)
ultimately show direct sat (parse direct l)unfolding direct sat def parse direct def by auto
This theory provides a notion of iterator, and defines simple parsers (for null-terminated lists) on top of this.
hide-const Word .slice
10.1 Iterators
This locale provides the abstract interface of an iterator.
Note that there is no direct notion of reaching the end. This is only indirectly modeled by the invariant notholding for the iterator any more. Thus, algorithms against this interface can only be written if one canderive from the precondition that the iterator will remain valid.
Two examples how this could be asserted are:
• The precondition states that there is a string at the iterator position
• There is an explicit iterator range begin . . . end, which is valid, the current iterator is in between, andthe algorithm stops if it reaches end.
locale iterator =fixes
I :: ′it ::order ⇒ bool — Iterator invariantand next :: ′it ⇒ ′it — Advance iteratorand peek :: ′it ⇒ ′a — Get element at current positionassumes ordered : I it =⇒ it < next it
— Advancing an iterator must result in a bigger iterator.begin
10.1.1 Segments
primrec seg :: ′it ⇒ ′a list ⇒ ′it ⇒ bool whereseg it [] it ′ ←→ I it ∧ it ′=it| seg it (x#xs) it ′ ←→ I it ∧ x = peek it ∧ seg (next it) xs it ′
43
definition itran it it ′ ≡ ∃ l . seg it l it ′
lemma seg invar1 [simp]: seg it xs it ′ =⇒ I it by (cases xs) autolemma seg invar2 [simp]: seg it xs it ′ =⇒ I it ′
by (induction xs arbitrary : it) auto
lemma itran invar [simp]: assumes itran it it ′ shows I it I it ′
using assmsunfolding itran defby auto
lemma seg I next [simp, elim]: [[seg it l it ′; it 6=it ′]] =⇒ I (next it)by (cases l) auto
lemma itran I next [simp, elim]: [[itran it it ′; it 6=it ′]] =⇒ I (next it)unfolding itran def by auto
lemma seg concat [simp]: seg it (xs@ys) it ′
←→ (∃ ith. seg it xs ith ∧ seg ith ys it ′)by (induction xs arbitrary : it) auto
lemma seg ord : seg it l it ′ =⇒ it ≤ it ′
apply (induction l arbitrary : it)using less imp le less le trans ordered by (auto; blast)+
lemma itran ord : itran it it ′ =⇒ it ≤ it ′
by (auto simp: itran def seg ord)
lemma seg no cyc[simp]: ¬seg (next it) list itby (meson less le not le ordered seg invar2 seg ord)
lemma seg eq iff empty [simp]: seg it l it ←→ I it ∧ l=[]by (cases l) (auto)
lemma seg unique: [[ seg it l1 it ′; seg it l2 it ′ ]] =⇒ l1=l2proof (induction l1 arbitrary : it l2 )
case Nilthen show ?case by auto
nextcase (Cons a l1 )then show ?case by (cases l2 ) auto
qed
definition the seg it it ′ ≡ THE l . seg it l it ′
lemma seg the seg : itran it it ′ =⇒ seg it (the seg it it ′) it ′
unfolding itran def the seg defby (metis seg unique the equality)
lemma the seg eq [simp]: seg it l it ′ =⇒ the seg it it ′ = lunfolding itran def the seg defby (metis seg unique the equality)
lemma the seg next append :assumes seg it l it ′ itran it ′ (next it ′)shows the seg it (next it ′) = l @ [peek it ′]apply (rule the seg eq)using assms by auto
lemma itranE : assumes itran it it ′ obtains l where seg it l it ′
using assms unfolding itran def by auto
lemma itran next [simp]:
44
[[I it ; it 6=itE ]] =⇒ itran (next it) itE ←→ itran it itEapply (rule iffI ; clarsimp simp: itran def )subgoal for l by (rule exI [where x=peek it#l ]) autosubgoal for l by (cases l) autodone
lemma itran measure[simp]:[[itran it it ′; it 6=it ′]]=⇒ length (the seg (next it) it ′) < length (the seg it it ′)apply (erule itranE ; simp)subgoal for l by (cases l) autodone
lemma itran measure ′:[[itran it ith; itran ith it ′; it 6=ith ]]=⇒ length (the seg ith it ′) < length (the seg it it ′)
proof (elim itranE ; simp)fix l1 l2assume it 6= ith seg it l1 ith seg ith l2 it ′
hence [simp]: l1 6=[] and S12 : seg it (l1@l2 ) it ′ by autoshow length l2 < length (the seg it it ′)
using the seg eq [OF S12 ] by autoqed
lemma itran refl [simp]: itran it it ←→ I it by (auto simp: itran def )lemma itran antisym: [[itran it it ′; itran it ′ it ]] =⇒ it=it ′
by (auto dest !: itran ord)lemma itran trans[trans]: itran it ith =⇒ itran ith it ′ =⇒ itran it it ′
by (meson itran def seg concat)
lemma itran next2I : [[itran it it ′; I (next it ′)]] =⇒ itran it (next it ′)by (metis itran invar(2 ) itran next itran refl itran trans)
10.1.2 Zero-Terminated Strings
definition lz string Z it l it ′ ≡ seg it (l@[Z ]) it ′ ∧ Z /∈set l
lemma lz string empty [simp]:lz string Z ith [] it ′
←→ I ith ∧ I (next ith) ∧ peek ith=Z ∧ it ′=next ithunfolding lz string defby auto
lemma lz string cons[simp]: lz string Z it (x#xs) it ′
←→ I it ∧ x=peek it ∧ x 6=Z ∧ lz string Z (next it) xs it ′
unfolding lz string defby auto
lemma lz string invar [simp]:assumes lz string Z it l it ′ shows I it I it ′
using assms unfolding lz string def by auto
lemma lz string noZ : lz string Z it l it ′ =⇒ Z /∈set lunfolding lz string def by auto
lemma lz string determ:assumes lz string Z it l it ′
assumes lz string Z it l ′ it ′′
shows l ′=l ∧ it ′′=it ′
using assmsproof (induction l arbitrary : l ′ it)
case Nil thus ?case by (cases l ′; auto)next
case (Cons a l) thus ?case by (cases l ′; auto)
45
qed
definition the lz string Z it ≡ THE l . ∃ it ′. lz string Z it l it ′
lemma the lz string eq [simp]:lz string Z it l it ′ =⇒ the lz string Z it = lunfolding the lz string defusing lz string determ by blast
definition parse lz ERR Z itE it c f s ≡ doE {CHECK (it 6=itE) ERR;(it ,s) ← EWHILEIT
(λ(it ,s). I it ∧ itran it itE ∧ it 6=itE)(λ(it ,s). peek it 6= Z ∧ c s)(λ(it ,s). doE {
EASSERT (itran it itE ∧ it 6= itE);let x = peek it ;EASSERT (x 6= Z );s ← f x s;let it = next it ;CHECK (it 6=itE) ERR;ERETURN (it ,s)}) (it ,s);
EASSERT (itran it itE ∧ it 6= itE);let it = next it ;ERETURN (it ,s)}
lemma parse lz rule:assumes Φ: Φ [] sassumes IT : itran it itEassumes C RL:
∧x l s. [[Φ l s; x 6=Z ; c s]] =⇒ f x s ≤ ESPEC E (Φ (l@[x ]))
assumes IMP Q :∧
it ′ s l .[[lz string Z it l it ′; itran it ′ itE ; Φ l s; I it ′; c s]] =⇒ Q (it ′,s)
assumes IMP INTR:∧
it ′ s l .[[ itran it it ′; itran it ′ itE ; Z /∈set l ; Φ l s; ¬c s ]] =⇒ Q (it ′,s)
assumes IMP E : Z /∈ set (the seg it itE) =⇒ E ERRshows parse lz ERR Z itE it c f s ≤ ESPEC E Qunfolding parse lz defapply (refine vcg
EWHILEIT expinv rule[whereI =λ(it ′,s). ∃ l . seg it l it ′
∧ itran it ′ itE ∧ it ′6=itE ∧ Z /∈set l ∧ Φ l sand R=measure (λ(it ′, ). length (the seg it ′ itE))
])apply (vc solve simp: Φ IT itran invar [OF IT ])subgoal for it ′ s l
apply (refine vcg C RL[of l , THEN ESPEC trans])apply (vc solve simp: the seg next append)subgoal for s ′ apply (rule exI [where x=l@[peek it ′]]) by autosubgoal apply (rule IMP E) by (auto simp: the seg next append)done
subgoal for it ′ s lproof −
assume a1 : Φ l sassume a2 : it ′ 6= itEassume a3 : Z /∈ set lassume a4 : itran it ′ itEassume a5 : seg it l it ′
assume a6 : peek it ′ = Z ∨ ¬ c shave f7 : ¬ I it ′ ∨ itran (next it ′) itE
using a4 a2 itran next by blasthave f8 :
∧i . ¬ I (next i) ∨ ¬ I i ∨ next i = i ∨ itran i (next i)
46
by (metis (no types) itran next itran refl)then have the seg it (next it ′) = l @ [peek it ′]
using a5 a4 a2by (metis (full types) itran I next itran def itran invar(2 )
itran refl the seg next append)then show ?thesis
using f8 f7 a6 a5 a4 a3 a2 a1by (metis IMP INTR IMP Q itran I next itran def itran invar(2 )
itran trans lz string def seg the seg)qedsubgoal apply (rule IMP E) using IT by autodone
definition iterate lz Z itE it c f s ≡ doE {EASSERT (it 6=itE);(it ,s) ← EWHILEIT
(λ(it ,s). I it ∧ itran it itE ∧ it 6=itE)(λ(it ,s). peek it 6= Z ∧ c s)(λ(it ,s). doE {
EASSERT (itran it itE ∧ it 6= itE);let x = peek it ;EASSERT (x 6= Z );s ← f x s;let it = next it ;ERETURN (it ,s)}) (it ,s);
ERETURN s}
lemma iterate lz rule:assumes P : lz string Z it l it ′ itran it ′ itEassumes Φ: Φ [] l sassumes F RL:
∧x l1 l2 s. [[ l = l1@x#l2 ; Φ l1 (x#l2 ) s; c s]]
=⇒ f x s ≤ ESPEC Ψ (Φ (l1@[x ]) l2 )assumes IMP INTR:
∧l1 l2 s. [[ l = l1@l2 ; Φ l1 l2 s; ¬c s ]] =⇒ Q s
assumes IMP Q :∧
s. [[ Φ l [] s; c s ]] =⇒ Q sshows iterate lz Z itE it c f s ≤ ESPEC Ψ Q
proof −from P have 1 : I it and [simp]: it 6=itE
apply −subgoal by autosubgoal
by (metis Nil is append conv itran antisym itran def list .simps(3 )lz string def seg eq iff empty)
done
show ?thesisunfolding iterate lz defapply (refine vcg EWHILEIT expinv rule[where
I = λ(ith,s). ∃ l1 l2 . seg it l1 ith∧ lz string Z ith l2 it ′ ∧ l=l1@l2 ∧ Φ l1 l2 s
and R = measure (λ(ith, ). length (the seg ith it ′))])
apply (vc solve simp: P Φ 1 )subgoal using P(2 ) itran def itran trans lz string def by blastsubgoal
by (metis Nil is append conv assms(2 ) itran antisym itran deflz string def lz string empty seg eq iff empty)
subgoal for ith s l1 l2apply (cases l2 ; simp)subgoal for x l2 ′
The parsing algorithm succeeds iff the input is non-empty and ends with a zero. In case of success, it returnsthe tokenization of the input
As a warm-up, we phrase the parser on lists. Our ultimate goal, however, is to phrase the parser as afold-operation on iterators.
partial-function (option) tok parser wheretok parser Z l = (case l of
[] ⇒ Some []| [x ] ⇒ if x=Z then Some [[]] else None| x#xs ⇒ if x=Z then do { ls ← tok parser Z xs; Some ([]#ls) }
else do {ls ← tok parser Z xs;case ls of l#ls ⇒ Some ((x#l)#ls) | ⇒ None}
)
lemma tok parser some eq : tok parser Z l = Some ls =⇒ ls=tokenize Z lapply (induction Z≡Z l arbitrary : ls rule: tokenize.induct)subgoal
by (subst (asm) tok parser .simps) autosubgoal for x
by (subst (asm) tok parser .simps) autosubgoal for x1 x2 xs ls
apply (rewrite at tok parser Z (x1 # x2 # xs) in asm tok parser .simps)apply (auto split !: list .splits Option.bind splits)done
done
lemma tok parser undefined iff : tok parser Z l = None ←→ l 6=[] ∧ last l 6= Zapply (induction Z≡Z l rule: tokenize.induct)subgoal by (subst tok parser .simps) (auto)subgoal for x by (subst tok parser .simps) (auto)subgoal for x1 x2 xs
apply (rewrite at tok parser Z (x1 # x2 # xs) tok parser .simps)apply (auto split !: list .splits Option.bind splits if splits)apply (auto dest !: tok parser some eq)by (metis last ConsR list .simps(3 ) tokenize not empty)
done
lemma tok parser defined iff :
48
tok parser Z l = Some ls ←→ (l=[] ∨ last l = Z ) ∧ ls=tokenize Z lby (metis not None eq tok parser some eq tok parser undefined iff )
theorem tok parser correct : case tok parser Z l ofNone ⇒ l 6=[] ∧ last l 6= Z| Some ls ⇒ (l=[] ∨ last l = Z ) ∧ l = concat sep Z ls
by (autosplit : option.splitsimp: tok parser defined iff tok parser undefined iff concat tokenize id)
10.3 Parsing Fold over Tokenization
context iterator begin
definition tok fold:: ′it ⇒ ′it ⇒ ( ′it ⇒ ′s ⇒ ( ′e, ′it× ′s) enres) ⇒ ′s ⇒ ( ′e, ′s) enreswhere tok fold itE it f s ≡ doE {
( ,s) ← EWHILEIT(λ(it ,s). I it) (λ(it ,s). it 6=itE) (λ(it ,s). f it s) (it ,s);
ERETURN s}
lemma tok fold rule:assumes [simp]: Φ [] sassumes SEG: seg it l itEassumes F RL:
∧ls s it . [[ Φ ls s; I it ; it 6= itE ; itran it itE ]]
=⇒ f it s ≤ ESPEC E (λ(it ′,s ′). ∃ l . lz string Z it l it ′
∧ itran it ′ itE ∧ Φ (ls@[l ]) s ′)assumes IMP Q :
∧s. [[ l 6=[] −→ last l = Z ; Φ (tokenize Z l) s]] =⇒ Q s
shows tok fold itE it f s ≤ ESPEC E Qunfolding tok fold defapply (refine vcg
EWHILEIT expinv rule[whereI =λ(it ′,s). ∃ l . seg it l it ′ ∧ itran it ′ itE
∧ (l 6=[] −→ last l = Z ) ∧ Φ (tokenize Z l) sand R = measure (λ(it ′, ). length (the seg it ′ itE))
])
apply (vc solve)subgoal using SEG by (auto simp: itran def )subgoal for ith s l
apply (refine vcg F RL[THEN ESPEC trans, refine vcg ])apply assumptionapply (vc solve)subgoal for it ′ s ′ l ′
apply (rule exI [where x=l@l ′@[Z ]]; intro conjI )subgoal by (metis (no types, lifting) lz string def seg concat)applyS autoapplyS (auto simp: tokenize append lz string noZ )done
iti it si s. [[ (iti ,it)∈Id ; (si ,s)∈R; I it ; it 6=itE ]]=⇒ fi iti si ≤ ⇓E E (Id ×r R) (f it s)
49
shows tok fold itEi iti fi si ≤ ⇓E E R (tok fold itE it f s)unfolding tok fold defapply (refine rcg STEP REF )apply (auto simp: R0 )done
lemmas [enres inline] = tok fold def
end
10.4 Array Iterator
We instantiate the abstract iterator interface for indexes into an array.
definition ait next ( :: list) ≡ Sucdefinition ait peek ≡ nthdefinition ait begin ( :: list) ≡ (1 ::nat)definition ait end ≡ length
locale array iterator =fixes a :: ′a::heap list
begindefinition I it ≡ it>0 ∧ it≤length a — Unused zero-positionabbreviation peek ≡ ait peek aabbreviation next where next ≡ ait next aabbreviation begin where begin ≡ ait begin aabbreviation end where end ≡ ait end a
sublocale iterator I next peek by unfold locales (auto simp: ait next def )
lemma I begin[simp, intro!]: a 6=[] =⇒ I beginby (auto simp: I def ait begin def )
lemma I end [simp, intro!]: a 6=[] =⇒ I endby (auto simp: I def ait end def )
definition a assn a ′ p ≡ p 7→a a ′ ∗ ↑(a ′=a ∧ a 6=[])definition it assn ≡ b assn nat assn I
lemma it assn pure[safe constraint rules]: CONSTRAINT is pure it assnunfolding it assn def by solve constraint
lemma it assn unused [safe constraint rules]:CONSTRAINT (is unused elem 0 ) it assnby (auto simp: is unused elem def it assn def pure def I def )
lemma a assn rdompD : rdomp a assn a ′ =⇒ a ′=aunfolding a assn defby (auto simp: rdomp def )
lemma next refine[sepref fr rules]:(uncurry (return oo (λ . (+) 1 )), uncurry (RETURN oo ait next))∈ [λ( ,it). it 6=end ]a a assnk ∗a it assnk → it assn
unfolding it assn defapply sepref to hoareapply (sep auto simp: ait end def I def ait next def )done
lemma peek refine[sepref fr rules]:(uncurry Array .nth, uncurry (RETURN oo ait peek))∈ [λ( ,it). it 6=end ]a a assnk ∗a it assnk → id assnunfolding it assn def a assn defapply sepref to hoareapply (sep auto simp: I def ait end def ait peek def )
50
done
lemma begin refine[sepref fr rules]:(λ . return 1 , RETURN o ait begin) ∈ a assnk →a it assnunfolding it assn def a assn defapply sepref to hoareapply (sep auto simp: I def ait begin def )done
lemma end refine[sepref fr rules]:(Array .len, RETURN o ait end) ∈ a assnk →a it assnunfolding it assn def a assn defapply sepref to hoareapply (sep auto simp: I def ait end def )done
lemma it assn eq impl [sepref fr rules]:(uncurry (return oo (=)),uncurry (RETURN oo (=)))∈ it assnk ∗a it assnk →a bool assnunfolding it assn defapply sepref to hoareapply sep autodone
lemma begin less end [simp]: begin ≤ end ←→ a 6=[]unfolding ait begin def ait end def by auto
lemma itran alt : itran it it ′ ←→ begin≤it ∧ it ≤ it ′ ∧ it ′ ≤ endunfolding ait begin def ait end defapply (rule iffI ; clarsimp)subgoal by (auto simp: I def itran ord dest : itran invar)subgoal proof −
assumeit ≤ it ′
Suc 0 ≤ itit ′ ≤ length a
thus itran it it ′
apply (induction rule: dec induct)subgoal by (auto simp: I def )subgoal for ith
using itran next2Iunfolding ait next defapply (auto simp: I def )done
doneqeddone
lemma seg is slice:assumes seg it l it ′
shows l = slice it it ′ ausing assmsapply (induction l arbitrary : it)applyS (auto)apply clarsimpapply (rewrite in seg ◊ in asm ait next def )apply (rewrite in peek # ait peek def )
proof −fix la :: ′a list and ita :: natassume a1 : seg (Suc ita) la it ′
assume a2 :∧
it . seg it la it ′ =⇒ la = slice it it ′ ahave f3 : ∀n na nb. ¬ (n::nat) ≤ na ∨ ¬ nb < n ∨ nb < na
using dual order .strict trans1 by blast
51
have f4 : Suc ita ≤ it ′
using a1 seg ord by blastthen have f5 : ita < it ′
using f3 by blasthave f6 : ∀n na. ¬ (n::nat) < na ∧ n 6= na ∨ n ≤ na
using less or eq imp le by blastthen have f7 : ita ≤ Suc ita
by (meson lessI )have length (take it ′ a) ≤ ita −→ drop (Suc ita) (take it ′ a) 6= []
using f6 f4 f3 a1 by (metis (no types) I def Misc.slice def antisym conv2 diff diff cancel drop all drop take lessIseg invar2 slice len)
then have ¬ length (take it ′ a) ≤ itausing f7 f6 f3 by (metis (no types) antisym conv2 drop all)then show a ! ita # la = slice ita it ′ a
using f5 a2 a1 by (metis (no types) Cons nth drop Suc I def Misc.slice def drop take hd drop conv nth leIseg invar2 slice head)
qed
lemma seg exists:[[ 0<it ; it≤it ′; it ′≤length a ]] =⇒ ∃ l . seg it l it ′
by (metis I def ait end def itran alt itran def itran refl order trans)
lemma seg sliceI :[[ 0<it ; it≤it ′; it ′≤length a ]] =⇒ seg it (slice it it ′ a) it ′
apply (drule (2 ) seg exists)apply (clarify)apply (frule seg is slice)by simp
lemma seg slice conv :seg it l it ′ ←→ 0<it ∧ it≤it ′ ∧ it ′≤length a ∧ l = slice it it ′ aby (auto
simp: seg sliceI seg ord I def seg is slicedest : seg invar1 seg invar2 )
end
sepref-register ait next ait peek ait begin ait end
lemma list set assn finite[simp, intro]:[[rdomp (list set assn (pure R)) s; single valued R]] =⇒ finite sby (auto simp: rdomp def list set assn def elim!: finite set rel transfer)
lemma list set assn IS TO SORTED LIST GA ′[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)apply (clarsimp simp: is pure conv list set assn def
list assn pure conv IS PURE def list set rel compp)apply (rule sepref gen algo rules)done
11.1 Input Parser
locale input pre =iterator it invar ′ it next it peek
for it invar ′ it next and it peek :: ′it ::linorder ⇒ int +fixes
it end :: ′it
begindefinition it invar it ≡ itran it it endlemma it invar imp ′[simp, intro]: it invar it =⇒ it invar ′ it
unfolding it invar def by autolemma it invar imp ran[simp, intro]: it invar it =⇒ itran it it end
unfolding it invar def by autolemma itran invarD : itran it it end =⇒ it invar it
unfolding it invar def by autolemma itran invarI : [[itran it it ′; it invar it ′]] =⇒ it invar it
unfolding it invar def by (blast intro: itran trans)
abbreviation mk errI :: ⇒ ⇒ ′it errorwhere mk errI msg i ≡ (msg , Some i , None)
abbreviation mk errit :: ⇒ ⇒ ′it errorwhere mk errit msg it ≡ (msg , None, Some it)
abbreviation mk errNit :: ⇒ ⇒ ⇒ ′it errorwhere mk errNit msg n it ≡ (msg , Some (int n), Some it)
abbreviation mk errIit :: ⇒ ⇒ ⇒ ′it errorwhere mk errIit msg i it ≡ (msg , Some i , Some it)
Check that iterator has not reached the end.
definition check not end it≡ CHECK (it 6= it end) (mk err STR ′′Parsed beyond end ′′)
lemma check not end correct [THEN ESPEC trans, refine vcg ]:it invar it =⇒ check not end it ≤ ESPEC (λ . True) (λ . it 6= it end)unfolding check not end def by (refine vcg ; auto)
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 it0 ≡ doE {(x ,it) ← parse int it0;CHECK (x≥0 ) (mk errIit STR ′′Invalid nat ′′ x it0);ERETURN (nat x ,it)}
54
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 ′). it invar it ′ ∧ (it ′,it)∈WF+)
unfolding parse literal defby refine vcg auto
lemma skip spec[THEN ESPEC trans,refine vcg ]:[[it invar it ]]=⇒ skip it ≤ ESPEC (λ . True) (λit ′. it invar it ′ ∧ (it ′,it)∈WF+)unfolding skip defby refine vcg auto
lemma parse int spec[THEN ESPEC trans,refine vcg ]:[[it invar it ]]=⇒ parse int it ≤ ESPEC (λ . True) (λ(x ,it ′). it invar it ′ ∧ (it ′,it)∈WF+)unfolding parse int defby refine vcg auto
lemma parse nat spec[THEN ESPEC trans,refine vcg ]:[[it invar it ]]=⇒ parse nat it ≤ ESPEC (λ . True) (λ(x ,it ′). it invar it ′ ∧ (it ′,it)∈WF+)unfolding parse nat defby refine vcg auto
We inline many of the specifications on breaking down the exception monad
lemmas [enres inline] = check not end def skip def parse literal defparse int def parse nat def
sepref-definition op lit is true impl is uncurry (RETURN oo op lit is true):: (pure lit rel)k ∗a assignment assnk →a bool assnunfolding op lit is true alt assignment assn defsupply option.splits[split ]by sepref
sepref-definition op lit is false impl is uncurry (RETURN oo op lit is false):: (pure lit rel)k ∗a assignment assnk →a bool assnunfolding op lit is false alt assignment assn defsupply option.splits[split ]by sepref
definition [simp]: b2vv conv b ≡ bdefinition [code unfold ]: b2vv conv impl b ≡ if b then 2 else 1 ::nat
term op map lookupdefinition 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)>unfolding is creg def op creg lookup defby (sep auto intro!: ext simp: lit rel def in br conv)
lemma creg lookup hnr [sepref fr rules]:(uncurry op creg lookup, uncurry (RETURN oo op map lookup))∈ (pure lit rel)k ∗a is cregk →a option assn (list assn id assn)unfolding list assn pure conv option assn pure convapply sepref to hoareapply sep autodone
11.2.5 Clause Database
contextfixes DB :: clausedb2fixes frml end :: nat
begindefinition item next it ≡
let sz = DB !(it−1 ) inif 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 !itend
context DB2 def locbegin
abbreviation cm assn ≡ prod assn (amd assn 0 nat assn liti .it assn) is cregtype-synonym i cm = (nat ,nat) i map × (nat literal , nat list) i map
abbreviation state assn ≡ nat assn ×a cm assn ×a assignment assntype-synonym i state = nat × i cm × i assignment
60
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
return 0}
lemma item next hnr [sepref fr rules]:(uncurry item next impl , uncurry (RETURN oo item next))∈ liti .a assnk ∗a liti .it assnk →a dflt option assn 0 liti .it assnunfolding liti .it assn def liti .a assn def dflt option assn defapply (simp add : b assn pure conv)apply (sepref to hoare)unfolding item next impl defby (sep auto simp: liti .I def item next def dflt option rel aux def )
lemma at item end hnr [sepref fr rules]:(uncurry (return oo at item end), uncurry (RETURN oo at item end))∈ nat assnk ∗a liti .it assnk →a bool assnunfolding liti .it assn def liti .a assn def dflt option assn defapply (simp add : b assn pure conv)apply (sepref to hoare)apply sep autodone
end
11.3 Common GRAT Stuff
datatype item type =INVALID| UNIT PROP| DELETION| RUP LEMMA| RAT LEMMA| CONFLICT| RAT COUNTS
type-synonym id = nat
11.3.1 Clause Map
11.3.2 Correctness
The input to the verified part of the checker is an array of integers DB and an index F end, such that therange from index 1 :: ′a (inclusive) to index F end (exclusive) contains the formula in DIMACs format.
The array is represented as a list here.
We phrase an invariant that expressed a valid formula, and a characterization whether the representedformula is satisfiable.
definition clause DB valid DB F end ≡1 ≤ F end ∧ F end ≤ length DB∧ F invar (tl (take F end DB))
definition clause DB sat DB F end ≡ sat (F α (tl (take F end DB)))
definition verify sat spec DB F end≡ clause DB valid DB F end ∧ clause DB sat DB F end
61
definition verify unsat spec DB F end≡ clause DB valid DB F end ∧ ¬clause DB sat DB F end
lemma verify sat spec DB F end ←→ 1 ≤ F end ∧ F end ≤ length DB ∧(let lst = tl (take F end DB) in F invar lst ∧ sat (F α lst))unfolding verify sat spec def clause DB valid def clause DB sat def Let defby auto
lemma verify unsat spec DB F end ←→ 1 ≤ F end ∧ F end ≤ length DB ∧(let lst = tl (take F end DB) in F invar lst ∧ ¬sat (F α lst))unfolding verify unsat spec def clause DB valid def clause DB sat def Let defby auto
Concise version only using elementary list operations
lemma clause DB valid concise: clause DB valid DB F end ≡1 ≤ F end ∧ F end ≤ length DB∧ (let lst=tl (take F end DB) in lst 6=[] −→ last lst = 0 )apply (rule eq reflection)unfolding clause DB valid def F invar defby auto
lemma clause DB sat concise:clause DB sat DB F end ≡ ∃σ. assn consistent σ∧ (∀C∈set ‘ set (tokenize 0 (tl (take F end DB))). ∃ l∈C . σ l)
using clause DB sat defunfolding direct sat iff sat [symmetric] direct sat def parse direct defby auto
The input describes a satisfiable formula, iff F end is in range, the described DIMACS string is empty orends with zero, and there exists a consistent assignment such that each clause contains a literal assigned totrue.
lemma verify sat spec concise:shows verify sat spec DB F end ≡ 1≤F end ∧ F end ≤ length DB ∧ (
let lst = tl (take F end DB) in(lst 6=[] −→ last lst = 0 )∧ (∃σ. assn consistent σ ∧ (∀C∈set (tokenize 0 lst). ∃ l∈set C . σ l)))
unfolding verify sat spec def clause DB sat concise clause DB valid conciseby (simp add : Let def )
The input describes an unsatisfiable formula, iff F end is in range and does not describe the empty DIMACSstring, the DIMACS string ends with zero, and there exists no consistent assignment such that every clausecontains at least one literal assigned to true.
lemma verify unsat spec concise:verify unsat spec DB F end ≡ 1 < F end ∧ F end ≤ length DB ∧ (
let lst = tl (take F end DB) inlast lst = 0
∧ (@σ. assn consistent σ ∧ (∀C∈set (tokenize 0 lst). ∃ l∈set C . σ l)))unfolding verify unsat spec def clause DB sat concise clause DB valid conciseapply (rule eq reflection)apply (cases F end = 1 )apply (auto simp add : Let def tl take)done
definition [simp]: ndls rel ≡ br set (λ . True)definition nd list set assn A ≡ pure (ndls rel O 〈the pure A〉set rel)
contextnotes [fcomp norm unfold ] = nd list set assn def [symmetric]notes [fcomp norm unfold ] = list set assn def [symmetric]
begin
lemma ndls empty hnr aux : ([],op set empty) ∈ ndls rel by (auto simp: in br conv)sepref-decl-impl (no register) ndls empty : ndls empty hnr aux [sepref param] .
lemma ndls is empty hnr aux : ((=) [], op set is empty) ∈ ndls rel → bool relby (auto simp: in br conv)
sepref-decl-impl ndls is empty : ndls is empty hnr aux [sepref param] .
lemma ndls insert hnr aux : ((#), op set insert) ∈ Id → ndls rel → ndls relby (auto simp: in br conv)
sepref-decl-op ndls ls copy : λx :: ′a set . x :: 〈A〉set rel → 〈A〉set rel .lemma op ndls ls copy hnr aux :
(remdups, op ndls ls copy)∈ndls rel → 〈Id〉list set relby (auto simp: in br conv list set rel def )
sepref-decl-impl op ndls ls copy hnr aux [sepref param] .end
definition [simp]: op ndls empty = op set emptyinterpretation ndls: set custom empty return [] op ndls empty
by unfold locales simpsepref-register op ndls emptylemmas [sepref fr rules] = ndls empty hnr [folded op ndls empty def ]
lemma fold ndls ls copy : x = op ndls ls copy x by simp
end
12 Unsat Checker
theory Unsat Check Split MMimports Impl List Set Ndj Grat Basicbegin
hide-const (open) Word .slice
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-terminatedclauses), and the suffix contains a certificate in the GRAT format.
12.1 Abstract level
definition mkp raw err :: ⇒ ⇒ ⇒ (nat× ′prf ) error wheremkp raw err msg I p ≡ (msg , I , p)
locale unsat input = input it invar ′ for it invar ′:: ′it ::linorder ⇒ +
definition parse id prf ≡ doE {(x ,prf ) ← parse prf prf ;CHECK (x>0 ) (mkp errIprf STR ′′Invalid id ′′ x prf );ERETURN (nat x ,prf )}
definition parse idZ prf ≡ doE {(x ,prf ) ← parse prf prf ;CHECK (x≥0 ) (mkp errIprf STR ′′Invalid idZ ′′ 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 STR ′′Invalid item type ′′ v prf )}
definition parse prf literal prf ≡ doE {(i ,prf ) ← parse prf prf ;CHECK (i 6= 0 ) (mkp errprf STR ′′Expected literal but found 0 ′′ prf );ERETURN (lit α i , prf )}
(λ(CMRL,i ,it). cm invar CMRL∧ cm F CMRL ⊆ cm F CMRL0
∧ cm ids CMRL ⊆ cm ids CMRL0)(λ( ,i , ). i 6=0 )(λ(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) enreswhere 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) enreswhereget rat candidates ≡ λ(CM ,RL) A l . doE {
let l = neg lit l ;CHECK (RL l 6= None) (mkp err STR ′′Resolution literal not declared ′′);(∗ 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 ′ (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 )
unfolding resolve id defapply refine vcgapply (auto simp: cm F def intro: ranI )done
lemma remove id correct [THEN ESPEC trans,refine vcg ]:cm invar CMRL=⇒ remove id i CMRL≤ ESPEC
(λ . False)(λCMRL ′. cm invar CMRL ′
66
∧ cm F CMRL ′ ⊆ cm F CMRL∧ cm ids CMRL ′ ⊆ cm ids CMRL)
unfolding remove id defapply (refine vcg)apply (auto
simp: cm F def ran def restrict map def cm invar def cm ids defsplit : if split asm)
apply fastforcedone
lemma rtrancl inv image ss: (inv image R f )∗ ⊆ inv image (R∗) fproof (clarify)
lemma is syn taut mono aux : is syn taut (C−X ) =⇒ is syn taut Cby (auto simp: is syn taut def )
67
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)
unfolding get rat candidates defapply refine vcgunfolding cm invar def rat candidates def is blocked defapply (auto dest !: is syn taut mono aux simp: ranI )apply forcedone
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 ′ 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 ). i 6=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 ′. equiv ′ (cm F CM ) A A ′)unfolding apply unit def check unit clause defapply (refine vcg)apply (auto simp: unit propagation)apply (auto simp: is unit lit def )done
lemma apply units correct [THEN ESPEC trans, refine vcg ]:apply units CM A prf
≤ ESPEC(λ . True)(λ(A ′,prf ′). equiv ′ (cm F CM ) A A ′ ∧ (prf ′,prf )∈prfWF+)
unfolding apply units defapply (refine vcg
EWHILET rule[whereI =λ(A ′, , ). equiv ′ (cm F CM ) A A ′
and R=inv image (prfWF+) (λ( , ,prf ). prf )])
apply (auto dest : equiv ′ trans rtrancl inv image ssI )done
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 ′,it ′). (∃ l .
68
lz string litZ it l it ′
∧ it invar it ′
∧ C =clause α l∧ ¬is blocked A C∧ A ′ = and not C A C ))}
cleft ⊆ candidates∧ (∀ c∈candidates − cleft . Φ c)
69
and R=inv image (prfWF+) (λ( , ,prf ). prf )])
by (auto dest : rtrancl inv image ssI )
definition check rup proof :: state ⇒ ′it ⇒ (nat× ′prf ) ⇒ ( , state × ′it × (nat× ′prf )) enres wherecheck rup proof ≡ λ(CM ,A0) it prf . doE {
(i ,prf ) ← parse id prf ;CHECK (i /∈cm ids CM ) (mkp errNprf STR ′′Duplicate ID ′′ i prf );(C ,A ′,it) ← parse check blocked A0 it ;(A ′,prf ) ← apply units CM A ′ prf ;(confl id ,prf ) ← parse id prf ;confl ← resolve id CM confl id ;CHECK (is conflict clause A ′ confl)
(mkp errNprf STR ′′Expected conflict clause ′′ confl id prf );EASSERT (redundant clause (cm F CM ) A0 C );EASSERT (i /∈ cm ids CM );CM ← add clause i C CM ;ERETURN ((CM ,A0),it ,prf )}
lemma check rup proof correct [THEN ESPEC trans, refine vcg ]:assumes [simp]: s=(CM ,A)assumes cm invar CMassumes it invar itshowscheck rup proof s it prf ≤ ESPEC (λ . True) (λ((CM ′,A ′),it ′,prf ′).
cm invar CM ′
∧ (sat ′ (cm F CM ) A −→ sat ′ (cm F CM ′) A ′)∧ (it invar it ′) ∧ (prf ′,prf )∈prfWF+
simp:split !: if split asmintro: implied is redundant one step implied syn taut imp blockedsolve: asm rl)
definition check rat proof :: state ⇒ ′it ⇒ (nat × ′prf ) ⇒ ( , state × ′it × (nat × ′prf )) enres wherecheck rat proof ≡ λ(CM ,A0) it prf . doE {
(reslit ,prf ) ← parse prf literal prf ;
CHECK (sem lit ′ reslit A0 6= Some False)(mkp errprf STR ′′Resolution literal is false ′′ prf );
(i ,prf ) ← parse id prf ;CHECK (i /∈cm ids CM ) (mkp errNprf STR ′′Duplicate ID ′′ i prf );(∗(C ,it) ← lift parser parse clause it ;∗)(C ,A ′,it) ← parse check blocked A0 it ;CHECK (reslit ∈ C ) (mkp errprf STR ′′Resolution literal not in clause ′′ prf );(A ′,prf ) ← apply units CM A ′ prf ;candidates ← get rat candidates CM A ′ reslit ;prf ← check candidates candidates prf (λcand id prf . doE {
cand ← resolve id CM cand id ;
EASSERT (¬is blocked A ′ (cand−{neg lit reslit}));let A ′′ = and not C A ′ (cand−{neg lit reslit});(A ′′,prf ) ← apply units CM A ′′ prf ;(confl id ,prf ) ← parse id prf ;confl ← resolve id CM confl id ;
shows redundant clause (cm F (CM ,RL)) A Cproof (rule abs rat criterion[OF LIC NFALSE ]; safe)
fix Dassume A: D∈cm F (CM ,RL) neg lit reslit ∈ D
show implied clause (cm F (CM , RL)) A (C ∪ (D − {neg lit reslit}))proof (cases is blocked A ′ (D − {neg lit reslit}))
case Falsewith A obtain cand
where D=the (CM cand) and cand∈rat candidates CM A ′ reslitby (force simp: rat candidates def cm F def ran def )
thus ?thesisusing CANDS by auto
nextcase Truethus ?thesis
apply (rule tac two step implied)using EQ1 by auto
qedqed
lemma check rat proof correct [THEN ESPEC trans, refine vcg ]:assumes [simp]: s=(CM ,A)assumes cm invar CMassumes it invar itshowscheck rat proof s it prf ≤ ESPEC (λ . True) (λ((CM ′,A ′),it ′,prf ′).
cm invar CM ′
∧ (sat ′ (cm F CM ) A −→ sat ′ (cm F CM ′) A ′)∧ it invar it ′ ∧ (prf ′,prf )∈prfWF+
)unfolding check rat proof def parse check blocked defapply refine vcgsubgoal using assms by autosubgoal using assms by autousing assmsapply (cases CM )apply (elim conjE exE ; simp; elim conjE)apply hypsubst apply simp
71
subgoal premises prems for reslit prf1 i prf2 it ′ A ′ prf3 CM RL lproof −
from prems have A:reslit ∈ clause α l
and CMI : cm invar (CM , RL)and RESLIT SEM : sem lit ′ (reslit) A 6= Some Falseand INID : i /∈cm ids (CM , RL)and NBLK : ¬ is blocked A (clause α l)and EQ1 : equiv ′ (cm F (CM , RL)) (and not C A (clause α l)) A ′
INVALID ⇒ THROW (mkp err STR ′′Invalid item ′′)| UNIT PROP ⇒ doE {
(A,prf ) ← apply units CM A prf ;ERETURN (Some ((CM ,A),it ,prf ))}| DELETION ⇒ doE {
(CM ,prf ) ← remove ids CM prf ;ERETURN (Some ((CM ,A),it ,prf ))}| RUP LEMMA ⇒ doE {
s ← check rup proof (CM ,A) it prf ;ERETURN (Some s)}| RAT LEMMA ⇒ doE {
s ← check rat proof (CM ,A) it prf ;ERETURN (Some s)
72
}| CONFLICT ⇒ doE {
(i ,prf ) ← parse id prf ;C ← resolve id CM i ;CHECK (is conflict clause A C )
(mkp errNprf STR ′′Conflict clause has no conflict ′′ i prf );ERETURN None}| RAT COUNTS ⇒
THROW (mkp errprf STR ′′Not expecting rat−counts in the middle of proof ′′ prf )}
lemma check item correct pre:assumes [simp]: s = (CM ,A)assumes cm invar CMassumes [simp]: it invar itshows check item s it prf ≤ ESPEC (λ . True) (λ
Some ((CM ′,A ′),it ′,prf ′) ⇒cm invar CM ′
∧ (sat ′ (cm F CM ) A −→ sat ′ (cm F CM ′) A ′)∧ it invar it ′ ∧ (prf ′,prf )∈prfWF+
| None ⇒ ¬sat ′ (cm F CM ) A)using assms(2 ,3 )apply clarsimpunfolding check item defapply refine vcgapply (split item type.split ; intro allI impI conjI )applyS (refine vcg ; auto)applyS (refine vcg ; auto simp: sat ′ equiv)applyS (refine vcg ; auto simp: sat ′ antimono)applyS (refine vcg ; auto)applyS (refine vcg ; auto)applyS (refine vcg ; auto simp: conflict clause imp no models sat ′ def )applyS (refine vcg ; auto)done
lemma check item correct [THEN ESPEC trans, refine vcg ]:assumes case s of (CM ,A) ⇒ cm invar CMassumes it invar itshows check item s it prf ≤ ESPEC (λ . True) (case s of (CM ,A) ⇒ (λ
Some ((CM ′,A ′),it ′,prf ′) ⇒cm invar CM ′
∧ (sat ′ (cm F CM ) A −→ sat ′ (cm F CM ′) A ′)∧ it invar it ′ ∧ (prf ′,prf )∈prfWF+
| None ⇒ ¬sat ′ (cm F CM ) A))using check item correct pre[of s it prf ] assmsapply (cases s) by auto
definition cm empty :: clausemap where cm empty ≡ (Map.empty , Map.empty)lemma cm empty invar [simp]: cm invar cm empty
by (auto simp: cm empty def cm invar def )lemma cm F empty [simp]: cm F cm empty = {}
by (auto simp: cm empty def cm F def )lemma cm ids empty [simp]: cm ids cm empty = {}
by (auto simp: cm empty def cm ids def )
lemma cm ids empty imp F empty : cm ids CM = {} =⇒ cm F CM = {}unfolding cm F def cm ids def by (auto simp: ran def )
73
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 ′,(t ,A)) ← parse lz
(mkp err STR ′′Parsed beyond end ′′)litZ itE it (λ . True) (λx (t ,A). doE {
let l = lit α x ;if (sem lit ′ 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 ′,(t ,A))}
lemma clause assignment syn taut aux :[[∀ l . (sem lit ′ l A = Some True) = (l ∈ C ); is syn taut C ]] =⇒ Falseapply (clarsimp simp: is syn taut conv)by (metis map option eq Some option.inject sem neg lit ′)
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 ′,(t ,A)). A = Map.empty
∧ (∃ l . lz string litZ it l it ′
∧ itran it ′ itE∧ (t = is syn taut (clause α l))))
parse lz rule[whereΦ=λlst (t ,A). dom A ⊆ var of lit‘clause α lst∧ (t −→ is syn taut (clause α lst))∧ (¬t −→ (∀ l . sem lit ′ l A = Some True ←→ l ∈ clause α lst))
]iterate lz rule[where Φ=λ l2 A. dom A ⊆ var of lit‘clause α l2 ]
)apply (vc solve simp: not Some bool if itran invarI )applyS autoapplyS (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 ′ assign conv split : if splits)applyS (auto)applyS (auto simp: itran ord)applyS (auto)applyS (auto)applyS (auto dest : clause assignment syn taut aux )done
definition read cnf new:: ′it ⇒ ′it ⇒ clausemap ⇒ ( , clausemap) enreswhere read cnf new itE it CM ≡ doE {
(CM ,next id ,A) ← tok fold itE it (λit (CM ,next id ,A). doE {
74
(it ′,(t ,A)) ← read clause check taut itE it A;if t then ERETURN (it ′, (CM ,next id+1 ,A))else doE {
EASSERT (∃ l it ′. lz string litZ it l it ′ ∧ it invar it ′);let C = clause α (the lz string litZ it);CM ← add clause next id C CM ;ERETURN (it ′,(CM ,next id+1 ,A))}}) (CM ,1 ,Map.empty);ERETURN (CM )}
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 ).
(lst 6= [] −→ last lst = litZ )∧ cm invar CM∧ sat (cm F CM ) = sat (set (map clause α (tokenize litZ lst)))
)unfolding read cnf new defapply (refine vcg tok fold rule[where
Φ=λlst (CM ,next id ,A).A = Map.empty∧ cm invar CM∧ SAT Basic.models (cm F CM )
= SAT Basic.models (set (map clause α lst))∧ (∀ i∈cm ids CM . i<next id)
type-synonym bt assignment = (var ⇀ bool) × var set
definition backtrack A T ≡ A|‘ (−T )lemma backtrack empty [simp]: backtrack A {} = A
unfolding backtrack def by auto
definition is backtrack A ′ T ′ A ≡ T ′⊆dom A ′ ∧ A = backtrack A ′ T ′
lemma is backtrack empty [simp]: is backtrack A {} Aunfolding is backtrack def by auto
lemma is backtrack not undec:[[ is backtrack A ′ T ′ A; var of lit l∈T ′ ]] =⇒ sem lit ′ l A ′ 6= Noneunfolding is backtrack def apply (cases l) by auto
lemma is backtrack assignI :[[is backtrack A ′ T ′ A; sem lit ′ l A ′ = None; x = var of lit l ]]=⇒ is backtrack (assign lit A ′ l) (insert x T ′) Aunfolding is backtrack def backtrack defapply (cases l ; simp; intro conjI )by (auto simp: restrict map def )
context unsat input begin
definition assign lit bt ≡ λA T l . doE {EASSERT (sem lit ′ 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 ). i 6=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∗))
77
(λ(C ,(A ′,T ′),it ′). ∃ l .lz string litZ it l it ′
∧ it invar it ′
∧ C =clause α l∧ ¬is blocked A C∧ A ′ = and not C A C∧ T ′ = { 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 rup proof bt :: state ⇒ ′it ⇒ (nat× ′prf ) ⇒ ( , state × ′it × (nat× ′prf )) enres wherecheck rup proof bt ≡ λ(CM ,A) it prf . doE {
(i ,prf ) ← parse id prf ;CHECK (i /∈cm ids CM ) (mkp errNprf STR ′′Duplicate ID ′′ 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 STR ′′Expected conflict clause ′′ confl id prf );EASSERT (i /∈ cm ids CM );CM ← add clause i C CM ;ERETURN ((CM ,backtrack A T ),it ,prf )}
definition check rat proof bt :: state ⇒ ′it ⇒ (nat × ′prf ) ⇒ ( ,state × ′it × (nat × ′prf )) enres wherecheck rat proof bt ≡ λ(CM ,A) it prf . doE {
(reslit ,prf ) ← parse prf literal prf ;
CHECK (sem lit ′ reslit A 6= Some False)(mkp errprf STR ′′Resolution literal is false ′′ prf );
(i ,prf ) ← parse id prf ;CHECK (i /∈cm ids CM ) (mkp errNprf STR ′′Duplicate ID ′′ i prf );(C ,(A,T ),it) ← parse check blocked bt A it ;CHECK (reslit ∈ C ) (mkp errprf STR ′′Resolution literal not in clause ′′ prf );((A,T ),prf ) ← apply units bt CM A T prf ;candidates ← get rat candidates CM A reslit ;(A,prf ) ← check candidates ′ 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 ;CHECK (is conflict clause A confl)
EASSERT (i /∈ cm ids CM );CM ← add clause i C CM ;ERETURN ((CM ,backtrack A T ),it ,prf )}
definition bt assign rel A≡ { ((A ′,T ),A ′) | A ′ T . T ⊆ dom A ′ ∧ A = A ′|‘ (−T ) }
definition bt need bt rel A0
≡ br (λ . A0) (λ(A ′,T ′). T ′⊆dom A ′ ∧ backtrack A ′ T ′ = 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 Aiunfolding bt assign rel def bt need bt rel def
79
by (auto simp: backtrack def in br conv)
lemma bt in bta rel : T ⊆ dom A =⇒ ((A,T ),A)∈bt assign rel (backtrack A T )by (auto simp: bt assign rel def backtrack def )
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 ))apply (auto
simp: pw ele iff refine pw simpssimp: and not C bt def and not C def bt assign rel def restrict map defsplit !: if splits intro!: ext)
apply forceapply forceapply (metis var of lit .elims)apply forceapply forceapply (force simp: is blocked alt sem clause ′ true conv)apply (force simp: is blocked alt sem clause ′ true conv)done
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)
subgoal for litby (cases lit ; auto simp: and not C def ; force)
subgoalapply (
clarsimpsimp: and not C def restrict map def is blocked defintro!: ext ;
safe)apply (force|force simp: sem clause ′ true conv)+done
subgoal by autodone
lemma assign lit bt refine[refine]:[[ sem lit ′ 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))
unfolding assign lit bt def assign lit def bt assign rel defapply refine vcgapplyS simpsubgoal by (cases l) autosubgoal by (cases l ; auto simp: restrict map def intro!: ext)done
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)
unfolding apply unit bt def apply unit defapply refine rcgapply refine dref typeapply (vc solve dest !: bt rel simps)
80
done
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)
unfolding apply units bt def apply units defsupply RELATESI [of bt assign rel A for A, refine dref RELATES ]apply refine rcgapply refine dref typeapply autodone
term check rup prooflemma 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 )unfolding check rup proof bt def check rup proof defapply refine rcgapply refine dref typeapply (auto simp: bt in bta rel dest !: bt rel simps)done
lemma check rat proof bt refine[refine]:[[ (si ,s)∈Id ; (iti ,it)∈Id ; (prfi ,prf )∈Id ]]=⇒ check rat proof bt si iti prfi ≤⇓E UNIV Id (check rat proof s it prf )unfolding check rat proof bt def check rat proof defapply refine rcgapply refine dref typeapply (auto simp: bt in bta rel dest !: bt rel simps)done
definition verify unsat bt F begin F end it prf ≡ doE {EASSERT (it invar it);
(CM ,prf ) ← init rat counts prf ;
CM ← read cnf new F end F begin CM ;
let s = (CM ,Map.empty);
EWHILEIT(λSome ( ,it , ) ⇒ it invar it | None ⇒ True)(λs. s 6=None)(λs.
doE {EASSERT (s 6=None);let (s,it ,prf ) = the s;
EASSERT (it invar it);
check item bt s it prf}) (Some (s,it ,prf ));ERETURN ()(∗CHECK (is None s) (mkp err ′′Proof did not contain conflict declaration ′′)∗)}
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 )
definition cref rel≡ { (cref ,C ). ∃ l it ′. lz string litZ cref l it ′
82
∧ it invar it ′
∧ C = clause α l}definition next it rel≡ { (cref ,it ′). ∃ l . lz string litZ cref l it ′ ∧ it invar it ′}
definition clausemap1 rel≡ (Id → 〈cref rel〉option rel) ×r (Id → 〈br set (λ . True)〉option rel)
abbreviation state1 rel ≡ clausemap1 rel ×r Id
definition parse check clause cref c f s ≡ doE {(it ,s) ← parse lz (mkp err STR ′′Parsed beyond end ′′) litZ it end cref c (λx s. doE {
EASSERT (x 6= litZ );let l = lit α x ;f l s}) s;ERETURN (s,it)}
lemma parse check clause rule aux :assumes I [simp]: I {} sassumes F RL:∧
C l s. [[I C s; c s]] =⇒ f l s ≤ ESPEC (λ . True) (I (insert l C ))assumes [simp]: it invar crefshows parse check clause cref c f s ≤ ESPEC
((∗ TODO : Spec that parsing failed ∗) λ . True)(λ(s,it ′). ∃C .
I C s∧ (c s −→ it invar it ′
∧ (cref ,C ) ∈ cref rel∧ (cref ,it ′) ∈ next it rel)
)unfolding parse check clause defapply (refine vcg parse lz rule[where Φ=λl s. I (clause α l) s])apply (vc solve simp: F RL)apply (auto simp: cref rel def next it rel def dest !: itran invarD)done
lemma parse check clause rule:assumes I0 : I {} sassumes [simp]: it invar crefassumes F RL:∧
C l s. [[I C s; c s]] =⇒ f l s ≤ ESPEC (λ . True) (I (insert l C ))assumes
∧C s it ′. [[I C s; ¬c s ]] =⇒ Q (s,it ′)
assumes∧
C s it ′.[[ I C s; c s; (cref ,it ′)∈next it rel ; (cref ,C )∈cref rel ]] =⇒ Q (s,it ′)
shows parse check clause cref c f s ≤ ESPEC (λ . True) Qapply (rule order trans)apply (rule parse check clause rule aux [of I , OF I0 ])apply (erule (1 ) F RL)apply factusing assms(4 ,5 )by (fastforce simp: ESPEC rule iff next it rel def cref rel def )
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 relassumes I0 : I {} sassumes F RL:
∧C1 l s.
[[ I C1 s; C1⊆C ; l∈C ; c s ]] =⇒ f l s ≤ ESPEC E (I (insert l C1 ))
83
assumes T IMP :∧
s. [[ c s; I C s ]] =⇒ P sassumes C IMP :
∧s C1 . [[ ¬c s; C1⊆C ; I C1 s ]] =⇒ P s
shows iterate clause cref c f s ≤ ESPEC E Pproof −
from CR obtain l it ′ whereISLZ : lz string litZ cref l it ′
and INV : it invar it ′
and [simp]: C = clause α lby (auto simp: cref rel def )
show ?thesisunfolding iterate clause defapply (refine vcg
iterate lz rule[OF ISLZ , where Φ=λl1 l2 s. I (clause α l1 ) s])apply vc solveapplyS (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)done
qed
definition check unit clause1 A cref ≡ doE {ul ← iterate clause cref (λul . True) (λl ul . doE {
CHECK (sem lit ′ l A 6= Some True)(mkp err STR ′′True literal in clause assumed to be unit ′′);
if (sem lit ′ l A = Some False) then ERETURN ulelse doE {
CHECK (ul = None ∨ ul = Some l)(mkp err STR ′′2−undec in clause assumed to be unit ′′);
ERETURN (Some l)}}) None;CHECK (ul 6= None) (mkp err STR ′′Conflict in clause assumed to be unit ′′);EASSERT (ul 6= None);ERETURN (the ul)}
lemma check unit clause1 refine[refine]:assumes [simplified , simp]: (Ai ,A)∈Idassumes CR: (cref ,C )∈cref relshows check unit clause1 Ai cref ≤⇓EUNIV Id (check unit clause A C )unfolding check unit clause1 def check unit clause def econc fun univ idapply refine vcgapply (refine vcg iterate clause rule[OF CR, where
I =λC ′ ul . case ul ofNone ⇒ sem clause ′ C ′ A = Some False| Some l ⇒ is unit lit A C ′ l ]
)apply (auto split : option.splits simp: is unit clause def )subgoal by (smt Diff iff insert iff is unit lit def sem clause ′ false conv)subgoal by (smt Diff empty Diff insert0 boolopt cases aux .cases
insertI1 insert Diff1 is unit lit defsem clause ′ false conv)
subgoal by (simp add : is unit lit def )subgoal apply (drule (2 ) is unit lit unique ss)
using sem not false the unit lit by blastsubgoal using is unit clauseI unit contains no true by blastsubgoal using is unit clauseI unit contains no true by blastsubgoal by (simp add : unit clause sem ′)done
84
definition resolve id1 ≡ λ(CM , ) i . doE {CHECK (i∈dom CM ) (mkp errN STR ′′Invalid clause id ′′ i);ERETURN (the (CM i))}
lemma resolve id1 refine[refine]:[[ (CMi ,CM )∈clausemap1 rel ; (ii ,i)∈Id ]]=⇒ resolve id1 CMi ii ≤⇓EUNIV cref rel (resolve id CM i)unfolding resolve id1 def resolve id def clausemap1 rel defapply (cases CM ; cases CMi)apply (clarsimp simp: pw ele iff refine pw simps)apply (auto dest !: fun relD [where x=i and x ′=i ] elim: option relE)done
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}
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 ≤ ⇓EUNIV Id (apply unit bt i CM A T )unfolding apply unit bt def apply unit1 bt defapply refine rcgapply (vc solve)done
definition apply units1 bt CM A T prf ≡ doE {(i ,prf ) ← parse idZ prf ;((A,T ),i ,prf ) ← EWHILET
(λ((A,T ),i ,prf ). i 6=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)unfolding apply units1 bt def apply units bt defapply refine rcgapply refine dref typeapply vc solvedone
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 ≤ ⇓EUNIV Id (apply unit i CM A)unfolding apply unit def apply unit1 defapply refine rcgapply (vc solve)done
85
definition apply units1 CM A prf ≡ doE {(i ,prf ) ← parse idZ prf ;(A,i ,prf ) ← EWHILET
(λ(A,i ,prf ). i 6=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)unfolding apply units1 def apply units defapply refine rcgapply refine dref typeapply vc solvedone
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}apply (auto simp: is blocked def sem clause ′ true conv)apply (auto simp: dom def and not C def split : if split asm)apply forceapply forcesubgoal for l by (cases l) autodone
lemma dom and not C eq : dom (and not C A C ) = dom A ∪ var of lit‘Capply (safe; clarsimp? )apply (force simp: and not C def dom def split : if split asm) []apply (force simp: and not C def ) []subgoal for l by (cases l) (auto simp: and not C def )done
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}
apply (safe; clarsimp? )subgoal
apply (clarsimpsimp: is backtrack def backtrack defsimp: dom and not C eq restrict map def )
parse check clause rule[where I =λC (A ′,T ′).is backtrack A ′ T ′ A∧ ¬is blocked A C∧ A ′ = and not C A C
])apply (vc solve
simp: and not insert Falsesimp: is backtrack assignI is backtrack not undec)
subgoal by (autosimp: is blocked insert iff sem lit and not C convintro: is blockedI1 is blockedI2 ) []
subgoal by (auto simp: not Some bool if ) []subgoal by (auto simp: is blocked insert iff sem lit and not C None conv) []subgoal by (auto simp: simp: and not insert None) []subgoal
≤⇓E UNIV Id (CHECK (is conflict clause A C ) msg)proof −
have ES REW : ⇓E UNIV Id (CHECK (is conflict clause A C ) msg)= ESPEC (λ . ¬is conflict clause A C ) (λ . is conflict clause A C )by (auto simp: pw eeq iff refine pw simps)
show ?thesisunfolding check conflict clause1 def ES REWapply (refine vcg
iterate clause rule[OF CR, where I =λC . is conflict clause A C ])by (auto simp: sem clause ′ false conv)
87
qed
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 relshows lit in clause1 cref lc ≤ ESPEC (λ . False) (λr . r ←→ lc∈C )unfolding lit in clause1 defapply (refine vcg iterate clause rule[OF CR, where I =λC r . r ←→ lc∈C ])by auto
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 1else if (sem lit ′ l A = Some True) then ERETURN 2else 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 relshows lit in clause and not true A cref lc
≤ ESPEC (λ . False)(λr . r ←→ lc∈C ∧ sem clause ′ (C−{lc}) A 6= Some True)
unfolding lit in clause and not true defapply (refine vcg iterate clause rule[OF CR, where I =λC f . f ∈{0 ,1 ,2}
∧ (f =2 ←→ sem clause ′ (C−{lc}) A = Some True)∧ (f =1 −→ lc∈C )∧ (f =0 −→ lc /∈C )])
by (vc solve simp: insert minus eq sem clause ′ true conv solve: asm rl)
definition and not C excl A cref exl ≡ doE {iterate clause cref (λ . True) (λl (A,T ). doE {
if (l 6= exl) then doE {EASSERT (sem lit ′ l A 6= Some True);if (sem lit ′ 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)∈Idassumes CR: (cref ,C ) ∈ cref relassumes [simplified ,simp]: (exli ,exl)∈Id
shows and not C excl Ai cref exli≤⇓E UNIV (Id×rId) (and not C bt A (C−{exl}))
unfolding and not C bt defapply (rule EASSERT bind refine right)apply (simp add : econc fun ERETURN )unfolding and not C excl def
88
apply (refine vcg iterate clause rule[OF CR,where I =λC ′ (A ′,T ′). A ′ = and not C A (C ′ − {exl})
∧ is backtrack A ′ T ′ A])apply (vc solve simp: insert minus eq)subgoal
by (autosimp: sem lit and not C conv sem clause ′ true conv is blocked alt)
subgoalby (meson boolopt cases aux .cases is backtrack not undec)
subgoalby (metis (full types) and not insert None boolopt cases aux .cases
insert minus eq)subgoal
by (metis (full types) boolopt cases aux .cases is backtrack assignIsem lit ′ none conv var of lit neg eq)
subgoal by (simp add : and not insert False)subgoal using backtrack and not C trail eq by blastdone
definition get rat candidates1:: ( ′it) clausemap1 ⇒ (var ⇀ bool) ⇒ var literal ⇒ ( ,id set) enreswhereget rat candidates1 ≡ λ(CM ,RL) A l . doE {
let l = neg lit l ;let cands raw = RL l ;CHECK (¬is None cands raw) (mkp err STR ′′Resolution literal not declared ′′);(∗ 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 relassumes [simplified , simp]: (Ai ,A)∈Id (resliti ,reslit)∈Idshows get rat candidates1 CMi Ai resliti
≤⇓E UNIV (Id) (get rat candidates CM A reslit)unfolding get rat candidates1 def get rat candidates defapply (rewrite at Let (RL ) in case CMi of (CM ,RL) ⇒ ◊ Let def )apply refine rcgapply refine dref typeapply vc solvesubgoal
using CMRby (auto
simp: clausemap1 rel def cref rel defdest !: fun relD [where x=neg lit reslit and x ′=neg lit reslit ]elim: option relE
89
)
subgoal premises prems for CM RL CMi RLi cands rawproof −
from CMR prems haveCM ref : (CMi , CM ) ∈ Id → 〈cref rel〉option rel andRL ref : (RLi , RL) ∈ Id → 〈br set (λ . True)〉option relby (auto simp: clausemap1 rel def in br conv)
define cands rawi where cands rawi = the (RLi (neg lit reslit))from prems fun relD [OF RL ref IdI [of neg lit reslit ]]have [simp]: cands raw = set cands rawi
unfolding cands rawi def by (auto simp: in br conv elim: option relE)note cands rawi def [symmetric,simp]
show ?thesisapply (refine vcg enfoldli rule[where I =λl1 l2 s.
(∗distinct (l1@l2 )∧∗) s = { i∈set l1 . ∃C .
CM i = Some C∧ neg lit reslit∈C∧ sem clause ′ (C − {neg lit reslit}) A 6= Some True }])
apply vc solve
subgoal for i l1 l2using fun relD [OF CM ref IdI [of i ]]by (auto elim: option relE simp: cref rel def in br conv)
focus apply (rename tac i l1 l2 )apply (subgoal tac (the (CMi i), the (CM i)) ∈ cref rel , assumption)subgoal for i l1 l2
using fun relD [OF CM ref IdI [of i ]]by (force elim!: option relE simp: cref rel def in br conv)
solvedsubgoal for i l1 l2
using fun relD [OF CM ref IdI [of i ]]by (auto elim!: option relE simp: cref rel def in br conv)
subgoal for i l1 l2using fun relD [OF CM ref IdI [of i ]]by (auto elim!: option relE simp: cref rel def in br conv)
doneqeddone
definition backtrack1 A T ≡ do {ASSUME (finite T );FOREACH T (λx A. RETURN (A(x :=None))) A}
lemma backtrack1 correct [THEN SPEC trans, refine vcg ]:backtrack1 A T ≤ SPEC (λr . r = backtrack A T )unfolding backtrack1 defapply (refine vcg FOREACH rule[where I =λit A ′. A ′ = backtrack A (T−it)])apply (vc solve simp: backtrack def )by (auto simp: it step insert iff restrict map def intro!: ext)
definition (in −) abs cr register ndj:: ′a literal ⇒ ′id ⇒ ( ′a literal ⇀ ′id list) ⇒ ( ′a literal ⇀ ′id list)where abs cr register ndj l cid cr ≡ case cr l of
None ⇒ cr | Some s ⇒ cr(l 7→ cid#s)
90
definition register clause1 cid cref RL ≡ doE {iterate clause cref (λ . True) (λl RL. doE {
ERETURN (abs cr register ndj l cid RL)}) RL}
definition RL upd cid C RL ≡ (λl . case RL l ofNone ⇒ None| Some s ⇒ if l∈C then Some (insert cid s) else Some s)
add clause1 ii cref CMi ≤⇓E UNIV clausemap1 rel (add clause i C CM )unfolding add clause1 def add clause defapply (cases CMi ; cases CM ; simp only : split)subgoal for RLi RL
apply refine vcgsupply RELATESI [of Id → , refine dref RELATES ]supply RELATESI [of br set (λ . True), refine dref RELATES ]apply refine dref typeapplyS assumptionapplyS (erule fun relD [rotated , where f =RLi and f ′=RL];
auto simp: clausemap1 rel def )
apply1 clarsimp subgoal for RLi ′ lapply (drule fun relD [OF IdI [of l ]])apply (cases RLi ′ l ; cases RL l ; simp)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 convsplit : if split asm)
donesubgoal
apply (simp add : clausemap1 rel def )apply parametricityby auto
(i ,prf ) ← parse id prf ;CHECK (i /∈cm ids CM ) (mkp errNprf STR ′′Duplicate ID ′′ 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 ((CM ,A),it ,prf )}
lemma cm1 rel imp eq ids[simp]:assumes (cm1 ,cm)∈clausemap1 relshows cm ids cm1 = cm ids cm
show ?thesisunfolding check rup proof1 def check rup proof bt defunfolding REWusing SRapply refine rcgapply refine dref typeapply (vc solve)subgoal by (intro refine dref RELATES)subgoal by refine vcg autodone
qed
definition check rat candidates part1 CM reslit candidates A prf ≡check candidates ′ 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:: ( ′it) state1 ⇒ ′it ⇒ (nat × ′prf ) ⇒ ( ,( ′it) state1 × ′it × (nat × ′prf )) enreswherecheck rat proof1 ≡ λ(CM ,A) it prf . doE {
(reslit ,prf ) ← parse prf literal prf ;CHECK (sem lit ′ reslit A 6= Some False)
(mkp errprf STR ′′Resolution literal is false ′′ prf );(i ,prf ) ← parse id prf ;CHECK (i /∈cm ids CM ) (mkp errNprf STR ′′Ids must be strictly increasing ′′ i prf );(cref ,(A,T ),it) ← parse check blocked1 A it ;
CHECK monadic (lit in clause1 cref reslit)(mkp errprf STR ′′Resolution literal not in clause ′′ prf );
((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 ((CM ,A),it ,prf )}
93
lemma check rat proof1 refine[refine]:assumes SR: (si ,s)∈state1 relassumes [simplified , simp]: (iti ,it)∈Id (prfi ,prf )∈Idshows check rat proof1 si iti prfi
≤⇓E UNIV (state1 rel ×r Id ×r Id) (check rat proof bt s it prf )proof −
have REW1 : ERETURN (i ,CM , backtrack A T ) = doE {let A = backtrack A T ;ERETURN (i ,CM ,A)} for i CM A Tby auto
have REW2 : ERETURN (backtrack A T , it) = doE {let A = backtrack A T ;ERETURN (A,it)} for A T itby auto
show ?thesisunfolding check rat proof1 def check rat proof bt def
check rat candidates part1 defunfolding REW1 REW2using SRapply refine vcgsupply RELATESI [of Id → Id , refine dref RELATES ]apply refine dref typesupply [[goals limit=1 ]]apply (vc solve solve: asm rl RELATESI )done
definition (in −) cm empty1 :: ( ′cref ) clausemap1where cm empty1 ≡ (Map.empty , Map.empty)
lemma cm empty refine[refine]: (cm empty1 , cm empty) ∈ clausemap1 relunfolding cm empty1 def cm empty def clausemap1 rel defby auto
definition is syn taut1 cref A ≡ doE {EASSERT (A = Map.empty);(t ,A) ← iterate clause cref (λ(t ,A). ¬t) (λl (t ,A). doE {
if (sem lit ′ l A = Some False) then ERETURN (True,A)else if sem lit ′ l A = Some True then ERETURN (False,A) (∗ DUP literal . Perhaps check for it? ∗)else doE {
EASSERT (sem lit ′ 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 relassumes [simp]: A = Map.emptyshows is syn taut1 cref A
≤ ESPEC (λ . False) (λ(t ,A). (t ←→ is syn taut C ) ∧ A=Map.empty)
96
proof −show ?thesis
unfolding is syn taut1 defapply (refine vcg
iterate clause rule[OF CR, where I =λC (t ,A).(t −→ is syn taut C )∧ (¬t −→ (∀ l . sem lit ′ l A = Some True ←→ l∈C ))∧ dom A ⊆ var of lit‘C ]
iterate clause rule[OF CR,where I =λC ′ A. (dom A ⊆ var of lit‘ (C − C ′))]
)apply (vc solve simp: not Some bool if )apply (auto)apply (auto simp: is syn taut def ) []apply (auto simp: sem lit ′ assign conv split : if splits) []apply (force simp: sem lit ′ assign conv split : if splits) []subgoal for l by (case tac l ; auto split : if splits)subgoal premises prems for Aproof −
from prems haveSL: ∀ l . sem lit ′ l A = Some True ←→ l∈C andTAUT : is syn taut Cby auto
from TAUT obtain l where l∈C neg lit l ∈ Cby (auto simp: is syn taut conv)
with SLhave sem lit ′ l A = Some True sem lit ′ (neg lit l) A = Some True
by (auto simp del : sem neg lit ′)thus False by simp
qedsubgoal by fastforcesubgoal by (fastforce simp: is syn taut def )done
qed
definition read cnf new1:: ′it ⇒ ′it ⇒ ′it clausemap1 ⇒ ( , ′it clausemap1 ) enreswhere read cnf new1 itE it CM ≡ doE {
(CM ,next id ,A) ← tok fold itE it (λit (CM ,next id ,A). doE {(it ′,(t ,A)) ← read clause check taut itE it A;if t then ERETURN (it ′, (CM ,next id+1 ,A))else doE {
EASSERT (∃ l it ′. lz string litZ it l it ′);let C = it ;CM ← add clause1 next id C CM ;ERETURN (it ′,(CM ,next id+1 ,A))}}) (CM ,1 ,Map.empty);ERETURN (CM )}
lemma read cnf new1 refine[refine]:assumes [simplified ,simp]: (F begini , F begin)∈Id (F endi ,F end)∈Idassumes [simp]: (CMi ,CM )∈clausemap1 relshows read cnf new1 F endi F begini CMi
≤ ⇓E UNIV (clausemap1 rel)(read cnf new F end F begin CM )
unfolding read cnf new1 def read cnf new defapply refine rcgsupply RELATESI [of clausemap1 rel , refine dref RELATES ]
97
apply refine dref typeapply vc solveapplyS autosubgoal unfolding cref rel def by autodone
definition cm init lit1:: var literal ⇒ ( ′it) clausemap1 ⇒ ( ,( ′it) clausemap1 ) enreswhere 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 STR ′′Expected RAT counts item ′′ prf );
lemma init rat counts1 refine[refine]:assumes [simplified ,simp]: (prfi ,prf )∈Idshows init rat counts1 prfi ≤⇓E UNIV (clausemap1 rel ×r Id) (init rat counts prf )unfolding init rat counts1 def init rat counts def
cm init lit def cm init lit1 defapply refine rcgsupply RELATESI [of clausemap1 rel , refine dref RELATES ]apply refine dref typeapply (vc solve simp: cm empty refine)subgoal by (auto simp: clausemap1 rel def in br conv dest !: fun relD)done
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 )
synth-definition check unit clause1 bdis [enres unfolds]: check unit clause1 A cref = ◊
99
apply (rule CNV eqD)unfolding check unit clause1 def iterate clause defapply opt enres unfoldapply (rule CNV I )done
— Optimization to reduce map lookupslemma resolve id1 alt : resolve id1 = (λ(CM , ) i . doE {
let x = CM i ;if (x=None) then THROW (mkp errN STR ′′Invalid clause id ′′ i)else ERETURN (the x )})unfolding resolve id1 defapply (intro ext)apply (auto simp: pw eeq iff refine pw simps Let def split : if split asm)done
synth-definition resolve id1 bd is [enres unfolds]: resolve id1 CM cid = ◊apply (rule CNV eqD)unfolding resolve id1 altapply opt enres unfoldapply (rule CNV I )done
synth-definition apply unit1 bt bdis [enres unfolds]: apply unit1 bt i CM A T = ◊apply (rule CNV eqD)unfolding apply unit1 bt def assign lit bt defapply opt enres unfoldapply (rule CNV I )done
synth-definition apply units1 bt bdis [enres unfolds]: apply units1 bt CM A T units = ◊apply (rule CNV eqD)unfolding apply units1 bt defapply opt enres unfoldapply (rule CNV I )done
synth-definition apply unit1 bd is [enres unfolds]: apply unit1 i CM A = ◊apply (rule CNV eqD)unfolding apply unit1 defapply opt enres unfoldapply (rule CNV I )done
synth-definition apply units1 bdis [enres unfolds]: apply units1 CM A units = ◊apply (rule CNV eqD)unfolding apply units1 defapply opt enres unfoldapply (rule CNV I )done
synth-definition and not C excl bdis [enres breakdown]: and not C excl A cref exl = enres lift ◊unfolding and not C excl def iterate clause defby opt enres unfold
synth-definition lit in clause and not true bdis [enres breakdown]: lit in clause and not true A cref lc = enres lift ◊unfolding lit in clause and not true def iterate clause defby opt enres unfold
synth-definition lit in clause bdis [enres breakdown]: lit in clause1 cref lc = enres lift ◊unfolding lit in clause1 def iterate clause defby opt enres unfold
synth-definition get rat candidates1 bdis [enres unfolds]: get rat candidates1 CM A l = ◊apply (rule CNV eqD)unfolding get rat candidates1 defapply opt enres unfoldapply (rule CNV I )done
synth-definition add clause1 bdis [enres breakdown]: add clause1 i it CM = enres lift ◊unfolding add clause1 def register clause1 def iterate clause defby opt enres unfold
synth-definition check rup proof1 bdis [enres unfolds]: check rup proof1 s it prf = ◊apply (rule CNV eqD)unfolding check rup proof1 defapply opt enres unfoldapply (rule CNV I )done
term check rat candidates part1synth-definition check rat candidates part1 bd
is [enres unfolds]:check rat candidates part1 CM reslit candidates A prf = ◊
apply (rule CNV eqD)unfolding check rat candidates part1 def
synth-definition check rat proof1 bdis [enres unfolds]: check rat proof1 s it prf = ◊apply (rule CNV eqD)unfolding check rat proof1 defapply opt enres unfoldapply (rule CNV I )done
synth-definition check item1 bd is [enres unfolds]: check item1 s it prf = ◊apply (rule CNV eqD)unfolding check item1 deforestapply opt enres unfoldapply (rule CNV I )done
synth-definition is syn taut1 bdis [enres breakdown]: is syn taut1 cref A = enres lift ◊unfolding is syn taut1 def iterate clause defby opt enres unfold
synth-definition read clause check taut bdis [enres unfolds]: read clause check taut F end F begin A = ◊apply (rule CNV eqD)unfolding read clause check taut defapply opt enres unfoldapply (rule CNV I )done
synth-definition read cnf new1 bdis [enres unfolds]: read cnf new1 F begin F end CM = ◊apply (rule CNV eqD)unfolding read cnf new1 def tok fold defapply opt enres unfoldapply (rule CNV I )done
synth-definition init rat counts1 bdis [enres unfolds]: init rat counts1 prf = ◊apply (rule CNV eqD)unfolding init rat counts1 deforest cm init lit1 defapply opt enres unfoldapply (rule CNV I )done
synth-definition verify unsat1 bdis [enres unfolds]: verify unsat1 F begin F end it prf = ◊apply (rule CNV eqD)unfolding verify unsat1 defapply opt enres unfoldapply (rule CNV I )done
end
102
12.4.2 Instantiating Input Locale
locale GRAT def loc = DB2 def loc +fixes prf next :: ′prf ⇒ int × ′prf
locale GRAT loc = DB2 loc DB frml end + GRAT def loc DB frml end prf nextfor DB frml end and prf next :: ′prf ⇒ int × ′prf
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 locuses 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]
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 locuses 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 locuses 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 extr-loc 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 locuses 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]
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 locuses 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 locuses 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 locuses check rat proof1 bd def [unfolded extrloc unfolds]
declare (in GRAT loc) check rat proof2 loc.refine[extrloc unfolds]
104
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]
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 locuses 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]
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 locuses 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]
sepref-register apply units2 :: ⇒ ⇒ (nat) clausemap1 ⇒:: int list ⇒ ′prf i prfn ⇒ i cm ⇒ i assignment ⇒ ′prf i prfi⇒ ( ′prf i prfi error + i assignment × ′prf i prfi) nres
(assignment assn ×a list set assn nat assn) ×a prfi assnunfolding apply units2 bt defapply (rewrite in insert (var of lit ) fold set insert dj )supply [[id debug , goals limit = 1 ]]by sepref
sepref-register apply units2 bt :: ⇒ ⇒ (nat) clausemap1 ⇒:: int list ⇒ ′prf i prfn ⇒ i cm ⇒ i assignment ⇒ nat set ⇒ ′prf i prfi⇒ ( ′prf i prfi error + (i assignment × nat set) × ′prf i prfi) nres
→a prod assn assignment assn (list set assn nat assn)unfolding and not C excl2 defapply (rewrite at ( , ,◊) ls.fold custom empty)apply (rewrite in insert (var of lit ) fold set insert dj )by sepref
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
sepref-definition lit in clause and not true3is uncurry3 lit in clause and not true2:: liti .a assnk ∗a (assignment assn)k ∗a liti .it assnk ∗a (pure lit rel)k
→a bool assnunfolding lit in clause and not true2 defby sepref
lemmas [sepref fr rules] = lit in clause and not true3 .refinesepref-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 assnk ∗a cm assnk ∗a (assignment assn)k ∗a (pure lit rel)k
→a sum assn errorp assn (list set assn nat assn)unfolding get rat candidates2 defsupply option.splits[split ]apply (rewrite ndls.fold custom empty)apply (rewrite in RETURN (Inr ◊) fold ndls ls copy)by sepref
sepref-register get rat candidates2:: int list ⇒ i cm ⇒ i assignment ⇒ nat literal⇒ ( ′prf 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 assnunfolding backtrack2 def
109
by seprefsepref-register backtrack2 :: (nat⇀bool) ⇒
:: i assignment ⇒ nat set ⇒ i assignment nreslemmas [sepref fr rules] = backtrack3 .refine
lemma not in cm ids unf : i /∈cm ids CM ←→ (case CM of (CM , ) ⇒ is None (CM i))unfolding cm ids def by (cases CM ) (auto split : option.splits)
sepref-register check rat candidates part2 :: ⇒ ⇒ (nat) clausemap1 ⇒:: int list ⇒ ′prf i prfn ⇒ i cm ⇒ nat literal ⇒ nat set ⇒ i assignment ⇒ ′prf i prfi⇒ ( ′prf i prfi error + i assignment × ′prf i prfi) nres
lemmas [sepref fr rules] = check rat candidates part3 .refine
term check rat proof2sepref-definition check rat proof3 is uncurry4 check rat proof2
→a errorp assn +a state assn ′ ×a liti .it assn ×a prfi assnunfolding check rat proof2 def short circuit convsupply [[goals limit = 1 , id debug ]]supply if splits[split !]apply (rewrite not in cm ids unf )by sepref
sepref-register check rat proof2:: int list ⇒ ′prf i prfn ⇒ i state ′ ⇒ nat ⇒ ′prf i prfi⇒ ( ′prf i prfi error + i state ′ × nat × ′prf i prfi) nres
lemmas [sepref fr rules] = check rat proof3 .refine
sepref-register check item2:: int list ⇒ ′prf i prfn ⇒ i state ′ ⇒ nat ⇒ ′prf i prfi⇒ ( ′prf i prfi error + (i state ′ × nat × ′prf i prfi) option) nres
lemmas [sepref fr rules] = check item3 .refine
term is syn taut2sepref-definition is syn taut3 is uncurry2 is syn taut2
assumes SEG: liti .seg F begin lst F endassumes itI [simp]: it invar F end it invar itshows<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
proof −note verify unsat2 .refine[OF GRAT loc axioms, symmetric, THEN meta eq to obj eq ]also note verify unsat2 loc.refine[symmetric,THEN meta eq to obj eq ]also note verify unsat1 bd .refine[symmetric]also note verify unsat1 refine[OF IdI IdI IdI ]also note verify unsat bt refine[OF IdI IdI IdI ]also note verify unsat correct [OF SEG itI ]finally have C1 : verify unsat2 DB prf next F begin F end it prf≤ ESPEC (λ . True) (λ . F invar lst ∧ ¬ sat ((F α lst)))
by (auto simp: pw ele iff refine pw simps)
from C1 have NF : nofail (verify unsat2 DB prf next F begin F end it prf )by (auto simp: pw ele iff refine pw simps)
note A = verify unsat3 .refine[of DB , to hnr ]note A = A[
of prf prf it it F end F end F begin F begin prf next prf next DB DBi ,unfolded autoref tag defs]
note A = A[THEN hn refineD ]note A = A[OF NF ]note A = A[
unfolded hn ctxt def liti .it assn def liti .a assn defb assn pure conv list assn pure conv sum assn pure convoption assn pure conv prod assn pure conv ,
unfolded pure def ,simplified , rule format]
from C1 have 1 : RETURN x ≤ verify unsat2 DB prf next F begin F end it prf=⇒ ¬isl x −→ F invar lst ∧ ¬sat (F α lst) for xunfolding enres unfoldsapply (cases x )apply (auto simp: pw le iff refine pw simps)done
from SEG have I begin: liti .I F begin by auto
show ?thesisapply (rule cons rule[OF A])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)done
qedend
112
Main correctness theorem: Given an array DBi that contains the integers DB, the verification algorithmdoes not change the array, and if it returns a non-Inl value, the formula in the array is unsatisfiable.
verify unsat split impl wrapper DBi prf next F end it prf<λresult . DBi 7→a DB ∗ ↑(¬isl result −→ verify unsat spec DB F end)>t
proof −{
assume A: 1 ≤ F end F end ≤ length DB 0 < it it ≤ length DB
then interpret GRAT loc DB F endapply unfold locales by auto
have SEG: liti .seg 1 (slice 1 F end DB) F endusing 〈1 ≤ F end 〉 〈F end ≤ length DB 〉
by (simp add : liti .seg sliceI )
have INV : it invar F end it invar itsubgoal
by (meson SEG it end invar it invar imp ranitran invarD liti .itran alt liti .itran refl liti .seg invar2 )
subgoalby (metis 〈0 < it〉 〈it ≤ length DB 〉 liti .seg exists exists leI
it invar imp ranitran invarD it end invar liti .itran alt liti .itran reflliti .seg invar1 )
done
have U1 : slice 1 F end DB = tl (take F end DB)unfolding Misc.slice defby (metis One nat def drop 0 drop Suc Cons drop take list .sel(3 ) tl drop)
have U2 : F invar (tl (take F end DB)) ∧ ¬ sat (F α (tl (take F end DB)))←→ verify unsat spec DB F endunfolding verify unsat spec def clause DB valid def clause DB sat defusing A by auto
note verify unsat3 correct aux [OF SEG INV , unfolded U1 U2 ]} note [sep heap rules] = this
show ?thesisunfolding verify unsat split impl wrapper def by sep auto
qed
end
13 Satisfiability Check
theory Sat Checkimports Grat Basicbegin
13.1 Abstract Specification
locale sat input = input it invar ′ it next it peek it end for it invar ′ :: ′it ::linorder ⇒ booland it next it peek it end
context sat input begin
definition read assignment it ≡ doE {
113
let A = Map.empty ;check not end it ;(A, ) ← EWHILEIT (λ( ,it). it invar it ∧ it 6=it end) (λ( ,it). it peek it 6= litZ ) (λ(A,it). doE {
(l ,it) ← parse literal it ;check not end it ;CHECK (sem lit ′ l A 6= Some False) (mk errit STR ′′Contradictory assignment ′′ it);let A = assign lit A l ;ERETURN (A,it)}) (A,it);ERETURN A}
We merely specify that this does not fail, i.e. termination and assertions.
definition read clause check sat itE it A ≡ doE {EASSERT (it invar it ∧ it invar itE ∧ itran itE it end);parse lz
(mk errit STR ′′Parsed beyond end ′′ it)litZ itE it (λ . True) (λx r . doE {
let l = lit α x ;ERETURN (r ∨ (sem lit ′ 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 ′,r). ∃ l . lz string litZ it l it ′ ∧ itran it ′ itE
∧ (r ←→ sem clause ′ (clause α l) A = Some True))unfolding read clause check sat defapply (refine vcg parse lz rule[
where Φ = λl r . r ←→ sem clause ′ (clause α l) A = Some True] )
apply (vc solve simp: itran invarI )subgoal by (auto simp: sem clause ′ true conv)subgoal by autodone
definition check sat it itE A ≡ doE {tok fold itE it (λit . doE {
(it ′,r) ← read clause check sat itE it A;CHECK (r) (mk errit STR ′′Clause not satisfied by given assignment ′′ it);ERETURN (it ′,())}) ()}
term sem cnf
lemma obtain compat assignment : obtains σ where compat assignment A σproof
show compat assignment A (λx . A x = Some True) unfolding compat assignment def by autoqed
114
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))unfolding check sat defapply (refine vcg tok fold rule[where
Φ = λlst . ∀C∈set (map clause α lst). sem clause ′ C A = Some True and Z =litZ and l=lst]
)apply (vc solve simp: F invar def )subgoal
apply (rule obtain compat assignment [of A])apply (auto simp: F α def sat def sem cnf def dest : compat clause)done
done
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))unfolding verify sat defapply refine vcgapply assumptionby auto
end
13.2 Implementation
context sat input begin
13.2.1 Getting Out of Exception Monad
synth-definition read assignment bd is [enres unfolds]: read assignment it = ◊apply (rule CNV eqD)unfolding read assignment defapply opt enres unfoldapply (rule CNV I )done
synth-definition read clause check sat bd is [enres unfolds]: read clause check sat itE it A = ◊apply (rule CNV eqD)unfolding read clause check sat defapply opt enres unfoldapply (rule CNV I )done
synth-definition check sat bd is [enres unfolds]: check sat it itE = ◊apply (rule CNV eqD)unfolding check sat defapply opt enres unfoldapply (rule CNV I )done
synth-definition verify sat bd is [enres unfolds]: verify sat F begin F end it = ◊apply (rule CNV eqD)unfolding verify sat defapply opt enres unfoldapply (rule CNV I )done
115
end
13.3 Extraction from Locales
named-theorems extrloc unfolds
context DB2 loc beginsublocale sat input liti .I liti .next liti .peek liti .end
export-code verify sat impl wrapper checking SML imp
13.4 Correctness Theorem
context DB2 loc beginlemma verify sat3 correct :
assumes SEG: liti .seg F begin lst F endassumes itI [simp]: it invar F end it invar itshows <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
proof −note verify sat2 .refine[of DB F begin F end it , OF DB2 loc axioms,symmetric,THEN meta eq to obj eq ]also note verify sat2 loc.refine[symmetric,THEN meta eq to obj eq ]also note verify sat bd .refine[symmetric]also note verify sat correct [OF SEG itI order refl ]finally have C1 : verify sat2 DB F begin F end it ≤ ESPEC (λ . True) (λ . F invar lst ∧ sat (F α lst)) .
from C1 have NF : nofail (verify sat2 DB F begin F end it)by (auto simp: pw ele iff refine pw simps)
note A = verify sat3 .refine[of DB , to hnr , of it it F end F end F begin F begin, unfolded autoref tag defs]note A = A[THEN hn refineD ]note A = A[OF NF ]note A = A[
unfolded hn ctxt def liti .it assn def liti .a assn defb assn pure conv list assn pure conv sum assn pure conv option assn pure conv prod assn pure conv ,
unfolded pure def ,simplified , rule format
]
from C1 have 1 : RETURN x ≤ verify sat2 DB F begin F end it =⇒ ¬isl x −→ F invar lst ∧ sat (F α lst) forx
unfolding enres unfoldsapply (cases x )apply (auto simp: pw le iff refine pw simps)done
117
from SEG have I begin: liti .I F begin by auto
show ?thesisapply (rule cons rule[OF A])applyS sep autoapplyS (sep auto dest !: 1 simp: sum.disc eq case split : sum.splits)applyS (simp add : I begin)done
verify sat impl wrapper DBi F end<λresult . DBi 7→a DB ∗ ↑(¬isl result −→ verify sat spec DB F end)>t
proof −{
assume A: 1 ≤ F end F end ≤ length DB
then interpret DB2 loc DB F endapply unfold locales by auto
have SEG: liti .seg 1 (slice 1 F end DB) F endusing 〈1 ≤ F end 〉 〈F end ≤ length DB 〉
by (simp add : liti .seg sliceI )
have INV : it invar F endsubgoal
by (meson SEG it end invar it invar imp ranitran invarD liti .itran alt liti .itran refl liti .seg invar2 )
done
have U1 : slice 1 F end DB = tl (take F end DB)unfolding slice defby (metis Misc.slice def One nat def drop 0 drop Suc Cons drop take list .sel(3 ) tl drop)
have U2 : F invar (tl (take F end DB)) ∧ sat (F α (tl (take F end DB)))←→ verify sat spec DB F endunfolding verify sat spec def clause DB valid def clause DB sat def using Aby simp
note verify sat3 correct [OF SEG INV INV , unfolded U1 U2 ]} note [sep heap rules] = this
show ?thesisunfolding verify sat impl wrapper defby sep auto
qed
end
14 Code Generation and Summary of Correctness Theorems
theory Grat Check Code Exporterimports Unsat Check Unsat Check Split MM Sat Checkbegin
118
14.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 codedoes not compile.
The second statement actually exports the two main functions, and some auxiliary functions to convertbetween SML and Isabelle integers, and to access the sum data type of Isabelle, which is used to encode thechecker’s result.
In this section, we summarize the correctness theorems for our checker
The precondition of the triples just state that their is an integer array, which contains the DIMACS repre-sentation of the formula in the segment from indexes [1 ..<F end ]. The postcondition states that the array isnot changed, and, if the checker does not fail, the F end index will be in range, the DIMACS representationof the formula is valid, and the represented formula is satisfiable or unsatisfiable, respectively.
Note that this only proved soundness of the checker, that is, the checker may always fail, but if it does not,we guarantee a valid and (un)satisfiable formula.
theorem<DBi 7→a DB>
verify sat impl wrapper DBi F end<λresult . DBi 7→a DB ∗ ↑(¬isl result −→ verify sat spec DB F end) >t
by (rule verify sat impl wrapper correct)
theorem<DBi 7→a DB>
verify unsat impl wrapper DBi F end it<λresult . DBi 7→a DB ∗ ↑(¬isl result −→ verify unsat spec DB F end) >t
by (rule verify unsat impl wrapper correct)
theoremshows<DBi 7→a DB>
verify unsat split impl wrapper DBi prf next F end it prf<λresult . DBi 7→a DB ∗ ↑(¬isl result −→ verify unsat spec DB F end) >t
by (rule verify unsat split impl wrapper correct)
The specifications for a formula being valid and satisfiable/unsatisfiable can be written up in a very conciseway, only relying on basic list operations and the notion of a consistent assignment of truth values to integers.
An assignment is consistent, if each non-zero integer is assigned the opposite of its negated value.
lemma assn consistent σ ←→ (∀ l . l 6=0 −→ σ l = (¬ σ (−l)))by (rule assn consistent def )
119
The input described a valid and satisfiable formula, iff the F end index is in range, the correspondingDIMACS string is empty or ends with a zero, and there is a consistent assignment such that each representedclause contains a true literal.
lemmaverify sat spec DB F end ≡ 1≤F end ∧ F end ≤ length DB ∧ (
let lst = tl (take F end DB) in(lst 6=[] −→ last lst = 0 )∧ (∃σ. assn consistent σ ∧ (∀C∈set (tokenize 0 lst). ∃ l∈set C . σ l)))
by (rule verify sat spec concise)
The input describes a valid and unsatisfiable formula, iff F end is in range and does not describe the emptyDIMACS string, the DIMACS string ends with zero, and there exists no consistent assignment such thatevery clause contains at least one literal assigned to true.
lemmaverify unsat spec DB F end ≡ 1 < F end ∧ F end ≤ length DB ∧ (