# HG changeset patch # User Christian Urban # Date 1400854772 -3600 # Node ID af38526275f8daf81911b7a94aa3273ad09df5bb # Parent 92f61f6a0fe795596c04d1b24243b83c36323951 added a test theory for polishing teh proofs diff -r 92f61f6a0fe7 -r af38526275f8 PrioG.thy --- a/PrioG.thy Thu May 22 17:40:39 2014 +0100 +++ b/PrioG.thy Fri May 23 15:19:32 2014 +0100 @@ -800,9 +800,11 @@ apply(fold wq_def) apply(drule_tac step_back_step) apply(ind_cases " step s (P (hd (wq s cs)) cs)") - apply(auto simp:s_RAG_def wq_def cs_holding_def) + apply(simp add:s_RAG_def wq_def cs_holding_def) + apply(auto) done +(* FIXME: Unused lemma simple_A: fixes A assumes h: "\ x y. \x \ A; y \ A\ \ x = y" @@ -814,6 +816,7 @@ with h have "A = {a}" by auto thus ?thesis by simp qed +*) lemma RAG_target_th: "(Th th, x) \ RAG (s::state) \ \ cs. x = Cs cs" by (unfold s_RAG_def, auto) @@ -822,126 +825,125 @@ fixes s assumes vt: "vt s" shows "acyclic (RAG s)" -proof - - from vt show ?thesis - proof(induct) - case (vt_cons s e) - assume ih: "acyclic (RAG s)" - and stp: "step s e" - and vt: "vt s" - show ?case - proof(cases e) - case (Create th prio) - with ih - show ?thesis by (simp add:RAG_create_unchanged) - next - case (Exit th) - with ih show ?thesis by (simp add:RAG_exit_unchanged) - next - case (V th cs) - from V vt stp have vtt: "vt (V th cs#s)" by auto - from step_RAG_v [OF this] - have eq_de: - "RAG (e # s) = - RAG s - {(Cs cs, Th th)} - {(Th th', Cs cs) |th'. next_th s th cs th'} \ - {(Cs cs, Th th') |th'. next_th s th cs th'}" - (is "?L = (?A - ?B - ?C) \ ?D") by (simp add:V) - from ih have ac: "acyclic (?A - ?B - ?C)" by (auto elim:acyclic_subset) - from step_back_step [OF vtt] - have "step s (V th cs)" . - thus ?thesis - proof(cases) - assume "holding s th cs" - hence th_in: "th \ set (wq s cs)" and - eq_hd: "th = hd (wq s cs)" unfolding s_holding_def wq_def by auto - then obtain rest where - eq_wq: "wq s cs = th#rest" - by (cases "wq s cs", auto) - show ?thesis - proof(cases "rest = []") - case False - let ?th' = "hd (SOME q. distinct q \ set q = set rest)" - from eq_wq False have eq_D: "?D = {(Cs cs, Th ?th')}" - by (unfold next_th_def, auto) - let ?E = "(?A - ?B - ?C)" - have "(Th ?th', Cs cs) \ ?E\<^sup>*" - proof - assume "(Th ?th', Cs cs) \ ?E\<^sup>*" - hence " (Th ?th', Cs cs) \ ?E\<^sup>+" by (simp add: rtrancl_eq_or_trancl) - from tranclD [OF this] - obtain x where th'_e: "(Th ?th', x) \ ?E" by blast - hence th_d: "(Th ?th', x) \ ?A" by simp - from RAG_target_th [OF this] - obtain cs' where eq_x: "x = Cs cs'" by auto - with th_d have "(Th ?th', Cs cs') \ ?A" by simp - hence wt_th': "waiting s ?th' cs'" - unfolding s_RAG_def s_waiting_def cs_waiting_def wq_def by simp - hence "cs' = cs" - proof(rule waiting_unique [OF vt]) - from eq_wq wq_distinct[OF vt, of cs] - show "waiting s ?th' cs" - apply (unfold s_waiting_def wq_def, auto) - proof - - assume hd_in: "hd (SOME q. distinct q \ set q = set rest) \ set rest" +using assms +proof(induct) + case (vt_cons s e) + assume ih: "acyclic (RAG s)" + and stp: "step s e" + and vt: "vt s" + show ?case + proof(cases e) + case (Create th prio) + with ih + show ?thesis by (simp add:RAG_create_unchanged) + next + case (Exit th) + with ih show ?thesis by (simp add:RAG_exit_unchanged) + next + case (V th cs) + from V vt stp have vtt: "vt (V th cs#s)" by auto + from step_RAG_v [OF this] + have eq_de: + "RAG (e # s) = + RAG s - {(Cs cs, Th th)} - {(Th th', Cs cs) |th'. next_th s th cs th'} \ + {(Cs cs, Th th') |th'. next_th s th cs th'}" + (is "?L = (?A - ?B - ?C) \ ?D") by (simp add:V) + from ih have ac: "acyclic (?A - ?B - ?C)" by (auto elim:acyclic_subset) + from step_back_step [OF vtt] + have "step s (V th cs)" . + thus ?thesis + proof(cases) + assume "holding s th cs" + hence th_in: "th \ set (wq s cs)" and + eq_hd: "th = hd (wq s cs)" unfolding s_holding_def wq_def by auto + then obtain rest where + eq_wq: "wq s cs = th#rest" + by (cases "wq s cs", auto) + show ?thesis + proof(cases "rest = []") + case False + let ?th' = "hd (SOME q. distinct q \ set q = set rest)" + from eq_wq False have eq_D: "?D = {(Cs cs, Th ?th')}" + by (unfold next_th_def, auto) + let ?E = "(?A - ?B - ?C)" + have "(Th ?th', Cs cs) \ ?E\<^sup>*" + proof + assume "(Th ?th', Cs cs) \ ?E\<^sup>*" + hence " (Th ?th', Cs cs) \ ?E\<^sup>+" by (simp add: rtrancl_eq_or_trancl) + from tranclD [OF this] + obtain x where th'_e: "(Th ?th', x) \ ?E" by blast + hence th_d: "(Th ?th', x) \ ?A" by simp + from RAG_target_th [OF this] + obtain cs' where eq_x: "x = Cs cs'" by auto + with th_d have "(Th ?th', Cs cs') \ ?A" by simp + hence wt_th': "waiting s ?th' cs'" + unfolding s_RAG_def s_waiting_def cs_waiting_def wq_def by simp + hence "cs' = cs" + proof(rule waiting_unique [OF vt]) + from eq_wq wq_distinct[OF vt, of cs] + show "waiting s ?th' cs" + apply (unfold s_waiting_def wq_def, auto) + proof - + assume hd_in: "hd (SOME q. distinct q \ set q = set rest) \ set rest" and eq_wq: "wq_fun (schs s) cs = th # rest" - have "(SOME q. distinct q \ set q = set rest) \ []" - proof(rule someI2) - from wq_distinct[OF vt, of cs] and eq_wq - show "distinct rest \ set rest = set rest" unfolding wq_def by auto - next - fix x assume "distinct x \ set x = set rest" - with False show "x \ []" by auto - qed - hence "hd (SOME q. distinct q \ set q = set rest) \ - set (SOME q. distinct q \ set q = set rest)" by auto - moreover have "\ = set rest" - proof(rule someI2) - from wq_distinct[OF vt, of cs] and eq_wq - show "distinct rest \ set rest = set rest" unfolding wq_def by auto - next - show "\x. distinct x \ set x = set rest \ set x = set rest" by auto - qed - moreover note hd_in - ultimately show "hd (SOME q. distinct q \ set q = set rest) = th" by auto + have "(SOME q. distinct q \ set q = set rest) \ []" + proof(rule someI2) + from wq_distinct[OF vt, of cs] and eq_wq + show "distinct rest \ set rest = set rest" unfolding wq_def by auto next - assume hd_in: "hd (SOME q. distinct q \ set q = set rest) \ set rest" + fix x assume "distinct x \ set x = set rest" + with False show "x \ []" by auto + qed + hence "hd (SOME q. distinct q \ set q = set rest) \ + set (SOME q. distinct q \ set q = set rest)" by auto + moreover have "\ = set rest" + proof(rule someI2) + from wq_distinct[OF vt, of cs] and eq_wq + show "distinct rest \ set rest = set rest" unfolding wq_def by auto + next + show "\x. distinct x \ set x = set rest \ set x = set rest" by auto + qed + moreover note hd_in + ultimately show "hd (SOME q. distinct q \ set q = set rest) = th" by auto + next + assume hd_in: "hd (SOME q. distinct q \ set q = set rest) \ set rest" and eq_wq: "wq s cs = hd (SOME q. distinct q \ set q = set rest) # rest" - have "(SOME q. distinct q \ set q = set rest) \ []" - proof(rule someI2) - from wq_distinct[OF vt, of cs] and eq_wq - show "distinct rest \ set rest = set rest" by auto - next - fix x assume "distinct x \ set x = set rest" - with False show "x \ []" by auto - qed - hence "hd (SOME q. distinct q \ set q = set rest) \ - set (SOME q. distinct q \ set q = set rest)" by auto - moreover have "\ = set rest" - proof(rule someI2) - from wq_distinct[OF vt, of cs] and eq_wq - show "distinct rest \ set rest = set rest" by auto - next - show "\x. distinct x \ set x = set rest \ set x = set rest" by auto - qed - moreover note hd_in - ultimately show False by auto + have "(SOME q. distinct q \ set q = set rest) \ []" + proof(rule someI2) + from wq_distinct[OF vt, of cs] and eq_wq + show "distinct rest \ set rest = set rest" by auto + next + fix x assume "distinct x \ set x = set rest" + with False show "x \ []" by auto + qed + hence "hd (SOME q. distinct q \ set q = set rest) \ + set (SOME q. distinct q \ set q = set rest)" by auto + moreover have "\ = set rest" + proof(rule someI2) + from wq_distinct[OF vt, of cs] and eq_wq + show "distinct rest \ set rest = set rest" by auto + next + show "\x. distinct x \ set x = set rest \ set x = set rest" by auto qed + moreover note hd_in + ultimately show False by auto qed - with th'_e eq_x have "(Th ?th', Cs cs) \ ?E" by simp - with False - show "False" by (auto simp: next_th_def eq_wq) qed - with acyclic_insert[symmetric] and ac - and eq_de eq_D show ?thesis by auto - next - case True - with eq_wq - have eq_D: "?D = {}" - by (unfold next_th_def, auto) - with eq_de ac - show ?thesis by auto - qed - qed + with th'_e eq_x have "(Th ?th', Cs cs) \ ?E" by simp + with False + show "False" by (auto simp: next_th_def eq_wq) + qed + with acyclic_insert[symmetric] and ac + and eq_de eq_D show ?thesis by auto + next + case True + with eq_wq + have eq_D: "?D = {}" + by (unfold next_th_def, auto) + with eq_de ac + show ?thesis by auto + qed + qed next case (P th cs) from P vt stp have vtt: "vt (P th cs#s)" by auto @@ -970,14 +972,14 @@ proof assume "(Cs cs, Th th) \ (RAG s)\<^sup>*" hence "(Cs cs, Th th) \ (RAG s)\<^sup>+" by (simp add: rtrancl_eq_or_trancl) - moreover from step_back_step [OF vtt] have "step s (P th cs)" . - ultimately show False - proof - - show " \(Cs cs, Th th) \ (RAG s)\<^sup>+; step s (P th cs)\ \ False" - by (ind_cases "step s (P th cs)", simp) - qed + moreover from step_back_step [OF vtt] have "step s (P th cs)" . + ultimately show False + proof - + show " \(Cs cs, Th th) \ (RAG s)\<^sup>+; step s (P th cs)\ \ False" + by (ind_cases "step s (P th cs)", simp) qed - with acyclic_insert ih eq_r show ?thesis by auto + qed + with acyclic_insert ih eq_r show ?thesis by auto qed ultimately show ?thesis by simp next @@ -990,8 +992,8 @@ case vt_nil show "acyclic (RAG ([]::state))" by (auto simp: s_RAG_def cs_waiting_def - cs_holding_def wq_def acyclic_def) - qed + cs_holding_def wq_def acyclic_def) +qed qed lemma finite_RAG: diff -r 92f61f6a0fe7 -r af38526275f8 Test.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Test.thy Fri May 23 15:19:32 2014 +0100 @@ -0,0 +1,370 @@ +theory Test +imports Precedence_ord +begin + +type_synonym thread = nat -- {* Type for thread identifiers. *} +type_synonym priority = nat -- {* Type for priorities. *} +type_synonym cs = nat -- {* Type for critical sections (or critical resources). *} + +datatype event = + Create thread priority +| Exit thread +| P thread cs +| V thread cs +| Set thread priority + +type_synonym state = "event list" + +fun threads :: "state \ thread set" + where + "threads [] = {}" +| "threads (Create th prio#s) = {th} \ threads s" +| "threads (Exit th # s) = (threads s) - {th}" +| "threads (_#s) = threads s" + +fun priority :: "thread \ state \ priority" + where + "priority th [] = 0" +| "priority th (Create th' prio#s) = (if th' = th then prio else priority th s)" +| "priority th (Set th' prio#s) = (if th' = th then prio else priority th s)" +| "priority th (_#s) = priority th s" + +fun last_set :: "thread \ state \ nat" + where + "last_set th [] = 0" +| "last_set th ((Create th' prio)#s) = (if (th = th') then length s else last_set th s)" +| "last_set th ((Set th' prio)#s) = (if (th = th') then length s else last_set th s)" +| "last_set th (_#s) = last_set th s" + +definition preced :: "thread \ state \ precedence" + where "preced th s \ Prc (priority th s) (last_set th s)" + +definition + "holds wq th cs \ th \ set (wq cs) \ th = hd (wq cs)" + +definition + "waits wq th cs \ th \ set (wq cs) \ th \ hd (wq cs)" + +datatype node = + Th "thread" +| Cs "cs" + +definition + "RAG wq \ {(Th th, Cs cs) | th cs. waits wq th cs} \ {(Cs cs, Th th) | cs th. holds wq th cs}" + +definition + "dependants wq th \ {th' . (Th th', Th th) \ (RAG wq)^+}" + +record schedule_state = + wq_fun :: "cs \ thread list" + cprec_fun :: "thread \ precedence" + +definition cpreced :: "(cs \ thread list) \ state \ thread \ precedence" + where + "cpreced wq s th \ Max ({preced th s} \ {preced th' s | th'. th' \ dependants wq th})" + +abbreviation + "all_unlocked \ \_::cs. ([]::thread list)" + +abbreviation + "initial_cprec \ \_::thread. Prc 0 0" + +abbreviation + "release qs \ case qs of + [] => [] + | (_#qs) => (SOME q. distinct q \ set q = set qs)" + +fun schs :: "state \ schedule_state" + where + "schs [] = (| wq_fun = \ cs. [], cprec_fun = (\_. Prc 0 0) |)" +| "schs (Create th prio # s) = + (let wq = wq_fun (schs s) in + (|wq_fun = wq, cprec_fun = cpreced wq (Create th prio # s)|))" +| "schs (Exit th # s) = + (let wq = wq_fun (schs s) in + (|wq_fun = wq, cprec_fun = cpreced wq (Exit th # s)|))" +| "schs (Set th prio # s) = + (let wq = wq_fun (schs s) in + (|wq_fun = wq, cprec_fun = cpreced wq (Set th prio # s)|))" +| "schs (P th cs # s) = + (let wq = wq_fun (schs s) in + let new_wq = wq(cs := (wq cs @ [th])) in + (|wq_fun = new_wq, cprec_fun = cpreced new_wq (P th cs # s)|))" +| "schs (V th cs # s) = + (let wq = wq_fun (schs s) in + let new_wq = wq(cs := release (wq cs)) in + (|wq_fun = new_wq, cprec_fun = cpreced new_wq (V th cs # s)|))" + +definition wq :: "state \ cs \ thread list" + where "wq s = wq_fun (schs s)" + +definition cp :: "state \ thread \ precedence" + where "cp s \ cprec_fun (schs s)" + +definition + "holds2 s \ holds (wq_fun (schs s))" + +definition + "waits2 s \ waits (wq_fun (schs s))" + +definition + "RAG2 s \ RAG (wq_fun (schs s))" + +definition + "dependants2 s \ dependants (wq_fun (schs s))" + +definition readys :: "state \ thread set" + where "readys s \ {th . th \ threads s \ (\ cs. \ waits2 s th cs)}" + +definition runing :: "state \ thread set" + where "runing s \ {th . th \ readys s \ cp s th = Max ((cp s) ` (readys s))}" + +definition holding :: "state \ thread \ cs set" + where "holding s th \ {cs . holds2 s th cs}" + +lemma holding_RAG: + "holding s th = {cs . (Cs cs, Th th) \ RAG2 s}" +unfolding holding_def +unfolding holds2_def +unfolding RAG2_def RAG_def +unfolding holds_def waits_def +by auto + +inductive step :: "state \ event \ bool" + where + step_Create: "\th \ threads s\ \ step s (Create th prio)" +| step_Exit: "\th \ runing s; holding s th = {}\ \ step s (Exit th)" +| step_P: "\th \ runing s; (Cs cs, Th th) \ (RAG2 s)^+\ \ step s (P th cs)" +| step_V: "\th \ runing s; holds2 s th cs\ \ step s (V th cs)" +| step_Set: "\th \ runing s\ \ step s (Set th prio)" + +inductive vt :: "state \ bool" + where + vt_nil[intro]: "vt []" +| vt_cons[intro]: "\vt s; step s e\ \ vt (e#s)" + +lemma runing_ready: + shows "runing s \ readys s" + unfolding runing_def readys_def + by auto + +lemma readys_threads: + shows "readys s \ threads s" + unfolding readys_def + by auto + +lemma wq_distinct_step: + assumes "step s e" "distinct (wq s cs)" + shows "distinct (wq (e # s) cs)" +using assms +apply(induct) +apply(auto simp add: wq_def Let_def) +apply(auto simp add: wq_def Let_def RAG2_def RAG_def holds_def runing_def waits2_def waits_def readys_def)[1] +apply(auto split: list.split) +apply(rule someI2) +apply(auto) +done + +lemma wq_distinct: + assumes "vt s" + shows "distinct (wq s cs)" +using assms +apply(induct) +apply(simp add: wq_def) +apply(simp add: wq_distinct_step) +done + +lemma RAG_set_unchanged[simp]: + shows "RAG2 (Set th prio # s) = RAG2 s" +unfolding RAG2_def +by (simp add: Let_def) + +lemma RAG_create_unchanged[simp]: + "RAG2 (Create th prio # s) = RAG2 s" +unfolding RAG2_def +by (simp add: Let_def) + +lemma RAG_exit_unchanged[simp]: + shows "RAG2 (Exit th # s) = RAG2 s" +unfolding RAG2_def +by (simp add: Let_def) + +lemma RAG_p1: + assumes "wq s cs = []" + shows "RAG2 (P th cs # s) = RAG2 s \ {(Cs cs, Th th)}" + using assms + apply(auto simp add: RAG2_def RAG_def wq_def Let_def waits_def holds_def) + apply (metis in_set_insert insert_Nil list.distinct(1)) + done + +lemma RAG_p2: + assumes "vt (P th cs#s)" "wq s cs \ []" + shows "RAG2 (P th cs # s) = RAG2 s \ {(Th th, Cs cs)}" + using assms + apply(simp add: RAG2_def Let_def) + apply(erule_tac vt.cases) + apply(simp) + apply(clarify) + apply(simp) + apply(erule_tac step.cases) + apply(simp_all) + apply(simp add: wq_def RAG_def RAG2_def) + apply(simp add: waits_def holds_def) + apply(auto) + done + +definition next_th:: "state \ thread \ cs \ thread \ bool" + where "next_th s th cs t = + (\ rest. wq s cs = th#rest \ rest \ [] \ t = hd (SOME q. distinct q \ set q = set rest))" + +lemma RAG_v: +assumes vt:"vt (V th cs#s)" +shows " + RAG2 (V th cs # s) = + RAG2 s - {(Cs cs, Th th)} - + {(Th th', Cs cs) |th'. next_th s th cs th'} \ + {(Cs cs, Th th') |th'. next_th s th cs th'}" + apply (insert vt, unfold RAG2_def RAG_def) + sorry + +lemma waiting_unique: + assumes "vt s" + and "waits2 s th cs1" + and "waits2 s th cs2" + shows "cs1 = cs2" +sorry + +lemma singleton_Un: + shows "A \ {x} = insert x A" +by simp + + +lemma acyclic_RAG_step: + assumes vt: "vt s" + and stp: "step s e" + and ac: "acyclic (RAG2 s)" + shows "acyclic (RAG2 (e # s))" +using stp vt ac +proof (induct) + case (step_P th s cs) + have vt: "vt s" by fact + have ac: "acyclic (RAG2 s)" by fact + have rn: "th \ runing s" by fact + have ds: "(Cs cs, Th th) \ (RAG2 s)\<^sup>+" by fact + have vtt: "vt (P th cs#s)" using vt rn ds by (metis step.step_P vt_cons) + { assume a: "wq s cs = []" -- "case waiting queue is empty" + have "(Th th, Cs cs) \ (RAG2 s)\<^sup>*" + proof + assume "(Th th, Cs cs) \ (RAG2 s)\<^sup>*" + then have "(Th th, Cs cs) \ (RAG2 s)\<^sup>+" by (simp add: rtrancl_eq_or_trancl) + then obtain x where "(x, Cs cs) \ RAG2 s" using tranclD2 by metis + with a show False by (auto simp: RAG2_def RAG_def wq_def waits_def) + qed + with acyclic_insert ac + have "acyclic (RAG2 s \ {(Cs cs, Th th)})" by simp + then have "acyclic (RAG2 (P th cs # s))" using RAG_p1[OF a] by simp + } + moreover + { assume a: "wq s cs \ []" -- "case waiting queue is not empty" + from ds have "(Cs cs, Th th) \ (RAG2 s)\<^sup>*" by (metis node.distinct(1) rtranclD) + with acyclic_insert ac + have "acyclic (RAG2 s \ {(Th th, Cs cs)})" by auto + then have "acyclic (RAG2 (P th cs # s))" using RAG_p2[OF vtt a] by simp + } + ultimately show "acyclic (RAG2 (P th cs # s))" by metis +next + case (step_V th s cs) + have vt: "vt s" by fact + have ac: "acyclic (RAG2 s)" by fact + have rn: "th \ runing s" by fact + have hd: "holds2 s th cs" by fact + from hd + have th_in: "th \ set (wq s cs)" and + eq_hd: "th = hd (wq s cs)" unfolding holds2_def holds_def wq_def by auto + then obtain rest where + eq_wq: "wq s cs = th # rest" by (cases "wq s cs") (auto) + show ?case + apply(subst RAG_v) + apply(rule vt_cons) + apply(rule vt) + apply(rule step.step_V) + apply(rule rn) + apply(rule hd) + using eq_wq + apply(cases "rest = []") + apply(subgoal_tac "{(Cs cs, Th th') |th'. next_th s th cs th'} = {}") + apply(simp) + apply(rule acyclic_subset) + apply(rule ac) + apply(auto)[1] + apply(auto simp add: next_th_def)[1] + -- "case wq more than a singleton" + apply(subgoal_tac "{(Cs cs, Th (hd (SOME q. distinct q \ set q = set rest)))} = + {(Cs cs, Th th') |th'. next_th s th cs th'}") + apply(rotate_tac 2) + apply(drule sym) + apply(simp only: singleton_Un) + apply(simp only: acyclic_insert) + apply(rule conjI) + apply(rule acyclic_subset) + apply(rule ac) + apply(auto)[1] + apply(rotate_tac 2) + apply(thin_tac "?X") + defer + apply(simp add: next_th_def) + apply(clarify) + apply(simp add: rtrancl_eq_or_trancl) + apply(drule tranclD) + apply(erule exE) + apply(drule conjunct1) + apply(subgoal_tac "(Th (hd (SOME q. distinct q \ set q = set rest)), z) \ RAG2 s") + prefer 2 + apply(simp) + apply(case_tac z) + apply(simp add: RAG2_def RAG_def) + apply(clarify) + apply(simp) + apply(simp add: next_th_def) + apply(rule waiting_unique) + apply(rule vt) + apply(simp add: RAG2_def RAG_def waits2_def waits_def wq_def) + apply(rotate_tac 2) + apply(thin_tac "?X") + apply(subgoal_tac "distinct (wq s cs)") + prefer 2 + apply(rule wq_distinct) + apply(rule vt) + apply (unfold waits2_def waits_def wq_def, auto) + apply(subgoal_tac "(SOME q. distinct q \ set q = set rest) \ []") + prefer 2 + apply (metis (mono_tags) set_empty tfl_some) + apply(subgoal_tac "hd (SOME q. distinct q \ set q = set rest) \ + set (SOME q. distinct q \ set q = set rest)") + prefer 2 + apply(auto)[1] + apply(subgoal_tac "set (SOME q. distinct q \ set q = set rest) = set rest") + prefer 2 + apply(rule someI2) + apply(auto)[2] + apply(auto)[1] + apply(subgoal_tac "(SOME q. distinct q \ set q = set rest) \ []") + prefer 2 + apply (metis (mono_tags) set_empty tfl_some) + apply(subgoal_tac "hd (SOME q. distinct q \ set q = set rest) \ + set (SOME q. distinct q \ set q = set rest)") + prefer 2 + apply(auto)[1] + apply(subgoal_tac "set (SOME q. distinct q \ set q = set rest) = set rest") + prefer 2 + apply(rule someI2) + apply(auto)[2] + apply(auto)[1] + done +qed (simp_all) + + + + + +