vericert.hls.Predicate
Definition predicate : Type := positive.
Inductive pred_op : Type :=
| Plit: (bool * predicate) -> pred_op
| Ptrue: pred_op
| Pfalse: pred_op
| Pand: pred_op -> pred_op -> pred_op
| Por: pred_op -> pred_op -> pred_op.
Notation "A ∧ B" := (Pand A B) (at level 20) : pred_op.
Notation "A ∨ B" := (Por A B) (at level 25) : pred_op.
Notation "⟂" := (Pfalse) : pred_op.
Notation "'T'" := (Ptrue) : pred_op.
#[local] Open Scope pred_op.
Fixpoint sat_predicate (p: pred_op) (a: asgn) : bool :=
match p with
| Plit (b, p') => if b then a (Pos.to_nat p') else negb (a (Pos.to_nat p'))
| Ptrue => true
| Pfalse => false
| Pand p1 p2 => sat_predicate p1 a && sat_predicate p2 a
| Por p1 p2 => sat_predicate p1 a || sat_predicate p2 a
end.
Definition sat_equiv p1 p2 := forall c, sat_predicate p1 c = sat_predicate p2 c.
Lemma equiv_symm : forall a b, sat_equiv a b -> sat_equiv b a.
Lemma equiv_trans : forall a b c, sat_equiv a b -> sat_equiv b c -> sat_equiv a c.
Lemma equiv_refl : forall a, sat_equiv a a.
#[global]
Instance Equivalence_SAT : Equivalence sat_equiv :=
{ Equivalence_Reflexive := equiv_refl ;
Equivalence_Symmetric := equiv_symm ;
Equivalence_Transitive := equiv_trans ;
}.
#[global]
Instance SATSetoid : Setoid pred_op :=
{ equiv := sat_equiv; }.
#[global]
Instance PandProper : Proper (equiv ==> equiv ==> equiv) Pand.
#[global]
Instance PorProper : Proper (equiv ==> equiv ==> equiv) Por.
#[global]
Instance sat_predicate_Proper : Proper (equiv ==> eq ==> eq) sat_predicate.
Fixpoint negate (p: pred_op) :=
match p with
| Plit (b, pr) => Plit (negb b, pr)
| T => ⟂
| ⟂ => T
| A ∧ B => negate A ∨ negate B
| A ∨ B => negate A ∧ negate B
end.
Notation "¬ A" := (negate A) (at level 15) : pred_op.
Lemma negate_correct :
forall h a, sat_predicate (negate h) a = negb (sat_predicate h a).
Definition unsat p := forall a, sat_predicate p a = false.
Definition sat p := exists a, sat_predicate p a = true.
Lemma unsat_correct1 :
forall a b c,
unsat (Pand a b) ->
sat_predicate a c = true ->
sat_predicate b c = false.
Lemma unsat_correct2 :
forall a b c,
unsat (Pand a b) ->
sat_predicate b c = true ->
sat_predicate a c = false.
Lemma unsat_not a: unsat (a ∧ (¬ a)).
Lemma unsat_commut a b: unsat (a ∧ b) -> unsat (b ∧ a).
Lemma sat_imp_equiv :
forall a b,
unsat (a ∧ ¬ b ∨ ¬ a ∧ b) -> a == b.
Lemma sat_predicate_and :
forall a b c,
sat_predicate (a ∧ b) c = sat_predicate a c && sat_predicate b c.
Lemma sat_predicate_or :
forall a b c,
sat_predicate (a ∨ b) c = sat_predicate a c || sat_predicate b c.
Lemma sat_equiv2 :
forall a b,
a == b -> unsat (a ∧ ¬ b ∨ ¬ a ∧ b).
Lemma sat_equiv3 :
forall a b,
unsat (a ∧ ¬ b ∨ b ∧ ¬ a) -> a == b.
Lemma sat_equiv4 :
forall a b,
a == b -> unsat (a ∧ ¬ b ∨ b ∧ ¬ a).
Definition simplify' (p: pred_op) :=
match p with
| (Plit (b1, a)) ∧ (Plit (b2, b)) as p' =>
if Pos.eqb a b then
if negb (xorb b1 b2) then Plit (b1, a) else ⟂
else p'
| (Plit (b1, a)) ∨ (Plit (b2, b)) as p' =>
if Pos.eqb a b then
if negb (xorb b1 b2) then Plit (b1, a) else T
else p'
| A ∧ T => A
| T ∧ A => A
| _ ∧ ⟂ => ⟂
| ⟂ ∧ _ => ⟂
| _ ∨ T => T
| T ∨ _ => T
| A ∨ ⟂ => A
| ⟂ ∨ A => A
| A => A
end.
Lemma pred_op_dec :
forall p1 p2: pred_op,
{ p1 = p2 } + { p1 <> p2 }.
Fixpoint simplify (p: pred_op) :=
match p with
| A ∧ B =>
let A' := simplify A in
let B' := simplify B in
simplify' (A' ∧ B')
| A ∨ B =>
let A' := simplify A in
let B' := simplify B in
simplify' (A' ∨ B')
| T => T
| ⟂ => ⟂
| Plit a => Plit a
end.
Lemma simplify'_correct :
forall h a,
sat_predicate (simplify' h) a = sat_predicate h a.
Lemma simplify_correct :
forall h a,
sat_predicate (simplify h) a = sat_predicate h a.
Fixpoint mult {A: Type} (a b: list (list A)) : list (list A) :=
match a with
| nil => nil
| l :: ls => mult ls b ++ (List.map (fun x => l ++ x) b)
end.
Lemma satFormula_concat:
forall a b agn,
satFormula a agn ->
satFormula b agn ->
satFormula (a ++ b) agn.
Lemma satFormula_concat2:
forall a b agn,
satFormula (a ++ b) agn ->
satFormula a agn /\ satFormula b agn.
Lemma satClause_concat:
forall a a1 a0,
satClause a a1 ->
satClause (a0 ++ a) a1.
Lemma satClause_concat2:
forall a a1 a0,
satClause a0 a1 ->
satClause (a0 ++ a) a1.
Lemma satClause_concat3:
forall a b c,
satClause (a ++ b) c ->
satClause a c \/ satClause b c.
Lemma satFormula_mult':
forall p2 a a0,
satFormula p2 a0 \/ satClause a a0 ->
satFormula (map (fun x : list lit => a ++ x) p2) a0.
Lemma satFormula_mult2':
forall p2 a a0,
satFormula (map (fun x : list lit => a ++ x) p2) a0 ->
satClause a a0 \/ satFormula p2 a0.
Lemma satFormula_mult:
forall p1 p2 a,
satFormula p1 a \/ satFormula p2 a ->
satFormula (mult p1 p2) a.
Lemma satFormula_mult2:
forall p1 p2 a,
satFormula (mult p1 p2) a ->
satFormula p1 a \/ satFormula p2 a.
Fixpoint trans_pred (p: pred_op) :
{fm: formula | forall a,
sat_predicate p a = true <-> satFormula fm a}.
Defined.
Definition bar (p1: lit): lit := (negb (fst p1), (snd p1)).
Definition stseytin_or (cur p1 p2: lit) : formula :=
(bar cur :: p1 :: p2 :: nil)
:: (cur :: bar p1 :: nil)
:: (cur :: bar p2 :: nil) :: nil.
Definition stseytin_and (cur p1 p2: lit) : formula :=
(cur :: bar p1 :: bar p2 :: nil)
:: (bar cur :: p1 :: nil)
:: (bar cur :: p2 :: nil) :: nil.
Fixpoint xtseytin (next: nat) (p: pred_op) {struct p} : (nat * lit * formula) :=
match p with
| Plit (b, p') => (next, (b, Pos.to_nat p'), nil)
| Ptrue =>
((next+1)%nat, (true, next), ((true, next)::nil)::nil)
| Pfalse =>
((next+1)%nat, (true, next), ((false, next)::nil)::nil)
| Por p1 p2 =>
let '(m1, n1, f1) := xtseytin next p1 in
let '(m2, n2, f2) := xtseytin m1 p2 in
((m2+1)%nat, (true, m2), stseytin_or (true, m2) n1 n2 ++ f1 ++ f2)
| Pand p1 p2 =>
let '(m1, n1, f1) := xtseytin next p1 in
let '(m2, n2, f2) := xtseytin m1 p2 in
((m2+1)%nat, (true, m2), stseytin_and (true, m2) n1 n2 ++ f1 ++ f2)
end.
Lemma stseytin_and_correct :
forall cur p1 p2 fm c,
stseytin_and cur p1 p2 = fm ->
satLit cur c ->
satLit p1 c /\ satLit p2 c ->
satFormula fm c.
Lemma stseytin_and_correct2 :
forall cur p1 p2 fm c,
stseytin_and cur p1 p2 = fm ->
satFormula fm c ->
satLit cur c <-> satLit p1 c /\ satLit p2 c.
Lemma stseytin_or_correct :
forall cur p1 p2 fm c,
stseytin_or cur p1 p2 = fm ->
satLit cur c ->
satLit p1 c \/ satLit p2 c ->
satFormula fm c.
Lemma stseytin_or_correct2 :
forall cur p1 p2 fm c,
stseytin_or cur p1 p2 = fm ->
satFormula fm c ->
satLit cur c <-> satLit p1 c \/ satLit p2 c.
Lemma xtseytin_correct :
forall p next l n fm c,
xtseytin next p = (n, l, fm) ->
sat_predicate p c = true <-> satFormula ((l::nil)::fm) c.
Fixpoint max_predicate (p: pred_op) : positive :=
match p with
| Plit (b, p) => p
| Ptrue => 1
| Pfalse => 1
| Pand a b => Pos.max (max_predicate a) (max_predicate b)
| Por a b => Pos.max (max_predicate a) (max_predicate b)
end.
Definition tseytin (p: pred_op) :
{fm: formula | forall a,
sat_predicate p a = true <-> satFormula fm a}.
Definition tseytin_simple (p: pred_op) : formula :=
let m := Pos.to_nat (max_predicate p + 1) in
let '(m, n, fm) := xtseytin m p in
(n::nil) :: fm.
Definition sat_pred_tseytin (p: pred_op) :
({al : alist | sat_predicate p (interp_alist al) = true}
+ {forall a : asgn, sat_predicate p a = false}).
Defined.
Definition sat_pred_simple (p: pred_op) : option alist :=
match sat_pred_tseytin p with
| inleft (exist _ a _) => Some a
| inright _ => None
end.
Definition sat_pred (p: pred_op) :
({al : alist | sat_predicate p (interp_alist al) = true}
+ {forall a : asgn, sat_predicate p a = false}).
Defined.
#[local] Open Scope positive.
Lemma sat_dec a: {sat a} + {unsat a}.
Definition equiv_check p1 p2 :=
match sat_pred_simple (simplify (p1 ∧ ¬ p2 ∨ p2 ∧ ¬ p1)) with
| None => true
| _ => false
end.
Lemma equiv_check_correct :
forall p1 p2, equiv_check p1 p2 = true -> p1 == p2.
Lemma equiv_check_correct2 :
forall p1 p2, p1 == p2 -> equiv_check p1 p2 = true.
Lemma equiv_check_dec :
forall p1 p2, equiv_check p1 p2 = true <-> p1 == p2.
Lemma equiv_check_decidable :
forall p1 p2, decidable (p1 == p2).
Lemma equiv_check_decidable2 :
forall p1 p2, {p1 == p2} + {p1 =/= p2}.
#[global]
Instance DecidableSATSetoid : DecidableSetoid SATSetoid :=
{ setoid_decidable := equiv_check_decidable }.
#[global]
Instance SATSetoidEqDec : EqDec SATSetoid := equiv_check_decidable2.
Definition Pimplies p p' := ¬ p ∨ p'.
Notation "A → B" := (Pimplies A B) (at level 30) : pred_op.
Definition implies p p' :=
forall c, sat_predicate p c = true -> sat_predicate p' c = true.
Notation "A ⇒ B" := (implies A B) (at level 35) : pred_op.
Lemma Pimplies_implies: forall p p', (p → p') ∧ p ⇒ p'.
#[global]
Instance PimpliesProper : Proper (equiv ==> equiv ==> equiv) Pimplies.
#[global]
Instance simplifyProper : Proper (equiv ==> equiv) simplify.