aboutsummaryrefslogtreecommitdiffstats
path: root/src/cnf/Cnf.v
diff options
context:
space:
mode:
Diffstat (limited to 'src/cnf/Cnf.v')
-rw-r--r--src/cnf/Cnf.v419
1 files changed, 419 insertions, 0 deletions
diff --git a/src/cnf/Cnf.v b/src/cnf/Cnf.v
new file mode 100644
index 0000000..d918dab
--- /dev/null
+++ b/src/cnf/Cnf.v
@@ -0,0 +1,419 @@
+(**************************************************************************)
+(* *)
+(* SMTCoq *)
+(* Copyright (C) 2011 - 2015 *)
+(* *)
+(* Michaël Armand *)
+(* Benjamin Grégoire *)
+(* Chantal Keller *)
+(* *)
+(* Inria - École Polytechnique - MSR-Inria Joint Lab *)
+(* *)
+(* This file is distributed under the terms of the CeCILL-C licence *)
+(* *)
+(**************************************************************************)
+
+Require Import PArray List Bool.
+(* Add LoadPath ".." as SMTCoq. *)
+Require Import Misc State SMT_terms.
+
+Import Form.
+
+Local Open Scope array_scope.
+Local Open Scope int63_scope.
+
+Set Implicit Arguments.
+Unset Strict Implicit.
+
+Definition or_of_imp args :=
+ let last := PArray.length args - 1 in
+ PArray.mapi (fun i l => if i == last then l else Lit.neg l) args.
+Register or_of_imp as PrimInline.
+
+Lemma length_or_of_imp : forall args,
+ PArray.length (or_of_imp args) = PArray.length args.
+Proof. intro; apply length_mapi. Qed.
+
+Lemma get_or_of_imp : forall args i,
+ i < (PArray.length args) - 1 -> (or_of_imp args).[i] = Lit.neg (args.[i]).
+Proof.
+ unfold or_of_imp; intros args i H; case_eq (0 < PArray.length args).
+ intro Heq; rewrite get_mapi.
+ replace (i == PArray.length args - 1) with false; auto; symmetry; rewrite eqb_false_spec; intro; subst i; unfold is_true in H; rewrite ltb_spec, (to_Z_sub_1 _ _ Heq) in H; omega.
+ rewrite ltb_spec; unfold is_true in H; rewrite ltb_spec, (to_Z_sub_1 _ _ Heq) in H; omega.
+ rewrite ltb_negb_geb; case_eq (PArray.length args <= 0); try discriminate; intros Heq _; assert (H1: PArray.length args = 0).
+ apply to_Z_inj; rewrite leb_spec in Heq; destruct (to_Z_bounded (PArray.length args)) as [H1 _]; change [|0|] with 0%Z in *; omega.
+ rewrite !get_outofbound.
+ rewrite default_mapi, H1; auto.
+ rewrite H1; case_eq (i < 0); auto; intro H2; eelim ltb_0; eassumption.
+ rewrite length_mapi, H1; case_eq (i < 0); auto; intro H2; eelim ltb_0; eassumption.
+Qed.
+
+Lemma get_or_of_imp2 : forall args i, 0 < PArray.length args ->
+ i = (PArray.length args) - 1 -> (or_of_imp args).[i] = args.[i].
+Proof.
+ unfold or_of_imp; intros args i Heq Hi; rewrite get_mapi; subst i.
+ rewrite Int63Axioms.eqb_refl; auto.
+ rewrite ltb_spec, (to_Z_sub_1 _ _ Heq); omega.
+Qed.
+
+
+Section CHECKER.
+
+ Variable t_form : PArray.array form.
+ Local Notation get_hash := (PArray.get t_form) (only parsing).
+ Variable s : S.t.
+
+
+ (* * true : {true} *)
+
+ Definition check_True := C._true.
+
+
+ (* * false : {(not false)} *)
+
+ Definition check_False := Lit.neg (Lit._false)::nil.
+
+
+ (* * and_neg : {(and a_1 ... a_n) (not a_1) ... (not a_n)}
+ * or_pos : {(not (or a_1 ... a_n)) a_1 ... a_n}
+ * implies_pos : {(not (implies a b)) (not a) b}
+ * xor_pos1 : {(not (xor a b)) a b}
+ * xor_neg1 : {(xor a b) a (not b)}
+ * equiv_pos1 : {(not (iff a b)) a (not b)}
+ * equiv_neg1 : {(iff a b) (not a) (not b)}
+ * ite_pos1 : {(not (if_then_else a b c)) a c}
+ * ite_neg1 : {(if_then_else a b c) a (not c)} *)
+
+ Definition check_BuildDef l :=
+ match get_hash (Lit.blit l) with
+ | Fand args =>
+ if Lit.is_pos l then l :: List.map Lit.neg (PArray.to_list args)
+ else C._true
+ | For args =>
+ if Lit.is_pos l then C._true
+ else l :: PArray.to_list args
+ | Fimp args =>
+ if Lit.is_pos l then C._true
+ else
+ let args := or_of_imp args in
+ l :: PArray.to_list args
+ | Fxor a b =>
+ if Lit.is_pos l then l::a::Lit.neg b::nil
+ else l::a::b::nil
+ | Fiff a b =>
+ if Lit.is_pos l then l::Lit.neg a::Lit.neg b::nil
+ else l::a::Lit.neg b::nil
+ | Fite a b c =>
+ if Lit.is_pos l then l::a::Lit.neg c::nil
+ else l::a::c::nil
+ | _ => C._true
+ end.
+
+
+ (* * not_and : {(not (and a_1 ... a_n))} --> {(not a_1) ... (not a_n)}
+ * or : {(or a_1 ... a_n)} --> {a_1 ... a_n}
+ * implies : {(implies a b)} --> {(not a) b}
+ * xor1 : {(xor a b)} --> {a b}
+ * not_xor1 : {(not (xor a b))} --> {a (not b)}
+ * equiv2 : {(iff a b)} --> {a (not b)}
+ * not_equiv2 : {(not (iff a b))} --> {(not a) (not b)}
+ * ite1 : {(if_then_else a b c)} --> {a c}
+ * not_ite1 : {(not (if_then_else a b c))} --> {a (not c)} *)
+
+ Definition check_ImmBuildDef pos :=
+ match S.get s pos with
+ | l::nil =>
+ match get_hash (Lit.blit l) with
+ | Fand args =>
+ if Lit.is_pos l then C._true
+ else List.map Lit.neg (PArray.to_list args)
+ | For args =>
+ if Lit.is_pos l then PArray.to_list args
+ else C._true
+ | Fimp args =>
+ if Lit.is_pos l then
+ let args := or_of_imp args in
+ PArray.to_list args
+ else C._true
+ | Fxor a b =>
+ if Lit.is_pos l then a::b::nil
+ else a::Lit.neg b::nil
+ | Fiff a b =>
+ if Lit.is_pos l then a::Lit.neg b::nil
+ else Lit.neg a::Lit.neg b::nil
+ | Fite a b c =>
+ if Lit.is_pos l then a::c::nil
+ else a::Lit.neg c::nil
+ | _ => C._true
+ end
+ | _ => C._true
+ end.
+
+
+ (* * xor_pos2 : {(not (xor a b)) (not a) (not b)}
+ * xor_neg2 : {(xor a b) (not a) b}
+ * equiv_pos2 : {(not (iff a b)) (not a) b}
+ * equiv_neg2 : {(iff a b) a b}
+ * ite_pos2 : {(not (if_then_else a b c)) (not a) b}
+ * ite_neg2 : {(if_then_else a b c) (not a) (not b)} *)
+
+ Definition check_BuildDef2 l :=
+ match get_hash (Lit.blit l) with
+ | Fxor a b =>
+ if Lit.is_pos l then l::Lit.neg a::b::nil
+ else l::Lit.neg a::Lit.neg b::nil
+ | Fiff a b =>
+ if Lit.is_pos l then l::a::b::nil
+ else l::Lit.neg a::b::nil
+ | Fite a b c =>
+ if Lit.is_pos l then l::Lit.neg a::Lit.neg b::nil
+ else l::Lit.neg a::b::nil
+ | _ => C._true
+ end.
+
+
+ (* * xor2 : {(xor a b)} --> {(not a) (not b)}
+ * not_xor2 : {(not (xor a b))} --> {(not a) b}
+ * equiv1 : {(iff a b)} --> {(not a) b}
+ * not_equiv1 : {(not (iff a b))} --> {a b}
+ * ite2 : {(if_then_else a b c)} --> {(not a) b}
+ * not_ite2 : {(not (if_then_else a b c))} --> {(not a) (not b)}
+ *)
+
+ Definition check_ImmBuildDef2 pos :=
+ match S.get s pos with
+ | l::nil =>
+ match get_hash (Lit.blit l) with
+ | Fxor a b =>
+ if Lit.is_pos l then Lit.neg a::Lit.neg b::nil
+ else Lit.neg a::b::nil
+ | Fiff a b =>
+ if Lit.is_pos l then Lit.neg a::b::nil
+ else a::b::nil
+ | Fite a b c =>
+ if Lit.is_pos l then Lit.neg a::b::nil
+ else Lit.neg a::Lit.neg b::nil
+ | _ => C._true
+ end
+ | _ => C._true
+ end.
+
+
+ (* * or_neg : {(or a_1 ... a_n) (not a_i)}
+ * and_pos : {(not (and a_1 ... a_n)) a_i}
+ * implies_neg1 : {(implies a b) a}
+ * implies_neg2 : {(implies a b) (not b)} *)
+
+ Definition check_BuildProj l i :=
+ let x := Lit.blit l in
+ match get_hash x with
+ | For args =>
+ if i < PArray.length args then Lit.lit x::Lit.neg (args.[i])::nil
+ else C._true
+ | Fand args =>
+ if i < PArray.length args then Lit.nlit x::(args.[i])::nil
+ else C._true
+ | Fimp args =>
+ let len := PArray.length args in
+ if i < len then
+ if i == len - 1 then Lit.lit x::Lit.neg (args.[i])::nil
+ else Lit.lit x::(args.[i])::nil
+ else C._true
+ | _ => C._true
+ end.
+
+
+ (* * and : {(and a_1 ... a_n)} --> {a_i}
+ * not_or : {(not (or a_1 ... a_n))} --> {(not a_i)}
+ * not_implies1 : {(not (implies a b))} --> {a}
+ * not_implies2 : {(not (implies a b))} --> {(not b)} *)
+
+ Definition check_ImmBuildProj pos i :=
+ match S.get s pos with
+ | l::nil =>
+ let x := Lit.blit l in
+ match get_hash x with
+ | For args =>
+ if (i < PArray.length args) && negb (Lit.is_pos l) then Lit.neg (args.[i])::nil
+ else C._true
+ | Fand args =>
+ if (i < PArray.length args) && (Lit.is_pos l) then (args.[i])::nil
+ else C._true
+ | Fimp args =>
+ let len := PArray.length args in
+ if (i < len) && negb (Lit.is_pos l) then
+ if i == len - 1 then Lit.neg (args.[i])::nil
+ else (args.[i])::nil
+ else C._true
+ | _ => C._true
+ end
+ | _ => C._true
+ end.
+
+ (** The correctness proofs *)
+
+ Variable interp_atom : atom -> bool.
+
+ Hypothesis Hch_f : check_form t_form.
+
+ Local Notation rho := (Form.interp_state_var interp_atom t_form).
+
+ Let Hwfrho : Valuation.wf rho.
+ Proof.
+ destruct (check_form_correct interp_atom _ Hch_f) as (_, H);exact H.
+ Qed.
+
+ Lemma valid_check_True : C.valid rho check_True.
+ Proof.
+ apply C.interp_true;trivial.
+ Qed.
+
+ Lemma valid_check_False : C.valid rho check_False.
+ Proof.
+ unfold check_False, C.valid;simpl.
+ rewrite Lit.interp_neg.
+ assert (W:= Lit.interp_false _ Hwfrho).
+ destruct (Lit.interp rho Lit._false);trivial;elim W;red;trivial.
+ Qed.
+
+ Let rho_interp : forall x : int,
+ rho x = interp interp_atom t_form (t_form.[ x]).
+ Proof.
+ destruct (check_form_correct interp_atom _ Hch_f) as ((H,H0), _).
+ intros x;apply wf_interp_form;trivial.
+ Qed.
+
+ Ltac tauto_check :=
+ try (rewrite !Lit.interp_neg);
+ repeat
+ match goal with |- context [Lit.interp rho ?x] =>
+ destruct (Lit.interp rho x);trivial end.
+
+ Axiom afold_left_and : forall a,
+ afold_left bool int true andb (Lit.interp rho) a =
+ List.forallb (Lit.interp rho) (to_list a).
+
+ Axiom afold_left_or : forall a,
+ afold_left bool int false orb (Lit.interp rho) a =
+ C.interp rho (to_list a).
+
+ Axiom afold_right_impb : forall a,
+ (afold_right bool int true implb (Lit.interp rho) a) =
+ C.interp rho (to_list (or_of_imp a)).
+
+ Axiom Cinterp_neg : forall cl,
+ C.interp rho (map Lit.neg cl) = negb (forallb (Lit.interp rho) cl).
+
+ Lemma valid_check_BuildDef : forall l, C.valid rho (check_BuildDef l).
+ Proof.
+ unfold check_BuildDef,C.valid;intros l.
+ case_eq (t_form.[Lit.blit l]);intros;auto using C.interp_true;
+ case_eq (Lit.is_pos l);intros Heq;auto using C.interp_true;simpl;
+ unfold Lit.interp at 1;rewrite Heq;unfold Var.interp; rewrite rho_interp, H;simpl;
+ tauto_check.
+ rewrite afold_left_and, Cinterp_neg;apply orb_negb_r.
+ rewrite afold_left_or, orb_comm;apply orb_negb_r.
+ rewrite afold_right_impb, orb_comm;apply orb_negb_r.
+ Qed.
+
+ Lemma valid_check_BuildDef2 : forall l, C.valid rho (check_BuildDef2 l).
+ Proof.
+ unfold check_BuildDef2,C.valid;intros l.
+ case_eq (t_form.[Lit.blit l]);intros;auto using C.interp_true;
+ case_eq (Lit.is_pos l);intros Heq;auto using C.interp_true;simpl;
+ unfold Lit.interp at 1;rewrite Heq;unfold Var.interp; rewrite rho_interp, H;simpl;
+ tauto_check.
+ Qed.
+
+ Lemma valid_check_BuildProj : forall l i, C.valid rho (check_BuildProj l i).
+ Proof.
+ unfold check_BuildProj,C.valid;intros l i.
+ case_eq (t_form.[Lit.blit l]);intros;auto using C.interp_true;
+ case_eq (i < PArray.length a);intros Hlt;auto using C.interp_true;simpl.
+
+ rewrite Lit.interp_nlit;unfold Var.interp;rewrite rho_interp, orb_false_r, H.
+ simpl;rewrite afold_left_and.
+ case_eq (forallb (Lit.interp rho) (to_list a));trivial.
+ rewrite forallb_forall;intros Heq;rewrite Heq;trivial.
+ apply to_list_In; auto.
+ rewrite Lit.interp_lit;unfold Var.interp;rewrite rho_interp, orb_false_r, H.
+ simpl;rewrite afold_left_or.
+
+ unfold C.interp;case_eq (existsb (Lit.interp rho) (to_list a));trivial.
+ rewrite <-not_true_iff_false, existsb_exists, Lit.interp_neg.
+ case_eq (Lit.interp rho (a .[ i]));trivial.
+ intros Heq Hex;elim Hex;exists (a.[i]);split;trivial.
+ apply to_list_In; auto.
+ case_eq (i == PArray.length a - 1);intros Heq;simpl;
+ rewrite Lit.interp_lit;unfold Var.interp;rewrite rho_interp, H;simpl;
+ rewrite afold_right_impb; case_eq (C.interp rho (to_list (or_of_imp a)));trivial;
+ unfold C.interp;rewrite <-not_true_iff_false, existsb_exists;
+ try rewrite Lit.interp_neg; case_eq (Lit.interp rho (a .[ i]));trivial;
+ intros Heq' Hex;elim Hex.
+ exists (a.[i]);split;trivial.
+ assert (H1: 0 < PArray.length a) by (apply (leb_ltb_trans _ i _); auto; apply leb_0); rewrite Int63Properties.eqb_spec in Heq; rewrite <- (get_or_of_imp2 H1 Heq); apply to_list_In; rewrite length_or_of_imp; auto.
+ exists (Lit.neg (a.[i]));rewrite Lit.interp_neg, Heq';split;trivial.
+ assert (H1: i < PArray.length a - 1 = true) by (rewrite ltb_spec, (to_Z_sub_1 _ _ Hlt); rewrite eqb_false_spec in Heq; assert (H1: [|i|] <> ([|PArray.length a|] - 1)%Z) by (intro H1; apply Heq, to_Z_inj; rewrite (to_Z_sub_1 _ _ Hlt); auto); rewrite ltb_spec in Hlt; omega); rewrite <- (get_or_of_imp H1); apply to_list_In; rewrite length_or_of_imp; auto.
+ Qed.
+
+ Hypothesis Hs : S.valid rho s.
+
+ Lemma valid_check_ImmBuildDef : forall cid,
+ C.valid rho (check_ImmBuildDef cid).
+ Proof.
+ unfold check_ImmBuildDef,C.valid;intros cid.
+ generalize (Hs cid);unfold C.valid.
+ destruct (S.get s cid) as [ | l [ | _l _c]];auto using C.interp_true.
+ simpl;unfold Lit.interp, Var.interp; rewrite !rho_interp;
+ destruct (t_form.[Lit.blit l]);auto using C.interp_true;
+ case_eq (Lit.is_pos l);intros Heq;auto using C.interp_true;simpl;
+ tauto_check.
+ rewrite afold_left_and, Cinterp_neg, orb_false_r;trivial.
+ rewrite afold_left_or, orb_false_r;trivial.
+ rewrite afold_right_impb, orb_false_r;trivial.
+ Qed.
+
+ Lemma valid_check_ImmBuildDef2 : forall cid, C.valid rho (check_ImmBuildDef2 cid).
+ Proof.
+ unfold check_ImmBuildDef2,C.valid;intros cid.
+ generalize (Hs cid);unfold C.valid.
+ destruct (S.get s cid) as [ | l [ | _l _c]];auto using C.interp_true.
+ simpl;unfold Lit.interp, Var.interp; rewrite !rho_interp;
+ destruct (t_form.[Lit.blit l]);auto using C.interp_true;
+ case_eq (Lit.is_pos l);intros Heq;auto using C.interp_true;simpl;
+ tauto_check.
+ Qed.
+
+ Lemma valid_check_ImmBuildProj : forall cid i, C.valid rho (check_ImmBuildProj cid i).
+ Proof.
+ unfold check_ImmBuildProj,C.valid;intros cid i.
+ generalize (Hs cid);unfold C.valid.
+ destruct (S.get s cid) as [ | l [ | _l _c]];auto using C.interp_true.
+ simpl;unfold Lit.interp, Var.interp; rewrite !rho_interp;
+ destruct (t_form.[Lit.blit l]);auto using C.interp_true;
+ case_eq (i < PArray.length a); intros Hlt;auto using C.interp_true;
+ case_eq (Lit.is_pos l);intros Heq;auto using C.interp_true;simpl;
+ rewrite !orb_false_r.
+ rewrite afold_left_and.
+ rewrite forallb_forall;intros H;apply H;auto.
+ apply to_list_In; auto.
+ rewrite negb_true_iff, <-not_true_iff_false, afold_left_or.
+ unfold C.interp;rewrite existsb_exists, Lit.interp_neg.
+ case_eq (Lit.interp rho (a .[ i]));trivial.
+ intros Heq' Hex;elim Hex;exists (a.[i]);split;trivial.
+ apply to_list_In; auto.
+ rewrite negb_true_iff, <-not_true_iff_false, afold_right_impb.
+ case_eq (i == PArray.length a - 1);intros Heq';simpl;
+ unfold C.interp;simpl;try rewrite Lit.interp_neg;rewrite orb_false_r,
+ existsb_exists;case_eq (Lit.interp rho (a .[ i]));trivial;
+ intros Heq2 Hex;elim Hex.
+ exists (a.[i]);split;trivial.
+ assert (H1: 0 < PArray.length a) by (apply (leb_ltb_trans _ i _); auto; apply leb_0); rewrite Int63Properties.eqb_spec in Heq'; rewrite <- (get_or_of_imp2 H1 Heq'); apply to_list_In; rewrite length_or_of_imp; auto.
+ exists (Lit.neg (a.[i]));rewrite Lit.interp_neg, Heq2;split;trivial.
+ assert (H1: i < PArray.length a - 1 = true) by (rewrite ltb_spec, (to_Z_sub_1 _ _ Hlt); rewrite eqb_false_spec in Heq'; assert (H1: [|i|] <> ([|PArray.length a|] - 1)%Z) by (intro H1; apply Heq', to_Z_inj; rewrite (to_Z_sub_1 _ _ Hlt); auto); rewrite ltb_spec in Hlt; omega); rewrite <- (get_or_of_imp H1); apply to_list_In; rewrite length_or_of_imp; auto.
+ Qed.
+
+End CHECKER.
+
+Unset Implicit Arguments.