(***************************************************************************** * ESPL --- an embedded security protocol logic * http://people.inf.ethz.ch/meiersi/espl/ * * Copyright (c) 2009-2011, Simon Meier, ETH Zurich, Switzerland * * All rights reserved. See file LICENCE for more information. ******************************************************************************) theory DistinctList imports Main begin chapter{* Preliminaries *} section{* Splitting Lists *} fun splits :: "'a list \ ('a list \ 'a list) list" where "splits [] = [([],[])]" | "splits (x#xs) = ([],x#xs) # map (\(pre,suf). (x#pre,suf)) (splits xs)" lemma in_set_splits_conv: "((ys,zs) \ set (splits xs)) = (xs = ys @ zs)" by(induct xs arbitrary: ys zs) (auto simp: Cons_eq_append_conv) section{* Distinct Lists *} lemma distinct_in_set_decomp: assumes "x \ set xs" and "distinct xs" shows "\ ys zs. xs = ys@ x # zs \ x \ set ys \ x \ set zs \ set ys \ set zs = {}" (is "\ ys zs. ?split xs ys zs") using assms proof(induct xs) case (Cons a xs) hence "x = a \ x \ set xs" (is "?hd \ ?tl") by simp moreover { assume ?hd hence "?split (a#xs) [] xs" using Cons by auto hence ?case by fast } moreover { assume ?tl then obtain ys zs where "?split xs ys zs" using Cons by auto with Cons have "?split (a#xs) (a#ys) zs" by auto hence ?case by fast } ultimately show ?case by fast next qed simp subsection{* Direct Predecessors *} fun "nextRel" :: "'a list \ 'a \ 'a \ bool" where "nextRel [] a b = False" | "nextRel [x] a b = False" | "nextRel (x#y#xs) a b = ((a = x \ b = y) \ (nextRel (y#xs) a b))" lemma nextRelI: "xs = ys@x#y#zs \ nextRel xs x y" by (induct xs x y arbitrary: ys rule: nextRel.induct) (auto simp: Cons_eq_append_conv) lemma nextRelD: "nextRel xs x y \ (\ ys zs. xs = ys@x#y#zs)" by (induct xs x y arbitrary: ys rule: nextRel.induct) (auto simp: Cons_eq_append_conv) lemma nextRel_conv: "(nextRel xs x y) = (\ ys zs. xs = ys@x#y#zs)" by(auto intro: nextRelI nextRelD) lemma in_set_nextRel1: "nextRel xs x y \ x \ set xs" by(auto simp: nextRel_conv) lemma in_set_nextRel2: "nextRel xs x y \ y \ set xs" by(auto simp: nextRel_conv) lemma nextRel_rev: "nextRel (rev xs) x y = nextRel xs y x" unfolding nextRel_conv proof assume "\ys zs. xs = ys @ y # x # zs" then obtain ys zs where "xs = ys @ y # x # zs" by fast then have "rev xs = rev (ys @ y # x # zs)" by (rule arg_cong) then show "\ys zs. rev xs = ys @ x # y # zs" by auto next assume "\ys zs. rev xs = ys @ x # y # zs" then obtain ys zs where "rev xs = ys @ x # y # zs" by fast then have "rev (rev xs) = rev (ys @ x # y # zs)" by (rule arg_cong) then show "\ys zs. xs = ys @ y # x # zs" by auto qed text{* Specialized instances of nextRel_rev for Snoc appends *} lemma nextRel_Snoc_simps: "nextRel (xs@[a]) x y = nextRel (a#rev xs) y x" "nextRel (xs@[a,b]) x y = nextRel (b#a#rev xs) y x" by(subst nextRel_rev[symmetric], simp)+ lemma nextRel_Cons_simps: "x \ y \ nextRel (x#xs) y z = nextRel xs y z" "x' \ z \ nextRel (x#x'#xs) y z = nextRel (x'#xs) y z" by (cases xs) simp+ lemmas nextRel_simps [simp] = nextRel_rev nextRel_Snoc_simps nextRel_Cons_simps lemma nextRelI_direct [simp,intro!]: "nextRel (xs@x#y#ys) x y" by(auto simp: nextRel_conv) lemma nextRel_appendI1: "nextRel xs x y \ nextRel (xs@ys) x y" by(induct xs x y rule: nextRel.induct) auto subsection{* Predecessors *} fun listOrd :: "'a list \ 'a \ 'a \ bool" where "listOrd [] a b = False" | "listOrd (x#xs) a b = ((a = x \ b \ set xs) \ listOrd xs a b)" lemma in_set_listOrd1: "listOrd xs x y \ x \ set xs" by(induct xs, auto) lemma in_set_listOrd2: "listOrd xs x y \ y \ set xs" by(induct xs, auto) lemma listOrd_append [simp]: "listOrd (xs@ys) a b = (listOrd xs a b \ listOrd ys a b \ (a \ set xs \ b \ set ys))" by(induct xs, auto) lemma listOrd_rev [simp]: "listOrd (rev xs) x y = listOrd xs y x" by(induct xs, auto) lemma nextRel_imp_listOrd: "nextRel xs x y \ listOrd xs x y" by(induct xs x y rule: nextRel.induct) auto lemma listOrd_filter: "listOrd (filter p xs) x y \ listOrd xs x y" by(induct xs) (auto split: if_splits) lemma listOrd_takeWhile: "listOrd (takeWhile p xs) x y \ listOrd xs x y" proof(induct xs) case Nil thus ?case by auto next case (Cons a xs) thus ?case by(auto split: if_splits dest: set_takeWhileD) qed lemma list_Ord_singleton[simp]: "listOrd [a] x y \ False" by auto lemma listOrd_distinct_irr [simp]: "distinct xs \ \listOrd xs x x" by(induct xs, auto) lemma listOrd_distinct_trans: "\ listOrd xs x y; listOrd xs y z; distinct xs \ \ listOrd xs x z" by (induct xs) (auto dest: in_set_listOrd1 in_set_listOrd2) lemma listOrd_distinct_asymD: "\ listOrd xs x y; distinct xs \ \ \ listOrd xs y x" by (induct xs) (auto dest: in_set_listOrd1 in_set_listOrd2) lemma listOrd_distinct_cases: "\ x \ set xs; y \ set xs; distinct xs \ \ x = y \ listOrd xs x y \ listOrd xs y x" by(induct xs, auto) definition listEqOrd :: "'a list \ 'a \ 'a \ bool" where "listEqOrd xs x y \ (x = y) \ listOrd xs x y" subsection{* List Order *} locale distinct_list = fixes xs :: "'a list" assumes distinct [simp,intro!]: "distinct xs" begin abbreviation "next" (infixl "\\<^sub>1" 50) where "next \ nextRel xs" abbreviation pred (infixl "\" 50) where "pred \ listOrd xs" abbreviation predEq (infixl "\" 50) where "predEq \ listEqOrd xs" end text{* Aquiring the order properties *} sublocale distinct_list \ order "predEq" "pred" by unfold_locales (auto simp: listEqOrd_def dest: listOrd_distinct_asymD intro: listOrd_distinct_trans) text{* Relating @{term next} to the order *} context distinct_list begin lemma next_imp_less: "x \\<^sub>1 y \ x \ y" by(auto simp: listEqOrd_def dest!: nextRel_imp_listOrd) lemma next_imp_le: "x \\<^sub>1 y \ x \ y" by(auto dest: next_imp_less) lemma in_set_less1: "x \ y \ x \ set xs" by(simp add: pred_def in_set_listOrd1) lemma in_set_less2: "x \ y \ y \ set xs" by(simp add: pred_def in_set_listOrd2) lemmas in_set_next1 = in_set_less1[OF next_imp_less, rule_format] lemmas in_set_next2 = in_set_less2[OF next_imp_less, rule_format] end end