added enumeration of predicates
authorhaftmann
Fri, 06 Mar 2009 20:30:17 +0100
changeset 30328 ab47f43f7581
parent 30327 4d1185c77f4a
child 30329 97ce36d801b6
added enumeration of predicates
src/HOL/Predicate.thy
src/HOL/ex/ExecutableContent.thy
--- a/src/HOL/Predicate.thy	Fri Mar 06 20:30:17 2009 +0100
+++ b/src/HOL/Predicate.thy	Fri Mar 06 20:30:17 2009 +0100
@@ -1,15 +1,40 @@
 (*  Title:      HOL/Predicate.thy
-    ID:         $Id$
-    Author:     Stefan Berghofer, TU Muenchen
+    Author:     Stefan Berghofer and Lukas Bulwahn and Florian Haftmann, TU Muenchen
 *)
 
-header {* Predicates *}
+header {* Predicates as relations and enumerations *}
 
 theory Predicate
 imports Inductive Relation
 begin
 
-subsection {* Equality and Subsets *}
+notation
+  inf (infixl "\<sqinter>" 70) and
+  sup (infixl "\<squnion>" 65) and
+  Inf ("\<Sqinter>_" [900] 900) and
+  Sup ("\<Squnion>_" [900] 900) and
+  top ("\<top>") and
+  bot ("\<bottom>")
+
+
+subsection {* Predicates as (complete) lattices *}
+
+subsubsection {* @{const sup} on @{typ bool} *}
+
+lemma sup_boolI1:
+  "P \<Longrightarrow> P \<squnion> Q"
+  by (simp add: sup_bool_eq)
+
+lemma sup_boolI2:
+  "Q \<Longrightarrow> P \<squnion> Q"
+  by (simp add: sup_bool_eq)
+
+lemma sup_boolE:
+  "P \<squnion> Q \<Longrightarrow> (P \<Longrightarrow> R) \<Longrightarrow> (Q \<Longrightarrow> R) \<Longrightarrow> R"
+  by (auto simp add: sup_bool_eq)
+
+
+subsubsection {* Equality and Subsets *}
 
 lemma pred_equals_eq: "((\<lambda>x. x \<in> R) = (\<lambda>x. x \<in> S)) = (R = S)"
   by (simp add: mem_def)
@@ -24,7 +49,7 @@
   by fast
 
 
-subsection {* Top and bottom elements *}
+subsubsection {* Top and bottom elements *}
 
 lemma top1I [intro!]: "top x"
   by (simp add: top_fun_eq top_bool_eq)
@@ -39,7 +64,7 @@
   by (simp add: bot_fun_eq bot_bool_eq)
 
 
-subsection {* The empty set *}
+subsubsection {* The empty set *}
 
 lemma bot_empty_eq: "bot = (\<lambda>x. x \<in> {})"
   by (auto simp add: expand_fun_eq)
@@ -48,7 +73,7 @@
   by (auto simp add: expand_fun_eq)
 
 
-subsection {* Binary union *}
+subsubsection {* Binary union *}
 
 lemma sup1_iff [simp]: "sup A B x \<longleftrightarrow> A x | B x"
   by (simp add: sup_fun_eq sup_bool_eq)
@@ -92,7 +117,7 @@
   by simp iprover
 
 
-subsection {* Binary intersection *}
+subsubsection {* Binary intersection *}
 
 lemma inf1_iff [simp]: "inf A B x \<longleftrightarrow> A x \<and> B x"
   by (simp add: inf_fun_eq inf_bool_eq)
@@ -131,7 +156,7 @@
   by simp
 
 
-subsection {* Unions of families *}
+subsubsection {* Unions of families *}
 
 lemma SUP1_iff [simp]: "(SUP x:A. B x) b = (EX x:A. B x b)"
   by (simp add: SUPR_def Sup_fun_def Sup_bool_def) blast
@@ -158,7 +183,7 @@
   by (simp add: expand_fun_eq)
 
 
-subsection {* Intersections of families *}
+subsubsection {* Intersections of families *}
 
 lemma INF1_iff [simp]: "(INF x:A. B x) b = (ALL x:A. B x b)"
   by (simp add: INFI_def Inf_fun_def Inf_bool_def) blast
@@ -191,7 +216,9 @@
   by (simp add: expand_fun_eq)
 
 
-subsection {* Composition of two relations *}
+subsection {* Predicates as relations *}
+
+subsubsection {* Composition  *}
 
 inductive
   pred_comp  :: "['b => 'c => bool, 'a => 'b => bool] => 'a => 'c => bool"
@@ -207,7 +234,7 @@
   by (auto simp add: expand_fun_eq elim: pred_compE)
 
 
-subsection {* Converse *}
+subsubsection {* Converse *}
 
 inductive
   conversep :: "('a => 'b => bool) => 'b => 'a => bool"
@@ -253,7 +280,7 @@
   by (auto simp add: expand_fun_eq)
 
 
-subsection {* Domain *}
+subsubsection {* Domain *}
 
 inductive
   DomainP :: "('a => 'b => bool) => 'a => bool"
@@ -267,7 +294,7 @@
   by (blast intro!: Orderings.order_antisym predicate1I)
 
 
-subsection {* Range *}
+subsubsection {* Range *}
 
 inductive
   RangeP :: "('a => 'b => bool) => 'b => bool"
@@ -281,7 +308,7 @@
   by (blast intro!: Orderings.order_antisym predicate1I)
 
 
-subsection {* Inverse image *}
+subsubsection {* Inverse image *}
 
 definition
   inv_imagep :: "('b => 'b => bool) => ('a => 'b) => 'a => 'a => bool" where
@@ -294,7 +321,7 @@
   by (simp add: inv_imagep_def)
 
 
-subsection {* The Powerset operator *}
+subsubsection {* Powerset *}
 
 definition Powp :: "('a \<Rightarrow> bool) \<Rightarrow> 'a set \<Rightarrow> bool" where
   "Powp A == \<lambda>B. \<forall>x \<in> B. A x"
@@ -305,7 +332,7 @@
 lemmas Powp_mono [mono] = Pow_mono [to_pred pred_subset_eq]
 
 
-subsection {* Properties of relations - predicate versions *}
+subsubsection {* Properties of relations *}
 
 abbreviation antisymP :: "('a => 'a => bool) => bool" where
   "antisymP r == antisym {(x, y). r x y}"
@@ -316,4 +343,264 @@
 abbreviation single_valuedP :: "('a => 'b => bool) => bool" where
   "single_valuedP r == single_valued {(x, y). r x y}"
 
+
+subsection {* Predicates as enumerations *}
+
+subsubsection {* The type of predicate enumerations (a monad) *}
+
+datatype 'a pred = Pred "'a \<Rightarrow> bool"
+
+primrec eval :: "'a pred \<Rightarrow> 'a \<Rightarrow> bool" where
+  eval_pred: "eval (Pred f) = f"
+
+lemma Pred_eval [simp]:
+  "Pred (eval x) = x"
+  by (cases x) simp
+
+lemma eval_inject: "eval x = eval y \<longleftrightarrow> x = y"
+  by (cases x) auto
+
+definition single :: "'a \<Rightarrow> 'a pred" where
+  "single x = Pred ((op =) x)"
+
+definition bind :: "'a pred \<Rightarrow> ('a \<Rightarrow> 'b pred) \<Rightarrow> 'b pred" (infixl "\<guillemotright>=" 70) where
+  "P \<guillemotright>= f = Pred (\<lambda>x. (\<exists>y. eval P y \<and> eval (f y) x))"
+
+instantiation pred :: (type) complete_lattice
+begin
+
+definition
+  "P \<le> Q \<longleftrightarrow> eval P \<le> eval Q"
+
+definition
+  "P < Q \<longleftrightarrow> eval P < eval Q"
+
+definition
+  "\<bottom> = Pred \<bottom>"
+
+definition
+  "\<top> = Pred \<top>"
+
+definition
+  "P \<sqinter> Q = Pred (eval P \<sqinter> eval Q)"
+
+definition
+  "P \<squnion> Q = Pred (eval P \<squnion> eval Q)"
+
+definition
+  "\<Sqinter>A = Pred (INFI A eval)"
+
+definition
+  "\<Squnion>A = Pred (SUPR A eval)"
+
+instance by default
+  (auto simp add: less_eq_pred_def less_pred_def
+    inf_pred_def sup_pred_def bot_pred_def top_pred_def
+    Inf_pred_def Sup_pred_def,
+    auto simp add: le_fun_def less_fun_def le_bool_def less_bool_def
+    eval_inject mem_def)
+
 end
+
+lemma bind_bind:
+  "(P \<guillemotright>= Q) \<guillemotright>= R = P \<guillemotright>= (\<lambda>x. Q x \<guillemotright>= R)"
+  by (auto simp add: bind_def expand_fun_eq)
+
+lemma bind_single:
+  "P \<guillemotright>= single = P"
+  by (simp add: bind_def single_def)
+
+lemma single_bind:
+  "single x \<guillemotright>= P = P x"
+  by (simp add: bind_def single_def)
+
+lemma bottom_bind:
+  "\<bottom> \<guillemotright>= P = \<bottom>"
+  by (auto simp add: bot_pred_def bind_def expand_fun_eq)
+
+lemma sup_bind:
+  "(P \<squnion> Q) \<guillemotright>= R = P \<guillemotright>= R \<squnion> Q \<guillemotright>= R"
+  by (auto simp add: bind_def sup_pred_def expand_fun_eq)
+
+lemma Sup_bind: "(\<Squnion>A \<guillemotright>= f) = \<Squnion>((\<lambda>x. x \<guillemotright>= f) ` A)"
+  by (auto simp add: bind_def Sup_pred_def expand_fun_eq)
+
+lemma pred_iffI:
+  assumes "\<And>x. eval A x \<Longrightarrow> eval B x"
+  and "\<And>x. eval B x \<Longrightarrow> eval A x"
+  shows "A = B"
+proof -
+  from assms have "\<And>x. eval A x \<longleftrightarrow> eval B x" by blast
+  then show ?thesis by (cases A, cases B) (simp add: expand_fun_eq)
+qed
+  
+lemma singleI: "eval (single x) x"
+  unfolding single_def by simp
+
+lemma singleI_unit: "eval (single ()) x"
+  by simp (rule singleI)
+
+lemma singleE: "eval (single x) y \<Longrightarrow> (y = x \<Longrightarrow> P) \<Longrightarrow> P"
+  unfolding single_def by simp
+
+lemma singleE': "eval (single x) y \<Longrightarrow> (x = y \<Longrightarrow> P) \<Longrightarrow> P"
+  by (erule singleE) simp
+
+lemma bindI: "eval P x \<Longrightarrow> eval (Q x) y \<Longrightarrow> eval (P \<guillemotright>= Q) y"
+  unfolding bind_def by auto
+
+lemma bindE: "eval (R \<guillemotright>= Q) y \<Longrightarrow> (\<And>x. eval R x \<Longrightarrow> eval (Q x) y \<Longrightarrow> P) \<Longrightarrow> P"
+  unfolding bind_def by auto
+
+lemma botE: "eval \<bottom> x \<Longrightarrow> P"
+  unfolding bot_pred_def by auto
+
+lemma supI1: "eval A x \<Longrightarrow> eval (A \<squnion> B) x"
+  unfolding sup_pred_def by simp
+
+lemma supI2: "eval B x \<Longrightarrow> eval (A \<squnion> B) x" 
+  unfolding sup_pred_def by simp
+
+lemma supE: "eval (A \<squnion> B) x \<Longrightarrow> (eval A x \<Longrightarrow> P) \<Longrightarrow> (eval B x \<Longrightarrow> P) \<Longrightarrow> P"
+  unfolding sup_pred_def by auto
+
+
+subsubsection {* Derived operations *}
+
+definition if_pred :: "bool \<Rightarrow> unit pred" where
+  if_pred_eq: "if_pred b = (if b then single () else \<bottom>)"
+
+definition eq_pred :: "'a \<Rightarrow> 'a \<Rightarrow> unit pred" where
+  eq_pred_eq: "eq_pred a b = if_pred (a = b)"
+
+definition not_pred :: "unit pred \<Rightarrow> unit pred" where
+  not_pred_eq: "not_pred P = (if eval P () then \<bottom> else single ())"
+
+lemma if_predI: "P \<Longrightarrow> eval (if_pred P) ()"
+  unfolding if_pred_eq by (auto intro: singleI)
+
+lemma if_predE: "eval (if_pred b) x \<Longrightarrow> (b \<Longrightarrow> x = () \<Longrightarrow> P) \<Longrightarrow> P"
+  unfolding if_pred_eq by (cases b) (auto elim: botE)
+
+lemma eq_predI: "eval (eq_pred a a) ()"
+  unfolding eq_pred_eq if_pred_eq by (auto intro: singleI)
+
+lemma eq_predE: "eval (eq_pred a b) x \<Longrightarrow> (a = b \<Longrightarrow> x = () \<Longrightarrow> P) \<Longrightarrow> P"
+  unfolding eq_pred_eq by (erule if_predE)
+
+lemma not_predI: "\<not> P \<Longrightarrow> eval (not_pred (Pred (\<lambda>u. P))) ()"
+  unfolding not_pred_eq eval_pred by (auto intro: singleI)
+
+lemma not_predI': "\<not> eval P () \<Longrightarrow> eval (not_pred P) ()"
+  unfolding not_pred_eq by (auto intro: singleI)
+
+lemma not_predE: "eval (not_pred (Pred (\<lambda>u. P))) x \<Longrightarrow> (\<not> P \<Longrightarrow> thesis) \<Longrightarrow> thesis"
+  unfolding not_pred_eq
+  by (auto split: split_if_asm elim: botE)
+
+lemma not_predE': "eval (not_pred P) x \<Longrightarrow> (\<not> eval P x \<Longrightarrow> thesis) \<Longrightarrow> thesis"
+  unfolding not_pred_eq
+  by (auto split: split_if_asm elim: botE)
+
+
+subsubsection {* Implementation *}
+
+datatype 'a seq = Empty | Insert "'a" "'a pred" | Join "'a pred" "'a seq"
+
+primrec pred_of_seq :: "'a seq \<Rightarrow> 'a pred" where
+    "pred_of_seq Empty = \<bottom>"
+  | "pred_of_seq (Insert x P) = single x \<squnion> P"
+  | "pred_of_seq (Join P xq) = P \<squnion> pred_of_seq xq"
+
+definition Seq :: "(unit \<Rightarrow> 'a seq) \<Rightarrow> 'a pred" where
+  "Seq f = pred_of_seq (f ())"
+
+code_datatype Seq
+
+primrec member :: "'a seq \<Rightarrow> 'a \<Rightarrow> bool"  where
+  "member Empty x \<longleftrightarrow> False"
+  | "member (Insert y P) x \<longleftrightarrow> x = y \<or> eval P x"
+  | "member (Join P xq) x \<longleftrightarrow> eval P x \<or> member xq x"
+
+lemma eval_member:
+  "member xq = eval (pred_of_seq xq)"
+proof (induct xq)
+  case Empty show ?case
+  by (auto simp add: expand_fun_eq elim: botE)
+next
+  case Insert show ?case
+  by (auto simp add: expand_fun_eq elim: supE singleE intro: supI1 supI2 singleI)
+next
+  case Join then show ?case
+  by (auto simp add: expand_fun_eq elim: supE intro: supI1 supI2)
+qed
+
+lemma eval_code [code]: "eval (Seq f) = member (f ())"
+  unfolding Seq_def by (rule sym, rule eval_member)
+
+lemma single_code [code]:
+  "single x = Seq (\<lambda>u. Insert x \<bottom>)"
+  unfolding Seq_def by simp
+
+primrec "apply" :: "('a \<Rightarrow> 'b Predicate.pred) \<Rightarrow> 'a seq \<Rightarrow> 'b seq" where
+    "apply f Empty = Empty"
+  | "apply f (Insert x P) = Join (f x) (Join (P \<guillemotright>= f) Empty)"
+  | "apply f (Join P xq) = Join (P \<guillemotright>= f) (apply f xq)"
+
+lemma apply_bind:
+  "pred_of_seq (apply f xq) = pred_of_seq xq \<guillemotright>= f"
+proof (induct xq)
+  case Empty show ?case
+    by (simp add: bottom_bind)
+next
+  case Insert show ?case
+    by (simp add: single_bind sup_bind)
+next
+  case Join then show ?case
+    by (simp add: sup_bind)
+qed
+  
+lemma bind_code [code]:
+  "Seq g \<guillemotright>= f = Seq (\<lambda>u. apply f (g ()))"
+  unfolding Seq_def by (rule sym, rule apply_bind)
+
+lemma bot_set_code [code]:
+  "\<bottom> = Seq (\<lambda>u. Empty)"
+  unfolding Seq_def by simp
+
+lemma sup_code [code]:
+  "Seq f \<squnion> Seq g = Seq (\<lambda>u. case f ()
+    of Empty \<Rightarrow> g ()
+     | Insert x P \<Rightarrow> Insert x (P \<squnion> Seq g)
+     | Join P xq \<Rightarrow> Join (Seq g) (Join P xq))" (*FIXME order!?*)
+proof (cases "f ()")
+  case Empty
+  thus ?thesis
+    unfolding Seq_def by (simp add: sup_commute [of "\<bottom>"] sup_bot)
+next
+  case Insert
+  thus ?thesis
+    unfolding Seq_def by (simp add: sup_assoc)
+next
+  case Join
+  thus ?thesis
+    unfolding Seq_def by (simp add: sup_commute [of "pred_of_seq (g ())"] sup_assoc)
+qed
+
+
+declare eq_pred_def [code, code del]
+
+no_notation
+  inf (infixl "\<sqinter>" 70) and
+  sup (infixl "\<squnion>" 65) and
+  Inf ("\<Sqinter>_" [900] 900) and
+  Sup ("\<Squnion>_" [900] 900) and
+  top ("\<top>") and
+  bot ("\<bottom>") and
+  bind (infixl "\<guillemotright>=" 70)
+
+hide (open) type pred seq
+hide (open) const Pred eval single bind if_pred eq_pred not_pred
+  Empty Insert Join Seq member "apply"
+
+end
--- a/src/HOL/ex/ExecutableContent.thy	Fri Mar 06 20:30:17 2009 +0100
+++ b/src/HOL/ex/ExecutableContent.thy	Fri Mar 06 20:30:17 2009 +0100
@@ -24,6 +24,8 @@
   "~~/src/HOL/ex/Records"
 begin
 
+lemma [code, code del]: "(term_of \<Colon> 'a Predicate.pred \<Rightarrow> term) = term_of" ..
+
 text {* However, some aren't executable *}
 
 declare pair_leq_def[code del]