theory Demo08
  imports 
    Main
begin

section \<open>Sets and Lists in Isabelle\<close>

term "(\<in>)" (* membership *)
term "(\<subseteq>)" (* subset *)
term "(\<subset>)" (* strict subset *)
term Ball  (* all elements satisfy predicate *)
term Bex   (* at least one element satisfies predicate *)
term "(\<union>)" (* union *)
term "(\<inter>)" (* intersection *)
term "\<Union>"   (* big-union *)
term "\<Inter>"   (* big-intersection *)
term "- (A :: 'a set)" (* complement *)
term "A - (B :: 'a set)" (* difference *)
term "{}"   (* empty set *)
term "UNIV :: 'a set" (* all elements (of a specific type) *)
term "{x}"  (* singleton *)
term insert (* add single element *)
term finite (* is set finite? *)
term card   (* cardinality (0 for infinite sets *)
term "(`)"  (* image, apply function to all set elements *)
term "(-`)" (* inverse image, detected via: *) find_consts "(?'a \<Rightarrow> ?'b) \<Rightarrow> ?'b set \<Rightarrow> ?'a set"  
term Collect (* convert predicate to set *)
term "{x . P x}"  (* basic set comprehension *)
term "{ (x,y + z) | x y z u . x - y = u \<and> u \<le> 5 \<and> P z}"  (* more complex set comprehension *)
term "sum f A" (* sum_{a in A} f(a) *)
term "prod"    (* product, similar to sum *)
term "Max A"   (* maximum of finite non-empty set *)
term "Min A"   (* minimum of finite non-empty set *)


lemma "card { (x * 3, y) :: nat \<times> bool | x y. x < 10 \<and> P y } \<le> 20" 
  (is "card ?S \<le> _")
proof -
  show ?thesis sorry
qed
  
lemma "infinite S \<Longrightarrow> prod f S = 1 \<and> sum f S = 0"  by auto

lemma "sum (\<lambda> i. i) {..< (n :: nat)} \<le> n^2" 
proof -
  show ?thesis sorry
qed


text \<open>Functions on Lists\<close>

term set
term hd
term tl
term take
term drop
term append term "(@)" 
term filter
term map
term foldr
term foldl
term nth term "(!)" 
term concat
term distinct
term sorted
term sorted_list_of_set
term sum_list
term prod_list
term list_update  term "xs [ i := n ]" 
term "f (x := n)" 

term "[ (a, 2 * b) .  a <- [0 ..< n], even a, b <- [2 .. 5]]"

thm sum.cong
thm sum_mono
thm sum.neutral
thm nth_equalityI
thm set_conv_nth
thm split_list

find_theorems "sum _ (_ \<union> _) = _ + _"



section \<open>Binary Search Trees\<close>

datatype 'a tree = Leaf | Node "'a tree" 'a "'a tree" 

fun set_t :: "'a tree \<Rightarrow> 'a set" where
  "set_t Leaf = {}" 
| "set_t (Node l x r) = set_t l \<union> {x} \<union> set_t r" 

inductive ordered :: "'a :: linorder tree \<Rightarrow> bool" where
  oLeaf: "ordered Leaf" 
| oNode: "ordered l \<Longrightarrow> ordered r 
  \<Longrightarrow> Ball (set_t l) (\<lambda> y. y < x)
  \<Longrightarrow> Ball (set_t r) (\<lambda> y. y > x)
  \<Longrightarrow> ordered (Node l x r)" 

fun member:: "'a :: linorder \<Rightarrow> 'a tree \<Rightarrow> bool" where
  "member x Leaf = False" 
| "member y (Node l x r) = (if x = y then True else if y < x then member y l else member y r)" 

lemma member_correct: "ordered t \<Longrightarrow> member x t = (x \<in> set_t t)" 
  by (induction rule: ordered.induct, auto)

fun insert_t :: "'a :: linorder \<Rightarrow> 'a tree \<Rightarrow> 'a tree" where
  "insert_t y Leaf = undefined" 
| "insert_t y (Node l x r) = undefined" 

lemma insert_t: undefined 
  oops

fun delete_right :: "'a :: linorder tree \<Rightarrow> 'a tree \<times> 'a" where
  "delete_right (Node l x r) = undefined" 

fun delete :: "'a :: linorder \<Rightarrow> 'a tree \<Rightarrow> 'a tree" where
  "delete x t = undefined" 

lemma delete_right: "undefined (delete_right t)" 
  oops

lemma delete: "undefined (delete x t)" 
  oops


end