module TypeForm
use booltheory.BoolImplementation
type atomicformula =
| ATop
| ABot
| AVar i
function eval_atomicformula (phi: atomicformula) (f: i -> t) : t
= match phi with
| ATop -> top
| ABot -> bot
| AVar i -> f i
end
end
module SetAppAF
use TypeForm
clone export set.SetApp with type elt = atomicformula
end
module Converts
use TypeForm
use import formula.ConjunctiveNormalForm as CNF
use import formula.Horn as HornFormula
use import list.Mem as ListMem
use list.List, list.Append, list.Length
use booltheory.BoolImplementation, int.Int, setstheory.BoolSet, setstheory.PropositionalFormulaSet, option.Option
let function convertRStoAF (phi: rightside) : atomicformula
ensures {forall f. eval_rightside (assign_rightside phi f) = eval_atomicformula result f}
ensures { match phi with
RProp t -> if t = top then result = ATop else result = ABot
| RVar x -> result = AVar x
end}
= match phi with
| RProp t -> if t = top then ATop else ABot
| RVar x -> AVar x
end
let function convertPLtoAF (phi: pliteral) : atomicformula
ensures { forall f. eval_pliteral phi f = eval_atomicformula result f}
ensures{ match phi with
| LBottom -> result = ABot
| LVar x -> result = AVar x
end }
= match phi with
| LBottom -> ABot
| LVar x -> AVar x
end
let function convertAFtoPL (phi: atomicformula) : pliteral
requires{ phi <> ATop }
ensures { forall f. eval_atomicformula phi f = eval_pliteral result f}
ensures{ match phi with
| ATop -> false
| ABot -> result = LBottom
| AVar x -> result = LVar x
end }
= match phi with
| ATop -> absurd
| ABot -> LBottom
| AVar x -> LVar x
end
let function convertAFtoRS (phi: atomicformula) : rightside
ensures { forall f. eval_atomicformula phi f = eval_rightside (assign_rightside result f)}
ensures { match phi with
| ATop -> result = RProp top
| ABot -> result = RProp bot
| AVar x -> result = RVar x
end }
= match phi with
| ATop -> RProp top
| ABot -> RProp bot
| AVar x -> RVar x
end
lemma convertPLtoAF_evaluation: forall f phi. eval_pliteral phi f = eval_atomicformula (convertPLtoAF phi) f
lemma convertAFtoPL_evaluation: forall f phi. phi <> ATop -> eval_atomicformula phi f = eval_pliteral (convertAFtoPL phi) f
lemma PLtoAF_AFtoPL: forall x. x <> ATop -> x = convertPLtoAF (convertAFtoPL x)
lemma RStoAF_AFtoRS: forall x. x = convertRStoAF (convertAFtoRS x)
lemma AFtoRS_RStoAF: forall x. x = convertAFtoRS (convertRStoAF x)
end
module Eval
use TypeForm
use import formula.ConjunctiveNormalForm as CNF
use import formula.Horn as HornFormula
use list.Mem as ListMem
use list.List, list.Append, list.Length, list.HdTl, list.Permut, list.NumOcc, list.Distinct
use option.Option
use booltheory.BoolImplementation, int.Int, setstheory.BoolSet, setstheory.PropositionalFormulaSet
use Converts
use import set.Fset as FS
function eval_setconjunction (s: fset atomicformula) (f: i-> BoolImplementation.t) : BoolImplementation.t
axiom eval_setconjunction_empty: forall f, s: fset atomicformula. is_empty s -> eval_setconjunction s f = top
axiom eval_setconjunction_pick: forall f, s: fset atomicformula. not is_empty s -> forall x. mem x s ->
eval_setconjunction s f = (eval_atomicformula x f) /*\ eval_setconjunction (remove x s) f
lemma eval_setconjunction_singleton: forall f, s: fset atomicformula. cardinal s = 1 ->
let x = pick s in eval_setconjunction s f = (eval_atomicformula x f)
val function eq_pos (x y: atomicformula) : bool
ensures { result <-> x = y }
val function rs_eq_pos (x y: rightside) : bool
ensures { result <-> x = y }
let rec lemma eval_commutes_add (s: fset atomicformula) (x: atomicformula) (f: i -> t)
variant { cardinal (add x s) }
ensures { eval_setconjunction (add x s) f = eval_atomicformula x f /*\ eval_setconjunction s f }
= if FS.is_empty s then ()
else let y = FS.pick (FS.add x s) in
if eq_pos x y then ()
else let new_s = FS.remove y (FS.add x s) in
eval_commutes_add new_s x f
lemma add_eval: forall f s x.
eval_setconjunction (add x s) f = eval_atomicformula x f /*\ eval_setconjunction s f
function eval_clause (clause: (fset atomicformula, rightside)) (f: i-> BoolImplementation.t) : BoolImplementation.t
= match clause with
| (setc,p) -> ((eval_setconjunction setc f) ->* (eval_rightside (assign_rightside p f)))
end
function eval_clauselist (l: list (fset atomicformula, rightside)) (f: i-> BoolImplementation.t) : BoolImplementation.t
= match l with
| Nil -> top
| Cons clause l1 -> eval_clause clause f /*\ eval_clauselist l1 f
end
lemma eval_clauselist_top_is_conj_eval_clause_top:
forall cl f.
(eval_clauselist cl f = top) <->
(forall c. ListMem.mem c cl -> eval_clause c f = top)
lemma eval_clauselist_bot_is_conj_eval_clause_bot:
forall cl.
not (is_nil cl) -> forall f. ((eval_clauselist cl f = bot) <->
(exists c. ListMem.mem c cl /\ eval_clause c f = bot))
let rec lemma all_x_top_then_eval_setconjunction_top (s: fset atomicformula) (f: i -> t)
ensures { (forall x. mem x s ->
eval_atomicformula x f = top) ->
eval_setconjunction s f = top }
variant{ cardinal s }
= if( FS.is_empty s ) then
()
else
let o = pick s in
all_x_top_then_eval_setconjunction_top (FS.remove o s) f
let lemma forall_eval_af_bot_exists_eval_af_bot (f: i -> t)
ensures { eval_atomicformula ABot f = bot -> (exists f. eval_atomicformula ABot f = bot) }
= ()
let lemma eval_cl_bot_then_exists_eval_clause_bot (clauselist: list (fset atomicformula, rightside)) (f: i -> t)
ensures { eval_clauselist clauselist f = bot -> exists x p. eval_clause (x,p) f = bot /\ ListMem.mem (x,p) clauselist}
= ()
lemma eval_append:
forall f cl1 cl2.
(eval_clauselist cl1 f = top) && (eval_clauselist cl2 f = top) ->
(eval_clauselist (cl1 ++ cl2) f = top)
end
module SAT
use TypeForm
use import formula.ConjunctiveNormalForm as CNF
use import formula.Horn as HornFormula
use list.Mem as ListMem
use list.List, list.Append, list.Length, list.HdTl, list.Permut, list.NumOcc, list.Distinct
use booltheory.BoolImplementation, int.Int, setstheory.BoolSet, setstheory.PropositionalFormulaSet, option.Option
use Converts
use import set.Fset as FS
use Eval
predicate is_satisfiable_rs (rs: rightside)
= exists f. eval_rightside (assign_rightside rs f) = top
predicate is_unsatisfiable_rs (rs: rightside)
= forall f. eval_rightside (assign_rightside rs f) = bot
lemma rs_unsat_then_not_sat:
forall rs. is_unsatisfiable_rs rs ->
not is_satisfiable_rs rs
predicate is_satisfiable_af (af: atomicformula)
= exists f. eval_atomicformula af f = top
predicate is_unsatisfiable_af (af: atomicformula)
= forall f. eval_atomicformula af f = bot
lemma af_unsat_then_not_sat:
forall af. is_unsatisfiable_af af ->
not is_satisfiable_af af
predicate is_satisfiable_set (set: fset atomicformula)
= exists f. eval_setconjunction set f = top
predicate is_unsatisfiable_set (set: fset atomicformula)
= forall f. eval_setconjunction set f = bot
lemma set_unsat_then_not_sat:
forall set. is_unsatisfiable_set set ->
not is_satisfiable_set set
predicate is_satisfiable_clause (clause: (fset atomicformula, rightside))
= exists f. eval_clause clause f = top
predicate is_unsatisfiable_clause (clause: (fset atomicformula, rightside))
= not is_satisfiable_clause clause
predicate is_satisfiable_clauselist (clauselist: list (fset atomicformula, rightside))
= exists f. eval_clauselist clauselist f = top
predicate is_unsatisfiable_clauselist (clauselist: list (fset atomicformula, rightside))
= not (is_satisfiable_clauselist clauselist)
constant val_all_top: i -> t = fun _ -> top
constant val_all_bot: i -> t = fun _ -> bot
let ghost constant val_top_c (c: fset atomicformula) : (i -> t) =
fun x -> if mem (AVar x) c then top else bot
let rec lemma all_set_without_bot_eval_set (c: fset atomicformula)
requires{ not mem ABot c }
ensures { (eval_setconjunction c val_all_top = top) }
variant{ cardinal c }
= if (FS.is_empty c) then
()
else
let o = pick c in
all_set_without_bot_eval_set (FS.remove o c)
let rec lemma bot_not_in_set_then_sat_set (c: fset atomicformula)
requires{ not mem ABot c }
ensures { exists f. eval_setconjunction c f = top }
variant{ cardinal c }
= if (FS.is_empty c) then
()
else
let o = pick c in
bot_not_in_set_then_sat_set (FS.remove o c)
let rec lemma subset_of_satisfiable_set (c d: fset atomicformula) (f: i-> BoolImplementation.t)
requires { eval_setconjunction d f = top }
requires { subset c d }
ensures { eval_setconjunction c f = top }
variant { cardinal d }
= if FS.is_empty d then
()
else
if FS.is_empty c then
()
else
let o = pick d in
subset_of_satisfiable_set (FS.remove o c) (FS.remove o d) f
lemma satisfiable_clause:
forall clauselist f.
(eval_clauselist clauselist f = top) -> (forall clause. ListMem.mem clause clauselist -> eval_clause clause f = top)
lemma sublist_is_satisfiable_clauselist:
forall clauselist sublist. (forall clause.
(ListMem.mem clause sublist -> ListMem.mem clause clauselist)) ->
(is_satisfiable_clauselist clauselist -> is_satisfiable_clauselist sublist)
lemma sat_cl_bot_right:
forall cl.
is_satisfiable_clauselist cl ->
(forall set.
ListMem.mem (set, RProp bot) cl -> (exists f. eval_setconjunction set f = bot))
lemma sat_cl_bot_left:
forall cl.
is_satisfiable_clauselist cl ->
(forall set p.
ListMem.mem (set, p) cl /\ mem ABot set -> is_unsatisfiable_set set)
lemma not_unsat_set_sat_set:
forall set.
not is_unsatisfiable_set set <-> (exists f:i -> t. eval_setconjunction set f = top)
lemma not_unsat_clause_sat_clause:
forall clause.
(not is_unsatisfiable_clause clause) <-> is_satisfiable_clause clause
lemma not_unsat_sat:
forall clauselist.
(not is_unsatisfiable_clauselist clauselist) <-> is_satisfiable_clauselist clauselist
lemma not_sat_unsat:
forall clauselist.
(not is_satisfiable_clauselist clauselist) <-> is_unsatisfiable_clauselist clauselist
lemma unsat_then_bot:
forall p.
(forall f:i -> t. eval_rightside (assign_rightside p f) = bot) -> rs_eq_pos p (RProp bot)
lemma is_unsat_then_p_is_bot:
forall x p.
is_unsatisfiable_clause (x,p) -> rs_eq_pos p (RProp bot)
lemma unsat_permut:
forall cl1 cl2.
permut cl1 cl2 ->
is_unsatisfiable_clauselist cl1 -> is_unsatisfiable_clauselist cl2
end
module ListPlus
use TypeForm
use import formula.Horn as HornFormula
use list.Mem as ListMem
use list.List, list.Append, list.Length, list.Permut, list.NumOcc, int.Int
use import set.Fset as FS
let rec ghost predicate sublist (list1 list2: list 'a)
ensures { result <-> (forall elem. ListMem.mem elem list1 -> ListMem.mem elem list2) }
= match list1 with
| Nil -> true
| Cons x l -> ListMem.mem x list2 && sublist l list2
end
predicate is_equal_list (list1 list2: list 'a)
= match list1,list2 with
| Nil, Nil -> True
| Cons _ _, Nil | Nil, Cons _ _ -> False
| Cons x1 list1', Cons x2 list2' ->
x1 = x2 &&
is_equal_list list1' list2'
end
let rec lemma equality_is_equal_list (l1 l2: list 'a)
requires { is_equal_list l1 l2 }
ensures { l1 = l2 }
= match l1,l2 with
| Nil, Nil -> ()
| Cons x l, Cons y ls -> begin assert { x = y } end;
equality_is_equal_list l ls
| _ -> ()
end
let rec lemma is_equal_list_reflexive (l1: list 'a)
ensures { is_equal_list l1 l1 }
= match l1 with
| Nil -> ()
| Cons x ls -> begin assert { x = x } end;
is_equal_list_reflexive ls
end
let rec lemma is_equal_list_commutative (l1 l2: list 'a)
ensures { is_equal_list l1 l2 <-> is_equal_list l2 l1 }
= ()
let rec lemma tuple_equality (z1 z2 r1 r2: list 'a)
ensures { is_equal_list (z1++z2) (r1++r2) -> is_equal_list z1 r1 -> is_equal_list z2 r2 }
ensures { is_equal_list (z1++z2) (r1++r2) -> is_equal_list z2 r2 -> is_equal_list z1 r1 }
variant { length r1 }
= match z1,r1 with
| Nil, Nil -> ()
| Cons _ l, Cons _ lx -> tuple_equality l z2 lx r2
| _ -> ()
end
lemma permut_ref:
forall cl: list 'a.
permut cl cl
lemma permut_trans:
forall cl1 cl2 cl3: list 'a.
permut cl1 cl2 && permut cl2 cl3 -> permut cl1 cl3
lemma permut_cl1_cl2:
forall cl1 cl2: list 'a.
permut cl1 cl2 <->
permut cl2 cl1
lemma concat_with_element:
forall l:list 'a, x.
ListMem.mem x l ->
exists l1 l2. is_equal_list (l1 ++ (Cons x l2)) l
let lemma num_occ_permut_concat (left right left1 right1: list (fset atomicformula, rightside))
requires { permut (left ++ right) (left1 ++ right1) }
ensures { forall x. num_occ x (left ++ right) = num_occ x (left1 ++ right1) }
= ()
let lemma num_occ_concat (left right: list (fset atomicformula, rightside))
ensures { forall x. num_occ x (left ++ right) = num_occ x left + num_occ x right }
= ()
let lemma num_occ_1_plus_tail (set: fset atomicformula) (p: rightside) (left right l: list (fset atomicformula, rightside))
requires { is_equal_list right (Cons (set,p) l) }
ensures { 1 + num_occ (set,p) (left ++ l) = num_occ (set,p) (left ++ right) }
= begin
assert { num_occ (set,p) right = 1 + num_occ (set,p) l }
end
let lemma num_occ_permut_list (set: fset atomicformula) (p: rightside) (left right l left1 right1 l1: list (fset atomicformula, rightside))
requires { permut (left ++ right) (left1 ++ right1) }
requires { is_equal_list right (Cons (set,p) l) }
requires { is_equal_list right1 (Cons (set,p) l1) }
ensures { forall x. num_occ x (left ++ l) = num_occ x (left1 ++ l1) }
= ()
let lemma permut_list_permut_sublist (set: fset atomicformula) (p: rightside) (left right l left1 right1 l1: list (fset atomicformula, rightside))
requires { permut (left ++ right) (left1 ++ right1) }
requires { is_equal_list right (Cons (set,p) l) }
requires { is_equal_list right1 (Cons (set,p) l1) }
ensures { permut (left ++ l) (left1 ++ l1) }
= begin
assert{num_occ (set,p) right = 1 + num_occ (set,p) l};
end
end
module RemoveFromList
use ListPlus
use list.Mem as ListMem
use list.List, list.NumOcc, int.Int, list.Length, list.Append, list.Permut
function removeFromList (elem: 'a) (clauselist: list 'a) : list 'a
= match clauselist with
| Nil -> Nil
| Cons x l -> if (x = elem) then l else Cons x (removeFromList elem l)
end
lemma removeFromList_numocc:
forall clauselist:list 'a, elem. ListMem.mem elem clauselist ->
num_occ elem clauselist = 1 + num_occ elem (removeFromList elem clauselist)
lemma removeFromList_numocc_not_elem:
forall clauselist:list 'a, elem x. ListMem.mem elem clauselist ->
not x = elem ->
num_occ x clauselist = num_occ x (removeFromList elem clauselist)
lemma removeFromList_length:
forall clauselist:list 'a, elem. ListMem.mem elem clauselist ->
length clauselist = 1 + length (removeFromList elem clauselist)
lemma removeFromList_concat_not_mem_l1:
forall l1 l2:list 'a, x.
not ListMem.mem x l1 ->
is_equal_list (removeFromList x (l1 ++ l2)) (l1 ++ (removeFromList x l2))
lemma removeFromList_concat:
forall left l1 l2: list 'a, x.
not ListMem.mem x left ->
is_equal_list (left ++ (Cons x l1)) l2 ->
is_equal_list (removeFromList x l2) (left ++ l1)
lemma removeFromList_permut:
forall clauselist clauselist2:list 'a, elem. ListMem.mem elem clauselist ->
permut clauselist clauselist2 ->
permut (removeFromList elem clauselist) (removeFromList elem clauselist2)
lemma removeFromList_permut_concat:
forall left right l clauselist2:list 'a, x.
is_equal_list right (Cons x l) ->
permut (left ++ right) clauselist2 ->
permut (left ++ l) (removeFromList x clauselist2)
lemma removeFromList_elem_not_in_list:
forall l:list 'a, x.
not ListMem.mem x l ->
is_equal_list (removeFromList x l) l
lemma removeFromList_sublist:
forall l1 l2: list 'a, x.
sublist l1 l2 ->
sublist (removeFromList x l1) l2
end
module FindOneSubset
use import formula.Horn as HornFormula
use list.Mem as ListMem
use TypeForm, list.List, list.Append, list.Length, list.Permut, list.NumOcc, int.Int, option.Option
use import set.Fset as FS
function findOneSubset (clauselist: list (fset atomicformula,rightside))
(c: fset atomicformula)
: option (fset atomicformula,rightside)
axiom findOneSubset_def:
forall cl c.
match findOneSubset cl c with
| None -> forall s p. (ListMem.mem (s,p) cl -> not subset s c)
| Some (s,p) -> ListMem.mem (s,p) cl /\ subset s c
end
axiom findOneSubset_exists:
forall cl c.
not is_nil cl ->
(forall s1 p1. ListMem.mem (s1,p1) cl /\ subset s1 c ->
findOneSubset cl c = Some (s1,p1))
lemma findOneSubset_if_only_if_some:
forall cl c.
not is_nil cl ->
(forall s1 p1. ListMem.mem (s1,p1) cl /\ subset s1 c <->
findOneSubset cl c = Some (s1,p1))
lemma findOneSubset_mem_subset:
forall cl c.
not is_nil cl ->
match findOneSubset cl c with
| None -> true
| Some (s,p) -> ListMem.mem (s,p) cl /\ subset s c
end
lemma findOneSubset_nil:
forall cl c.
is_nil cl -> findOneSubset cl c = None
lemma findOneSubset_notsubset:
forall cl c.
(forall s1 p1. (ListMem.mem (s1,p1) cl -> not subset s1 c)) ->
findOneSubset cl c = None
end
module SetOfSymbols
use import formula.Horn as HornFormula
use list.Mem as ListMem
use TypeForm, list.List, list.Append, list.Length, list.Permut, list.NumOcc, int.Int, option.Option, Converts
use import set.Fset as FS
function set_smb_clauselist (clauselist: list (fset atomicformula,rightside)) : fset atomicformula
= match clauselist with
| Nil -> empty
| Cons (set,p) l -> union (add (convertRStoAF p) set) (set_smb_clauselist l)
end
lemma if_mem_then_subset_set_smb: forall set p clauselist.
ListMem.mem (set,p) clauselist -> subset (add (convertRStoAF p) set) (set_smb_clauselist clauselist)
lemma subset_set_smb_clauselist:
forall clauselist set p.
ListMem.mem (set,p) clauselist -> mem (convertRStoAF p) (set_smb_clauselist clauselist)
lemma sublist_subset_set_smb:
forall clauselist sublist. (forall clause.
(ListMem.mem clause sublist -> ListMem.mem clause clauselist)) ->
subset (set_smb_clauselist sublist) (set_smb_clauselist clauselist)
end
module Horn_Logic
use list.Mem as ListMem
use list.List, list.Length, list.Permut, list.Append, option.Option
use TypeForm, Converts, Eval, SAT, RemoveFromList, ListPlus, FindOneSubset, SetOfSymbols, formula.Horn, booltheory.BoolImplementation
use import set.Fset as FS
let rec ghost function algorithmA_spec (ghost full_clauselist: list (fset atomicformula,rightside)) (ghost processed_clauses: list (fset atomicformula,rightside)) (clauselist: list (fset atomicformula,rightside))
(c: fset atomicformula) : fset atomicformula
requires{ mem ATop c }
requires{ not mem ABot c }
requires{ sublist clauselist full_clauselist }
requires{ permut (processed_clauses ++ clauselist) full_clauselist }
requires{ subset c (add ATop (set_smb_clauselist full_clauselist)) }
requires{ forall f. (eval_clauselist full_clauselist f = top) -> eval_setconjunction c f = top }
requires{ is_satisfiable_clauselist processed_clauses }
requires{ forall f. eval_clauselist processed_clauses f = top <-> eval_setconjunction c f = top }
ensures { subset c result }
ensures { subset result (add ATop (add ABot (set_smb_clauselist full_clauselist))) }
ensures { forall f. (eval_clauselist full_clauselist f = top) -> eval_setconjunction result f = top }
variant { length clauselist }
= match clauselist with
| Nil -> c
| _ -> match findOneSubset clauselist c with
| None -> c
| Some (s,p) -> if eq_pos (convertRStoAF p) ABot then
(FS.add ABot c)
else
algorithmA_spec full_clauselist (Cons (s,p) processed_clauses) (removeFromList (s,p) clauselist) (FS.add (convertRStoAF p) c)
end
end
let rec lemma permutations (ghost full_clauselist: list (fset atomicformula, rightside)) (ghost processed_clauses: list (fset atomicformula, rightside)) (clauselist clauselist2: list (fset atomicformula, rightside)) (c: fset atomicformula)
requires { permut clauselist clauselist2 }
requires { permut (clauselist ++ processed_clauses) full_clauselist }
requires { mem ATop c }
requires{ not mem ABot c }
requires { sublist clauselist full_clauselist }
requires{ subset c (add ATop (set_smb_clauselist full_clauselist)) }
requires{ forall f. (eval_clauselist full_clauselist f = top) -> eval_setconjunction c f = top }
requires{ forall f. eval_clauselist processed_clauses f = top <-> eval_setconjunction c f = top }
ensures { (algorithmA_spec full_clauselist processed_clauses clauselist c == algorithmA_spec full_clauselist processed_clauses clauselist2 c) }
ensures { result == algorithmA_spec full_clauselist processed_clauses clauselist c }
variant { length clauselist }
= match clauselist with
| Nil -> c
| _ -> match findOneSubset clauselist c with
| None -> c
| Some (s,p) -> if eq_pos (convertRStoAF p) ABot then
(FS.add ABot c)
else
permutations full_clauselist (Cons (s,p) processed_clauses) (removeFromList (s,p) clauselist) (removeFromList (s,p) clauselist2) (FS.add (convertRStoAF p) c)
end
end
let rec lemma monotone_algA (c d: fset atomicformula) (ghost full_clauselist: list (fset atomicformula,rightside)) (ghost processed_clauses: list (fset atomicformula,rightside)) (clauselist: list (fset atomicformula,rightside))
requires{ mem ATop c }
requires{ not mem ABot d }
requires{ subset c d }
requires{ sublist clauselist full_clauselist }
requires { permut (clauselist ++ processed_clauses) full_clauselist }
requires{ subset d (add ATop (set_smb_clauselist full_clauselist)) }
requires{ forall f. (eval_clauselist full_clauselist f = top) -> eval_setconjunction d f = top }
requires{ forall f. eval_clauselist processed_clauses f = top <-> eval_setconjunction c f = top }
requires{ forall f. eval_clauselist processed_clauses f = top <-> eval_setconjunction d f = top }
ensures { subset (algorithmA_spec full_clauselist processed_clauses clauselist c) (algorithmA_spec full_clauselist processed_clauses clauselist d) }
variant { length clauselist }
= match clauselist with
| Nil -> ()
| _ -> match findOneSubset clauselist c with
| None -> ()
| Some (s,p) -> if eq_pos (convertRStoAF p) ABot then
()
else
monotone_algA (FS.add (convertRStoAF p) c) (FS.add (convertRStoAF p) d) full_clauselist (Cons (s,p) processed_clauses) (removeFromList (s,p) clauselist)
end
end
let lemma smb (clauselist: list (fset atomicformula, rightside)) (ghost processed_clauses: list (fset atomicformula, rightside)) (c: fset atomicformula)
requires{ mem ATop c }
requires{ not mem ABot c }
requires{ permut (clauselist ++ processed_clauses) clauselist }
requires{ subset c (add (ATop) (add ABot (set_smb_clauselist clauselist))) }
requires{ (forall f. (eval_clauselist clauselist f = top) -> eval_setconjunction c f = top) }
requires{ forall f. eval_clauselist processed_clauses f = top <-> eval_setconjunction c f = top }
ensures { let newc = algorithmA_spec clauselist processed_clauses clauselist c in
subset newc (add (ATop) (add ABot (set_smb_clauselist clauselist))) }
= ()
let rec lemma unsat_cl_mem_ABot_in_algorithmA (ghost full_clauselist: list (fset atomicformula, rightside)) (ghost processed_clauses: list (fset atomicformula, rightside)) (clauselist: list (fset atomicformula, rightside)) (c: fset atomicformula)
requires{ is_unsatisfiable_clauselist full_clauselist }
requires{ permut (processed_clauses ++ clauselist) full_clauselist }
requires{ sublist clauselist full_clauselist }
requires{ subset c (add ATop (set_smb_clauselist full_clauselist)) }
requires{ is_satisfiable_clauselist processed_clauses }
requires{ forall f. (eval_clauselist full_clauselist f = top) -> eval_setconjunction c f = top }
requires{ forall f. eval_clauselist processed_clauses f = top <-> eval_setconjunction c f = top }
requires{ mem ATop c }
requires{ not mem ABot c }
ensures { mem ABot (algorithmA_spec full_clauselist processed_clauses clauselist c) }
variant { length clauselist }
= match clauselist with
| Nil -> ()
| Cons _ Nil -> ()
| Cons _ _ -> match findOneSubset clauselist c with
| None -> ()
| Some (s,p) -> if eq_pos (convertRStoAF p) ABot then
()
else
unsat_cl_mem_ABot_in_algorithmA full_clauselist (Cons (s,p) processed_clauses) (removeFromList (s,p) clauselist) (FS.add (convertRStoAF p) c)
end
end
let lemma not_mem_ABot_then_cl_sat (clauselist: list (fset atomicformula, rightside))
requires{ not mem ABot (algorithmA_spec clauselist Nil clauselist (singleton ATop)) }
ensures { is_satisfiable_clauselist clauselist }
= ()
let rec lemma sat_cl_not_ABot_in_algorithmA (ghost full_clauselist: list (fset atomicformula, rightside)) (ghost processed_clauses: list (fset atomicformula, rightside)) (clauselist: list (fset atomicformula, rightside)) (c: fset atomicformula)
requires{ is_satisfiable_clauselist full_clauselist }
requires{ permut (processed_clauses ++ clauselist) full_clauselist }
requires{ sublist clauselist full_clauselist }
requires{ subset c (add ATop (set_smb_clauselist full_clauselist)) }
requires{ forall f. (eval_clauselist full_clauselist f = top) -> eval_setconjunction c f = top }
requires{ forall f. eval_setconjunction c f = top <-> eval_clauselist processed_clauses f = top }
requires{ mem ATop c }
requires{ not mem ABot c }
ensures { not mem ABot (algorithmA_spec full_clauselist processed_clauses clauselist c) }
variant { length clauselist }
= match clauselist with
| Nil -> ()
| Cons _ Nil -> ()
| Cons _ _ -> match findOneSubset clauselist c with
| None -> ()
| Some (s,p) -> if eq_pos (convertRStoAF p) ABot then
()
else
sat_cl_not_ABot_in_algorithmA full_clauselist (Cons (s,p) processed_clauses) (removeFromList (s,p) clauselist) (FS.add (convertRStoAF p) c)
end
end
let lemma mem_ABot_then_cl_unsat (clauselist: list (fset atomicformula, rightside))
requires{ mem ABot (algorithmA_spec clauselist Nil clauselist (singleton ATop)) }
ensures { is_unsatisfiable_clauselist clauselist }
= ()
let ghost function horn_logic (clauselist: list (fset atomicformula, rightside)) : bool
= not (FS.mem ABot (algorithmA_spec clauselist Nil clauselist (FS.singleton ATop)))
lemma horn_sat:
forall clauselist.
is_satisfiable_clauselist clauselist <-> (horn_logic clauselist = true)
lemma horn_unsat:
forall clauselist.
is_unsatisfiable_clauselist clauselist <-> (horn_logic clauselist = false)
end
module Horn
use list.List, list.Length, list.Append, list.Permut, int.Int, option.Option
use TypeForm, Converts, Eval, SAT, RemoveFromList, FindOneSubset, SetOfSymbols, ListPlus, SetAppAF, Horn_Logic, booltheory.BoolImplementation, formula.Horn
function listset_to_listfset (clauselist: list (set, rightside))
: list (fset atomicformula, rightside)
= match clauselist with
| Nil -> Nil
| Cons (setc, p) l -> Cons (to_fset setc, p) (listset_to_listfset l)
end
meta rewrite_def function listset_to_listfset
lemma length_equal_listset_to_list_fset:
forall cl.
length cl = length (listset_to_listfset cl)
function listfset_to_listset (clauselist: list (fset atomicformula, rightside))
: list (set, rightside)
= match clauselist with
| Nil -> Nil
| Cons (setc, p) l -> Cons (mk (setc), p) (listfset_to_listset l)
end
meta rewrite_def function listfset_to_listset
val findOneSubset_prog (clauselist: list (set ,rightside))
(c: set)
: option (set ,rightside)
ensures { match result with
| None -> match findOneSubset (listset_to_listfset clauselist) c with
| None -> true
| Some _ -> false
end
| Some (setc,p) -> Some (to_fset setc, p) = findOneSubset (listset_to_listfset clauselist) c
end
}
let rec removeFromList_prog (elem: (set, rightside)) (clauselist: list (set, rightside)) : list (set, rightside)
ensures { let (set,p) = elem in
listset_to_listfset result = (removeFromList ((to_fset set),p) (listset_to_listfset clauselist)) }
variant { length clauselist }
= match clauselist with
| Nil -> Nil
| Cons (s1,p1) l -> let (s2,p2) = elem in
if (s1 == s2 && rs_eq_pos p1 p2) then l else Cons (s1,p1) (removeFromList_prog elem l)
end
let rec function algorithmA (ghost full_clauselist: list (fset atomicformula ,rightside)) (ghost processed_clauses: list (fset atomicformula ,rightside)) (clauselist: list (set ,rightside)) (c: set) : set
requires{ mem ATop c }
requires{ not mem ABot c }
requires{ sublist (listset_to_listfset clauselist) full_clauselist }
requires{ permut ((listset_to_listfset clauselist) ++ processed_clauses) (full_clauselist) }
requires{ subset c (add ATop (set_smb_clauselist full_clauselist)) }
requires{ is_satisfiable_clauselist processed_clauses }
requires{ forall f. (eval_clauselist full_clauselist f = top) -> eval_setconjunction c f = top }
requires{ forall f. eval_clauselist processed_clauses f = top <-> eval_setconjunction c f = top }
ensures { to_fset result = algorithmA_spec (full_clauselist) (processed_clauses) (listset_to_listfset clauselist) (to_fset c) }
variant { length clauselist }
= match clauselist with
| Nil -> c
| _ -> match findOneSubset_prog clauselist c with
| None -> c
| Some (s,p) -> if eq_pos (convertRStoAF p) ABot then
(add ABot c)
else
algorithmA full_clauselist (Cons (to_fset s,p) processed_clauses) (removeFromList_prog (s,p) clauselist) (add (convertRStoAF p) c)
end
end
let horn (clauselist: list (set ,rightside)) : bool
ensures { result = horn_logic (listset_to_listfset clauselist) }
= not (mem ABot (algorithmA (listset_to_listfset clauselist) Nil clauselist (singleton ATop)))
end