theory LiveDemo03 imports Main begin section \Finding Theorems and Constants\ find_theorems (* by far too many results *) find_theorems "_ * (_ + _) = _" (* find distributive law *) find_theorems "?x * ?x = _" (* use same value *) find_theorems "_ \ _" (* too many results *) find_theorems "_ \ _" name: HOL (* restrict by name *) find_theorems (100) "_ \ _" name: HOL (* show up to 100 results *) find_theorems "_ \ _" name: HOL -"_ \ _" -"_ \ _" -All -Ex (* restrict by exclusion *) term "(\ x. P x) \ Q x" find_consts "?'a \ ?'a \ _ list" section \Drinker's Paradox -- Tuning Proofs\ text \previous version copied from Demo02\ lemma drinkers_paradox_v2: "\ p. drinks p \ (\ x. drinks x)" proof - { assume "\ x. \ drinks x" then obtain x where nex: "\ drinks x" by auto have ?thesis proof from nex show "drinks x \ (\y. drinks y)" by auto qed } hence part1: "(\ x. \ drinks x) \ ?thesis" by auto { assume "\ (\ x. \ drinks x)" hence "\ x. drinks x" by auto hence ?thesis by auto } hence "\ (\ x. \ drinks x) \ ?thesis" by auto thus ?thesis using part1 by auto qed lemma drinkers_paradox_v2a: "\ p. drinks p \ (\ x. drinks x)" proof - { assume "\ x. \ drinks x" then obtain x where nex: "\ drinks x" by auto have ?thesis proof from nex show "drinks x \ (\y. drinks y)" by auto qed } moreover have "5 > (3 :: nat)" by auto moreover { assume "\ (\ x. \ drinks x)" hence "\ x. drinks x" by auto hence ?thesis by auto } ultimately show ?thesis by auto qed text \Usage of "then", "hence", "moreover", "ultimately"\ lemma drinkers_paradox_v3: "\ p. drinks p \ (\ x. drinks x)" proof - { assume "\ x. \ drinks x" then obtain x where "\ drinks x" by auto (* then = from this *) hence ?thesis by auto (* hence = then have *) } moreover (* store fact *) { assume "\ (\ x. \ drinks x)" hence ?thesis by auto } ultimately show ?thesis by auto (* assume previously stored facts and "this" *) qed text \Usage of case-analysis on Booleans with cases True/False separated by "next".\ lemma drinkers_paradox_v4: "\ p. drinks p \ (\ x. drinks x)" proof (cases "\ x. \ drinks x") case True then obtain x where "\ drinks x" by auto then show ?thesis by auto qed auto section \Intro and Elim: apply several introduction / elimination rules\ lemma "A \ (\ x :: nat. B x \ (C \ D x))" proof (intro conjI exI) \ \three subgoals: A, B ?x, C \ D ?x\ show A sorry show "B 5" sorry (* here we choose witness 5 *) show "C \ D 5" sorry (* no choice of witness anymore *) qed lemma True (* True is used as dummy property *) proof - fix A B C D assume "\ x :: nat. A \ (B x \ C x)" hence D proof (elim exE conjE disjE) (* apply multiple elimination rules *) (* inspect proof goals at this point *) oops section \Case-Analysis and Induction\ text \A copy of the list datatype to illustrate print-theorems\ datatype 'a ls = Empty | Con 'a "'a ls" text \This datatype definition proves a lot of theorems for you, as can be seen by print_theorems that is used directly after some definition.\ thm list.exhaust (* case analysis on lists *) thm list.induct (* induction on lists *) thm list.simps (* simplification rules for list-constructors *) fun app :: "'a list \ 'a list \ 'a list" where "app [] ys = ys" | "app (x # xs) ys = x # (app xs ys)" print_theorems fun reverse :: "'a list \ 'a list" where "reverse [] = []" | "reverse (x # xs) = app (reverse xs) ([x])" lemma app_Nil_right[simp]: "app xs [] = xs" by (induction xs) auto lemma app_assoc: "app (app xs ys) zs = app xs (app ys zs)" by (induction xs) auto lemma rev_app: "reverse (app xs ys) = app (reverse ys) (reverse xs)" proof (induction xs) case [simp]: (Cons x xs) show ?case by (auto simp: app_assoc) qed auto lemma rev_rev[simp]: "reverse (reverse xs) = xs" proof (induction xs) case (Cons y ys) thus ?case by (auto simp: rev_app) qed auto text \A proof by case-analysis\ fun tail :: "'a list \ 'a list" where "tail [] = []" | "tail (_ # xs) = xs" lemma len_tail: "length (tail xs) = length xs - 1" proof (cases xs) case (Cons y ys) then show ?thesis by auto qed auto text \An induction proof involving case-analysis\ fun drop_last :: "'a list \ 'a list" where "drop_last (x # y # ys) = x # drop_last (y # ys)" | "drop_last xs = []" thm drop_last.simps (* observe how the second defining equation is handled *) lemma len_drop: "length (drop_last xs) = length xs - 1" proof (induction xs) case (Cons x xs) show ?case proof (cases xs) case innerCons: (Cons y ys) thus ?thesis using Cons by auto qed auto qed auto lemma len_drop2: "length (drop_last xs) = length xs - 1" proof (induction xs) case (Cons x xs) thus ?case by (cases xs) auto qed auto end