Theory JordanHolder
theory JordanHolder
imports
  CompositionSeries
  MaximalNormalSubgroups
  "HOL-Library.Multiset"
  GroupIsoClasses
begin
section ‹The Jordan-H\"older Theorem›
locale jordan_hoelder = group
  + compℌ?: composition_series G ℌ
  + comp𝔊?: composition_series G 𝔊 for ℌ and 𝔊
  + assumes finite: "finite (carrier G)"
text ‹Before we finally start the actual proof of the theorem, one last lemma: Cancelling
  the last entry of a normal series results in a normal series with quotients being all but the last
  of the original ones.›
lemma (in normal_series) quotients_butlast:
  assumes "length 𝔊 > 1"
  shows "butlast quotients = normal_series.quotients (G⦇carrier := 𝔊 ! (length 𝔊 - 1 - 1)⦈) (take (length 𝔊 - 1) 𝔊)"
proof (rule nth_equalityI )
  define n where "n = length 𝔊 - 1"
  hence "n = length (take n 𝔊)" "n > 0" "n < length 𝔊" using assms notempty by auto
  interpret normal𝔊butlast: normal_series "(G⦇carrier := 𝔊 ! (n - 1)⦈)" "take n 𝔊" 
    using normal_series_prefix_closed ‹n > 0› ‹n < length 𝔊› by auto
  have "length (butlast quotients) = length quotients - 1" by (metis length_butlast)
  also have "… = length 𝔊 - 1 - 1" by (metis add_diff_cancel_right' quotients_length)
  also have "… = length (take n 𝔊) - 1" by (metis ‹n = length (take n 𝔊)› n_def)
  also have "… = length normal𝔊butlast.quotients" by (metis normal𝔊butlast.quotients_length diff_add_inverse2)
  finally show "length (butlast quotients) = length normal𝔊butlast.quotients" .
  have "∀i<length (butlast quotients). butlast quotients ! i = normal𝔊butlast.quotients ! i"
  proof auto
    fix i
    assume i: "i < length quotients - Suc 0"
    hence i': "i < length 𝔊 - 1" "i < n" "i + 1 < n" unfolding n_def using quotients_length by auto
    from i have "butlast quotients ! i = quotients ! i" by (metis One_nat_def length_butlast nth_butlast)
    also have "… = G⦇carrier := 𝔊 ! (i + 1)⦈ Mod 𝔊 ! i" unfolding quotients_def using i'(1) by auto
    also have "… = G⦇carrier := (take n 𝔊) ! (i + 1)⦈ Mod (take n 𝔊) ! i" using i'(2,3) nth_take by metis
    also have "… = normal𝔊butlast.quotients ! i" unfolding normal𝔊butlast.quotients_def using i' by fastforce
    finally show "butlast (normal_series.quotients G 𝔊) ! i = normal_series.quotients (G⦇carrier := 𝔊 ! (n - Suc 0)⦈) (take n 𝔊) ! i" by auto
  qed
  thus "⋀i. i < length (butlast quotients) 
            ⟹ butlast quotients ! i
              = normal_series.quotients (G⦇carrier := 𝔊 ! (length 𝔊 - 1 - 1)⦈)  (take (length 𝔊 - 1) 𝔊) ! i"
    unfolding n_def by auto
qed
text ‹The main part of the Jordan Hölder theorem is its statement about the uniqueness of 
  a composition series. Here, uniqueness up to reordering and isomorphism is modelled by stating
  that the multisets of isomorphism classes of all quotients are equal.›
theorem jordan_hoelder_multisets:
  assumes "group G"
  assumes "finite (carrier G)"
  assumes "composition_series G 𝔊"
  assumes "composition_series G ℌ"
  shows "mset (map group.iso_class (normal_series.quotients G 𝔊))
    = mset (map group.iso_class (normal_series.quotients G ℌ))"
using assms
proof (induction "length 𝔊" arbitrary: 𝔊 ℌ G rule: full_nat_induct)
  case (1 𝔊 ℌ G)
  then interpret comp𝔊: composition_series G 𝔊 by simp
  from 1 interpret compℌ: composition_series G ℌ by simp
  from 1 interpret grpG: group G by simp
  show ?case
  proof (cases "length 𝔊 ≤ 2")
  next
    case True
    hence  "length 𝔊 = 0 ∨ length 𝔊 = 1 ∨ length 𝔊 = 2" by arith
    with comp𝔊.notempty have  "length 𝔊 = 1 ∨ length 𝔊 = 2" by simp
    thus ?thesis
    proof (auto simp del: mset_map)
      
      assume "length 𝔊 = Suc 0"
      hence length: "length 𝔊 = 1" by simp
      hence "length [] + 1 = length 𝔊" by auto
      moreover from length have char𝔊: "𝔊 = [{𝟭⇘G⇙}]" by (metis comp𝔊.composition_series_length_one)
      hence "carrier G = {𝟭⇘G⇙}" by (metis comp𝔊.composition_series_triv_group)
      with length char𝔊 have "𝔊 = ℌ" using compℌ.composition_series_triv_group by simp
      thus ?thesis by simp
    next
      
      assume "length 𝔊 = 2"
      hence 𝔊char: "𝔊 = [{𝟭⇘G⇙}, carrier G]" by (metis comp𝔊.length_two_unique)
      hence simple: "simple_group G" by (metis comp𝔊.composition_series_simple_group)
      hence "ℌ = [{𝟭⇘G⇙}, carrier G]" using compℌ.composition_series_simple_group by auto
      with 𝔊char have "𝔊 = ℌ" by simp
      thus ?thesis by simp
    qed
  next
    case False
    
    hence length: "length 𝔊 ≥ 3" by simp
    
    hence "¬ simple_group G" using comp𝔊.composition_series_simple_group by auto
    hence "ℌ ≠ [{𝟭⇘G⇙}, carrier G]" using compℌ.composition_series_simple_group by auto
    hence "length ℌ ≠ 2" using compℌ.length_two_unique by auto
    moreover from length have "carrier G ≠ {𝟭⇘G⇙}" using comp𝔊.composition_series_length_one comp𝔊.composition_series_triv_group by auto
    hence "length ℌ ≠ 1" using compℌ.composition_series_length_one compℌ.composition_series_triv_group by auto
    moreover from compℌ.notempty have "length ℌ ≠ 0" by simp
    ultimately have lengthℌbig: "length ℌ ≥ 3" using compℌ.notempty by arith
    define m where "m = length ℌ - 1"
    define n where "n = length 𝔊 - 1"
    from lengthℌbig have m': "m > 0" "m < length ℌ" "(m - 1) + 1 < length ℌ" "m - 1 = length ℌ - 2" "m - 1 + 1 = length ℌ - 1" "m - 1 < length ℌ"
      unfolding m_def by auto
    from length have n': "n > 0" "n < length 𝔊" "(n - 1) + 1 < length 𝔊" "n - 1 < length 𝔊" "Suc n ≤ length 𝔊"
     "n - 1 = length 𝔊 - 2" "n - 1 + 1 = length 𝔊 - 1"  unfolding n_def by auto
    define 𝔊Pn where "𝔊Pn = G⦇carrier := 𝔊 ! (n - 1)⦈"
    define ℌPm where "ℌPm = G⦇carrier := ℌ ! (m - 1)⦈"
    then interpret grp𝔊Pn: group 𝔊Pn unfolding 𝔊Pn_def using n' by (metis comp𝔊.normal_series_subgroups comp𝔊.subgroup_imp_group)
    interpret grpℌPm: group ℌPm unfolding ℌPm_def using m' compℌ.normal_series_subgroups 1(2) group.subgroup_imp_group by force
    have finGbl: "finite (carrier 𝔊Pn)" using ‹n - 1 < length 𝔊› 1(3) unfolding 𝔊Pn_def using comp𝔊.normal_series_subgroups comp𝔊.subgroup_finite by auto
    have finHbl: "finite (carrier ℌPm)" using ‹m - 1 < length ℌ› 1(3) unfolding ℌPm_def using compℌ.normal_series_subgroups comp𝔊.subgroup_finite by auto
    have quots𝔊notempty: "comp𝔊.quotients ≠ []" using comp𝔊.quotients_length length by auto
    have quotsℌnotempty: "compℌ.quotients ≠ []" using compℌ.quotients_length lengthℌbig by auto
    
    
    interpret ℌbutlast: composition_series ℌPm "take m ℌ" using compℌ.composition_series_prefix_closed m'(1,2) ℌPm_def by auto
    interpret 𝔊butlast: composition_series 𝔊Pn "take n 𝔊" using comp𝔊.composition_series_prefix_closed n'(1,2) 𝔊Pn_def by auto
    have ltaken: "n = length (take n 𝔊)" using length_take n'(2) by auto
    have ltakem: "m = length (take m ℌ)" using length_take m'(2) by auto
    show ?thesis
    proof (cases "ℌ ! (m - 1)  = 𝔊 ! (n - 1)")
      
      case True
      
      have lasteq: "last comp𝔊.quotients = last compℌ.quotients"
      proof -
        from length have lg: "length 𝔊 - 1 - 1 + 1 = length 𝔊 - 1" by (metis Suc_diff_1 Suc_eq_plus1 n'(1) n_def)
        from lengthℌbig have lh: "length ℌ - 1 - 1 + 1 = length ℌ - 1" by (metis Suc_diff_1 Suc_eq_plus1 ‹0 < m› m_def)
        have "last comp𝔊.quotients =  G Mod 𝔊 ! (n - 1)" using length comp𝔊.last_quotient unfolding n_def by auto
        also have "… = G Mod ℌ ! (m - 1)" using True by simp
        also have "… = last compℌ.quotients" using lengthℌbig compℌ.last_quotient unfolding m_def by auto
        finally show ?thesis .
      qed
      from ltaken have ind: "mset (map group.iso_class 𝔊butlast.quotients) = mset (map group.iso_class ℌbutlast.quotients)"
        using 1(1) True n'(5) grp𝔊Pn.is_group finGbl 𝔊butlast.is_composition_series ℌbutlast.is_composition_series unfolding 𝔊Pn_def ℌPm_def by metis
      have "mset (map group.iso_class comp𝔊.quotients)
                    = mset (map group.iso_class (butlast comp𝔊.quotients @ [last comp𝔊.quotients]))" by (simp add: quots𝔊notempty)
      also have "… = mset (map group.iso_class (𝔊butlast.quotients @ [last (comp𝔊.quotients)]))" using comp𝔊.quotients_butlast length unfolding n_def 𝔊Pn_def by auto
      also have "… = mset ((map group.iso_class 𝔊butlast.quotients) @ [group.iso_class (last (comp𝔊.quotients))])" by auto
      also have "… = mset (map group.iso_class 𝔊butlast.quotients) + {# group.iso_class (last (comp𝔊.quotients)) #}" by auto
      also have "… = mset (map group.iso_class ℌbutlast.quotients) + {# group.iso_class (last (comp𝔊.quotients)) #}" using ind by simp
      also have "… = mset (map group.iso_class ℌbutlast.quotients) + {# group.iso_class (last (compℌ.quotients)) #}" using lasteq by simp
      also have "… = mset ((map group.iso_class ℌbutlast.quotients) @ [group.iso_class (last (compℌ.quotients))])" by auto
      also have "… = mset (map group.iso_class (ℌbutlast.quotients @ [last (compℌ.quotients)]))" by auto
      also have "… = mset (map group.iso_class (butlast compℌ.quotients @ [last compℌ.quotients]))" using lengthℌbig compℌ.quotients_butlast unfolding m_def ℌPm_def by auto
      also have "… = mset (map group.iso_class compℌ.quotients)" using append_butlast_last_id quotsℌnotempty by simp
      finally show ?thesis .
    next
      case False 
      define ℌPmInt𝔊Pn where "ℌPmInt𝔊Pn = G⦇carrier := ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)⦈"
      interpret 𝔊Pnmax: max_normal_subgroup "𝔊 ! (n - 1)" G unfolding n_def
        by (metis add_lessD1 diff_diff_add n'(3) add.commute one_add_one 1(3) comp𝔊.snd_to_last_max_normal)
      interpret ℌPmmax: max_normal_subgroup "ℌ ! (m - 1)" G unfolding m_def
        by (metis add_lessD1 diff_diff_add m'(3) add.commute one_add_one 1(3) compℌ.snd_to_last_max_normal)
      have ℌPmnormG: "ℌ ! (m - 1) ⊲ G" using compℌ.normal_series_snd_to_last m'(4) unfolding m_def by auto
      have 𝔊PnnormG: "𝔊 ! (n - 1) ⊲ G" using comp𝔊.normal_series_snd_to_last n'(6) unfolding n_def by auto
      have ℌPmint𝔊PnnormG: "ℌ ! (m - 1) ∩ 𝔊 ! (n - 1) ⊲ G" using ℌPmnormG 𝔊PnnormG by (rule comp𝔊.normal_subgroup_intersect)
      have Intnorm𝔊Pn: "ℌ ! (m - 1) ∩ 𝔊 ! (n - 1) ⊲ 𝔊Pn" using 𝔊PnnormG ℌPmnormG Int_lower2 unfolding 𝔊Pn_def
        by (metis comp𝔊.normal_restrict_supergroup comp𝔊.normal_series_subgroups comp𝔊.normal_subgroup_intersect n'(4))
      then interpret grp𝔊PnModℌPmint𝔊Pn: group "𝔊Pn Mod ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)" by (rule normal.factorgroup_is_group)
      have IntnormℌPm: "ℌ ! (m - 1) ∩ 𝔊 ! (n - 1) ⊲ ℌPm" using ℌPmnormG 𝔊PnnormG Int_lower2 Int_commute unfolding ℌPm_def
        by (metis comp𝔊.normal_restrict_supergroup comp𝔊.normal_subgroup_intersect compℌ.normal_series_subgroups m'(6))
      then interpret grpℌPmModℌPmint𝔊Pn: group "ℌPm Mod ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)" by (rule normal.factorgroup_is_group)
      
      have notℌPmSub𝔊Pn: "¬ (ℌ ! (m - 1) ⊆ 𝔊 ! (n - 1))" using ℌPmmax.max_normal 𝔊PnnormG False[symmetric] 𝔊Pnmax.proper by simp
      have not𝔊PnSubℌPm: "¬ (𝔊 ! (n - 1) ⊆ ℌ ! (m - 1))" using 𝔊Pnmax.max_normal ℌPmnormG False ℌPmmax.proper by simp
      
      
      have ℌPmSubSetmult: "ℌ ! (m - 1) ⊆ ℌ ! (m - 1) <#>⇘G⇙ 𝔊 ! (n - 1)"
        using 𝔊Pnmax.subgroup_axioms ℌPmnormG second_isomorphism_grp.H_contained_in_set_mult 
          second_isomorphism_grp_axioms_def second_isomorphism_grp_def by blast
      have 𝔊PnSubSetmult: "𝔊 ! (n - 1) ⊆ ℌ ! (m - 1) <#>⇘G⇙ 𝔊 ! (n - 1)"
        by (metis 𝔊Pnmax.subset 𝔊PnnormG ℌPmSubSetmult ℌPmmax.max_normal ℌPmmax.subgroup_axioms ℌPmnormG 
            comp𝔊.normal_subgroup_set_mult_closed comp𝔊.set_mult_inclusion)
      have "𝔊 ! (n - 1) ≠ (ℌ ! (m - 1)) <#>⇘G⇙ (𝔊 ! (n - 1))" using ℌPmSubSetmult notℌPmSub𝔊Pn by auto
      hence set_multG: "(ℌ ! (m - 1)) <#>⇘G⇙ (𝔊 ! (n - 1)) = carrier G"
        by (metis 𝔊PnSubSetmult 𝔊Pnmax.max_normal 𝔊PnnormG ℌPmnormG comp𝔊.normal_subgroup_set_mult_closed)
      then obtain φ where "φ ∈ iso (𝔊Pn Mod (ℌ ! (m - 1) ∩ 𝔊 ! (n - 1))) (G⦇carrier := carrier G⦈ Mod ℌ ! (m - 1))"
        by (metis second_isomorphism_grp.normal_intersection_quotient_isom ℌPmnormG  
            𝔊Pn_def 𝔊Pnmax.subgroup_axioms second_isomorphism_grp_axioms_def second_isomorphism_grp_def)
      hence φ: "φ ∈ iso (𝔊Pn Mod (ℌ ! (m - 1) ∩ 𝔊 ! (n - 1))) (G Mod ℌ ! (m - 1))" by auto
      then obtain φ2 where φ2: "φ2 ∈ iso (G Mod ℌ ! (m - 1)) (𝔊Pn Mod (ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)))"
        using group.iso_set_sym grp𝔊PnModℌPmint𝔊Pn.is_group by auto
      moreover have "simple_group (G⦇carrier := ℌ ! (m - 1 + 1)⦈ Mod ℌ ! (m - 1))" using compℌ.simplefact m'(3) by simp
      hence "simple_group (G Mod ℌ ! (m - 1))" using compℌ.last last_conv_nth compℌ.notempty m'(5) by fastforce
      ultimately have simple𝔊PnModInt: "simple_group (𝔊Pn Mod (ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)))"
        using simple_group.iso_simple grp𝔊PnModℌPmint𝔊Pn.is_group by auto
      interpret grpGModℌPm: group "(G Mod ℌ ! (m - 1))" by (metis ℌPmnormG normal.factorgroup_is_group)
      
      have ℌPmSubSetmult': "ℌ ! (m - 1) ⊆ 𝔊 ! (n - 1) <#>⇘G⇙ ℌ ! (m - 1)"
        by (metis 𝔊PnnormG ℌPmSubSetmult comp𝔊.commut_normal ℌPmnormG normal_imp_subgroup)
      have 𝔊PnSubSetmult': "𝔊 ! (n - 1) ⊆ 𝔊 ! (n - 1) <#>⇘G⇙ ℌ ! (m - 1)"
        by (metis ℌPmnormG normal_imp_subgroup 𝔊PnSubSetmult 𝔊PnnormG comp𝔊.commut_normal)
      have "ℌ ! (m - 1) ≠ (𝔊 ! (n - 1)) <#>⇘G⇙ (ℌ ! (m - 1))" using 𝔊PnSubSetmult' not𝔊PnSubℌPm by auto
      hence set_multG: "(𝔊 ! (n - 1)) <#>⇘G⇙ (ℌ ! (m - 1)) = carrier G"
        using ℌPmmax.max_normal 𝔊PnnormG comp𝔊.normal_subgroup_set_mult_closed ℌPmSubSetmult' ℌPmnormG by blast
      from set_multG obtain ψ where 
            "ψ ∈ iso (ℌPm Mod (𝔊 ! (n - 1) ∩ ℌ ! (m - 1))) (G⦇carrier := carrier G⦈ Mod 𝔊 ! (n - 1))"
        by (metis ℌPm_def ℌPmnormG second_isomorphism_grp_axioms_def second_isomorphism_grp_def 
            second_isomorphism_grp.normal_intersection_quotient_isom 𝔊PnnormG normal_imp_subgroup)
      hence ψ: "ψ ∈ iso (ℌPm Mod (ℌ ! (m - 1) ∩ (𝔊 ! (n - 1)))) (G⦇carrier := carrier G⦈ Mod 𝔊 ! (n - 1))" using Int_commute by metis
      then obtain ψ2 where
             ψ2: "ψ2 ∈ iso (G Mod 𝔊 ! (n - 1)) (ℌPm Mod (ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)))"
        using group.iso_set_sym grpℌPmModℌPmint𝔊Pn.is_group by auto
      moreover have "simple_group (G⦇carrier := 𝔊 ! (n - 1 + 1)⦈ Mod 𝔊 ! (n - 1))" using comp𝔊.simplefact n'(3) by simp
      hence "simple_group (G Mod 𝔊 ! (n - 1))" using comp𝔊.last last_conv_nth comp𝔊.notempty n'(7) by fastforce
      ultimately have simpleℌPmModInt: "simple_group (ℌPm Mod (ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)))" 
        using simple_group.iso_simple grpℌPmModℌPmint𝔊Pn.is_group by auto
      interpret grpGMod𝔊Pn: group "(G Mod 𝔊 ! (n - 1))" by (metis 𝔊PnnormG normal.factorgroup_is_group)
      
      
      define 𝔎 where "𝔎 = remdups_adj (map ((∩) (ℌ ! (m - 1))) 𝔊)"
      define 𝔏 where "𝔏 = remdups_adj (map ((∩) (𝔊 ! (n - 1))) ℌ)"
      interpret 𝔎: composition_series ℌPm 𝔎 using comp𝔊.intersect_normal 1(3) ℌPmnormG unfolding 𝔎_def ℌPm_def by auto
      interpret 𝔏: composition_series 𝔊Pn 𝔏 using compℌ.intersect_normal 1(3) 𝔊PnnormG unfolding 𝔏_def 𝔊Pn_def by auto
      
      from n'(2) have "Suc (length (take n 𝔊)) ≤ length 𝔊" by auto
      hence multisets𝔊butlast𝔏: "mset (map group.iso_class 𝔊butlast.quotients) = mset (map group.iso_class 𝔏.quotients)"
        using  "1.hyps" grp𝔊Pn.is_group finGbl 𝔊butlast.is_composition_series 𝔏.is_composition_series by metis
      hence length𝔏: "n = length 𝔏" using 𝔊butlast.quotients_length 𝔏.quotients_length length_map size_mset ltaken by metis
      hence length𝔏': "length 𝔏 > 1" "length 𝔏 - 1 > 0" "length 𝔏 - 1 ≤ length 𝔏" using n'(6) length by auto
      have Inteq𝔏sndlast: "ℌ ! (m - 1) ∩ 𝔊 ! (n - 1) = 𝔏 ! (length 𝔏 - 1 - 1)"
      proof -
        have "length 𝔏 - 1 - 1 + 1 < length 𝔏" using length𝔏' by auto
        moreover have KGnotempty: "(map ((∩) (𝔊 ! (n - 1))) ℌ) ≠ []" using compℌ.notempty by (metis Nil_is_map_conv)
        ultimately obtain i where i: "i + 1 < length (map ((∩) (𝔊 ! (n - 1))) ℌ)"
          "𝔏 ! (length 𝔏 - 1 - 1) = (map ((∩) (𝔊 ! (n - 1))) ℌ) ! i" "𝔏 ! (length 𝔏 - 1 - 1 + 1) = (map ((∩) (𝔊 ! (n - 1))) ℌ) ! (i + 1)"
          using remdups_adj_obtain_adjacency unfolding 𝔏_def by force
        hence "𝔏 ! (length 𝔏 - 1 - 1) = ℌ ! i ∩ 𝔊 ! (n - 1)" "𝔏 ! (length 𝔏 - 1 - 1 + 1) = ℌ ! (i + 1) ∩ 𝔊 ! (n - 1)" by auto
        hence "𝔏 ! (length 𝔏 - 1) = ℌ ! (i + 1) ∩ 𝔊 ! (n - 1)" using length𝔏'(2) by (metis Suc_diff_1 Suc_eq_plus1)
        hence 𝔊PnsubℌPm: "𝔊 ! (n - 1) ⊆ ℌ ! (i + 1)" using 𝔏.last 𝔏.notempty last_conv_nth unfolding 𝔊Pn_def by auto
        from i(1) have "i + 1 < m + 1" unfolding m_def by auto
        moreover have "¬ (i + 1 ≤ m - 1)" using compℌ.entries_mono m'(6) not𝔊PnSubℌPm 𝔊PnsubℌPm by fastforce
        ultimately have "m - 1 = i" by auto
        with i show ?thesis by auto
      qed
      hence 𝔏sndlast: "ℌPmInt𝔊Pn = (𝔊Pn⦇carrier := 𝔏 ! (length 𝔏 - 1 - 1)⦈)" unfolding ℌPmInt𝔊Pn_def 𝔊Pn_def by auto
      then interpret 𝔏butlast: composition_series ℌPmInt𝔊Pn "take (length 𝔏 - 1) 𝔏" using length𝔏' 𝔏.composition_series_prefix_closed by metis
      from ‹length 𝔏 > 1› have quots𝔏notemtpy: "𝔏.quotients ≠ []" unfolding 𝔏.quotients_def by auto
      
      have "length 𝔎 > 1"
      proof (rule ccontr)
        assume "¬ length 𝔎 > 1"
        with 𝔎.notempty have "length 𝔎 = 1" by (metis One_nat_def Suc_lessI length_greater_0_conv)
        hence "carrier ℌPm = {𝟭⇘ℌPm⇙}" using 𝔎.composition_series_length_one 𝔎.composition_series_triv_group by auto
        hence "carrier ℌPm = {𝟭⇘G⇙}" unfolding ℌPm_def by auto
        hence "carrier ℌPm ⊆ 𝔊 ! (n - 1)" using 𝔊Pnmax.is_subgroup subgroup.one_closed by auto
        with notℌPmSub𝔊Pn show False unfolding ℌPm_def by auto
      qed
      hence length𝔎': "length 𝔎 - 1 > 0" "length 𝔎 - 1 ≤ length 𝔎" by auto 
      have Inteq𝔎sndlast: "ℌ ! (m - 1) ∩ 𝔊 ! (n - 1) = 𝔎 ! (length 𝔎 - 1 - 1)"
      proof -
        have "length 𝔎 - 1 - 1 + 1 < length 𝔎" using length𝔎' by auto
        moreover have KGnotempty: "(map ((∩) (ℌ ! (m - 1))) 𝔊) ≠ []" using comp𝔊.notempty by (metis Nil_is_map_conv)
        ultimately obtain i where i: "i + 1 < length (map ((∩) (ℌ ! (m - 1))) 𝔊)"
          "𝔎 ! (length 𝔎 - 1 - 1) = (map ((∩) (ℌ ! (m - 1))) 𝔊) ! i" "𝔎 ! (length 𝔎 - 1 - 1 + 1) = (map ((∩) (ℌ ! (m - 1))) 𝔊) ! (i + 1)"
          using remdups_adj_obtain_adjacency unfolding 𝔎_def by force
        hence "𝔎 ! (length 𝔎 - 1 - 1) = 𝔊 ! i ∩ ℌ ! (m - 1)" "𝔎 ! (length 𝔎 - 1 - 1 + 1) = 𝔊 ! (i + 1) ∩ ℌ ! (m - 1)" by auto
        hence "𝔎 ! (length 𝔎 - 1) = 𝔊 ! (i + 1) ∩ ℌ ! (m - 1)" using length𝔎'(1) by (metis Suc_diff_1 Suc_eq_plus1)
        hence ℌPmsub𝔊Pn: "ℌ ! (m - 1) ⊆ 𝔊 ! (i + 1)" using 𝔎.last 𝔎.notempty last_conv_nth unfolding ℌPm_def by auto
        from i(1) have "i + 1 < n + 1" unfolding n_def by auto
        moreover have "¬ (i + 1 ≤ n - 1)" using comp𝔊.entries_mono n'(2) notℌPmSub𝔊Pn ℌPmsub𝔊Pn by fastforce
        ultimately have "n - 1 = i" by auto
        with i show ?thesis by auto
      qed
      have "composition_series (G⦇carrier := 𝔎 ! (length 𝔎 - 1 - 1)⦈) (take (length 𝔎 - 1) 𝔎)"
        using length𝔎' 𝔎.composition_series_prefix_closed unfolding ℌPmInt𝔊Pn_def ℌPm_def by fastforce
      then interpret 𝔎butlast: composition_series ℌPmInt𝔊Pn "(take (length 𝔎 - 1) 𝔎)" using Inteq𝔎sndlast unfolding ℌPmInt𝔊Pn_def by auto
      from finGbl have finInt: "finite (carrier ℌPmInt𝔊Pn)" unfolding ℌPmInt𝔊Pn_def 𝔊Pn_def by simp
      moreover have "Suc (length (take (length 𝔏 - 1) 𝔏)) ≤ length 𝔊" using length𝔏 unfolding n_def using n'(2) by auto
      ultimately have multisets𝔎𝔏butlast: "mset (map group.iso_class 𝔏butlast.quotients) = mset (map group.iso_class 𝔎butlast.quotients)"
         using "1.hyps" 𝔏butlast.is_group 𝔎butlast.is_composition_series 𝔏butlast.is_composition_series by auto
      hence "length (take (length 𝔎 - 1) 𝔎) = length (take (length 𝔏 - 1) 𝔏)"
        using 𝔎butlast.quotients_length 𝔏butlast.quotients_length length_map size_mset by metis
      hence "length (take (length 𝔎 - 1) 𝔎) = n - 1" using length𝔏 n'(1) by auto
      hence length𝔎: "length 𝔎 = n" by (metis Suc_diff_1 𝔎.notempty butlast_conv_take length_butlast length_greater_0_conv n'(1))
      
      
      from Inteq𝔎sndlast have 𝔎sndlast: "ℌPmInt𝔊Pn = (ℌPm⦇carrier := 𝔎 ! (length 𝔎 - 1 - 1)⦈)" unfolding ℌPmInt𝔊Pn_def ℌPm_def 𝔎_def by auto
      from length𝔎 have "Suc (length 𝔎) ≤ length 𝔊" using n'(2) by auto
      hence multisetsℌbutlast𝔎: "mset (map group.iso_class ℌbutlast.quotients) = mset (map group.iso_class 𝔎.quotients)"
        using  "1.hyps" grpℌPm.is_group finHbl ℌbutlast.is_composition_series 𝔎.is_composition_series by metis
      hence length𝔎: "m = length 𝔎" using ℌbutlast.quotients_length 𝔎.quotients_length length_map size_mset ltakem by metis
      hence  "length 𝔎 > 1" "length 𝔎 - 1 > 0" "length 𝔎 - 1 ≤ length 𝔎" using m'(4) lengthℌbig by auto
      hence quots𝔎notemtpy: "𝔎.quotients ≠ []" unfolding 𝔎.quotients_def by auto
      
      interpret 𝔎butlastadd𝔊Pn: composition_series 𝔊Pn "(take (length 𝔎 - 1) 𝔎) @ [𝔊 ! (n - 1)]"
        using grp𝔊Pn.composition_series_extend 𝔎butlast.is_composition_series simple𝔊PnModInt Intnorm𝔊Pn
        unfolding 𝔊Pn_def ℌPmInt𝔊Pn_def by auto
      interpret 𝔏butlastaddℌPm: composition_series ℌPm "(take (length 𝔏 - 1) 𝔏) @ [ℌ ! (m - 1)]"
        using grpℌPm.composition_series_extend 𝔏butlast.is_composition_series simpleℌPmModInt IntnormℌPm
        unfolding ℌPm_def ℌPmInt𝔊Pn_def by auto
      
      
      have "mset (map group.iso_class comp𝔊.quotients)
                    = mset (map group.iso_class ((butlast comp𝔊.quotients) @ [last comp𝔊.quotients]))" using quots𝔊notempty by simp
      also have "… = mset (map group.iso_class (𝔊butlast.quotients @ [G Mod 𝔊 ! (n - 1)]))"
        using comp𝔊.quotients_butlast comp𝔊.last_quotient length unfolding n_def 𝔊Pn_def by auto
      also have "… = mset (map group.iso_class ((butlast 𝔏.quotients) @ [last 𝔏.quotients])) + {# group.iso_class (G Mod 𝔊 ! (n - 1)) #}"
        using multisets𝔊butlast𝔏 quots𝔏notemtpy by simp
      also have "… = mset (map group.iso_class (𝔏butlast.quotients @ [𝔊Pn Mod ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)])) + {# group.iso_class (G Mod 𝔊 ! (n - 1)) #}"
        using 𝔏.quotients_butlast 𝔏.last_quotient ‹length 𝔏 > 1› 𝔏sndlast Inteq𝔏sndlast unfolding n_def by auto
      also have "… = mset (map group.iso_class 𝔎butlast.quotients) + {# group.iso_class (𝔊Pn Mod ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)) #} + {# group.iso_class (G Mod 𝔊 ! (n - 1)) #}"
        using multisets𝔎𝔏butlast by simp
      also have "… = mset (map group.iso_class 𝔎butlast.quotients) + {# group.iso_class (G Mod ℌ ! (m - 1)) #} + {# group.iso_class (ℌPm Mod ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)) #}"
        using φ ψ2 iso_classes_iff grp𝔊PnModℌPmint𝔊Pn.is_group grpGModℌPm.is_group grpGMod𝔊Pn.is_group grpℌPmModℌPmint𝔊Pn.is_group
        by metis
      also have "… = mset (map group.iso_class 𝔎butlast.quotients) + {# group.iso_class (ℌPm Mod ℌ ! (m - 1) ∩ 𝔊 ! (n - 1)) #} + {# group.iso_class (G Mod ℌ ! (m - 1)) #}"
        by simp
      also have "… = mset (map group.iso_class ((butlast 𝔎.quotients) @ [last 𝔎.quotients])) + {# group.iso_class (G Mod ℌ ! (m - 1)) #}"
        using 𝔎.quotients_butlast 𝔎.last_quotient ‹length 𝔎 > 1› 𝔎sndlast Inteq𝔎sndlast unfolding m_def by auto
      also have "… = mset (map group.iso_class ℌbutlast.quotients) + {# group.iso_class (G Mod ℌ ! (m - 1)) #}"
        using multisetsℌbutlast𝔎 quots𝔎notemtpy by simp
      also have "… = mset (map group.iso_class ((butlast compℌ.quotients) @ [last compℌ.quotients]))"
        using compℌ.quotients_butlast compℌ.last_quotient lengthℌbig unfolding m_def ℌPm_def by auto
      also have "… = mset (map group.iso_class compℌ.quotients)" using quotsℌnotempty by simp
      finally show ?thesis .
    qed
  qed
qed
text ‹As a corollary, we see that the composition series of a fixed group all have the same length.›
corollary (in jordan_hoelder) jordan_hoelder_size:
  shows "length 𝔊 = length ℌ"
proof -
  have "length 𝔊 = length comp𝔊.quotients + 1" by (metis comp𝔊.quotients_length)
  also have "… = size (mset (map group.iso_class comp𝔊.quotients)) + 1" by (metis length_map size_mset)
  also have "… = size (mset (map group.iso_class compℌ.quotients)) + 1"
    using jordan_hoelder_multisets is_group finite is_composition_series compℌ.is_composition_series by metis
  also have "… = length compℌ.quotients + 1" by (metis size_mset length_map)
  also have "… = length ℌ" by (metis compℌ.quotients_length)
  finally show ?thesis.
qed
end