[5fdc19]: thys / Group-Ring-Module / Algebra8.thy Maximize Restore History

Download this file

Algebra8.thy    4024 lines (3765 with data), 258.8 kB

(**        Algebra8
                            author Hidetsune Kobayashi
                            Group You Santo
                            Department of Mathematics
                            Nihon University
                            hikoba at math.cst.nihon-u.ac.jp
                            May 3, 2004.


   chapter 6. Construction of a special aelian group
    section 1. Abelian group generated by a singleton(constructive way)
    section 2. Abelian Group generated by one element
    section 3. Free Generated Modules
    section 4. a fgmodule and a free module
    section 5. direct sum, again
      subsection 5-1. existence of the tensor product
   **)

theory Algebra8
imports Algebra7
begin

section "10. free generated abelian group, direct sum and direct product 2"

(** Make a free generated abelian group **)

constdefs (* for abelian groups, modules *)
 bop :: "['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a, 'a] \<Rightarrow> 'a"
 "bop f a b == f a b"

 iop :: "['a \<Rightarrow> 'a, 'a] \<Rightarrow> 'a"
    ("(\<^sub>_-/ _)" [64,65]64)
 "\<^sub>i- a == i a"

constdefs (* for modules *)
 sop :: "['r \<Rightarrow> 'a \<Rightarrow> 'a, 'r, 'a] \<Rightarrow> 'a"
 "sop s r a == s r a"

syntax
 "@BOP"::"['a, 'a \<Rightarrow> 'a \<Rightarrow> 'a, 'a] \<Rightarrow> 'a"
     ("(3_/ \<^sub>_+/ _)" [62,62,63]62)

 "@SOP"::"['r, 'r \<Rightarrow> 'a \<Rightarrow> 'a, 'a] \<Rightarrow> 'a"
     ("(3_/ \<^sub>_\<cdot> _)" [68,68,69]68)

translations
 "a \<^sub>f+ b" == "bop f a b"
 "r \<^sub>s\<cdot> a" == "sop s r a"

constdefs
 minus_set :: "['a \<Rightarrow> 'a, 'a set] \<Rightarrow> 'a set"
 "minus_set i A == {x. \<exists>y\<in>A. x = \<^sub>i- y}"

 pm_set :: "['a \<Rightarrow> 'a, 'a set] \<Rightarrow> 'a set"
 "pm_set i A == A \<union> (minus_set i A)"

 s_set :: "[('r, 'm) RingType_scheme, 'r \<Rightarrow> 'a \<Rightarrow> 'a, 'a set] \<Rightarrow> 'a set"
 "s_set R s A == {x. \<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a} \<union> A"

consts
 add_set :: "['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a set] \<Rightarrow> nat \<Rightarrow> 'a set"

primrec
 add_set_0 : "add_set f A 0 = A"
 add_set_Suc: "add_set f A (Suc n) = {x. \<exists>s\<in> (add_set f A n). \<exists>t\<in> A. x = s \<^sub>f+ t}"

constdefs
 aug_pm_set::"['a, 'a \<Rightarrow> 'a, 'a set] \<Rightarrow> 'a set"
 "aug_pm_set z i A == {z} \<union> A \<union> (minus_set i A)"

constdefs
 addition_set::"['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a set] \<Rightarrow> 'a set"
 "addition_set f A == \<Union> {add_set f A n | n. (0::nat)\<le> n}"

constdefs
 assoc_bop :: "['a set, 'a \<Rightarrow> 'a \<Rightarrow> 'a] \<Rightarrow> bool"
 "assoc_bop A f == \<forall>a\<in>(addition_set f A). \<forall>b\<in>(addition_set f A). \<forall>c\<in>(addition_set f A). (a \<^sub>f+ b) \<^sub>f+ c = a \<^sub>f+ (b \<^sub>f+ c)"

 commute_bop::"['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a set] \<Rightarrow> bool"
"commute_bop f A == \<forall>x\<in>addition_set f A. \<forall>y\<in>addition_set f A. x \<^sub>f+ y = y \<^sub>f+ x"

constdefs
 zeroA :: "['a, 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a \<Rightarrow> 'a, 'a set] \<Rightarrow> 'a \<Rightarrow> bool"
 "zeroA z i f A z1 == \<forall>x \<in> addition_set f (aug_pm_set z i A). z1 \<^sub>f+ x = x"

constdefs
 inv_iop :: "['a, 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a \<Rightarrow> 'a, 'a set] \<Rightarrow> bool"
 "inv_iop z i f A  == \<forall>a\<in>addition_set f (aug_pm_set z i A). zeroA z i f A ((\<^sub>i- a) \<^sub>f+ a)"

 iop_cond1::"['a set, 'a \<Rightarrow> 'a] \<Rightarrow> bool"
 "iop_cond1 A i == \<forall>x\<in>A. \<^sub>i- (\<^sub>i- x) = x"

 iop_cond2::"['a, 'a set, 'a \<Rightarrow> 'a,  'a \<Rightarrow> 'a \<Rightarrow> 'a] \<Rightarrow> bool"
 "iop_cond2 z A i f== \<forall>x\<in>(addition_set f (aug_pm_set z i A)).
 \<forall>y\<in> (addition_set f (aug_pm_set z i A)). \<^sub>i-(x \<^sub>f+ y) = \<^sub>i- y \<^sub>f+ (\<^sub>i- x)"

 iop_cond3::"['a, 'a \<Rightarrow> 'a] \<Rightarrow> bool"
 "iop_cond3 z i == \<^sub>i- z = z"

lemma add_set_mono:"A \<subseteq> B \<Longrightarrow> add_set f A n \<subseteq> add_set f B n"
apply (induct_tac n)
 apply simp
apply (rule subsetI) apply simp
 apply (subgoal_tac "\<forall>s1\<in>add_set f A n. \<forall>t1\<in>A. x = s1 \<^sub>f+ t1 \<longrightarrow>
 (\<exists>s\<in>add_set f B n. \<exists>t\<in>B. x = s \<^sub>f+ t)") apply blast
 apply (thin_tac "\<exists>s\<in>add_set f A n. \<exists>t\<in>A. x = s \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI)
 apply (frule_tac A = "add_set f A n" and B = "add_set f B n" and c = s1 in subsetD, assumption+)
 apply (frule_tac A = A and B = B and c = t1 in subsetD, assumption+)
 apply blast
done

lemma addition_inc_add:"add_set f A n \<subseteq> addition_set f A"
apply (rule subsetI)
 apply (simp add:addition_set_def)
 apply blast
done

lemma addition_inc_add0:" A \<subseteq> addition_set f A"
apply (rule subsetI)
apply (insert addition_inc_add [of "f" "A" "0"])
 apply simp
 apply (simp add:subsetD)
done

lemma addition_set_mono:"A \<subseteq> B \<Longrightarrow> addition_set f A \<subseteq> addition_set f B"
apply (rule subsetI)
apply (simp add:addition_set_def [of "f" "A"])
 apply (subgoal_tac "\<forall>xa. (\<exists>n. xa = add_set f A n) \<and> x \<in> xa \<longrightarrow> x \<in> addition_set f B") apply blast apply (thin_tac "\<exists>xa. (\<exists>n. xa = add_set f A n) \<and> x \<in> xa")
 apply (rule allI) apply (rule impI) apply (erule conjE)
 apply (subgoal_tac "\<forall>n. xa = add_set f A n \<longrightarrow> x \<in> addition_set f B")
 apply blast apply (thin_tac "\<exists>n. xa = add_set f A n") apply (rule allI)
 apply (rule impI) apply simp apply (thin_tac "xa = add_set f A n")
 apply (frule_tac n = n in add_set_mono [of "A" "B" "f"])
 apply (frule_tac A = "add_set f A n" and B = "add_set f B n" and c = x in subsetD, assumption+)
 apply (subgoal_tac "add_set f B n \<subseteq> addition_set f B")
 apply (frule_tac A = "add_set f B n" and B = "addition_set f B" and c = x in
 subsetD, assumption+)
 apply (simp add:addition_inc_add)
done

lemma a_in_aug_pm_set:"a \<in> A \<Longrightarrow> a \<in> aug_pm_set z i A"
apply (simp add:aug_pm_set_def)
done

lemma addition_assoc:"\<lbrakk>assoc_bop A f; x \<in> addition_set f A; y \<in> addition_set f A; z \<in> addition_set f A\<rbrakk> \<Longrightarrow> (x \<^sub>f+ y) \<^sub>f+ z = x \<^sub>f+ (y \<^sub>f+ z)"
apply (simp add:assoc_bop_def)
done

lemma bop_closedTr:"assoc_bop A f \<Longrightarrow>  \<forall>x y. x \<in> add_set f A n \<and> y \<in> add_set f A m \<longrightarrow> x \<^sub>f+ y \<in> add_set f A (n + m + Suc 0)"
apply (induct_tac m) apply simp apply blast
 apply (rule allI)+ apply (rule impI) apply (erule conjE)
 apply simp
 apply (subgoal_tac "\<forall>s1\<in>add_set f A na. \<forall>t1\<in>A. y = s1 \<^sub>f+ t1 \<longrightarrow>
 (\<exists>s. (\<exists>sa\<in>add_set f A (n + na). \<exists>t\<in>A. s = sa \<^sub>f+ t)\<and>(\<exists>t\<in>A. x \<^sub>f+ y = s \<^sub>f+ t))")
 apply blast
 apply (thin_tac "\<exists>s\<in>add_set f A na. \<exists>t\<in>A. y = s \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI)
 apply (subgoal_tac "\<exists>s\<in>add_set f A (n + na). \<exists>t\<in>A. x \<^sub>f+ s1 = s \<^sub>f+ t")
 prefer 2 apply simp
 apply (thin_tac "\<forall>x y. x \<in> add_set f A n \<and> y \<in> add_set f A na \<longrightarrow>
                (\<exists>s\<in>add_set f A (n + na). \<exists>t\<in>A. x \<^sub>f+ y = s \<^sub>f+ t)")
 apply (subgoal_tac "\<forall>s2\<in>add_set f A (n + na). \<forall>t2\<in>A. x \<^sub>f+ s1 = s2 \<^sub>f+ t2 \<longrightarrow>
(\<exists>s. (\<exists>sa\<in>add_set f A (n + na). \<exists>t\<in>A. s = sa \<^sub>f+ t) \<and> (\<exists>t\<in>A. x \<^sub>f+ y = s \<^sub>f+ t))")
 apply blast
 apply (thin_tac "\<exists>s\<in>add_set f A (n + na). \<exists>t\<in>A. x \<^sub>f+ s1 = s \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI) apply simp
 apply (subgoal_tac "x \<^sub>f+ (s1 \<^sub>f+ t1) = (x \<^sub>f+ s1) \<^sub>f+ t1")
 apply simp
 apply blast
apply (thin_tac "y = s1 \<^sub>f+ t1")
 apply (thin_tac "x \<^sub>f+ s1 = s2 \<^sub>f+ t2")
 apply (thin_tac "s2 \<in> add_set f A (n + na)")
 apply (thin_tac "t2 \<in> A")
 apply (subgoal_tac "x \<in> addition_set f A")
 apply (subgoal_tac "s1 \<in> addition_set f A")
 apply (subgoal_tac "t1 \<in> addition_set f A")
 apply (simp add:assoc_bop_def)
 apply (thin_tac "x \<in> addition_set f A")
 apply (thin_tac "s1 \<in> addition_set f A")
 apply (simp add:addition_set_def)
 apply (subgoal_tac "t1 \<in> add_set f A 0") apply blast
 apply simp
 apply (thin_tac "t1 \<in> A")
 apply (simp add:addition_set_def) apply blast
 apply (simp add:addition_set_def) apply blast
done

lemma bop_closed1:"\<lbrakk>assoc_bop A f; x \<in> add_set f A n; y \<in> add_set f A m\<rbrakk> \<Longrightarrow>
 x \<^sub>f+ y \<in> add_set f A (n + m + Suc 0)"
apply (insert bop_closedTr[of "A" "f"])
apply blast
done

lemma bop_closed:"\<lbrakk>assoc_bop A f; x \<in> addition_set f A; y \<in> addition_set f A\<rbrakk> \<Longrightarrow>  x \<^sub>f+ y \<in> addition_set f A"
apply (subgoal_tac "\<exists>xa. (\<exists>n. xa = add_set f A n) \<and> x \<in> xa")
prefer 2 apply (simp add:addition_set_def)
apply (subgoal_tac "\<forall>xa. (\<exists>n. xa = add_set f A n) \<and> x \<in> xa \<longrightarrow>  x \<^sub>f+ y \<in> addition_set f A")
apply blast
apply (thin_tac "\<exists>xa. (\<exists>n. xa = add_set f A n) \<and> x \<in> xa")
apply (rule allI) apply (rule impI) apply (erule conjE)
apply (subgoal_tac "\<forall>n. xa = add_set f A n \<longrightarrow> x \<^sub>f+ y \<in> addition_set f A")
apply blast apply (thin_tac "\<exists>n. xa = add_set f A n")
apply (rule allI) apply (rule impI) apply simp
apply (thin_tac "xa = add_set f A n") apply (thin_tac "x \<in> addition_set f A")
apply simp
apply (subgoal_tac "\<exists>xa. (\<exists>m. xa = add_set f A m) \<and> y \<in> xa")
prefer 2 apply (simp add:addition_set_def)
apply (subgoal_tac "\<forall>xa. (\<exists>m. xa = add_set f A m) \<and> y \<in> xa \<longrightarrow>  x \<^sub>f+ y \<in> addition_set f A")
apply blast
apply (thin_tac "\<exists>xa. (\<exists>m. xa = add_set f A m) \<and> y \<in> xa")
apply (rule allI) apply (rule impI) apply (erule conjE)
apply (subgoal_tac "\<forall>m. xa = add_set f A m \<longrightarrow> x \<^sub>f+ y \<in> addition_set f A")
apply blast apply (thin_tac "\<exists>m. xa = add_set f A m")
apply (rule allI) apply (rule impI) apply simp
apply (frule bop_closed1 [of "A" "f" "x" _ "y"], assumption+)
apply (thin_tac "y \<in> addition_set f A")
 apply (thin_tac "x \<in> add_set f A n")
 apply (thin_tac "y \<in> add_set f A m")
 apply (thin_tac "xa = add_set f A m")
apply (subst addition_set_def) apply (simp del:add_set_0 add_set_Suc)
apply blast
done

lemma aug_addition_inc_z:" z \<in> addition_set f (aug_pm_set z i A)"
apply (subgoal_tac "z \<in> aug_pm_set z i A")
apply (subgoal_tac "aug_pm_set z i A \<subseteq> addition_set f (aug_pm_set z i A)")
 apply (simp add:subsetD)
 apply (simp add:addition_inc_add0)
 apply (simp add:aug_pm_set_def)
done

lemma aug_bop_closed:"\<lbrakk>assoc_bop (aug_pm_set z i A) f; x \<in> addition_set f (aug_pm_set z i A); y \<in> addition_set f (aug_pm_set z i A)\<rbrakk> \<Longrightarrow>  x \<^sub>f+ y \<in> addition_set f (aug_pm_set z i A)"
apply (simp add:bop_closed [of "aug_pm_set z i A" "f"])
done

lemma aug_commute:"\<lbrakk>commute_bop f (aug_pm_set z i A); x \<in> addition_set f (aug_pm_set z i A); y \<in> addition_set f (aug_pm_set z i A)\<rbrakk> \<Longrightarrow> x \<^sub>f+ y = y \<^sub>f+ x"
apply (simp add: commute_bop_def)
done

lemma addition_set_inc_z:"z \<in> addition_set f (aug_pm_set z i A)"
apply (simp add:addition_set_def)
apply (subgoal_tac "z \<in> add_set f (aug_pm_set z i A) 0")
apply blast
apply (simp add:aug_pm_set_def)
done

lemma  aug_iop_closed0:"\<lbrakk>commute_bop f (aug_pm_set z i A); assoc_bop (aug_pm_set z i A) f; iop_cond1 A i; iop_cond2 z A i f; iop_cond3 z i;
x \<in> add_set f (aug_pm_set z i A) 0\<rbrakk> \<Longrightarrow> \<^sub>i- x \<in> add_set f (aug_pm_set z i A) 0"
 apply (simp add:aug_pm_set_def)
 apply (case_tac "x \<in> A") apply (simp add:minus_set_def) apply blast
 apply simp
 apply (simp add:minus_set_def)
 apply (case_tac "x = z") apply simp apply (simp add:iop_cond3_def)
 apply simp
 apply (subgoal_tac "\<forall>y\<in>A. x = \<^sub>i- y \<longrightarrow> (\<^sub>i- x = z \<or> \<^sub>i- x \<in> A \<or> (\<exists>y\<in>A. \<^sub>i- x = \<^sub>i- y))") apply blast apply (thin_tac "\<exists>y\<in>A. x = \<^sub>i- y")
 apply (rule ballI) apply (rule impI) apply (simp add:iop_cond1_def)
done

lemma aug_iop_closedTr:"\<lbrakk>commute_bop f (aug_pm_set z i A); assoc_bop (aug_pm_set z i A) f; iop_cond1 A i; iop_cond2 z A i f; iop_cond3 z i\<rbrakk> \<Longrightarrow>  \<forall>x. x \<in> add_set f (aug_pm_set z i A) n \<longrightarrow>  \<^sub>i- x \<in> add_set f (aug_pm_set z i A) n"
apply (induct_tac n) apply (rule allI) apply (rule impI)
 apply (simp add:aug_pm_set_def)
 apply (case_tac "x = z") apply (simp add:iop_cond3_def)
 apply simp
 apply (case_tac "x \<in> A") apply (simp add:minus_set_def) apply blast
 apply simp
 apply (simp add:minus_set_def)
 apply (subgoal_tac "\<forall>y\<in>A. x = \<^sub>i- y \<longrightarrow> (\<^sub>i- x = z \<or> \<^sub>i- x \<in> A \<or> (\<exists>y\<in>A. \<^sub>i- x = \<^sub>i- y))") apply blast apply (thin_tac "\<exists>y\<in>A. x = \<^sub>i- y")
 apply (rule ballI) apply (rule impI) apply (simp add:iop_cond1_def)
apply (rule allI) apply (rule impI) apply simp
 apply (subgoal_tac "\<forall>s\<in>add_set f (aug_pm_set z i A) n. \<forall>t\<in>aug_pm_set z i A.
 x = s \<^sub>f+ t \<longrightarrow> (\<exists>s\<in>add_set f (aug_pm_set z i A) n. \<exists>t\<in>aug_pm_set z i A. \<^sub>i- x = s \<^sub>f+ t)") apply blast
 apply (thin_tac "\<exists>s\<in>add_set f (aug_pm_set z i A) n. \<exists>t\<in>aug_pm_set z i A.
                         x = s \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI)
 apply (subgoal_tac "\<^sub>i- s \<in> add_set f (aug_pm_set z i A) n")
 prefer 2 apply simp
 apply (thin_tac "\<forall>x. x \<in> add_set f (aug_pm_set z i A) n \<longrightarrow>
              \<^sub>i- x \<in> add_set f (aug_pm_set z i A) n")
 apply (simp add:iop_cond2_def)
 apply (subgoal_tac "add_set f (aug_pm_set z i A) n \<subseteq> addition_set f (aug_pm_set z i A)") prefer 2
  apply (rule addition_inc_add [of "f" "aug_pm_set z i A"])
  apply (frule_tac A = "add_set f (aug_pm_set z i A) n" and B = "addition_set f (aug_pm_set z i A)" and c = "s" in subsetD, assumption+)
 apply (insert addition_inc_add0[of "aug_pm_set z i A" "f"])
 apply (frule_tac c = t in subsetD [of "aug_pm_set z i A" "addition_set f (aug_pm_set z i A)"], assumption+)
 apply (subgoal_tac "\<^sub>i- (s \<^sub>f+ t) = \<^sub>i- t \<^sub>f+ (\<^sub>i- s)") prefer 2 apply simp
 apply (thin_tac "\<forall>x\<in>addition_set f (aug_pm_set z i A). \<forall>y\<in>addition_set f (aug_pm_set z i A).  \<^sub>i- (x \<^sub>f+ y) = \<^sub>i- y \<^sub>f+ \<^sub>i- x")
 apply (simp add: commute_bop_def)
 apply (subgoal_tac "\<^sub>i-t \<in> aug_pm_set z i A")
 apply (frule_tac c = "\<^sub>i- t" in subsetD [of "aug_pm_set z i A" "addition_set f (aug_pm_set z i A)"], assumption+)
 apply (subgoal_tac "\<^sub>i- t \<^sub>f+ \<^sub>i- s = \<^sub>i- s \<^sub>f+ \<^sub>i- t") prefer 2
 apply blast
 apply simp
 apply blast
apply (thin_tac "\<forall>x\<in>addition_set f (aug_pm_set z i A).
           \<forall>y\<in>addition_set f (aug_pm_set z i A). x \<^sub>f+ y = y \<^sub>f+ x")
 apply (thin_tac " s \<in> add_set f (aug_pm_set z i A) n")
 apply (thin_tac "add_set f (aug_pm_set z i A) n \<subseteq> addition_set f (aug_pm_set z i A)")
 apply (thin_tac "t \<in> addition_set f (aug_pm_set z i A)")
 apply (thin_tac "\<^sub>i- (s \<^sub>f+ t) = \<^sub>i- t \<^sub>f+ \<^sub>i- s")
 apply (thin_tac "aug_pm_set z i A \<subseteq> addition_set f (aug_pm_set z i A)")
 apply (thin_tac "s \<in> addition_set f (aug_pm_set z i A)")
 apply (thin_tac "\<^sub>i- s \<in> add_set f (aug_pm_set z i A) n")
 apply (thin_tac "assoc_bop (aug_pm_set z i A) f")
 apply (thin_tac "x = s \<^sub>f+ t")
apply (simp add:aug_pm_set_def)
 apply (case_tac "t = z")
 apply (simp add:iop_cond3_def) apply simp
 apply (case_tac "t \<in> A") apply (simp add:minus_set_def) apply blast
 apply simp
 apply (simp add:minus_set_def)
 apply (subgoal_tac "\<forall>y\<in>A. t = \<^sub>i- y \<longrightarrow> (\<^sub>i- t = z \<or> \<^sub>i- t \<in> A \<or> (\<exists>y\<in>A. \<^sub>i- t = \<^sub>i- y))") apply blast apply (thin_tac "\<exists>y\<in>A. t = \<^sub>i- y")
 apply (rule ballI) apply (rule impI) apply (simp add:iop_cond1_def)
done


lemma aug_iop_closedTr2:"\<lbrakk>commute_bop f (aug_pm_set z i A); assoc_bop (aug_pm_set z i A) f; iop_cond1 A i; iop_cond2 z A i f; iop_cond3 z i; x \<in> add_set f (aug_pm_set z i A) n\<rbrakk> \<Longrightarrow>  \<^sub>i- x \<in> add_set f (aug_pm_set z i A) n"
apply (simp add:aug_iop_closedTr)
done

lemma aug_iop_closed:"\<lbrakk>commute_bop f (aug_pm_set z i A); assoc_bop (aug_pm_set z i A) f; iop_cond1 A i; iop_cond2 z A i f; iop_cond3 z i; x \<in> addition_set f (aug_pm_set z i A) \<rbrakk> \<Longrightarrow>  \<^sub>i- x \<in> addition_set f (aug_pm_set z i A)"
apply (subgoal_tac "\<exists>n. x \<in> add_set f (aug_pm_set z i A) n")
 prefer 2 apply (simp add:addition_set_def) apply blast
 apply (subgoal_tac "\<forall>n. x \<in> add_set f (aug_pm_set z i A) n \<longrightarrow> \<^sub>i- x \<in> addition_set f (aug_pm_set z i A)")  apply blast apply (thin_tac " \<exists>n. x \<in> add_set f (aug_pm_set z i A) n") apply (rule allI) apply (rule impI)
apply (frule_tac x = x and n = n in aug_iop_closedTr2 [of "f" "z" "i" "A"], assumption+)
 apply (subgoal_tac "add_set f (aug_pm_set z i A) n \<subseteq> addition_set f (aug_pm_set z i A)")
 apply (simp add:subsetD)
apply (simp add:addition_inc_add)
done

lemma aug_zero_unique:"\<lbrakk>commute_bop f (aug_pm_set z i A); z1 \<in> addition_set f (aug_pm_set z i A); zeroA z i f A z; zeroA z i f A z1\<rbrakk> \<Longrightarrow> z = z1"
apply (simp add:zeroA_def[of "z" _ _ _ "z"])
apply (subgoal_tac "z \<^sub>f+ z1 = z1") prefer 2 apply simp
apply (insert addition_set_inc_z [of "z" "f" "i" "A"])
apply (frule aug_commute [of "f" "z" "i" "A" "z" "z1"], assumption+)
 apply (thin_tac "\<forall>x\<in>addition_set f (aug_pm_set z i A). z \<^sub>f+ x = x")
apply simp
apply (simp add:zeroA_def[of _ _ _ _ "z1"])
done

lemma inv_aug_addition:"\<lbrakk>commute_bop f (aug_pm_set z i A); assoc_bop (aug_pm_set z i A) f;
iop_cond1 A i; iop_cond2 z A i f; iop_cond3 z i; inv_iop z i f A; commute_bop f (aug_pm_set z i A); zeroA z i f A z\<rbrakk> \<Longrightarrow> \<forall>a\<in>addition_set f (aug_pm_set z i A). (\<^sub>i-a) \<^sub>f+ a = z"
apply (simp add:inv_iop_def)
apply (rule ballI)
apply (subgoal_tac "zeroA z i f A (\<^sub>i- a \<^sub>f+ a)") prefer 2 apply simp
 apply (thin_tac "\<forall>a\<in>addition_set f (aug_pm_set z i A). zeroA z i f A (\<^sub>i- a \<^sub>f+ a)")
 apply (frule_tac ?z1.0 = "(\<^sub>i- a \<^sub>f+ a)" in aug_zero_unique [of "f" "z" "i" "A"])
 apply (frule_tac x = a in aug_iop_closed [of "f" "z" "i" "A"], assumption+)
 apply (rule_tac x = "\<^sub>i- a" and y = a in aug_bop_closed [of "z" "i" "A" "f"],
                                       assumption+)
 apply (simp add:zeroA_def)
done

constdefs
 fag_gen_by :: "['a set, 'a \<Rightarrow> 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a, 'a] \<Rightarrow> 'a AgroupType"
 "fag_gen_by A f i z == \<lparr> carrier = addition_set f (aug_pm_set z i A), pOp = \<lambda>x\<in>(addition_set f (aug_pm_set z i A)). \<lambda>y\<in>(addition_set f (aug_pm_set z i A)). x \<^sub>f+ y, mOp = \<lambda>x\<in>(addition_set f (aug_pm_set z i A)). \<^sub>i- x, zero = z\<rparr>"

lemma fag_agroup:"\<lbrakk>commute_bop f (aug_pm_set z i A); assoc_bop (aug_pm_set z i A) f;
iop_cond1 A i; iop_cond2 z A i f; iop_cond3 z i; inv_iop z i f A; commute_bop f (aug_pm_set z i A); zeroA z i f A z\<rbrakk> \<Longrightarrow> agroup (fag_gen_by A f i z)"
apply (subst agroup_def)
apply (rule conjI)
 apply (rule bivar_func_test)
 apply (rule ballI)+
 apply (simp add:fag_gen_by_def)
 apply (simp add:aug_bop_closed)
apply (rule conjI)
 apply (rule univar_func_test)
 apply (rule ballI) apply (simp add:fag_gen_by_def)
 apply (simp add:aug_iop_closed)
apply (rule conjI)
 apply (simp add:fag_gen_by_def)
 apply (simp add:aug_addition_inc_z)
apply (rule ballI)+
 apply (rule conjI)
 apply (simp add:fag_gen_by_def zeroA_def)
 apply (simp add:aug_addition_inc_z)
 apply (rule conjI)
 apply (simp add:fag_gen_by_def)
apply (rule conjI) apply (rule impI)
 apply (simp add:inv_iop_def zeroA_def)
 apply (subgoal_tac "z \<in> addition_set f (aug_pm_set z i A)")
 apply (rename_tac a1 b1 za)
 apply (subgoal_tac "\<forall>x\<in>addition_set f (aug_pm_set z i A). \<^sub>i- a1 \<^sub>f+ a1 \<^sub>f+ x = x") prefer 2 apply simp
 apply (thin_tac "\<forall>a\<in>addition_set f (aug_pm_set z i A).
             \<forall>x\<in>addition_set f (aug_pm_set z i A). \<^sub>i- a \<^sub>f+ a \<^sub>f+ x = x")
 apply (subgoal_tac "zeroA z i f A ( \<^sub>i- a1 \<^sub>f+ a1)")
  prefer 2 apply (simp add:zeroA_def)
 apply (subgoal_tac "zeroA z i f A z") prefer 2 apply (simp add:zeroA_def)
 apply (rule aug_zero_unique [THEN sym, of "f" "z" "i" "A"], assumption+)
 apply (rule aug_bop_closed) apply (simp add:aug_pm_set_def)
 apply assumption+ apply (simp add:aug_addition_inc_z)
 apply (rule impI)
 apply (frule_tac x = x in aug_iop_closed [of "f" "z" "i" "A"])
 apply (simp add:aug_pm_set_def) apply assumption+ apply simp
 apply (rule conjI)
 apply (simp add:fag_gen_by_def)
 apply (subgoal_tac "assoc_bop (aug_pm_set z i A) f")
 apply (frule_tac x = x and y = y in aug_bop_closed [of "z" "i" "A" "f"], assumption+)
 apply (frule_tac x = y and y = za in aug_bop_closed [of "z" "i" "A" "f"], assumption+) apply simp
 apply (simp add:assoc_bop_def) apply (simp add:aug_pm_set_def)
apply (simp add:fag_gen_by_def)
 apply (simp add: commute_bop_def)
done

chapter "6. Construction of a special aelian group"

section "1. Abelian group generated by a singleton (constructive way)"

 constdefs
 fag_single :: "['a, 'a \<Rightarrow> 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a, 'a] \<Rightarrow> 'a AgroupType"
 "fag_single a f i z == fag_gen_by {a} f i z"

lemma aug_pm_aug_pm_minus:"iop_cond1 {a} i \<Longrightarrow> aug_pm_set z i {a} = aug_pm_set z i {\<^sub>i- a}"
apply (simp add:aug_pm_set_def minus_set_def)
 apply (subgoal_tac "\<^sub>i- (\<^sub>i- a) = a") apply simp
 apply (rule equalityI) apply (rule subsetI) apply simp apply blast
 apply (rule subsetI) apply simp apply blast
apply (simp add:iop_cond1_def)
done

lemma iop_cond1_minus:"iop_cond1 {a} i \<Longrightarrow> iop_cond1 {\<^sub>i- a} i"
 apply (simp add:iop_cond1_def)
done

lemma iop_cond2_minus:"\<lbrakk>iop_cond1 {a} i; iop_cond2 z {a} i f\<rbrakk> \<Longrightarrow> iop_cond2 z {\<^sub>i- a} i f"
 apply (simp add:iop_cond2_def) apply (simp add:aug_pm_aug_pm_minus)
done

lemma zeroA_minus:"\<lbrakk>iop_cond1 {a} i; zeroA z i f {a} z1\<rbrakk> \<Longrightarrow> zeroA z i f {\<^sub>i- a} z1"
apply (simp add:zeroA_def)
apply (simp add:aug_pm_aug_pm_minus)
done

lemma inv_iop_minus:"\<lbrakk>iop_cond1 {a} i; inv_iop z i f {a}\<rbrakk> \<Longrightarrow> inv_iop z i f {\<^sub>i- a}"
 apply (simp add:inv_iop_def [of _ _ _ "{a}"])
 apply (simp add:aug_pm_aug_pm_minus)
apply (simp add:inv_iop_def)
apply (simp add:zeroA_minus)
done

lemma fag_single_additionTr1:"\<lbrakk>commute_bop f (aug_pm_set z i {a});
assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z\<rbrakk> \<Longrightarrow> \<forall>s. s\<in> add_set f {a} (Suc n) \<longrightarrow> s \<^sub>f+ \<^sub>i- a \<in> add_set f {a} n"
apply (subgoal_tac "(aug_pm_set z i {a}) \<subseteq> addition_set f (aug_pm_set z i {a})") prefer 2 apply (simp add:addition_inc_add0)
apply (subgoal_tac "a \<in> aug_pm_set z i {a}")
 prefer 2 apply (rule a_in_aug_pm_set) apply simp
 apply (frule subsetD[of "aug_pm_set z i {a}" "addition_set f (aug_pm_set z i {a})" "a"], assumption+)
apply (induct_tac n)
apply (rule allI) apply (rule impI) apply simp
 apply (frule aug_iop_closed [of "f" "z" "i" "{a}" "a"], assumption+)
 apply (simp add:addition_assoc)
 apply (frule aug_commute [of "f" "z" "i" "{a}" "a" "\<^sub>i- a"], assumption+)
 apply simp apply (thin_tac "a \<^sub>f+ \<^sub>i- a = \<^sub>i- a \<^sub>f+ a")
 apply (simp add:inv_aug_addition)
 apply (subgoal_tac "z \<in> addition_set f (aug_pm_set z i {a})")
 apply (frule aug_commute [of "f" "z" "i" "{a}" "a" "z"], assumption+)
 apply simp apply (thin_tac "a \<^sub>f+ z = z \<^sub>f+ a")
 apply (simp add:zeroA_def)
 apply (simp add:addition_set_inc_z)
apply (rule allI) apply (rule impI)
 apply (subgoal_tac "\<exists>sa. (\<exists>sb\<in>add_set f {a} n. sa = sb \<^sub>f+ a) \<and> s = sa \<^sub>f+ a")
 prefer 2 apply simp
 apply (subgoal_tac "\<forall>sa. (\<exists>sb\<in>add_set f {a} n. sa = sb \<^sub>f+ a) \<and> s = sa \<^sub>f+ a
 \<longrightarrow>  s \<^sub>f+ \<^sub>i- a \<in> add_set f {a} (Suc n)") apply blast
 apply (thin_tac "\<exists>sa. (\<exists>sb\<in>add_set f {a} n. sa = sb \<^sub>f+ a) \<and> s = sa \<^sub>f+ a")
 apply (rule allI) apply (rule impI) apply (erule conjE)
 apply (subgoal_tac "\<forall>sb\<in>add_set f {a} n. sa =  sb \<^sub>f+ a \<longrightarrow> (s \<^sub>f+ \<^sub>i- a \<in> add_set f {a} (Suc n))") apply blast
  apply (thin_tac "\<exists>sb\<in>add_set f {a} n. sa = sb \<^sub>f+ a")
 apply (rule ballI) apply (rule impI) apply (subgoal_tac "sa \<in> add_set f {a} (Suc n)")
 apply (subgoal_tac "sa  \<^sub>f+ \<^sub>i- a \<in> add_set f {a} n ") prefer 2 apply blast
 apply (thin_tac "\<forall>s. s \<in> add_set f {a} (Suc n) \<longrightarrow> s \<^sub>f+ \<^sub>i- a \<in> add_set f {a} n")
 apply simp
 apply (subgoal_tac "{a} \<subseteq> aug_pm_set z i {a}") prefer 2 apply (rule subsetI)
  apply (simp add:aug_pm_set_def)
  apply (frule_tac n = n in add_set_mono [of "{a}" "aug_pm_set z i {a}" "f"])
  apply (frule_tac A = "add_set f {a} n" and B = "add_set f (aug_pm_set z i {a}) n" and c = sb in subsetD, assumption+)
  apply (subgoal_tac "add_set f (aug_pm_set z i {a}) n \<subseteq> addition_set f ((aug_pm_set z i {a}))")
  apply (frule_tac A = "add_set f (aug_pm_set z i {a}) n" and B = "addition_set f (aug_pm_set z i {a})" and c = sb in subsetD, assumption+)
  apply (thin_tac "add_set f (aug_pm_set z i {a}) n
          \<subseteq> addition_set f (aug_pm_set z i {a})")
  apply (frule_tac x = sb and y = a in aug_bop_closed[of "z" "i" "{a}" "f"], assumption+)
  apply (frule aug_iop_closed [of "f" "z" "i" "{a}" "a"], assumption+)
 apply (subst addition_assoc [of "aug_pm_set z i {a}" "f" _ "a" " \<^sub>i- a "], assumption+)
  apply (frule aug_commute [of "f" "z" "i" "{a}" "a" "\<^sub>i- a"], assumption+)
  apply simp apply (thin_tac "a \<^sub>f+ \<^sub>i- a = \<^sub>i- a \<^sub>f+ a")
  apply (simp add:inv_aug_addition)
  apply (subgoal_tac "z \<in> addition_set f (aug_pm_set z i {a})")
  apply (frule_tac x = "sb \<^sub>f+ a" in aug_commute [of "f" "z" "i" "{a}" _  "z"], assumption+)
  apply simp apply (thin_tac "sb \<^sub>f+ a \<^sub>f+ z = z \<^sub>f+ (sb \<^sub>f+ a)")
  apply (simp add:zeroA_def)
  apply (simp add:addition_set_inc_z) apply (simp add:addition_inc_add)
 apply (thin_tac "\<forall>s. s \<in> add_set f {a} (Suc n) \<longrightarrow> s \<^sub>f+ \<^sub>i- a \<in> add_set f {a} n") apply (thin_tac "s \<in> add_set f {a} (Suc (Suc n))") apply simp
 apply blast
done

lemma fag_single_additionTr2:"\<lbrakk>commute_bop f (aug_pm_set z i {a}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; s \<in> add_set f {a} 0\<rbrakk> \<Longrightarrow> s \<^sub>f+ \<^sub>i- a = z"
 apply simp
 apply (subgoal_tac "a \<in> addition_set f (aug_pm_set z i {a})")
 apply (frule aug_iop_closed [of "f" "z" "i" "{a}" "a"], assumption+)
  apply (frule aug_commute [of "f" "z" "i" "{a}" "a" "\<^sub>i- a"], assumption+)
  apply simp apply (thin_tac "a \<^sub>f+ \<^sub>i- a = \<^sub>i- a \<^sub>f+ a")
  apply (simp add:inv_aug_addition)
apply (subgoal_tac "(aug_pm_set z i {a}) \<subseteq> addition_set f (aug_pm_set z i {a})") prefer 2 apply (simp add:addition_inc_add0)
apply (subgoal_tac "a \<in> aug_pm_set z i {a}")
 prefer 2 apply (rule a_in_aug_pm_set) apply simp
 apply (frule subsetD[of "aug_pm_set z i {a}" "addition_set f (aug_pm_set z i {a})" "a"], assumption+)
done

lemma fag_single_additionTr3:"\<lbrakk>commute_bop f (aug_pm_set z i {a});
assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; s\<in> add_set f {\<^sub>i- a} n\<rbrakk> \<Longrightarrow> s \<^sub>f+ \<^sub>i- a \<in> add_set f {\<^sub>i- a} (Suc n)"
apply simp apply blast
done

lemma fag_single_elemTr:"\<lbrakk>commute_bop f (aug_pm_set z i {a}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z\<rbrakk> \<Longrightarrow> \<forall>x. x \<in> add_set f (aug_pm_set z i {a}) n \<longrightarrow> (\<exists>n1. x \<in> add_set f {a} n1) \<or> (\<exists>m1. x \<in> add_set f {\<^sub>i- a} m1) \<or> x = z"
 apply (subgoal_tac "a \<in> addition_set f (aug_pm_set z i {a})")
 prefer 2
 apply (subgoal_tac "aug_pm_set z i {a} \<subseteq> addition_set f (aug_pm_set z i {a})") apply (subgoal_tac "a \<in> aug_pm_set z i {a}") apply (simp add:subsetD)
 apply (simp add:aug_pm_set_def) apply (simp add:addition_inc_add0)
 apply (subgoal_tac "z \<in> addition_set f (aug_pm_set z i {a})")
 prefer 2  apply (simp add:aug_addition_inc_z)
apply (induct_tac n)
 apply (rule allI) apply (rule impI)
 apply (simp add:aug_pm_set_def)
 apply (case_tac "x = a")
 apply (subgoal_tac "x \<in> add_set f {a} 0") apply blast
 apply simp apply simp
 apply (case_tac "x = z") apply simp apply simp
 apply (simp add:minus_set_def)
 apply (subgoal_tac "x \<in> add_set f {\<^sub>i- a} 0") apply blast apply simp
apply (rule allI) apply (rule impI) apply simp
 apply (subgoal_tac "\<forall>s\<in>add_set f (aug_pm_set z i {a}) n. \<forall>t\<in>aug_pm_set z i {a}. x = s \<^sub>f+ t \<longrightarrow>(\<exists>n1. x \<in> add_set f {a} n1) \<or> (\<exists>m1. x \<in> add_set f {\<^sub>i- a} m1) \<or> x = z")  apply blast
 apply (thin_tac "\<exists>s\<in>add_set f (aug_pm_set z i {a}) n. \<exists>t\<in>aug_pm_set z i {a}. x = s \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI) apply simp
 apply (subgoal_tac "(\<exists>n1. s \<in> add_set f {a} n1) \<or>
              (\<exists>m1. s \<in> add_set f {\<^sub>i- a} m1) \<or> s = z") prefer 2 apply simp
 apply (thin_tac "\<forall>x. x \<in> add_set f (aug_pm_set z i {a}) n \<longrightarrow>
 (\<exists>n1. x \<in> add_set f {a} n1) \<or> (\<exists>m1. x \<in> add_set f {\<^sub>i- a} m1) \<or> x = z")
 apply (case_tac "\<exists>n1. s \<in> add_set f {a} n1")
  apply (thin_tac "(\<exists>n1. s \<in> add_set f {a} n1) \<or>
          (\<exists>m1. s \<in> add_set f {\<^sub>i- a} m1) \<or> s = z")
 apply (subgoal_tac "\<forall>n2. s \<in> add_set f {a} n2  \<longrightarrow> ((\<exists>n1. s \<^sub>f+ t \<in> add_set f {a} n1) \<or> (\<exists>m1. s \<^sub>f+ t \<in> add_set f {\<^sub>i- a} m1) \<or> s \<^sub>f+ t = z)") apply blast
 apply (thin_tac "\<exists>n1. s \<in> add_set f {a} n1")
 apply (rule allI) apply (rule impI)
 apply (thin_tac "s \<in> add_set f (aug_pm_set z i {a}) n")
 apply (simp add:aug_pm_set_def)
 apply (case_tac "t = a")
 apply (subgoal_tac " s \<^sub>f+ t \<in> add_set f {a} (Suc n2)")  apply blast
 apply simp apply blast apply simp
 apply (case_tac "t = z")
 apply (subgoal_tac " s \<^sub>f+ t = s") apply simp apply blast
 apply (simp add:minus_set_def)
 apply (subgoal_tac "{a} \<subseteq> {a, z, \<^sub>i- a}")
 apply (frule_tac n = n2 in add_set_mono [of "{a}" "{a, z, \<^sub>i- a}" "f"])
 apply (frule_tac A = "add_set f {a} n2" and B = "add_set f {a, z, \<^sub>i- a} n2" and c = s in subsetD, assumption+)
 apply (subgoal_tac "add_set f {a, z, \<^sub>i- a} n2 \<subseteq> addition_set f {a, z, \<^sub>i- a}")
 apply (frule_tac A = "add_set f {a, z, \<^sub>i- a} n2" and B = "addition_set f {a, z, \<^sub>i- a}" and c = s in subsetD, assumption+)
 apply (subgoal_tac "{a, z, \<^sub>i- a} = aug_pm_set z i {a}") apply simp
 apply (frule_tac x = s and y = z in aug_commute[of "f" "z" "i" "{a}"], assumption+) apply simp
 apply (simp add:zeroA_def) apply (simp add:aug_pm_set_def minus_set_def)
 apply (rule equalityI) apply (rule subsetI) apply simp apply blast
 apply (rule subsetI) apply simp apply blast apply (simp add:addition_inc_add)
 apply (rule subsetI) apply simp apply (simp add:minus_set_def)
 apply (case_tac "n2 = 0")
 apply (subgoal_tac "{a, z, \<^sub>i- a} = aug_pm_set z i {a}") apply simp
 apply (frule fag_single_additionTr2 [of "f" "z" "i" "a" "a"], assumption+)
 apply (simp add:aug_pm_set_def) apply simp apply (simp add:aug_pm_set_def)
 apply (simp add:minus_set_def) apply simp
 apply (subgoal_tac "n2 = Suc (n2 - Suc 0)")
 apply (simp del:Suc_pred)
 apply (subgoal_tac "s \<in> add_set f {a} (Suc (n2 - Suc 0))")
 prefer 2 apply simp
 apply (subgoal_tac "{a, z, \<^sub>i- a} = aug_pm_set z i {a}")
 apply (simp del:Suc_pred)
 apply (frule_tac n = "n2 - Suc 0" in fag_single_additionTr1 [of "f" "z" "i" "a"], assumption+)
 apply (subgoal_tac "s \<^sub>f+ \<^sub>i- a \<in> add_set f {a} (n2 - Suc 0)")
 prefer 2 apply simp apply blast apply (simp add:aug_pm_set_def minus_set_def)
 apply (rule equalityI) apply (rule subsetI) apply simp apply blast
 apply (rule subsetI) apply simp apply blast apply simp apply simp
 apply (thin_tac " \<forall>n1. s \<notin> add_set f {a} n1")
apply (case_tac "s = z") apply simp
 apply (subgoal_tac "t \<in> addition_set f (aug_pm_set z i {a})")
 apply (simp add:zeroA_def)
 apply (thin_tac "\<forall>x\<in>addition_set f (aug_pm_set z i {a}). z \<^sub>f+ x = x")
 apply (thin_tac "t \<in> addition_set f (aug_pm_set z i {a})")
 apply (simp add:aug_pm_set_def minus_set_def)
 apply (case_tac "t = \<^sub>i- a")
 apply (subgoal_tac "t \<in> add_set f {\<^sub>i- a} 0") apply blast
 apply simp apply simp
apply (case_tac "t = a") apply (subgoal_tac "t \<in> add_set f {a} 0")
 apply blast apply simp apply simp
 apply (subgoal_tac "aug_pm_set z i {a} \<subseteq> addition_set f (aug_pm_set z i {a})") apply (simp add:subsetD)
 apply (rule addition_inc_add0) apply simp
 apply (subgoal_tac "\<forall>m2. s \<in> add_set f {\<^sub>i- a} m2 \<longrightarrow> (\<exists>n1. s \<^sub>f+ t \<in> add_set f {a} n1) \<or> (\<exists>m1. s \<^sub>f+ t \<in> add_set f {\<^sub>i- a} m1) \<or> s \<^sub>f+ t = z") apply blast
 apply (thin_tac "\<exists>m1. s \<in> add_set f {\<^sub>i- a} m1")
 apply (rule allI) apply (rule impI)
 apply (subgoal_tac "t = a \<or> t = z \<or> t = \<^sub>i- a")
  prefer 2 apply (simp add:aug_pm_set_def minus_set_def) apply blast
 apply (case_tac "m2 = 0") apply simp
  apply (case_tac "t = a") apply simp
 apply (simp add:inv_iop_def)
  apply (subgoal_tac "zeroA z i f {a} (\<^sub>i- a \<^sub>f+ a)")
  apply (subgoal_tac " \<^sub>i- a \<^sub>f+ a \<in> addition_set f (aug_pm_set z i {a})")
  apply (frule_tac ?z1.0 = "\<^sub>i- a \<^sub>f+ a" in aug_zero_unique [of "f" "z" "i" "{a}"], assumption+)
  apply (rotate_tac -1) apply (frule sym) apply (thin_tac "z = \<^sub>i- a \<^sub>f+ a")
  apply (thin_tac "\<forall>aa\<in>addition_set f (aug_pm_set z i {a}). zeroA z i f {a} (\<^sub>i- aa \<^sub>f+ aa)")
  apply simp
  apply (subgoal_tac "add_set f (aug_pm_set z i {a}) n \<subseteq> addition_set f (aug_pm_set z i {a})")
  apply (frule_tac A = "add_set f (aug_pm_set z i {a}) n" and B = "addition_set f (aug_pm_set z i {a})" and c = "\<^sub>i- a" in subsetD, assumption+)
  apply (simp add:bop_closed) apply (simp add:addition_inc_add)
  apply blast
 apply simp
 apply (case_tac "t = z") apply simp
  apply (subgoal_tac "add_set f (aug_pm_set z i {a}) n \<subseteq> addition_set f (aug_pm_set z i {a})")
  apply (frule_tac A = "add_set f (aug_pm_set z i {a}) n" and B = "addition_set f (aug_pm_set z i {a})" and c = "\<^sub>i- a" in subsetD, assumption+)
  apply (subgoal_tac "z \<in> addition_set f (aug_pm_set z i {a})")
  apply (subgoal_tac " \<^sub>i- a \<^sub>f+ z =  \<^sub>i- a") apply simp
  apply (subgoal_tac " \<^sub>i- a \<in> add_set f {\<^sub>i- a} 0") apply blast
  apply simp
  apply (subst aug_commute, assumption+) apply (simp add:zeroA_def)
  apply assumption apply (simp add:addition_inc_add)
  apply simp
  apply (subgoal_tac " \<^sub>i- a \<^sub>f+ \<^sub>i- a \<in> add_set f {\<^sub>i- a} (Suc 0)")
  apply blast
  apply simp apply simp
  apply (subgoal_tac "s \<in> add_set f {\<^sub>i- a} (Suc (m2 - Suc 0))")
  apply (case_tac "t = a")
  apply (simp del:Suc_pred add_set_Suc)
 apply (simp del:Suc_pred add_set_Suc add:aug_pm_aug_pm_minus)
 apply (frule iop_cond2_minus [of "a" "i" "z" "f"], assumption+)
 apply (frule iop_cond1_minus[of "a" "i"])
 apply (frule inv_iop_minus [of "a" "i" "z" "f"], assumption+)
 apply (frule zeroA_minus [of "a" "i" "z" "f" "z"], assumption+)
 apply (frule_tac n = "m2 - Suc 0" in fag_single_additionTr1 [of "f" "z" "i" "\<^sub>i- a"], assumption+)
 apply (subgoal_tac "s \<^sub>f+ \<^sub>i- (\<^sub>i- a) \<in> add_set f {\<^sub>i- a} (m2 - Suc 0)")
 prefer 2 apply simp
 apply (thin_tac "\<forall>s. s \<in> add_set f {\<^sub>i- a} (Suc (m2 - Suc 0)) \<longrightarrow>
              s \<^sub>f+ \<^sub>i- (\<^sub>i- a) \<in> add_set f {\<^sub>i- a} (m2 - Suc 0)")
 apply (subgoal_tac " \<^sub>i- (\<^sub>i- a) = a") apply simp apply blast
 apply (simp add:iop_cond1_def) apply (simp del:Suc_pred add_set_Suc)
 prefer 2 apply simp
 apply (case_tac "t = z") apply (simp del:add_set_Suc) apply (subgoal_tac "s \<^sub>f+ z = s")
 apply simp apply blast
 apply (subst aug_commute, assumption+)
 apply (subgoal_tac "add_set f (aug_pm_set z i {a}) n \<subseteq> addition_set f (aug_pm_set z i {a})") apply (simp add:subsetD) apply (simp add:addition_inc_add)
 apply (simp add:addition_set_inc_z)
 apply (subgoal_tac "s \<in> addition_set f (aug_pm_set z i {a})")
 apply (simp add:zeroA_def)
 apply (subgoal_tac "add_set f (aug_pm_set z i {a}) n \<subseteq> addition_set f (aug_pm_set z i {a})") apply (simp add:subsetD) apply (simp add:addition_inc_add)
 apply (simp del:Suc_pred add_set_Suc)
 apply (thin_tac "s \<in> add_set f (aug_pm_set z i {a}) n")
 apply (thin_tac "s \<in> add_set f {\<^sub>i- a} (Suc (m2 - Suc 0))")
 apply (subgoal_tac " s \<^sub>f+ \<^sub>i- a \<in> add_set f {\<^sub>i- a} (Suc m2)")
 apply blast apply simp apply blast
done

(** remark at first show z \<in> addition_set and a \<in> addition_set **)

lemma fag_single_elem:"\<lbrakk>commute_bop f (aug_pm_set z i {a}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; x \<in> addition_set f (aug_pm_set z i {a})\<rbrakk> \<Longrightarrow>  (\<exists>n1. x \<in> add_set f {a} n1) \<or> (\<exists>m1. x \<in> add_set f {\<^sub>i- a} m1) \<or> x = z"
apply (simp add:addition_set_def)
apply (subgoal_tac "\<forall>xa. (\<exists>n. xa = add_set f (aug_pm_set z i {a}) n) \<and> x \<in> xa
\<longrightarrow> (\<exists>n1. x \<in> add_set f {a} n1) \<or> (\<exists>m1. x \<in> add_set f {\<^sub>i- a} m1) \<or> x = z")
apply blast
 apply (thin_tac "\<exists>xa. (\<exists>n. xa = add_set f (aug_pm_set z i {a}) n) \<and> x \<in> xa")
 apply (rule allI) apply (rule impI) apply (erule conjE)
 apply (subgoal_tac "\<forall>n. xa = add_set f (aug_pm_set z i {a}) n \<longrightarrow>
 (\<exists>n1. x \<in> add_set f {a} n1) \<or> (\<exists>m1. x \<in> add_set f {\<^sub>i- a} m1) \<or> x = z")
 apply blast apply (thin_tac "\<exists>n. xa = add_set f (aug_pm_set z i {a}) n")
 apply (rule allI) apply (rule impI) apply simp
apply (simp add:fag_single_elemTr)
done

lemma add_set_single1Tr:"\<lbrakk>commute_bop f (aug_pm_set z i {a}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z\<rbrakk> \<Longrightarrow> \<forall>x y. x \<in> add_set f {a} n \<and> y \<in> add_set f {a} n \<longrightarrow> x = y"
apply (induct_tac n)
 apply (rule allI)+ apply (rule impI) apply (erule conjE)
 apply simp
apply (rule allI)+ apply (rule impI) apply simp apply (erule conjE)
apply (subgoal_tac "\<forall>s1\<in>add_set f {a} n. x = s1 \<^sub>f+ a \<longrightarrow> x = y")
 apply blast apply (thin_tac "\<exists>s\<in>add_set f {a} n. x = s \<^sub>f+ a")
 apply (rule ballI) apply (rule impI)
apply (subgoal_tac "\<forall>s2\<in>add_set f {a} n. y = s2 \<^sub>f+ a \<longrightarrow> x = y")
 apply blast apply (thin_tac "\<exists>s\<in>add_set f {a} n. y = s \<^sub>f+ a")
 apply (rule ballI) apply (rule impI)
 apply (subgoal_tac "s1 = s2")  apply simp
 apply simp
done

lemma add_set_single_nonempty1:"\<lbrakk>commute_bop f (aug_pm_set z i {a}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z\<rbrakk> \<Longrightarrow>
 \<exists>x. x\<in>add_set f {a} n"
apply (induct_tac n)
 apply simp
 apply (subgoal_tac "\<forall>x. x \<in> add_set f {a} n \<longrightarrow> (\<exists>x. x \<in> add_set f {a} (Suc n))") apply blast apply (thin_tac "\<exists>x. x \<in> add_set f {a} n")
 apply (rule allI) apply (rule impI)
 apply (subgoal_tac "(x \<^sub>f+ a) \<in> add_set f {a} (Suc n)")
 apply blast
 apply simp apply blast
done

lemma add_set_single_nonempty2:"\<lbrakk>commute_bop f (aug_pm_set z i {a}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z\<rbrakk> \<Longrightarrow>
 \<exists>x. x\<in>add_set f {\<^sub>i- a} n"
apply (simp add:aug_pm_aug_pm_minus)
apply (frule iop_cond1_minus[of "a" "i"])
apply (frule iop_cond2_minus[of "a" "i" "z" "f"], assumption+)
apply (frule inv_iop_minus[of "a" "i" "z" "f"], assumption+)
apply (frule zeroA_minus[of "a" "i" "z" "f" "z"], assumption+)
apply (simp add:add_set_single_nonempty1 [of "f" "z" "i" "\<^sub>i- a" "n"])
done

lemma add_set_single1:"\<lbrakk>commute_bop f (aug_pm_set z i {a}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; x \<in> add_set f {a} n; y \<in> add_set f {a} n\<rbrakk> \<Longrightarrow> x = y"
apply (frule add_set_single1Tr [of "f" "z" "i" "a" "n"], assumption+)
apply blast
done

lemma add_set_single2:"\<lbrakk>commute_bop f (aug_pm_set z i {a}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; x \<in> add_set f {\<^sub>i- a} n; y \<in> add_set f {\<^sub>i- a} n\<rbrakk> \<Longrightarrow>  x = y"
apply (simp add:aug_pm_aug_pm_minus)
apply (frule iop_cond1_minus[of "a" "i"])
apply (frule iop_cond2_minus[of "a" "i" "z" "f"], assumption+)
apply (frule inv_iop_minus[of "a" "i" "z" "f"], assumption+)
apply (frule zeroA_minus[of "a" "i" "z" "f" "z"], assumption+)
apply (rule add_set_single1 [of "f" "z" "i" "\<^sub>i- a" _ "n" _], assumption+)
done

lemma fag_single_additionTr4:"\<lbrakk>commute_bop f (aug_pm_set z i {a});
assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z \<rbrakk> \<Longrightarrow> \<forall>s t. s \<in> add_set f {a} n \<and> t \<in> add_set f {\<^sub>i- a} n\<longrightarrow> s \<^sub>f+ t = z"
 apply (subgoal_tac "a \<in> addition_set f (aug_pm_set z i {a})")
 prefer 2
 apply (subgoal_tac "aug_pm_set z i {a} \<subseteq> addition_set f (aug_pm_set z i {a})") apply (subgoal_tac "a \<in> aug_pm_set z i {a}") apply (simp add:subsetD)
 apply (simp add:aug_pm_set_def) apply (simp add:addition_inc_add0)
apply (induct_tac n)
 apply simp
 apply (frule inv_aug_addition [of "f" "z" "i" "{a}"], assumption+)
 apply (frule aug_iop_closed [of "f" "z" "i" "{a}" "a"], assumption+)
 apply (frule fag_single_additionTr2 [of "f" "z" "i" "a" "a"], assumption+)
 apply simp apply assumption
apply (rule allI)+ apply (rule impI) apply (erule conjE)
 apply simp
 apply (subgoal_tac "\<forall>s1\<in>add_set f {a} n. s = s1 \<^sub>f+ a \<longrightarrow> s \<^sub>f+ t = z")
 apply blast apply (thin_tac "\<exists>sa\<in>add_set f {a} n. s = sa \<^sub>f+ a")
 apply (rule ballI) apply (rule impI) apply simp apply (thin_tac "s = s1 \<^sub>f+ a")
 apply (subgoal_tac "\<forall>s2\<in>add_set f {\<^sub>i- a} n. t = s2 \<^sub>f+ \<^sub>i- a \<longrightarrow> (s1 \<^sub>f+ a \<^sub>f+ t = z)") apply blast apply (thin_tac "\<exists>s\<in>add_set f {\<^sub>i- a} n. t = s \<^sub>f+ \<^sub>i- a")
 apply (rule ballI) apply (rule impI)
 apply (frule aug_iop_closed [of "f" "z" "i" "{a}" "a"], assumption+)
 apply simp
 apply (subgoal_tac "s1 \<^sub>f+ s2 = z") prefer 2 apply simp
 apply (thin_tac "\<forall>s t. s \<in> add_set f {a} n \<and> t \<in> add_set f {\<^sub>i- a} n \<longrightarrow> s \<^sub>f+ t = z")
apply (subgoal_tac "s1 \<in> addition_set f (aug_pm_set z i {a})")
 apply (subgoal_tac "s2 \<in> addition_set f (aug_pm_set z i {a})")
 apply (frule_tac x = s2 in aug_bop_closed [of "z" "i" "{a}" "f" _ " \<^sub>i- a"],
  assumption+)
 apply (frule_tac x = s1 and y = a and z = "s2 \<^sub>f+ \<^sub>i- a" in
                 addition_assoc [of "aug_pm_set z i {a}" "f"], assumption+)
 apply simp apply (thin_tac "s1 \<^sub>f+ a \<^sub>f+ (s2 \<^sub>f+ \<^sub>i- a) = s1 \<^sub>f+ (a \<^sub>f+ (s2 \<^sub>f+ \<^sub>i- a))")
 apply (frule_tac x1 = a and y1 = s2 and z1 = "\<^sub>i- a" in addition_assoc [THEN sym, of "aug_pm_set z i {a}" "f"], assumption+) apply simp
 apply (frule_tac y = s2 in aug_commute [of "f" "z" "i" "{a}" "a"], assumption+) apply simp
 apply (frule_tac x = s2 and y = a and z = "\<^sub>i- a" in
                 addition_assoc [of "aug_pm_set z i {a}" "f"], assumption+)
 apply simp apply (thin_tac "a \<^sub>f+ (s2 \<^sub>f+ \<^sub>i- a) = s2 \<^sub>f+ (a \<^sub>f+ \<^sub>i- a)")
 apply (thin_tac "a \<^sub>f+ s2 = s2 \<^sub>f+ a")
 apply (thin_tac "s2 \<^sub>f+ a \<^sub>f+ \<^sub>i- a = s2 \<^sub>f+ (a \<^sub>f+ \<^sub>i- a)")
 apply (thin_tac "s2 \<^sub>f+ \<^sub>i- a \<in> addition_set f (aug_pm_set z i {a})")
 apply (frule_tac y = " \<^sub>i- a" in aug_commute [of "f" "z" "i" "{a}" "a"], assumption+) apply simp
 apply (frule_tac x = s1 and y = a and z = "s2 \<^sub>f+ \<^sub>i- a" in
                 addition_assoc [of "aug_pm_set z i {a}" "f"], assumption+)
 apply (frule_tac x = s2 in aug_bop_closed [of "z" "i" "{a}" "f" _ " \<^sub>i- a"],
  assumption+)
 apply (thin_tac "s1 \<^sub>f+ a \<^sub>f+ (s2 \<^sub>f+ \<^sub>i- a) = s1 \<^sub>f+ (a \<^sub>f+ (s2 \<^sub>f+ \<^sub>i- a))")
 apply (thin_tac "a \<^sub>f+ \<^sub>i- a = \<^sub>i- a \<^sub>f+ a")
 apply (frule inv_aug_addition [of "f" "z" "i" "{a}" ], assumption+)
 apply (subgoal_tac " \<^sub>i- a \<^sub>f+ a = z") prefer 2 apply simp apply simp
 apply (thin_tac "\<forall>a\<in>addition_set f (aug_pm_set z i {a}). \<^sub>i- a \<^sub>f+ a = z")
 apply (frule_tac x = s2 and y = z in aug_commute [of "f" "z" "i" "{a}"], assumption+)
 apply (simp add:addition_set_inc_z)
apply (frule_tac x = s2 and y = z in aug_commute [of "f" "z" "i" "{a}"], assumption+) apply (simp add:addition_set_inc_z) apply simp
 apply (simp add:zeroA_def)
 apply (subgoal_tac "{\<^sub>i- a} \<subseteq> (aug_pm_set z i {a})")
 apply (frule_tac n = n in add_set_mono[of "{\<^sub>i- a}" "aug_pm_set z i {a}" "f"])
 apply (frule_tac A = "add_set f {\<^sub>i- a} n" and B = "add_set f (aug_pm_set z i {a}) n" and c = s2 in subsetD, assumption+)
 apply (subgoal_tac "add_set f (aug_pm_set z i {a}) n \<subseteq> addition_set f (aug_pm_set z i {a})") apply (simp add:subsetD) apply (simp add:addition_inc_add)
 apply (rule subsetI) apply (simp add:aug_pm_set_def minus_set_def)
 apply (subgoal_tac "{a} \<subseteq> (aug_pm_set z i {a})")
 apply (frule_tac n = n in add_set_mono[of "{a}" "aug_pm_set z i {a}" "f"])
 apply (frule_tac A = "add_set f {a} n" and B = "add_set f (aug_pm_set z i {a}) n" and c = s1 in subsetD, assumption+)
 apply (subgoal_tac "add_set f (aug_pm_set z i {a}) n \<subseteq> addition_set f (aug_pm_set z i {a})") apply (simp add:subsetD) apply (simp add:addition_inc_add)
 apply (rule subsetI) apply (simp add:aug_pm_set_def minus_set_def)
done

lemma fag_single_additionTr4_1:"\<lbrakk>commute_bop f (aug_pm_set z i {a});
assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z;s \<in> add_set f {a} n; t \<in> add_set f {\<^sub>i- a} n \<rbrakk> \<Longrightarrow> s \<^sub>f+ t = z"
apply (frule fag_single_additionTr4[of "f" "z" "i" "a" "n"], assumption+)
 apply blast
done

lemma fag_single_additionTr5:"\<lbrakk>assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z\<rbrakk> \<Longrightarrow>  \<forall>m. m < Suc n \<longrightarrow> (THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+ (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} (n - m))"
 apply (subgoal_tac "a \<in> addition_set f (aug_pm_set z i {a})")
 prefer 2
 apply (subgoal_tac "aug_pm_set z i {a} \<subseteq> addition_set f (aug_pm_set z i {a})") apply (subgoal_tac "a \<in> aug_pm_set z i {a}") apply (simp add:subsetD)
 apply (simp add:aug_pm_set_def) apply (simp add:addition_inc_add0)
 apply (subgoal_tac "z \<in> addition_set f (aug_pm_set z i {a})")
 prefer 2  apply (simp add:aug_addition_inc_z)
 apply (frule aug_iop_closed [of "f" "z" "i" "{a}" "a"], assumption+)
apply (induct_tac n) apply (rule allI) apply (rule impI) apply simp
apply (simp add: addition_assoc [of "aug_pm_set z i {a}" "f" "a" "a" "\<^sub>i- a"])
 apply (frule fag_single_additionTr2 [of "f" "z" "i" "a" "a"], assumption+)
 apply simp apply simp
 apply (thin_tac "a \<^sub>f+ \<^sub>i- a = z")
 apply (simp add:aug_commute [of "f" "z" "i" "{a}" "a" "z"])
 apply (simp add:zeroA_def)
apply (rule allI) apply (rule impI)
apply (subgoal_tac "(THE x. x \<in> add_set f {a} (Suc (Suc n))) = (THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+ a")
 apply (simp del:add_set_Suc)
 apply (subgoal_tac "Suc m \<le> Suc (Suc n)") prefer 2 apply (simp add: Suc_leI)
 apply (case_tac "Suc m = Suc (Suc n)")
  apply (frule_tac x = m and y = "Suc n" in Suc_inject)
  apply (thin_tac "Suc m = Suc (Suc n)")
  apply (rotate_tac -1) apply (frule sym) apply (thin_tac "m = Suc n")
  apply (thin_tac "\<forall>m. m < Suc n \<longrightarrow> (THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+
  (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} (n - m))")
  apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc (Suc n))) =
             (THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+ a")
  apply simp
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} m) \<in> addition_set f (aug_pm_set z i {a})")
 apply (subgoal_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m) \<in> addition_set f (aug_pm_set z i {a})")
 apply (frule_tac x = "THE x. x \<in> add_set f {a} m" and y = a and z = "THE x. x \<in> add_set f {\<^sub>i- a} m" in addition_assoc [of "aug_pm_set z i {a}" "f"], assumption+) apply simp
 apply (thin_tac "(THE x. x \<in> add_set f {a} m) \<^sub>f+ a \<^sub>f+ (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} m) \<^sub>f+ (a \<^sub>f+ (THE x. x \<in> add_set f {\<^sub>i- a} m))")
 apply (frule_tac x = a and y = "THE x. x \<in> add_set f {\<^sub>i- a} m" in aug_commute [of "f" "z" "i" "{a}"], assumption+) apply simp
 apply (thin_tac "a \<^sub>f+ (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {\<^sub>i- a} m) \<^sub>f+ a")
 apply (frule_tac x1 = "THE x. x \<in> add_set f {a} m" and y1 = "THE x. x \<in> add_set f {\<^sub>i- a} m" and z1 = a in addition_assoc[THEN sym, of "aug_pm_set z i {a}" "f"], assumption+)  apply simp
 apply (frule_tac n = m in fag_single_additionTr4 [of "f" "z" "i" "a"], assumption+)
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} m) \<^sub>f+ (THE x. x \<in> add_set f {\<^sub>i- a} m) = z")
 prefer 2
 apply (thin_tac "(THE x. x \<in> add_set f {a} m)
             \<in> addition_set f (aug_pm_set z i {a})")
 apply (thin_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m)
             \<in> addition_set f (aug_pm_set z i {a})")
 apply (thin_tac "(THE x. x \<in> add_set f {a} m) \<^sub>f+ ((THE x. x \<in> add_set f {\<^sub>i- a} m) \<^sub>f+ a) = (THE x. x \<in> add_set f {a} m) \<^sub>f+ (THE x. x \<in> add_set f {\<^sub>i- a} m)  \<^sub>f+ a")
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} m) \<in> add_set f {a} m")
 apply (subgoal_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m) \<in> add_set f {\<^sub>i- a} m")
  apply simp
  apply (thin_tac "\<forall>s t. s \<in> add_set f {a} m \<and> t \<in> add_set f {\<^sub>i- a} m \<longrightarrow> s \<^sub>f+ t = z")
  apply (thin_tac "(THE x. x \<in> add_set f {a} m) \<in> add_set f {a} m")
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty2)
  apply (simp add:add_set_single2)
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty1)
  apply (simp add:add_set_single1)
  apply (thin_tac "\<forall>s t. s \<in> add_set f {a} m \<and> t \<in> add_set f {\<^sub>i- a} m \<longrightarrow>
                   s \<^sub>f+ t = z")
  apply simp apply (simp add:zeroA_def)
 apply (subgoal_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m) \<in> add_set f {\<^sub>i- a} m")
 apply (subgoal_tac "{\<^sub>i- a} \<subseteq> (aug_pm_set z i {a})")
 apply (frule_tac n = m in add_set_mono[of "{\<^sub>i- a}" "aug_pm_set z i {a}" "f"])
 apply (frule_tac A = "add_set f {\<^sub>i- a} m" and B = "add_set f (aug_pm_set z i {a}) m" and c = "THE x. x \<in> add_set f {\<^sub>i- a} m" in subsetD, assumption+)
 apply (subgoal_tac "add_set f (aug_pm_set z i {a}) m \<subseteq> addition_set f (aug_pm_set z i {a})")  apply (simp add:subsetD) apply (simp add:addition_inc_add)
 apply (rule subsetI) apply (simp add:aug_pm_set_def minus_set_def)
 apply (thin_tac "(THE x. x \<in> add_set f {a} m)
             \<in> addition_set f (aug_pm_set z i {a})")
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty2)
  apply (simp add:add_set_single2)
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} m) \<in> add_set f {a} m")
 apply (subgoal_tac "{a} \<subseteq> (aug_pm_set z i {a})")
 apply (frule_tac n = m in add_set_mono[of "{a}" "aug_pm_set z i {a}" "f"])
 apply (frule_tac A = "add_set f {a} m" and B = "add_set f (aug_pm_set z i {a}) m" and c = "THE x. x \<in> add_set f {a} m" in subsetD, assumption+)
 apply (subgoal_tac "add_set f (aug_pm_set z i {a}) m \<subseteq> addition_set f (aug_pm_set z i {a})")  apply (simp add:subsetD) apply (simp add:addition_inc_add)
 apply (rule subsetI) apply (simp add:aug_pm_set_def minus_set_def)
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty1)
  apply (simp add:add_set_single1) apply (simp del:add_set_Suc)
 apply (frule_tac m = m and n = "Suc n" in le_imp_less_or_eq)
 apply (thin_tac "m \<le> Suc n") apply (simp del:add_set_Suc)
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+
       (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} (n - m))")
 prefer 2 apply simp
 apply (thin_tac "\<forall>m. m < Suc n \<longrightarrow> (THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+
 (THE x. x \<in> add_set f {\<^sub>i- a} m) =  (THE x. x \<in> add_set f {a} (n - m))")
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc (Suc n))) =
             (THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+ a")
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<in> add_set f {a} (Suc n)")
 prefer 2
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp del:add_set_Suc add:add_set_single_nonempty1)
  apply (simp del:add_set_Suc add:add_set_single1)
 apply (subgoal_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m) \<in> add_set f {\<^sub>i- a} m")
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<in> addition_set f (aug_pm_set z i {a})")
 apply (subgoal_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m) \<in> addition_set f (aug_pm_set z i {a})")
 apply (frule_tac x = "THE x. x \<in> add_set f {a} (Suc n)" and y = a and z = "THE x. x \<in> add_set f {\<^sub>i- a} m" in addition_assoc [of "aug_pm_set z i {a}" "f"], assumption+) apply (simp del:add_set_Suc)
 apply (frule_tac x = a and y = "THE x. x \<in> add_set f {\<^sub>i- a} m" in aug_commute [of "f" "z" "i" "{a}"], assumption+) apply (simp del:add_set_Suc)
apply (frule_tac x1 = "THE x. x \<in> add_set f {a} (Suc n)" and y1 = "THE x. x \<in> add_set f {\<^sub>i- a} m" and z1 = a in addition_assoc[THEN sym, of "aug_pm_set z i {a}" "f"], assumption+)  apply (simp del:add_set_Suc)
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+
       (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} (n - m))")
 apply (thin_tac " (THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+ a \<^sub>f+
  (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} (n - m)) \<^sub>f+ a")
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+
 ((THE x. x \<in> add_set f {\<^sub>i- a} m) \<^sub>f+ a) = (THE x. x \<in> add_set f {a} (n - m)) \<^sub>f+ a")
 apply (thin_tac "a \<^sub>f+ (THE x. x \<in> add_set f {\<^sub>i- a} m) =
                       (THE x. x \<in> add_set f {\<^sub>i- a} m) \<^sub>f+ a")
 apply (subgoal_tac "Suc n - m = Suc (n - m)") apply (simp del:add_set_Suc)
 apply (thin_tac "Suc n - m = Suc (n - m)")
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (Suc (n - m))) \<in> add_set f {a}
 (Suc (n - m))")
 apply (subgoal_tac "\<exists>s\<in>add_set f {a} (n - m). (THE x. x \<in>add_set f {a} (Suc (n - m))) = s \<^sub>f+ a") prefer 2 apply simp
 apply (subgoal_tac "\<forall>s\<in>add_set f {a} (n - m). (THE x. x\<in>add_set f {a} (Suc (n - m))) = s \<^sub>f+ a \<longrightarrow> (THE x. x \<in> add_set f {a} (n - m)) \<^sub>f+ a =
             (THE x. x \<in> add_set f {a} (Suc (n - m)))")
 apply blast apply (thin_tac "\<exists>s\<in>add_set f {a} (n - m).
                (THE x. x \<in> add_set f {a} (Suc (n - m))) = s \<^sub>f+ a")
 apply (rule ballI) apply (rule impI) apply (simp del:add_set_Suc)
 apply (thin_tac "s \<^sub>f+ a \<in> add_set f {a} (Suc (n - m))")
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc (n - m))) = s \<^sub>f+ a")
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (n - m)) = s ")
 apply simp
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (n - m)) \<in> add_set f {a} (n - m)")
 apply (simp add:add_set_single1)
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty1)
  apply (simp add:add_set_single1)
 apply (thin_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m) \<in> addition_set f (aug_pm_set z i {a})")
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<in> add_set f {a} (Suc n)")
 apply (thin_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m) \<in> add_set f {\<^sub>i- a} m")
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc n))
             \<in> addition_set f (aug_pm_set z i {a})")
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp del:add_set_Suc add:add_set_single_nonempty1)
  apply (simp del:add_set_Suc add:add_set_single1)
  apply (simp add:Suc_diff_le)
apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+
(THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} (n - m))")
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<in> add_set f {a} (Suc n)")
 apply (thin_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m) \<in> add_set f {\<^sub>i- a} m")
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc n))
             \<in> addition_set f (aug_pm_set z i {a})")
 apply (subgoal_tac "{\<^sub>i- a} \<subseteq> (aug_pm_set z i {a})")
 apply (frule_tac A = "{\<^sub>i- a}" and B = "(aug_pm_set z i {a})" and n = m and f = f in add_set_mono)
 apply (subgoal_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m) \<in> add_set f {\<^sub>i- a} m")
 apply (subgoal_tac "add_set f (aug_pm_set z i {a}) m \<subseteq> addition_set f (aug_pm_set z i {a})") apply (simp add:subsetD)+ apply (simp add:addition_inc_add)
 apply (thin_tac "add_set f {\<^sub>i- a} m \<subseteq> add_set f (aug_pm_set z i {a}) m")
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty2)
  apply (simp add:add_set_single2)
  apply (rule subsetI) apply (simp add:aug_pm_set_def minus_set_def)
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+
  (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} (n - m))")
 apply (thin_tac "(THE x. x \<in> add_set f {\<^sub>i- a} m) \<in> add_set f {\<^sub>i- a} m")
  apply (subgoal_tac "{a} \<subseteq> (aug_pm_set z i {a})")
  apply (frule_tac A = "{a}" and B = "aug_pm_set z i {a}" and n = "Suc n" and f = f in add_set_mono)
  apply (subgoal_tac "add_set f (aug_pm_set z i {a}) (Suc n) \<subseteq> addition_set f (aug_pm_set z i {a})") apply (simp del:add_set_Suc add:subsetD)+
  apply (simp del:add_set_Suc add:addition_inc_add)
  apply (rule subsetI) apply (simp add:aug_pm_set_def minus_set_def)
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+
       (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} (n - m))")
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<in> add_set f {a} (Suc n)")
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty2)
  apply (simp add:add_set_single2)
 apply (thin_tac "\<forall>m. m < Suc n \<longrightarrow> (THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+
 (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} (n - m))")
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (Suc (Suc n))) \<in> add_set f {a} (Suc (Suc n))")
 apply (subgoal_tac "\<exists>s\<in>add_set f {a} (Suc n). (THE x. x \<in> add_set f {a} (Suc (Suc n))) = s \<^sub>f+ a") prefer 2 apply simp
 apply (subgoal_tac "\<forall>s\<in>add_set f {a} (Suc n).  (THE x. x \<in> add_set f {a} (Suc (Suc n))) = s \<^sub>f+ a \<longrightarrow> (THE x. x \<in> add_set f {a} (Suc (Suc n))) =
             (THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+ a") apply blast
 apply (thin_tac "\<exists>s\<in>add_set f {a} (Suc n).
                (THE x. x \<in> add_set f {a} (Suc (Suc n))) = s \<^sub>f+ a")
 apply (rule ballI) apply (rule impI)
 apply (simp del:add_set_Suc)
 apply (thin_tac "(THE x. x \<in> add_set f {a} (Suc (Suc n))) = s \<^sub>f+ a")
 apply (thin_tac "s \<^sub>f+ a \<in> add_set f {a} (Suc (Suc n))")
 apply (subgoal_tac "s = (THE x. x \<in> add_set f {a} (Suc n))")
 apply (simp del:add_set_Suc)
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (Suc n)) \<in> add_set f {a} (Suc n)")
 apply (simp del:add_set_Suc add:add_set_single1)
 apply (thin_tac "s \<in> add_set f {a} (Suc n)")
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp del:add_set_Suc add:add_set_single_nonempty1)
  apply (simp del:add_set_Suc add:add_set_single1)
 apply (rule theI') apply (rule ex_ex1I)
  apply (simp del:add_set_Suc add:add_set_single_nonempty1)
  apply (simp del:add_set_Suc add:add_set_single1)
done

lemma fag_single_additionTr5_1:"\<lbrakk>assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; m < Suc n\<rbrakk> \<Longrightarrow> (THE x. x \<in> add_set f {a} (Suc n)) \<^sub>f+ (THE x. x \<in> add_set f {\<^sub>i- a} m) = (THE x. x \<in> add_set f {a} (n - m))"
apply (frule_tac n = n in fag_single_additionTr5 [of "z" "i" "a" "f"], assumption+) apply simp
done

lemma fag_single_additionTr5_2:"\<lbrakk>assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; n < Suc m\<rbrakk> \<Longrightarrow> (THE x. x \<in> add_set f {\<^sub>i- a} (Suc m)) \<^sub>f+ (THE x. x \<in> add_set f {a} n) = (THE x. x \<in> add_set f {\<^sub>i- a} (m - n))"
apply (simp del:add_set_Suc add:aug_pm_aug_pm_minus)
 apply (frule iop_cond1_minus[of "a" "i"])
 apply (frule iop_cond2_minus[of "a" "i" "z" "f"], assumption+)
 apply (frule inv_iop_minus[of "a" "i" "z" "f"], assumption+)
 apply (frule zeroA_minus[of "a" "i" "z" "f" "z"], assumption+)
 apply (subgoal_tac "\<^sub>i- (\<^sub>i- a) = a")
 apply (frule fag_single_additionTr5_1 [of "z" "i" "\<^sub>i- a" "f" "n" "m"], assumption+) apply (simp del:add_set_Suc)
 apply (simp add:iop_cond1_def)
done


constdefs
 free_gen_condition::"['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a, 'a, 'a] \<Rightarrow> bool"
 "free_gen_condition f i a z == \<forall>n. z \<notin> add_set f {a} n"

constdefs
 fg_elem_single::"['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a, 'a, 'a] \<Rightarrow> int \<Rightarrow> 'a"
 "fg_elem_single f i a z n == if 0 = n then z else
   (if 0 < n then (THE x. x \<in> (add_set f {a} (nat (n - 1))))
      else (THE x. x \<in> (add_set f {\<^sub>i- a} (nat (- n - 1)))))"

syntax
 "@FGELEMSNGLE"::"[int, 'a, 'a \<Rightarrow> 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a, 'a] \<Rightarrow> 'a"
             ("(5_\<Odot>_\<^sub>_\<^sub>,\<^sub>_\<^sub>,\<^sub>_)" [99,98,98,98,98]99)
translations
  "n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z" == "fg_elem_single f i a z n"

lemma  single_addition_pm_mem:"\<lbrakk>assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z\<rbrakk> \<Longrightarrow> (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<in> addition_set f (aug_pm_set z i {a})"
apply (case_tac "n = 0")
 apply (simp add:fg_elem_single_def) apply (simp add:aug_addition_inc_z)
 apply (frule_tac non_zero_int [of "n"])
apply (case_tac "0 < n")
 apply (simp add:fg_elem_single_def)
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (nat (n - 1))) \<in> add_set f {a} (nat (n - 1))")
 apply (subgoal_tac "add_set f {a} (nat (n - 1)) \<subseteq> addition_set f {a}")
 apply (subgoal_tac "addition_set f {a} \<subseteq>  addition_set f (aug_pm_set z i {a})") apply (simp add:subsetD)+
 apply (rule addition_set_mono)
 apply (rule subsetI) apply (simp add:aug_pm_set_def minus_set_def)
 apply (simp add:addition_inc_add)
 apply (rule theI')
  apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty1)
  apply (simp add:add_set_single1) apply (thin_tac "n \<noteq> 0")
 apply simp
 apply (simp add:fg_elem_single_def)
 apply (subgoal_tac "(THE x. x \<in> add_set f {\<^sub>i- a} (nat (- n - 1))) \<in> add_set f {\<^sub>i- a} (nat (- n - 1))")
 apply (subgoal_tac "add_set f {\<^sub>i- a} (nat (- n - 1)) \<subseteq> addition_set f {\<^sub>i- a}")
 apply (subgoal_tac "addition_set f {\<^sub>i- a} \<subseteq>  addition_set f (aug_pm_set z i {a})") apply (simp add:subsetD)+
 apply (rule addition_set_mono)
 apply (rule subsetI) apply (simp add:aug_pm_set_def minus_set_def)
 apply (simp add:addition_inc_add)
 apply (rule theI')
  apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty2)
  apply (simp add:add_set_single2)
done

lemma assoc_aug_assoc:"assoc_bop (aug_pm_set z i {a}) f \<Longrightarrow> assoc_bop {a} f"
apply (simp add:assoc_bop_def)
apply (rule ballI)+
apply (subgoal_tac "{a} \<subseteq> aug_pm_set z i {a}")
apply (frule addition_set_mono[of "{a}" "aug_pm_set z i {a}" "f"])
 apply (frule_tac c = aa in subsetD[of "addition_set f {a}" "addition_set f (aug_pm_set z i {a})"], assumption+)
 apply (frule_tac c = b in subsetD[of "addition_set f {a}" "addition_set f (aug_pm_set z i {a})"], assumption+)
 apply (frule_tac c = c in subsetD[of "addition_set f {a}" "addition_set f (aug_pm_set z i {a})"], assumption+)
 apply simp
 apply (rule subsetI)
 apply (simp add:aug_pm_set_def minus_set_def)
done

lemma single_addition_posTr:"\<lbrakk>commute_bop f (aug_pm_set z i {(a::'a)}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; 0 < (n::int); 0 < (m::int)\<rbrakk> \<Longrightarrow> (THE x. x \<in> add_set f {a} (nat (n - 1))) \<^sub>f+
(THE x. x \<in> add_set f {a} (nat (m - 1))) = (THE x. x \<in> add_set f {a} (nat (n + m - 1)))"
apply (subgoal_tac "(THE x. x \<in> add_set f {a} (nat (n - 1))) \<in> add_set f {a} (nat (n - 1))")
apply (subgoal_tac "(THE x. x \<in> add_set f {a} (nat (m - 1))) \<in> add_set f {a} (nat (m - 1))")
apply (subgoal_tac "(THE x. x \<in> add_set f {a} (nat (n + m - 1))) \<in> add_set f {a} (nat (n + m - 1))")
apply (frule assoc_aug_assoc [of "z" "i" "a" "f"])
apply (frule_tac x = "THE x. x \<in> add_set f {a} (nat (n - 1))" and y = "THE x. x \<in> add_set f {a} (nat (m - 1))" in bop_closed1 [of "{a}" "f" _ "nat (n - 1)" _ "nat (m - 1)"], assumption+)
apply (subgoal_tac "nat (n - 1) + nat (m - 1) + Suc 0 = nat (n + m - 1)")
apply (simp del:add_set_Suc)
apply (simp add:add_set_single1)
prefer 2
  apply (thin_tac "(THE x. x \<in> add_set f {a} (nat (n - 1)))
       \<in> add_set f {a} (nat (n - 1))")
  apply (thin_tac "(THE x. x \<in> add_set f {a} (nat (m - 1)))
       \<in> add_set f {a} (nat (m - 1))")
  apply (rule theI')
  apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty1)
  apply (simp add:add_set_single1)
prefer 2
  apply (rule theI')
  apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty1)
  apply (simp add:add_set_single1)
prefer 2
  apply (rule theI')
  apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty1)
  apply (simp add:add_set_single1)
apply (rule int_nat_add, assumption+)
done

lemma single_addition_pos:"\<lbrakk>commute_bop f (aug_pm_set z i {(a::'a)}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; 0 < (n::int); 0 < (m::int)\<rbrakk> \<Longrightarrow> (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = (n + m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"
apply (frule_tac single_addition_posTr [of "f" "z" "i" "a" "n" "m"], assumption+)
apply (simp add:fg_elem_single_def)
done

lemma single_addition_neg:"\<lbrakk>commute_bop f (aug_pm_set z i {(a::'a)}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; (n::int) < 0; (m::int) < 0 \<rbrakk> \<Longrightarrow> (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = (n + m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"
apply (simp add:fg_elem_single_def)
apply (simp del:add_set_Suc add:aug_pm_aug_pm_minus)
 apply (frule iop_cond1_minus[of "a" "i"])
 apply (frule iop_cond2_minus[of "a" "i" "z" "f"], assumption+)
 apply (frule inv_iop_minus[of "a" "i" "z" "f"], assumption+)
 apply (frule zeroA_minus[of "a" "i" "z" "f" "z"], assumption+)
apply (frule single_addition_posTr [of "f" "z" "i" "\<^sub>i- a" "- n" "- m"], assumption+) apply simp+
done

lemma single_addition_zero:"\<lbrakk>commute_bop f (aug_pm_set z i {(a::'a)}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z\<rbrakk> \<Longrightarrow> 0\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = z"
apply (simp add:fg_elem_single_def)
done

lemma s_a_p_1:"\<lbrakk>assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i;
iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; m < 0; 0 < n\<rbrakk> \<Longrightarrow> (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = (n + m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"
 apply (case_tac "- m < n")
 apply (simplesubst zminus_zadd_cancel [THEN sym, of "n" "m"])
 apply (subgoal_tac "0 < -m") apply (subgoal_tac "0 < m + n")
 apply (subst single_addition_pos[THEN sym, of "f" "z" "i" "a" "-m" "m + n"],
             assumption+)
 apply (subst zadd_assoc) apply (subst zadd_assoc)
 apply (simp add:zminus_zadd_cancel [of "m" "m + n"])
apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "-m"], assumption+)
 apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "m + n"], assumption+)
 apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "m"], assumption+)
 apply (subst addition_assoc, assumption+)
 apply (simp add:aug_commute[of "f" "z" "i" "{a}" "(m + n)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z" "m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"])
 apply (subst addition_assoc[THEN sym], assumption+)
 apply (subgoal_tac "((- m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = z") apply simp
 apply (simp add:zeroA_def)
 apply (simp add:fg_elem_single_def)
 apply (rule fag_single_additionTr4_1[of "f" "z" "i" "a"_ "nat (- m - 1)"], assumption+)
  apply (rule theI') apply (rule ex_ex1I)
   apply (simp add:add_set_single_nonempty1)
   apply (simp add:add_set_single1)
  apply (rule theI') apply (rule ex_ex1I)
   apply (simp add:add_set_single_nonempty2)
  apply (simp add:add_set_single2)
 apply simp+ apply (subgoal_tac "n \<le> - m") prefer 2 apply simp
 apply (thin_tac "\<not> - m < n")
 apply (frule zle_imp_zless_or_eq) apply (thin_tac "n \<le> - m")
 apply (case_tac "n = -m")
 apply (thin_tac "n < - m \<or> n = - m")   apply simp
 apply (subgoal_tac "0 < -m") apply (thin_tac "n = - m")
 apply (simp add:fg_elem_single_def)
 apply (rule fag_single_additionTr4_1 [of "f" "z" "i" "a" _ "nat (-m - 1)"], assumption+)
  apply (rule theI') apply (rule ex_ex1I)
   apply (simp add:add_set_single_nonempty1)
   apply (simp add:add_set_single1)
  apply (rule theI') apply (rule ex_ex1I)
   apply (simp add:add_set_single_nonempty2)
   apply (simp add:add_set_single2)
  apply simp
 apply simp
apply (simplesubst zminus_zadd_cancel [THEN sym, of "m" "n"])
 apply (subst single_addition_neg[THEN sym, of "f" "z" "i" "a" "-n" "n + m"], assumption+) apply simp apply simp apply simp
 apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "-n"], assumption+)
 apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "n + m"], assumption+)  apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "n"], assumption+)
 apply (simp add:addition_assoc[THEN sym])
 apply (subgoal_tac "(n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ ((- n)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = z") apply (simp add:zeroA_def)
 apply (thin_tac "(- n)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<in> addition_set f (aug_pm_set z i {a})")
 apply (thin_tac "(n + m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<in> addition_set f (aug_pm_set z i {a})")
 apply (thin_tac "n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<in> addition_set f (aug_pm_set z i {a})")
 apply (simp add:fg_elem_single_def)
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (nat (n - 1))) \<in> add_set f {a} (nat (n - 1))")
 apply (subgoal_tac "(THE x. x \<in> add_set f {\<^sub>i- a} (nat (n - 1))) \<in> add_set f {\<^sub>i- a} (nat (n - 1))")
 apply (simp add:fag_single_additionTr4_1)
 apply (rule theI') apply (rule ex_ex1I)
   apply (simp add:add_set_single_nonempty2)
   apply (simp add:add_set_single2)
  apply (rule theI') apply (rule ex_ex1I)
   apply (simp add:add_set_single_nonempty1)
   apply (simp add:add_set_single1)
done

lemma single_addition_pm:"\<lbrakk>commute_bop f (aug_pm_set z i {(a::'a)}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z\<rbrakk> \<Longrightarrow> (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = (n + m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"
apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "n"], assumption+)
 apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "m"], assumption+)
 apply (case_tac "n = 0")
 apply (subgoal_tac "(n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = z") apply simp
 apply (simp add:zeroA_def) apply (subst fg_elem_single_def) apply simp
 apply (case_tac "m = 0")
 apply (simp add:aug_commute)
 apply (subgoal_tac " (0\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = z") apply simp
 apply (simp add:zeroA_def) apply (subst fg_elem_single_def) apply simp
apply (frule_tac non_zero_int [of "n"]) apply (thin_tac "n \<noteq> 0")
apply (frule_tac non_zero_int [of "m"]) apply (thin_tac "m \<noteq> 0")
apply (case_tac "0 < n") apply (thin_tac "0 < n \<or> n < 0")
 apply (case_tac "0 < m") apply (thin_tac "0 < m \<or> m < 0")
 apply (simp add:single_addition_pos)
 apply simp apply (thin_tac "m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<in> addition_set f (aug_pm_set z i {a})")
apply (simp add:s_a_p_1)
 apply simp
 apply (subst aug_commute, assumption+)
 apply (case_tac "0 < m") apply (thin_tac "0 < m \<or> m < 0")
 apply (simp add:s_a_p_1) apply (simp add:zadd_commute)
apply simp
 apply (simp add:single_addition_neg) apply (simp add:zadd_commute)
done

lemma single_inv:"\<lbrakk>commute_bop f (aug_pm_set z i {(a::'a)}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z\<rbrakk> \<Longrightarrow>
      \<^sub>i- (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = (-m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"
apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "m"], assumption+)
 apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "- m"], assumption+)
apply (frule single_addition_pm[THEN sym, of "f" "z" "i" "a" "-m" "m"],
                                         assumption+) apply simp
apply (simp add:single_addition_zero)
 apply (subgoal_tac "z \<^sub>f+ (\<^sub>i- (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)) = ((- m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (\<^sub>i- (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z))") prefer 2 apply simp
 apply (frule aug_iop_closed [of "f" "z" "i" "{a}" "m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"], assumption+)
 apply (thin_tac "z = ((- m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)")
 apply (simp add:addition_assoc)
 apply (simp add:aug_commute [of "f" "z" "i" "{a}" "(m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)" "\<^sub>i- (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)"])
 apply (subgoal_tac "\<^sub>i- (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = z") apply simp
 apply (subgoal_tac "z \<in> addition_set f (aug_pm_set z i {a})")
 prefer 2 apply (simp add:addition_set_inc_z)
 apply (simp add:aug_commute[of "f" "z" "i" "{a}" "(- m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z" "z"])
 apply (simp add:zeroA_def)
 apply (simp add:inv_iop_def)
 apply (subgoal_tac "zeroA z i f {a} (\<^sub>i- (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z))")
 prefer 2  apply simp
 apply (frule aug_zero_unique[of "f" "z" "i" "{a}" "\<^sub>i- (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<^sub>f+ (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)"])
 apply (rule aug_bop_closed, assumption+)
 apply (rule sym) apply assumption
done

lemma free_ag_single:"\<lbrakk>commute_bop f (aug_pm_set z i {a}); assoc_bop (aug_pm_set z i {a}) f; iop_cond1 {a} i; iop_cond2 z {a} i f; iop_cond3 z i; inv_iop z i f {a}; commute_bop f (aug_pm_set z i {a}); zeroA z i f {a} z; free_gen_condition f i a z; n \<noteq> m\<rbrakk> \<Longrightarrow> (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<noteq> (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)"
apply (rule contrapos_pp, simp+)
apply (frule single_addition_pm[THEN sym, of "f" "z" "i" "a" "n" "-m"], assumption+) apply simp
apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "m"], assumption+)
 apply (frule single_addition_pm_mem[of "z" "i" "a" "f" "- m"], assumption+)
 apply (simp add:aug_commute [of "f" "z" "i" "{a}" "(m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)" "(- m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"])
 apply (simp add:single_inv[THEN sym, of "f" "z" "i" "a" "m"])
 apply (simp add:inv_aug_addition)
 apply (thin_tac "n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
 apply (thin_tac " \<^sub>i- (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<in> addition_set f (aug_pm_set z i {a})")
 apply (thin_tac " m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<in> addition_set f (aug_pm_set z i {a})")
 apply (insert int_neq_iff[of "n" "m"]) apply simp
 apply (case_tac "n < m") apply (thin_tac "n < m \<or> m < n")
 apply (frule single_inv [THEN sym, of "f" "z" "i" "a" "n - m"], assumption+)
 apply simp apply (subgoal_tac "\<^sub>i- z = z") apply simp
 apply (thin_tac " \<^sub>i- z = z") prefer 2  apply (simp add:iop_cond3_def)
 apply (subgoal_tac "0 < m - n") prefer 2 apply simp
 apply (thin_tac "(n - m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = z")
 apply (simp add:fg_elem_single_def)
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (nat (m - n - 1))) \<in> add_set f {a} (nat (m - n - 1))") apply simp
 apply (thin_tac "(THE x. x \<in> add_set f {a} (nat (m - n - 1))) = z")
 apply (simp add:free_gen_condition_def)
  apply (rule theI') apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty1)
   apply (simp add:add_set_single1) apply simp
 apply (subgoal_tac "0 < n - m") prefer 2 apply simp
 apply (simp add:fg_elem_single_def)
 apply (subgoal_tac "(THE x. x \<in> add_set f {a} (nat (n - m - 1))) \<in> add_set f {a} (nat (n - m - 1))") apply simp
 apply (thin_tac "(THE x. x \<in> add_set f {a} (nat (n - m - 1))) = z")
apply (simp add:free_gen_condition_def)
  apply (rule theI') apply (rule ex_ex1I)
  apply (simp add:add_set_single_nonempty1)
   apply (simp add:add_set_single1)
done

constdefs
 fags_cond::"['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a, 'a \<Rightarrow> 'a, 'a] \<Rightarrow> bool"
 "fags_cond f z i a == commute_bop f (aug_pm_set z i {a}) \<and> assoc_bop (aug_pm_set z i {a}) f \<and> iop_cond1 {a} i \<and> iop_cond2 z {a} i f \<and>  iop_cond3 z i \<and> inv_iop z i f {a} \<and> commute_bop f (aug_pm_set z i {a}) \<and>  zeroA z i f {a} z \<and> free_gen_condition f i a z"

lemma fag_single_free:"\<lbrakk>fags_cond f z i a; n \<noteq> m\<rbrakk> \<Longrightarrow> (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<noteq> (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)"
apply (simp add:fags_cond_def) apply (erule conjE)+
 apply (simp add:free_ag_single)
done

lemma fag_single_free1:"\<lbrakk>fags_cond f z i a;(n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)\<rbrakk> \<Longrightarrow> n = m"
apply (rule contrapos_pp, simp+)
apply (frule fag_single_free [of "f" "z" "i" "a" "n" "m"], assumption+)
apply simp
done

constdefs
 fags_carr::"['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a, 'a \<Rightarrow> 'a, 'a] \<Rightarrow> 'a set"
 "fags_carr f z i a == {x. \<exists>n. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z}"

constdefs
 fags_bop::"['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a, 'a \<Rightarrow> 'a, 'a] \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> 'a"
 "fags_bop f z i a == \<lambda>x\<in>(fags_carr f z i a). \<lambda>y\<in>(fags_carr f z i a).
    ((THE n. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) + (THE m. y = m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z))\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"

constdefs
 fags_iop::"['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a, 'a \<Rightarrow> 'a, 'a] \<Rightarrow> 'a \<Rightarrow> 'a"
 "fags_iop f z i a == \<lambda>x\<in>(fags_carr f z i a).
                                   (- (THE n. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z))\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"

lemma fags_mem:"fags_cond f z i a \<Longrightarrow> (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<in> fags_carr f z i a"
apply (simp add:fags_carr_def)
apply blast
done

lemma fags_iopTr:"fags_cond f z i a \<Longrightarrow> fags_iop f z i a (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = (- n)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"
apply (subgoal_tac "(n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<in>  fags_carr f z i a")
apply (simp add:fags_iop_def)
 apply (subgoal_tac "n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = (THE na. n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = na\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
 apply (frule_tac m = "THE na. n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = na\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z" in fag_single_free1 [of "f" "z" "i" "a" "n"], assumption+) apply simp
 apply (rule theI') apply (rule ex_ex1I) apply blast
 apply (simp add:fag_single_free1 [of "f" "z" "i" "a" ])
 apply (simp add:fags_mem)
done

lemma fags_bopTr:"fags_cond f z i a \<Longrightarrow> fags_bop f z i a (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) (m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = (n + m)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z"
apply (subgoal_tac "(n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<in>  fags_carr f z i a")
apply (subgoal_tac "(m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) \<in>  fags_carr f z i a")
apply (simp add:fags_bop_def)
 apply (subgoal_tac "n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = (THE na. n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = na\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
 apply (frule_tac m = "THE na. n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = na\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z" in fag_single_free1 [of "f" "z" "i" "a" "n"], assumption+)
 apply (subgoal_tac "m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = (THE ma. m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = ma\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
 apply (frule_tac m = "THE ma. m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = ma\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z" in fag_single_free1 [of "f" "z" "i" "a" "m"], assumption+)
 apply simp
 apply (rule theI') apply (rule ex_ex1I) apply blast
 apply (simp add:fag_single_free1 [of "f" "z" "i" "a" ])
 apply (rule theI') apply (rule ex_ex1I) apply blast
 apply (simp add:fag_single_free1 [of "f" "z" "i" "a" ])
apply (simp add:fags_carr_def) apply blast
apply (simp add:fags_carr_def) apply blast
done

constdefs
 fags :: "['a \<Rightarrow> 'a \<Rightarrow> 'a, 'a, 'a \<Rightarrow> 'a, 'a] \<Rightarrow> 'a AgroupType"
 "fags f z i a == \<lparr> carrier = fags_carr f z i a, pOp = fags_bop f z i a, mOp = fags_iop f z i a, zero = z\<rparr>"

lemma fags_ag:"fags_cond f z i a \<Longrightarrow> agroup (fags f z i a)"
apply (simp add:agroup_def)
apply (rule conjI)
 apply (rule bivar_func_test)
 apply (rule ballI)+
 apply (simp add:fags_def)
 apply (simp add:fags_carr_def)
 apply (subgoal_tac "\<forall>n1 n2. aa = n1\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<and> b = n2\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<longrightarrow>
                             (\<exists>n. fags_bop f z i a aa b = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)")
 apply blast apply (thin_tac "\<exists>n. aa = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
             apply (thin_tac "\<exists>n. b = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
 apply (rule allI)+
 apply (rule impI) apply (erule conjE) apply simp
  apply (simp add:fags_bopTr)
  apply blast
apply (rule conjI)
 apply (rule univar_func_test)
 apply (rule ballI)
 apply (simp add:fags_def)  apply (simp add:fags_carr_def)
 apply (subgoal_tac "\<forall>m. x = m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<longrightarrow> (\<exists>n. fags_iop f z i a x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)")
 apply blast apply (thin_tac "\<exists>n. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
 apply (rule allI) apply (rule impI) apply simp
 apply (simp add:fags_iopTr) apply blast
apply (rule conjI)
 apply (simp add:fags_def) apply (simp add:fags_carr_def)
 apply (simp add:fags_cond_def) apply (erule conjE)+
 apply (frule single_addition_zero[of "f" "z" "i" "a"], assumption+)
 apply (rotate_tac -1) apply (frule sym) apply (thin_tac "0\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = z")
 apply blast
apply (rule ballI)+
 apply (rule conjI)
 apply (simp add:fags_def) apply (thin_tac "y \<in> fags_carr f z i a")
 apply (thin_tac "za \<in> fags_carr f z i a") apply (simp add:fags_carr_def)
 apply (subgoal_tac "\<forall>n. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<longrightarrow> fags_bop f z i a z x = x")
 apply blast apply (thin_tac "\<exists>n. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
 apply (rule allI) apply (rule impI)
 apply (simp add:fags_cond_def) apply (erule conjE)+
 apply (frule single_addition_zero[of "f" "z" "i" "a"], assumption+)
 apply (rotate_tac -1) apply (frule sym) apply (thin_tac "0\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z = z")
 apply (subgoal_tac "fags_bop f z i a z (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) = fags_bop f z i a (0\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z) (n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z)") prefer 2 apply simp apply (thin_tac "z = 0\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z") apply simp
 apply (subgoal_tac "fags_cond f z i a")
 apply (simp add:fags_bopTr) apply (simp add:fags_cond_def)
apply (rule conjI)
 apply (simp add:fags_def)
 apply (thin_tac "y \<in> fags_carr f z i a")
 apply (thin_tac "za \<in> fags_carr f z i a")
 apply (simp add:fags_carr_def)
 apply (subgoal_tac "\<forall>n. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<longrightarrow> fags_bop f z i a (fags_iop f z i a x) x = z") apply blast apply (thin_tac "\<exists>n. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
 apply (rule allI) apply (rule impI) apply simp
 apply (simp add:fags_iopTr) apply (simp add:fags_bopTr)
 apply (simp add:fags_cond_def) apply (erule conjE)+
 apply (simp add:single_addition_zero)
apply (rule conjI)
 apply (simp add:fags_def) apply (simp add:fags_carr_def)
 apply (subgoal_tac "\<forall>n1 n2 n3. x = n1\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<and>  y = n2\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<and> za = n3\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<longrightarrow>  fags_bop f z i a (fags_bop f z i a x y) za = fags_bop f z i a x (fags_bop f z i a y za)") apply blast
 apply (thin_tac "\<exists>n. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z") apply (thin_tac "\<exists>n. y = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
 apply (thin_tac "\<exists>n. za = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z") apply (rule allI)+ apply (rule impI)
 apply (erule conjE)+ apply simp
 apply (simp add:fags_bopTr)+ apply (simp add:zadd_assoc)
apply (thin_tac "za \<in> carrier (fags f z i a)")
 apply (simp add:fags_def) apply (simp add:fags_carr_def)
 apply (subgoal_tac "\<forall>n m. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<and> y = m\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z \<longrightarrow> fags_bop f z i a x y = fags_bop f z i a y x") apply blast
 apply (thin_tac "\<exists>n. x = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z") apply (thin_tac "\<exists>n. y = n\<Odot>a\<^sub>f\<^sub>,\<^sub>i\<^sub>,\<^sub>z")
 apply (rule allI)+ apply (rule impI) apply (erule conjE) apply simp
 apply (simp add:fags_bopTr) apply (simp add:zadd_commute)
done

 section "2. Abelian Group generated by one element"

constdefs
 ag_single_gen::"['a AgroupType, 'a] \<Rightarrow> bool"
  "ag_single_gen G a == agroup G \<and> carrier G = \<Inter> {H. asubgroup G H \<and> a \<in> H}"

(* syntax
   "@AGSGEN"::"['a AgroupType, 'a] \<Rightarrow> bool"
    ("(_\<^sub>_)" [90,91]90)
translations
  "G\<^sub>a" == "ag_single_gen G a" *)

consts
 aSum :: "['a AgroupType, nat, 'a]  \<Rightarrow> 'a"

primrec
 aSum_0   :"aSum G 0 a = 0\<^sub>G"
 aSum_Suc :"aSum G (Suc n) a = aSum G n a +\<^sub>G a"

constdefs
 sprod_n_a ::"['a AgroupType, int, 'a]  \<Rightarrow> 'a"
 "sprod_n_a G n a == if 0 \<le> n then (aSum G (nat n) a)
                          else (aSum G (nat (- n)) (-\<^sub>G a))"

syntax
 "@SPRODNA" :: "[int, 'a, 'a AgroupType] \<Rightarrow> 'a"
                  ("(3_\<triangleright>_\<^sub>_)" [90,90,91]90)
translations
  "n\<triangleright>a\<^sub>G" == "sprod_n_a G n a"

lemma asum_mem:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow> aSum G n a \<in> carrier G"
apply (induct_tac n)
 apply simp apply (simp add:ag_inc_zero)
 apply simp
 apply (rule ag_pOp_closed, assumption+)
done

lemma nt_mem0:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow> n\<triangleright>a\<^sub>G \<in> carrier G"
apply (case_tac "n = 0") apply (simp add:sprod_n_a_def)
 apply (simp add:ag_inc_zero)
 apply (frule non_zero_int[of "n"])
 apply (case_tac "0 < n") apply (simp add:sprod_n_a_def)
 apply (simp add:asum_mem) apply (thin_tac "n \<noteq> 0") apply simp
apply (simp add:sprod_n_a_def)
 apply (rule asum_mem [of "G"], assumption+)
 apply (simp add:ag_mOp_closed)
done

lemma nt_zero0:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow> 0\<triangleright>a\<^sub>G = 0\<^sub>G"
apply (simp add:sprod_n_a_def)
done

lemma nt_1:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow> 1\<triangleright>a\<^sub>G = a"
apply (simp add:sprod_n_a_def)
apply (simp add:ag_l_zero)
done

lemma asumTr:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow> aSum G (n + m) a = aSum G n a +\<^sub>G (aSum G m a)"
apply (induct_tac m)
 apply simp
 apply (frule asum_mem[of "G" "a" "n"], assumption+)
apply (rule ag_r_zero [THEN sym, of "G" "aSum G n a"], assumption+)
 apply (subgoal_tac "n + Suc na = Suc (n + na)") apply simp
 apply (rule ag_pOp_assoc, assumption+)
 apply (simp add:asum_mem)+
done

lemma aSum_zero:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow> aSum G n (0\<^sub>G) = 0\<^sub>G"
apply (induct_tac n)
 apply simp apply simp apply (rule ag_r_zero, assumption+)
 apply (simp add:ag_inc_zero)
done

lemma agsum_add1p:"\<lbrakk>agroup G; a \<in> carrier G; 0 \<le> n; 0 \<le> m\<rbrakk> \<Longrightarrow>
                      (n + m)\<triangleright>a\<^sub>G = n\<triangleright>a\<^sub>G +\<^sub>G (m\<triangleright>a\<^sub>G)"
apply (simp add:sprod_n_a_def)
apply (subst nat_add_distrib[of "n" "m"], assumption+)
apply (simp add:asumTr)
done

lemma zdiff:"z - (w::int) = z + (- w)"
apply simp
done   (** later move this lemma to algebra1 **)

lemma agsum_add1m:"\<lbrakk>agroup G; a \<in> carrier G; n < 0; m < 0\<rbrakk> \<Longrightarrow>
                      (n + m)\<triangleright>a\<^sub>G = n\<triangleright>a\<^sub>G +\<^sub>G (m\<triangleright>a\<^sub>G)"
apply (simp add:sprod_n_a_def)
 apply (subst zdiff)
 apply (subgoal_tac "0 \<le> -n") apply (thin_tac "n < 0")
 apply (subgoal_tac "0 \<le> -m") apply (thin_tac "m < 0")
 apply (subst nat_add_distrib [of "-n" "-m"], assumption+)
 apply (rule asumTr, assumption+)
 apply (simp add:ag_mOp_closed) apply simp+
done

lemma agsum_add2Tr:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow>
                0\<^sub>G = aSum G n a +\<^sub>G (aSum G n (-\<^sub>G a))"
apply (induct_tac n)
 apply simp
 apply (frule ag_inc_zero[of "G"])
 apply (simp add:ag_r_zero[THEN sym])
apply simp
 apply (frule  ag_mOp_closed[of "G" "a"], assumption+)
 apply (frule_tac n = n in asum_mem [of "G" "-\<^sub>G a"], assumption+)
 apply (frule_tac x = "aSum G n (-\<^sub>G a)" in ag_pOp_closed [of "G" _ "-\<^sub>G a"],
                                 assumption+)
 apply (frule_tac n = n in asum_mem [of "G" "a"], assumption+)
 apply (subst ag_pOp_assoc[of "G" _ "a" _], assumption+)
 apply (subst ag_pOp_assoc[THEN sym, of "G" "a" _ "-\<^sub>G a"], assumption+)
 apply (subst ag_pOp_commute[of "G" "a" _], assumption+)
 apply (subst ag_pOp_assoc[of "G" _ "a" "-\<^sub>G a"], assumption+)
apply (frule sym) apply (thin_tac "0\<^sub>G =  aSum G n a +\<^sub>G (aSum G n (-\<^sub>G a))")
apply (simp add:ag_r_inv1[of "G" "a"])
 apply (subst ag_r_zero, assumption+) apply simp
done

lemma agsum_add2p:"\<lbrakk>agroup G; a \<in> carrier G; 0 \<le> n\<rbrakk> \<Longrightarrow>
                                    0\<^sub>G = n\<triangleright>a\<^sub>G +\<^sub>G ((-n)\<triangleright>a\<^sub>G) "
apply (case_tac "n = 0")
 apply (simp add:sprod_n_a_def)
 apply (frule ag_inc_zero[of "G"])
 apply (simp add:ag_r_zero[THEN sym])
apply (frule non_zero_int[of "n"]) apply (thin_tac "n \<noteq> 0") apply simp
 apply (subgoal_tac "-n < 0") prefer 2 apply simp
apply (simp add:sprod_n_a_def)
 apply (simp add:agsum_add2Tr)
done

lemma agsum_add2m:"\<lbrakk>agroup G; a \<in> carrier G; n < 0\<rbrakk> \<Longrightarrow>
                                    0\<^sub>G = n\<triangleright>a\<^sub>G +\<^sub>G ((-n)\<triangleright>a\<^sub>G) "
apply (simp add:sprod_n_a_def)
apply (subst ag_pOp_commute, assumption+)
 apply (rule asum_mem, assumption+)
 apply (simp add:ag_mOp_closed)
 apply (rule asum_mem, assumption+)
 apply (simp add:agsum_add2Tr)
done

lemma agsum_add3pm:"\<lbrakk>agroup G; a \<in> carrier G; 0 < n; m < 0\<rbrakk> \<Longrightarrow>
                        (n + m)\<triangleright>a\<^sub>G = n\<triangleright>a\<^sub>G +\<^sub>G (m\<triangleright>a\<^sub>G)"
apply (subgoal_tac "n < - m \<or> n = - m \<or> - m < n")
prefer 2 apply (simp add:zless_linear [of "n" "-m"])
apply (case_tac "n = -m")
 apply simp
 apply (subst ag_pOp_commute, assumption+)
 apply (simp add:nt_mem0)+
 apply (subgoal_tac "0\<triangleright>a\<^sub>G = 0\<^sub>G") apply (simp add:agsum_add2m)
apply (simp add:sprod_n_a_def) apply simp
apply (case_tac "n < -m")
 apply (simplesubst zminus_zadd_cancel[THEN sym, of "m" "n"])
 apply (subgoal_tac "-n < 0") prefer 2 apply simp  (** atode shiraberu **)
 apply (subgoal_tac "n + m < 0") prefer 2 apply simp  (** atode shiraberu *)
 apply (subst agsum_add1m [of "G" "a" "-n" "n + m"], assumption+)
 apply simp
 apply (subst ag_pOp_assoc [THEN sym], assumption+)
 apply (simp add:nt_mem0)+
 apply (subst agsum_add2p [THEN sym, of "G" "a" "n"], assumption+)
 apply simp
 apply (rule ag_l_zero[THEN sym, of "G" "(n + m)\<triangleright>a\<^sub>G"], assumption+)
 apply (simp add:nt_mem0)
 apply (thin_tac "n \<noteq> - m") apply simp
apply (subst zminus_zadd_cancel[THEN sym, of "n" "m"])
 apply (subgoal_tac "0 \<le> -m") prefer 2 apply simp  (** atode shiraberu **)
 apply (subgoal_tac "0 \<le> n + m") prefer 2 apply simp  (** atode shiraberu *)
 apply (frule agsum_add1p [of "G" "a" "-m" "n + m"], assumption+)
 apply simp apply (thin_tac "n\<triangleright>a\<^sub>G =  (- m)\<triangleright>a\<^sub>G +\<^sub>G (n + m)\<triangleright>a\<^sub>G")
 apply (subst ag_pOp_commute[of "G" "(- m)\<triangleright>a\<^sub>G" "(n + m)\<triangleright>a\<^sub>G"], assumption+)
 apply (simp add:nt_mem0)+
 apply (subst ag_pOp_assoc, assumption+)
 apply (simp add:nt_mem0)+
 apply (subst ag_pOp_commute [of "G" "(- m)\<triangleright>a\<^sub>G" "m\<triangleright>a\<^sub>G"], assumption+)
 apply (simp add:nt_mem0)+
 apply (simp add:agsum_add2m[THEN sym])
apply (rule ag_r_zero[THEN sym], assumption+)
 apply (simp add:nt_mem0)
done

lemma agsum_add3mp:"\<lbrakk>agroup G; a \<in> carrier G; n < 0; 0 < m\<rbrakk> \<Longrightarrow>
                        (n + m)\<triangleright>a\<^sub>G = n\<triangleright>a\<^sub>G +\<^sub>G (m\<triangleright>a\<^sub>G)"
apply (simp add:zadd_commute)
apply (subst ag_pOp_commute, assumption+) apply (simp add:nt_mem0)+
apply (simp add:agsum_add3pm)
done

lemma nt_sum0:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow> (n + m)\<triangleright>a\<^sub>G = n\<triangleright>a\<^sub>G +\<^sub>G (m\<triangleright>a\<^sub>G)"
apply (subgoal_tac "n < 0 \<or> n = 0 \<or> 0 < n")
  prefer 2 apply (simp add:zless_linear[of "n" "0"])
 apply (case_tac "n < 0")
  apply (subgoal_tac "m < 0 \<or> m = 0 \<or> 0 < m")
  prefer 2 apply (simp add:zless_linear[of "m" "0"])
  apply (case_tac "m < 0") apply (simp add:agsum_add1m) apply simp
  apply (thin_tac "\<not> m < 0")
  apply (case_tac "m = 0") apply simp
  apply (simp add:nt_zero0)
  apply (rule ag_r_zero[THEN sym], assumption+) apply (simp add:nt_mem0)
  apply simp apply (simp add:agsum_add3mp) apply simp
  apply (thin_tac "\<not> n < 0")
 apply (case_tac "n = 0") apply simp apply (simp add:nt_zero0)
  apply (rule ag_l_zero[THEN sym], assumption+) apply (simp add:nt_mem0)
  apply simp
  apply (subgoal_tac "m < 0 \<or> m = 0 \<or> 0 < m")
  prefer 2 apply (simp add:zless_linear[of "m" "0"])
  apply (case_tac "m < 0")
  apply (simp add:agsum_add3pm) apply simp apply (thin_tac "\<not> m < 0")
   apply (case_tac "m = 0") apply simp apply (simp add:nt_zero0)
   apply (rule ag_r_zero[THEN sym], assumption+) apply (simp add:nt_mem0)
   apply simp
  apply (simp add:agsum_add1p)
done

lemma nt_inv0:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow> -\<^sub>G(n\<triangleright>a\<^sub>G) = (- n)\<triangleright>a\<^sub>G"
apply (subgoal_tac "(n + -n)\<triangleright>a\<^sub>G = n\<triangleright>a\<^sub>G +\<^sub>G ((- n)\<triangleright>a\<^sub>G)")
 prefer 2 apply (rule nt_sum0, assumption+) apply (simp add:nt_zero0)
 apply (subgoal_tac "-\<^sub>G (n\<triangleright>a\<^sub>G) +\<^sub>G 0\<^sub>G = -\<^sub>G (n\<triangleright>a\<^sub>G) +\<^sub>G (n\<triangleright>a\<^sub>G +\<^sub>G (- n)\<triangleright>a\<^sub>G)")
 apply (subgoal_tac "n\<triangleright>a\<^sub>G \<in> carrier G")
 apply (frule ag_mOp_closed [of "G" "n\<triangleright>a\<^sub>G"], assumption+)
 apply (thin_tac "0\<^sub>G =  n\<triangleright>a\<^sub>G +\<^sub>G (- n)\<triangleright>a\<^sub>G")
 apply (simp add:ag_r_zero)
 apply (subgoal_tac "(- n)\<triangleright>a\<^sub>G \<in> carrier G")
 apply (simp add:ag_pOp_assoc[THEN sym])
 apply (simp add:ag_l_inv1) apply (simp add:ag_l_zero)
 apply (simp add:nt_mem0)+
done

lemma m_x_asum:"\<lbrakk>agroup G; a \<in> carrier G; b \<in> carrier G\<rbrakk>
        \<Longrightarrow> aSum G m (a +\<^sub>G b) = (aSum G m a)  +\<^sub>G (aSum G m b)"
apply (induct_tac m) apply simp
 apply (rule ag_r_zero[THEN sym], assumption+)
 apply (simp add:ag_inc_zero)
 apply simp
 apply (frule_tac n = n in asum_mem[of "G" "a"], assumption+)
 apply (frule_tac n = n in asum_mem[of "G" "b"], assumption+)
 apply (frule_tac a = "aSum G n a" and c = "aSum G n b" in pOp_assocTr43 [of "G" _ "a" _ "b"], assumption+) apply simp
 apply (frule_tac x = a and y = "aSum G n b" in ag_pOp_commute[of "G"], assumption+) apply simp
 apply (simp add:pOp_assocTr43[THEN sym])
done

lemma asum_multTr_pp:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk>
                            \<Longrightarrow> aSum G m (aSum G n a) = aSum G (m * n) a"
apply (induct_tac n)
 apply simp
 apply (induct_tac m) apply simp
 apply simp apply (rule ag_r_zero, assumption+) apply (simp add:ag_inc_zero)
 apply simp
 apply (frule_tac n = n in asum_mem[of "G" "a"], assumption+)
 apply (frule_tac a = "aSum G n a" and b = a and m= m in m_x_asum [of "G"],
                                           assumption+)  apply simp
 apply (frule_tac n = m and m = "m * n" in asumTr [of "G" "a"], assumption+)
 apply simp
 apply (frule_tac n = "m * n" in asum_mem[of "G" "a"], assumption+)
 apply (frule_tac n = m in asum_mem[of "G" "a"], assumption+)
 apply (simp add:ag_pOp_commute)
done

lemma nt_mult_pp:"\<lbrakk>agroup G; a \<in> carrier G; 0 \<le> m; 0 \<le> n\<rbrakk>
                                   \<Longrightarrow> m\<triangleright>(n\<triangleright>a\<^sub>G)\<^sub>G = (m * n)\<triangleright>a\<^sub>G"
apply (simp add:sprod_n_a_def)
 apply (subgoal_tac "0 \<le> m * n") apply simp
 apply (simp add:asum_multTr_pp)
 apply (simp add:nat_mult_distrib)
 apply (frule int_mult_le [of "0" "m" "n"], assumption+)
 apply (simp add:zmult_commute)
done

lemma asum_multTr_pm:"\<lbrakk>agroup G; a \<in> carrier G; 0 \<le> m; n < 0\<rbrakk> \<Longrightarrow>
 aSum G (nat m) (aSum G (nat (- n)) (-\<^sub>G a)) = aSum G (nat (m * (- n))) (-\<^sub>G a)"
apply (frule ag_mOp_closed [of "G" "a"], assumption+)
 apply (simp add:asum_multTr_pp)
 apply (subgoal_tac "nat m * nat (- n) = nat (- (m * n))") apply simp
 apply (subgoal_tac "(nat m) * (nat (- n)) = nat (m * (- n))")  apply simp
 apply simp
apply (subst zmult_zminus_right[THEN sym, of "m" "n"])
 apply (rule nat_mult_distrib [THEN sym, of "m"], assumption+)
done

lemma nt_mult_pm:"\<lbrakk>agroup G; a \<in> carrier G; 0 \<le> m; n < 0\<rbrakk> \<Longrightarrow>
                        m\<triangleright>(n\<triangleright>a\<^sub>G)\<^sub>G = (m * n)\<triangleright>a\<^sub>G"
apply (frule zmult_zle_mono1_neg [of "0" "m" "n"])
 apply simp apply simp
 apply (simp add:sprod_n_a_def)
 apply (case_tac "0 \<le> m * n") apply simp
 apply simp apply (simp add:asum_multTr_pm)
done

lemma asum_multTr_mp:"\<lbrakk>agroup G; a \<in> carrier G; m < 0; 0 \<le> n\<rbrakk> \<Longrightarrow>
 aSum G (nat (-m))(-\<^sub>G (aSum G (nat n) a)) = aSum G (nat ((- m) * n)) (-\<^sub>G a)"
apply (frule asum_mem [of "G" "a" "nat n"], assumption+)
apply (frule ag_mOp_closed [of "G" "aSum G (nat n) a"], assumption+)
apply (simp add:sprod_n_a_def)
apply (subgoal_tac "-\<^sub>G (aSum G (nat n) a) = aSum G (nat n) (-\<^sub>G a)")
 apply simp
 apply (subst asum_multTr_pp, assumption+)
 apply (simp add:ag_mOp_closed)
 apply (subgoal_tac "(nat (- m)) * (nat n) = nat ((- m) * n)")  apply simp
 apply (subst nat_mult_distrib) apply simp apply simp
 apply (frule nt_inv0 [of "G" "a" "n"], assumption+)
 apply (simp add:sprod_n_a_def)
done

lemma nt_mult_mp:"\<lbrakk>agroup G; a \<in> carrier G; m < 0; 0 \<le> n\<rbrakk> \<Longrightarrow>
                        m\<triangleright>(n\<triangleright>a\<^sub>G)\<^sub>G = (m * n)\<triangleright>a\<^sub>G"
apply (simp add:sprod_n_a_def)
 apply (subgoal_tac "m \<le> 0")
 apply (frule int_mult_le [of "m" "0" "n"]) apply simp
 apply (case_tac "0 \<le> m * n") apply simp
 apply (frule zle_imp_zless_or_eq [of "0" "m * n"])
 apply (thin_tac "0 \<le> m * n") apply (simp add:zle zmult_commute)
 apply (simp add:ag_inv_zero) apply (simp add:aSum_zero)
apply simp
 apply (simp add:asum_multTr_mp)
 apply (simp add:zle_imp_zless_or_eq)
done

lemma asum_multTr_mm:"\<lbrakk>agroup G; a \<in> carrier G; m < 0; n < 0\<rbrakk> \<Longrightarrow>
 aSum G (nat (-m))(-\<^sub>G (aSum G (nat (- n)) (-\<^sub>G a))) = aSum G (nat ((- m) * (- n))) a"
apply (simp add:sprod_n_a_def)
apply (subgoal_tac "-\<^sub>G (aSum G (nat (- n)) (-\<^sub>G a)) = aSum G (nat (- n)) a")
 apply simp
 apply (simp add:asum_multTr_pp)
 apply (subst nat_mult_distrib[THEN sym]) apply simp
 apply simp
 apply (frule ag_mOp_closed [of "G" "a"], assumption+)
 apply (frule nt_inv0 [of "G" "-\<^sub>G a" "- n"], assumption+)
 apply (simp add:sprod_n_a_def)
 apply (simp add:ag_inv_inv)
done

lemma nt_mult_mm:"\<lbrakk>agroup G; a \<in> carrier G; m < 0; n < 0\<rbrakk> \<Longrightarrow>
                     m\<triangleright>(n\<triangleright>a\<^sub>G)\<^sub>G = (m * n)\<triangleright>a\<^sub>G"
apply (simp add:sprod_n_a_def)
apply (subgoal_tac "0 \<le> m * n") apply simp
 apply (simp add:asum_multTr_mm)
 apply (frule zmult_neg[of "m" "n"], assumption+)
 apply (simp add:zle_imp_zless_or_eq)
done

lemma nt_mult_assoc0:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow> m\<triangleright>n\<triangleright>a\<^sub>G\<^sub>G = (m * n)\<triangleright>a\<^sub>G"
apply (case_tac "0 \<le> n")
 apply (case_tac "0 \<le> m")
  apply (simp add:nt_mult_pp) apply (simp add:zle)
  apply (subgoal_tac "0 \<le> n") apply (thin_tac "\<not> n < 0")
  apply (simp add:nt_mult_mp)
  apply (subgoal_tac "0 < m \<or> 0 = m \<or> m < 0")
  apply (simp add:zle_imp_zless_or_eq)
 apply (simp add:zle_imp_zless_or_eq [of "0" "m"])
apply (simp add:zle)
 apply (case_tac "0 \<le> m")
 apply (simp add:nt_mult_pm)
apply (simp add:zle)
 apply (simp add:nt_mult_mm)
done

lemma single_gen_carrTr:"\<lbrakk>agroup G; a \<in> carrier G\<rbrakk> \<Longrightarrow>
                               asubgroup G {x. \<exists>n. x =  (n\<triangleright>a\<^sub>G)}"
apply (rule asubg_test, assumption+)
 apply (rule subsetI) apply simp
 apply (subgoal_tac "\<forall>n. x = n\<triangleright>a\<^sub>G \<longrightarrow> x \<in> carrier G") apply blast
 apply (thin_tac "\<exists>n. x = n\<triangleright>a\<^sub>G") apply (rule allI) apply (rule impI)
 apply simp apply (simp add:nt_mem0)
 apply simp apply blast
apply (rule ballI)+ apply simp
 apply (subgoal_tac "\<forall>n1 n2. aa = n1\<triangleright>a\<^sub>G \<and>  b = n2\<triangleright>a\<^sub>G \<longrightarrow> (\<exists>n.  aa +\<^sub>G -\<^sub>G b = n\<triangleright>a\<^sub>G)") apply blast apply (thin_tac "\<exists>n. aa = n\<triangleright>a\<^sub>G")
  apply (thin_tac "\<exists>n. b = n\<triangleright>a\<^sub>G") apply (rule allI)+ apply (rule impI)
 apply (erule conjE)+ apply simp apply (subst nt_inv0, assumption+)
  apply (subst nt_sum0[THEN sym], assumption+)
 apply blast
done

lemma ag_single_inc_a:"ag_single_gen G a \<Longrightarrow> a \<in> carrier G"
apply (simp add:ag_single_gen_def)
done

lemma single_gen:"ag_single_gen G a \<Longrightarrow> carrier G = {g. \<exists>n. g = (n\<triangleright>a\<^sub>G)}"
apply (rule equalityI)
 apply (frule ag_single_inc_a [of "G" "a"])
 apply (rule subsetI) apply simp
apply (unfold ag_single_gen_def) apply (erule conjE)
apply (frule single_gen_carrTr [of "G" "a"], assumption+)
apply (subgoal_tac "a \<in> {x. \<exists>n. x = n\<triangleright>a\<^sub>G}")
 apply (subgoal_tac "\<Inter>{H. H <+ G \<and> a \<in> H} \<subseteq> {x. \<exists>n. x = n\<triangleright>a\<^sub>G}")
 apply (frule_tac A = "\<Inter>{H. H <+ G \<and> a \<in> H}" and B = "{x. \<exists>n. x = n\<triangleright>a\<^sub>G}" and c = x in  subsetD) apply (frule sym) apply (thin_tac "carrier G = \<Inter>{H. H <+ G \<and> a \<in> H}") apply simp apply simp
 apply (thin_tac "carrier G = \<Inter>{H. H <+ G \<and> a \<in> H}")
 apply (rule subsetI) apply blast
apply (thin_tac "carrier G = \<Inter>{H. H <+ G \<and> a \<in> H}")
 apply (thin_tac "{x. \<exists>n. x = n\<triangleright>a\<^sub>G} <+ G")
 apply (subgoal_tac "a = 1\<triangleright>a\<^sub>G") apply blast
 apply (simp add:sprod_n_a_def) apply (simp add:ag_l_zero[THEN sym])
apply (fold ag_single_gen_def)
  apply (frule ag_single_inc_a [of "G" "a"])
 apply (unfold ag_single_gen_def)
 apply (erule conjE) apply (thin_tac "carrier G = \<Inter>{H. H <+ G \<and> a \<in> H}")
 apply (rule subsetI) apply simp
 apply (subgoal_tac "\<forall>n. x = n\<triangleright>a\<^sub>G \<longrightarrow> x \<in> carrier G")  apply blast
 apply (thin_tac "\<exists>n. x = n\<triangleright>a\<^sub>G") apply (rule allI) apply (rule impI)
 apply simp  apply (simp add:nt_mem0)
done

constdefs
 single_gen_free::"['a AgroupType, 'a] \<Rightarrow> bool"
 "single_gen_free G a == \<forall>n. n \<noteq> 0 \<longrightarrow> 0\<^sub>G \<noteq> n\<triangleright>a\<^sub>G"

constdefs
 sfg ::"['a AgroupType, 'a] \<Rightarrow> bool"
 "sfg G a == ag_single_gen G a \<and> single_gen_free G a"
  (** single free generated by a **)

lemma single_gen_free_neg:"\<lbrakk>sfg G a; n\<triangleright>a\<^sub>G = 0\<^sub>G\<rbrakk> \<Longrightarrow> n = 0"
apply (simp add:sfg_def) apply (erule conjE)
apply (rule contrapos_pp, simp+)
apply (simp add:single_gen_free_def)
 apply (subgoal_tac "0\<^sub>G \<noteq> n\<triangleright>a\<^sub>G") prefer 2 apply blast
 apply (frule sym) apply (thin_tac "n\<triangleright>a\<^sub>G = 0\<^sub>G")
 apply (thin_tac "\<forall>n. n \<noteq> 0 \<longrightarrow> 0\<^sub>G \<noteq> n\<triangleright>a\<^sub>G")
 apply simp
done

lemma sfg_G_inc_a:"sfg G a \<Longrightarrow> a \<in> carrier G"
apply (simp add:sfg_def ag_single_inc_a)
done

lemma sfg_agroup:"sfg G a \<Longrightarrow> agroup G"
apply (simp add:sfg_def ag_single_gen_def)
done

lemma mem_G_nt:"\<lbrakk>sfg G a; x \<in> carrier G\<rbrakk> \<Longrightarrow> \<exists>n. x = n\<triangleright>a\<^sub>G"
apply (simp add:sfg_def)  apply (erule conjE)
 apply (frule single_gen [of "G" "a"]) apply simp
done

lemma nt_mem:"sfg G a \<Longrightarrow> n\<triangleright>a\<^sub>G \<in> carrier G"
apply (frule sfg_G_inc_a[of "G"])
apply (frule sfg_agroup [of "G"])
apply (simp add:nt_mem0)
done

lemma nt_zero:"sfg G a \<Longrightarrow> 0\<triangleright>a\<^sub>G = 0\<^sub>G"
apply (frule sfg_G_inc_a[of "G"])
apply (frule sfg_agroup [of "G"])
apply (simp add:nt_zero0)
done

lemma nt_sum:"sfg G a \<Longrightarrow> (n + m)\<triangleright>a\<^sub>G = n\<triangleright>a\<^sub>G +\<^sub>G (m\<triangleright>a\<^sub>G)"
apply (frule sfg_G_inc_a[of "G"])
apply (frule sfg_agroup [of "G"])
apply (simp add:nt_sum0)
done

lemma nt_inv:"sfg G a \<Longrightarrow> -\<^sub>G(n\<triangleright>a\<^sub>G) = (- n)\<triangleright>a\<^sub>G"
apply (frule sfg_G_inc_a[of "G"])
apply (frule sfg_agroup [of "G"])
apply (simp add:nt_inv0)
done

lemma nt_mult_assoc:"sfg G a \<Longrightarrow> m\<triangleright>n\<triangleright>a\<^sub>G\<^sub>G = (m * n)\<triangleright>a\<^sub>G"
apply (frule sfg_G_inc_a[of "G"])
apply (frule sfg_agroup [of "G"])
apply (simp add:nt_mult_assoc0)
done

lemma sfg_free:"\<lbrakk>sfg G a; n \<noteq> m \<rbrakk> \<Longrightarrow> n\<triangleright>a\<^sub>G \<noteq> (m\<triangleright>a\<^sub>G)"
apply (rule contrapos_pp, simp+)
apply (frule sfg_G_inc_a[of "G"])
apply (frule sfg_agroup [of "G"])
 apply (frule nt_mem [of "G" "a" "m"])
 apply (frule nt_mem [of "G" "a" "n"])
 apply (subgoal_tac "n\<triangleright>a\<^sub>G +\<^sub>G (-\<^sub>G (m\<triangleright>a\<^sub>G)) = 0\<^sub>G")
 apply (thin_tac "n\<triangleright>a\<^sub>G = m\<triangleright>a\<^sub>G")  (* we have to remove this equation *)
 apply (simp add:nt_inv)
 apply (simp add:nt_sum[THEN sym])
 apply (frule single_gen_free_neg[of "G" "a" "n - m"], assumption+)
 apply simp
apply (simp add:ag_r_inv1)
done

lemma sfg_free_inj:"\<lbrakk>sfg G a; n\<triangleright>a\<^sub>G = (m\<triangleright>a\<^sub>G) \<rbrakk> \<Longrightarrow> n = m"
apply (rule contrapos_pp, simp+)
apply (simp add:sfg_free)
done

section "3. Free Generated Modules"

constdefs
 sop_one::"[('r, 'm) RingType_scheme, 'r \<Rightarrow> 'a \<Rightarrow> 'a, 'a set] \<Rightarrow> bool"
 "sop_one R s A == \<forall>x\<in>A. (1\<^sub>R) \<^sub>s\<cdot> x = x"

constdefs
 sop_assoc::"[('r, 'm) RingType_scheme, 'r \<Rightarrow> 'a \<Rightarrow> 'a, 'a set] \<Rightarrow> bool"
 "sop_assoc R s A == \<forall>a\<in>carrier R. \<forall>b\<in>carrier R. \<forall>x\<in>A.
                         (tOp R a b) \<^sub>s\<cdot> x = a \<^sub>s\<cdot> (b \<^sub>s\<cdot> x)"
constdefs
 sop_inv ::"[('r, 'm) RingType_scheme, 'r \<Rightarrow> 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a, 'a set]
      \<Rightarrow> bool"
 "sop_inv R s i A == \<forall>r\<in>carrier R. \<forall>x\<in>A. r \<^sub>s\<cdot> (\<^sub>i- x) = (-\<^sub>R r) \<^sub>s\<cdot> x"

 sop_distr1 :: "[('r, 'm) RingType_scheme, 'r \<Rightarrow> 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a \<Rightarrow> 'a,
 'a \<Rightarrow> 'a, 'a set, 'a] \<Rightarrow> bool"

 "sop_distr1 R s f i A z == \<forall>a\<in>carrier R. \<forall>b\<in>carrier R. \<forall>x\<in>(aug_pm_set z i A). (a +\<^sub>R b) \<^sub>s\<cdot> x = (a \<^sub>s\<cdot> x) \<^sub>f+ (b \<^sub>s\<cdot> x)"

 sop_distr2 :: "[('r, 'm) RingType_scheme, 'r \<Rightarrow> 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a \<Rightarrow> 'a,
 'a \<Rightarrow> 'a, 'a set, 'a] \<Rightarrow> bool"

 "sop_distr2 R s f i A z == \<forall>a\<in>carrier R. \<forall>x\<in>addition_set f (aug_pm_set z i A). \<forall>y\<in>addition_set f (aug_pm_set z i A). a \<^sub>s\<cdot> (x \<^sub>f+ y) = (a \<^sub>s\<cdot> x) \<^sub>f+ (a \<^sub>s\<cdot> y)"

 sop_z :: "[('r, 'm) RingType_scheme, 'r \<Rightarrow> 'a \<Rightarrow> 'a, 'a] \<Rightarrow> bool"
 "sop_z R s z == \<forall>r\<in>carrier R. r \<^sub>s\<cdot> z = z"

constdefs
 fgmodule :: "[('r, 'm) RingType_scheme, 'a set, 'a, 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a \<Rightarrow> 'a,
 'r \<Rightarrow> 'a \<Rightarrow> 'a] \<Rightarrow> ('a, 'r) ModuleType"
 "fgmodule R A z i f s == \<lparr>carrier = addition_set f (aug_pm_set z i (s_set R s A)), pOp = \<lambda>x\<in>addition_set f (aug_pm_set z i (s_set R s A)). \<lambda>y\<in>addition_set f (aug_pm_set z i (s_set R s A)). x \<^sub>f+ y, mOp = \<lambda>x\<in>addition_set f (aug_pm_set z i (s_set R s A)). \<^sub>i- x, zero = z, sprod = \<lambda>r\<in>carrier R. \<lambda>x\<in>addition_set f (aug_pm_set z i (s_set R s A)). r \<^sub>s\<cdot> x \<rparr>"

lemma sop_closedTr0:"\<lbrakk>ring R; iop_cond1 (s_set R s A) i; iop_cond2 z (s_set R s A) i f; iop_cond3 z i; inv_iop z i f (s_set R s A); zeroA z i f (s_set R s A) z; sop_distr2 R s f i (s_set R s A) z; sop_assoc R s (aug_pm_set z i (s_set R s A)); sop_inv R s i (s_set R s A); sop_one R s (aug_pm_set z i (s_set R s A)); sop_z R s z;  r \<in> carrier R; x \<in> aug_pm_set z i (s_set R s A)\<rbrakk> \<Longrightarrow>
   r \<^sub>s\<cdot> x \<in> aug_pm_set z i (s_set R s A)"
apply (subgoal_tac "x = z \<or> (\<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a) \<or> x \<in> A \<or>
 x \<in> minus_set i ({x. \<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a} \<union> A)")
prefer 2 apply (simp add:aug_pm_set_def s_set_def)
 apply (thin_tac "x \<in> aug_pm_set z i (s_set R s A)")
 apply (case_tac "x = z") apply simp apply (simp add:sop_z_def)
 apply (simp add:aug_pm_set_def) apply simp
 apply (case_tac "x \<in> A") apply (simp add:aug_pm_set_def s_set_def)
 apply blast apply simp
 apply (case_tac "\<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a")
 apply (thin_tac "(\<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a) \<or>
       x \<in> minus_set i ({x. \<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a} \<union> A)")
 apply (subgoal_tac "\<forall>r1\<in>carrier R. \<forall>a1\<in>A. x = r1 \<^sub>s\<cdot> a1 \<longrightarrow> r \<^sub>s\<cdot> x \<in> aug_pm_set z i (s_set R s A)") apply blast
 apply (thin_tac "\<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a") apply (rule ballI)+
 apply (rule impI) apply simp
 apply (subgoal_tac "(r \<cdot>\<^sub>R r1) \<^sub>s\<cdot> a1 = r \<^sub>s\<cdot> (r1 \<^sub>s\<cdot> a1)") apply (rotate_tac -1)
 apply (frule sym) apply (thin_tac "( r \<cdot>\<^sub>R r1) \<^sub>s\<cdot> a1 = r \<^sub>s\<cdot> (r1 \<^sub>s\<cdot> a1)")
 apply simp apply (thin_tac "r \<^sub>s\<cdot> (r1 \<^sub>s\<cdot> a1) = ( r \<cdot>\<^sub>R r1) \<^sub>s\<cdot> a1")
 apply (frule_tac x = r and y = r1 in ring_tOp_closed [of "R"], assumption+)
 apply (simp add:aug_pm_set_def s_set_def) apply blast
 apply (subgoal_tac "a1 \<in> aug_pm_set z i (s_set R s A)")
 apply (simp add:sop_assoc_def) apply (simp add:aug_pm_set_def s_set_def)
 apply simp apply (thin_tac "x \<noteq> z")
 apply (thin_tac "\<forall>r\<in>carrier R. \<forall>a\<in>A. x \<noteq> r \<^sub>s\<cdot> a")
 apply (simp add:minus_set_def)
 apply (subgoal_tac "\<forall>y\<in>{x. \<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a} \<union> A. x = \<^sub>i- y \<longrightarrow>
 r \<^sub>s\<cdot> x \<in> aug_pm_set z i (s_set R s A)") apply blast
 apply (thin_tac "\<exists>y\<in>{x. \<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a} \<union> A. x = \<^sub>i- y")
 apply (rule ballI) apply simp apply (rule impI) apply (thin_tac "x = \<^sub>i- y")
 apply (case_tac "y \<in> A")
 apply (subgoal_tac "y \<in> s_set R s A")
 apply (simp add:sop_inv_def) apply (subgoal_tac "-\<^sub>R r \<in> carrier R")
 apply (simp add:aug_pm_set_def s_set_def) apply blast
 apply (frule ring_is_ag [of "R"]) apply (simp add:ag_mOp_closed)
 apply (simp add:s_set_def) apply simp
 apply (subgoal_tac "\<forall>r1\<in>carrier R. \<forall>a1\<in>A. y = r1 \<^sub>s\<cdot> a1 \<longrightarrow> r \<^sub>s\<cdot> (\<^sub>i- y) \<in> aug_pm_set z i (s_set R s A)") apply blast
 apply (thin_tac "\<exists>r\<in>carrier R. \<exists>a\<in>A. y = r \<^sub>s\<cdot> a")
 apply (rule ballI)+ apply (rule impI)
 apply (subgoal_tac "y \<in> (s_set R s A)")
 apply (simp add:sop_inv_def)
 prefer 2 apply (simp add:s_set_def) apply blast
 apply (subgoal_tac "a1 \<in> (s_set R s A)")
 apply (subgoal_tac "(-\<^sub>R r) \<^sub>s\<cdot> (r1 \<^sub>s\<cdot> a1) = ((-\<^sub>R r) \<cdot>\<^sub>R r1) \<^sub>s\<cdot> a1") apply simp
 apply (subgoal_tac "-\<^sub>R r \<in> carrier R")
 apply (frule_tac x = "-\<^sub>R r" and y = r1 in ring_tOp_closed[of "R"],
                                                             assumption+)
 apply (simp add:aug_pm_set_def s_set_def)
 apply blast apply (frule ring_is_ag [of "R"]) apply (simp add:ag_mOp_closed)
 apply (rule sym) apply (subgoal_tac "a1 \<in> aug_pm_set z i (s_set R s A)")
 apply (subgoal_tac "-\<^sub>R r \<in> carrier R")
 apply (simp add:sop_assoc_def) apply (frule ring_is_ag [of "R"])
 apply (simp add:ag_mOp_closed) apply (simp add:aug_pm_set_def)
 apply (simp add:s_set_def)
done

lemma sop_closedTr:"\<lbrakk>ring R; iop_cond1 (s_set R s A) i; iop_cond2 z (s_set R s A) i f; iop_cond3 z i; inv_iop z i f (s_set R s A); zeroA z i f (s_set R s A) z; sop_distr2 R s f i (s_set R s A) z; sop_assoc R s (aug_pm_set z i (s_set R s A)); sop_inv R s i (s_set R s A); sop_one R s (aug_pm_set z i (s_set R s A)); sop_z R s z\<rbrakk> \<Longrightarrow> \<forall>r\<in>carrier R. \<forall>x\<in>add_set f (aug_pm_set z i (s_set R s A)) n. r \<^sub>s\<cdot> x \<in> add_set f (aug_pm_set z i (s_set R s A)) n"
apply (induct_tac n)
 apply simp apply (rule ballI)+
 apply (simp add:sop_closedTr0)
apply (rule ballI)+ apply simp
 apply (subgoal_tac "\<forall>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n.
 \<forall>t\<in>aug_pm_set z i (s_set R s A). x = sa \<^sub>f+ t \<longrightarrow> (\<exists>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n. \<exists>t\<in>aug_pm_set z i (s_set R s A). r \<^sub>s\<cdot> x = sa \<^sub>f+ t)")
 apply blast
 apply (thin_tac "\<exists>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n.
             \<exists>t\<in>aug_pm_set z i (s_set R s A). x = sa \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI)
 apply (subgoal_tac "r \<^sub>s\<cdot> sa \<in> add_set f (aug_pm_set z i (s_set R s A)) n")
 prefer 2 apply simp
 apply (thin_tac "\<forall>r\<in>carrier R. \<forall>x\<in>add_set f (aug_pm_set z i (s_set R s A)) n.
                r \<^sub>s\<cdot> x \<in> add_set f (aug_pm_set z i (s_set R s A)) n")
 apply (frule_tac r = r and x = t in sop_closedTr0 [of "R" "s" "A" "i" "z" "f"], assumption+)
 apply (subgoal_tac "sa \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (subgoal_tac "t \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (simp add:sop_distr2_def) apply blast
 apply (subgoal_tac "aug_pm_set z i (s_set R s A) \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD)
 apply (simp add:addition_inc_add0)
apply (subgoal_tac "add_set f (aug_pm_set z i (s_set R s A)) n \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD)
 apply (simp add:addition_inc_add)
done

lemma sop_closed:"\<lbrakk>ring R; iop_cond1 (s_set R s A) i; iop_cond2 z (s_set R s A) i f; iop_cond3 z i; inv_iop z i f (s_set R s A); zeroA z i f (s_set R s A) z; sop_distr2 R s f i (s_set R s A) z; sop_assoc R s (aug_pm_set z i (s_set R s A)); sop_inv R s i (s_set R s A); sop_one R s (aug_pm_set z i (s_set R s A)); sop_z R s z\<rbrakk> \<Longrightarrow> \<forall>r\<in>carrier R. \<forall>x\<in>addition_set f (aug_pm_set z i (s_set R s A)) . r \<^sub>s\<cdot> x \<in> addition_set f (aug_pm_set z i (s_set R s A))"
apply (simp add: addition_set_def)
 apply (rule ballI) apply (rule allI) apply (rule impI)
 apply (subgoal_tac "\<forall>n. y = add_set f (aug_pm_set z i (s_set R s A)) n \<longrightarrow>
 (\<forall>x\<in>y. \<exists>xa. (\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n) \<and>  r \<^sub>s\<cdot> x \<in> xa)") apply blast
 apply (thin_tac "\<exists>n. y = add_set f (aug_pm_set z i (s_set R s A)) n")
 apply (rule allI) apply (rule impI) apply (rule ballI) apply simp
 apply (thin_tac "y = add_set f (aug_pm_set z i (s_set R s A)) n")
 apply (subgoal_tac " r \<^sub>s\<cdot> x \<in> add_set f (aug_pm_set z i (s_set R s A)) n")
 apply blast
 apply (simp add:sop_closedTr)
done

lemma sop_oneTr:"\<lbrakk>ring R; commute_bop f (aug_pm_set z i (s_set R s A)); assoc_bop (aug_pm_set z i (s_set R s A)) f; iop_cond1 (s_set R s A) i; iop_cond2 z (s_set R s A) i f; iop_cond3 z i; inv_iop z i f (s_set R s A); zeroA z i f (s_set R s A) z; sop_distr2 R s f i (s_set R s A) z; sop_assoc R s (aug_pm_set z i (s_set R s A)); sop_one R s (aug_pm_set z i (s_set R s A))\<rbrakk>  \<Longrightarrow> \<forall>x\<in>add_set f (aug_pm_set z i (s_set R s A)) n.  (1\<^sub>R) \<^sub>s\<cdot> x = x"
apply (induct_tac n)
 apply (rule ballI) apply simp apply (simp add:sop_one_def)
 apply simp
 apply (rule allI) apply (rule impI)
apply (subgoal_tac "\<forall>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n.
 \<forall>t\<in>aug_pm_set z i (s_set R s A). x = sa \<^sub>f+ t \<longrightarrow> (1\<^sub>R) \<^sub>s\<cdot> x = x")
 apply blast
 apply (thin_tac "\<exists>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n.
                \<exists>t\<in>aug_pm_set z i (s_set R s A). x = sa \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI) apply simp
 apply (subgoal_tac "t \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (subgoal_tac "sa \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (frule ring_one[of "R"])
 apply (simp add:sop_distr2_def)
 apply (thin_tac "\<forall>x\<in>add_set f (aug_pm_set z i (s_set R s A)) n. (1\<^sub>R) \<^sub>s\<cdot> x = x") apply (simp add:sop_one_def)
 apply (subgoal_tac "add_set f (aug_pm_set z i (s_set R s A)) n \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD)
 apply (simp add:addition_inc_add)
 apply (subgoal_tac "aug_pm_set z i (s_set R s A) \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD)
 apply (simp add:addition_inc_add0)
done

lemma sop_one:"\<lbrakk>ring R; commute_bop f (aug_pm_set z i (s_set R s A)); assoc_bop (aug_pm_set z i (s_set R s A)) f; iop_cond1 (s_set R s A) i; iop_cond2 z (s_set R s A) i f; iop_cond3 z i; inv_iop z i f (s_set R s A); zeroA z i f (s_set R s A) z; sop_distr2 R s f i (s_set R s A) z; sop_assoc R s (aug_pm_set z i (s_set R s A)); sop_one R s (aug_pm_set z i (s_set R s A))\<rbrakk>  \<Longrightarrow> \<forall>x\<in>addition_set f (aug_pm_set z i (s_set R s A)).  (1\<^sub>R) \<^sub>s\<cdot> x = x"
apply (rule ballI) apply (simp add:addition_set_def)
apply (subgoal_tac "\<forall>xa. (\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n) \<and> x \<in> xa \<longrightarrow> (1\<^sub>R) \<^sub>s\<cdot> x = x") apply blast
 apply (thin_tac "\<exists>xa. (\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n) \<and>
                x \<in> xa")
 apply (rule allI) apply (rule impI) apply (erule conjE)
 apply (subgoal_tac "\<forall>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n \<longrightarrow>
                          (1\<^sub>R) \<^sub>s\<cdot> x = x") apply blast
 apply (thin_tac "\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n")
 apply (rule allI) apply (rule impI) apply simp
apply (simp add:sop_oneTr)
done

lemma sop_assocTr:"\<lbrakk>ring R; iop_cond1 (s_set R s A) i; iop_cond2 z (s_set R s A) i f; iop_cond3 z i; inv_iop z i f (s_set R s A); zeroA z i f (s_set R s A) z; sop_distr2 R s f i (s_set R s A) z; sop_assoc R s (aug_pm_set z i (s_set R s A)); sop_inv R s i (s_set R s A); sop_one R s (aug_pm_set z i (s_set R s A)); sop_z R s z\<rbrakk>  \<Longrightarrow> \<forall>a\<in>carrier R. \<forall>b\<in>carrier R. \<forall>x\<in>add_set f (aug_pm_set z i (s_set R s A)) n.  a \<^sub>s\<cdot> ( b \<^sub>s\<cdot> x) = (a \<cdot>\<^sub>R b) \<^sub>s\<cdot> x"
apply (induct_tac n)
apply (rule ballI)+
apply (simp add:sop_assoc_def)
apply (rule ballI)+ apply simp
apply (subgoal_tac "\<forall>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n. \<forall>t\<in>(aug_pm_set z i (s_set R s A)). x = sa \<^sub>f+ t \<longrightarrow> a \<^sub>s\<cdot> (b \<^sub>s\<cdot> x) = ( a \<cdot>\<^sub>R b) \<^sub>s\<cdot> x")
apply blast
 apply (thin_tac "\<exists>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n.
             \<exists>t\<in>(aug_pm_set z i (s_set R s A)). x = sa \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI) apply simp
 apply (subgoal_tac "a \<^sub>s\<cdot> (b \<^sub>s\<cdot> sa) = ( a \<cdot>\<^sub>R b) \<^sub>s\<cdot> sa") prefer 2 apply simp
 apply (thin_tac "\<forall>a\<in>carrier R. \<forall>b\<in>carrier R. \<forall>x\<in>add_set f (aug_pm_set z i (s_set R s A)) n.  a \<^sub>s\<cdot> (b \<^sub>s\<cdot> x) = ( a \<cdot>\<^sub>R b) \<^sub>s\<cdot> x")
apply (subgoal_tac "sa \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (subgoal_tac "t \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (subgoal_tac "b \<^sub>s\<cdot> sa \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (subgoal_tac "b \<^sub>s\<cdot> t \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (frule_tac x = a and y = b in ring_tOp_closed [of "R"], assumption+)
 apply (simp add:sop_distr2_def)
 apply (subgoal_tac "a \<^sub>s\<cdot> (b \<^sub>s\<cdot> t) = (a \<cdot>\<^sub>R b) \<^sub>s\<cdot> t") apply simp
 apply (thin_tac "\<forall>a\<in>carrier R. \<forall>x\<in>addition_set f (aug_pm_set z i (s_set R s A)). \<forall>y\<in>addition_set f (aug_pm_set z i (s_set R s A)).
                   a \<^sub>s\<cdot> (x \<^sub>f+ y) = a \<^sub>s\<cdot> x \<^sub>f+ (a \<^sub>s\<cdot> y)")
 apply (simp add:sop_assoc_def)
 apply (simp add:sop_closed) apply (simp add:sop_closed)
 apply (subgoal_tac "aug_pm_set z i (s_set R s A) \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD) apply (simp add:addition_inc_add0)
 apply (subgoal_tac "add_set f (aug_pm_set z i (s_set R s A)) n \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD)
 apply (simp add:addition_inc_add)
done

lemma sop_assoc:"\<lbrakk>ring R; iop_cond1 (s_set R s A) i; iop_cond2 z (s_set R s A) i f; iop_cond3 z i; inv_iop z i f (s_set R s A); zeroA z i f (s_set R s A) z; sop_distr2 R s f i (s_set R s A) z; sop_assoc R s (aug_pm_set z i (s_set R s A)); sop_inv R s i (s_set R s A); sop_z R s z; sop_one R s (aug_pm_set z i (s_set R s A))\<rbrakk> \<Longrightarrow> \<forall>a\<in>carrier R. \<forall>b\<in>carrier R. \<forall>x\<in>addition_set f (aug_pm_set z i (s_set R s A)).  a \<^sub>s\<cdot> (b \<^sub>s\<cdot> x) = ( a \<cdot>\<^sub>R b) \<^sub>s\<cdot> x"
apply (rule ballI)+ apply (simp add:addition_set_def)
 apply (subgoal_tac "\<forall>xa. (\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n) \<and> x \<in> xa \<longrightarrow> a \<^sub>s\<cdot> (b \<^sub>s\<cdot> x) = ( a \<cdot>\<^sub>R b) \<^sub>s\<cdot> x") apply blast
 apply (thin_tac "\<exists>xa. (\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n) \<and>
               x \<in> xa")
 apply (rule allI) apply (rule impI) apply (erule conjE)
 apply (subgoal_tac "\<forall>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n \<longrightarrow>
 a \<^sub>s\<cdot> (b \<^sub>s\<cdot> x) = ( a \<cdot>\<^sub>R b) \<^sub>s\<cdot> x") apply blast
 apply (thin_tac "\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n")
 apply (rule allI) apply (rule impI) apply simp
 apply (simp add:sop_assocTr)
done

lemma s_set_commute:"\<lbrakk>commute_bop f (aug_pm_set z i (s_set R s A)); x \<in> addition_set f (aug_pm_set z i (s_set R s A)); y \<in> addition_set f (aug_pm_set z i (s_set R s A))\<rbrakk> \<Longrightarrow> x \<^sub>f+ y = y \<^sub>f+ x"
apply (simp add:commute_bop_def)
done

lemma add_s_set_inc_add_set:"ring R \<Longrightarrow> add_set f (aug_pm_set z i A) n \<subseteq> add_set f (aug_pm_set z i (s_set R s A)) n"
apply (induct_tac n)
 apply simp apply (rule subsetI)
 apply (simp add:aug_pm_set_def)
 apply (case_tac "x = z") apply simp apply simp
 apply (case_tac "x \<in> A") apply (simp add:s_set_def) apply simp
 apply (simp add:minus_set_def s_set_def) apply blast
apply (rule subsetI) apply simp
 apply (subgoal_tac "\<forall>s1\<in>add_set f (aug_pm_set z i A) n. \<forall>t\<in>aug_pm_set z i A. x = s1 \<^sub>f+ t \<longrightarrow> (\<exists>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n. \<exists>t\<in> (aug_pm_set z i (s_set R s A)). x = sa \<^sub>f+ t)")
 apply blast
 apply (thin_tac "\<exists>s\<in>add_set f (aug_pm_set z i A) n. \<exists>t\<in>aug_pm_set z i A. x = s \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI) apply simp
 apply (frule_tac A = "add_set f (aug_pm_set z i A) n" and B = "add_set f (aug_pm_set z i (s_set R s A)) n" and c = s1 in subsetD, assumption+)
 apply (subgoal_tac "t \<in> (aug_pm_set z i (s_set R s A))")
 apply blast
 apply (thin_tac "add_set f (aug_pm_set z i A) n
          \<subseteq> add_set f (aug_pm_set z i (s_set R s A)) n")
 apply (thin_tac "s1 \<in> add_set f (aug_pm_set z i A) n")
 apply (thin_tac "s1 \<in> add_set f (aug_pm_set z i (s_set R s A)) n")
 apply (thin_tac "x = s1 \<^sub>f+ t")
 apply (simp add:s_set_def aug_pm_set_def)
 apply (case_tac "t = z") apply simp apply simp
 apply (case_tac "t \<in> A") apply simp apply simp
 apply (simp add:minus_set_def)
 apply (subgoal_tac "\<forall>y\<in>A. t = \<^sub>i- y \<longrightarrow> (\<exists>r\<in>carrier R. \<exists>a\<in>A. t = r \<^sub>s\<cdot> a) \<or>
           (\<exists>y\<in>{x. \<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a} \<union> A. t = \<^sub>i- y)")
 apply blast apply (thin_tac "\<exists>y\<in>A. t = \<^sub>i- y") apply (rule ballI)
 apply (rule impI)  apply blast
done


lemma sop_distr1Tr:"\<lbrakk>ring R; commute_bop f (aug_pm_set z i (s_set R s A)); assoc_bop (aug_pm_set z i (s_set R s A)) f; iop_cond1 (s_set R s A) i; iop_cond2 z (s_set R s A) i f; iop_cond3 z i; inv_iop z i f (s_set R s A); zeroA z i f (s_set R s A) z; sop_distr1 R s f i (s_set R s A) z; sop_distr2 R s f i (s_set R s A) z; sop_assoc R s (aug_pm_set z i (s_set R s A)); sop_inv R s i (s_set R s A); sop_one R s (aug_pm_set z i (s_set R s A)); sop_z R s z\<rbrakk>  \<Longrightarrow> \<forall>a\<in>carrier R. \<forall>b\<in>carrier R. \<forall>x\<in> add_set f (aug_pm_set z i (s_set R s A)) n. (a +\<^sub>R b) \<^sub>s\<cdot> x = a \<^sub>s\<cdot> x \<^sub>f+ (b \<^sub>s\<cdot> x)"
apply (induct_tac n)
 apply (rule ballI)+ apply (simp add:sop_distr1_def)
apply (rule ballI)+ apply simp
 apply (subgoal_tac "\<forall>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n.
 \<forall>t\<in>aug_pm_set z i (s_set R s A). x = sa \<^sub>f+ t \<longrightarrow> (a +\<^sub>R b) \<^sub>s\<cdot> x = a \<^sub>s\<cdot> x \<^sub>f+ (b \<^sub>s\<cdot> x)")
 apply blast
 apply (thin_tac "\<exists>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n.
             \<exists>t\<in>(aug_pm_set z i (s_set R s A)). x = sa \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI) apply simp
 apply (frule ring_is_ag [of "R"])
 apply (frule_tac x = a and y = b in ag_pOp_closed [of "R"], assumption+)
 apply (subgoal_tac "sa \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (subgoal_tac "t \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 prefer 2
 apply (subgoal_tac "aug_pm_set z i (s_set R s A) \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD)
 apply (simp add:addition_inc_add0)
 prefer 2
 apply (subgoal_tac "add_set f (aug_pm_set z i (s_set R s A)) n \<subseteq>
       addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD)
 apply (simp add:addition_inc_add)
 apply (subgoal_tac "a \<^sub>s\<cdot> sa \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (subgoal_tac "b \<^sub>s\<cdot> sa \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (subgoal_tac "a \<^sub>s\<cdot> t \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (subgoal_tac "b \<^sub>s\<cdot> t \<in> addition_set f (aug_pm_set z i (s_set R s A))")
prefer 2 apply (simp add:sop_closed)
prefer 2 apply (simp add:sop_closed)
prefer 2 apply (simp add:sop_closed)
prefer 2 apply (simp add:sop_closed)
apply (simp add:sop_distr1_def sop_distr2_def)
apply (frule_tac x = "b \<^sub>s\<cdot> sa" and y = "b \<^sub>s\<cdot> t" in bop_closed [of "(aug_pm_set z i (s_set R s A))" "f"], assumption+)
apply (simp add: addition_assoc)
 apply (thin_tac "\<forall>a\<in>carrier R. \<forall>b\<in>carrier R. \<forall>x\<in>aug_pm_set z i (s_set R s A). ( a +\<^sub>R b) \<^sub>s\<cdot> x = a \<^sub>s\<cdot> x \<^sub>f+ (b \<^sub>s\<cdot> x)")
 apply (thin_tac "\<forall>a\<in>carrier R. \<forall>x\<in>addition_set f (aug_pm_set z i (s_set R s A)). \<forall>y\<in>addition_set f (aug_pm_set z i (s_set R s A)).
                   a \<^sub>s\<cdot> (x \<^sub>f+ y) = a \<^sub>s\<cdot> x \<^sub>f+ (a \<^sub>s\<cdot> y)")
 apply (thin_tac "\<forall>a\<in>carrier R. \<forall>b\<in>carrier R. \<forall>x\<in>add_set f (aug_pm_set z i (s_set R s A)) n. (a +\<^sub>R b) \<^sub>s\<cdot> x = a \<^sub>s\<cdot> x \<^sub>f+ (b \<^sub>s\<cdot> x)")
apply (subgoal_tac "a \<^sub>s\<cdot> t \<^sub>f+ (b \<^sub>s\<cdot> sa \<^sub>f+ (b \<^sub>s\<cdot> t)) = a \<^sub>s\<cdot> t \<^sub>f+ (b \<^sub>s\<cdot> sa) \<^sub>f+ (b \<^sub>s\<cdot> t)") apply simp
 prefer 2 apply (simp add:addition_assoc [THEN sym])
 apply (thin_tac "a \<^sub>s\<cdot> t \<^sub>f+ (b \<^sub>s\<cdot> sa \<^sub>f+ (b \<^sub>s\<cdot> t)) = a \<^sub>s\<cdot> t \<^sub>f+ (b \<^sub>s\<cdot> sa) \<^sub>f+ (b \<^sub>s\<cdot> t)")
 apply (subgoal_tac "a \<^sub>s\<cdot> t \<^sub>f+ (b \<^sub>s\<cdot> sa) = b \<^sub>s\<cdot> sa \<^sub>f+ (a \<^sub>s\<cdot> t)")
 apply simp
 apply (subgoal_tac "a \<^sub>s\<cdot> sa \<^sub>f+ (b \<^sub>s\<cdot> sa \<^sub>f+ (a \<^sub>s\<cdot> t) \<^sub>f+ (b \<^sub>s\<cdot> t)) =
                      a \<^sub>s\<cdot> sa \<^sub>f+ (b \<^sub>s\<cdot> sa) \<^sub>f+ (a \<^sub>s\<cdot> t \<^sub>f+ (b \<^sub>s\<cdot> t))")
 apply simp
 apply (thin_tac "b \<^sub>s\<cdot> sa \<^sub>f+ (b \<^sub>s\<cdot> t) \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (thin_tac "a \<^sub>s\<cdot> t \<^sub>f+ (b \<^sub>s\<cdot> sa) = b \<^sub>s\<cdot> sa \<^sub>f+ (a \<^sub>s\<cdot> t)")
 apply (frule_tac  x = "a \<^sub>s\<cdot> t" and y = "b \<^sub>s\<cdot> t" in bop_closed [of "(aug_pm_set z i (s_set R s A))" "f"], assumption+)
 apply (subst addition_assoc, assumption+)
 apply (simp add:addition_assoc)
apply (simp add:commute_bop_def)
done

lemma sop_distr1:"\<lbrakk>ring R; commute_bop f (aug_pm_set z i (s_set R s A)); assoc_bop (aug_pm_set z i (s_set R s A)) f; iop_cond1 (s_set R s A) i; iop_cond2 z (s_set R s A) i f; iop_cond3 z i; inv_iop z i f (s_set R s A); zeroA z i f (s_set R s A) z; sop_distr1 R s f i (s_set R s A) z; sop_distr2 R s f i (s_set R s A) z; sop_assoc R s (aug_pm_set z i (s_set R s A)); sop_inv R s i (s_set R s A); sop_one R s (aug_pm_set z i (s_set R s A)); sop_z R s z\<rbrakk>  \<Longrightarrow> \<forall>a\<in>carrier R. \<forall>b\<in>carrier R. \<forall>x\<in> addition_set f (aug_pm_set z i (s_set R s A)). (a +\<^sub>R b) \<^sub>s\<cdot> x = a \<^sub>s\<cdot> x \<^sub>f+ (b \<^sub>s\<cdot> x)"
apply (rule ballI)+
 apply (simp add:addition_set_def)
 apply (subgoal_tac "\<forall>xa. (\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n) \<and> x \<in> xa \<longrightarrow> (a +\<^sub>R b) \<^sub>s\<cdot> x = a \<^sub>s\<cdot> x \<^sub>f+ (b \<^sub>s\<cdot> x)") apply blast
 apply (thin_tac " \<exists>xa. (\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n) \<and> x \<in> xa") apply (rule allI) apply (rule impI) apply (erule conjE)
 apply (subgoal_tac "\<forall>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n \<longrightarrow> (a +\<^sub>R b) \<^sub>s\<cdot> x = a \<^sub>s\<cdot> x \<^sub>f+ (b \<^sub>s\<cdot> x)") apply blast
 apply (thin_tac "\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n")
 apply (rule allI) apply (rule impI) apply simp
apply (simp add:sop_distr1Tr)
done

constdefs
 fgmodule_condition :: "[('r, 'm) RingType_scheme, 'a \<Rightarrow> 'a \<Rightarrow> 'a, 'a \<Rightarrow> 'a,
 'r \<Rightarrow> 'a \<Rightarrow> 'a, 'a set, 'a] \<Rightarrow> bool"
 "fgmodule_condition R f i s A z == commute_bop f (aug_pm_set z i (s_set R s A)) \<and> assoc_bop (aug_pm_set z i (s_set R s A)) f \<and> iop_cond1 (s_set R s A) i \<and> iop_cond2 z (s_set R s A) i f \<and> iop_cond3 z i \<and> inv_iop z i f (s_set R s A) \<and>
zeroA z i f (s_set R s A) z \<and> sop_distr1 R s f i (s_set R s A) z \<and> sop_distr2 R s f i (s_set R s A) z \<and> sop_assoc R s (aug_pm_set z i (s_set R s A)) \<and> sop_inv R s i (s_set R s A) \<and> sop_one R s (aug_pm_set z i (s_set R s A)) \<and> sop_z R s z"

lemma fgmodule_is_module:"\<lbrakk>ring R; fgmodule_condition R f i s A z\<rbrakk>
                                \<Longrightarrow>  R module (fgmodule R A z i f s)"
apply (simp add:fgmodule_condition_def) apply (erule conjE)+
apply (subst Module_def)
 apply simp
 apply (rule conjI)
prefer 2
 apply (rule conjI) apply (rule bivar_func_test)
 apply (rule ballI)+ apply (simp add:fgmodule_def)
 apply (simp add:sop_closed)
 apply (rule ballI)+
 apply (rule conjI)
 apply (simp add:fgmodule_def)
 apply (simp add:ring_tOp_closed) apply (simp add:sop_closed)
 apply (simp add:sop_assoc)
apply (rule conjI)
 apply (simp add:fgmodule_def) apply (frule ring_is_ag [of "R"])
 apply (simp add:sop_closed ag_pOp_closed)
 apply (simp add: sop_distr1[of "R" "f" "z" "i" "s" "A"])
apply (rule conjI)
 apply (simp add:fgmodule_def)
 apply (simp add:sop_closed) apply (simp add:bop_closed)
 apply (simp add:sop_distr2_def)
apply (simp add:fgmodule_def) apply (simp add:ring_one)
 apply (simp add:sop_one)
apply (frule fag_agroup [of "f" "z" "i" "s_set R s A"], assumption+)
apply (simp add:fag_gen_by_def fgmodule_def) apply (simp add:agroup_def)
 apply (rule impI)
 apply (simp add:zeroA_def)
done

lemma a_in_carr_fgmodule:"\<lbrakk>ring R; a \<in> A \<rbrakk>
                                \<Longrightarrow>  a \<in> carrier (fgmodule R A z i f s)"
apply (simp add:fgmodule_def)
 apply (subgoal_tac "a \<in> aug_pm_set z i (s_set R s A)")
 apply (subgoal_tac "aug_pm_set z i (s_set R s A) \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD)
 apply (simp add:addition_inc_add0)
apply (simp add:aug_pm_set_def s_set_def)
done

section "4. a fgmodule and a free module"

lemma fg_zeroTr:"\<lbrakk>ring R; fgmodule_condition R f i s A z; a \<in> A\<rbrakk> \<Longrightarrow> (0\<^sub>R) \<^sub>s\<cdot> a = z"
apply (frule fgmodule_is_module [of "R" "f" "i" "s" "A" "z"], assumption+)
apply (frule sprod_0_m [of "R" "fgmodule R A z i f s" "a"], assumption+)
apply (simp add:a_in_carr_fgmodule)
 apply (frule ring_is_ag [of "R"]) apply (frule ag_inc_zero[of "R"])
 apply (frule a_in_carr_fgmodule [of "R" "a" "A" "z" "i" "f" "s"], assumption+)
 apply (simp add:fgmodule_def)
done

lemma  fg_genTr0:"\<lbrakk>ring R; fgmodule_condition R f i s A z; x \<in> aug_pm_set z i (s_set R s A)\<rbrakk> \<Longrightarrow> x \<in> linear_span R (fgmodule R A z i f s) (carrier R) A"
 apply (simp add:aug_pm_set_def s_set_def)
 apply (case_tac "x = z")
 apply simp
 apply (simp add:linear_span_def)
  apply (case_tac "A = {}") apply simp apply (simp add:fgmodule_def)
  apply simp
  apply (frule nonempty_ex[of "A"]) apply (thin_tac "A \<noteq> {}")
  apply (subgoal_tac "\<forall>x. x \<in> A \<longrightarrow> (\<exists>n. \<exists>fa\<in>Nset n \<rightarrow> A. \<exists>sa\<in>Nset n \<rightarrow> carrier R. z = linear_combination R (fgmodule R A z i f s) n sa fa)")
  apply blast apply (thin_tac "\<exists>x. x \<in> A")
  apply (rule allI) apply (rule impI)
  apply (subgoal_tac "(\<lambda>j\<in>Nset 0. xa) \<in> Nset 0 \<rightarrow> A")
  apply (subgoal_tac "(\<lambda>k\<in>Nset 0. (0\<^sub>R)) \<in> Nset 0 \<rightarrow> carrier R")
  apply (subgoal_tac "z = linear_combination R (fgmodule R A z i f s) 0 (\<lambda>k\<in>Nset 0. (0\<^sub>R)) (\<lambda>j\<in>Nset 0. xa)") apply blast
  apply (simp add:linear_combination_def) apply (simp add:Nset_def)
  apply (frule_tac a1 = xa in fg_zeroTr [THEN sym, of "R" "f" "i" "s" "A" "z"],
                      assumption+)
  apply (frule_tac a = xa in a_in_carr_fgmodule [of "R" _ "A" "z" "i" "f" "s"],
                                                                assumption+)
  apply (frule fgmodule_is_module [of "R" "f" "i" "s" "A" "z"], assumption+)
  apply (frule ring_is_ag [of "R" ])
  apply (frule ag_inc_zero[of "R"])
  apply (simp add:fgmodule_def)
 apply (rule univar_func_test) apply (rule ballI)
 apply (frule ring_is_ag [of "R"]) apply (simp add:ag_inc_zero Nset_def)
 apply (rule univar_func_test) apply (rule ballI) apply (simp add:Nset_def)
 apply simp
 apply (case_tac "x \<in> A")
  apply (subgoal_tac "(\<lambda>j\<in>Nset 0. x) \<in> Nset 0 \<rightarrow> A")
  apply (subgoal_tac "(\<lambda>k\<in>Nset 0. (1\<^sub>R)) \<in> Nset 0 \<rightarrow> carrier R")
  apply (subgoal_tac "x = linear_combination R (fgmodule R A z i f s) 0 (\<lambda>k\<in>Nset 0. (1\<^sub>R)) (\<lambda>j\<in>Nset 0. x)") apply (simp add:linear_span_def)
  apply (frule_tac x = x and A = A in nonempty) apply simp
  apply blast
  apply (simp add:linear_combination_def Nset_def)
  apply (frule fgmodule_is_module [of "R" "f" "i" "s" "A" "z"], assumption+)
  apply (rule sprod_one [THEN sym], assumption+)
  apply (simp add:a_in_carr_fgmodule)
  apply (frule ring_one [of "R"])
  apply (rule univar_func_test) apply (rule ballI) apply simp
  apply (rule univar_func_test) apply (rule ballI) apply simp apply simp
  apply (case_tac "\<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a")
   apply (thin_tac "(\<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a) \<or>
           x \<in> minus_set i ({x. \<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a} \<union> A)")
   apply (subgoal_tac "\<forall>r\<in>carrier R. \<forall>a\<in>A. x = r \<^sub>s\<cdot> a \<longrightarrow> x \<in> linear_span R (fgmodule R A z i f s) (carrier R) A") apply blast
   apply (thin_tac "\<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a") apply (rule ballI)+
   apply (rule impI)
  apply (subgoal_tac "(\<lambda>j\<in>Nset 0. a) \<in> Nset 0 \<rightarrow> A")
  apply (subgoal_tac "(\<lambda>k\<in>Nset 0. r) \<in> Nset 0 \<rightarrow> carrier R")
  apply (subgoal_tac "x = linear_combination R (fgmodule R A z i f s) 0 (\<lambda>k\<in>Nset 0. r) (\<lambda>j\<in>Nset 0. a)")
 apply (frule_tac x = a and A = A in nonempty) apply (simp add:linear_span_def) apply (frule sym) apply (thin_tac "linear_combination R (fgmodule R A z i f s) 0 (\<lambda>k\<in>Nset 0. r) (\<lambda>j\<in>Nset 0. a) =  r \<^sub>s\<cdot> a")
 apply blast
 apply (simp add:linear_combination_def Nset_def)
 apply (frule_tac a = a in a_in_carr_fgmodule [of "R" _ "A" "z" "i" "f" "s"], assumption+)
 apply (simp add:a_in_carr_fgmodule fgmodule_def)
 apply (rule univar_func_test) apply (rule ballI) apply (simp add:Nset_def)
 apply (rule univar_func_test) apply (rule ballI) apply (simp add:Nset_def)
 apply simp apply (thin_tac "x \<noteq> z") apply (thin_tac "\<forall>r\<in>carrier R. \<forall>a\<in>A. x \<noteq> r \<^sub>s\<cdot> a")
 apply (simp add:minus_set_def)
 apply (subgoal_tac "\<forall>y\<in>{x. \<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a} \<union> A. x = \<^sub>i- y \<longrightarrow>
 x \<in> linear_span R (fgmodule R A z i f s) (carrier R) A") apply blast
 apply (thin_tac "\<exists>y\<in>{x. \<exists>r\<in>carrier R. \<exists>a\<in>A. x = r \<^sub>s\<cdot> a} \<union> A. x = \<^sub>i- y")
 apply (rule ballI) apply (rule impI) apply simp
 apply (case_tac "y \<in> A")
 apply (thin_tac "x = \<^sub>i- y")
 apply (frule_tac x = y and A = A in nonempty)
 apply (simp add:linear_span_def)
  apply (subgoal_tac "(\<lambda>j\<in>Nset 0. y) \<in> Nset 0 \<rightarrow> A")
  apply (subgoal_tac "(\<lambda>k\<in>Nset 0. (-\<^sub>R (1\<^sub>R))) \<in> Nset 0 \<rightarrow> carrier R")
  apply (subgoal_tac " \<^sub>i- y = linear_combination R (fgmodule R A z i f s) 0 (\<lambda>k\<in>Nset 0. (-\<^sub>R (1\<^sub>R))) (\<lambda>j\<in>Nset 0. y)") apply blast
  apply (simp add:linear_combination_def Nset_def)
  apply (frule fgmodule_is_module [of "R" "f" "i" "s" "A" "z"], assumption+)
  apply (frule_tac a = y in a_in_carr_fgmodule [of "R" _ "A" "z" "i" "f" "s"], assumption+)
  apply (frule ring_one [of "R"])
  apply (frule ring_is_ag [of "R"]) apply (frule ag_mOp_closed [of "R" "1\<^sub>R"])
  apply assumption
  apply (simp add:sprod_minus_am1 [THEN sym, of "R" "fgmodule R A z i f s"])
  apply (simp add:sprod_minus_am [of "R" "fgmodule R A z i f s"])
  apply (frule module_is_ag [of "R" "fgmodule R A z i f s"], assumption+)
  apply (frule_tac x = y in ag_mOp_closed [of "fgmodule R A z i f s"], assumption+)
  apply (simp add:sprod_one)
  apply (simp add:fgmodule_def)
  apply (frule ring_one [of "R"])
  apply (frule ring_is_ag [of "R"]) apply (frule ag_mOp_closed [of "R" "1\<^sub>R"], assumption+)
  apply (rule univar_func_test) apply (rule ballI) apply simp
  apply (rule univar_func_test) apply (rule ballI) apply simp
 apply simp
 apply (subgoal_tac "\<forall>r\<in>carrier R. \<forall>a\<in>A. y = r \<^sub>s\<cdot> a \<longrightarrow> \<^sub>i- y \<in> linear_span R (fgmodule R A z i f s) (carrier R) A")
 apply blast
 apply (thin_tac "\<exists>r\<in>carrier R. \<exists>a\<in>A. y = r \<^sub>s\<cdot> a") apply (rule ballI)+
 apply (rule impI) apply simp
 apply (subgoal_tac "\<^sub>i- (r \<^sub>s\<cdot> a) = (-\<^sub>R r) \<^sub>s\<cdot> a") apply simp
 apply (thin_tac "x = (-\<^sub>R r) \<^sub>s\<cdot> a") apply (thin_tac "y = r \<^sub>s\<cdot> a")
 apply (thin_tac " \<^sub>i- (r \<^sub>s\<cdot> a) = (-\<^sub>R r) \<^sub>s\<cdot> a")
 apply (frule ring_is_ag [of "R"])
 apply (frule_tac x = r in ag_mOp_closed [of "R"], assumption+)
 apply (simp add:linear_span_def) apply (simp add: nonempty [of _ "A"])
 apply (subgoal_tac "(\<lambda>j\<in>Nset 0. a) \<in> Nset 0 \<rightarrow> A")
  apply (subgoal_tac "(\<lambda>k\<in>Nset 0. (-\<^sub>R r)) \<in> Nset 0 \<rightarrow> carrier R")
  apply (subgoal_tac " (-\<^sub>R r) \<^sub>s\<cdot> a = linear_combination R (fgmodule R A z i f s) 0 (\<lambda>k\<in>Nset 0. (-\<^sub>R r)) (\<lambda>j\<in>Nset 0. a)") apply blast
  apply (simp add:linear_combination_def Nset_def)
  apply (frule_tac a = a in a_in_carr_fgmodule [of "R" _ "A" "z" "i" "f" "s"], assumption+)
  apply (simp add:fgmodule_def)
  apply (rule univar_func_test) apply (rule ballI) apply simp
  apply (rule univar_func_test) apply (rule ballI) apply simp
  apply (frule fgmodule_is_module [of "R" "f" "i" "s" "A" "z"], assumption+)
  apply (frule_tac a = a in a_in_carr_fgmodule [of "R" _ "A" "z" "i" "f" "s"], assumption+)
  apply (frule_tac a = r and m = a in sprod_minus_am1[of "R" "fgmodule R A z i f s"], assumption+)
  apply (subgoal_tac "r \<^sub>s\<cdot> a \<in> addition_set f (aug_pm_set z i (s_set R s A))")
  apply (frule ring_is_ag [of "R"])
  apply (frule_tac x = r in ag_mOp_closed [of "R"], assumption+)
  apply (simp add:fgmodule_def)
  apply (subgoal_tac "r \<^sub>s\<cdot> a \<in> aug_pm_set z i (s_set R s A)")
  apply (subgoal_tac "aug_pm_set z i (s_set R s A) \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD)
  apply (simp add:addition_inc_add0)
  apply (simp add:aug_pm_set_def s_set_def) apply blast
done

lemma fg_genTr:"\<lbrakk>ring R; fgmodule_condition R f i s A z\<rbrakk> \<Longrightarrow>\<forall>x. x \<in> (add_set f (aug_pm_set z i (s_set R s A)) n) \<longrightarrow> x \<in> linear_span R (fgmodule R A z i f s) (carrier R) A"
apply (induct_tac n)
apply (rule allI) apply (rule impI) apply simp
apply (simp add:fg_genTr0)
apply (rule allI) apply (rule impI) apply simp
 apply (subgoal_tac "\<forall>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n.
 \<forall>t\<in>aug_pm_set z i (s_set R s A). x = sa \<^sub>f+ t \<longrightarrow> (x \<in> linear_span R (fgmodule R A z i f s) (carrier R) A)") apply blast
 apply (thin_tac "\<exists>sa\<in>add_set f (aug_pm_set z i (s_set R s A)) n.
                \<exists>t\<in>aug_pm_set z i (s_set R s A). x = sa \<^sub>f+ t")
 apply (rule ballI)+ apply (rule impI)
 apply (subgoal_tac "sa \<in> linear_span R (fgmodule R A z i f s) (carrier R) A")
 prefer 2 apply simp
 apply (thin_tac "\<forall>x. x \<in> add_set f (aug_pm_set z i (s_set R s A)) n \<longrightarrow>
              x \<in> linear_span R (fgmodule R A z i f s) (carrier R) A")
 apply (frule_tac x = t in fg_genTr0[of "R" "f" "i" "s" "A" "z"], assumption+)
 apply simp
 apply (frule fgmodule_is_module [of "R" "f" "i" "s" "A" "z"], assumption+)
 apply (frule whole_ideal[of "R"])
 apply (subgoal_tac "A \<subseteq> carrier (fgmodule R A z i f s)")
 apply (frule_tac a = sa and b = t in linear_span_tOp_closed [of "R" "fgmodule R A z i f s" "carrier R" "A"], assumption+)
 apply (subgoal_tac "sa +\<^sub>(fgmodule R A z i f s) t = sa \<^sub>f+ t") apply simp
  apply (subst fgmodule_def) apply simp
  apply (subgoal_tac "t \<in> addition_set f (aug_pm_set z i (s_set R s A))")
  apply (subgoal_tac "sa \<in> addition_set f (aug_pm_set z i (s_set R s A))")
  apply (simp add:fgmodule_def subsetD)
  apply (subgoal_tac "add_set f (aug_pm_set z i (s_set R s A)) n \<subseteq>
                        addition_set f (aug_pm_set z i (s_set R s A))")
  apply (simp add:subsetD) apply (simp add:addition_inc_add)
  apply (subgoal_tac "aug_pm_set z i (s_set R s A) \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") apply (simp add:subsetD)
  apply (simp add:addition_inc_add0)
apply (rule subsetI)
 apply (simp add:a_in_carr_fgmodule)
done

lemma generator_of_fgm:"\<lbrakk> ring R; fgmodule_condition R f i s A z\<rbrakk> \<Longrightarrow> generator R (fgmodule R A z i f s) A"
apply (simp add:generator_def)
apply (frule fgmodule_is_module [of "R" "f" "i" "s" "A" "z"]) apply simp
 apply (frule module_is_ag [of "R" "fgmodule R A z i f s"], assumption+)
apply (rule conjI)
 apply (rule subsetI)
 apply (simp add:a_in_carr_fgmodule)
apply (subgoal_tac "aug_pm_set z i (s_set R s A) \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))") prefer 2 apply (simp add:addition_inc_add0)
 apply (rule equalityI)
 apply (frule whole_ideal [of "R"])
 apply (rule lin_span_sub_carrier, assumption+)
 apply (rule subsetI) apply (simp add:a_in_carr_fgmodule)
apply (rule subsetI)
 apply (thin_tac "agroup (fgmodule R A z i f s)")
 apply (thin_tac "R module fgmodule R A z i f s")
 apply (thin_tac "aug_pm_set z i (s_set R s A)
           \<subseteq> addition_set f (aug_pm_set z i (s_set R s A))")
 apply (subgoal_tac "x \<in> addition_set f (aug_pm_set z i (s_set R s A))")
 prefer 2 apply (simp add:fgmodule_def)
 apply (thin_tac "x \<in> carrier (fgmodule R A z i f s)")
 apply (simp add:addition_set_def)
 apply (subgoal_tac "\<forall>xa. (\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n) \<and> x \<in> xa \<longrightarrow> x \<in> linear_span R (fgmodule R A z i f s) (carrier R) A")
 apply blast
 apply (thin_tac "\<exists>xa. (\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n) \<and>
                x \<in> xa")
 apply (rule allI) apply (rule impI) apply (erule conjE)
 apply (subgoal_tac "\<forall>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n \<longrightarrow>
 x \<in> linear_span R (fgmodule R A z i f s) (carrier R) A") apply blast
 apply (thin_tac "\<exists>n. xa = add_set f (aug_pm_set z i (s_set R s A)) n")
 apply (rule allI) apply (rule impI) apply simp
 apply (simp add:fg_genTr)
done

lemma fg_freeTr1:"\<lbrakk>ring R; R module M; free_generator R M A;
 R module fgmodule R A z i f s; free_generator R (fgmodule R A z i f s) A;
 g \<in> mHom R M (fgmodule R A z i f s); \<forall>x\<in>A. g x = x\<rbrakk> \<Longrightarrow> \<forall>fa sa. fa \<in> Nset n \<rightarrow> A \<and> sa \<in> Nset n \<rightarrow> carrier R \<longrightarrow> linear_combination R (fgmodule R A z i f s) n sa (cmp g fa) = linear_combination R (fgmodule R A z i f s) n sa fa"
apply (induct_tac n) apply (rule allI)+ apply (rule impI) apply (erule conjE)
 apply (simp add:linear_combination_def)
 apply (subgoal_tac "0 \<in> Nset 0") apply (subgoal_tac "fa 0 \<in> A")
 prefer 2 apply (simp add:funcset_mem) prefer 2 apply (simp add:Nset_def)
 apply (simp add:cmp_def)
apply (rule allI)+ apply (rule impI) apply (erule conjE)
 apply (frule_tac f = fa and n = n and A = A in func_pre)
 apply (frule_tac f = sa and n = n and A = "carrier R" in func_pre)
 apply (subgoal_tac "linear_combination R (fgmodule R A z i f s) n sa (cmp g fa) = linear_combination R (fgmodule R A z i f s) n sa fa") prefer 2 apply blast
 apply (thin_tac "\<forall>fa sa. fa \<in> Nset n \<rightarrow> A \<and> sa \<in> Nset n \<rightarrow> carrier R \<longrightarrow>
 linear_combination R (fgmodule R A z i f s) n sa (cmp g fa) =
             linear_combination R (fgmodule R A z i f s) n sa fa")
 apply (simp add:linear_combination_def)
 apply (subgoal_tac "sa (Suc n) \<star>\<^sub>(fgmodule R A z i f s) (cmp g fa (Suc n)) =
 sa (Suc n) \<star>\<^sub>(fgmodule R A z i f s) (fa (Suc n))") apply simp
 apply (subgoal_tac "Suc n \<in> Nset (Suc n)")
 apply (frule_tac f = fa and A = "Nset (Suc n)" and B = A in funcset_mem, assumption+)
 apply (simp add:cmp_def)
 apply (simp add:Nset_def)
done

lemma fg_freeTr:"\<lbrakk>ring R; R module M; free_generator R M A;
 R module fgmodule R A z i f s; free_generator R (fgmodule R A z i f s) A;
 g \<in> mHom R M (fgmodule R A z i f s); \<forall>x\<in>A. g x = x; fa \<in> Nset n \<rightarrow> A; sa \<in> Nset n \<rightarrow> carrier R\<rbrakk> \<Longrightarrow> linear_combination R (fgmodule R A z i f s) n sa (cmp g fa) = linear_combination R (fgmodule R A z i f s) n sa fa"
apply (simp add:fg_freeTr1)
done

lemma fg_free1:"\<lbrakk> A \<noteq> {}; ring R; fgmodule_condition R f i s A z; free_generator R (fgmodule R A z i f s) A; R module M; free_generator R M A\<rbrakk> \<Longrightarrow> M \<cong>\<^sub>R (fgmodule R A z i f s)"
apply (subgoal_tac "(\<lambda>x\<in>A. x) \<in> A \<rightarrow> carrier (fgmodule R A z i f s)")
 prefer 2 apply (rule univar_func_test) apply (rule ballI) apply simp
 apply (simp add:a_in_carr_fgmodule)
 apply (frule fgmodule_is_module [of "R" "f" "i" "s" "A" "z"], assumption+)
 apply (frule exist_extension_mhom [of "R" "M" "fgmodule R A z i f s" "A"], assumption+) apply simp
 apply (subgoal_tac "\<forall>g\<in> mHom R M (fgmodule R A z i f s). (\<forall>x\<in>A. g x = x) \<longrightarrow> M \<cong>\<^sub>R (fgmodule R A z i f s)") apply blast
 apply (thin_tac "\<exists>g\<in>mHom R M (fgmodule R A z i f s). \<forall>x\<in>A. g x = x")
 apply (rule ballI) apply (rule impI)
 apply (thin_tac "(\<lambda>x\<in>A. x) \<in> A \<rightarrow> carrier (fgmodule R A z i f s)")
 apply (simp add:misomorphic_def)
 apply (subgoal_tac "bijec\<^sub>M\<^sub>,\<^sub>(fgmodule R A z i f s) g") apply blast
 apply (simp add:bijec_def)
apply (rule conjI)
 apply (simp add:injec_def)
 apply (rule conjI) apply (simp add:mHom_def)
 apply (rule equalityI)
 apply (rule subsetI)
 apply (simp add:ker_def) apply (erule conjE)
 apply (subgoal_tac "generator R M A")  prefer 2
  apply (simp add:free_generator_def) apply (simp add:generator_def)
  apply (erule conjE)
  apply (subgoal_tac "x \<in> linear_span R M (carrier R) A")
  prefer 2 apply simp apply (thin_tac "linear_span R M (carrier R) A = carrier M")
  apply (simp add:linear_span_def)
  apply (subgoal_tac "\<forall>n. \<forall>f\<in>Nset n \<rightarrow> A. \<forall>s\<in>Nset n \<rightarrow> carrier R.
  x = linear_combination R M n s f \<longrightarrow> x = 0\<^sub>M") apply blast
  apply (thin_tac "\<exists>n. \<exists>f\<in>Nset n \<rightarrow> A. \<exists>s\<in>Nset n \<rightarrow> carrier R.
                                       x = linear_combination R M n s f")
  apply (rule allI) apply (rule ballI)+ apply (rule impI)
  apply (frule whole_ideal [of "R"])
  apply (subgoal_tac "A \<subseteq> carrier M") prefer 2 apply (simp add:free_generator_def generator_def)
 apply (frule_tac s = sa and n = n and f = fa and H = A in same_together[of "R" "carrier R" "M"], assumption+)
 apply (subgoal_tac "\<forall>t\<in>Nset (card (fa ` Nset n) - Suc 0) \<rightarrow> carrier R.
 \<forall>g\<in>Nset (card (fa ` Nset n) - Suc 0) \<rightarrow> fa ` Nset n.
 surj_to g (Nset (card (fa ` Nset n) - Suc 0)) (fa ` Nset n) \<and>
 e\<Sigma> M (\<lambda>j. sa j \<star>\<^sub>M (fa j)) n =  e\<Sigma> M (\<lambda>k. t k \<star>\<^sub>M (g k)) (card (fa ` (Nset n)) - Suc 0) \<longrightarrow> x = 0\<^sub>M")
 apply (thin_tac "g \<in> mHom R M (fgmodule R A z i f s)")
 apply (thin_tac "g x = 0\<^sub>(fgmodule R A z i f s)") apply simp
 apply (thin_tac "\<exists>t\<in>Nset (card (fa ` Nset n) - Suc 0) \<rightarrow> carrier R.
 \<exists>g\<in>Nset (card (fa ` Nset n) - Suc 0) \<rightarrow> fa ` Nset n.
  surj_to g (Nset (card (fa ` Nset n) - Suc 0)) (fa ` Nset n) \<and>
  e\<Sigma> M (\<lambda>j.  sa j \<star>\<^sub>M (fa j)) n = e\<Sigma> M (\<lambda>k. t k \<star>\<^sub>M (g k)) (card (fa ` Nset n) - Suc 0)") apply (rule ballI)+ apply (rule impI) apply (erule conjE)+
 apply (simp add:linear_combination_def)
 apply (thin_tac "e\<Sigma> M (\<lambda>j.  sa j \<star>\<^sub>M (fa j)) n =
          e\<Sigma> M (\<lambda>k. t k \<star>\<^sub>M (ga k)) (card (fa ` (Nset n)) - Suc 0)")
  apply (frule whole_ideal [of "R"])
  apply (frule_tac f = g and s = t and g = ga in linmap_im_lincomb [of "R" "carrier R" "M" "fgmodule R A z i f s" _ "A"], assumption+)
  apply (rule univar_func_test) apply (rule ballI)
  apply (subgoal_tac "ga xa \<in> fa ` Nset n")
  apply (frule_tac f = fa and A = "Nset n" and B = A and ?A1.0 = "Nset n" in image_sub) apply simp apply (simp add:subsetD) apply (simp add:funcset_mem)
  apply (subgoal_tac "ga \<in> Nset (card (fa ` Nset n) - Suc 0) \<rightarrow> A")
  apply (subgoal_tac "inj_on ga (Nset (card (fa ` Nset n) - Suc 0))")
  apply (thin_tac "ga \<in> Nset (card (fa ` Nset n) - Suc 0) \<rightarrow> fa ` Nset n")
  apply (simp add:fg_freeTr) apply (simp add:linear_combination_def)
  apply (subgoal_tac "t \<in> Nset (card (fa ` Nset n) - Suc 0) \<rightarrow> {0\<^sub>R}")
  apply (frule_tac s = t and n = "card (fa ` Nset n) - Suc 0" and m = ga in linear_comb0_1[of "R" "M" "A"], assumption+)
  apply (simp add:linear_combination_def)
  apply (thin_tac "g (e\<Sigma> M (\<lambda>k. t k \<star>\<^sub>M (ga k)) (card (fa ` Nset n) - Suc 0)) =
  e\<Sigma> (fgmodule R A z i f s) (\<lambda>j. t j \<star>\<^sub>(fgmodule R A z i f s) (ga j)) (card (fa ` Nset n) - Suc 0)")
  apply (thin_tac "x = e\<Sigma> M (\<lambda>k. t k \<star>\<^sub>M (ga k)) (card (fa ` Nset n) - Suc 0)")
  apply (frule sym) apply (thin_tac "0\<^sub>(fgmodule R A z i f s) =
 e\<Sigma> (fgmodule R A z i f s) (\<lambda>j. t j \<star>\<^sub>(fgmodule R A z i f s) (ga j)) (card (fa ` Nset n) - Suc 0)")
  apply (simp add:free_generator_def[of "R" "fgmodule R A z i f s"] linear_combination_def) apply (erule conjE) apply blast
  apply (subgoal_tac "finite (Nset n)") prefer 2 apply (simp add:finite_Nset)
  apply (subgoal_tac "finite (fa ` (Nset n))") prefer 2 apply simp
  apply (frule_tac A = "fa ` (Nset n)" and n = "card (fa ` Nset n) - Suc 0" and f = ga in Nset2finite_inj)
  apply (subgoal_tac "0 < card (fa ` (Nset n))") apply simp
  apply (rule nonempty_card_pos, assumption+)
  apply (frule_tac f = fa and A = "Nset n" and B = "A" and a = "0::nat" in mem_in_image) apply (simp add:Nset_def) apply (simp add:nonempty)
  apply (subgoal_tac "0 \<in> Nset n") apply (simp add:nonempty)
  apply (simp add:Nset_def) apply assumption+
  apply (rule univar_func_test)
  apply (rule ballI)
  apply (frule_tac f = fa and A = "Nset n" and B = A and ?A1.0 = "Nset n" in image_sub) apply simp
   apply (frule_tac f = ga and A = "Nset (card (fa ` Nset n) - Suc 0)" and B =  "fa ` Nset n" and x = xa in funcset_mem) apply assumption apply (simp add:subsetD)
  apply (rule subsetI)
  apply (simp add:ker_def)
  apply (frule module_is_ag[of "R" "M"], assumption+)
  apply (simp add:ag_inc_zero) apply (simp add:mHom_0)
apply (simp add:surjec_def) apply (rule conjI)
 apply (simp add:mHom_def)
 apply (rule surj_to_test) apply (simp add:mHom_def aHom_def)
 apply (rule ballI)
 apply (subgoal_tac "generator R (fgmodule R A z i f s) A")
 prefer 2 apply (simp add:free_generator_def)
 apply (simp add:generator_def)
 apply (subgoal_tac "b \<in> linear_span R (fgmodule R A z i f s) (carrier R) A ")
 prefer 2 apply simp apply (erule conjE)
 apply (thin_tac "linear_span R (fgmodule R A z i f s) (carrier R) A =
             carrier (fgmodule R A z i f s)")
 apply (simp add:linear_span_def)
 apply (subgoal_tac "\<forall>n. \<forall>fa\<in>Nset n \<rightarrow> A. \<forall>sa\<in>Nset n \<rightarrow> carrier R.
 b = linear_combination R (fgmodule R A z i f s) n sa fa \<longrightarrow> (\<exists>a\<in>carrier M. g a = b)") apply blast
 apply (thin_tac "\<exists>n. \<exists>fa\<in>Nset n \<rightarrow> A. \<exists>sa\<in>Nset n \<rightarrow> carrier R.
         b = linear_combination R (fgmodule R A z i f s) n sa fa")
 apply (rule allI) apply (rule ballI)+ apply (rule impI) apply simp
 apply (subgoal_tac "linear_combination R M n sa fa \<in> carrier M")
 apply (subgoal_tac "g (linear_combination R M n sa fa) = linear_combination R (fgmodule R A z i f s) n sa fa") apply blast
 apply (frule whole_ideal [of "R"])
 apply (frule_tac f = g and s = sa and g = fa and n = n in linmap_im_lincomb [of "R" "carrier R" "M" "fgmodule R A z i f s" _ "A"], assumption+)
 apply (simp add:free_generator_def generator_def) apply assumption+
 apply simp apply (simp add:fg_freeTr)
 apply (subgoal_tac "submodule R M (carrier M)")
 apply (frule whole_ideal[of "R"])
 apply (rule linear_combination_mem [of "R" "M" "carrier R" "carrier M"],
                                                assumption+)
 apply simp apply assumption+
 apply (simp add:free_generator_def generator_def) apply (erule conjE)+
 apply (rule univar_func_test) apply (rule ballI)
 apply (simp add:funcset_mem subsetD)
 apply (simp add:submodule_whole)
done

lemma fg_free:"\<lbrakk>ring R; fgmodule_condition R f i s A z; free_generator R (fgmodule R A z i f s) A; R module M; free_generator R M A\<rbrakk> \<Longrightarrow> M \<cong>\<^sub>R (fgmodule R A z i f s)"
apply (case_tac "A = {}")
apply (simp add:free_generator_def generator_def linear_span_def)
 apply (erule conjE)+
 apply (thin_tac "\<forall>n sa. sa \<in> Nset n \<rightarrow> carrier R \<and> (\<exists>fa. fa \<in> Nset n \<rightarrow> {} \<and>
 inj_on fa (Nset n) \<and> linear_combination R (fgmodule R {} z i f s) n sa fa =
 0\<^sub>(fgmodule R {} z i f s)) \<longrightarrow> sa \<in> Nset n \<rightarrow> {0\<^sub>R}")
 apply (thin_tac "\<forall>n s. s \<in> Nset n \<rightarrow> carrier R \<and> (\<exists>f. f \<in> Nset n \<rightarrow> {} \<and>
 inj_on f (Nset n) \<and> linear_combination R M n s f = 0\<^sub>M) \<longrightarrow> s \<in> Nset n \<rightarrow> {0\<^sub>R}")
 apply (frule fgmodule_is_module[of "R" "f" "i" "s" "{}" "z"], assumption+)
 apply (frule mHom_ex_one[of "R" "M" "fgmodule R {} z i f s"], assumption+)

 apply (subgoal_tac "bijec\<^sub>M\<^sub>,\<^sub>(fgmodule R {} z i f s) (mzeromap M (fgmodule R {} z i f s))")
 apply (simp add:misomorphic_def) apply blast
 apply (simp add:bijec_def)
 apply (simp add:injec_def surjec_def mHom_def)
 apply (rule conjI)
 apply (rule equalityI) apply (rule subsetI) apply (simp add:ker_def)
 apply (subgoal_tac "carrier M = {0\<^sub>M}") apply (thin_tac "{0\<^sub>M} = carrier M")
 apply simp apply (simp add:ker_def) apply (rule sym) apply (simp add:mzeromap_def) apply (rule sym) apply assumption
 apply (rule surj_to_test)
 apply (simp add:aHom_def) apply (rule ballI)
 apply (subgoal_tac "b \<in> {0\<^sub>fgmodule R {} z i f s}") prefer 2 apply simp
 apply (thin_tac "{0\<^sub>fgmodule R {} z i f s} = carrier (fgmodule R {} z i f s)") apply simp
 apply (subgoal_tac "carrier M = {0\<^sub>M}") apply (thin_tac "{0\<^sub>M} = carrier M")
 apply simp apply (simp add:mzeromap_def) apply (rule sym) apply assumption
apply (simp add:fg_free1)
done

section "5. direct sum, again"

constdefs
 miota :: "[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme,
 ('a, 'r, 'm1) ModuleType_scheme] \<Rightarrow> 'a \<Rightarrow> 'a"
 "miota R M1 M == \<lambda>x\<in>carrier M1. x"

 msubmodule ::"[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme,
 ('a, 'r, 'm1) ModuleType_scheme] \<Rightarrow> bool"
 "msubmodule R M M1 == miota R M1 M \<in> mHom R M1 M \<and> (carrier M1) \<subseteq> (carrier M)"  (** M and M1 are R modules. **)

constdefs
 ds2 :: "[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('a, 'r, 'm1) ModuleType_scheme] \<Rightarrow> bool"
 "ds2 R M M1 M2 == R module M \<and> msubmodule R M M1 \<and> msubmodule R M M2 \<and>
(\<forall>x\<in>carrier M. \<exists>m1\<in>carrier M1. \<exists>m2\<in>carrier M2. x = m1 +\<^sub>M m2) \<and>
 (carrier M1) \<inter> (carrier M2) = {0\<^sub>M}"

syntax
"@DS2"::"[('a, 'r, 'm1) ModuleType_scheme, ('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('a, 'r, 'm1) ModuleType_scheme] \<Rightarrow> bool"
  ("(4_/ \<Oplus>\<^sub>_\<^sub>,\<^sub>_/ _)" [92,93,92,92]92)
 translations
 "M1 \<Oplus>\<^sub>R\<^sub>,\<^sub>M M2" == "ds2 R M M1 M2"

lemma msub_submodule:"\<lbrakk>ring R; R module M; R module M1; msubmodule R M M1\<rbrakk> \<Longrightarrow>
                       submodule R M (carrier M1)"
apply (simp add:submodule_def msubmodule_def) apply (erule conjE)
apply (rule conjI)
 apply (simp add:asubgroup_def) apply (simp add:b_ag_def subgroup_def)
 apply (rule conjI)
 apply (rule ballI)+
 apply (frule_tac m = x and n = y in mHom_add[of "R" "M1" "M" "miota R M1 M"],
             assumption+)
 apply (frule module_is_ag [of "R" "M1"], assumption+)
 apply (frule_tac x = x and y = y in ag_pOp_closed [of "M1"], assumption+)
 apply (simp add:miota_def)
apply (rule conjI) apply (rule ballI)
 apply (frule module_is_ag [of "R" "M1"], assumption+)
 apply (frule_tac x = x in ag_mOp_closed[of "M1"], assumption+)
 apply (frule_tac m = x in mHom_inv[of "R" "M1" "M" _ "miota R M1 M"], assumption+) apply (simp add:miota_def)
 apply (frule mHom_0[of "R" "M1" "M" "miota R M1 M"], assumption+)
 apply (frule module_inc_zero [of "R" "M1"], assumption+)
 apply (simp add:miota_def)
apply (rule ballI)+
 apply (frule_tac m = m and a = a in mHom_lin [of "R" "M1" "M" _ "miota R M1 M" _], assumption+)
 apply (frule_tac a = a and m = m in sprod_mem[of "R" "M1"], assumption+)
 apply (simp add:miota_def)
done

lemma ds2_unique:"\<lbrakk>ring R; R module M; R module M1; R module M2; ds2 R M M1 M2;
 m1 \<in> carrier M1; m1' \<in> carrier M1; m2 \<in> carrier M2; m2' \<in> carrier M2; m1 +\<^sub>M m2 = m1' +\<^sub>M m2'\<rbrakk> \<Longrightarrow> m1 = m1' \<and> m2 = m2'"
apply (frule msub_submodule [of "R" "M" "M1"], assumption+)
 apply (simp add:ds2_def)
apply (frule msub_submodule [of "R" "M" "M2"], assumption+)
 apply (simp add:ds2_def)
 apply (subgoal_tac "carrier M1 \<subseteq> carrier M")
 apply (subgoal_tac "carrier M2 \<subseteq> carrier M")
 apply (frule subsetD [of "carrier M1" "carrier M" "m1"], assumption+)
 apply (frule subsetD [of "carrier M1" "carrier M" "m1'"], assumption+)
 apply (frule subsetD [of "carrier M2" "carrier M" "m2"], assumption+)
 apply (frule subsetD [of "carrier M2" "carrier M" "m2'"], assumption+)
 apply (subgoal_tac "-\<^sub>M m1' +\<^sub>M (m1 +\<^sub>M m2) = -\<^sub>M m1' +\<^sub>M (m1' +\<^sub>M m2')")
 prefer 2 apply simp apply (thin_tac "m1 +\<^sub>M m2 =  m1' +\<^sub>M m2'")
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (frule_tac x = m1' in ag_mOp_closed [of "M"], assumption+)
 apply (simp add:ag_pOp_assoc [THEN sym]) apply (simp add:ag_l_inv1)
 apply (simp add:ag_l_zero)
 apply (subgoal_tac "-\<^sub>M m1' +\<^sub>M m1 +\<^sub>M m2 +\<^sub>M (-\<^sub>M m2) = m2' +\<^sub>M (-\<^sub>M m2)")
 prefer 2 apply simp apply (thin_tac "-\<^sub>M m1' +\<^sub>M m1 +\<^sub>M m2 = m2'")
 apply (frule ag_pOp_closed [of "M" "-\<^sub>M m1'" "m1"], assumption+)
 apply (frule_tac x = m2 in ag_mOp_closed [of "M"], assumption+)
 apply (simp add:ag_pOp_assoc [of "M" "-\<^sub>M m1' +\<^sub>M m1" "m2" "-\<^sub>M m2"])
 apply (simp add:ag_r_inv1) apply (simp add:ag_r_zero)
 apply (frule submodule_mOp_closed [of "R" "M" "carrier M1" "m1'"], assumption+)
 apply (frule submodule_pOp_closed [of "R" "M" "carrier M1" "-\<^sub>M m1'" "m1"], assumption+)
 apply (frule submodule_pOp_closed [of "R" "M" "carrier M2" "m2'" "-\<^sub>M m2"], assumption+)
 apply (rule submodule_mOp_closed [of "R" "M" "carrier M2" "m2"], assumption+)
 apply (subgoal_tac "-\<^sub>M m1' +\<^sub>M m1 \<in> carrier M1 \<inter> carrier M2")
 prefer 2 apply simp apply (subgoal_tac "carrier M1 \<inter> carrier M2 = {0\<^sub>M}")
 apply (frule sym) apply (thin_tac "-\<^sub>M m1' +\<^sub>M m1 =  m2' +\<^sub>M -\<^sub>M m2")
 apply simp
 apply (subgoal_tac "m1' +\<^sub>M ( -\<^sub>M m1' +\<^sub>M m1) = m1' +\<^sub>M 0\<^sub>M")
 apply (thin_tac "-\<^sub>M m1' +\<^sub>M m1 = 0\<^sub>M")
 apply (simp add:ag_pOp_assoc[THEN sym]) apply (simp add:ag_r_inv1)
 apply (simp add:ag_l_zero) apply (simp add:ag_r_zero)
 apply (subgoal_tac "m2' +\<^sub>M -\<^sub>M m2 +\<^sub>M m2 = 0\<^sub>M +\<^sub>M m2") prefer 2 apply simp
 apply (thin_tac "m2' +\<^sub>M -\<^sub>M m2 = 0\<^sub>M") apply (simp add:ag_pOp_assoc)
 apply (simp add:ag_l_inv1) apply (simp add:ag_l_zero)
 apply (simp add:ag_r_zero) apply (simp add:ag_l_inv1)
 apply (simp add:ds2_def)
 apply (simp add:ds2_def msubmodule_def)+
done

lemma miota_injec:"\<lbrakk>ring R; R module M; R module M1; R module M2; ds2 R M M1 M2; msubmodule R M M1\<rbrakk> \<Longrightarrow> miota R M1 M \<in> mHom R M1 M \<and> injec\<^sub>M1\<^sub>,\<^sub>M (miota R M1 M )"
apply (rule conjI)
 apply (simp add:msubmodule_def)
apply (simp add:injec_def)
 apply (rule conjI)
 apply (simp add:msubmodule_def mHom_def)
apply (rule equalityI)
 prefer 2
 apply (rule subsetI) apply simp apply (simp add:ker_def)
 apply (simp add:module_inc_zero) apply (simp add:msubmodule_def)
 apply (erule conjE)
 apply (simp add:mHom_0)
apply (rule subsetI)
 apply (simp add:ker_def) apply (erule conjE)
 apply (simp add:miota_def) thm mHom_0 apply (simp add:msubmodule_def)
 apply (erule conjE)
 apply (frule mHom_0 [of "R" "M1" "M" "miota R M1 M"], assumption+)
 apply (frule module_inc_zero [of "R" "M1"], assumption+)
 apply (simp add:miota_def)
done

constdefs
 mproj1 :: "[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme,
 ('a, 'r, 'm1) ModuleType_scheme, ('a, 'r, 'm1) ModuleType_scheme] \<Rightarrow> 'a \<Rightarrow> 'a"
 "mproj1 R M1 M2 M ==\<lambda>x\<in>carrier M. THE x1. x1 \<in> carrier M1 \<and> (x +\<^sub>M (-\<^sub>M x1)) \<in> carrier M2"

 mproj2 :: "[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme,
 ('a, 'r, 'm1) ModuleType_scheme, ('a, 'r, 'm1) ModuleType_scheme] \<Rightarrow> 'a \<Rightarrow> 'a"
 "mproj2 R M1 M2 M == mproj1 R M2 M1 M"

(** mproj is used under the condition ds2 R M M1 M2 **)

lemma mprojTr1:"\<lbrakk>ring R; R module M1; R module M2; R module M; ds2 R M M1 M2;
x \<in> carrier M \<rbrakk> \<Longrightarrow> \<exists>!x1. x1 \<in> carrier M1 \<and> (x +\<^sub>M (-\<^sub>M x1)) \<in> carrier M2"
apply (rule ex_ex1I)
 apply (simp add:ds2_def) apply (erule conjE)+
 apply (subgoal_tac "\<exists>m1\<in>carrier M1. \<exists>m2\<in>carrier M2. x =  m1 +\<^sub>M m2")
 prefer 2 apply simp
 apply (thin_tac "\<forall>x\<in>carrier M. \<exists>m1\<in>carrier M1. \<exists>m2\<in>carrier M2. x= m1 +\<^sub>M m2")
 apply (subgoal_tac "\<forall>m1\<in>carrier M1. \<forall>m2\<in>carrier M2. x = m1 +\<^sub>M m2 \<longrightarrow> (\<exists>x1. x1 \<in> carrier M1 \<and>  x +\<^sub>M -\<^sub>M x1 \<in> carrier M2)") apply blast
 apply (thin_tac "\<exists>m1\<in>carrier M1. \<exists>m2\<in>carrier M2. x =  m1 +\<^sub>M m2")
 apply (rule ballI)+ apply (rule impI)
 apply (subgoal_tac "m1 \<in> carrier M") apply (subgoal_tac "m2 \<in> carrier M")
 apply (subgoal_tac "x +\<^sub>M (-\<^sub>M m1) = m1 +\<^sub>M m2 +\<^sub>M (-\<^sub>M m1)")
   prefer 2 apply simp
   apply (frule module_is_ag [of "R" "M"], assumption+)
   apply (frule_tac x = m1 in ag_mOp_closed[of "M"], assumption+)
   apply (thin_tac "x =  m1 +\<^sub>M m2")
   apply (simp add:ag_pOp_assoc)
   apply (frule_tac x = m2 and y = "-\<^sub>M m1" in ag_pOp_commute [of "M"], assumption+) apply simp apply (thin_tac "m2 +\<^sub>M -\<^sub>M m1 =  -\<^sub>M m1 +\<^sub>M m2")
 apply (simp add:ag_pOp_assoc [THEN sym]) apply (simp add:ag_r_inv1)
 apply (simp add:ag_l_zero)
 apply (rotate_tac -3) apply (frule sym) apply (thin_tac "x +\<^sub>M -\<^sub>M m1 = m2")
 apply simp apply (thin_tac "x +\<^sub>M -\<^sub>M m1 \<in> carrier M") apply blast
 apply (simp add:msubmodule_def [of "R" "M" "M2"]) apply (erule conjE)+
 apply (simp add:subsetD)
 apply (simp add:msubmodule_def [of "R" "M" "M1"]) apply (erule conjE)+
 apply (simp add:subsetD)
 apply (erule conjE)+
 apply (frule_tac x = "x +\<^sub>M -\<^sub>M x1" and A = "carrier M2" in inEx)
 apply (subgoal_tac "\<forall>y1\<in>carrier M2. y1 = x +\<^sub>M -\<^sub>M x1 \<longrightarrow> x1 = y")
 apply blast apply (thin_tac "\<exists>y\<in>carrier M2. y =  x +\<^sub>M -\<^sub>M x1")
 apply (rule ballI) apply (rule impI)
 apply (frule_tac x = "x +\<^sub>M -\<^sub>M y" and A = "carrier M2" in inEx)
 apply (subgoal_tac "\<forall>ya\<in>carrier M2. ya = x +\<^sub>M -\<^sub>M y \<longrightarrow> x1 = y")
 apply blast apply (thin_tac "\<exists>ya\<in>carrier M2. ya =  x +\<^sub>M -\<^sub>M y")
 apply (rule ballI) apply (rule impI)
apply (subgoal_tac "x1 \<in> carrier M") apply (subgoal_tac "y \<in> carrier M")
 apply (subgoal_tac "y1 \<in> carrier M") apply (subgoal_tac "ya \<in> carrier M")
 apply (subgoal_tac "y1 +\<^sub>M x1 = x +\<^sub>M -\<^sub>M x1 +\<^sub>M x1")
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (frule_tac x = x1 in ag_mOp_closed [of "M"], assumption+)
 apply (thin_tac "y1 =  x +\<^sub>M -\<^sub>M x1")
 apply (thin_tac "x +\<^sub>M -\<^sub>M y \<in> carrier M2")
 apply (thin_tac "x +\<^sub>M -\<^sub>M x1 \<in> carrier M2")
 apply (simp add:ag_pOp_assoc)
 apply (simp add:ag_l_inv1) apply (simp add:ag_r_zero)
 apply (frule sym)
 apply (thin_tac "ya =  x +\<^sub>M -\<^sub>M y") apply simp
 apply (subgoal_tac "x +\<^sub>M -\<^sub>M y +\<^sub>M y = ya +\<^sub>M y")
 apply (frule_tac x = y in ag_mOp_closed [of "M"], assumption+)
 apply (thin_tac "x +\<^sub>M -\<^sub>M y = ya")
 apply (simp add:ag_pOp_assoc)  apply (simp add:ag_l_inv1)
 apply (simp add:ag_r_zero)
 apply (thin_tac "ya +\<^sub>M y \<in> carrier M")
 apply (thin_tac "x = ya +\<^sub>M y")
 apply (simp add:ag_pOp_commute)
apply (simp add:ds2_unique [of "R" "M" "M1" "M2"]) apply simp apply simp
 apply (simp add:ds2_def msubmodule_def) apply (erule conjE)+
 apply (simp add:subsetD)+
 apply (simp add:ds2_def msubmodule_def) apply (erule conjE)+
 apply (simp add:subsetD)+
 apply (simp add:ds2_def msubmodule_def) apply (erule conjE)+
 apply (simp add:subsetD)+
 apply (simp add:ds2_def msubmodule_def) apply (erule conjE)+
 apply (simp add:subsetD)+
done

lemma mprojTr2:"\<lbrakk>ring R; R module M1; R module M2; R module M; ds2 R M M1 M2;
x \<in> carrier M; x1 \<in> carrier M1; (x +\<^sub>M (-\<^sub>M x1)) \<in> carrier M2; y1 \<in> carrier M1;(x +\<^sub>M (-\<^sub>M y1)) \<in> carrier M2  \<rbrakk> \<Longrightarrow> x1 = y1"
apply (frule_tac x = x in mprojTr1[of "R" "M1" "M2" "M"], assumption+)
apply blast
done

lemma mproj:"\<lbrakk>ring R; R module M1; R module M2; R module M; ds2 R M M1 M2\<rbrakk> \<Longrightarrow> mproj1 R M1 M2 M \<in> mHom R M M1"
apply (simp add:mHom_def)
apply (rule conjI)
 apply (simp add:aHom_def)
 apply (rule conjI)
 apply (rule univar_func_test) apply (rule ballI)
 apply (simp add:mproj1_def)
 apply (subgoal_tac "(THE x1. x1 \<in> carrier M1 \<and>  x +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1 \<and> x +\<^sub>M -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and>  x +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2") apply simp
 apply (rule theI')
 apply (simp add:mprojTr1)
apply (simp add:restrict_def mproj1_def extensional_def)
 apply (rule ballI)+ apply (rule conjI) apply (rule impI)
 prefer 2
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (simp add:ag_pOp_closed)
 apply (subgoal_tac "\<exists>a1\<in>carrier M1. \<exists>a2\<in>carrier M2. a = a1 +\<^sub>M a2")
 prefer 2 apply (simp add:ds2_def)
 apply (subgoal_tac "\<forall>a1\<in>carrier M1. \<forall>a2\<in>carrier M2. a = a1 +\<^sub>M a2 \<longrightarrow>
  (THE x1. x1 \<in> carrier M1 \<and>   a +\<^sub>M b +\<^sub>M -\<^sub>M x1 \<in> carrier M2) =
              (THE x1. x1 \<in> carrier M1 \<and>  a +\<^sub>M -\<^sub>M x1 \<in> carrier M2) +\<^sub>M1
                (THE x1. x1 \<in> carrier M1 \<and>  b +\<^sub>M -\<^sub>M x1 \<in> carrier M2)")
 apply blast
 apply (thin_tac "\<exists>a1\<in>carrier M1. \<exists>a2\<in>carrier M2. a = a1 +\<^sub>M a2")
 apply (rule ballI)+ apply (rule impI)
 apply (subgoal_tac "\<exists>b1\<in>carrier M1. \<exists>b2\<in>carrier M2. b = b1 +\<^sub>M b2")
 prefer 2 apply (simp add:ds2_def)
 apply (subgoal_tac "\<forall>b1\<in>carrier M1. \<forall>b2\<in>carrier M2. b = b1 +\<^sub>M b2 \<longrightarrow>
  (THE x1. x1 \<in> carrier M1 \<and>   a +\<^sub>M b +\<^sub>M -\<^sub>M x1 \<in> carrier M2) =
              (THE x1. x1 \<in> carrier M1 \<and>  a +\<^sub>M -\<^sub>M x1 \<in> carrier M2) +\<^sub>M1
                (THE x1. x1 \<in> carrier M1 \<and>  b +\<^sub>M -\<^sub>M x1 \<in> carrier M2)")
 apply blast
 apply (thin_tac "\<exists>b1\<in>carrier M1. \<exists>b2\<in>carrier M2. b = b1 +\<^sub>M b2")
 apply (rule ballI)+ apply (rule impI)
 apply simp
 apply (subgoal_tac "(THE x1.  x1 \<in> carrier M1 \<and>
          a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) = a1 +\<^sub>M b1")
 apply (subgoal_tac "(THE x1.  x1 \<in> carrier M1 \<and>
          a1 +\<^sub>M a2 +\<^sub>M  (-\<^sub>M x1) \<in> carrier M2) = a1")
 apply (subgoal_tac "(THE x1.  x1 \<in> carrier M1 \<and>
          b1 +\<^sub>M b2 +\<^sub>M  (-\<^sub>M x1) \<in> carrier M2) = b1")
 apply simp
 apply (simp add:ds2_def) apply (erule conjE)+
 apply (simp add:msubmodule_def [of "R" "M" "M1"]) apply (erule conjE)+
 apply (frule_tac m = a1 and n = b1 in mHom_add [of "R" "M1" "M" "miota R M1 M"], assumption+)
 apply (frule module_is_ag [of "R" "M1"], assumption+)
 apply (frule_tac x = a1 and y = b1 in ag_pOp_closed [of "M1"], assumption+)
 apply (simp add:miota_def)
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and> a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) =  a1 +\<^sub>M b1")
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and>   a1 +\<^sub>M a2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) = a1")
 apply (subgoal_tac "(THE x1. x1 \<in> carrier M1 \<and>   b1 +\<^sub>M b2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1 \<and>   b1 +\<^sub>M b2 +\<^sub>M -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and>   b1 +\<^sub>M b2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2") apply (erule conjE)
 apply (rule_tac x = "b1 +\<^sub>M b2" and ?x1.0 = "THE x1. x1 \<in> carrier M1 \<and>   b1 +\<^sub>M b2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2" and ?y1.0 = b1 in mprojTr2[of "R" "M1" "M2" "M"], assumption+)
 apply (thin_tac "a1 +\<^sub>M a2 \<in> carrier M")
 apply (thin_tac " b1 +\<^sub>M b2 \<in> carrier M")
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and>   b1 +\<^sub>M b2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1")
 apply (thin_tac "b1 +\<^sub>M b2 +\<^sub>M  -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and>
 b1 +\<^sub>M b2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2")
 apply (thin_tac "b =  b1 +\<^sub>M b2")
 apply (subgoal_tac "b1 \<in> carrier M") apply (subgoal_tac "b2 \<in> carrier M")
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (frule_tac x = b1 in ag_mOp_closed [of "M"], assumption+)
 apply (simp add:ag_pOp_assoc)
 apply (frule_tac x = b2 and y = "-\<^sub>M b1" in ag_pOp_commute, assumption+)
 apply simp apply (thin_tac " b2 +\<^sub>M -\<^sub>M b1 =  -\<^sub>M b1 +\<^sub>M b2")
 apply (simp add:ag_pOp_assoc [THEN sym])
 apply (simp add:ag_r_inv1) apply (simp add:ag_l_zero)
 apply (simp add:ds2_def msubmodule_def [of "R" "M" "M2"]) apply (erule conjE)+
 apply (simp add:subsetD)
 apply (simp add:ds2_def msubmodule_def [of "R" "M" "M1"]) apply (erule conjE)+
 apply (simp add:subsetD)
apply (rule theI')
 apply (simp add:mprojTr1)
 apply (thin_tac "a1 +\<^sub>M a2 \<in> carrier M")
 apply (thin_tac " b1 +\<^sub>M b2 \<in> carrier M")
 apply (thin_tac "b =  b1 +\<^sub>M b2")
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and> a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) = a1 +\<^sub>M b1")
 apply (subgoal_tac "(THE x1. x1 \<in> carrier M1 \<and>   a1 +\<^sub>M a2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1 \<and>  a1 +\<^sub>M a2 +\<^sub>M -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and>   a1 +\<^sub>M a2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2") apply (erule conjE)
 apply (rule_tac x = "a1 +\<^sub>M a2" and ?x1.0 = "THE x1. x1 \<in> carrier M1 \<and> a1 +\<^sub>M a2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2" and ?y1.0 = a1 in mprojTr2[of "R" "M1" "M2" "M"], assumption+)
 apply (subgoal_tac "a1 \<in> carrier M") apply (subgoal_tac "a2 \<in> carrier M")
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (simp add:ag_pOp_closed)
 apply (simp add:ds2_def msubmodule_def [of "R" "M" "M2"]) apply (erule conjE)+
 apply (simp add:subsetD)
 apply (simp add:ds2_def msubmodule_def [of "R" "M" "M1"]) apply (erule conjE)+
 apply (simp add:subsetD) apply assumption+
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and>   a1 +\<^sub>M a2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1")
 apply (thin_tac "a1 +\<^sub>M a2 +\<^sub>M -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and>   a1 +\<^sub>M a2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2")
 apply (frule module_is_ag[of "R" "M"], assumption+)
 apply (subgoal_tac "a1 \<in> carrier M")
 apply (frule_tac x = a1 in ag_mOp_closed [of "M"], assumption+)
 apply (subgoal_tac "a2 \<in> carrier M")   (** here is repeatition *)
 apply (simp add:ag_pOp_assoc)
 apply (frule_tac x = a2 and y = "-\<^sub>M a1" in ag_pOp_commute, assumption+)
 apply simp apply (thin_tac "a2 +\<^sub>M -\<^sub>M a1 =  -\<^sub>M a1 +\<^sub>M a2")
 apply (simp add:ag_pOp_assoc [THEN sym])
 apply (simp add:ag_r_inv1) apply (simp add:ag_l_zero)
 apply (simp add:ds2_def msubmodule_def [of "R" "M" "M2"]) apply (erule conjE)+
 apply (simp add:subsetD)
 apply (simp add:ds2_def msubmodule_def [of "R" "M" "M1"]) apply (erule conjE)+
 apply (simp add:subsetD)
(** from here repeat *)
apply (rule theI')
 apply (rule_tac x = "a1 +\<^sub>M a2" in mprojTr1 [of "R" "M1" "M2" "M"], assumption+)
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (rule ag_pOp_closed [of "M"], assumption+)
 apply (simp add:ds2_def msubmodule_def [of "R" "M" "M1"]) apply (erule conjE)+
 apply (simp add:subsetD)
 apply (simp add:ds2_def msubmodule_def [of "R" "M" "M2"]) apply (erule conjE)+
 apply (simp add:subsetD)
 apply (subgoal_tac "(THE x1. x1 \<in> carrier M1 \<and> a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1 \<and> a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) +\<^sub>M -\<^sub>M (THE x1.
 x1 \<in> carrier M1 \<and> a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2")
 apply (erule conjE)+
 apply (rule_tac x = "a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2)" and ?x1.0 = "THE x1. x1 \<in> carrier M1 \<and> a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2" and ?y1.0 = "a1 +\<^sub>M b1" in mprojTr2[of "R" "M1" "M2" "M"], assumption+)
 apply (frule module_is_ag[of "R" "M1"], assumption+)
 apply (simp add:ds2_def) apply (erule conjE)+
 apply (simp add:msubmodule_def [of "R" "M" "M1"]) apply (erule conjE)+
 apply (frule_tac m = a1 and n = b1 in mHom_add [of "R" "M1" "M" "miota R M1 M"], assumption+)
 apply (frule_tac x = a1 and y = b1 in ag_pOp_closed [of "M1"], assumption+)
 apply (simp add:miota_def)
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and> a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1")
 apply (thin_tac "a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) +\<^sub>M -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and>
  a1 +\<^sub>M a2 +\<^sub>M (b1 +\<^sub>M b2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2")
 apply (thin_tac "a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) \<in> carrier M")
 apply (subgoal_tac "a1 \<in> carrier M") apply (subgoal_tac "a2 \<in> carrier M")
 apply (subgoal_tac "b1 \<in> carrier M") apply (subgoal_tac "b2 \<in> carrier M")
apply (frule module_is_ag[of "R" "M"], assumption+)
 apply (frule_tac x = a1 and y = a2 and z = "b1 +\<^sub>M b2" in ag_pOp_assoc, assumption+) apply simp apply (thin_tac "a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2) =  a1 +\<^sub>M ( a2 +\<^sub>M ( b1 +\<^sub>M b2))")
 apply (frule_tac  x1 = a2 and y1 = b1 and z1 = b2 in ag_pOp_assoc [THEN sym, of "M"], assumption+) apply simp apply (thin_tac "a2 +\<^sub>M ( b1 +\<^sub>M b2) =   a2 +\<^sub>M b1 +\<^sub>M b2")
 apply (frule_tac x = a2 and y = b1 in ag_pOp_commute[of "M"], assumption+)
 apply simp apply (thin_tac " a2 +\<^sub>M b1 =  b1 +\<^sub>M a2")
 apply (frule_tac x = a2 and y = b2 in ag_pOp_closed [of "M"], assumption+)
 apply (frule_tac x = b1 and y = a2 and z = b2 in ag_pOp_assoc, assumption+)
 apply simp apply (thin_tac "b1 +\<^sub>M a2 +\<^sub>M b2 =  b1 +\<^sub>M ( a2 +\<^sub>M b2)")
 apply (frule_tac x1 = a1 and y1 = b1 and z1 = "a2 +\<^sub>M b2" in ag_pOp_assoc [THEN sym, of "M"], assumption+) apply simp
 apply (thin_tac "a1 +\<^sub>M ( b1 +\<^sub>M ( a2 +\<^sub>M b2)) =   a1 +\<^sub>M b1 +\<^sub>M ( a2 +\<^sub>M b2)")
 apply (frule_tac x = a1 and y = b1 in ag_pOp_closed [of "M"], assumption+)
 apply (frule_tac x = "a1 +\<^sub>M b1" in ag_mOp_closed[of "M"], assumption+)
 apply (frule_tac x = "a1 +\<^sub>M b1" and y = "a2 +\<^sub>M b2" and z = "-\<^sub>M (a1 +\<^sub>M b1)"
 in ag_pOp_assoc, assumption+)
 apply simp apply (thin_tac "a1 +\<^sub>M b1 +\<^sub>M ( a2 +\<^sub>M b2) +\<^sub>M -\<^sub>M ( a1 +\<^sub>M b1) =
            a1 +\<^sub>M b1 +\<^sub>M (  a2 +\<^sub>M b2 +\<^sub>M -\<^sub>M ( a1 +\<^sub>M b1))")
 apply (frule_tac x = "a2 +\<^sub>M b2" and y = " -\<^sub>M ( a1 +\<^sub>M b1)" in ag_pOp_commute[of "M"], assumption+) apply simp
 apply (thin_tac "a2 +\<^sub>M b2 +\<^sub>M -\<^sub>M ( a1 +\<^sub>M b1) =  -\<^sub>M ( a1 +\<^sub>M b1) +\<^sub>M ( a2 +\<^sub>M b2)")
 apply (frule_tac x1 = "a1 +\<^sub>M b1" and y1 = "-\<^sub>M ( a1 +\<^sub>M b1)" and z1 = "a2 +\<^sub>M b2" in ag_pOp_assoc [THEN sym], assumption+) apply simp
 apply (thin_tac "a1 +\<^sub>M b1 +\<^sub>M ( -\<^sub>M ( a1 +\<^sub>M b1) +\<^sub>M ( a2 +\<^sub>M b2)) =
             a1 +\<^sub>M b1 +\<^sub>M -\<^sub>M ( a1 +\<^sub>M b1) +\<^sub>M ( a2 +\<^sub>M b2)")
 apply (simp add:ag_r_inv1) apply (simp add:ag_l_zero)
 apply (simp add:ds2_def msubmodule_def [of "R" "M" "M2"]) apply (erule conjE)+
 apply (frule_tac m = a2 and n = b2 in mHom_add [of "R" "M2" "M" "miota R M2 M"], assumption+)
 apply (frule module_is_ag [of "R" "M2"], assumption+)
 apply (frule_tac x = a2 and y = b2 in ag_pOp_closed [of "M2"], assumption+)
 apply (simp add:miota_def)
apply (simp add:ds2_def msubmodule_def) apply (erule conjE)+ (*simple repeat*)
 apply (simp add:subsetD)
apply (simp add:ds2_def msubmodule_def) apply (erule conjE)+ (*simple repeat*)
 apply (simp add:subsetD)
apply (simp add:ds2_def msubmodule_def) apply (erule conjE)+ (*simple repeat*)
 apply (simp add:subsetD)
apply (simp add:ds2_def msubmodule_def) apply (erule conjE)+ (*simple repeat*)
 apply (simp add:subsetD)
apply (rule theI')
 apply (frule_tac x = "a1 +\<^sub>M a2 +\<^sub>M ( b1 +\<^sub>M b2)" in mprojTr1 [of "R" "M1" "M2" "M"], assumption+)
apply (rule ballI)+
 apply (simp add:mproj1_def)
 apply (simp add:sprod_mem)
 apply (subgoal_tac "\<exists>m1\<in>carrier M1. \<exists>m2\<in>carrier M2. m = m1 +\<^sub>M m2")
 prefer 2 apply (simp add:ds2_def)
 apply (subgoal_tac "\<forall>m1\<in>carrier M1. \<forall>m2\<in>carrier M2. m = m1 +\<^sub>M m2 \<longrightarrow>
 (THE x1. x1 \<in> carrier M1 \<and>   a \<star>\<^sub>M m +\<^sub>M -\<^sub>M x1 \<in> carrier M2) =
              a \<star>\<^sub>M1 (THE x1. x1 \<in> carrier M1 \<and>  m +\<^sub>M -\<^sub>M x1 \<in> carrier M2)")
 apply blast
 apply (thin_tac "\<exists>m1\<in>carrier M1. \<exists>m2\<in>carrier M2. m =  m1 +\<^sub>M m2")
 apply (rule ballI)+ apply (rule impI) apply simp
 apply (subgoal_tac "m1 \<in> carrier M") apply (subgoal_tac "m2 \<in> carrier M")
 apply (simp add:sprod_distrib2)
 apply (thin_tac "m =  m1 +\<^sub>M m2")
 apply (subgoal_tac "(THE x1. x1 \<in> carrier M1 \<and> a \<star>\<^sub>M m1 +\<^sub>M  (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) = a \<star>\<^sub>M m1")
 apply (subgoal_tac "(THE x1. x1 \<in> carrier M1 \<and>   m1 +\<^sub>M m2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) = m1")
 apply simp
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and> a \<star>\<^sub>M m1 +\<^sub>M  (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) = a \<star>\<^sub>M m1")
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and> m1 +\<^sub>M m2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) = m1")
 apply (simp add:ds2_def msubmodule_def [of "R" "M1" "M"]) apply (erule conjE)+
 apply (frule_tac m = m1 and f = "miota R M1 M" and a = a in mHom_lin [of "R" "M1" "M"], assumption+) apply (simp add:msubmodule_def)
 apply assumption
 apply (frule_tac a = a and m = m1 in sprod_mem [of "R" "M1"], assumption+)
 apply (simp add:miota_def)
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and> a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) = a \<star>\<^sub>M m1")
 apply (subgoal_tac "(THE x1. x1 \<in> carrier M1 \<and> m1 +\<^sub>M m2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1 \<and> m1 +\<^sub>M m2 +\<^sub>M -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and> m1 +\<^sub>M m2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2")
 apply (erule conjE)+
 apply (rule_tac x = "m1 +\<^sub>M m2" and ?x1.0 = "THE x1. x1 \<in> carrier M1 \<and> m1 +\<^sub>M m2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2" and ?y1.0 = m1 in mprojTr2 [of "R" "M1" "M2" "M"], assumption+)
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and> m1 +\<^sub>M m2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1")
 apply (thin_tac "m1 +\<^sub>M m2 +\<^sub>M -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and> m1 +\<^sub>M m2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2")
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (frule_tac x = m1 in ag_mOp_closed[of "M"], assumption+)
 apply (simp add:ag_pOp_assoc)
 apply (subst ag_pOp_commute, assumption+)
 apply (simp add:ag_pOp_closed) apply (simp add:ag_pOp_assoc)
 apply (simp add:ag_l_inv1) apply (simp add:ag_r_zero)
 apply (rule theI')
 apply (simp add:mprojTr1)
 apply (subgoal_tac "(THE x1. x1 \<in> carrier M1 \<and> a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1 \<and> a \<star>\<^sub>M m1 +\<^sub>M  (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and> a \<star>\<^sub>M m1 +\<^sub>M  a \<star>\<^sub>M m2 +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2")
 apply (erule conjE)+
 apply (rule_tac x = "a \<star>\<^sub>M m1 +\<^sub>M  a \<star>\<^sub>M m2" and ?x1.0 = "THE x1. x1 \<in> carrier M1 \<and> a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2" and ?y1.0 = "a \<star>\<^sub>M m1" in mprojTr2 [of "R" "M1" "M2" "M"], assumption+)
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and> a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1")
 apply (thin_tac "a \<star>\<^sub>M m1 +\<^sub>M  a \<star>\<^sub>M m2 +\<^sub>M -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and>
 a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2")
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (rule ag_pOp_closed, assumption+)
 apply (simp add:sprod_mem) apply (simp add:sprod_mem) apply assumption+
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and> a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1")
 apply (thin_tac "a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and>
 a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M2")
 apply (simp add:ds2_def) apply (erule conjE)+ apply (simp add:msubmodule_def [of "R" "M" "M1"]) apply (erule conjE)
 apply (frule_tac m = m1 and a = a in mHom_lin [of "R" "M1" "M" _ "miota R M1 M"], assumption+)
 apply (frule_tac a = a and m = m1 in sprod_mem[of "R" "M1"], assumption+)
 apply (simp add:miota_def)
 apply (thin_tac "(THE x1. x1 \<in> carrier M1 \<and> a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2) \<in> carrier M1")
 apply (thin_tac "a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M  -\<^sub>M (THE x1. x1 \<in> carrier M1 \<and>
 a \<star>\<^sub>M m1 +\<^sub>M (a \<star>\<^sub>M m2) +\<^sub>M -\<^sub>M x1 \<in> carrier M2)  \<in> carrier M2")
 apply (frule_tac a = a and m = m1 in sprod_mem[of "R" "M"], assumption+)
 apply (frule_tac a = a and m = m2 in sprod_mem[of "R" "M"], assumption+)
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (frule_tac x = "a \<star>\<^sub>M m1" in ag_mOp_closed, assumption+)
 apply (simp add:ag_pOp_assoc)
 apply (frule_tac x = "a \<star>\<^sub>M m2" and y = "-\<^sub>M (a \<star>\<^sub>M m1)" in ag_pOp_commute [of "M"], assumption+) apply simp apply (thin_tac "a \<star>\<^sub>M m2 +\<^sub>M (-\<^sub>M  (a \<star>\<^sub>M m1)) =  -\<^sub>M  (a \<star>\<^sub>M m1) +\<^sub>M  (a \<star>\<^sub>M m2)")
 apply (simp add:ag_pOp_assoc [THEN sym])
 apply (simp add:ag_r_inv1) apply (simp add:ag_l_zero)
 apply (simp add:ds2_def) apply (erule conjE)+ apply (simp add:msubmodule_def [of "R" "M" "M2"]) apply (erule conjE)+
 apply (frule_tac m = m2 and a = a in mHom_lin [of "R" "M2" "M" _ "miota R M2 M"], assumption+)
 apply (frule_tac a = a and m = m2 in sprod_mem[of "R" "M2"], assumption+)
 apply (simp add:miota_def)
 apply (rule theI')
 apply (rule mprojTr1, assumption+)
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (rule ag_pOp_closed, assumption+)
 apply (simp add:sprod_mem)  apply (simp add:sprod_mem)
apply (simp add:ds2_def msubmodule_def) apply (erule conjE)+
 apply (simp add:subsetD)
apply (simp add:ds2_def msubmodule_def) apply (erule conjE)+
 apply (simp add:subsetD)
done

lemma mproj2:"\<lbrakk>ring R; R module M1; R module M2; R module M; M1 \<Oplus>\<^sub>R\<^sub>,\<^sub>M M2\<rbrakk>
    \<Longrightarrow> mproj2 R M1 M2 M \<in> mHom R M M2"
apply (subgoal_tac "M2 \<Oplus>\<^sub>R\<^sub>,\<^sub>M M1")
 apply (simp add:mproj2_def)
 apply (simp add:mproj)
apply (simp add:ds2_def) apply (erule conjE)+
 apply (simp add:Int_commute)
apply (rule ballI)
 apply (subgoal_tac "\<exists>m1\<in>carrier M1. \<exists>m2\<in>carrier M2. x =  m1 +\<^sub>M m2")
 prefer 2 apply simp
 apply (thin_tac "\<forall>x\<in>carrier M. \<exists>m1\<in>carrier M1. \<exists>m2\<in>carrier M2. x =m1 +\<^sub>M m2")
 apply (subgoal_tac "\<forall>n1\<in>carrier M1. \<forall>n2\<in>carrier M2. x = n1 +\<^sub>M n2 \<longrightarrow>
 (\<exists>m1\<in>carrier M2. \<exists>m2\<in>carrier M1. x =  m1 +\<^sub>M m2)") apply blast
 apply (thin_tac "\<exists>m1\<in>carrier M1. \<exists>m2\<in>carrier M2. x =  m1 +\<^sub>M m2")
 apply (rule ballI)+ apply (rule impI) apply simp
 apply (thin_tac "x =  n1 +\<^sub>M n2") apply (subgoal_tac "n1 +\<^sub>M n2 = n2 +\<^sub>M n1")
 apply simp apply blast
apply (subgoal_tac "n1 \<in> carrier M") apply (subgoal_tac "n2 \<in> carrier M")
 apply (frule_tac module_is_ag [of "R" "M"], assumption+)
 apply (simp add:ag_pOp_commute)
 apply (simp add:msubmodule_def [of "R" "M" "M2"]) apply (erule conjE)+
 apply (simp add:subsetD)
 apply (simp add:msubmodule_def [of "R" "M" "M1"]) apply (erule conjE)+
 apply (simp add:subsetD)
done


 subsection "5-1. existence of the tensor product"

constdefs
 fm_gen_by_prod::"[('r, 'm) RingType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme] \<Rightarrow> bool"  ("(4FM\<^sub>_/ _ _ _)" [100,100,101]100)
 "FM\<^sub>R P M N == R module P \<and> free_generator R P (M \<times>\<^sub>c N)"

lemma free_gen_gen:"\<lbrakk>ring R;  FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> generator R P (M \<times>\<^sub>c N)"
apply (simp add:fm_gen_by_prod_def)
apply (erule conjE)
apply (simp add:free_generator_def)
done

lemma free_gen_mem:"\<lbrakk>ring R; FM\<^sub>R P M N; a \<in> (M \<times>\<^sub>c N)\<rbrakk> \<Longrightarrow>  a \<in> carrier P"
apply (simp add:fm_gen_by_prod_def)
 apply (erule conjE)
 apply (simp add:free_generator_def) apply (erule conjE)+
 apply (simp add:generator_def)
 apply (erule conjE)+
 apply (simp add:subsetD)
done

lemma mHom_lin_eSumTr:"\<lbrakk>ring R; R module M; R module N; t \<in> mHom R M N\<rbrakk> \<Longrightarrow>
 f \<in> Nset n \<rightarrow> carrier M  \<longrightarrow> t (eSum M f n) = eSum N (cmp t f) n"
apply (induct_tac n)
 apply (rule impI) apply (simp add:cmp_def)
apply (rule impI)
 apply simp
 apply (frule_tac func_pre) apply simp
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (frule_tac n = n and i = n in eSum_mem [of "M" "f"], assumption+)
 apply (simp add:Nset_def)
 apply (subgoal_tac "Suc n \<in> Nset (Suc n)")
 apply (frule_tac f = f and A = "Nset (Suc n)" and B = "carrier M" and x = "Suc n" in funcset_mem, assumption+)
 apply (simp add:mHom_add cmp_def)
 apply (simp add:Nset_def)
done

lemma mHom_lin_eSum:"\<lbrakk>ring R; R module M; R module N; t \<in> mHom R M N\<rbrakk> \<Longrightarrow>
 f \<in> Nset n \<rightarrow> carrier M  \<longrightarrow> t (eSum M f n) = eSum N (cmp t f) n"
apply (simp add:mHom_lin_eSumTr)
done

lemma module_over_zeroring:"\<lbrakk> zeroring R; R module M\<rbrakk> \<Longrightarrow>  carrier M = {0\<^sub>M}"
apply (simp add:zeroring_def) apply (erule conjE)
apply (rule equalityI)
 apply (rule subsetI)
 apply (frule_tac sprod_one [of "R" "M"], assumption+)
 apply (frule_tac ring_one[of "R"]) apply simp
 apply (simp add:sprod_0_m)
apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (simp add:ag_inc_zero)
done

lemma submodule_over_zeroring:"\<lbrakk>zeroring R; R module M; submodule R M N\<rbrakk> \<Longrightarrow>
                                   N = {0\<^sub>M}"
apply (rule equalityI)
 apply (rule subsetI)
 apply (simp add:submodule_def) apply (erule conjE)+
 apply (thin_tac "\<forall>a\<in>carrier R. \<forall>m\<in>N.  a \<star>\<^sub>M m \<in> N")
 apply (frule module_over_zeroring [of "R" "M"], assumption+)
 apply simp
 apply (frule_tac A = N and B = "{0\<^sub>M}" and c = x in subsetD, assumption+)
 apply simp
apply (simp add:zeroring_def) apply (erule conjE)+
apply (frule submodule_inc_0 [of "R" "M" "N"], assumption+)
done

constdefs
 Least_submodule::"[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme,
 'a set] \<Rightarrow> 'a set"
         ("(3LSM\<^sub>_/ _/ _)" [100,100,101]100)
 "LSM\<^sub>R M T == \<Inter> {N. submodule R M N \<and> T \<subseteq> N}"

lemma LSM_mem:"\<lbrakk>ring R; R module M; T \<subseteq> carrier M; t \<in> T\<rbrakk> \<Longrightarrow> t \<in> (LSM\<^sub>R M T)"
apply (simp add:Least_submodule_def) apply (rule allI) apply (rule impI)
apply (erule conjE)
apply (simp add:subsetD)
done

lemma LSM_sub_T:"\<lbrakk>ring R; R module M; T \<subseteq> carrier M\<rbrakk> \<Longrightarrow> T \<subseteq> (LSM\<^sub>R M T)"
apply (rule subsetI)
apply (simp add:LSM_mem)
done

lemma submodule_Least_submodule:"\<lbrakk> ring R; R module M; T \<subseteq> carrier M \<rbrakk> \<Longrightarrow>
 submodule R M (LSM\<^sub>R M T)"
apply (subgoal_tac "Least_submodule R M T \<subseteq> carrier M")
 prefer 2
 apply (frule submodule_whole [of "R" "M"], assumption+)
 apply (subgoal_tac "(carrier M) \<in> {N. submodule R M N \<and> T \<subseteq> N}")
 prefer 2 apply simp
 apply (subst Least_submodule_def)
 apply blast
apply (simp add:submodule_def)
apply (rule conjI)
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (rule asubg_test, assumption+)
 apply (simp add:Least_submodule_def)
 apply (subgoal_tac "0\<^sub>M \<in> \<Inter>{N. submodule R M N \<and> T \<subseteq> N}")
 apply blast
 apply (simp add:Int_def)
 apply (rule allI) apply (rule impI) apply (erule conjE)
 apply (simp add:submodule_inc_0)
 apply (rule ballI)+
 apply (simp add:Least_submodule_def)
 apply (rule allI) apply (rule impI) apply (erule conjE)
 apply (rule submodule_pOp_closed, assumption+)
 apply simp
 apply (rule submodule_mOp_closed, assumption+)
 apply simp
apply (rule ballI)+
 apply (simp add:Least_submodule_def)
 apply (rule allI) apply (rule impI) apply (erule conjE)
 apply (rule submodule_sprod_closed, assumption+)
 apply simp
done

lemma linear_comb_memTr:"\<lbrakk>ring R; R module M; submodule R M N; T \<subseteq> N\<rbrakk> \<Longrightarrow>
\<forall>f s. f \<in> Nset n \<rightarrow> T \<and> s \<in> Nset n \<rightarrow> carrier R \<longrightarrow> linear_combination R M n s f \<in> N"
apply (induct_tac n)
 apply (rule allI)+ apply (rule impI) apply (erule conjE)+
 apply (simp add:linear_combination_def) apply (subgoal_tac "0 \<in> Nset 0")
 apply (rule submodule_sprod_closed, assumption+)
 apply (simp add:funcset_mem) apply (simp add:funcset_mem subsetD)
 apply (simp add:Nset_def)
apply (rule allI)+ apply (rule impI) apply (erule conjE)
 apply (frule_tac f = f and n = n and A = T in func_pre)
 apply (frule_tac f = s and n = n and A = "carrier R" in func_pre)
 apply (subgoal_tac "linear_combination R M n s f \<in> N") prefer 2 apply simp
 apply (thin_tac "\<forall>f s. f \<in> Nset n \<rightarrow> T \<and> s \<in> Nset n \<rightarrow> carrier R \<longrightarrow>
                linear_combination R M n s f \<in> N")
 apply (simp add:linear_combination_def)
 apply (rule submodule_pOp_closed, assumption+)
 apply (subgoal_tac "Suc n \<in> Nset (Suc n)")
 apply (rule submodule_sprod_closed, assumption+)
 apply (simp add:funcset_mem)  apply (simp add:funcset_mem subsetD)
apply (simp add:Nset_def)
done

lemma linear_comb_mem:"\<lbrakk>ring R; R module M; submodule R M N; T \<subseteq> N; f \<in> Nset n \<rightarrow> T; s \<in> Nset n \<rightarrow> carrier R\<rbrakk> \<Longrightarrow> linear_combination R M n s f \<in> N"
apply (simp add:linear_comb_memTr)
done

lemma LSM_eq_linear_span:"\<lbrakk>ring R; R module M; T \<subseteq> carrier M\<rbrakk> \<Longrightarrow> (LSM\<^sub>R M T) = linear_span R M (carrier R) T"
apply (rule equalityI)
apply (frule_tac R = R and M = M and H = T in elem_linear_span1, assumption+)
 apply (frule_tac R = R and M = M and A = "carrier R" and H = T in linear_span_subModule, assumption+) apply (simp add:whole_ideal) apply assumption
 apply (subst  Least_submodule_def)
 apply (rule subsetI) apply simp
 apply (subst linear_span_def) apply (case_tac "T = {}") apply simp
 apply (subst Least_submodule_def) apply simp
 apply (rule allI) apply (rule impI)
 apply (simp add:submodule_inc_0)
 apply simp
 apply (rule subsetI) apply simp
 apply (subgoal_tac "\<forall>n. \<forall>f\<in>Nset n \<rightarrow> T. \<forall>s\<in>Nset n \<rightarrow> carrier R. x = linear_combination R M n s f \<longrightarrow> x \<in> LSM\<^sub>R M T") apply blast
 apply (thin_tac "\<exists>n. \<exists>f\<in>Nset n \<rightarrow> T. \<exists>s\<in>Nset n \<rightarrow> carrier R.
                                   x = linear_combination R M n s f")
 apply (rule allI) apply (rule ballI)+ apply (rule impI)
apply simp
 apply (rule_tac R = R and M = M and N = "LSM\<^sub>R M T" and T = T and f = f and s = s in linear_comb_mem, assumption+)
 apply (simp add:submodule_Least_submodule)
 apply (simp add:LSM_sub_T) apply assumption+
done

lemma LSM_sub_ker:"\<lbrakk>ring R; R module M; R module N; T \<subseteq> carrier M; f \<in> mHom R M N; T \<subseteq> ker\<^sub>M\<^sub>,\<^sub>N f\<rbrakk> \<Longrightarrow> LSM\<^sub>R M T \<subseteq> ker\<^sub>M\<^sub>,\<^sub>N f"
apply (rule subsetI)
apply (frule_tac R = R and M = M and T = T in LSM_eq_linear_span, assumption+)
 apply simp
 apply (thin_tac "LSM\<^sub>R M T = linear_span R M (carrier R) T")
 apply (simp add:linear_span_def)
 apply (case_tac "T = {}") apply simp
 apply (simp add:ker_def)
 apply (simp add:module_inc_zero)
 apply (simp add:mHom_0) apply simp
 apply (subgoal_tac "\<forall>m. \<forall>g\<in>Nset m \<rightarrow> T. \<forall>t\<in>Nset m \<rightarrow> carrier R.
 x = linear_combination R M m t g \<longrightarrow> x \<in> ker\<^sub>M\<^sub>,\<^sub>N f") apply blast
 apply (thin_tac "\<exists>n. \<exists>f\<in>Nset n \<rightarrow> T. \<exists>s\<in>Nset n \<rightarrow> carrier R.
                                        x = linear_combination R M n s f")
 apply (rule allI) apply (rule ballI)+ apply (rule impI)
 apply (subst ker_def) apply simp
 apply (frule whole_ideal [of "R"])
 apply (frule_tac R = R and M = M and A = "carrier R" and H = T and s = t and n = m and m = g in linear_combination_mem, assumption+) apply simp
 apply (simp add:linmap_im_lincomb) apply (subst linear_combination_def)
 apply (rule eSum_zero, assumption+)
apply (rule univar_func_test)
 apply (rule ballI) apply simp
 apply (frule_tac f = t and A = "Nset m" and B = "carrier R" and x = xa in
                         funcset_mem, assumption+)
 apply (subgoal_tac "cmp f g xa = 0\<^sub>N") apply simp
 apply (rule_tac R = R and M = N and a = "t xa" in sprod_a_0, assumption+)
apply (simp add:cmp_def) apply (frule_tac f = g and A = "Nset m" and B = T and x = xa in funcset_mem, assumption+)
 apply (frule_tac A = T and B = "ker\<^sub>M\<^sub>,\<^sub>N f" and c = "g xa" in subsetD, assumption+)
 apply (simp add:ker_def)
done

(* in the following costdefs, MN is the free module generated by  M \<times>\<^sub>c N *)
constdefs
tensor_relations1::"[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme] \<Rightarrow> ('a * 'b) set"
       ("(4TR1/ _/ _/ _/ _)" [100,100,100,101]100)
 "TR1 R M N MN == {x. \<exists>m1\<in>carrier M. \<exists>m2\<in>carrier M. \<exists>n\<in>carrier N.
  x = (m1 +\<^sub>M m2, n) +\<^sub>MN (-\<^sub>MN ((m1, n) +\<^sub>MN (m2, n)))}"

tensor_relations2::"[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme] \<Rightarrow> ('a * 'b) set"
       ("(4TR2/ _/ _/ _/ _)" [100,100,100, 101]100)
 "TR2 R M N MN == {x. \<exists>m\<in>carrier M. \<exists>n1\<in>carrier N. \<exists>n2\<in>carrier N.
  x = (m, n1 +\<^sub>N n2) +\<^sub>MN (-\<^sub>MN ((m, n1) +\<^sub>MN (m, n2)))}"
constdefs
 tensor_relations3::"[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme] \<Rightarrow> ('a * 'b ) set"
       ("(4TR3/ _/ _/ _/ _)" [100,100,100,101]100)
 "TR3 R M N P == {x. \<exists>m\<in>carrier M. \<exists>n\<in>carrier N. \<exists> a\<in>carrier R.
  x = (a \<star>\<^sub>M m, n) +\<^sub>P (-\<^sub>P (a \<star>\<^sub>P (m, n)))}"
constdefs
 tensor_relations4::"[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme] \<Rightarrow> ('a * 'b) set"
       ("(4TR4/ _/ _/ _/ _)" [100,100,100,101]100)
 "TR4 R M N MN == {x. \<exists>m\<in>carrier M. \<exists>n\<in>carrier N. \<exists> a\<in>carrier R.
  x = (m, a \<star>\<^sub>N n) +\<^sub>MN (-\<^sub>MN (a \<star>\<^sub>MN(m, n)))}"

 tensor_relations::"[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme] \<Rightarrow> ('a * 'b) set"
       ("(4TR\<^sub>_ _/ _/ _)" [100,100,101]100)

 "TR\<^sub>R M N MN == LSM\<^sub>R MN ((TR1 R M N MN) \<union> (TR2 R M N MN) \<union>
 (TR3 R M N MN) \<union> (TR4 R M N MN))"

constdefs
 tensor_product::"[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme] \<Rightarrow> (('a * 'b) set, 'r) ModuleType"
 "tensor_product R M N MN == MN /\<^sub>m (TR\<^sub>R M N MN)"

syntax
 "@TENSORPROD"::"[('a, 'r, 'm1) ModuleType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme, ('r, 'm) RingType_scheme, ('b, 'r, 'm1) ModuleType_scheme] \<Rightarrow> (('a * 'b) set, 'r) ModuleType"
  ("(4_/ \<^sub>_\<Otimes>\<^sub>_/ _)" [92,92,92,93]92)

translations
 "M \<^sub>P\<Otimes>\<^sub>R N" == "tensor_product R M N P"

lemma cartesianTr:"\<lbrakk>ring R; R module M; R module N; x \<in> M \<times>\<^sub>c N\<rbrakk> \<Longrightarrow> \<exists>m n. m\<in>carrier M \<and> n \<in> carrier N \<and> x = (m, n)"
apply (simp add: prod_carr_def)
apply auto
done

lemma free_module_mem:"\<lbrakk>ring R; R module M; R module N; m \<in> carrier M; n \<in> carrier N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow>  (m, n) \<in> carrier P"
 apply (rule free_gen_mem [of "R" "P" "M" "N"], assumption+)
 apply (simp add:prod_carr_def)
done

lemma TR1_sub_carr:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> (TR1 R M N P) \<subseteq> carrier P"
apply (simp add:fm_gen_by_prod_def)
apply (erule conjE)
 apply (rule subsetI)
 apply (simp add:tensor_relations1_def)
 apply (subgoal_tac "\<forall>m1\<in>carrier M. \<forall>m2\<in>carrier M. \<forall>n\<in>carrier N.
   x =  ( m1 +\<^sub>M m2, n) +\<^sub>P ( -\<^sub>P ((m1, n) +\<^sub>P (m2, n))) \<longrightarrow> x \<in> carrier P")
 apply blast
 apply (thin_tac "\<exists>m1\<in>carrier M. \<exists>m2\<in>carrier M. \<exists>n\<in>carrier N.
                    x =  ( m1 +\<^sub>M m2, n) +\<^sub>P ( -\<^sub>P ((m1, n) +\<^sub>P (m2, n)))")
 apply (rule ballI)+ apply (rule impI)
 apply (frule module_is_ag [of "R" "P"], assumption+) apply simp
 apply (rule ag_pOp_closed, assumption)
 apply (rule free_module_mem, assumption+)
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (rule ag_pOp_closed [of "M"], assumption+)
 apply (simp add:fm_gen_by_prod_def)
apply (rule ag_mOp_closed[of "P"], assumption+)
 apply (rule ag_pOp_closed [of "P"], assumption+)
 apply (rule free_module_mem, assumption+)
 apply (simp add:fm_gen_by_prod_def)
 apply (rule free_module_mem, assumption+)
 apply (simp add:fm_gen_by_prod_def)
done

lemma TR2_sub_carr:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> (TR2 R M N P) \<subseteq> carrier P"
apply (simp add:fm_gen_by_prod_def)
apply (erule conjE)
 apply (rule subsetI)
 apply (simp add:tensor_relations2_def)
 apply (subgoal_tac "\<forall>m\<in>carrier M. \<forall>n1\<in>carrier N. \<forall>n2\<in>carrier N.
   x =  ( m, n1 +\<^sub>N n2) +\<^sub>P -\<^sub>P ((m, n1) +\<^sub>P (m, n2)) \<longrightarrow> x \<in> carrier P")
 apply blast
 apply (thin_tac "\<exists>m\<in>carrier M. \<exists>n1\<in>carrier N. \<exists>n2\<in>carrier N.
                    x =  (m, n1 +\<^sub>N n2) +\<^sub>P  -\<^sub>P ((m, n1) +\<^sub>P (m, n2))")
 apply (rule ballI)+ apply (rule impI)
 apply (frule module_is_ag [of "R" "P"], assumption+) apply simp
 apply (rule ag_pOp_closed, assumption)
 apply (rule free_module_mem, assumption+)
 apply (frule module_is_ag [of "R" "N"], assumption+)
 apply (rule ag_pOp_closed [of "N"], assumption+)
 apply (simp add:fm_gen_by_prod_def)
apply (rule ag_mOp_closed [of "P"], assumption+)
 apply (rule ag_pOp_closed [of "P"], assumption+)
 apply (rule free_module_mem, assumption+)
 apply (simp add:fm_gen_by_prod_def)
 apply (rule free_module_mem, assumption+)
 apply (simp add:fm_gen_by_prod_def)
done

lemma TR3_sub_carr:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> (TR3 R M N P) \<subseteq> carrier P"
apply (simp add:fm_gen_by_prod_def)
apply (erule conjE)
 apply (rule subsetI)
 apply (simp add:tensor_relations3_def)
 apply (subgoal_tac "\<forall>m\<in>carrier M. \<forall>n\<in>carrier N. \<forall>a\<in>carrier R.
   x = (a \<star>\<^sub>M m, n) +\<^sub>P -\<^sub>P  (a \<star>\<^sub>P (m, n)) \<longrightarrow> x \<in> carrier P")
 apply blast
 apply (thin_tac "\<exists>m\<in>carrier M. \<exists>n\<in>carrier N. \<exists>a\<in>carrier R.
                    x = (a \<star>\<^sub>M m, n) +\<^sub>P -\<^sub>P  (a \<star>\<^sub>P (m, n))")
 apply (rule ballI)+ apply (rule impI)
 apply (frule module_is_ag [of "R" "P"], assumption+) apply simp
 apply (rule ag_pOp_closed, assumption)
 apply (rule free_module_mem, assumption+)
 apply (simp add:sprod_mem) apply assumption
 apply (simp add:fm_gen_by_prod_def)
 apply (rule ag_mOp_closed[of "P"], assumption+)
 apply (rule sprod_mem, assumption+)
 apply (rule free_module_mem, assumption+)
 apply (simp add:fm_gen_by_prod_def)
done

lemma TR4_sub_carr:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> (TR4 R M N P) \<subseteq> carrier P"
apply (simp add:fm_gen_by_prod_def)
apply (erule conjE)
 apply (rule subsetI)
 apply (simp add:tensor_relations4_def)
 apply (subgoal_tac "\<forall>m\<in>carrier M. \<forall>n\<in>carrier N. \<forall>a\<in>carrier R.
   x = (m, a \<star>\<^sub>N n) +\<^sub>P -\<^sub>P  (a \<star>\<^sub>P (m, n)) \<longrightarrow> x \<in> carrier P")
 apply blast
 apply (thin_tac "\<exists>m\<in>carrier M. \<exists>n\<in>carrier N. \<exists>a\<in>carrier R.
                    x = (m, a \<star>\<^sub>N n) +\<^sub>P -\<^sub>P  (a \<star>\<^sub>P (m, n))")
 apply (rule ballI)+ apply (rule impI)
 apply (frule module_is_ag [of "R" "P"], assumption+) apply simp
 apply (rule ag_pOp_closed, assumption)
 apply (rule free_module_mem, assumption+)
 apply (rule sprod_mem, assumption+)
 apply (simp add:fm_gen_by_prod_def)
 apply (rule ag_mOp_closed[of "P"], assumption+)
 apply (rule sprod_mem, assumption+)
 apply (rule free_module_mem, assumption+)
 apply (simp add:fm_gen_by_prod_def)
done

lemma TR_sub_carr:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> (TR1 R M N P) \<union> (TR2 R M N P) \<union> (TR3 R M N P) \<union> (TR4 R M N P) \<subseteq> carrier P"
apply (rule subsetI)
 apply (case_tac "x \<in> TR1 R M N P") apply simp
 apply (frule TR1_sub_carr [of "R" "M" "N" "P"], assumption+)
 apply (simp add:subsetD)
 apply (case_tac "x \<in> TR2 R M N P") apply simp
 apply (frule TR2_sub_carr [of "R" "M" "N" "P"], assumption+)
 apply (simp add:subsetD)
 apply (case_tac "x \<in> TR3 R M N P") apply simp
 apply (frule TR3_sub_carr [of "R" "M" "N" "P"], assumption+)
 apply (simp add:subsetD)  apply simp
 apply (frule TR4_sub_carr [of "R" "M" "N" "P"], assumption+)
apply (simp add:subsetD)
done


lemma TR_submodule:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> submodule R P (TR\<^sub>R M N P)"
apply (simp add:tensor_relations_def)
 apply (rule submodule_Least_submodule[of "R" "P" _], assumption+)
 apply (simp add:fm_gen_by_prod_def)
 apply (simp add:TR_sub_carr del:Un_subset_iff)
done

lemma TR_cont_TR1234:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow>
  TR1 R M N P \<union> TR2 R M N P \<union> TR3 R M N P \<union> TR4 R M N P \<subseteq> TR\<^sub>R M N P"
apply (simp add:tensor_relations_def del:Un_subset_iff)
 apply (frule LSM_sub_T [of "R" "P" "TR1 R M N P \<union> TR2 R M N P \<union> TR3 R M N P \<union> TR4 R M N P"])
 apply (simp add:fm_gen_by_prod_def)
 apply (simp add:TR_sub_carr del:Un_subset_iff)
 apply assumption
done

lemma TR1_mem:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N; m1 \<in> carrier M;
m2 \<in> carrier M; n \<in> carrier N \<rbrakk> \<Longrightarrow> (m1 +\<^sub>M m2, n) +\<^sub>P -\<^sub>P ((m1, n) +\<^sub>P (m2, n)) \<in> TR\<^sub>R M N P"
apply (subgoal_tac "(m1 +\<^sub>M m2, n) +\<^sub>P -\<^sub>P ((m1, n) +\<^sub>P (m2, n)) \<in> TR1 R M N P")
prefer 2
apply (simp add:tensor_relations1_def)
apply blast
apply (frule TR_cont_TR1234 [of "R" "M" "N" "P"], assumption+)
apply (simp add:subsetD del:Un_subset_iff)
done

lemma TR2_mem:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N; m \<in> carrier M;
n1 \<in> carrier N; n2 \<in> carrier N \<rbrakk> \<Longrightarrow> (m, n1 +\<^sub>N n2) +\<^sub>P -\<^sub>P ((m, n1) +\<^sub>P (m, n2)) \<in> TR\<^sub>R M N P"
apply (subgoal_tac "(m, n1 +\<^sub>N n2) +\<^sub>P -\<^sub>P ((m, n1) +\<^sub>P (m, n2)) \<in> TR2 R M N P")
prefer 2
apply (simp add:tensor_relations2_def)
apply blast
apply (frule TR_cont_TR1234 [of "R" "M" "N" "P"], assumption+)
apply (simp add:subsetD del:Un_subset_iff)
done

lemma TR3_mem:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N; m \<in> carrier M;
n \<in> carrier N; a \<in> carrier R\<rbrakk> \<Longrightarrow> (a \<star>\<^sub>M m, n) +\<^sub>P -\<^sub>P (a \<star>\<^sub>P (m, n)) \<in> TR\<^sub>R M N P"
apply (subgoal_tac "(a \<star>\<^sub>M m, n) +\<^sub>P -\<^sub>P (a \<star>\<^sub>P (m, n)) \<in> TR3 R M N P")
prefer 2
apply (simp add:tensor_relations3_def)
apply blast
apply (frule TR_cont_TR1234 [of "R" "M" "N" "P"], assumption+)
apply (simp add:subsetD del:Un_subset_iff)+
done

lemma TR4_mem:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N; m \<in> carrier M;
n \<in> carrier N; a \<in> carrier R\<rbrakk> \<Longrightarrow> (m, a \<star>\<^sub>N n) +\<^sub>P -\<^sub>P (a \<star>\<^sub>P (m, n)) \<in> TR\<^sub>R M N P"
apply (subgoal_tac "(m, a \<star>\<^sub>N n) +\<^sub>P -\<^sub>P (a \<star>\<^sub>P (m, n)) \<in> TR4 R M N P")
prefer 2
apply (simp add:tensor_relations4_def)
apply blast
apply (frule TR_cont_TR1234 [of "R" "M" "N" "P"], assumption+)
apply (simp add:subsetD del:Un_subset_iff)
done


lemma tensor_product_module:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow>  R module (tensor_product R M N P)"
apply (simp add:fm_gen_by_prod_def) apply (erule conjE)
apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
 apply (simp add:fm_gen_by_prod_def)
 apply (simp add:tensor_product_def)
 apply (simp add:qmodule_module [of "R" "P" "TR\<^sub>R M N P"])
done

lemma tau_mpj_bilin1:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N;
 x1 \<in> carrier M; x2 \<in> carrier M; y \<in> carrier N\<rbrakk>  \<Longrightarrow> (mpj P (TR\<^sub>R M N P)) ( x1 +\<^sub>M x2, y) = (mpj P (TR\<^sub>R M N P)) (x1, y) +\<^sub>(M \<^sub>P\<Otimes>\<^sub>R N) (mpj P (TR\<^sub>R M N P) (x2, y))"
apply (subgoal_tac "R module P") prefer 2 apply (simp add:fm_gen_by_prod_def)
apply (subgoal_tac "(x1 +\<^sub>M x2, y) +\<^sub>P (-\<^sub>P ((x1, y) +\<^sub>P (x2, y))) \<in>  ker\<^sub>P\<^sub>,\<^sub>(P /\<^sub>m (TR\<^sub>R M N P)) (mpj P (TR\<^sub>R M N P))")
apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
apply (frule qmodule_module [of "R" "P" "TR\<^sub>R M N P"], assumption+)
apply (frule mpj_mHom [of "R" "P" "TR\<^sub>R M N P"], assumption+)
apply (frule  mHom_eq_ker[of "R" "P" "P /\<^sub>m (TR\<^sub>R M N P)" "mpj P (TR\<^sub>R M N P)" "( x1 +\<^sub>M x2, y)" "(x1, y) +\<^sub>P (x2, y)"], assumption+)
apply (rule free_module_mem, assumption+)
apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (simp add:ag_pOp_closed) apply assumption+
apply (frule module_is_ag [of "R" "P"], assumption+)
 apply (rule ag_pOp_closed) apply assumption+
apply (rule free_module_mem, assumption+)
apply (rule free_module_mem, assumption+)
apply (subgoal_tac "(x1, y) \<in> carrier P")
 prefer 2
 apply (rule free_module_mem, assumption+)
 apply (subgoal_tac "(x2, y) \<in> carrier P")
 prefer 2
 apply (rule free_module_mem, assumption+)
apply (simp add:mHom_add[of "R" "P" "P /\<^sub>m (TR\<^sub>R M N P)" "mpj P (TR\<^sub>R M N P)" "(x1, y)" "(x2, y)"])
 apply (simp add:tensor_product_def)
apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
 apply (simp add:mker_of_mpj)
 apply (thin_tac "submodule R P (TR\<^sub>R M N P)")
 apply (simp add:TR1_mem)
done

lemma tau_mpj_bilin2:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N;
m \<in> carrier M; n1 \<in> carrier N; n2 \<in> carrier N\<rbrakk>  \<Longrightarrow> (mpj P (TR\<^sub>R M N P)) (m, n1 +\<^sub>N n2) = (mpj P (TR\<^sub>R M N P)) (m, n1) +\<^sub>(M \<^sub>P\<Otimes>\<^sub>R N) (mpj P (TR\<^sub>R M N P) (m, n2))"
apply (subgoal_tac "R module P") prefer 2 apply (simp add:fm_gen_by_prod_def)
apply (subgoal_tac "(m, n1 +\<^sub>N n2) +\<^sub>P (-\<^sub>P ((m, n1) +\<^sub>P (m, n2))) \<in>  ker\<^sub>P\<^sub>,\<^sub>(P /\<^sub>m (TR\<^sub>R M N P)) (mpj P (TR\<^sub>R M N P))")
apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
apply (frule qmodule_module [of "R" "P" "TR\<^sub>R M N P"], assumption+)
apply (frule mpj_mHom [of "R" "P" "TR\<^sub>R M N P"], assumption+)
apply (frule  mHom_eq_ker[of "R" "P" "P /\<^sub>m (TR\<^sub>R M N P)" "mpj P (TR\<^sub>R M N P)" "(m, n1 +\<^sub>N n2)" "(m, n1) +\<^sub>P (m, n2)"], assumption+)
apply (rule free_module_mem, assumption+)
apply (frule module_is_ag [of "R" "N"], assumption+)
 apply (simp add:ag_pOp_closed) apply assumption+
apply (frule module_is_ag [of "R" "P"], assumption+)
 apply (rule ag_pOp_closed, assumption+)
apply (rule free_module_mem, assumption+)
apply (rule free_module_mem, assumption+)
apply (subgoal_tac "(m, n1) \<in> carrier P")
 prefer 2
 apply (rule free_module_mem, assumption+)
 apply (subgoal_tac "(m, n2) \<in> carrier P")
 prefer 2
 apply (rule free_module_mem, assumption+)
apply (simp add:mHom_add[of "R" "P" "P /\<^sub>m (TR\<^sub>R M N P)" "mpj P (TR\<^sub>R M N P)" "(m, n1)" "(m, n2)"])
 apply (simp add:tensor_product_def)
apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
 apply (simp add:mker_of_mpj)
 apply (thin_tac "submodule R P (TR\<^sub>R M N P)")
 apply (simp add:TR2_mem)
done

lemma tau_mpj_bilin3:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N;
m \<in> carrier M; n \<in> carrier N; a \<in> carrier R\<rbrakk>  \<Longrightarrow> (mpj P (TR\<^sub>R M N P)) (a \<star>\<^sub>M m, n) = a \<star>\<^sub>(M \<^sub>P\<Otimes>\<^sub>R N) (mpj P (TR\<^sub>R M N P) (m, n))"
apply (subgoal_tac "R module P") prefer 2 apply (simp add:fm_gen_by_prod_def)
apply (subgoal_tac "(a \<star>\<^sub>M m, n) +\<^sub>P -\<^sub>P (a \<star>\<^sub>P (m, n)) \<in>  ker\<^sub>P\<^sub>,\<^sub>(P /\<^sub>m (TR\<^sub>R M N P)) (mpj P (TR\<^sub>R M N P))")
apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
apply (frule qmodule_module [of "R" "P" "TR\<^sub>R M N P"], assumption+)
apply (frule mpj_mHom [of "R" "P" "TR\<^sub>R M N P"], assumption+)
apply (frule  mHom_eq_ker[of "R" "P" "P /\<^sub>m (TR\<^sub>R M N P)" "mpj P (TR\<^sub>R M N P)" "(a \<star>\<^sub>M m, n)" "a \<star>\<^sub>P (m, n)"], assumption+)
apply (rule free_module_mem, assumption+)
 apply (simp add:sprod_mem) apply assumption
 apply (simp add:fm_gen_by_prod_def)
 apply (rule sprod_mem, assumption+)
apply (rule free_module_mem, assumption+) apply simp
 apply (rule mHom_lin, assumption+)
 apply (simp add:tensor_product_module)
 apply (rule free_module_mem, assumption+) apply (simp add:tensor_product_def)
 apply assumption
apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
 apply (simp add:mker_of_mpj)
 apply (simp add:TR3_mem)
done

lemma tau_mpj_bilin4:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N;
m \<in> carrier M; n \<in> carrier N; a \<in> carrier R\<rbrakk>  \<Longrightarrow> (mpj P (TR\<^sub>R M N P)) (m, a \<star>\<^sub>N n) = a \<star>\<^sub>(M \<^sub>P\<Otimes>\<^sub>R N) (mpj P (TR\<^sub>R M N P) (m, n))"
apply (subgoal_tac "R module P") prefer 2 apply (simp add:fm_gen_by_prod_def)
apply (subgoal_tac "(m, a \<star>\<^sub>N n) +\<^sub>P -\<^sub>P (a \<star>\<^sub>P (m, n)) \<in>  ker\<^sub>P\<^sub>,\<^sub>(P /\<^sub>m (TR\<^sub>R M N P)) (mpj P (TR\<^sub>R M N P))")
apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
apply (frule qmodule_module [of "R" "P" "TR\<^sub>R M N P"], assumption+)
apply (frule mpj_mHom [of "R" "P" "TR\<^sub>R M N P"], assumption+)
apply (frule  mHom_eq_ker[of "R" "P" "P /\<^sub>m (TR\<^sub>R M N P)" "mpj P (TR\<^sub>R M N P)" "(m, a \<star>\<^sub>N n)" "a \<star>\<^sub>P (m, n)"], assumption+)
apply (rule free_module_mem, assumption+)
 apply (simp add:sprod_mem) apply assumption
 apply (simp add:fm_gen_by_prod_def)
 apply (rule sprod_mem, assumption+)
apply (rule free_module_mem, assumption+)
 apply (simp add:fm_gen_by_prod_def) apply assumption apply simp
 apply (rule mHom_lin, assumption+)
 apply (simp add:tensor_product_module)
 apply (rule free_module_mem, assumption+) apply (simp add:tensor_product_def)
 apply assumption
apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
 apply (simp add:mker_of_mpj)
 apply (simp add:TR4_mem)
done


constdefs
 tau::"[('r, 'm) RingType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme] \<Rightarrow>
                                            ('a * 'b) \<Rightarrow> ('a * 'b)"
 "tau R M N P == \<lambda>x\<in>(M \<times>\<^sub>c N). x"

lemma tau_func:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow>
   tau R M N P \<in> M \<times>\<^sub>c N \<rightarrow> carrier P"
apply (rule univar_func_test)
 apply (rule ballI)
 apply (frule_tac x = x in cartesianTr [of "R" "M" "N"], assumption+)
 apply (subgoal_tac "\<forall>m n. m \<in> carrier M \<and> n \<in> carrier N \<and> x = (m, n) \<longrightarrow>
          tau R M N P x \<in> carrier P")
 apply blast
 apply (thin_tac "\<exists>m n. m \<in> carrier M \<and> n \<in> carrier N \<and> x = (m, n)")
 apply (rule allI)+ apply (rule impI) apply (erule conjE)+
 apply simp
 apply (simp add:tau_def)
apply (simp add:free_module_mem)
done

lemma tau_mem:"\<lbrakk>ring R; R module M; R module N; m \<in> carrier M; n \<in> carrier N;
FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> tau R M N P (m, n) \<in> carrier P"
apply (frule tau_func [of "R" "M" "N" "P"], assumption+)
apply (rule funcset_mem, assumption+)
apply (simp add:prod_carr_mem)
done

lemma tau_inj0:"\<lbrakk>\<not> zeroring R; ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> inj_on (tau R M N P) (M \<times>\<^sub>c N)"
apply (simp add:inj_on_def) apply (rule ballI)+
 apply (rule impI)
 apply (simp add:tau_def)
done

lemma tau_inj1:"\<lbrakk> zeroring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> inj_on (tau R M N P) (M \<times>\<^sub>c N)"
apply (simp add:inj_on_def)
apply (rule ballI)+ apply (rule impI)
apply (frule module_over_zeroring[of "R" "M"], assumption+)
apply (frule module_over_zeroring[of "R" "N"], assumption+)
apply (simp add:zeroring_def)  apply (erule conjE)
apply (frule_tac x = x in cartesianTr[of "R" "M" "N"], assumption+)
 apply (subgoal_tac "\<forall>m n. m \<in> carrier M \<and> n \<in> carrier N \<and> x = (m, n) \<longrightarrow>
                           x = y")
 apply blast
 apply (thin_tac "\<exists>m n. m \<in> carrier M \<and> n \<in> carrier N \<and> x = (m, n)")
 apply (rule allI)+ apply (rule impI) apply (erule conjE)+
 apply simp
apply (frule_tac x = y in cartesianTr[of "R" "M" "N"], assumption+)
 apply (subgoal_tac "\<forall>m1 n1. m1 \<in> carrier M \<and> n1 \<in> carrier N \<and> y = (m1, n1) \<longrightarrow> (0\<^sub>M, 0\<^sub>N) = y")
 apply blast
 apply (thin_tac "\<exists>m n. m \<in> carrier M \<and> n \<in> carrier N \<and> y = (m, n)")
 apply (rule allI)+ apply (rule impI) apply (erule conjE)+
 apply simp
done

lemma tau_inj:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow> inj_on (tau R M N P) (M \<times>\<^sub>c N)"
apply (case_tac "zeroring R")
 apply (simp add:tau_inj1)
 apply (simp add:tau_inj0)
done

lemma tau_mpj_bilinear:"\<lbrakk> ring R; R module M; R module N; FM\<^sub>R P M N\<rbrakk> \<Longrightarrow>
 bilinear_map R M N (M \<^sub>P\<Otimes>\<^sub>R N) (compose (M \<times>\<^sub>c N) (mpj P (TR\<^sub>R M N P)) (tau R M N P))"
apply (simp add:bilinear_map_def)
apply (rule conjI)
 apply (rule univar_func_test) apply (rule ballI)
 apply (simp add:compose_def)
 apply (simp add:tau_def)
 apply (simp add:tensor_product_def)
 apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
 apply (frule mpj_mHom[of "R" "P" "TR\<^sub>R M N P"])
 apply (simp add:fm_gen_by_prod_def) apply assumption
apply (rule mHom_mem [of "R" "P" "P /\<^sub>m (TR\<^sub>R M N P)" "(mpj P (TR\<^sub>R M N P))"], assumption+)
 apply (simp add:fm_gen_by_prod_def)
 apply (simp add:fm_gen_by_prod_def) apply (erule conjE)+
 apply (simp add:qmodule_module [of "R" "P" "TR\<^sub>R M N P"])
 apply assumption
 apply (simp add:free_gen_mem)
apply (rule conjI)
 apply (rule ballI)+
 apply (simp add:tau_def) apply (simp add:compose_def tau_def)
 apply (simp add:prod_carr_def)
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (simp add:ag_pOp_closed)
 apply (simp add:tau_mpj_bilin1)
apply (rule conjI)
 apply (rule ballI)+
 apply (simp add:tau_def) apply (simp add:compose_def tau_def)
 apply (simp add:prod_carr_def)
 apply (frule module_is_ag [of "R" "N"], assumption+)
 apply (simp add:ag_pOp_closed)
 apply (simp add:tau_mpj_bilin2)
apply (rule ballI)+
 apply (rule conjI)
 apply (simp add:tau_def) apply (simp add:compose_def tau_def)
 apply (simp add:prod_carr_def) apply (simp add:sprod_mem)
 apply (simp add:tau_mpj_bilin3)
 apply (simp add:tau_def) apply (simp add:compose_def tau_def)
 apply (simp add:prod_carr_def) apply (simp add:sprod_mem)
 apply (simp add:tau_mpj_bilin4)
done

constdefs
 tnm::"[('r, 'm) RingType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme] \<Rightarrow> ('a * 'b) \<Rightarrow> ('a * 'b) set"
 "tnm R P M N == compose (M \<times>\<^sub>c N) (mpj P (TR\<^sub>R M N P)) (tau R M N P)"
 (* tensor natural map *)

lemma tnm_bilinear:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N \<rbrakk> \<Longrightarrow>  bilinear_map R M N (M \<^sub>P\<Otimes>\<^sub>R N) (tnm R P M N)"
apply (simp add:tnm_def)
apply (simp add:tau_mpj_bilinear)
done

lemma tnm_mem:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N; m \<in> carrier M; n \<in> carrier N\<rbrakk>  \<Longrightarrow> tnm R P M N (m, n) \<in> carrier (M \<^sub>P\<Otimes>\<^sub>R N)"
apply (simp add:tnm_def)
apply (frule tau_mem [of "R" "M" "N" "m" "n"], assumption+)
 apply (simp add:compose_def) apply (simp add:prod_carr_def)
 apply (simp add:tensor_product_def)
 apply (frule TR_submodule [of "R" "M" "N" "P"], assumption+)
apply (rule mpj_mem[of "R" "P" "TR\<^sub>R M N P" "tau R M N P (m, n)"], assumption+)
 apply (simp add:fm_gen_by_prod_def) apply assumption+
done

constdefs
 tensor_elem::"[('r, 'm) RingType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme] \<Rightarrow> 'a \<Rightarrow>  'b \<Rightarrow> ('a * 'b) set"
 "tensor_elem R P M N m n == tnm R P M N (m, n)"

syntax
 "@TNSELEM"::"['a, ('r, 'm) RingType_scheme, (('a * 'b), 'r, 'm1) ModuleType_scheme, ('a, 'r, 'm1) ModuleType_scheme, ('b, 'r, 'm1) ModuleType_scheme, 'b] \<Rightarrow>
('a * 'b) set" ("(6_ \<^sub>_\<^sub>,\<^sub>_\<otimes>\<^sub>_\<^sub>,\<^sub>_/ _)" [100,100,100,100,100,101]101)

 translations
 "m \<^sub>R\<^sub>,\<^sub>P\<otimes>\<^sub>M\<^sub>,\<^sub>N n" == "tensor_elem R P M N m n"

lemma tensor_univ_propTr:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N; R module Z; bilinear_map R M N Z f\<rbrakk> \<Longrightarrow> \<exists>g. g \<in> mHom R P Z \<and> (compose (M \<times>\<^sub>c N) g (tau R M N P)) = f"
apply (unfold fm_gen_by_prod_def)
 apply (frule conj_1)
 apply (frule conj_2) apply (fold fm_gen_by_prod_def)
 apply (subgoal_tac "f \<in> (M \<times>\<^sub>c N) \<rightarrow> carrier Z")
 prefer 2 apply (simp add:bilinear_map_def)
apply (frule exist_extension_mhom [of "R" "P" "Z" "M \<times>\<^sub>c N" "f"], assumption+)
apply (subgoal_tac "\<forall>g\<in>mHom R P Z. (\<forall>x\<in>M \<times>\<^sub>c N. g x = f x) \<longrightarrow> (\<exists>g. g \<in> mHom R P Z \<and> compose (M \<times>\<^sub>c N) g (tau R M N P) = f)")
apply blast
 apply (thin_tac "\<exists>g\<in>mHom R P Z. \<forall>x\<in>M \<times>\<^sub>c N. g x = f x")
 apply (rule ballI) apply (rule impI)
 apply (rename_tac h)
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) h (tau R M N P) = f")
 apply blast
apply (rule funcset_eq [of _ "M \<times>\<^sub>c N"])
 apply (simp add:compose_def) apply (simp add:bilinear_map_def)
 apply (rule ballI)
 apply (simp add:compose_def tau_def)
done

lemma tensor_univ_propTr1:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N; R module Z; bilinear_map R M N Z f\<rbrakk> \<Longrightarrow> \<exists>!g. g\<in>(mHom R (M \<^sub>P\<Otimes>\<^sub>R N) Z) \<and> (compose (M \<times>\<^sub>c N) g (tnm R P M N)) = f"
apply (simp add:tnm_def)
apply (rule ex_ex1I)
prefer 2
 apply (subgoal_tac "R module P") prefer 2 apply (simp add:fm_gen_by_prod_def)
 apply (frule_tac R = R and M = "P" and H = "TR\<^sub>R M N P" in mpj_surjec, assumption+)
apply (rule TR_submodule [of "R" "M" "N"], assumption+)
 apply (erule conjE)+
 apply (subgoal_tac "P /\<^sub>m (TR\<^sub>R M N P) = M \<^sub>P\<Otimes>\<^sub>R N") apply simp
 apply (simp add:fm_gen_by_prod_def) apply (unfold free_generator_def)
 apply (frule conj_1) apply (fold free_generator_def)
 apply (frule_tac R = R and M = "P" and N = "M \<^sub>P\<Otimes>\<^sub>R N" and f = "mpj P (TR\<^sub>R M N P)" and H = "(M \<times>\<^sub>c N)" in surjec_generator, assumption+)
 apply (rule tensor_product_module, assumption+)
 apply (simp add:fm_gen_by_prod_def)
apply (rotate_tac -2)
 apply (frule sym) apply (thin_tac "P /\<^sub>m (TR\<^sub>R M N P) = M \<^sub>P\<Otimes>\<^sub>R N")
 apply simp
 apply (rule mpj_mHom, assumption+)
apply (rule TR_submodule [of "R" "M" "N"], assumption+)
 apply (simp add:fm_gen_by_prod_def) apply assumption+
apply (rule_tac R = R and M = "M \<^sub>P\<Otimes>\<^sub>R N" and N = Z and H = "mpj P (TR\<^sub>R M N P) ` (M \<times>\<^sub>c N)" and f = g and g = y in gen_mHom_eq, assumption+)
 apply (rule tensor_product_module, assumption+)
 apply (simp add:fm_gen_by_prod_def)
 apply assumption+
 apply (rule ballI)
 apply (simp add:image_def)
 apply (subgoal_tac "\<forall>x\<in>(M \<times>\<^sub>c N). h = (mpj P (TR\<^sub>R M N P)) x \<longrightarrow> g h = y h")
 apply blast
 apply (thin_tac "\<exists>x\<in>M \<times>\<^sub>c N. h = mpj P (TR\<^sub>R M N P) x") apply (rule ballI) apply (rule impI) apply simp
 apply (thin_tac "surjec\<^sub>P\<^sub>,\<^sub>(M \<^sub>P\<Otimes>\<^sub>R N) (mpj P (TR\<^sub>R M N P))")
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (compose (M \<times>\<^sub>c N) (mpj P (TR\<^sub>R M N P)) (tau R M N P)) x = f x") prefer 2 apply simp
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) y (compose (M \<times>\<^sub>c N) (mpj P (TR\<^sub>R M N P)) (tau R M N P)) x = f x") prefer 2 apply simp
 apply (thin_tac " compose (M \<times>\<^sub>c N) g (compose (M \<times>\<^sub>c N) (mpj P (TR\<^sub>R M N P)) (tau R M N P)) =  f")
 apply (thin_tac "compose (M \<times>\<^sub>c N) y (compose (M \<times>\<^sub>c N) (mpj P (TR\<^sub>R M N P)) (tau R M N P)) = f")
 apply (thin_tac "P /\<^sub>m (TR\<^sub>R M N P) = M \<^sub>P\<Otimes>\<^sub>R N")
 apply (thin_tac "generator R (M \<^sub>P\<Otimes>\<^sub>R N) {y. \<exists>x\<in>M \<times>\<^sub>c N. y = mpj P (TR\<^sub>R M N P) x}")
 apply (simp add:compose_def)
 apply (simp add:tau_def) apply (simp add:tensor_product_def)
 apply (frule tensor_univ_propTr[of "R" "M" "N" "P" "Z" "f"], assumption+)
 apply (subgoal_tac "\<forall>g. g \<in> mHom R P Z \<and> compose (M \<times>\<^sub>c N) g (tau R M N P) = f \<longrightarrow> (\<exists>g. g \<in> mHom R (M \<^sub>P\<Otimes>\<^sub>R N) Z \<and> compose (M \<times>\<^sub>c N) g (compose (M \<times>\<^sub>c N) (mpj  P (TR\<^sub>R M N P)) (tau R M N P)) = f)")
 apply blast
 apply (thin_tac "\<exists>g. g \<in> mHom R P Z \<and> compose (M \<times>\<^sub>c N) g (tau R M N P) = f") apply (rule allI) apply (rule impI) apply (erule conjE)+
 apply (subgoal_tac "R module P") prefer 2 apply (simp add:fm_gen_by_prod_def)
apply (frule TR_submodule [of "R" "M" "N"], assumption+)
apply (frule_tac f = g in indmhom1[of "R" "P" "TR\<^sub>R M N P" "Z"], assumption+)
prefer 2
 apply (simp add:tensor_product_def)
 apply (subgoal_tac "\<exists>ga. ga \<in> mHom R (P /\<^sub>m (TR\<^sub>R M N P)) Z \<and> compose (carrier  P) ga (mpj P (TR\<^sub>R M N P)) = g")
 prefer 2 apply (simp add:ex1_implies_ex)
 apply (thin_tac "\<exists>!ga. ga \<in> mHom R (P /\<^sub>m (TR\<^sub>R M N P)) Z \<and>
                 compose (carrier P) ga (mpj P (TR\<^sub>R M N P)) = g")
 apply (rule contrapos_pp, simp+)
 apply (subgoal_tac "\<forall>ga. ga \<in> mHom R (P /\<^sub>m (TR\<^sub>R M N P)) Z \<and> compose (carrier P) ga (mpj P (TR\<^sub>R M N P)) = g \<longrightarrow> False")
 apply blast
 apply (thin_tac "\<exists>ga. ga \<in> mHom R (P /\<^sub>m (TR\<^sub>R M N P)) Z \<and> compose (carrier P) ga (mpj P (TR\<^sub>R M N P)) = g")
 apply (rule allI) apply (rule impI)
 apply (erule conjE)
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) ga (compose (M \<times>\<^sub>c N) (mpj P (TR\<^sub>R M N P)) (tau R M N P)) \<noteq> f")
 prefer 2 apply simp
 apply (thin_tac "\<forall>g. g \<in> mHom R (P /\<^sub>m (TR\<^sub>R M N P)) Z \<longrightarrow> compose (M \<times>\<^sub>c N) g (compose (M \<times>\<^sub>c N) (mpj P (TR\<^sub>R M N P)) (tau R M N P)) \<noteq> f")
apply (subgoal_tac "compose (M \<times>\<^sub>c N) ga (compose (M \<times>\<^sub>c N) (mpj P (TR\<^sub>R M N P)) (tau R M N P)) = f") apply simp
 apply (subgoal_tac "f \<in> M \<times>\<^sub>c N \<rightarrow> carrier Z \<and> f \<in> extensional (M \<times>\<^sub>c N)")
 prefer 2 apply (simp add:bilinear_map_def) apply (erule conjE)
 apply (thin_tac "compose (M \<times>\<^sub>c N) ga (compose (M \<times>\<^sub>c N) (mpj P (TR\<^sub>R M N P)) (tau R M N P)) \<noteq> f")
 apply (rule funcset_eq [of _ "M \<times>\<^sub>c N"])
 apply (simp add:compose_def) apply assumption+
 apply (rule ballI)
 apply (simp add:compose_def) apply (simp add:tau_def)
 apply (subgoal_tac "(\<lambda>x\<in>M \<times>\<^sub>c N. g (if x \<in> M \<times>\<^sub>c N then x else arbitrary)) x = f x") prefer 2 apply simp
 apply (thin_tac "(\<lambda>x\<in>M \<times>\<^sub>c N. g (if x \<in> M \<times>\<^sub>c N then x else arbitrary)) = f")
 apply simp
 apply (frule_tac a = x in free_gen_mem [of "R" "P" "M" "N"], assumption+)
 apply (subgoal_tac "(\<lambda>x\<in>carrier P. ga (mpj P (TR\<^sub>R M N P) x)) x = g x")
 prefer 2 apply simp
 apply (thin_tac "(\<lambda>x\<in>carrier P. ga (mpj P (TR\<^sub>R M N P) x)) = g")
 apply simp
apply (simp add:tensor_relations_def)
 apply (frule_tac f = g in LSM_sub_ker [of "R" "P" "Z" "(TR1 R M N P \<union> TR2 R M N P \<union> TR3 R M N P \<union> TR4 R M N P)"], assumption+)
 apply (simp add:TR_sub_carr del:Un_subset_iff)
 apply assumption
apply (thin_tac " submodule R P (LSM\<^sub>R P (TR1 R M N P \<union> TR2 R M N P \<union> TR3 R M N P \<union> TR4 R M N P))")
prefer 2 apply assumption
 apply (rule subsetI)
 apply (case_tac "x \<in> TR1 R M N P") (** case x \<in> TR1 R M N P **)
 apply (thin_tac "x \<in> TR1 R M N P \<union> TR2 R M N P \<union> TR3 R M N P \<union> TR4 R M N P")  apply (simp add:tensor_relations1_def)
 apply (subgoal_tac "\<forall>m1\<in>carrier M. \<forall>m2\<in>carrier M. \<forall>n\<in>carrier N. x = (m1 +\<^sub>M m2, n) +\<^sub>P -\<^sub>P((m1, n) +\<^sub>P (m2, n)) \<longrightarrow> (x \<in>  ker\<^sub>P\<^sub>,\<^sub>Z g)")
 apply blast
 apply (thin_tac "\<exists>m1\<in>carrier M. \<exists>m2\<in>carrier M. \<exists>n\<in>carrier N. x = (m1 +\<^sub>M m2, n) +\<^sub>P -\<^sub>P((m1, n) +\<^sub>P (m2, n))")
 apply (rule ballI)+ apply (rule impI) apply (simp add:ker_def)
 apply (thin_tac "x = (m1 +\<^sub>M m2, n) +\<^sub>P -\<^sub>P ( (m1, n) +\<^sub>P (m2, n))")
 apply (subgoal_tac "R module P") prefer 2 apply (simp add:fm_gen_by_prod_def)
apply (frule module_is_ag [of "R" "P"], assumption+)
 apply (subgoal_tac "(m1 +\<^sub>M m2, n) \<in> carrier P")
 apply (subgoal_tac "(m1, n) \<in> carrier P")
 apply (subgoal_tac "(m2, n) \<in> carrier P")
 apply (rule conjI)
 apply (rule ag_pOp_closed, assumption+)
 apply (simp add:ag_pOp_closed)
 apply (rule ag_mOp_closed [of "P"], assumption+)
 apply (rule ag_pOp_closed [of "P"], assumption+)
 apply (frule_tac f = g and m = "(m1 +\<^sub>M m2, n)" and n = "-\<^sub>P ((m1, n) +\<^sub>P (m2, n))" in mHom_add[of "R" "P" "Z"], assumption+)
 apply (rule ag_mOp_closed, assumption+)
 apply (rule ag_pOp_closed, assumption+) apply simp
 apply (thin_tac "g (( m1 +\<^sub>M m2, n) +\<^sub>P -\<^sub>P ( (m1, n) +\<^sub>P (m2, n))) =
           g (m1 +\<^sub>M m2, n) +\<^sub>Z (g (-\<^sub>P ( (m1, n) +\<^sub>P (m2, n))))")
 apply (frule_tac m = "(m1, n) +\<^sub>P (m2, n)" and f = g in mHom_inv [of "R" "P" "Z"], assumption+)
 apply (simp add:ag_pOp_closed) apply assumption apply simp
 apply (frule_tac f = g and m = "(m1, n)" and n = "(m2, n)" in mHom_add[of "R" "P" "Z"], assumption+) apply simp apply (thin_tac "g ((m1, n) +\<^sub>P (m2, n)) = g (m1, n) +\<^sub>Z (g (m2, n))")
 apply (thin_tac "g (-\<^sub>P ((m1, n) +\<^sub>P (m2, n)))= -\<^sub>Z (g (m1, n) +\<^sub>Z (g (m2, n)))")
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) (m1 +\<^sub>M m2, n) = f (m1 +\<^sub>M m2, n)")
 prefer 2 apply (simp add:compose_def tau_def)
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) (m1, n) = f (m1, n)")
 prefer 2 apply (simp add:compose_def tau_def)
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) (m2, n) = f (m2, n)")
 prefer 2 apply (simp add:compose_def tau_def)
 apply (thin_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) = f")
 apply (subgoal_tac "(m1 +\<^sub>M m2, n) \<in> M \<times>\<^sub>c N")
 apply (subgoal_tac "(m1, n) \<in> M \<times>\<^sub>c N") apply (subgoal_tac "(m2, n) \<in> M \<times>\<^sub>c N")
 apply (simp add:compose_def tau_def)
 apply (subgoal_tac "f (m1 +\<^sub>M m2, n) = f (m1, n) +\<^sub>Z (f (m2, n))")
 apply (subgoal_tac "f (m1, n) +\<^sub>Z (f (m2, n)) \<in> carrier Z")
 apply (frule module_is_ag [of "R" "Z"], assumption+)
 apply (simp add:ag_r_inv1 [of "Z"])
 apply (frule module_is_ag [of "R" "Z"], assumption+)
 apply (rule ag_pOp_closed, assumption+)
 apply (simp add:bilinear_map_def) apply (frule conj_1)
 apply (simp add:funcset_mem)
 apply (simp add:bilinear_map_def) apply (frule conj_1)
 apply (simp add:funcset_mem)
apply (simp add:bilinear_map_def)
 apply (simp add:prod_carr_def) apply (simp add:prod_carr_def)
  apply (simp add:prod_carr_def)
  apply (frule module_is_ag [of "R" "M"], assumption+)
  apply (simp add:ag_pOp_closed)
 apply (simp add:free_module_mem)
 apply (simp add:free_module_mem)
 apply (rule free_module_mem, assumption+)
 apply (frule module_is_ag [of "R" "M"], assumption+)
 apply (simp add:ag_pOp_closed) apply assumption+
 apply simp  (** first case done **)
 apply (case_tac "x \<in> TR2 R M N P") (** case x \<in> TR2 R M N P **)
 apply (thin_tac "x \<in> TR2 R M N P \<or> x \<in> TR3 R M N P \<or> x \<in> TR4 R M N P")  apply (simp add:tensor_relations2_def)
 apply (subgoal_tac "\<forall>m\<in>carrier M. \<forall>n1\<in>carrier N. \<forall>n2\<in>carrier N. x = (m, n1 +\<^sub>N n2) +\<^sub>P -\<^sub>P((m, n1) +\<^sub>P (m, n2)) \<longrightarrow> (x \<in>  ker\<^sub>P\<^sub>,\<^sub>Z g)")
 apply blast
 apply (thin_tac "\<exists>m\<in>carrier M. \<exists>n1\<in>carrier N. \<exists>n2\<in>carrier N. x = (m, n1 +\<^sub>N n2) +\<^sub>P -\<^sub>P((m, n1) +\<^sub>P (m, n2))")
 apply (rule ballI)+ apply (rule impI) apply (simp add:ker_def)
 apply (thin_tac "x = (m,  n1 +\<^sub>N n2) +\<^sub>P -\<^sub>P ( (m, n1) +\<^sub>P (m, n2))")
 apply (subgoal_tac "R module P") prefer 2 apply (simp add:fm_gen_by_prod_def)
apply (frule module_is_ag [of "R" "P"], assumption+)
 apply (subgoal_tac "(m, n1 +\<^sub>N n2) \<in> carrier P")
 apply (subgoal_tac "(m, n1) \<in> carrier P")
 apply (subgoal_tac "(m, n2) \<in> carrier P")
 apply (rule conjI)
 apply (rule ag_pOp_closed, assumption+)
 apply (simp add:ag_pOp_closed)
 apply (rule ag_mOp_closed [of "P"], assumption+)
 apply (rule ag_pOp_closed [of "P"], assumption+)
 apply (frule_tac f = g and m = "(m, n1 +\<^sub>N n2)" and n = "-\<^sub>P ((m, n1) +\<^sub>P (m, n2))" in mHom_add[of "R" "P" "Z"], assumption+)
 apply (rule ag_mOp_closed, assumption+)
 apply (rule ag_pOp_closed, assumption+) apply simp
 apply (thin_tac "g ((m, n1 +\<^sub>N n2) +\<^sub>P -\<^sub>P ((m, n1) +\<^sub>P (m, n2))) =
           g (m, n1 +\<^sub>N n2) +\<^sub>Z (g (-\<^sub>P ((m, n1) +\<^sub>P (m, n2))))")
 apply (frule_tac m = "(m, n1) +\<^sub>P (m, n2)" and f = g in mHom_inv [of "R" "P" "Z"], assumption+)
 apply (simp add:ag_pOp_closed) apply assumption apply simp
 apply (frule_tac f = g and m = "(m, n1)" and n = "(m, n2)" in mHom_add[of "R" "P" "Z"], assumption+) apply simp apply (thin_tac "g ((m, n1) +\<^sub>P (m, n2)) = g (m, n1) +\<^sub>Z (g (m, n2))")
 apply (thin_tac "g (-\<^sub>P ((m, n1) +\<^sub>P (m, n2)))= -\<^sub>Z (g (m, n1) +\<^sub>Z (g (m, n2)))")
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) (m, n1 +\<^sub>N n2) = f (m, n1 +\<^sub>N n2)")
 prefer 2 apply (simp add:compose_def tau_def)
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) (m, n1) = f (m, n1)")
 prefer 2 apply (simp add:compose_def tau_def)
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) (m, n2) = f (m, n2)")
 prefer 2 apply (simp add:compose_def tau_def)
 apply (thin_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) = f")
 apply (subgoal_tac "(m, n1 +\<^sub>N n2) \<in> M \<times>\<^sub>c N")
 apply (subgoal_tac "(m, n1) \<in> M \<times>\<^sub>c N") apply (subgoal_tac "(m, n2) \<in> M \<times>\<^sub>c N")
 apply (simp add:compose_def tau_def)
 apply (subgoal_tac "f (m, n1 +\<^sub>N n2) = f (m, n1) +\<^sub>Z (f (m, n2))")
 apply (subgoal_tac "f (m, n1) +\<^sub>Z (f (m, n2)) \<in> carrier Z")
 apply (frule module_is_ag [of "R" "Z"], assumption+)
 apply (simp add:ag_r_inv1 [of "Z"])
 apply (frule module_is_ag [of "R" "Z"], assumption+)
 apply (rule ag_pOp_closed, assumption+)
 apply (simp add:bilinear_map_def) apply (frule conj_1)
 apply (simp add:funcset_mem)
 apply (simp add:bilinear_map_def) apply (frule conj_1)
 apply (simp add:funcset_mem)
apply (simp add:bilinear_map_def)
 apply (simp add:prod_carr_def) apply (simp add:prod_carr_def)
  apply (simp add:prod_carr_def)
  apply (frule module_is_ag [of "R" "N"], assumption+)
  apply (simp add:ag_pOp_closed)
 apply (simp add:free_module_mem)
 apply (simp add:free_module_mem)
 apply (rule free_module_mem, assumption+)
 apply (frule module_is_ag [of "R" "N"], assumption+)
 apply (simp add:ag_pOp_closed) apply assumption+
 apply simp (** case TR2 done **)
apply (case_tac "x \<in> TR3 R M N P") (** case x \<in> TR3 R M N P **)
 apply (thin_tac "x \<in> TR3 R M N P \<or> x \<in> TR4 R M N P")
 apply (simp add:tensor_relations3_def)
 apply (subgoal_tac "\<forall>m\<in>carrier M. \<forall>n\<in>carrier N. \<forall>a\<in>carrier R. x = (a \<star>\<^sub>M m, n) +\<^sub>P -\<^sub>P (a \<star>\<^sub>P (m, n)) \<longrightarrow> (x \<in>  ker\<^sub>P\<^sub>,\<^sub>Z g)")
 apply blast
 apply (thin_tac "\<exists>m\<in>carrier M. \<exists>n\<in>carrier N. \<exists>a\<in>carrier R. x = (a \<star>\<^sub>M m, n) +\<^sub>P -\<^sub>P  (a \<star>\<^sub>P (m, n))")
 apply (rule ballI)+ apply (rule impI) apply (simp add:ker_def)
 apply (thin_tac "x = (a \<star>\<^sub>M m, n) +\<^sub>P -\<^sub>P  (a \<star>\<^sub>P (m, n))")
 apply (subgoal_tac "(a \<star>\<^sub>M m, n) \<in> carrier P")
 apply (subgoal_tac "(m, n) \<in> carrier P")
 apply (rule conjI)
 apply (frule module_is_ag [of "R" "P"], assumption+)
 apply (rule ag_pOp_closed, assumption+)
 apply (rule ag_mOp_closed [of "P"], assumption+)
 apply (simp add:sprod_mem)
 apply (frule_tac f = g and m = "(a \<star>\<^sub>M m, n)" and n = "-\<^sub>P (a \<star>\<^sub>P (m, n))" in mHom_add[of "R" "P" "Z"], assumption+)
 apply (frule module_is_ag [of "R" "P"], assumption+)
 apply (rule ag_mOp_closed, assumption+) apply (simp add:sprod_mem)
 apply simp
 apply (thin_tac "g ((a \<star>\<^sub>M m, n) +\<^sub>P -\<^sub>P  (a \<star>\<^sub>P (m, n))) = g (a \<star>\<^sub>M m, n) +\<^sub>Z (g (-\<^sub>P  (a \<star>\<^sub>P (m, n))))")
 apply (frule_tac f = g in mHom_inv [of "R" "P" "Z"], assumption+)
 apply (subgoal_tac " g (-\<^sub>P  (a \<star>\<^sub>P (m, n))) = g (-\<^sub>P ( a \<star>\<^sub>M m, n))")
 apply simp
 apply (subgoal_tac "g ( a \<star>\<^sub>M m, n) \<in> carrier Z")
 prefer 2 apply (simp add:mHom_mem)
 apply (frule module_is_ag [of "R" "Z"], assumption+) apply (simp add:ag_r_inv1)
 apply (frule_tac a = a and m = "(m, n)" in  sprod_mem [of "R" "P"], assumption+)
 apply (simp add:mHom_inv)
 apply (simp add:mHom_lin)
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) (a \<star>\<^sub>M m, n) = f (a \<star>\<^sub>M m, n)")
 prefer 2 apply (simp add:compose_def tau_def)
apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) (m, n) = f (m, n)")
 apply (thin_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) = f")
 apply (subgoal_tac "(m, n) \<in> M \<times>\<^sub>c N")
 apply (subgoal_tac "(a \<star>\<^sub>M m, n) \<in> M \<times>\<^sub>c N")
 apply (simp add:compose_def tau_def)
 apply (subgoal_tac "f (a \<star>\<^sub>M m, n) = a \<star>\<^sub>Z (f (m, n))")
 apply simp
 apply (simp add:bilinear_map_def)
 apply (simp add:prod_carr_def) apply (simp add:sprod_mem)
  apply (simp add:prod_carr_def)
  apply simp apply (simp add:free_module_mem)
  apply (rule free_module_mem, assumption+) apply (simp add:sprod_mem)
  apply assumption+
 apply simp  (** x \<in> TR3 done **)
(** case x \<in> TR4 R M N P **)
 apply (simp add:tensor_relations4_def)
 apply (subgoal_tac "\<forall>m\<in>carrier M. \<forall>n\<in>carrier N. \<forall>a\<in>carrier R. x = (m, a \<star>\<^sub>N n) +\<^sub>P -\<^sub>P (a \<star>\<^sub>P (m, n)) \<longrightarrow> (x \<in>  ker\<^sub>P\<^sub>,\<^sub>Z g)")
 apply blast
 apply (thin_tac "\<exists>m\<in>carrier M. \<exists>n\<in>carrier N. \<exists>a\<in>carrier R. x = (m, a \<star>\<^sub>N n) +\<^sub>P -\<^sub>P  (a \<star>\<^sub>P (m, n))")
 apply (rule ballI)+ apply (rule impI) apply (simp add:ker_def)
 apply (thin_tac "x = (m, a \<star>\<^sub>N n) +\<^sub>P -\<^sub>P  (a \<star>\<^sub>P (m, n))")
 apply (subgoal_tac "(m, a \<star>\<^sub>N n) \<in> carrier P")
 apply (subgoal_tac "(m, n) \<in> carrier P")
 apply (rule conjI)
 apply (frule module_is_ag [of "R" "P"], assumption+)
 apply (rule ag_pOp_closed, assumption+)
 apply (rule ag_mOp_closed [of "P"], assumption+)
 apply (simp add:sprod_mem)
 apply (frule_tac f = g and m = "(m, a \<star>\<^sub>N n)" and n = "-\<^sub>P (a \<star>\<^sub>P (m, n))" in mHom_add[of "R" "P" "Z"], assumption+)
 apply (frule module_is_ag [of "R" "P"], assumption+)
 apply (rule ag_mOp_closed, assumption+) apply (simp add:sprod_mem)
 apply simp
 apply (thin_tac "g ((m, a \<star>\<^sub>N n) +\<^sub>P -\<^sub>P  (a \<star>\<^sub>P (m, n))) = g (m, a \<star>\<^sub>N n) +\<^sub>Z (g (-\<^sub>P (a \<star>\<^sub>P (m, n))))")
 apply (frule_tac f = g in mHom_inv [of "R" "P" "Z"], assumption+)
 apply (subgoal_tac " g (-\<^sub>P  (a \<star>\<^sub>P (m, n))) = g (-\<^sub>P ( m, a \<star>\<^sub>N n))")
 apply simp
 apply (subgoal_tac "g (m, a \<star>\<^sub>N n) \<in> carrier Z")
 prefer 2 apply (simp add:mHom_mem)
 apply (frule module_is_ag [of "R" "Z"], assumption+) apply (simp add:ag_r_inv1)
 apply (frule_tac a = a and m = "(m, n)" in  sprod_mem [of "R" "P"], assumption+)
 apply (simp add:mHom_inv)
 apply (simp add:mHom_lin)
 apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) (m, a \<star>\<^sub>N n) = f (m, a \<star>\<^sub>N n)")
 prefer 2 apply (simp add:compose_def tau_def)
apply (subgoal_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) (m, n) = f (m, n)")
 apply (thin_tac "compose (M \<times>\<^sub>c N) g (tau R M N P) = f")
 apply (subgoal_tac "(m, n) \<in> M \<times>\<^sub>c N")
 apply (subgoal_tac "(m, a \<star>\<^sub>N n) \<in> M \<times>\<^sub>c N")
 apply (simp add:compose_def tau_def)
 apply (subgoal_tac "f (m, a \<star>\<^sub>N n) = a \<star>\<^sub>Z (f (m, n))")
 apply simp
 apply (simp add:bilinear_map_def)
 apply (simp add:prod_carr_def) apply (simp add:sprod_mem)
  apply (simp add:prod_carr_def)
  apply simp apply (simp add:free_module_mem)
  apply (rule free_module_mem, assumption+) apply (simp add:sprod_mem)
  apply assumption+
done

lemma tensor_universal_property:"\<lbrakk>ring R; R module M; R module N; FM\<^sub>R P M N \<rbrakk> \<Longrightarrow>
 universal_property R M N (M \<^sub>P\<Otimes>\<^sub>R N) (tnm R P M N)"
apply (simp add:universal_property_def)
 apply (frule tau_mpj_bilinear [of "R" "M" "N"], assumption+)
 apply (rule conjI)  apply (simp add:tnm_def)
apply (rule allI)+ apply (rule impI) apply (erule conjE)
 apply (rule_tac Z = Z and f = g in tensor_univ_propTr1 [of "R" "M" "N"],
             assumption+)
done

text{*                    f
                  M \<times> N  \<longrightarrow> Z
                    |       /
         tnp R M N  |      / g
                    |     /
                  M \<Otimes>\<^sub>R N
     *}


end