theory Demo03 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 *) 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" from this obtain x where nex: "\ drinks x" by auto have ?thesis proof from nex show "drinks x \ (\y. drinks y)" by auto qed } from this have part1: "(\ x. \ drinks x) \ ?thesis" by auto { assume "\ (\ x. \ drinks x)" from this have "\ x. drinks x" by auto from this have ?thesis by auto } from this have part2: "\ (\ x. \ drinks x) \ ?thesis" by auto from part1 part2 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 (* we could also have started with case False *) from True obtain x where "\ drinks x" using exE by auto thus ?thesis by (intro exI[of _ x]) auto (* thus = then show *) next case ownLabel: False from ownLabel show ?thesis by auto qed text \Omit trivial cases via final method\ lemma drinkers_paradox_v5: "\ p. drinks p \ (\ x. drinks x)" proof (cases "\ x. \ drinks x") case True then obtain x where "\ drinks x" by auto thus ?thesis by auto qed auto (* solve trivial cases by auto after qed *) 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" print_theorems 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 aim: "reverse (reverse xs) = xs" oops text \What follows is the final proof of the fact that reversing a list twice results in the input list. The development process of this proof is much more interesting than the final proof and will be given via a live demo in the lecture.\ text \This is a good equation for simplification\ lemma app_Nil[simp]: "app xs [] = xs" by (induction xs) auto text \Making associativity a [simp]-rule is not that obvious: what direction should we choose?\ lemma app_assoc: "app xs (app ys zs) = app (app xs ys) zs" by (induction xs) auto lemma rev_app: "reverse (app xs ys) = app (reverse ys) (reverse xs)" proof (induction xs) case (Cons x xs) then show ?case by (auto simp: app_assoc) qed auto lemma rev_rev[simp]: "reverse (reverse xs) = xs" proof (induction xs) case (Cons x xs) then show ?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 Nil then show ?thesis by auto next case (Cons x xs) then show ?thesis by auto qed 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) text \case analysis on xs required to trigger simp-rules of @{const drop_last}.\ show ?case proof (cases xs) case xs: (Cons y ys) text \use different label so that inner Cons (xs = y # ys) does not hide outer Cons (IH)\ with Cons show ?thesis by auto qed auto qed auto end