theory Semantics_OpenFlow
imports List_Group Sort_Descending
  IP_Addresses.IPv4
  OpenFlow_Helpers
begin

datatype 'a flowtable_behavior = Action 'a | NoAction | Undefined

definition "option_to_ftb b \<equiv> case b of Some a \<Rightarrow> Action a | None \<Rightarrow> NoAction"
definition "ftb_to_option b \<equiv> case b of Action a \<Rightarrow> Some a | NoAction \<Rightarrow> None"

(*section\<open>OpenFlow\<close>*)

(*https://www.opennetworking.org/images/stories/downloads/sdn-resources/onf-specifications/openflow/openflow-switch-v1.5.0.pdf*)

(*"OpenFlow packets are received on an ingress port [...]. The packet ingress port is a property of the packet
throughout the OpenFlow pipeline and represents the OpenFlow port on which the packet was received
into the OpenFlow switch."
*)

(* "Packet forwarded to non-existent ports are just dropped"*)

(*we do not support egress tables (those are optional in the standard).
  we only support flow table 0 (ingress table).
  Essentially, this means, we only support one flow table and no pipelining.
  This corresponds to OpenFlow 1.0.0
*)

(*priority \<times> Match Fields \<times> instructions
 not modeled: counters, timeouts, cookie ("Not used when processing packets"), flags,
     instructions (only an output list of egress ports will be modeled)
*)

datatype ('m, 'a) flow_entry_match = OFEntry (ofe_prio: "16 word") (ofe_fields: "'m set") (ofe_action: 'a)

(* why is there curry *)
find_consts "(('a \<times> 'b) \<Rightarrow> 'c) \<Rightarrow> 'a \<Rightarrow> 'b \<Rightarrow> 'c"
(* but no "uncurry" *)
find_consts "('a \<Rightarrow> 'b \<Rightarrow> 'c) \<Rightarrow> ('a \<times> 'b) \<Rightarrow> 'c"
(* Anyway, we want this to easily construct OFEntrys from tuples *)
definition "split3 f p \<equiv> case p of (a,b,c) \<Rightarrow> f a b c"
find_consts "('a \<Rightarrow> 'b \<Rightarrow> 'c \<Rightarrow> 'd) \<Rightarrow> ('a \<times> 'b \<times> 'c) \<Rightarrow> 'd"

(*
"If there are multiple matching flow entries with the same highest priority, the selected flow entry is explicitly undefined."
OFP 1.0.0 also stated that non-wildcarded matches implicitly have the highest priority (which is gone in 1.5).
*)
(*Defined None \<longleftrightarrow> No match
  Defined (Some a) \<longleftrightarrow> Match and instruction is a
  Undefined \<longleftrightarrow> Undefined*)

type_synonym ('m, 'a) flowtable = "(('m, 'a) flow_entry_match) list"
type_synonym ('m, 'p) field_matcher = "('m set \<Rightarrow> 'p \<Rightarrow> bool)"

definition OF_same_priority_match2 :: "('m, 'p) field_matcher \<Rightarrow> ('m, 'a) flowtable \<Rightarrow> 'p \<Rightarrow> 'a flowtable_behavior" where
  "OF_same_priority_match2 \<gamma> flow_entries packet \<equiv> let s =
  	{ofe_action f|f. f \<in> set flow_entries \<and> \<gamma> (ofe_fields f) packet \<and>
  	  (\<forall>fo \<in> set flow_entries. ofe_prio fo > ofe_prio f \<longrightarrow> \<not>\<gamma> (ofe_fields fo) packet)} in
  	case card s of 0       \<Rightarrow> NoAction
                 | (Suc 0) \<Rightarrow> Action (the_elem s)
                 | _       \<Rightarrow> Undefined"

(* are there any overlaping rules? *)
definition "check_no_overlap \<gamma> ft = (\<forall>a \<in> set ft. \<forall>b \<in> set ft. \<forall>p \<in> UNIV. (ofe_prio a = ofe_prio b \<and> \<gamma> (ofe_fields a) p \<and> a \<noteq> b) \<longrightarrow> \<not>\<gamma> (ofe_fields b) p)"
definition "check_no_overlap2 \<gamma> ft = (\<forall>a \<in> set ft. \<forall>b \<in> set ft. (a \<noteq> b \<and> ofe_prio a = ofe_prio b) \<longrightarrow> \<not>(\<exists>p \<in> UNIV. \<gamma> (ofe_fields a) p \<and> \<gamma> (ofe_fields b) p))"
lemma check_no_overlap_alt: "check_no_overlap \<gamma> ft = check_no_overlap2 \<gamma> ft"
	unfolding check_no_overlap2_def check_no_overlap_def
	by blast

(* If there are no overlapping rules, our match should check out. *)
lemma no_overlap_not_unefined: "check_no_overlap \<gamma> ft \<Longrightarrow> OF_same_priority_match2 \<gamma> ft p \<noteq> Undefined"
proof
  assume goal1: "check_no_overlap \<gamma> ft" "OF_same_priority_match2 \<gamma> ft p = Undefined"
	let ?as = "{f. f \<in> set ft \<and> \<gamma> (ofe_fields f) p \<and> (\<forall>fo \<in> set ft. ofe_prio f < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)}"
	have fin: "finite ?as" by simp
	note goal1(2)[unfolded OF_same_priority_match2_def]
	then have "2 \<le> card (ofe_action ` ?as)" unfolding f_Img_ex_set
		unfolding Let_def
		by(cases "card (ofe_action ` ?as)", simp) (rename_tac nat1, case_tac nat1, simp add: image_Collect, presburger)
	then have "2 \<le> card ?as" using card_image_le[OF fin, of ofe_action] by linarith
	then obtain a b where ab: "a \<noteq> b" "a \<in> ?as" "b \<in> ?as" using card2_eI by blast
	then have ab2: "a \<in> set ft" "\<gamma> (ofe_fields a) p" "(\<forall>fo\<in>set ft. ofe_prio a < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)"
	               "b \<in> set ft" "\<gamma> (ofe_fields b) p" "(\<forall>fo\<in>set ft. ofe_prio b < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)" by simp_all
	then have "ofe_prio a = ofe_prio b"
		by fastforce
	note goal1(1)[unfolded check_no_overlap_def] ab2(1) ab2(4) this ab2(2) ab(1) ab2(5)
	then show False by blast
qed

fun OF_match_linear :: "('m, 'p) field_matcher \<Rightarrow> ('m, 'a) flowtable \<Rightarrow> 'p \<Rightarrow> 'a flowtable_behavior" where
"OF_match_linear _ [] _ = NoAction" |
"OF_match_linear \<gamma> (a#as) p = (if \<gamma> (ofe_fields a) p then Action (ofe_action a) else OF_match_linear \<gamma> as p)"

lemma OF_match_linear_ne_Undefined: "OF_match_linear \<gamma> ft p \<noteq> Undefined"
	by(induction ft) auto

lemma OF_match_linear_append: "OF_match_linear \<gamma> (a @ b) p = (case OF_match_linear \<gamma> a p of NoAction \<Rightarrow> OF_match_linear \<gamma> b p | x \<Rightarrow> x)"
by(induction a) simp_all
lemma OF_match_linear_match_allsameaction: "\<lbrakk>gr \<in> set oms; \<gamma> gr p = True\<rbrakk>
       \<Longrightarrow> OF_match_linear \<gamma> (map (\<lambda>x. split3 OFEntry (pri, x, act)) oms) p = Action act"
by(induction oms) (auto simp add: split3_def)
lemma OF_lm_noa_none_iff: "OF_match_linear \<gamma> ft p = NoAction \<longleftrightarrow> (\<forall>e\<in>set ft. \<not> \<gamma> (ofe_fields e) p)"
	by(induction ft) (simp_all split: if_splits)

lemma set_eq_rule: "(\<And>x. x \<in> a \<Longrightarrow> x \<in> b) \<Longrightarrow> (\<And>x. x \<in> b \<Longrightarrow> x \<in> a) \<Longrightarrow> a = b" by(rule antisym[OF subsetI subsetI])

lemma unmatching_insert_agnostic: "\<not> \<gamma> (ofe_fields a) p \<Longrightarrow> OF_same_priority_match2 \<gamma> (a # ft) p = OF_same_priority_match2 \<gamma> ft p"
proof -
	let ?as = "{f. f \<in> set ft \<and> \<gamma> (ofe_fields f) p \<and> (\<forall>fo \<in> set ft. ofe_prio f < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)}"
	let ?aas = "{f |f. f \<in> set (a # ft) \<and> \<gamma> (ofe_fields f) p \<and> (\<forall>fo\<in>set (a # ft). ofe_prio f < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)}"
	assume nm: "\<not> \<gamma> (ofe_fields a) p"
	have aa: "?aas = ?as"
	proof(rule set_eq_rule)
	  fix x
		assume "x \<in> {f |f. f \<in> set (a # ft) \<and> \<gamma> (ofe_fields f) p \<and> (\<forall>fo\<in>set (a # ft). ofe_prio f < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)}"
		hence as: "x \<in> set (a # ft) \<and> \<gamma> (ofe_fields x) p \<and> (\<forall>fo\<in>set (a # ft). ofe_prio x < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)" by simp
		with nm have "x \<in> set ft" by fastforce
		moreover from as have "(\<forall>fo\<in>set ft. ofe_prio x < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)" by simp
		ultimately show "x \<in> {f \<in> set ft. \<gamma> (ofe_fields f) p \<and> (\<forall>fo\<in>set ft. ofe_prio f < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)}" using as by force
	next
	  fix x
		assume "x \<in> {f \<in> set ft. \<gamma> (ofe_fields f) p \<and> (\<forall>fo\<in>set ft. ofe_prio f < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)}"
		hence as: "x \<in> set ft" "\<gamma> (ofe_fields x) p" "(\<forall>fo\<in>set ft. ofe_prio x < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)" by simp_all
		from as(1) have "x \<in> set (a # ft)" by simp
		moreover from as(3) have "(\<forall>fo\<in>set (a # ft). ofe_prio x < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)" using nm by simp
		ultimately show "x \<in> {f |f. f \<in> set (a # ft) \<and> \<gamma> (ofe_fields f) p \<and> (\<forall>fo\<in>set (a # ft). ofe_prio f < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)}" using as(2) by blast
	qed
	note uf = arg_cong[OF aa, of "(`) ofe_action", unfolded image_Collect]
	show ?thesis unfolding OF_same_priority_match2_def using uf by presburger
qed

lemma OF_match_eq: "sorted_descending (map ofe_prio ft) \<Longrightarrow> check_no_overlap \<gamma> ft \<Longrightarrow>
	OF_same_priority_match2 \<gamma> ft p = OF_match_linear \<gamma> ft p"
proof(induction "ft")
	case (Cons a ft)
	have 1: "sorted_descending (map ofe_prio ft)" using Cons(2) by simp
	have 2: "check_no_overlap \<gamma> ft" using Cons(3) unfolding check_no_overlap_def using set_subset_Cons by fast
	note mIH = Cons(1)[OF 1 2]
	show ?case (is ?kees)
	proof(cases "\<gamma> (ofe_fields a) p")
		case False thus ?kees
			by(simp only: OF_match_linear.simps if_False mIH[symmetric] unmatching_insert_agnostic[of \<gamma>, OF False])
	next
		note sorted_descending_split[OF Cons(2)]
		then obtain m n where mn: "a # ft = m @ n" "\<forall>e\<in>set m. ofe_prio a = ofe_prio e" "\<forall>e\<in>set n. ofe_prio e < ofe_prio a"
			unfolding list.sel by blast
		hence aem: "a \<in> set m"
			by (metis UnE less_imp_neq list.set_intros(1) set_append)
		have mover: "check_no_overlap \<gamma> m" using Cons(3) unfolding check_no_overlap_def
			by (metis Un_iff mn(1) set_append)
		let ?fc = "(\<lambda>s.
			{f. f \<in> set s \<and> \<gamma> (ofe_fields f) p \<and>
			(\<forall>fo\<in>set (a # ft). ofe_prio f < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)})"
		case True
		have "?fc (m @ n) = ?fc m \<union> ?fc n" by auto
		moreover have "?fc n = {}"
		proof(rule set_eq_rule, rule ccontr, goal_cases)
			case (1 x)
			hence g1: "x \<in> set n" "\<gamma> (ofe_fields x) p"
				"(\<forall>fo\<in>set m. ofe_prio x < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)"
				"(\<forall>fo\<in>set n. ofe_prio x < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)"
				unfolding mn(1) by(simp_all)
			from g1(1) mn(3) have le: "ofe_prio x < ofe_prio a" by simp
			note le g1(3) aem True
			then show False by blast
		qed simp
		ultimately have cc: "?fc (m @ n) = ?fc m" by blast
		have cm: "?fc m = {a}" (* using Cons(3) *)
		proof -
			have "\<forall>f \<in> set m. (\<forall>fo\<in>set (a # ft). ofe_prio f < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)"
				by (metis UnE less_asym mn set_append)
			hence 1: "?fc m = {f \<in> set m. \<gamma> (ofe_fields f) p}" by blast
			show "{f \<in> set m. \<gamma> (ofe_fields f) p \<and> (\<forall>fo\<in>set (a # ft). ofe_prio f < ofe_prio fo \<longrightarrow> \<not> \<gamma> (ofe_fields fo) p)} = {a} " unfolding 1
			proof(rule set_eq_rule, goal_cases fwd bwd)
				case (bwd x)
				have "a \<in> {f \<in> set m. \<gamma> (ofe_fields f) p}" using True aem by simp
				thus ?case using bwd by simp
			next
				case (fwd x) show ?case proof(rule ccontr)
					assume "x \<notin> {a}" hence ne: "x \<noteq> a" by simp
					from fwd have 1: "x \<in> set m" "\<gamma> (ofe_fields x) p" by simp_all
					have 2: "ofe_prio x = ofe_prio a" using 1(1) mn(2) by simp
					show False using 1 ne mover aem True 2 unfolding check_no_overlap_def by blast
				qed
			qed
		qed
		show ?kees
			unfolding mn(1)
			unfolding OF_same_priority_match2_def
			unfolding f_Img_ex_set
			unfolding cc[unfolded mn(1)]
			unfolding cm[unfolded mn(1)]
			unfolding Let_def
			by(simp only: mn(1)[symmetric] OF_match_linear.simps True if_True, simp)
		qed
qed (simp add: OF_same_priority_match2_def)

lemma overlap_sort_invar[simp]: "check_no_overlap \<gamma> (sort_descending_key k ft) = check_no_overlap \<gamma> ft"
	unfolding check_no_overlap_def
	unfolding sort_descending_set_inv
	..

lemma OF_match_eq2:
  assumes "check_no_overlap \<gamma> ft"
  shows "OF_same_priority_match2 \<gamma> ft p = OF_match_linear \<gamma> (sort_descending_key ofe_prio ft) p"
proof -
	have "sorted_descending (map ofe_prio (sort_descending_key ofe_prio ft))" by (simp add: sorted_descending_sort_descending_key)
	note ceq = OF_match_eq[OF this, unfolded overlap_sort_invar, OF \<open>check_no_overlap \<gamma> ft\<close>, symmetric]
	show ?thesis
		unfolding ceq
		unfolding OF_same_priority_match2_def
		unfolding sort_descending_set_inv
		..
qed

(* Just me, thinking about some alternate ways of writing this down. *)
lemma prio_match_matcher_alt: "{f. f \<in> set flow_entries \<and> \<gamma> (ofe_fields f) packet \<and>
  	  (\<forall>fo \<in> set flow_entries. ofe_prio fo > ofe_prio f \<longrightarrow> \<not>\<gamma> (ofe_fields fo) packet)}
  	  = (
  	  let matching = {f. f \<in> set flow_entries \<and> \<gamma> (ofe_fields f) packet}
  	  in {f. f \<in> matching \<and> (\<forall>fo \<in> matching. ofe_prio fo \<le> ofe_prio f)}
  	  )"
by(auto simp add: Let_def)
lemma prio_match_matcher_alt2: "(
  	  let matching = {f. f \<in> set flow_entries \<and> \<gamma> (ofe_fields f) packet}
  	  in {f. f \<in> matching \<and> (\<forall>fo \<in> matching. ofe_prio fo \<le> ofe_prio f)}
  	  ) = set (
  	  let matching = filter (\<lambda>f. \<gamma> (ofe_fields f) packet) flow_entries
  	  in filter (\<lambda>f. \<forall>fo \<in> set matching. ofe_prio fo \<le> ofe_prio f) matching
  	  )"
by(auto simp add: Let_def)

definition OF_priority_match where
  "OF_priority_match \<gamma> flow_entries packet \<equiv>
  let m  = filter (\<lambda>f. \<gamma> (ofe_fields f) packet) flow_entries;
  	  m' = filter (\<lambda>f. \<forall>fo \<in> set m. ofe_prio fo \<le> ofe_prio f) m in
  	case m' of []  \<Rightarrow> NoAction
             | [s] \<Rightarrow> Action (ofe_action s)
             |  _  \<Rightarrow> Undefined"

definition OF_priority_match_ana where
  "OF_priority_match_ana \<gamma> flow_entries packet \<equiv>
  let m  = filter (\<lambda>f. \<gamma> (ofe_fields f) packet) flow_entries;
  	  m' = filter (\<lambda>f. \<forall>fo \<in> set m. ofe_prio fo \<le> ofe_prio f) m in
  	case m' of []  \<Rightarrow> NoAction
             | [s] \<Rightarrow> Action s
             |  _  \<Rightarrow> Undefined"

lemma filter_singleton: "[x\<leftarrow>s. f x] = [y] \<Longrightarrow> f y \<and> y \<in> set s" by (metis filter_eq_Cons_iff in_set_conv_decomp)

lemma OF_spm3_get_fe: "OF_priority_match \<gamma> ft p = Action a \<Longrightarrow> \<exists>fe. ofe_action fe = a \<and> fe \<in> set ft \<and> OF_priority_match_ana \<gamma> ft p = Action fe"
	unfolding OF_priority_match_def OF_priority_match_ana_def
	by(clarsimp split: flowtable_behavior.splits list.splits) (drule filter_singleton; simp)

fun no_overlaps where
"no_overlaps _ [] = True" |
"no_overlaps \<gamma> (a#as) = (no_overlaps \<gamma> as \<and> (
	\<forall>b \<in> set as. ofe_prio a = ofe_prio b \<longrightarrow> \<not>(\<exists>p \<in> UNIV. \<gamma> (ofe_fields a) p \<and> \<gamma> (ofe_fields b) p)))"

lemma no_overlap_ConsI: "check_no_overlap2 \<gamma> (x#xs) \<Longrightarrow> check_no_overlap2 \<gamma> xs"
	unfolding check_no_overlap2_def by simp

lemma no_overlapsI: "check_no_overlap \<gamma> t \<Longrightarrow> distinct t \<Longrightarrow> no_overlaps \<gamma> t"
unfolding check_no_overlap_alt
proof(induction t)
	case (Cons a t)
	from no_overlap_ConsI[OF Cons(2)] Cons(3,1)
	have "no_overlaps \<gamma> t" by simp
	thus ?case using Cons(2,3) unfolding check_no_overlap2_def by auto
qed (simp add: check_no_overlap2_def)

lemma check_no_overlapI: "no_overlaps \<gamma> t \<Longrightarrow> check_no_overlap \<gamma> t"
unfolding check_no_overlap_alt
proof(induction t)
	case (Cons a t)
	from Cons(1)[OF conjunct1[OF Cons(2)[unfolded no_overlaps.simps]]]
	show ?case
		using conjunct2[OF Cons(2)[unfolded no_overlaps.simps]]
		unfolding check_no_overlap2_def
		by auto
qed (simp add: check_no_overlap2_def)

lemma "(\<And>e p. e \<in> set t \<Longrightarrow> \<not>\<gamma> (ofe_fields e) p) \<Longrightarrow> no_overlaps \<gamma> t"
	by(induction t) simp_all
lemma no_overlaps_append: "no_overlaps \<gamma> (x @ y) \<Longrightarrow> no_overlaps \<gamma> y"
	by(induction x) simp_all
lemma no_overlaps_ne1: "no_overlaps \<gamma> (x @ a # y @ b # z) \<Longrightarrow> ((\<exists>p. \<gamma> (ofe_fields a) p) \<or> (\<exists>p. \<gamma> (ofe_fields b) p)) \<Longrightarrow> a \<noteq> b"
proof (rule notI, goal_cases contr)
	case contr
	from contr(1) no_overlaps_append have "no_overlaps \<gamma> (a # y @ b # z)" by blast
	note this[unfolded no_overlaps.simps]
	with contr(3) have "\<not> (\<exists>p\<in>UNIV. \<gamma> (ofe_fields a) p \<and> \<gamma> (ofe_fields b) p)" by simp
	with contr(2) show False unfolding contr(3) by simp
qed

lemma no_overlaps_defeq: "no_overlaps \<gamma> fe \<Longrightarrow> OF_same_priority_match2 \<gamma> fe p = OF_priority_match \<gamma> fe p"
	unfolding OF_same_priority_match2_def OF_priority_match_def
	unfolding f_Img_ex_set
	unfolding prio_match_matcher_alt
	unfolding prio_match_matcher_alt2
proof (goal_cases uf)
	case uf
	let ?m' = "let m = [f\<leftarrow>fe . \<gamma> (ofe_fields f) p] in [f\<leftarrow>m . \<forall>fo\<in>set m. ofe_prio fo \<le> ofe_prio f]"
	let ?s = "ofe_action ` set ?m'"
	from uf show ?case
	proof(cases ?m')
		case Nil
		moreover then have "card ?s = 0" by force
		ultimately show ?thesis by(simp add: Let_def)
	next
		case (Cons a as)
		have "as = []"
		proof(rule ccontr)
			assume "as \<noteq> []"
			then obtain b bs where bbs: "as = b # bs" by (meson neq_Nil_conv)
			 note no = Cons[unfolded Let_def filter_filter]
			have f1: "a \<in> set ?m'" "b \<in> set ?m'" unfolding bbs local.Cons by simp_all
			hence "ofe_prio a = ofe_prio b" by (simp add: antisym)
			moreover have ms: "\<gamma> (ofe_fields a) p" "\<gamma> (ofe_fields b) p" using no[symmetric] unfolding bbs by(blast dest: Cons_eq_filterD)+
			moreover have abis: "a \<in> set fe" "b \<in> set fe" using f1 by auto
			moreover have "a \<noteq> b" proof(cases "\<exists>x y z. fe = x @ a # y @ b # z")
				case True
				then obtain x y z where xyz: "fe = x @ a # y @ b # z" by blast
				from no_overlaps_ne1 ms(1) uf[unfolded xyz]
				show ?thesis by blast
			next
				case False
				then obtain x y z where xyz: "fe = x @ b # y @ a # z"
					using no unfolding bbs
					by (metis (no_types, lifting) Cons_eq_filterD)
				from no_overlaps_ne1 ms(1) uf[unfolded xyz]
				show ?thesis by blast
			qed
			ultimately show False using check_no_overlapI[OF uf, unfolded check_no_overlap_def] by blast
		qed
		then have oe: "a # as = [a]" by simp
		show ?thesis using Cons[unfolded oe] by force
	qed
qed
(* the above lemma used to be this, but it's slightly weaker than I wanted. *)
lemma "distinct fe \<Longrightarrow> check_no_overlap \<gamma> fe \<Longrightarrow> OF_same_priority_match2 \<gamma> fe p = OF_priority_match \<gamma> fe p"
	by(rule no_overlaps_defeq) (drule (2) no_overlapsI)

theorem OF_eq:
	assumes no: "no_overlaps \<gamma> f"
	    and so: "sorted_descending (map ofe_prio f)"
	shows "OF_match_linear \<gamma> f p = OF_priority_match \<gamma> f p"
	unfolding no_overlaps_defeq[symmetric,OF no] OF_match_eq[OF so check_no_overlapI[OF no]]
	..

corollary OF_eq_sort:
	assumes no: "no_overlaps \<gamma> f"
	shows "OF_priority_match \<gamma> f p = OF_match_linear \<gamma> (sort_descending_key ofe_prio f) p"
	using OF_match_eq2 check_no_overlapI no no_overlaps_defeq by fastforce

lemma OF_lm_noa_none: "OF_match_linear \<gamma> ft p = NoAction \<Longrightarrow> \<forall>e\<in>set ft. \<not> \<gamma> (ofe_fields e) p"
	by(induction ft) (simp_all split: if_splits)

(* this should be provable without the overlaps assumption, but that's quite a bit harder. *)
lemma OF_spm3_noa_none:
	assumes no: "no_overlaps \<gamma> ft"
	shows "OF_priority_match \<gamma> ft p = NoAction \<Longrightarrow> \<forall>e \<in> set ft. \<not>\<gamma> (ofe_fields e) p"
unfolding OF_eq_sort[OF no] by(drule OF_lm_noa_none) simp

(* repetition of the lemma for definition 2 for definition 3 *)
lemma no_overlaps_not_unefined: "no_overlaps \<gamma> ft \<Longrightarrow> OF_priority_match \<gamma> ft p \<noteq> Undefined"
	using check_no_overlapI no_overlap_not_unefined no_overlaps_defeq by fastforce

end


section {*L\_ATS\_Isomorphism*}
theory
  L_ATS_Isomorphism

imports
  PRJ_06_06__PRE

begin

locale ATS_Isomorphism =
  GL:
  ATS_Language
  "TSstructure1 :: 'TSstructure1 \<Rightarrow> bool"
  "configurations1 :: 'TSstructure1 \<Rightarrow> 'conf1 set"
  "initial_configurations1 :: 'TSstructure1 \<Rightarrow> 'conf1 set"
  "step_labels1 :: 'TSstructure1 \<Rightarrow> 'label1 set"
  "step_relation1 :: 'TSstructure1 \<Rightarrow> 'conf1 \<Rightarrow> 'label1 \<Rightarrow> 'conf1 \<Rightarrow> bool"
  "effects1 :: 'TSstructure1 \<Rightarrow> 'event1 set"
  "marking_condition1 :: 'TSstructure1 \<Rightarrow> ('label1,'conf1)derivation \<Rightarrow> bool"
  "marked_effect1 :: 'TSstructure1 \<Rightarrow> ('label1,'conf1)derivation \<Rightarrow> 'event1 set"
  "unmarked_effect1 :: 'TSstructure1 \<Rightarrow> ('label1,'conf1)derivation \<Rightarrow> 'event1 set"
  +
  GR:
  ATS_Language
  "TSstructure2 :: 'TSstructure2 \<Rightarrow> bool"
  "configurations2 :: 'TSstructure2 \<Rightarrow> 'conf2 set"
  "initial_configurations2 :: 'TSstructure2 \<Rightarrow> 'conf2 set"
  "step_labels2 :: 'TSstructure2 \<Rightarrow> 'label2 set"
  "step_relation2 :: 'TSstructure2 \<Rightarrow> 'conf2 \<Rightarrow> 'label2 \<Rightarrow> 'conf2 \<Rightarrow> bool"
  "effects2 :: 'TSstructure2 \<Rightarrow> 'event2 set"
  "marking_condition2 :: 'TSstructure2 \<Rightarrow> ('label2,'conf2)derivation \<Rightarrow> bool"
  "marked_effect2 :: 'TSstructure2 \<Rightarrow> ('label2,'conf2)derivation \<Rightarrow> 'event2 set"
  "unmarked_effect2 :: 'TSstructure2 \<Rightarrow> ('label2,'conf2)derivation \<Rightarrow> 'event2 set"
  for
    TSstructure1 configurations1 initial_configurations1 step_labels1 step_relation1 effects1 marking_condition1 marked_effect1 unmarked_effect1 TSstructure2 configurations2 initial_configurations2 step_labels2 step_relation2 effects2 marking_condition2 marked_effect2 unmarked_effect2

+

fixes marking_configuration1 :: "'TSstructure1 \<Rightarrow> 'conf1 \<Rightarrow> bool"

fixes marking_configuration2 :: "'TSstructure2 \<Rightarrow> 'conf2 \<Rightarrow> bool"

fixes relation_TSstructure :: "'TSstructure1 \<Rightarrow> 'TSstructure2 \<Rightarrow> bool"

fixes relation_configuration :: "'TSstructure1 \<Rightarrow> 'TSstructure2 \<Rightarrow> 'conf1 \<Rightarrow> 'conf2 \<Rightarrow> bool"

fixes relation_label :: "'TSstructure1 \<Rightarrow> 'TSstructure2 \<Rightarrow> 'label1 \<Rightarrow> 'label2 \<Rightarrow> bool"

assumes AX_relation_TSstructure_closed1: "
  relation_TSstructure G1 G2
  \<Longrightarrow> TSstructure1 G1"

assumes AX_relation_TSstructure_closed2: "
  relation_TSstructure G1 G2
  \<Longrightarrow> TSstructure2 G2"

assumes AX_relation_configuration_closed1: "
  relation_TSstructure G1 G2
  \<Longrightarrow> relation_configuration G1 G2 c1 c2
  \<Longrightarrow> c1 \<in> configurations1 G1"

assumes AX_relation_configuration_closed2: "
  relation_TSstructure G1 G2
  \<Longrightarrow> relation_configuration G1 G2 c1 c2
  \<Longrightarrow> c2 \<in> configurations2 G2"

assumes AX_relation_configuration_for_initial_closed1: "
  relation_TSstructure G1 G2
  \<Longrightarrow> relation_configuration G1 G2 c1 c2
  \<Longrightarrow> c1 \<in> initial_configurations1 G1
  \<Longrightarrow> c2 \<in> initial_configurations2 G2"

assumes AX_relation_configuration_for_initial_closed2: "
  relation_TSstructure G1 G2
  \<Longrightarrow> relation_configuration G1 G2 c1 c2
  \<Longrightarrow> c2 \<in> initial_configurations2 G2
  \<Longrightarrow> c1 \<in> initial_configurations1 G1"

assumes AX_relation_label_closed1: "
  relation_TSstructure G1 G2
  \<Longrightarrow> relation_label G1 G2 e1 e2
  \<Longrightarrow> e1 \<in> step_labels1 G1"

assumes AX_relation_label_closed2: "
  relation_TSstructure G1 G2
  \<Longrightarrow> relation_label G1 G2 e1 e2
  \<Longrightarrow> e2 \<in> step_labels2 G2"

assumes AX_relation_configuration_bijection_on: "
  relation_TSstructure G1 G2
  \<Longrightarrow> bijection_on (relation_configuration G1 G2) (configurations1 G1) (configurations2 G2)"

assumes AX_relation_label_bijection_on: "
  relation_TSstructure G1 G2
  \<Longrightarrow> bijection_on (relation_label G1 G2) (step_labels1 G1) (step_labels2 G2)"

assumes AX_marking_configuration1_equivalent: "
  TSstructure1 G1
  \<Longrightarrow> GL.derivation_initial G1 d1
  \<Longrightarrow> marking_condition1 G1 d1
  \<longleftrightarrow> (\<exists>i c1. get_configuration(d1 i) = Some c1 \<and> marking_configuration1 G1 c1)"

assumes AX_marking_configuration2_equivalent: "
  TSstructure2 G2
  \<Longrightarrow> GR.derivation_initial G2 d2
  \<Longrightarrow> marking_condition2 G2 d2
  \<longleftrightarrow> (\<exists>i c2. get_configuration(d2 i) = Some c2 \<and> marking_configuration2 G2 c2)"

assumes AX_relation_configuration_preserves_marking_configuration: "
  relation_TSstructure G1 G2
  \<Longrightarrow> relation_configuration G1 G2 c1 c2
  \<Longrightarrow> marking_configuration1 G1 c1 \<longleftrightarrow> marking_configuration2 G2 c2"

assumes AX_step_preservation1: "
  relation_TSstructure G1 G2
  \<Longrightarrow> relation_configuration G1 G2 c1 c2
  \<Longrightarrow> step_relation1 G1 c1 e1 c1'
  \<Longrightarrow> relation_label G1 G2 e1 e2
  \<Longrightarrow> relation_configuration G1 G2 c1' c2'
  \<Longrightarrow> step_relation2 G2 c2 e2 c2'"

assumes AX_step_preservation2: "
  relation_TSstructure G1 G2
  \<Longrightarrow> relation_configuration G1 G2 c1 c2
  \<Longrightarrow> step_relation2 G2 c2 e2 c2'
  \<Longrightarrow> relation_label G1 G2 e1 e2
  \<Longrightarrow> relation_configuration G1 G2 c1' c2'
  \<Longrightarrow> step_relation1 G1 c1 e1 c1'"

context ATS_Isomorphism begin

lemma preserve_derivation1: "
  relation_TSstructure G1 G2
  \<Longrightarrow> GL.derivation G1 d1
  \<Longrightarrow> GL.belongs G1 d1
  \<Longrightarrow> \<exists>d2.
  GR.derivation G2 d2
  \<and> GR.belongs G2 d2
  \<and> (\<forall>i\<le>MAXval. \<forall>e1 c1.
  (d1 i = None \<longrightarrow> d2 i = None)
  \<and> (d1 i = Some (pair e1 c1) \<longrightarrow> (\<exists>e2 c2.
  d2 i = Some (pair e2 c2)
  \<and> relation_configuration G1 G2 c1 c2
  \<and> (case e1 of None \<Rightarrow> (case e2 of None \<Rightarrow> True | Some e2' \<Rightarrow> False)
  | Some e1' \<Rightarrow> (case e2 of None \<Rightarrow> False | Some e2' \<Rightarrow> relation_label G1 G2 e1' e2')
  ))))"
  apply(induct MAXval)
   apply(clarsimp)
   apply(subgoal_tac "\<exists>c1. d1 0 = Some (pair None c1)")
    prefer 2
    apply (metis GL.some_position_has_details_at_0)
   apply(clarsimp)
   apply(rename_tac c1)(*strict*)
   apply(subgoal_tac "X" for X)
    apply(rename_tac c1)(*strict*)
    prefer 2
    apply(rule_tac
      a="c1"
      in bijection_on_RT)
     apply(rename_tac c1)(*strict*)
     apply(rule AX_relation_configuration_bijection_on)
     apply(force)
    apply(rename_tac c1)(*strict*)
    apply (metis GL.belongs_configurations)
   apply(rename_tac c1)(*strict*)
   apply(clarsimp)
   apply(rename_tac c1 b)(*strict*)
   apply(rule_tac
      x="der1 b"
      in exI)
   apply(rule conjI)
    apply(rename_tac c1 b)(*strict*)
    apply(rule GR.der1_is_derivation)
   apply(rename_tac c1 b)(*strict*)
   apply(rule conjI)
    apply(rename_tac c1 b)(*strict*)
    apply(rule GR.der1_belongs)
    apply (metis)
   apply(rename_tac c1 b)(*strict*)
   apply(simp add: der1_def)
  apply(rename_tac MAXval)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d2)(*strict*)
  apply(case_tac "d1 (Suc MAXval)")
   apply(rename_tac MAXval d2)(*strict*)
   apply(rule_tac
      x="derivation_take d2 MAXval"
      in exI)
   apply(rule conjI)
    apply(rename_tac MAXval d2)(*strict*)
    apply(rule GR.derivation_take_preserves_derivation)
    apply(force)
   apply(rename_tac MAXval d2)(*strict*)
   apply(rule conjI)
    apply(rename_tac MAXval d2)(*strict*)
    apply(rule GR.derivation_take_preserves_belongs)
    apply(force)
   apply(rename_tac MAXval d2)(*strict*)
   apply(clarsimp)
   apply(rename_tac MAXval d2 i)(*strict*)
   apply(case_tac "i\<le>MAXval")
    apply(rename_tac MAXval d2 i)(*strict*)
    apply(clarsimp)
    apply(simp add: derivation_take_def)
   apply(rename_tac MAXval d2 i)(*strict*)
   apply(subgoal_tac "i=Suc MAXval")
    apply(rename_tac MAXval d2 i)(*strict*)
    prefer 2
    apply(force)
   apply(rename_tac MAXval d2 i)(*strict*)
   apply(clarsimp)
   apply(rename_tac MAXval d2)(*strict*)
   apply(simp add: derivation_take_def)
  apply(rename_tac MAXval d2 a)(*strict*)
  apply(case_tac a)
  apply(rename_tac MAXval d2 a option conf)(*strict*)
  apply(rename_tac e c)
  apply(rename_tac MAXval d2 a e c)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d2 e c)(*strict*)
  apply(case_tac e)
   apply(rename_tac MAXval d2 e c)(*strict*)
   apply(clarsimp)
   apply(rename_tac MAXval d2 c)(*strict*)
   apply(simp add: GL.derivation_def)
   apply(erule_tac
      x="Suc MAXval"
      in allE)+
   apply(clarsimp)
   apply(case_tac "d1 MAXval")
    apply(rename_tac MAXval d2 c)(*strict*)
    apply(force)
   apply(rename_tac MAXval d2 c a)(*strict*)
   apply(clarsimp)
   apply(case_tac a)
   apply(rename_tac MAXval d2 c a option conf)(*strict*)
   apply(force)
  apply(rename_tac MAXval d2 e c a)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d2 c a)(*strict*)
  apply(rename_tac e)
  apply(rename_tac MAXval d2 c e)(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac MAXval d2 c e)(*strict*)
   prefer 2
   apply(rule_tac
      a="e"
      and A="step_labels1 G1"
      in bijection_on_RT)
    apply(rename_tac MAXval d2 c e)(*strict*)
    apply(rule AX_relation_label_bijection_on)
    apply(force)
   apply(rename_tac MAXval d2 c e)(*strict*)
   apply (metis GL.belongs_step_labels)
  apply(rename_tac MAXval d2 c e)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d2 c e b)(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac MAXval d2 c e b)(*strict*)
   prefer 2
   apply(rule_tac
      a="c"
      in bijection_on_RT)
    apply(rename_tac MAXval d2 c e b)(*strict*)
    apply(rule AX_relation_configuration_bijection_on)
    apply(force)
   apply(rename_tac MAXval d2 c e b)(*strict*)
   apply (metis GL.belongs_configurations)
  apply(rename_tac MAXval d2 c e b)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d2 c e b ba)(*strict*)
  apply(rename_tac e' c')
  apply(rename_tac MAXval d2 c e e' c')(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac MAXval d2 c e e' c')(*strict*)
   prefer 2
   apply(rule_tac
      n="MAXval"
      and d="d1"
      and m="Suc MAXval"
      in GL.step_detail_before_some_position)
     apply(rename_tac MAXval d2 c e e' c')(*strict*)
     apply(force)
    apply(rename_tac MAXval d2 c e e' c')(*strict*)
    apply(force)
   apply(rename_tac MAXval d2 c e e' c')(*strict*)
   apply(force)
  apply(rename_tac MAXval d2 c e e' c')(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d2 c e e' c' e1 c1)(*strict*)
  apply(erule_tac x="MAXval" in allE')
  apply(simp (no_asm_use))
  apply(erule conjE)+
  apply(thin_tac "d1 MAXval = None \<longrightarrow> d2 MAXval = None")
  apply(erule_tac
      x="e1"
      in allE)
  apply(erule_tac
      x="c1"
      in allE)
  apply(erule impE)
   apply(rename_tac MAXval d2 c e e' c' e1 c1)(*strict*)
   apply(clarsimp)
  apply(rename_tac MAXval d2 c e e' c' e1 c1)(*strict*)
  apply(erule exE)+
  apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
  apply(clarsimp)
  apply(subgoal_tac "X" for X)
   apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
   prefer 2
   apply(rule_tac
      ?c1.0="c1"
      and c1'="c"
      and c2'="c'"
      and ?e1.0="e"
      and ?e2.0="e'"
      in AX_step_preservation1)
       apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
       apply(force)
      apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
      apply(force)
     apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
     apply(force)
    apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
    apply(force)
   apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
   apply(force)
  apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
  apply(rule_tac
      x="derivation_append d2 (der2 c2 e' c') MAXval"
      in exI)
  apply(rule context_conjI)
   apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
   apply(rule GR.derivation_append_preserves_derivation)
     apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
     apply(force)
    apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
    apply(rule GR.der2_is_derivation)
    apply(force)
   apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
   apply(clarsimp)
   apply(simp add: der2_def)
  apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
  apply(rule conjI)
   apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
   apply(rule GR.derivation_append_preserves_belongs)
     apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
     apply (metis AX_relation_TSstructure_closed2)
    apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
    apply(force)
   apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
   apply(force)
  apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2 i)(*strict*)
  apply(case_tac "i\<le>MAXval")
   apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2 i)(*strict*)
   apply(clarsimp)
   apply(erule_tac
      x="i"
      in allE)
   apply(clarsimp)
   apply(rule conjI)
    apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2 i)(*strict*)
    apply(clarsimp)
    apply(simp add: derivation_append_def)
   apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2 i)(*strict*)
   apply(clarsimp)
   apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2 i e1a c1a e2a c2a)(*strict*)
   apply(simp add: derivation_append_def)
  apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2 i)(*strict*)
  apply(subgoal_tac "i=Suc MAXval")
   apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2 i)(*strict*)
   prefer 2
   apply(force)
  apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2 i)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d2 c e e' c' e1 c1 e2 c2)(*strict*)
  apply(simp add: derivation_append_def der2_def)
  done

lemma preserve_initial_derivation1: "
  relation_TSstructure G1 G2
  \<Longrightarrow> GL.derivation_initial G1 d1
  \<Longrightarrow> \<exists>d2.
  GR.derivation_initial G2 d2
  \<and> (\<forall>i\<le>MAXval. \<forall>e1 c1.
  (d1 i = None \<longrightarrow> d2 i = None)
  \<and> (d1 i = Some (pair e1 c1) \<longrightarrow> (\<exists>e2 c2.
  d2 i = Some (pair e2 c2)
  \<and> relation_configuration G1 G2 c1 c2
  \<and> (case e1 of None \<Rightarrow> (case e2 of None \<Rightarrow> True | Some e2' \<Rightarrow> False)
  | Some e1' \<Rightarrow> (case e2 of None \<Rightarrow> False | Some e2' \<Rightarrow> relation_label G1 G2 e1' e2')
  ))))"
  apply(subgoal_tac "X" for X)
   prefer 2
   apply(rule_tac
      MAXval="MAXval"
      in preserve_derivation1)
     apply(force)
    apply(simp add: GL.derivation_initial_def)
    apply(force)
   apply(rule GL.derivation_initial_belongs)
    apply (metis AX_relation_TSstructure_closed1)
   apply(force)
  apply(clarsimp)
  apply(rename_tac d2)(*strict*)
  apply(rule_tac
      x="d2"
      in exI)
  apply(clarsimp)
  apply(rule GR.derivation_initialI)
   apply(rename_tac d2)(*strict*)
   apply(force)
  apply(rename_tac d2)(*strict*)
  apply(erule_tac
      x="0"
      in allE)
  apply(clarsimp)
  apply(rename_tac d2 c y)(*strict*)
  apply(simp add: get_configuration_def)
  apply(case_tac y)
  apply(rename_tac d2 c y option conf)(*strict*)
  apply(rename_tac e c)
  apply(rename_tac d2 ca y e c)(*strict*)
  apply(clarsimp)
  apply(rename_tac d2 ca e c)(*strict*)
  apply(case_tac e)
   apply(rename_tac d2 ca e c)(*strict*)
   prefer 2
   apply(rename_tac d2 ca e c a)(*strict*)
   apply(simp add: GL.derivation_initial_def GL.derivation_def)
  apply(rename_tac d2 ca e c)(*strict*)
  apply(clarsimp)
  apply(rename_tac d2 ca c)(*strict*)
  apply(simp add: GL.derivation_initial_def)
  apply(clarsimp)
  apply(rule AX_relation_configuration_for_initial_closed1)
    apply(rename_tac d2 ca c)(*strict*)
    apply(force)
   apply(rename_tac d2 ca c)(*strict*)
   apply(force)
  apply(rename_tac d2 ca c)(*strict*)
  apply(force)
  done

lemma preserve_derivation2: "
  relation_TSstructure G1 G2
  \<Longrightarrow> GR.derivation G2 d2
  \<Longrightarrow> GR.belongs G2 d2
  \<Longrightarrow> \<exists>d1.
  GL.derivation G1 d1
  \<and> GL.belongs G1 d1
  \<and> (\<forall>i\<le>MAXval. \<forall>e2 c2.
  (d2 i = None \<longrightarrow> d1 i = None)
  \<and> (d2 i = Some (pair e2 c2) \<longrightarrow> (\<exists>e1 c1.
  d1 i = Some (pair e1 c1)
  \<and> relation_configuration G1 G2 c1 c2
  \<and> (case e2 of None \<Rightarrow> (case e1 of None \<Rightarrow> True | Some e1' \<Rightarrow> False)
  | Some e2' \<Rightarrow> (case e1 of None \<Rightarrow> False | Some e1' \<Rightarrow> relation_label G1 G2 e1' e2')
  ))))"
  apply(induct MAXval)
   apply(clarsimp)
   apply(subgoal_tac "\<exists>c1. d2 0 = Some (pair None c1)")
    prefer 2
    apply (metis GR.some_position_has_details_at_0)
   apply(clarsimp)
   apply(rename_tac c1)(*strict*)
   apply(subgoal_tac "X" for X)
    apply(rename_tac c1)(*strict*)
    prefer 2
    apply(rule_tac
      b="c1"
      in bijection_on_LT)
     apply(rename_tac c1)(*strict*)
     apply(rule AX_relation_configuration_bijection_on)
     apply(force)
    apply(rename_tac c1)(*strict*)
    apply (metis GR.belongs_configurations)
   apply(rename_tac c1)(*strict*)
   apply(clarsimp)
   apply(rename_tac c1 a)(*strict*)
   apply(rule_tac
      x="der1 a"
      in exI)
   apply(rule conjI)
    apply(rename_tac c1 a)(*strict*)
    apply(rule GL.der1_is_derivation)
   apply(rename_tac c1 a)(*strict*)
   apply(rule conjI)
    apply(rename_tac c1 a)(*strict*)
    apply(rule GL.der1_belongs)
    apply (metis)
   apply(rename_tac c1 a)(*strict*)
   apply(simp add: der1_def)
  apply(rename_tac MAXval)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d1)(*strict*)
  apply(case_tac "d2 (Suc MAXval)")
   apply(rename_tac MAXval d1)(*strict*)
   apply(rule_tac
      x="derivation_take d1 MAXval"
      in exI)
   apply(rule conjI)
    apply(rename_tac MAXval d1)(*strict*)
    apply(rule GL.derivation_take_preserves_derivation)
    apply(force)
   apply(rename_tac MAXval d1)(*strict*)
   apply(rule conjI)
    apply(rename_tac MAXval d1)(*strict*)
    apply(rule GL.derivation_take_preserves_belongs)
    apply(force)
   apply(rename_tac MAXval d1)(*strict*)
   apply(clarsimp)
   apply(rename_tac MAXval d1 i)(*strict*)
   apply(case_tac "i\<le>MAXval")
    apply(rename_tac MAXval d1 i)(*strict*)
    apply(clarsimp)
    apply(simp add: derivation_take_def)
   apply(rename_tac MAXval d1 i)(*strict*)
   apply(subgoal_tac "i=Suc MAXval")
    apply(rename_tac MAXval d1 i)(*strict*)
    prefer 2
    apply(force)
   apply(rename_tac MAXval d1 i)(*strict*)
   apply(clarsimp)
   apply(rename_tac MAXval d1)(*strict*)
   apply(simp add: derivation_take_def)
  apply(rename_tac MAXval d1 a)(*strict*)
  apply(case_tac a)
  apply(rename_tac MAXval d1 a option conf)(*strict*)
  apply(rename_tac e c)
  apply(rename_tac MAXval d1 a e c)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d1 e c)(*strict*)
  apply(case_tac e)
   apply(rename_tac MAXval d1 e c)(*strict*)
   apply(clarsimp)
   apply(rename_tac MAXval d1 c)(*strict*)
   apply(simp add: GR.derivation_def)
   apply(erule_tac
      x="Suc MAXval"
      in allE)+
   apply(clarsimp)
   apply(case_tac "d2 MAXval")
    apply(rename_tac MAXval d1 c)(*strict*)
    apply(force)
   apply(rename_tac MAXval d1 c a)(*strict*)
   apply(clarsimp)
   apply(case_tac a)
   apply(rename_tac MAXval d1 c a option conf)(*strict*)
   apply(force)
  apply(rename_tac MAXval d1 e c a)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d1 c a)(*strict*)
  apply(rename_tac e)
  apply(rename_tac MAXval d1 c e)(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac MAXval d1 c e)(*strict*)
   prefer 2
   apply(rule_tac
      b="e"
      and A="step_labels1 G1"
      in bijection_on_LT)
    apply(rename_tac MAXval d1 c e)(*strict*)
    apply(rule AX_relation_label_bijection_on)
    apply(force)
   apply(rename_tac MAXval d1 c e)(*strict*)
   apply (metis GR.belongs_step_labels)
  apply(rename_tac MAXval d1 c e)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d1 c e a)(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac MAXval d1 c e a)(*strict*)
   prefer 2
   apply(rule_tac
      b="c"
      in bijection_on_LT)
    apply(rename_tac MAXval d1 c e a)(*strict*)
    apply(rule AX_relation_configuration_bijection_on)
    apply(force)
   apply(rename_tac MAXval d1 c e a)(*strict*)
   apply (metis GR.belongs_configurations)
  apply(rename_tac MAXval d1 c e a)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d1 c e a aa)(*strict*)
  apply(rename_tac e' c')
  apply(rename_tac MAXval d1 c e e' c')(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac MAXval d1 c e e' c')(*strict*)
   prefer 2
   apply(rule_tac
      n="MAXval"
      and d="d2"
      and m="Suc MAXval"
      in GR.step_detail_before_some_position)
     apply(rename_tac MAXval d1 c e e' c')(*strict*)
     apply(force)
    apply(rename_tac MAXval d1 c e e' c')(*strict*)
    apply(force)
   apply(rename_tac MAXval d1 c e e' c')(*strict*)
   apply(force)
  apply(rename_tac MAXval d1 c e e' c')(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d1 c e e' c' e1 c1)(*strict*)
  apply(erule_tac x="MAXval" in allE')
  apply(simp (no_asm_use))
  apply(erule conjE)+
  apply(thin_tac "d2 MAXval = None \<longrightarrow> d1 MAXval = None")
  apply(erule_tac
      x="e1"
      in allE)
  apply(erule_tac
      x="c1"
      in allE)
  apply(erule impE)
   apply(rename_tac MAXval d1 c e e' c' e1 c1)(*strict*)
   apply(clarsimp)
  apply(rename_tac MAXval d1 c e e' c' e1 c1)(*strict*)
  apply(erule exE)+
  apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
  apply(clarsimp)
  apply(subgoal_tac "X" for X)
   apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
   prefer 2
   apply(rule_tac
      ?c2.0="c1"
      and c2'="c"
      and c1'="c'"
      and ?e2.0="e"
      and ?e1.0="e'"
      in AX_step_preservation2)
       apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
       apply(force)
      apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
      apply(force)
     apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
     apply(force)
    apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
    apply(force)
   apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
   apply(force)
  apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
  apply(rule_tac
      x="derivation_append d1 (der2 c1a e' c') MAXval"
      in exI)
  apply(rule context_conjI)
   apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
   apply(rule GL.derivation_append_preserves_derivation)
     apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
     apply(force)
    apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
    apply(rule GL.der2_is_derivation)
    apply(force)
   apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
   apply(clarsimp)
   apply(simp add: der2_def)
  apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
  apply(rule conjI)
   apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
   apply(rule GL.derivation_append_preserves_belongs)
     apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
     apply (metis AX_relation_TSstructure_closed1)
    apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
    apply(force)
   apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
   apply(force)
  apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a i)(*strict*)
  apply(case_tac "i\<le>MAXval")
   apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a i)(*strict*)
   apply(clarsimp)
   apply(erule_tac
      x="i"
      in allE)
   apply(clarsimp)
   apply(rule conjI)
    apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a i)(*strict*)
    apply(clarsimp)
    apply(simp add: derivation_append_def)
   apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a i)(*strict*)
   apply(clarsimp)
   apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a i e2 c2 e1b c1b)(*strict*)
   apply(simp add: derivation_append_def)
  apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a i)(*strict*)
  apply(subgoal_tac "i=Suc MAXval")
   apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a i)(*strict*)
   prefer 2
   apply(force)
  apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a i)(*strict*)
  apply(clarsimp)
  apply(rename_tac MAXval d1 c e e' c' e1 c1 e1a c1a)(*strict*)
  apply(simp add: derivation_append_def der2_def)
  done

lemma preserve_initial_derivation2: "
  relation_TSstructure G1 G2
  \<Longrightarrow> GR.derivation_initial G2 d2
  \<Longrightarrow> \<exists>d1.
  GL.derivation_initial G1 d1
  \<and> (\<forall>i\<le>MAXval. \<forall>e2 c2.
  (d2 i = None \<longrightarrow> d1 i = None)
  \<and> (d2 i = Some (pair e2 c2) \<longrightarrow> (\<exists>e1 c1.
  d1 i = Some (pair e1 c1)
  \<and> relation_configuration G1 G2 c1 c2
  \<and> (case e2 of None \<Rightarrow> (case e1 of None \<Rightarrow> True | Some e1' \<Rightarrow> False)
  | Some e2' \<Rightarrow> (case e1 of None \<Rightarrow> False | Some e1' \<Rightarrow> relation_label G1 G2 e1' e2')
  ))))"
  apply(subgoal_tac "X" for X)
   prefer 2
   apply(rule_tac
      MAXval="MAXval"
      in preserve_derivation2)
     apply(force)
    apply(simp add: GR.derivation_initial_def)
    apply(force)
   apply(rule GR.derivation_initial_belongs)
    apply (metis AX_relation_TSstructure_closed2)
   apply(force)
  apply(clarsimp)
  apply(rename_tac d1)(*strict*)
  apply(rule_tac
      x="d1"
      in exI)
  apply(clarsimp)
  apply(rule GL.derivation_initialI)
   apply(rename_tac d1)(*strict*)
   apply(force)
  apply(rename_tac d1)(*strict*)
  apply(erule_tac
      x="0"
      in allE)
  apply(clarsimp)
  apply(rename_tac d1 c y)(*strict*)
  apply(simp add: get_configuration_def)
  apply(case_tac y)
  apply(rename_tac d1 c y option conf)(*strict*)
  apply(rename_tac e c)
  apply(rename_tac d1 ca y e c)(*strict*)
  apply(clarsimp)
  apply(rename_tac d1 ca e c)(*strict*)
  apply(case_tac e)
   apply(rename_tac d1 ca e c)(*strict*)
   prefer 2
   apply(rename_tac d1 ca e c a)(*strict*)
   apply(simp add: GR.derivation_initial_def GL.derivation_def)
  apply(rename_tac d1 ca e c)(*strict*)
  apply(clarsimp)
  apply(rename_tac d1 ca c)(*strict*)
  apply(simp add: GR.derivation_initial_def)
  apply(clarsimp)
  apply(rule AX_relation_configuration_for_initial_closed2)
    apply(rename_tac d1 ca c)(*strict*)
    apply(force)
   apply(rename_tac d1 ca c)(*strict*)
   apply(force)
  apply(rename_tac d1 ca c)(*strict*)
  apply(force)
  done

theorem is_forward_edge_deterministic_accessible_preservation: "
  relation_TSstructure G1 G2
  \<Longrightarrow> GL.is_forward_edge_deterministic_accessible G1
  \<Longrightarrow> GR.is_forward_edge_deterministic_accessible G2"
  apply(simp add: GR.is_forward_edge_deterministic_accessible_def GR.get_accessible_configurations_def)
  apply(clarsimp)
  apply(rename_tac c d c1 c2 e1 e2 i)(*strict*)
  apply(simp add: get_configuration_def)
  apply(case_tac "d i")
   apply(rename_tac c d c1 c2 e1 e2 i)(*strict*)
   apply(clarsimp)
  apply(rename_tac c d c1 c2 e1 e2 i a)(*strict*)
  apply(clarsimp)
  apply(case_tac a)
  apply(rename_tac c d c1 c2 e1 e2 i a option conf)(*strict*)
  apply(clarsimp)
  apply(rename_tac c d c1 c2 e1 e2 i option)(*strict*)
  apply(rename_tac e)
  apply(rename_tac c d c1 c2 e1 e2 i e)(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac c d c1 c2 e1 e2 i e)(*strict*)
   prefer 2
   apply(rule_tac
      MAXval="i"
      in preserve_initial_derivation2)
    apply(rename_tac c d c1 c2 e1 e2 i e)(*strict*)
    apply(force)
   apply(rename_tac c d c1 c2 e1 e2 i e)(*strict*)
   apply(force)
  apply(rename_tac c d c1 c2 e1 e2 i e)(*strict*)
  apply(clarsimp)
  apply(rename_tac c d c1 c2 e1 e2 i e d1)(*strict*)
  apply(simp add: GL.is_forward_edge_deterministic_accessible_def GL.get_accessible_configurations_def)
  apply(erule_tac
      x="i"
      in allE)
  apply(clarsimp)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a)(*strict*)
  apply(erule_tac
      x="c1a"
      in allE)
  apply(erule impE)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a)(*strict*)
   apply(simp add: get_configuration_def)
   apply(rule_tac
      x="d1"
      in exI)
   apply(clarsimp)
   apply(rule_tac
      x="i"
      in exI)
   apply(clarsimp)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a)(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a)(*strict*)
   prefer 2
   apply(rule_tac
      b="e1"
      and B="step_labels2 G2"
      in bijection_on_LT)
    apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a)(*strict*)
    apply(rule AX_relation_label_bijection_on)
    apply(force)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a)(*strict*)
   apply(rule GR.AX_step_relation_preserves_belongsE)
     apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a)(*strict*)
     apply(rule AX_relation_TSstructure_closed2)
     apply(force)
    apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a)(*strict*)
    apply(force)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a)(*strict*)
   apply (metis AX_relation_configuration_closed2)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a)(*strict*)
  apply(clarsimp)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a a)(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a a)(*strict*)
   prefer 2
   apply(rule_tac
      b="e2"
      and B="step_labels2 G2"
      in bijection_on_LT)
    apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a a)(*strict*)
    apply(rule AX_relation_label_bijection_on)
    apply(force)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a a)(*strict*)
   apply(rule GR.AX_step_relation_preserves_belongsE)
     apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a a)(*strict*)
     apply(rule AX_relation_TSstructure_closed2)
     apply(force)
    apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a a)(*strict*)
    apply(force)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a a)(*strict*)
   apply (metis AX_relation_configuration_closed2)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a a)(*strict*)
  apply(clarsimp)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a a aa)(*strict*)
  apply(rename_tac e1' e2')
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2')(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2')(*strict*)
   prefer 2
   apply(rule_tac
      b="c1"
      and B="configurations2 G2"
      in bijection_on_LT)
    apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2')(*strict*)
    apply(rule AX_relation_configuration_bijection_on)
    apply(force)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2')(*strict*)
   apply (metis GR.AX_step_relation_preserves_belongsC AX_relation_configuration_closed2 AX_relation_TSstructure_closed2)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2')(*strict*)
  apply(clarsimp)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' a)(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' a)(*strict*)
   prefer 2
   apply(rule_tac
      b="c2"
      and B="configurations2 G2"
      in bijection_on_LT)
    apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' a)(*strict*)
    apply(rule AX_relation_configuration_bijection_on)
    apply(force)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' a)(*strict*)
   apply (metis GR.AX_step_relation_preserves_belongsC AX_relation_configuration_closed2 AX_relation_TSstructure_closed2)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' a)(*strict*)
  apply(clarsimp)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' a aa)(*strict*)
  apply(rename_tac c1' c2')
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
  apply(erule_tac
      x="c1'"
      in allE)
  apply(erule_tac
      x="c2'"
      in allE)
  apply(erule_tac
      x="e1'"
      in allE)
  apply(erule_tac
      x="e2'"
      in allE)
  apply(erule impE)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
   apply(rule conjI)
    apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
    apply(rule_tac
      ?c2.0="c"
      in AX_step_preservation2)
        apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
        apply(force)
       apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
       apply(force)
      apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
      apply(force)
     apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
     apply(force)
    apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
    apply(force)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
   apply(rule_tac
      ?c2.0="c"
      and c2'="c2"
      in AX_step_preservation2)
       apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
       apply(force)
      apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
      apply(force)
     apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
     apply(force)
    apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
    apply(force)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
   apply(force)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
  apply(rule_tac
      a="e1'"
      and ?b1.0="e1"
      and ?b2.0="e2"
      in bijection_on_RU)
       apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
       apply(rule AX_relation_label_bijection_on)
       apply(force)
      apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
      apply(force)
     apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
     apply (metis AX_relation_label_closed2)
    apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
    apply (metis AX_relation_label_closed2)
   apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
   apply(force)
  apply(rename_tac c d c1 c2 e1 e2 i e d1 e1a c1a e1' e2' c1' c2')(*strict*)
  apply(force)
  done

theorem Nonblockingness_branching_preservation: "
  relation_TSstructure G1 G2
  \<Longrightarrow> GL.Nonblockingness_branching G1
  \<Longrightarrow> GR.Nonblockingness_branching G2"
  apply(simp add: GR.Nonblockingness_branching_def)
  apply(clarsimp)
  apply(rename_tac dh n)(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac dh n)(*strict*)
   prefer 2
   apply(rule_tac
      MAXval="Suc n"
      in preserve_initial_derivation2)
    apply(rename_tac dh n)(*strict*)
    apply(force)
   apply(rename_tac dh n)(*strict*)
   apply(force)
  apply(rename_tac dh n)(*strict*)
  apply(clarsimp)
  apply(rename_tac dh n d1)(*strict*)
  apply(simp add: GL.Nonblockingness_branching_def maximum_of_domain_def)
  apply(erule_tac
      x="d1"
      in allE)
  apply(clarsimp)
  apply(rename_tac dh n d1 y)(*strict*)
  apply(case_tac y)
  apply(rename_tac dh n d1 y option conf)(*strict*)
  apply(clarsimp)
  apply(rename_tac dh n d1 option conf)(*strict*)
  apply(rename_tac e1 c1)
  apply(rename_tac dh n d1 e1 c1)(*strict*)
  apply(erule_tac
      x="n"
      and P="\<lambda>n. (\<exists>y. d1 n = Some y) \<and> d1 (Suc n) = None \<longrightarrow> (\<exists>dc. ATS.derivation step_relation1 G1 dc \<and> ATS.belongs configurations1 step_labels1 G1 dc \<and> (\<exists>n'. (\<exists>y. dc n' = Some y) \<and> dc (Suc n') = None \<and> derivation_append_fit d1 dc n \<and> marking_condition1 G1 (derivation_append d1 dc n)))"
      in allE)
  apply(erule impE)
   apply(rename_tac dh n d1 e1 c1)(*strict*)
   apply(rule conjI)
    apply(rename_tac dh n d1 e1 c1)(*strict*)
    apply(erule_tac
      x="n"
      in allE)
    apply(force)
   apply(rename_tac dh n d1 e1 c1)(*strict*)
   apply(erule_tac
      x="Suc n"
      in allE)
   apply(force)
  apply(rename_tac dh n d1 e1 c1)(*strict*)
  apply(erule_tac x="n" in allE')
  apply(clarsimp)
  apply(rename_tac dh n d1 e1 c1 dc n' y)(*strict*)
  apply(case_tac y)
  apply(rename_tac dh n d1 e1 c1 dc n' y option conf)(*strict*)
  apply(clarsimp)
  apply(rename_tac dh n d1 e1 c1 dc n' option conf)(*strict*)
  apply(rename_tac e2 c2)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
  apply(subgoal_tac "X" for X)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
   prefer 2
   apply(rule_tac
      ?G1.0="G1"
      and ?d1.0="(derivation_append d1 dc n)"
      in AX_marking_configuration1_equivalent)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
    apply(rule AX_relation_TSstructure_closed1)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
   apply(rule GL.derivation_append_preserves_derivation_initial)
     apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
     apply(rule AX_relation_TSstructure_closed1)
     apply(force)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
   apply(rule GL.derivation_append_preserves_derivation)
     apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
     apply(simp add: GL.derivation_initial_def)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
   apply(case_tac "d1 n")
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
    apply(clarsimp)
    apply(erule_tac
      x="n"
      in allE)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 a)(*strict*)
   apply(clarsimp)
   apply(case_tac a)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 a option conf)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 option conf)(*strict*)
   apply(case_tac "dc 0")
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 option conf)(*strict*)
    apply(clarsimp)
    apply(simp add: GL.derivation_def)
    apply(erule_tac
      x="0"
      in allE)+
    apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 option conf a)(*strict*)
   apply(clarsimp)
   apply(case_tac a)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 option conf a optiona confa)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 option conf optiona confa)(*strict*)
   apply(case_tac optiona)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 option conf optiona confa)(*strict*)
    apply(clarsimp)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 option conf confa)(*strict*)
    apply(simp add: derivation_append_fit_def)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 option conf optiona confa a)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 option conf confa a)(*strict*)
   apply(simp add: GL.derivation_def)
   apply(erule_tac
      x="0"
      in allE)+
   apply(clarsimp)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
  apply(subgoal_tac "(\<exists>i c1. get_configuration (derivation_append d1 dc n i) = Some c1 \<and> marking_configuration1 G1 c1)")
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
   prefer 2
   apply(force)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2)(*strict*)
  apply(thin_tac "marking_condition1 G1 (derivation_append d1 dc n)")
  apply(thin_tac "marking_condition1 G1 (derivation_append d1 dc n) = (\<exists>i c1. get_configuration (derivation_append d1 dc n i) = Some c1 \<and> marking_configuration1 G1 c1)")
  apply(clarsimp)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 i c1a)(*strict*)
  apply(case_tac "i\<le>n")
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 i c1a)(*strict*)
   apply(subgoal_tac "\<exists>j. i+j=n")
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 i c1a)(*strict*)
    prefer 2
    apply(rule_tac
      x="n-i"
      in exI)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 i c1a)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j)(*strict*)
   apply(erule_tac
      x="i"
      in allE)
   apply(clarsimp)
   apply(subgoal_tac "X" for X)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j)(*strict*)
    prefer 2
    apply(rule_tac
      g="dh"
      and n="i"
      and m="i+j"
      in GR.pre_some_position_is_some_position)
      apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j)(*strict*)
      apply(simp add: GR.derivation_initial_def)
      apply(force)
     apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j)(*strict*)
     apply(force)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j)(*strict*)
    apply(force)
   apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
   apply(rule_tac
      x="der1 c1"
      in exI)
   apply(rule conjI)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
    apply(rule GR.der1_is_derivation)
   apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
   apply(rule conjI)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
    apply(rule GR.der1_belongs)
    apply (metis (full_types) GR.derivation_initial_configurations AX_relation_TSstructure_closed2)
   apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
   apply(rule conjI)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
    apply(rule_tac
      x="0"
      in exI)
    apply(simp add: maximum_of_domain_def der1_def)
   apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
   apply(rule conjI)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
    apply(simp add: derivation_append_fit_def der1_def)
   apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
   apply(rule_tac
      t="marking_condition2 G2 (derivation_append dh (der1 c1) (i + j))"
      in ssubst)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
    apply(rule AX_marking_configuration2_equivalent)
     apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
     apply(rule AX_relation_TSstructure_closed2)
     apply(force)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
    apply(rule GR.derivation_append_preserves_derivation_initial)
      apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
      apply(rule AX_relation_TSstructure_closed2)
      apply(force)
     apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
     apply(force)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
    apply(rule GR.derivation_append_preserves_derivation)
      apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
      apply(simp add: GR.derivation_initial_def)
     apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
     apply(rule GR.der1_is_derivation)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
    apply(clarsimp)
    apply(simp add: der1_def)
   apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
   apply(rule_tac
      x="i"
      in exI)
   apply(simp add: derivation_append_def get_configuration_def)
   apply(rule_tac
      P="\<lambda>X. X"
      in subst)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
    apply(rule AX_relation_configuration_preserves_marking_configuration)
     apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
     apply(force)
    apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
    apply(force)
   apply(rename_tac dh d1 e1 c1 dc n' e2 c2 i c1a j e c e1a c1b)(*strict*)
   apply(simp add: get_configuration_def derivation_append_def)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 i c1a)(*strict*)
  apply(subgoal_tac "n<i")
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 i c1a)(*strict*)
   prefer 2
   apply(force)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 i c1a)(*strict*)
  apply(subgoal_tac "\<exists>j. n+Suc j=i")
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 i c1a)(*strict*)
   prefer 2
   apply(rule_tac
      x="i-Suc n"
      in exI)
   apply(force)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 i c1a)(*strict*)
  apply(clarsimp)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j)(*strict*)
  apply(subgoal_tac "\<exists>e. dc (Suc j) = Some (pair e c1a)")
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j)(*strict*)
   prefer 2
   apply(simp add: derivation_append_def get_configuration_def)
   apply(case_tac "dc (Suc j)")
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j)(*strict*)
    apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j a)(*strict*)
   apply(clarsimp)
   apply(case_tac a)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j a option conf)(*strict*)
   apply(force)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j)(*strict*)
  apply(clarsimp)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e)(*strict*)
  apply(thin_tac "get_configuration (derivation_append d1 dc n (Suc (n + j))) = Some c1a")
  apply(subgoal_tac "X" for X)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e)(*strict*)
   prefer 2
   apply(rule_tac
      ?d1.0="dc"
      and MAXval="Suc n'"
      in preserve_derivation1)
     apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e)(*strict*)
     apply(force)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e)(*strict*)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e)(*strict*)
   apply(force)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e)(*strict*)
  apply(clarsimp)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
  apply(rule_tac
      x="d2"
      in exI)
  apply(clarsimp)
  apply(rule conjI)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
   apply(rule_tac
      x="n'"
      in exI)
   apply(simp add: maximum_of_domain_def)
   apply(erule_tac
      x="n'"
      in allE)+
   apply(clarsimp)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
  apply(rule conjI)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
   apply(simp add: derivation_append_fit_def)
   apply(case_tac "d2 0")
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
    apply(clarsimp)
    apply(simp add: GR.derivation_def GL.derivation_def)
    apply(erule_tac
      x="0"
      in allE)+
    apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 a)(*strict*)
   apply(clarsimp)
   apply(case_tac a)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 a option conf)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 option conf)(*strict*)
   apply(case_tac option)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 option conf)(*strict*)
    prefer 2
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 option conf a)(*strict*)
    apply(clarsimp)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf a)(*strict*)
    apply(simp add: GR.derivation_def GL.derivation_def)
    apply(erule_tac
      x="0"
      in allE)+
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 option conf)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf)(*strict*)
   apply(erule_tac
      x="n"
      in allE)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a c1b)(*strict*)
   apply(erule_tac
      x="0"
      in allE)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a c1b y)(*strict*)
   apply(case_tac y)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a c1b y option confa)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a c1b option confa)(*strict*)
   apply(case_tac option)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a c1b option confa)(*strict*)
    apply(simp add: GR.derivation_def GL.derivation_def)
    apply(erule_tac
      x="0"
      in allE)+
    apply(clarsimp)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a confa)(*strict*)
    apply(rule_tac
      a="confa"
      in bijection_on_RU)
         apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a confa)(*strict*)
         apply(rule AX_relation_configuration_bijection_on)
         apply(force)
        apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a confa)(*strict*)
        apply (metis AX_relation_configuration_closed1)
       apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a confa)(*strict*)
       apply (metis AX_relation_configuration_closed2)
      apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a confa)(*strict*)
      apply (metis AX_relation_configuration_closed2)
     apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a confa)(*strict*)
     apply(force)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a confa)(*strict*)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 conf e1a c1b option confa a)(*strict*)
   apply(clarsimp)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
  apply(rule_tac
      P="\<lambda>x. x"
      in ssubst)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
   apply(rule AX_marking_configuration2_equivalent)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
    apply(rule AX_relation_TSstructure_closed2)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
   apply(rule GR.derivation_append_preserves_derivation_initial)
     apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
     apply(rule AX_relation_TSstructure_closed2)
     apply(force)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
   apply(rule GR.derivation_append_preserves_derivation)
     apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
     apply(simp add: GR.derivation_initial_def)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
   apply(simp add: derivation_append_fit_def)
   apply(erule_tac
      x="n"
      in allE)
   apply(erule_tac
      x="0"
      in allE)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b)(*strict*)
   apply(case_tac "d2 0")
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b)(*strict*)
    apply(clarsimp)
    apply(simp add: GR.derivation_def GL.derivation_def)
    apply(erule_tac
      x="0"
      in allE)+
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b a)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b a y)(*strict*)
   apply(case_tac a)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b a y option conf)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b y option conf)(*strict*)
   apply(case_tac y)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b y option conf optiona confa)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b option conf optiona confa)(*strict*)
   apply(case_tac option)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b option conf optiona confa)(*strict*)
    prefer 2
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b option conf optiona confa a)(*strict*)
    apply(clarsimp)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa a)(*strict*)
    apply(simp add: GR.derivation_def GL.derivation_def)
    apply(erule_tac
      x="0"
      in allE)+
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b option conf optiona confa)(*strict*)
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa)(*strict*)
   apply(case_tac optiona)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa)(*strict*)
    prefer 2
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa a)(*strict*)
    apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa)(*strict*)
   apply(rule_tac
      a="confa"
      in bijection_on_RU)
        apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa)(*strict*)
        apply(rule AX_relation_configuration_bijection_on)
        apply(force)
       apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa)(*strict*)
       apply (metis AX_relation_configuration_closed1)
      apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa)(*strict*)
      apply (metis AX_relation_configuration_closed2)
     apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa)(*strict*)
     apply (metis AX_relation_configuration_closed2)
    apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa)(*strict*)
    apply(force)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e1a c1b conf optiona confa)(*strict*)
   apply(force)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
  apply(rule_tac
      x="n+Suc j"
      in exI)
  apply(erule_tac
      P="\<lambda>i. (i\<le>Suc n' \<longrightarrow> ((dc i = None \<longrightarrow> d2 i = None) \<and> (\<forall>e1 c1. dc i = Some (pair e1 c1) \<longrightarrow> (\<exists>e2 c2. d2 i = Some (pair e2 c2) \<and> relation_configuration G1 G2 c1 c2 \<and> (case e1 of None \<Rightarrow> (case e2 of None \<Rightarrow> True | Some e2' \<Rightarrow> False) | Some e1' \<Rightarrow> (case e2 of None \<Rightarrow> False | Some x \<Rightarrow> relation_label G1 G2 e1' x))))))"
      and x="Suc j"
      in allE)
  apply(clarsimp)
  apply(erule impE)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
   prefer 2
   apply(clarsimp)
   apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2 e2a c2a)(*strict*)
   apply(simp add: get_configuration_def derivation_append_def)
   apply (metis AX_relation_configuration_preserves_marking_configuration)
  apply(rename_tac dh n d1 e1 c1 dc n' e2 c2 c1a j e d2)(*strict*)
  apply (metis GL.allPreMaxDomSome_prime GL.derivationNoFromNone_prime maximum_of_domain_def)
  done

end

end