theory s3 imports Main begin -- ----------------------------------------------------- section "Balanced Parentheses" datatype letter = L | R type_synonym lang = "letter list set" -- "a)" inductive_set S :: "lang" where emptyI: "[] \ S" | insertI: "\xs \ S\ \ L # (xs @ [R]) \ S" | appendI: "\xs \ S; ys \ S\ \ xs @ ys \ S" -- "b)" lemma eg1: "[L,R,L,L,R,R] \ S" apply (rule appendI[where xs="[L,R]" and ys="[L,L,R,R]", simplified]) apply (rule insertI[where xs="[]", simplified]) apply (rule emptyI) apply (rule insertI[where xs="[L,R]", simplified]) apply (rule insertI[where xs="[]", simplified]) apply (rule emptyI) done lemma eg2: "[L,L,R,L,L,R,R,R] \ S" apply (rule insertI[where xs="[L,R,L,L,R,R]", simplified]) apply (rule eg1) done -- "c)" fun is_bal :: "letter list \ nat \ bool" where "is_bal [] n = (n = 0)" | "is_bal (L # xs) n = is_bal xs (Suc n)" | "is_bal (R # xs) n = (n \ 0 \ is_bal xs (n - 1))" value "is_bal [L,L,R,R] 0" value "is_bal [L,R,R] 0" value "is_bal [] 0" value "is_bal [L,L,R,L,L,R,R,R] 0" -- "d)" lemma is_bal_append: "\is_bal xs n; is_bal ys m\ \ is_bal (xs @ ys) (n+m)" by (induct xs n rule:is_bal.induct, auto) lemma "xs \ S \ is_bal xs 0" by (induct xs rule:S.induct, auto intro:is_bal_append[where n=0 and m="Suc 0", simplified] is_bal_append[where n=0 and m=0, simplified]) -- ----------------------------------------------------- section "Expressions" datatype expr = Const nat | Var string | Plus expr expr type_synonym state = "string \ nat" -- "a) Evaluating expressions" primrec aval :: "expr \ state \ nat" where "aval (Const n) s = n" | "aval (Var x) s = s x" | "aval (Plus v w) s = (aval v s) + (aval w s)" value "aval (Plus (Var ''x'') (Const 5)) ((\x. undefined)(''x'':=3))" -- "b) Simplifying expressions" type_synonym vars = "string \ nat option" fun asimp :: "expr \ vars \ expr" where "asimp (Const n) t = Const n" | "asimp (Var x) t = (case t x of Some n \ Const n | None \ Var x)" | "asimp (Plus v w) t = (case (asimp v t, asimp w t) of (Const k, Const l) \ Const (k+l) | (Const 0, e) \ e | (e, Const 0) \ e | (f,g) \ Plus f g)" -- "c) formulate and prove correctness lemma" lemma asimp_corr: "\\x n. t x = Some n \ s x = n \ \ aval (asimp e t) s = aval e s" by (induct e rule:expr.induct, auto split:option.splits expr.splits nat.splits) -- ----------------------------------------------------- section "File System Paths" datatype seg = Root | Parent | Seg string type_synonym path = "seg list" fun str_of where "str_of Root = ''//''" | "str_of Parent = ''..''" | "str_of (Seg s) = s" -- "a)" -- "implement sep and str:" fun sep :: "'a \ 'a list \ 'a list" where "sep a (x # y # zs) = x # a # sep a (y # zs)" | "sep a xs = xs" (* paths are stored in reverse" *) fun str :: "path \ string" where "str xs = concat (rev (sep ''/'' (map str_of xs)))" -- "b) implement chdir" fun chdir :: "seg \ path \ path" where "chdir Root x = [Root]" | "chdir Parent xs = (case xs of Seg s # xs \ xs | xs \ Parent # xs)" | "chdir (Seg s) xs = (Seg s) # xs" -- "c) implement norm" value "chdir Parent [Parent, Parent, Seg ''a'', Seg ''b'', Root]" fun norm :: "path \ path" where "norm [] = []" | "norm (x # xs) = chdir x (norm xs)" -- "d) formulate and prove correctness of norm" (* Elements of the base path - paths consisting of the root and parent *) inductive_set basePath :: "path set" where emptyBase: "[] \ basePath" | rootBase: "[Root] \ basePath" | parentBase: "p \ basePath \ (Parent # p) \ basePath" inductive_set normalisedPaths :: "path set" where baseNorm: "p \ basePath \ p \ normalisedPaths" | extendNorm: "p \ normalisedPaths \ (Seg x # p) \ normalisedPaths" declare basePath.intros[intro] declare normalisedPaths.intros[intro] lemma chdir_norm: "norm xs \ normalisedPaths \ chdir x (norm xs) \ normalisedPaths" apply(induct rule: normalisedPaths.induct) apply (case_tac x, auto split: list.splits seg.splits elim: basePath.cases)+ done lemma norm_corr: "norm p \ normalisedPaths" apply (induct p rule:norm.induct) apply (simp) apply (rule baseNorm) apply (rule emptyBase) apply (simp only: norm.simps(2)) apply (erule chdir_norm) done -- "e) prove that norm is the identity on normal paths" lemma basePath_id: "p \ basePath \ norm p = p" apply (induct p rule:basePath.induct) apply simp apply simp apply (simp only: norm.simps(2)) apply (erule basePath.cases) apply auto done lemma norm_id1: "\p \ normalisedPaths\ \ norm p = p" by (induct p rule:normalisedPaths.induct, auto elim:basePath_id) lemma norm_id2: "\norm p = p \ \ p \ normalisedPaths" by (erule subst, rule norm_corr) lemma norm_identity: "norm p = p \ p \ normalisedPaths" by (intro iffI, (elim norm_id2 norm_id1)+) end