https://github.com/EasyCrypt/easycrypt
Raw File
Tip revision: 9f6a2f9c698e6c47fa841a0b040bc45d82a601c5 authored by Benjamin Gregoire on 07 July 2016, 06:32:45 UTC
add make
Tip revision: 9f6a2f9
NewLogic.ec
(* --------------------------------------------------------------------
 * Copyright (c) - 2012--2016 - IMDEA Software Institute
 * Copyright (c) - 2012--2016 - Inria
 *
 * Distributed under the terms of the CeCILL-B-V1 license
 * -------------------------------------------------------------------- *)

(* This API has been mostly inspired from the [ssrbool] library of the
 * ssreflect Coq extension. *)

require import Pred Fun.

pragma +implicits.

(* -------------------------------------------------------------------- *)
(* These should be declared as externals (SMT-LIB knows them)
   external (\x): bool -> bool -> bool.
   external ite : bool -> bool -> bool -> bool. *)

(* op (&&) b1 b2 = if b1 then b2 else false. *)
(* op (||) b1 b2 = if b1 then true else b2. *)
op (^) b1 b2  = if b1 then !b2 else b2.

(* -------------------------------------------------------------------- *)
(* Negation lemmas. *)
lemma negbT b  : b = false => !b by [].
lemma negbTE b : !b => b = false by [].
lemma negbF b  : b => !b = false by [].
lemma negbFE b : !b = false => b by [].
lemma negbK    : involutive [!]  by case. (* FIXME: by []: "Not a formula: x1" *)
lemma negbNE b : !!b => b        by [].

lemma negb_inj : injective [!]      by exact: (can_inj _ _ negbK).
lemma negbLR b c : b = !c => !b = c by [].
lemma negbRL b c : !b = c => b = !c by [].

lemma contra (c b : bool) : (c => b) => !b => !c   by [].

lemma contraL (c b : bool) : (c => !b) => b => !c  by [].

lemma contraR (c b : bool) : (!c => b) => !b => c  by [].

lemma contraLR (c b : bool) : (!c => !b) => b => c by [].

lemma contraT b : (!b => false) => b               by [].

lemma wlog_neg b : (!b => b) => b                  by [].

lemma contraFT (c b : bool) : (!c => b) => b = false => c
by [].

lemma contraFN (c b : bool) : (c => b) => b = false => !c
by [].

lemma contraTF (c b : bool) : (c => !b) => b => c = false
by [].

lemma contraNF (c b : bool) : (c => b) => !b => c = false
by [].

lemma contraFF (c b : bool) : (c => b) => b = false => c = false
by [].

(* -------------------------------------------------------------------- *)
(* Lemmas for ifs *)

lemma ifT b (vT vF : 'a) : b => (if b then vT else vF) = vT         by [].
lemma ifF b (vT vF : 'a) : b = false => (if b then vT else vF) = vF by [].
lemma ifN b (vT vF : 'a) : !b => (if b then vT else vF) = vF        by [].

lemma if_same b (vT : 'a) : (if b then vT else vT) = vT
by [].

lemma if_neg b (vT vF : 'a) :
  (if !b then vT else vF) = if b then vF else vT
by [].

lemma fun_if (f : 'a -> 'b) b vT vF:
  f (if b then vT else vF) = if b then f vT else f vF
by [].

lemma if_arg b x (fT fF : 'a -> 'b) :
  (if b then fT else fF) x = if b then fT x else fF x
by [].

(* -------------------------------------------------------------------- *)
(* Boolean connectives laws. *)

lemma andTb : left_id true (/\)       by case.
lemma andFb : left_zero false (/\)    by case.
lemma andbT : right_id true (/\)      by case.
lemma andbF : right_zero false (/\)   by case.
lemma andbb : idempotent (/\)         by case.
lemma andbC : commutative (/\)        by do 2!case.
lemma andbA : associative (/\)        by do 3!case.
lemma andbCA : left_commutative (/\)  by do 3!case.
lemma andbAC : right_commutative (/\) by do 3!case.
lemma andbACA : interchange (/\) (/\) by do 4!case.

lemma orTb : forall b, true \/ b     by case.
lemma orFb : left_id false (\/)      by case.
lemma orbT : forall b, b \/ true     by case.
lemma orbF : right_id false (\/)     by case.
lemma orbb : idempotent (\/)         by case.
lemma orbC : commutative (\/)        by do 2!case.
lemma orbA : associative (\/)        by do 3!case.
lemma orbCA : left_commutative (\/)  by do 3!case.
lemma orbAC : right_commutative (\/) by do 3!case.
lemma orbACA : interchange (\/) (\/) by do 4!case.

lemma andbN b : (b /\ !b) <=> false by case: b.
lemma andNb b : (!b /\ b) <=> false by case: b.
lemma orbN b  : (b \/ !b) <=> true  by case: b.
lemma orNb b  : (!b \/ b) <=> true  by case: b.

lemma andb_orl : left_distributive (/\) (\/)  by do 3!case.
lemma andb_orr : right_distributive (/\) (\/) by do 3!case.
lemma orb_andl : left_distributive (\/) (/\)  by do 3!case.
lemma orb_andr : right_distributive (\/) (/\) by do 3!case.

lemma andb_idl (a b : bool) : (b => a) => a /\ b <=> b
by [].

lemma andb_idr (a b : bool) : (a => b) => a /\ b <=> a
by [].

lemma andb_id2l (a b c : bool) : (a => b = c) => a /\ b <=> a /\ c
by [].

lemma andb_id2r (a b c : bool) : (b => a = c) => a /\ b <=> c /\ b
by [].

lemma orb_idl (a b : bool) : (a => b) => a \/ b <=> b
by [].

lemma orb_idr (a b : bool) : (b => a) => a \/ b <=> a
by [].

lemma orb_id2l (a b c : bool) : (!a => b = c) => a \/ b <=> a \/ c
by [].

lemma orb_id2r (a b c : bool) : (!b => a = c) => a \/ b <=> c \/ b
by [].

lemma negb_and (a b : bool) : !(a /\ b) <=> !a \/ !b
by [].

lemma negb_or (a b : bool) : !(a \/ b) <=> !a /\ !b
by [].

(* -------------------------------------------------------------------- *)
(* Additional connective laws that work for us *)
lemma negb_exists (P : 'a -> bool): !(exists a, P a) <=> forall a, !P a
by [].

lemma negb_forall (P : 'a -> bool): !(forall a, P a) <=> exists a, !P a
by [].

(* -------------------------------------------------------------------- *)
(* Absorption *)

lemma andbK a b : a /\ b \/ a <=> a  by [].
lemma andKb a b : a \/ b /\ a <=> a  by [].
lemma orbK a b : (a \/ b) /\ a <=> a by [].
lemma orKb a b : a /\ (b \/ a) <=> a by [].

(* -------------------------------------------------------------------- *)
(* Imply *)

lemma implybT b : b => true         by [].
lemma implybF b : (b => false) = !b by [].
lemma implyFb b : false => b        by [].
lemma implyTb b : (true => b) = b   by [].
lemma implybb b : b => b            by [].

lemma negb_imply a b : !(a => b) <=> a /\ !b
by [].

lemma implybE a b : (a => b) <=> !a \/ b
by [].

lemma implyNb a b : (!a => b) <=> a \/ b
by [].

lemma implybN a b : (a => !b) <=> (b => !a)
by [].

lemma implybNN a b : (!a => !b) <=> b => a
by [].

lemma implyb_idl (a b : bool) : (!a => b) => (a => b) <=> b
by [].

lemma implyb_idr (a b : bool) : (b => !a) => (a => b) <=> !a
by [].

lemma implyb_id2l (a b c : bool) :
  (a => b <=> c) => (a => b) <=> (a => c)
by [].

(* -------------------------------------------------------------------- *)
(* Addition (xor) *)

lemma addFb : left_id false (^)               by case.
lemma addbF : right_id false (^)              by case.
lemma addbb : self_inverse false (^)          by case.
lemma addbC : commutative (^)                 by do 2!case.
lemma addbA : associative (^)                 by do 3!case.
lemma addbCA : left_commutative (^)           by do 3!case.
lemma addbAC : right_commutative (^)          by do 3!case.
lemma addbACA : interchange (^) (^)           by do 4!case.
lemma andb_addl : left_distributive (/\) (^)  by do 3!case.
lemma andb_addr : right_distributive (/\) (^) by do 3!case.
lemma addKb : left_loop idfun (^)             by do 2!case.
lemma addbK : right_loop idfun (^)            by do 2!case.
lemma addIb : left_injective (^)              by do 3!case.
lemma addbI : right_injective (^)             by do 3!case.

lemma addTb b : true ^ b <=> !b by case: b.
lemma addbT b : b ^ true <=> !b by case: b.

lemma addbN a b : a ^ !b <=> !(a ^ b) by case: a b.
lemma addNb a b : !a ^ b <=> !(a ^ b) by case: a b.

lemma addbP a b : (!a <=> b) <=> (a ^ b) by case: a b.

(* -------------------------------------------------------------------- *)
(* Short-circuiting *)

lemma andabP b1 b2 : b1 && b2 <=> b1 /\ b2 by [].
lemma orabP  b1 b2 : b1 || b2 <=> b1 \/ b2 by [].

lemma andab_andb : (&&) = (/\).
proof. by apply/ExtEq.rel_ext=> x y; rewrite andabP. qed.

lemma orab_orb : (||) = (\/).
proof. by apply/ExtEq.rel_ext=> x y; rewrite orabP. qed.

(* -------------------------------------------------------------------- *)
lemma forall_orl (P : bool) (Q : 'a -> bool) :
  (P \/ (forall (x : 'a), Q x)) <=> forall (x : 'a), (P \/ Q x).
proof. by case: P. qed.

lemma forall_orr (P : bool) (Q : 'a -> bool) :
  ((forall (x : 'a), Q x) \/ P) <=> forall (x : 'a), (Q x \/ P).
proof. by case: P. qed.

(* -------------------------------------------------------------------- *)
lemma forall_andl (P : bool) (Q : 'a -> bool) :
  (P /\ (forall (x : 'a), Q x)) <=> forall (x : 'a), (P /\ Q x).
proof. by case: P. qed.

lemma forall_andr (P : bool) (Q : 'a -> bool) :
  ((forall (x : 'a), Q x) /\ P) <=> forall (x : 'a), (Q x /\ P).
proof. by case: P. qed.

(* -------------------------------------------------------------------- *)
lemma forall_eq (P P' : 'a -> bool) :
  (forall x, P x = P' x) =>
  (forall (x : 'a), P x) <=> (forall (x : 'a), P' x).
proof. by move=> /ExtEq.fun_ext ->. qed.

lemma forall_eq_in (P : 'a -> bool) (Q Q' : 'a -> bool) :
  (forall x, P x => (Q x = Q' x)) =>
  (forall (x : 'a), P x => Q x) <=> (forall (x : 'a), P x => Q' x).
proof.
(* FIXME? Why is exact/eq_Q needed? *)
by move=> eq_Q; apply/forall_eq=> x /=; case (P x)=> //; exact/eq_Q.
qed.

lemma forall_iff (P P' : 'a -> bool) :
  (forall x, P x <=> P' x) =>
  (forall (x : 'a), P x) <=> (forall (x : 'a), P' x).
proof. by move=> eq_P; split=> h x; have /eq_P:= h x. qed.

lemma forall_iff_in (P : 'a -> bool) (Q Q' : 'a -> bool) :
  (forall x, P x => (Q x <=> Q' x)) =>
  (forall (x : 'a), P x => Q x) <=> (forall (x : 'a), P x => Q' x).
proof.
by move=> eq_Q; apply/forall_iff=> x /=; case (P x)=> //; exact/eq_Q.
qed.

(* -------------------------------------------------------------------- *)
lemma exists_orl (P : bool) (Q : 'a -> bool) :
  (P \/ (exists (x : 'a), Q x)) <=> exists (x : 'a), (P \/ Q x).
proof. by case: P. qed.

lemma exists_orr (P : bool) (Q : 'a -> bool) :
  ((exists (x : 'a), Q x) \/ P) <=> exists (x : 'a), (Q x \/ P).
proof. by case: P. qed.

(* -------------------------------------------------------------------- *)
lemma exists_andl (P : bool) (Q : 'a -> bool) :
  (P /\ (exists (x : 'a), Q x)) <=> exists (x : 'a), (P /\ Q x).
proof. by case: P. qed.

lemma exists_andr (P : bool) (Q : 'a -> bool) :
  ((exists (x : 'a), Q x) /\ P) <=> exists (x : 'a), (Q x /\ P).
proof. by case: P. qed.

(* -------------------------------------------------------------------- *)
lemma exists_eq (P P' : 'a -> bool) :
  (forall x, P x = P' x) =>
  (exists (x : 'a), P x) <=> (exists (x : 'a), P' x).
proof. by move=> /ExtEq.fun_ext ->. qed.

lemma exists_eq_in (P : 'a -> bool) (Q Q' : 'a -> bool) :
  (forall x, P x => (Q x = Q' x)) =>
  (exists (x : 'a), P x /\ Q x) <=> (exists (x : 'a), P x /\ Q' x).
proof.
by move=> eq_Q; apply/exists_eq=> x /=; case (P x)=> //; exact/eq_Q.
qed.

lemma exists_iff (P P' : 'a -> bool) :
  (forall x, P x <=> P' x) =>
  (exists (x : 'a), P x) <=> (exists (x : 'a), P' x).
proof. by move=> eq_P; split; move=> [a] /eq_P h; exists a. qed.

lemma exists_iff_in (P : 'a -> bool) (Q Q' : 'a -> bool) :
  (forall x, P x => (Q x <=> Q' x)) =>
  (exists (x : 'a), P x /\ Q x) <=> (exists (x : 'a), P x /\ Q' x).
proof.
by move=> eq_Q; apply/exists_iff=> x /=; case (P x)=> //; exact/eq_Q.
qed.

(* -------------------------------------------------------------------- *)
(* Pred? *)
(* Rel?  *)

(* -------------------------------------------------------------------- *)
(* Some things that may be needed in addition to ssrbool,
   but maybe better structured than currently *)
(*
lemma bool_case p: p true => p false => (forall b, p b) by [].

(* views on iff: eq_iff, iffLR, iffRL ... *)
(* congruence and rewriting               *)
(* ...                                    *)
*)
back to top