
berghofe@22259: (*  Title:      HOL/Predicate.thy
haftmann@30328:     Author:     Stefan Berghofer and Lukas Bulwahn and Florian Haftmann, TU Muenchen
berghofe@22259: *)
berghofe@22259: 
haftmann@30328: header {* Predicates as relations and enumerations *}
berghofe@22259: 
berghofe@22259: theory Predicate
haftmann@23708: imports Inductive Relation
berghofe@22259: begin
berghofe@22259: 
haftmann@30328: notation
haftmann@30328:   inf (infixl "\<sqinter>" 70) and
haftmann@30328:   sup (infixl "\<squnion>" 65) and
haftmann@30328:   Inf ("\<Sqinter>_" [900] 900) and
haftmann@30328:   Sup ("\<Squnion>_" [900] 900) and
haftmann@30328:   top ("\<top>") and
haftmann@30328:   bot ("\<bottom>")
haftmann@30328: 
haftmann@30328: 
haftmann@30328: subsection {* Predicates as (complete) lattices *}
haftmann@30328: 
haftmann@32779: subsubsection {* Equality *}
berghofe@22259: 
berghofe@26797: lemma pred_equals_eq: "((\<lambda>x. x \<in> R) = (\<lambda>x. x \<in> S)) = (R = S)"
berghofe@26797:   by (simp add: mem_def)
berghofe@22259: 
berghofe@23741: lemma pred_equals_eq2 [pred_set_conv]: "((\<lambda>x y. (x, y) \<in> R) = (\<lambda>x y. (x, y) \<in> S)) = (R = S)"
berghofe@26797:   by (simp add: expand_fun_eq mem_def)
berghofe@22259: 
haftmann@32779: 
haftmann@32779: subsubsection {* Order relation *}
haftmann@32779: 
berghofe@26797: lemma pred_subset_eq: "((\<lambda>x. x \<in> R) <= (\<lambda>x. x \<in> S)) = (R <= S)"
berghofe@26797:   by (simp add: mem_def)
berghofe@22259: 
berghofe@23741: lemma pred_subset_eq2 [pred_set_conv]: "((\<lambda>x y. (x, y) \<in> R) <= (\<lambda>x y. (x, y) \<in> S)) = (R <= S)"
berghofe@22259:   by fast
berghofe@22259: 
berghofe@23741: 
haftmann@30328: subsubsection {* Top and bottom elements *}
berghofe@23741: 
berghofe@23741: lemma top1I [intro!]: "top x"
berghofe@23741:   by (simp add: top_fun_eq top_bool_eq)
berghofe@22259: 
berghofe@23741: lemma top2I [intro!]: "top x y"
berghofe@23741:   by (simp add: top_fun_eq top_bool_eq)
berghofe@23741: 
berghofe@23741: lemma bot1E [elim!]: "bot x \<Longrightarrow> P"
berghofe@23741:   by (simp add: bot_fun_eq bot_bool_eq)
berghofe@23741: 
berghofe@23741: lemma bot2E [elim!]: "bot x y \<Longrightarrow> P"
berghofe@23741:   by (simp add: bot_fun_eq bot_bool_eq)
berghofe@22259: 
berghofe@23741: lemma bot_empty_eq: "bot = (\<lambda>x. x \<in> {})"
berghofe@23741:   by (auto simp add: expand_fun_eq)
berghofe@22259: 
berghofe@23741: lemma bot_empty_eq2: "bot = (\<lambda>x y. (x, y) \<in> {})"
berghofe@23741:   by (auto simp add: expand_fun_eq)
berghofe@22259: 
berghofe@23741: 
haftmann@30328: subsubsection {* Binary union *}
berghofe@22259: 
haftmann@32883: lemma sup1I1 [elim?]: "A x \<Longrightarrow> sup A B x"
haftmann@22422:   by (simp add: sup_fun_eq sup_bool_eq)
berghofe@22259: 
haftmann@32883: lemma sup2I1 [elim?]: "A x y \<Longrightarrow> sup A B x y"
haftmann@32883:   by (simp add: sup_fun_eq sup_bool_eq)
haftmann@32883: 
haftmann@32883: lemma sup1I2 [elim?]: "B x \<Longrightarrow> sup A B x"
haftmann@22422:   by (simp add: sup_fun_eq sup_bool_eq)
berghofe@22259: 
haftmann@32883: lemma sup2I2 [elim?]: "B x y \<Longrightarrow> sup A B x y"
haftmann@32883:   by (simp add: sup_fun_eq sup_bool_eq)
berghofe@22259: 
haftmann@32883: lemma sup1E [elim!]: "sup A B x ==> (A x ==> P) ==> (B x ==> P) ==> P"
haftmann@32883:   by (simp add: sup_fun_eq sup_bool_eq) iprover
berghofe@22259: 
haftmann@32883: lemma sup2E [elim!]: "sup A B x y ==> (A x y ==> P) ==> (B x y ==> P) ==> P"
haftmann@32883:   by (simp add: sup_fun_eq sup_bool_eq) iprover
berghofe@22259: 
berghofe@22259: text {*
berghofe@22259:   \medskip Classical introduction rule: no commitment to @{text A} vs
berghofe@22259:   @{text B}.
berghofe@22259: *}
berghofe@22259: 
haftmann@22422: lemma sup1CI [intro!]: "(~ B x ==> A x) ==> sup A B x"
haftmann@32883:   by (auto simp add: sup_fun_eq sup_bool_eq)
berghofe@22259: 
haftmann@22422: lemma sup2CI [intro!]: "(~ B x y ==> A x y) ==> sup A B x y"
haftmann@32883:   by (auto simp add: sup_fun_eq sup_bool_eq)
berghofe@22259: 
haftmann@32883: lemma sup_Un_eq: "sup (\<lambda>x. x \<in> R) (\<lambda>x. x \<in> S) = (\<lambda>x. x \<in> R \<union> S)"
haftmann@32883:   by (simp add: sup_fun_eq sup_bool_eq mem_def)
berghofe@22259: 
haftmann@32883: lemma sup_Un_eq2 [pred_set_conv]: "sup (\<lambda>x y. (x, y) \<in> R) (\<lambda>x y. (x, y) \<in> S) = (\<lambda>x y. (x, y) \<in> R \<union> S)"
haftmann@32883:   by (simp add: sup_fun_eq sup_bool_eq mem_def)
berghofe@22259: 
berghofe@22259: 
haftmann@30328: subsubsection {* Binary intersection *}
berghofe@22259: 
haftmann@32883: lemma inf1I [intro!]: "A x ==> B x ==> inf A B x"
haftmann@32883:   by (simp add: inf_fun_eq inf_bool_eq)
haftmann@32883: 
haftmann@32883: lemma inf2I [intro!]: "A x y ==> B x y ==> inf A B x y"
haftmann@32883:   by (simp add: inf_fun_eq inf_bool_eq)
haftmann@32883: 
haftmann@32883: lemma inf1E [elim!]: "inf A B x ==> (A x ==> B x ==> P) ==> P"
haftmann@22422:   by (simp add: inf_fun_eq inf_bool_eq)
berghofe@22259: 
haftmann@32883: lemma inf2E [elim!]: "inf A B x y ==> (A x y ==> B x y ==> P) ==> P"
haftmann@32883:   by (simp add: inf_fun_eq inf_bool_eq)
haftmann@32883: 
haftmann@32883: lemma inf1D1: "inf A B x ==> A x"
haftmann@32883:   by (simp add: inf_fun_eq inf_bool_eq)
haftmann@32883: 
haftmann@32883: lemma inf2D1: "inf A B x y ==> A x y"
haftmann@32883:   by (simp add: inf_fun_eq inf_bool_eq)
haftmann@32883: 
haftmann@32883: lemma inf1D2: "inf A B x ==> B x"
haftmann@32883:   by (simp add: inf_fun_eq inf_bool_eq)
haftmann@32883: 
haftmann@32883: lemma inf2D2: "inf A B x y ==> B x y"
haftmann@22422:   by (simp add: inf_fun_eq inf_bool_eq)
berghofe@22259: 
haftmann@32703: lemma inf_Int_eq: "inf (\<lambda>x. x \<in> R) (\<lambda>x. x \<in> S) = (\<lambda>x. x \<in> R \<inter> S)"
haftmann@32883:   by (simp add: inf_fun_eq inf_bool_eq mem_def)
berghofe@23741: 
berghofe@23741: lemma inf_Int_eq2 [pred_set_conv]: "inf (\<lambda>x y. (x, y) \<in> R) (\<lambda>x y. (x, y) \<in> S) = (\<lambda>x y. (x, y) \<in> R \<inter> S)"
haftmann@32883:   by (simp add: inf_fun_eq inf_bool_eq mem_def)
berghofe@22259: 
berghofe@22259: 
haftmann@30328: subsubsection {* Unions of families *}
berghofe@22259: 
haftmann@32601: lemma SUP1_iff: "(SUP x:A. B x) b = (EX x:A. B x b)"
haftmann@24345:   by (simp add: SUPR_def Sup_fun_def Sup_bool_def) blast
berghofe@22430: 
haftmann@32601: lemma SUP2_iff: "(SUP x:A. B x) b c = (EX x:A. B x b c)"
haftmann@24345:   by (simp add: SUPR_def Sup_fun_def Sup_bool_def) blast
berghofe@22259: 
berghofe@22430: lemma SUP1_I [intro]: "a : A ==> B a b ==> (SUP x:A. B x) b"
haftmann@32601:   by (auto simp add: SUP1_iff)
berghofe@22259: 
berghofe@22430: lemma SUP2_I [intro]: "a : A ==> B a b c ==> (SUP x:A. B x) b c"
haftmann@32601:   by (auto simp add: SUP2_iff)
berghofe@22430: 
berghofe@22430: lemma SUP1_E [elim!]: "(SUP x:A. B x) b ==> (!!x. x : A ==> B x b ==> R) ==> R"
haftmann@32601:   by (auto simp add: SUP1_iff)
berghofe@22430: 
berghofe@22430: lemma SUP2_E [elim!]: "(SUP x:A. B x) b c ==> (!!x. x : A ==> B x b c ==> R) ==> R"
haftmann@32601:   by (auto simp add: SUP2_iff)
berghofe@22259: 
berghofe@23741: lemma SUP_UN_eq: "(SUP i. (\<lambda>x. x \<in> r i)) = (\<lambda>x. x \<in> (UN i. r i))"
haftmann@32601:   by (simp add: SUP1_iff expand_fun_eq)
berghofe@22430: 
berghofe@23741: lemma SUP_UN_eq2: "(SUP i. (\<lambda>x y. (x, y) \<in> r i)) = (\<lambda>x y. (x, y) \<in> (UN i. r i))"
haftmann@32601:   by (simp add: SUP2_iff expand_fun_eq)
berghofe@22430: 
berghofe@23741: 
haftmann@30328: subsubsection {* Intersections of families *}
berghofe@22430: 
haftmann@32601: lemma INF1_iff: "(INF x:A. B x) b = (ALL x:A. B x b)"
berghofe@22430:   by (simp add: INFI_def Inf_fun_def Inf_bool_def) blast
berghofe@22430: 
haftmann@32601: lemma INF2_iff: "(INF x:A. B x) b c = (ALL x:A. B x b c)"
berghofe@22430:   by (simp add: INFI_def Inf_fun_def Inf_bool_def) blast
berghofe@22430: 
berghofe@22430: lemma INF1_I [intro!]: "(!!x. x : A ==> B x b) ==> (INF x:A. B x) b"
haftmann@32601:   by (auto simp add: INF1_iff)
berghofe@22259: 
berghofe@22430: lemma INF2_I [intro!]: "(!!x. x : A ==> B x b c) ==> (INF x:A. B x) b c"
haftmann@32601:   by (auto simp add: INF2_iff)
berghofe@22430: 
berghofe@22430: lemma INF1_D [elim]: "(INF x:A. B x) b ==> a : A ==> B a b"
haftmann@32601:   by (auto simp add: INF1_iff)
berghofe@22259: 
berghofe@22430: lemma INF2_D [elim]: "(INF x:A. B x) b c ==> a : A ==> B a b c"
haftmann@32601:   by (auto simp add: INF2_iff)
berghofe@22430: 
berghofe@22430: lemma INF1_E [elim]: "(INF x:A. B x) b ==> (B a b ==> R) ==> (a ~: A ==> R) ==> R"
haftmann@32601:   by (auto simp add: INF1_iff)
berghofe@22430: 
berghofe@22430: lemma INF2_E [elim]: "(INF x:A. B x) b c ==> (B a b c ==> R) ==> (a ~: A ==> R) ==> R"
haftmann@32601:   by (auto simp add: INF2_iff)
berghofe@22259: 
berghofe@23741: lemma INF_INT_eq: "(INF i. (\<lambda>x. x \<in> r i)) = (\<lambda>x. x \<in> (INT i. r i))"
haftmann@32601:   by (simp add: INF1_iff expand_fun_eq)
berghofe@23741: 
berghofe@23741: lemma INF_INT_eq2: "(INF i. (\<lambda>x y. (x, y) \<in> r i)) = (\<lambda>x y. (x, y) \<in> (INT i. r i))"
haftmann@32601:   by (simp add: INF2_iff expand_fun_eq)
berghofe@23741: 
berghofe@22259: 
haftmann@30328: subsection {* Predicates as relations *}
haftmann@30328: 
haftmann@30328: subsubsection {* Composition  *}
berghofe@22259: 
berghofe@23741: inductive
krauss@32235:   pred_comp  :: "['a => 'b => bool, 'b => 'c => bool] => 'a => 'c => bool"
berghofe@22259:     (infixr "OO" 75)
krauss@32235:   for r :: "'a => 'b => bool" and s :: "'b => 'c => bool"
berghofe@22259: where
krauss@32235:   pred_compI [intro]: "r a b ==> s b c ==> (r OO s) a c"
berghofe@22259: 
berghofe@23741: inductive_cases pred_compE [elim!]: "(r OO s) a c"
berghofe@22259: 
berghofe@22259: lemma pred_comp_rel_comp_eq [pred_set_conv]:
berghofe@23741:   "((\<lambda>x y. (x, y) \<in> r) OO (\<lambda>x y. (x, y) \<in> s)) = (\<lambda>x y. (x, y) \<in> r O s)"
berghofe@22259:   by (auto simp add: expand_fun_eq elim: pred_compE)
berghofe@22259: 
berghofe@22259: 
haftmann@30328: subsubsection {* Converse *}
berghofe@22259: 
berghofe@23741: inductive
berghofe@22259:   conversep :: "('a => 'b => bool) => 'b => 'a => bool"
berghofe@22259:     ("(_^--1)" [1000] 1000)
berghofe@22259:   for r :: "'a => 'b => bool"
berghofe@22259: where
berghofe@22259:   conversepI: "r a b ==> r^--1 b a"
berghofe@22259: 
berghofe@22259: notation (xsymbols)
berghofe@22259:   conversep  ("(_\<inverse>\<inverse>)" [1000] 1000)
berghofe@22259: 
berghofe@22259: lemma conversepD:
berghofe@22259:   assumes ab: "r^--1 a b"
berghofe@22259:   shows "r b a" using ab
berghofe@22259:   by cases simp
berghofe@22259: 
berghofe@22259: lemma conversep_iff [iff]: "r^--1 a b = r b a"
berghofe@22259:   by (iprover intro: conversepI dest: conversepD)
berghofe@22259: 
berghofe@22259: lemma conversep_converse_eq [pred_set_conv]:
berghofe@23741:   "(\<lambda>x y. (x, y) \<in> r)^--1 = (\<lambda>x y. (x, y) \<in> r^-1)"
berghofe@22259:   by (auto simp add: expand_fun_eq)
berghofe@22259: 
berghofe@22259: lemma conversep_conversep [simp]: "(r^--1)^--1 = r"
berghofe@22259:   by (iprover intro: order_antisym conversepI dest: conversepD)
berghofe@22259: 
berghofe@22259: lemma converse_pred_comp: "(r OO s)^--1 = s^--1 OO r^--1"
berghofe@22259:   by (iprover intro: order_antisym conversepI pred_compI
berghofe@22259:     elim: pred_compE dest: conversepD)
berghofe@22259: 
haftmann@22422: lemma converse_meet: "(inf r s)^--1 = inf r^--1 s^--1"
haftmann@22422:   by (simp add: inf_fun_eq inf_bool_eq)
berghofe@22259:     (iprover intro: conversepI ext dest: conversepD)
berghofe@22259: 
haftmann@22422: lemma converse_join: "(sup r s)^--1 = sup r^--1 s^--1"
haftmann@22422:   by (simp add: sup_fun_eq sup_bool_eq)
berghofe@22259:     (iprover intro: conversepI ext dest: conversepD)
berghofe@22259: 
berghofe@22259: lemma conversep_noteq [simp]: "(op ~=)^--1 = op ~="
berghofe@22259:   by (auto simp add: expand_fun_eq)
berghofe@22259: 
berghofe@22259: lemma conversep_eq [simp]: "(op =)^--1 = op ="
berghofe@22259:   by (auto simp add: expand_fun_eq)
berghofe@22259: 
berghofe@22259: 
haftmann@30328: subsubsection {* Domain *}
berghofe@22259: 
berghofe@23741: inductive
berghofe@22259:   DomainP :: "('a => 'b => bool) => 'a => bool"
berghofe@22259:   for r :: "'a => 'b => bool"
berghofe@22259: where
berghofe@22259:   DomainPI [intro]: "r a b ==> DomainP r a"
berghofe@22259: 
berghofe@23741: inductive_cases DomainPE [elim!]: "DomainP r a"
berghofe@22259: 
berghofe@23741: lemma DomainP_Domain_eq [pred_set_conv]: "DomainP (\<lambda>x y. (x, y) \<in> r) = (\<lambda>x. x \<in> Domain r)"
berghofe@26797:   by (blast intro!: Orderings.order_antisym predicate1I)
berghofe@22259: 
berghofe@22259: 
haftmann@30328: subsubsection {* Range *}
berghofe@22259: 
berghofe@23741: inductive
berghofe@22259:   RangeP :: "('a => 'b => bool) => 'b => bool"
berghofe@22259:   for r :: "'a => 'b => bool"
berghofe@22259: where
berghofe@22259:   RangePI [intro]: "r a b ==> RangeP r b"
berghofe@22259: 
berghofe@23741: inductive_cases RangePE [elim!]: "RangeP r b"
berghofe@22259: 
berghofe@23741: lemma RangeP_Range_eq [pred_set_conv]: "RangeP (\<lambda>x y. (x, y) \<in> r) = (\<lambda>x. x \<in> Range r)"
berghofe@26797:   by (blast intro!: Orderings.order_antisym predicate1I)
berghofe@22259: 
berghofe@22259: 
haftmann@30328: subsubsection {* Inverse image *}
berghofe@22259: 
berghofe@22259: definition
berghofe@22259:   inv_imagep :: "('b => 'b => bool) => ('a => 'b) => 'a => 'a => bool" where
berghofe@22259:   "inv_imagep r f == %x y. r (f x) (f y)"
berghofe@22259: 
berghofe@23741: lemma [pred_set_conv]: "inv_imagep (\<lambda>x y. (x, y) \<in> r) f = (\<lambda>x y. (x, y) \<in> inv_image r f)"
berghofe@22259:   by (simp add: inv_image_def inv_imagep_def)
berghofe@22259: 
berghofe@22259: lemma in_inv_imagep [simp]: "inv_imagep r f x y = r (f x) (f y)"
berghofe@22259:   by (simp add: inv_imagep_def)
berghofe@22259: 
berghofe@22259: 
haftmann@30328: subsubsection {* Powerset *}
berghofe@23741: 
berghofe@23741: definition Powp :: "('a \<Rightarrow> bool) \<Rightarrow> 'a set \<Rightarrow> bool" where
berghofe@23741:   "Powp A == \<lambda>B. \<forall>x \<in> B. A x"
berghofe@23741: 
berghofe@23741: lemma Powp_Pow_eq [pred_set_conv]: "Powp (\<lambda>x. x \<in> A) = (\<lambda>x. x \<in> Pow A)"
berghofe@23741:   by (auto simp add: Powp_def expand_fun_eq)
berghofe@23741: 
berghofe@26797: lemmas Powp_mono [mono] = Pow_mono [to_pred pred_subset_eq]
berghofe@26797: 
berghofe@23741: 
haftmann@30328: subsubsection {* Properties of relations *}
berghofe@22259: 
berghofe@22259: abbreviation antisymP :: "('a => 'a => bool) => bool" where
berghofe@23741:   "antisymP r == antisym {(x, y). r x y}"
berghofe@22259: 
berghofe@22259: abbreviation transP :: "('a => 'a => bool) => bool" where
berghofe@23741:   "transP r == trans {(x, y). r x y}"
berghofe@22259: 
berghofe@22259: abbreviation single_valuedP :: "('a => 'b => bool) => bool" where
berghofe@23741:   "single_valuedP r == single_valued {(x, y). r x y}"
berghofe@22259: 
haftmann@30328: 
haftmann@30328: subsection {* Predicates as enumerations *}
haftmann@30328: 
haftmann@30328: subsubsection {* The type of predicate enumerations (a monad) *}
haftmann@30328: 
haftmann@30328: datatype 'a pred = Pred "'a \<Rightarrow> bool"
haftmann@30328: 
haftmann@30328: primrec eval :: "'a pred \<Rightarrow> 'a \<Rightarrow> bool" where
haftmann@30328:   eval_pred: "eval (Pred f) = f"
haftmann@30328: 
haftmann@30328: lemma Pred_eval [simp]:
haftmann@30328:   "Pred (eval x) = x"
haftmann@30328:   by (cases x) simp
haftmann@30328: 
haftmann@30328: lemma eval_inject: "eval x = eval y \<longleftrightarrow> x = y"
haftmann@30328:   by (cases x) auto
haftmann@30328: 
haftmann@30328: definition single :: "'a \<Rightarrow> 'a pred" where
haftmann@30328:   "single x = Pred ((op =) x)"
haftmann@30328: 
haftmann@30328: definition bind :: "'a pred \<Rightarrow> ('a \<Rightarrow> 'b pred) \<Rightarrow> 'b pred" (infixl "\<guillemotright>=" 70) where
haftmann@30328:   "P \<guillemotright>= f = Pred (\<lambda>x. (\<exists>y. eval P y \<and> eval (f y) x))"
haftmann@30328: 
haftmann@32578: instantiation pred :: (type) "{complete_lattice, boolean_algebra}"
haftmann@30328: begin
haftmann@30328: 
haftmann@30328: definition
haftmann@30328:   "P \<le> Q \<longleftrightarrow> eval P \<le> eval Q"
haftmann@30328: 
haftmann@30328: definition
haftmann@30328:   "P < Q \<longleftrightarrow> eval P < eval Q"
haftmann@30328: 
haftmann@30328: definition
haftmann@30328:   "\<bottom> = Pred \<bottom>"
haftmann@30328: 
haftmann@30328: definition
haftmann@30328:   "\<top> = Pred \<top>"
haftmann@30328: 
haftmann@30328: definition
haftmann@30328:   "P \<sqinter> Q = Pred (eval P \<sqinter> eval Q)"
haftmann@30328: 
haftmann@30328: definition
haftmann@30328:   "P \<squnion> Q = Pred (eval P \<squnion> eval Q)"
haftmann@30328: 
haftmann@30328: definition
haftmann@31932:   [code del]: "\<Sqinter>A = Pred (INFI A eval)"
haftmann@30328: 
haftmann@30328: definition
haftmann@31932:   [code del]: "\<Squnion>A = Pred (SUPR A eval)"
haftmann@30328: 
haftmann@32578: definition
haftmann@32578:   "- P = Pred (- eval P)"
haftmann@32578: 
haftmann@32578: definition
haftmann@32578:   "P - Q = Pred (eval P - eval Q)"
haftmann@32578: 
haftmann@32578: instance proof
haftmann@32578: qed (auto simp add: less_eq_pred_def less_pred_def
haftmann@30328:     inf_pred_def sup_pred_def bot_pred_def top_pred_def
haftmann@32578:     Inf_pred_def Sup_pred_def uminus_pred_def minus_pred_def fun_Compl_def bool_Compl_def,
haftmann@30328:     auto simp add: le_fun_def less_fun_def le_bool_def less_bool_def
haftmann@30328:     eval_inject mem_def)
haftmann@30328: 
berghofe@22259: end
haftmann@30328: 
haftmann@30328: lemma bind_bind:
haftmann@30328:   "(P \<guillemotright>= Q) \<guillemotright>= R = P \<guillemotright>= (\<lambda>x. Q x \<guillemotright>= R)"
haftmann@30328:   by (auto simp add: bind_def expand_fun_eq)
haftmann@30328: 
haftmann@30328: lemma bind_single:
haftmann@30328:   "P \<guillemotright>= single = P"
haftmann@30328:   by (simp add: bind_def single_def)
haftmann@30328: 
haftmann@30328: lemma single_bind:
haftmann@30328:   "single x \<guillemotright>= P = P x"
haftmann@30328:   by (simp add: bind_def single_def)
haftmann@30328: 
haftmann@30328: lemma bottom_bind:
haftmann@30328:   "\<bottom> \<guillemotright>= P = \<bottom>"
haftmann@30328:   by (auto simp add: bot_pred_def bind_def expand_fun_eq)
haftmann@30328: 
haftmann@30328: lemma sup_bind:
haftmann@30328:   "(P \<squnion> Q) \<guillemotright>= R = P \<guillemotright>= R \<squnion> Q \<guillemotright>= R"
haftmann@30328:   by (auto simp add: bind_def sup_pred_def expand_fun_eq)
haftmann@30328: 
haftmann@30328: lemma Sup_bind: "(\<Squnion>A \<guillemotright>= f) = \<Squnion>((\<lambda>x. x \<guillemotright>= f) ` A)"
haftmann@32601:   by (auto simp add: bind_def Sup_pred_def SUP1_iff expand_fun_eq)
haftmann@30328: 
haftmann@30328: lemma pred_iffI:
haftmann@30328:   assumes "\<And>x. eval A x \<Longrightarrow> eval B x"
haftmann@30328:   and "\<And>x. eval B x \<Longrightarrow> eval A x"
haftmann@30328:   shows "A = B"
haftmann@30328: proof -
haftmann@30328:   from assms have "\<And>x. eval A x \<longleftrightarrow> eval B x" by blast
haftmann@30328:   then show ?thesis by (cases A, cases B) (simp add: expand_fun_eq)
haftmann@30328: qed
haftmann@30328:   
haftmann@30328: lemma singleI: "eval (single x) x"
haftmann@30328:   unfolding single_def by simp
haftmann@30328: 
haftmann@30328: lemma singleI_unit: "eval (single ()) x"
haftmann@30328:   by simp (rule singleI)
haftmann@30328: 
haftmann@30328: lemma singleE: "eval (single x) y \<Longrightarrow> (y = x \<Longrightarrow> P) \<Longrightarrow> P"
haftmann@30328:   unfolding single_def by simp
haftmann@30328: 
haftmann@30328: lemma singleE': "eval (single x) y \<Longrightarrow> (x = y \<Longrightarrow> P) \<Longrightarrow> P"
haftmann@30328:   by (erule singleE) simp
haftmann@30328: 
haftmann@30328: lemma bindI: "eval P x \<Longrightarrow> eval (Q x) y \<Longrightarrow> eval (P \<guillemotright>= Q) y"
haftmann@30328:   unfolding bind_def by auto
haftmann@30328: 
haftmann@30328: lemma bindE: "eval (R \<guillemotright>= Q) y \<Longrightarrow> (\<And>x. eval R x \<Longrightarrow> eval (Q x) y \<Longrightarrow> P) \<Longrightarrow> P"
haftmann@30328:   unfolding bind_def by auto
haftmann@30328: 
haftmann@30328: lemma botE: "eval \<bottom> x \<Longrightarrow> P"
haftmann@30328:   unfolding bot_pred_def by auto
haftmann@30328: 
haftmann@30328: lemma supI1: "eval A x \<Longrightarrow> eval (A \<squnion> B) x"
haftmann@32883:   unfolding sup_pred_def by (simp add: sup_fun_eq sup_bool_eq)
haftmann@30328: 
haftmann@30328: lemma supI2: "eval B x \<Longrightarrow> eval (A \<squnion> B) x" 
haftmann@32883:   unfolding sup_pred_def by (simp add: sup_fun_eq sup_bool_eq)
haftmann@30328: 
haftmann@30328: lemma supE: "eval (A \<squnion> B) x \<Longrightarrow> (eval A x \<Longrightarrow> P) \<Longrightarrow> (eval B x \<Longrightarrow> P) \<Longrightarrow> P"
haftmann@30328:   unfolding sup_pred_def by auto
haftmann@30328: 
haftmann@32578: lemma single_not_bot [simp]:
haftmann@32578:   "single x \<noteq> \<bottom>"
haftmann@32578:   by (auto simp add: single_def bot_pred_def expand_fun_eq)
haftmann@32578: 
haftmann@32578: lemma not_bot:
haftmann@32578:   assumes "A \<noteq> \<bottom>"
haftmann@32578:   obtains x where "eval A x"
haftmann@32578: using assms by (cases A)
haftmann@32578:   (auto simp add: bot_pred_def, auto simp add: mem_def)
haftmann@32578:   
haftmann@32578: 
haftmann@32578: subsubsection {* Emptiness check and definite choice *}
haftmann@32578: 
haftmann@32578: definition is_empty :: "'a pred \<Rightarrow> bool" where
haftmann@32578:   "is_empty A \<longleftrightarrow> A = \<bottom>"
haftmann@32578: 
haftmann@32578: lemma is_empty_bot:
haftmann@32578:   "is_empty \<bottom>"
haftmann@32578:   by (simp add: is_empty_def)
haftmann@32578: 
haftmann@32578: lemma not_is_empty_single:
haftmann@32578:   "\<not> is_empty (single x)"
haftmann@32578:   by (auto simp add: is_empty_def single_def bot_pred_def expand_fun_eq)
haftmann@32578: 
haftmann@32578: lemma is_empty_sup:
haftmann@32578:   "is_empty (A \<squnion> B) \<longleftrightarrow> is_empty A \<and> is_empty B"
haftmann@32578:   by (auto simp add: is_empty_def intro: sup_eq_bot_eq1 sup_eq_bot_eq2)
haftmann@32578: 
bulwahn@33111: definition singleton :: "(unit => 'a) \<Rightarrow> 'a pred \<Rightarrow> 'a" where
bulwahn@33111:   "singleton dfault A = (if \<exists>!x. eval A x then THE x. eval A x else dfault ())"
haftmann@32578: 
haftmann@32578: lemma singleton_eqI:
bulwahn@33110:   "\<exists>!x. eval A x \<Longrightarrow> eval A x \<Longrightarrow> singleton dfault A = x"
haftmann@32578:   by (auto simp add: singleton_def)
haftmann@32578: 
haftmann@32578: lemma eval_singletonI:
bulwahn@33110:   "\<exists>!x. eval A x \<Longrightarrow> eval A (singleton dfault A)"
haftmann@32578: proof -
haftmann@32578:   assume assm: "\<exists>!x. eval A x"
haftmann@32578:   then obtain x where "eval A x" ..
bulwahn@33110:   moreover with assm have "singleton dfault A = x" by (rule singleton_eqI)
haftmann@32578:   ultimately show ?thesis by simp 
haftmann@32578: qed
haftmann@32578: 
haftmann@32578: lemma single_singleton:
bulwahn@33110:   "\<exists>!x. eval A x \<Longrightarrow> single (singleton dfault A) = A"
haftmann@32578: proof -
haftmann@32578:   assume assm: "\<exists>!x. eval A x"
bulwahn@33110:   then have "eval A (singleton dfault A)"
haftmann@32578:     by (rule eval_singletonI)
bulwahn@33110:   moreover from assm have "\<And>x. eval A x \<Longrightarrow> singleton dfault A = x"
haftmann@32578:     by (rule singleton_eqI)
bulwahn@33110:   ultimately have "eval (single (singleton dfault A)) = eval A"
haftmann@32578:     by (simp (no_asm_use) add: single_def expand_fun_eq) blast
haftmann@32578:   then show ?thesis by (simp add: eval_inject)
haftmann@32578: qed
haftmann@32578: 
haftmann@32578: lemma singleton_undefinedI:
bulwahn@33111:   "\<not> (\<exists>!x. eval A x) \<Longrightarrow> singleton dfault A = dfault ()"
haftmann@32578:   by (simp add: singleton_def)
haftmann@32578: 
haftmann@32578: lemma singleton_bot:
bulwahn@33111:   "singleton dfault \<bottom> = dfault ()"
haftmann@32578:   by (auto simp add: bot_pred_def intro: singleton_undefinedI)
haftmann@32578: 
haftmann@32578: lemma singleton_single:
bulwahn@33110:   "singleton dfault (single x) = x"
haftmann@32578:   by (auto simp add: intro: singleton_eqI singleI elim: singleE)
haftmann@32578: 
haftmann@32578: lemma singleton_sup_single_single:
bulwahn@33111:   "singleton dfault (single x \<squnion> single y) = (if x = y then x else dfault ())"
haftmann@32578: proof (cases "x = y")
haftmann@32578:   case True then show ?thesis by (simp add: singleton_single)
haftmann@32578: next
haftmann@32578:   case False
haftmann@32578:   have "eval (single x \<squnion> single y) x"
haftmann@32578:     and "eval (single x \<squnion> single y) y"
haftmann@32578:   by (auto intro: supI1 supI2 singleI)
haftmann@32578:   with False have "\<not> (\<exists>!z. eval (single x \<squnion> single y) z)"
haftmann@32578:     by blast
bulwahn@33111:   then have "singleton dfault (single x \<squnion> single y) = dfault ()"
haftmann@32578:     by (rule singleton_undefinedI)
haftmann@32578:   with False show ?thesis by simp
haftmann@32578: qed
haftmann@32578: 
haftmann@32578: lemma singleton_sup_aux:
bulwahn@33110:   "singleton dfault (A \<squnion> B) = (if A = \<bottom> then singleton dfault B
bulwahn@33110:     else if B = \<bottom> then singleton dfault A
bulwahn@33110:     else singleton dfault
bulwahn@33110:       (single (singleton dfault A) \<squnion> single (singleton dfault B)))"
haftmann@32578: proof (cases "(\<exists>!x. eval A x) \<and> (\<exists>!y. eval B y)")
haftmann@32578:   case True then show ?thesis by (simp add: single_singleton)
haftmann@32578: next
haftmann@32578:   case False
haftmann@32578:   from False have A_or_B:
bulwahn@33111:     "singleton dfault A = dfault () \<or> singleton dfault B = dfault ()"
haftmann@32578:     by (auto intro!: singleton_undefinedI)
bulwahn@33110:   then have rhs: "singleton dfault
bulwahn@33111:     (single (singleton dfault A) \<squnion> single (singleton dfault B)) = dfault ()"
haftmann@32578:     by (auto simp add: singleton_sup_single_single singleton_single)
haftmann@32578:   from False have not_unique:
haftmann@32578:     "\<not> (\<exists>!x. eval A x) \<or> \<not> (\<exists>!y. eval B y)" by simp
haftmann@32578:   show ?thesis proof (cases "A \<noteq> \<bottom> \<and> B \<noteq> \<bottom>")
haftmann@32578:     case True
haftmann@32578:     then obtain a b where a: "eval A a" and b: "eval B b"
haftmann@32578:       by (blast elim: not_bot)
haftmann@32578:     with True not_unique have "\<not> (\<exists>!x. eval (A \<squnion> B) x)"
haftmann@32578:       by (auto simp add: sup_pred_def bot_pred_def)
bulwahn@33111:     then have "singleton dfault (A \<squnion> B) = dfault ()" by (rule singleton_undefinedI)
haftmann@32578:     with True rhs show ?thesis by simp
haftmann@32578:   next
haftmann@32578:     case False then show ?thesis by auto
haftmann@32578:   qed
haftmann@32578: qed
haftmann@32578: 
haftmann@32578: lemma singleton_sup:
bulwahn@33110:   "singleton dfault (A \<squnion> B) = (if A = \<bottom> then singleton dfault B
bulwahn@33110:     else if B = \<bottom> then singleton dfault A
bulwahn@33111:     else if singleton dfault A = singleton dfault B then singleton dfault A else dfault ())"
bulwahn@33110: using singleton_sup_aux [of dfault A B] by (simp only: singleton_sup_single_single)
haftmann@32578: 
haftmann@30328: 
haftmann@30328: subsubsection {* Derived operations *}
haftmann@30328: 
haftmann@30328: definition if_pred :: "bool \<Rightarrow> unit pred" where
haftmann@30328:   if_pred_eq: "if_pred b = (if b then single () else \<bottom>)"
haftmann@30328: 
bulwahn@33754: definition holds :: "unit pred \<Rightarrow> bool" where
bulwahn@33754:   holds_eq: "holds P = eval P ()"
bulwahn@33754: 
haftmann@30328: definition not_pred :: "unit pred \<Rightarrow> unit pred" where
haftmann@30328:   not_pred_eq: "not_pred P = (if eval P () then \<bottom> else single ())"
haftmann@30328: 
haftmann@30328: lemma if_predI: "P \<Longrightarrow> eval (if_pred P) ()"
haftmann@30328:   unfolding if_pred_eq by (auto intro: singleI)
haftmann@30328: 
haftmann@30328: lemma if_predE: "eval (if_pred b) x \<Longrightarrow> (b \<Longrightarrow> x = () \<Longrightarrow> P) \<Longrightarrow> P"
haftmann@30328:   unfolding if_pred_eq by (cases b) (auto elim: botE)
haftmann@30328: 
haftmann@30328: lemma not_predI: "\<not> P \<Longrightarrow> eval (not_pred (Pred (\<lambda>u. P))) ()"
haftmann@30328:   unfolding not_pred_eq eval_pred by (auto intro: singleI)
haftmann@30328: 
haftmann@30328: lemma not_predI': "\<not> eval P () \<Longrightarrow> eval (not_pred P) ()"
haftmann@30328:   unfolding not_pred_eq by (auto intro: singleI)
haftmann@30328: 
haftmann@30328: lemma not_predE: "eval (not_pred (Pred (\<lambda>u. P))) x \<Longrightarrow> (\<not> P \<Longrightarrow> thesis) \<Longrightarrow> thesis"
haftmann@30328:   unfolding not_pred_eq
haftmann@30328:   by (auto split: split_if_asm elim: botE)
haftmann@30328: 
haftmann@30328: lemma not_predE': "eval (not_pred P) x \<Longrightarrow> (\<not> eval P x \<Longrightarrow> thesis) \<Longrightarrow> thesis"
haftmann@30328:   unfolding not_pred_eq
haftmann@30328:   by (auto split: split_if_asm elim: botE)
bulwahn@33754: lemma "f () = False \<or> f () = True"
bulwahn@33754: by simp
haftmann@30328: 
bulwahn@33754: lemma closure_of_bool_cases:
bulwahn@33754: assumes "(f :: unit \<Rightarrow> bool) = (%u. False) \<Longrightarrow> P f"
bulwahn@33754: assumes "f = (%u. True) \<Longrightarrow> P f"
bulwahn@33754: shows "P f"
bulwahn@33754: proof -
bulwahn@33754:   have "f = (%u. False) \<or> f = (%u. True)"
bulwahn@33754:     apply (cases "f ()")
bulwahn@33754:     apply (rule disjI2)
bulwahn@33754:     apply (rule ext)
bulwahn@33754:     apply (simp add: unit_eq)
bulwahn@33754:     apply (rule disjI1)
bulwahn@33754:     apply (rule ext)
bulwahn@33754:     apply (simp add: unit_eq)
bulwahn@33754:     done
bulwahn@33754:   from this prems show ?thesis by blast
bulwahn@33754: qed
bulwahn@33754: 
bulwahn@33754: lemma unit_pred_cases:
bulwahn@33754: assumes "P \<bottom>"
bulwahn@33754: assumes "P (single ())"
bulwahn@33754: shows "P Q"
bulwahn@33754: using assms
bulwahn@33754: unfolding bot_pred_def Collect_def empty_def single_def
bulwahn@33754: apply (cases Q)
bulwahn@33754: apply simp
bulwahn@33754: apply (rule_tac f="fun" in closure_of_bool_cases)
bulwahn@33754: apply auto
bulwahn@33754: apply (subgoal_tac "(%x. () = x) = (%x. True)") 
bulwahn@33754: apply auto
bulwahn@33754: done
bulwahn@33754: 
bulwahn@33754: lemma holds_if_pred:
bulwahn@33754:   "holds (if_pred b) = b"
bulwahn@33754: unfolding if_pred_eq holds_eq
bulwahn@33754: by (cases b) (auto intro: singleI elim: botE)
bulwahn@33754: 
bulwahn@33754: lemma if_pred_holds:
bulwahn@33754:   "if_pred (holds P) = P"
bulwahn@33754: unfolding if_pred_eq holds_eq
bulwahn@33754: by (rule unit_pred_cases) (auto intro: singleI elim: botE)
bulwahn@33754: 
bulwahn@33754: lemma is_empty_holds:
bulwahn@33754:   "is_empty P \<longleftrightarrow> \<not> holds P"
bulwahn@33754: unfolding is_empty_def holds_eq
bulwahn@33754: by (rule unit_pred_cases) (auto elim: botE intro: singleI)
haftmann@30328: 
haftmann@30328: subsubsection {* Implementation *}
haftmann@30328: 
haftmann@30328: datatype 'a seq = Empty | Insert "'a" "'a pred" | Join "'a pred" "'a seq"
haftmann@30328: 
haftmann@30328: primrec pred_of_seq :: "'a seq \<Rightarrow> 'a pred" where
haftmann@30328:     "pred_of_seq Empty = \<bottom>"
haftmann@30328:   | "pred_of_seq (Insert x P) = single x \<squnion> P"
haftmann@30328:   | "pred_of_seq (Join P xq) = P \<squnion> pred_of_seq xq"
haftmann@30328: 
haftmann@30328: definition Seq :: "(unit \<Rightarrow> 'a seq) \<Rightarrow> 'a pred" where
haftmann@30328:   "Seq f = pred_of_seq (f ())"
haftmann@30328: 
haftmann@30328: code_datatype Seq
haftmann@30328: 
haftmann@30328: primrec member :: "'a seq \<Rightarrow> 'a \<Rightarrow> bool"  where
haftmann@30328:   "member Empty x \<longleftrightarrow> False"
haftmann@30328:   | "member (Insert y P) x \<longleftrightarrow> x = y \<or> eval P x"
haftmann@30328:   | "member (Join P xq) x \<longleftrightarrow> eval P x \<or> member xq x"
haftmann@30328: 
haftmann@30328: lemma eval_member:
haftmann@30328:   "member xq = eval (pred_of_seq xq)"
haftmann@30328: proof (induct xq)
haftmann@30328:   case Empty show ?case
haftmann@30328:   by (auto simp add: expand_fun_eq elim: botE)
haftmann@30328: next
haftmann@30328:   case Insert show ?case
haftmann@30328:   by (auto simp add: expand_fun_eq elim: supE singleE intro: supI1 supI2 singleI)
haftmann@30328: next
haftmann@30328:   case Join then show ?case
haftmann@30328:   by (auto simp add: expand_fun_eq elim: supE intro: supI1 supI2)
haftmann@30328: qed
haftmann@30328: 
haftmann@30328: lemma eval_code [code]: "eval (Seq f) = member (f ())"
haftmann@30328:   unfolding Seq_def by (rule sym, rule eval_member)
haftmann@30328: 
haftmann@30328: lemma single_code [code]:
haftmann@30328:   "single x = Seq (\<lambda>u. Insert x \<bottom>)"
haftmann@30328:   unfolding Seq_def by simp
haftmann@30328: 
haftmann@30328: primrec "apply" :: "('a \<Rightarrow> 'b Predicate.pred) \<Rightarrow> 'a seq \<Rightarrow> 'b seq" where
haftmann@30328:     "apply f Empty = Empty"
haftmann@30328:   | "apply f (Insert x P) = Join (f x) (Join (P \<guillemotright>= f) Empty)"
haftmann@30328:   | "apply f (Join P xq) = Join (P \<guillemotright>= f) (apply f xq)"
haftmann@30328: 
haftmann@30328: lemma apply_bind:
haftmann@30328:   "pred_of_seq (apply f xq) = pred_of_seq xq \<guillemotright>= f"
haftmann@30328: proof (induct xq)
haftmann@30328:   case Empty show ?case
haftmann@30328:     by (simp add: bottom_bind)
haftmann@30328: next
haftmann@30328:   case Insert show ?case
haftmann@30328:     by (simp add: single_bind sup_bind)
haftmann@30328: next
haftmann@30328:   case Join then show ?case
haftmann@30328:     by (simp add: sup_bind)
haftmann@30328: qed
haftmann@30328:   
haftmann@30328: lemma bind_code [code]:
haftmann@30328:   "Seq g \<guillemotright>= f = Seq (\<lambda>u. apply f (g ()))"
haftmann@30328:   unfolding Seq_def by (rule sym, rule apply_bind)
haftmann@30328: 
haftmann@30328: lemma bot_set_code [code]:
haftmann@30328:   "\<bottom> = Seq (\<lambda>u. Empty)"
haftmann@30328:   unfolding Seq_def by simp
haftmann@30328: 
haftmann@30376: primrec adjunct :: "'a pred \<Rightarrow> 'a seq \<Rightarrow> 'a seq" where
haftmann@30376:     "adjunct P Empty = Join P Empty"
haftmann@30376:   | "adjunct P (Insert x Q) = Insert x (Q \<squnion> P)"
haftmann@30376:   | "adjunct P (Join Q xq) = Join Q (adjunct P xq)"
haftmann@30376: 
haftmann@30376: lemma adjunct_sup:
haftmann@30376:   "pred_of_seq (adjunct P xq) = P \<squnion> pred_of_seq xq"
haftmann@30376:   by (induct xq) (simp_all add: sup_assoc sup_commute sup_left_commute)
haftmann@30376: 
haftmann@30328: lemma sup_code [code]:
haftmann@30328:   "Seq f \<squnion> Seq g = Seq (\<lambda>u. case f ()
haftmann@30328:     of Empty \<Rightarrow> g ()
haftmann@30328:      | Insert x P \<Rightarrow> Insert x (P \<squnion> Seq g)
haftmann@30376:      | Join P xq \<Rightarrow> adjunct (Seq g) (Join P xq))"
haftmann@30328: proof (cases "f ()")
haftmann@30328:   case Empty
haftmann@30328:   thus ?thesis
haftmann@34007:     unfolding Seq_def by (simp add: sup_commute [of "\<bottom>"])
haftmann@30328: next
haftmann@30328:   case Insert
haftmann@30328:   thus ?thesis
haftmann@30328:     unfolding Seq_def by (simp add: sup_assoc)
haftmann@30328: next
haftmann@30328:   case Join
haftmann@30328:   thus ?thesis
haftmann@30376:     unfolding Seq_def
haftmann@30376:     by (simp add: adjunct_sup sup_assoc sup_commute sup_left_commute)
haftmann@30328: qed
haftmann@30328: 
haftmann@30430: primrec contained :: "'a seq \<Rightarrow> 'a pred \<Rightarrow> bool" where
haftmann@30430:     "contained Empty Q \<longleftrightarrow> True"
haftmann@30430:   | "contained (Insert x P) Q \<longleftrightarrow> eval Q x \<and> P \<le> Q"
haftmann@30430:   | "contained (Join P xq) Q \<longleftrightarrow> P \<le> Q \<and> contained xq Q"
haftmann@30430: 
haftmann@30430: lemma single_less_eq_eval:
haftmann@30430:   "single x \<le> P \<longleftrightarrow> eval P x"
haftmann@30430:   by (auto simp add: single_def less_eq_pred_def mem_def)
haftmann@30430: 
haftmann@30430: lemma contained_less_eq:
haftmann@30430:   "contained xq Q \<longleftrightarrow> pred_of_seq xq \<le> Q"
haftmann@30430:   by (induct xq) (simp_all add: single_less_eq_eval)
haftmann@30430: 
haftmann@30430: lemma less_eq_pred_code [code]:
haftmann@30430:   "Seq f \<le> Q = (case f ()
haftmann@30430:    of Empty \<Rightarrow> True
haftmann@30430:     | Insert x P \<Rightarrow> eval Q x \<and> P \<le> Q
haftmann@30430:     | Join P xq \<Rightarrow> P \<le> Q \<and> contained xq Q)"
haftmann@30430:   by (cases "f ()")
haftmann@30430:     (simp_all add: Seq_def single_less_eq_eval contained_less_eq)
haftmann@30430: 
haftmann@30430: lemma eq_pred_code [code]:
haftmann@31133:   fixes P Q :: "'a pred"
haftmann@30430:   shows "eq_class.eq P Q \<longleftrightarrow> P \<le> Q \<and> Q \<le> P"
haftmann@30430:   unfolding eq by auto
haftmann@30430: 
haftmann@30430: lemma [code]:
haftmann@30430:   "pred_case f P = f (eval P)"
haftmann@30430:   by (cases P) simp
haftmann@30430: 
haftmann@30430: lemma [code]:
haftmann@30430:   "pred_rec f P = f (eval P)"
haftmann@30430:   by (cases P) simp
haftmann@30328: 
bulwahn@31105: inductive eq :: "'a \<Rightarrow> 'a \<Rightarrow> bool" where "eq x x"
bulwahn@31105: 
bulwahn@31105: lemma eq_is_eq: "eq x y \<equiv> (x = y)"
haftmann@31108:   by (rule eq_reflection) (auto intro: eq.intros elim: eq.cases)
haftmann@30948: 
haftmann@31216: definition map :: "('a \<Rightarrow> 'b) \<Rightarrow> 'a pred \<Rightarrow> 'b pred" where
haftmann@31216:   "map f P = P \<guillemotright>= (single o f)"
haftmann@31216: 
haftmann@32578: primrec null :: "'a seq \<Rightarrow> bool" where
haftmann@32578:     "null Empty \<longleftrightarrow> True"
haftmann@32578:   | "null (Insert x P) \<longleftrightarrow> False"
haftmann@32578:   | "null (Join P xq) \<longleftrightarrow> is_empty P \<and> null xq"
haftmann@32578: 
haftmann@32578: lemma null_is_empty:
haftmann@32578:   "null xq \<longleftrightarrow> is_empty (pred_of_seq xq)"
haftmann@32578:   by (induct xq) (simp_all add: is_empty_bot not_is_empty_single is_empty_sup)
haftmann@32578: 
haftmann@32578: lemma is_empty_code [code]:
haftmann@32578:   "is_empty (Seq f) \<longleftrightarrow> null (f ())"
haftmann@32578:   by (simp add: null_is_empty Seq_def)
haftmann@32578: 
bulwahn@33111: primrec the_only :: "(unit \<Rightarrow> 'a) \<Rightarrow> 'a seq \<Rightarrow> 'a" where
bulwahn@33111:   [code del]: "the_only dfault Empty = dfault ()"
bulwahn@33111:   | "the_only dfault (Insert x P) = (if is_empty P then x else let y = singleton dfault P in if x = y then x else dfault ())"
bulwahn@33110:   | "the_only dfault (Join P xq) = (if is_empty P then the_only dfault xq else if null xq then singleton dfault P
bulwahn@33110:        else let x = singleton dfault P; y = the_only dfault xq in
bulwahn@33111:        if x = y then x else dfault ())"
haftmann@32578: 
haftmann@32578: lemma the_only_singleton:
bulwahn@33110:   "the_only dfault xq = singleton dfault (pred_of_seq xq)"
haftmann@32578:   by (induct xq)
haftmann@32578:     (auto simp add: singleton_bot singleton_single is_empty_def
haftmann@32578:     null_is_empty Let_def singleton_sup)
haftmann@32578: 
haftmann@32578: lemma singleton_code [code]:
bulwahn@33110:   "singleton dfault (Seq f) = (case f ()
bulwahn@33111:    of Empty \<Rightarrow> dfault ()
haftmann@32578:     | Insert x P \<Rightarrow> if is_empty P then x
bulwahn@33110:         else let y = singleton dfault P in
bulwahn@33111:           if x = y then x else dfault ()
bulwahn@33110:     | Join P xq \<Rightarrow> if is_empty P then the_only dfault xq
bulwahn@33110:         else if null xq then singleton dfault P
bulwahn@33110:         else let x = singleton dfault P; y = the_only dfault xq in
bulwahn@33111:           if x = y then x else dfault ())"
haftmann@32578:   by (cases "f ()")
haftmann@32578:    (auto simp add: Seq_def the_only_singleton is_empty_def
haftmann@32578:       null_is_empty singleton_bot singleton_single singleton_sup Let_def)
haftmann@32578: 
bulwahn@33110: definition not_unique :: "'a pred => 'a"
bulwahn@33110: where
bulwahn@33111:   [code del]: "not_unique A = (THE x. eval A x)"
bulwahn@33110: 
bulwahn@33111: definition the :: "'a pred => 'a"
bulwahn@33111: where
bulwahn@33111:   [code del]: "the A = (THE x. eval A x)"
bulwahn@33111: 
bulwahn@33111: lemma the_eq[code]: "the A = singleton (\<lambda>x. not_unique A) A"
bulwahn@33111: by (auto simp add: the_def singleton_def not_unique_def)
bulwahn@33110: 
haftmann@33988: code_abort not_unique
haftmann@33988: 
haftmann@30948: ML {*
haftmann@30948: signature PREDICATE =
haftmann@30948: sig
haftmann@30948:   datatype 'a pred = Seq of (unit -> 'a seq)
haftmann@30948:   and 'a seq = Empty | Insert of 'a * 'a pred | Join of 'a pred * 'a seq
haftmann@30959:   val yield: 'a pred -> ('a * 'a pred) option
haftmann@30959:   val yieldn: int -> 'a pred -> 'a list * 'a pred
haftmann@31222:   val map: ('a -> 'b) -> 'a pred -> 'b pred
haftmann@30948: end;
haftmann@30948: 
haftmann@30948: structure Predicate : PREDICATE =
haftmann@30948: struct
haftmann@30948: 
haftmann@30959: @{code_datatype pred = Seq};
haftmann@30959: @{code_datatype seq = Empty | Insert | Join};
haftmann@30959: 
haftmann@32372: fun yield (@{code Seq} f) = next (f ())
haftmann@30959: and next @{code Empty} = NONE
haftmann@30959:   | next (@{code Insert} (x, P)) = SOME (x, P)
haftmann@30959:   | next (@{code Join} (P, xq)) = (case yield P
haftmann@30959:      of NONE => next xq
haftmann@33607:       | SOME (x, Q) => SOME (x, @{code Seq} (fn _ => @{code Join} (Q, xq))));
haftmann@30959: 
haftmann@30959: fun anamorph f k x = (if k = 0 then ([], x)
haftmann@30959:   else case f x
haftmann@30959:    of NONE => ([], x)
haftmann@30959:     | SOME (v, y) => let
haftmann@30959:         val (vs, z) = anamorph f (k - 1) y
haftmann@33607:       in (v :: vs, z) end);
haftmann@30959: 
haftmann@30959: fun yieldn P = anamorph yield P;
haftmann@30948: 
haftmann@31222: fun map f = @{code map} f;
haftmann@31222: 
haftmann@30948: end;
haftmann@30948: *}
haftmann@30948: 
haftmann@30948: code_reserved Eval Predicate
haftmann@30948: 
haftmann@30948: code_type pred and seq
haftmann@30948:   (Eval "_/ Predicate.pred" and "_/ Predicate.seq")
haftmann@30948: 
haftmann@30948: code_const Seq and Empty and Insert and Join
haftmann@30948:   (Eval "Predicate.Seq" and "Predicate.Empty" and "Predicate.Insert/ (_,/ _)" and "Predicate.Join/ (_,/ _)")
haftmann@30948: 
haftmann@30328: no_notation
haftmann@30328:   inf (infixl "\<sqinter>" 70) and
haftmann@30328:   sup (infixl "\<squnion>" 65) and
haftmann@30328:   Inf ("\<Sqinter>_" [900] 900) and
haftmann@30328:   Sup ("\<Squnion>_" [900] 900) and
haftmann@30328:   top ("\<top>") and
haftmann@30328:   bot ("\<bottom>") and
haftmann@30328:   bind (infixl "\<guillemotright>=" 70)
haftmann@30328: 
haftmann@30328: hide (open) type pred seq
bulwahn@33754: hide (open) const Pred eval single bind is_empty singleton if_pred not_pred holds
bulwahn@33111:   Empty Insert Join Seq member pred_of_seq "apply" adjunct null the_only eq map not_unique the
haftmann@30328: 
haftmann@30328: end




