Theory Planar_Complete

theory Planar_Complete
imports
  Digraph_Map_Impl
begin

section ‹Kuratowski Graphs are not Combinatorially Planar›

subsection ‹A concrete K5 graph›

definition "c_K5_list  ([0..4], [(x,y). x <- [0..4], y <- [0..4], x  y])"

abbreviation c_K5 :: "int pair_pre_digraph" where
  "c_K5  list_digraph c_K5_list"

lemma c_K5_not_comb_planar: "¬comb_planar c_K5"
  by (subst comb_planar_impl_correct) eval+

lemma pverts_c_K5: "pverts c_K5 = {0..4}"
  by (simp add: c_K5_list_def list_digraph_ext_def)

lemma parcs_c_K5: "parcs c_K5 = {(u,v). u  {0..4}  v  {0..4}  u  v}"
  by (auto simp: c_K5_list_def list_digraph_ext_def)

lemmas c_K5_simps = pverts_c_K5 parcs_c_K5

lemma complete_c_K5: "K⇘5c_K5"
proof -
  interpret K5: pair_graph c_K5 by eval
  show ?thesis unfolding complete_digraph_def by (auto simp: c_K5_simps)
qed


subsection ‹A concrete K33 graph›

definition "c_K33_list  ([0..5], [(x,y). x <- [0..5], y <- [0..5], even x  odd y])"

abbreviation c_K33 :: "int pair_pre_digraph" where
  "c_K33  list_digraph c_K33_list"

lemma c_K33_not_comb_planar: "¬comb_planar c_K33"
  by (subst comb_planar_impl_correct) eval+

lemma complete_c_K33: "K⇘3,3c_K33"
proof -
  interpret K33: pair_graph c_K33 by eval
  show ?thesis
    unfolding complete_bipartite_digraph_def
    apply (intro conjI)
    apply unfold_locales
    apply (rule exI[of _ "{0,2,4}"])
    apply (rule exI[of _ "{1,3,5}"])
    unfolding c_K33_list_def list_digraph_simps with_proj_simps
    apply eval
    done
qed



subsection ‹Generalization to arbitrary Kuratowski Graphs›

subsubsection ‹Number of Face Cycles is a Graph Invariant›

lemma (in digraph_map) wrap_wrap_iso:
  assumes hom: "digraph_isomorphism hom"
  assumes f: "f  arcs G  arcs G" and g: "g  arcs G  arcs G"
  shows "wrap_iso_arcs hom f (wrap_iso_arcs hom g x) = wrap_iso_arcs hom (f o g) x"
proof -
  have "x. x  arcs G  g x  arcs G" using g by auto
  with hom f show ?thesis
    by (cases "x  iso_arcs hom ` arcs G") (auto simp: wrap_iso_arcs_def perm_restrict_simps)
qed

lemma (in digraph_map) face_cycle_succ_iso:
  assumes hom: "digraph_isomorphism hom" "x  iso_arcs hom ` arcs G"
  shows "pre_digraph_map.face_cycle_succ (map_iso hom) x = wrap_iso_arcs hom face_cycle_succ x"
  using assms by (simp add: pre_digraph_map.face_cycle_succ_def map_iso_def wrap_wrap_iso)

lemma (in digraph_map) face_cycle_set_iso:
  assumes hom: "digraph_isomorphism hom" "x  iso_arcs hom ` arcs G"
  shows "pre_digraph_map.face_cycle_set (map_iso hom) x = iso_arcs hom ` face_cycle_set (iso_arcs (inv_iso hom) x)"
proof -
  have *: "x y. x  orbit face_cycle_succ y  y  arcs G  x  arcs G"
          "x. x  arcs G  x  orbit face_cycle_succ x"
    using face_cycle_set_def by (auto simp: in_face_cycle_setD)
  show ?thesis
    using assms unfolding pre_digraph_map.face_cycle_set_def
    by (subst orbit_inverse [where g'="pre_digraph_map.face_cycle_succ (map_iso hom)"])
       (auto simp: * face_cycle_succ_iso)
qed

lemma (in digraph_map) face_cycle_sets_iso:
  assumes hom: "digraph_isomorphism hom"
  shows "pre_digraph_map.face_cycle_sets (app_iso hom G) (map_iso hom) = (λx. iso_arcs hom ` x) ` face_cycle_sets" 
  using assms by (auto simp: pre_digraph_map.face_cycle_sets_def face_cycle_set_iso) (auto simp: face_cycle_set_iso intro: rev_image_eqI)

lemma (in digraph_map) card_face_cycle_sets_iso:
  assumes hom: "digraph_isomorphism hom"
  shows "card (pre_digraph_map.face_cycle_sets (app_iso hom G) (map_iso hom)) = card face_cycle_sets"
proof -
  have "inj_on ((`) (iso_arcs hom)) face_cycle_sets"
    by (rule inj_on_f_imageI digraph_isomorphism_inj_on_arcs hom in_face_cycle_setsD)+
  then show ?thesis using hom by (simp add: face_cycle_sets_iso card_image)
qed



subsubsection ‹Combinatorial planarity is a Graph Invariant›

lemma (in digraph_map) euler_char_iso:
  assumes "digraph_isomorphism hom"
  shows "pre_digraph_map.euler_char (app_iso hom G) (map_iso hom) = euler_char"
  using assms by (auto simp: pre_digraph_map.euler_char_def card_face_cycle_sets_iso)

lemma (in digraph_map) euler_genus_iso:
  assumes "digraph_isomorphism hom"
  shows "pre_digraph_map.euler_genus (app_iso hom G) (map_iso hom) = euler_genus"
  using assms by (auto simp: pre_digraph_map.euler_genus_def euler_char_iso)

lemma (in wf_digraph) comb_planar_iso:
  assumes "digraph_isomorphism hom"
  shows "comb_planar (app_iso hom G)  comb_planar G"
proof
  assume "comb_planar G"
  then obtain M where "digraph_map G M" "pre_digraph_map.euler_genus G M = 0"
    by (auto simp: comb_planar_def)
  then have "digraph_map (app_iso hom G) (pre_digraph_map.map_iso G M hom)"
      "pre_digraph_map.euler_genus (app_iso hom G) (pre_digraph_map.map_iso G M hom) = 0"
    using assms by (auto intro: digraph_map.digraph_map_isoI simp: digraph_map.euler_genus_iso)
  then show "comb_planar (app_iso hom G)"
    by (metis comb_planar_def)
next
  let ?G = "app_iso hom G"
  assume "comb_planar ?G"
  then obtain M where "digraph_map ?G M"
      "pre_digraph_map.euler_genus ?G M = 0"
    by (auto simp: comb_planar_def)
  moreover
  have "pre_digraph.digraph_isomorphism ?G (inv_iso hom)"
    using assms by (rule digraph_isomorphism_invI)
  ultimately
  have "digraph_map (app_iso (inv_iso hom) ?G) (pre_digraph_map.map_iso ?G M (inv_iso hom))"
      "pre_digraph_map.euler_genus (app_iso (inv_iso hom) ?G) (pre_digraph_map.map_iso ?G M (inv_iso hom)) = 0"
    using assms by (auto intro: digraph_map.digraph_map_isoI simp only: digraph_map.euler_genus_iso)
  then show "comb_planar G"
    using assms by (auto simp: comb_planar_def)
qed


subsubsection ‹Completeness is a Graph Invariant›

lemma (in loopfree_digraph) loopfree_digraphI_app_iso:
  assumes "digraph_isomorphism hom"
  shows "loopfree_digraph (app_iso hom G)"
proof -
  interpret iG: wf_digraph "app_iso hom G" using assms by (rule wf_digraphI_app_iso)
  show ?thesis
    using assms digraph_isomorphism_inj_on_verts[OF assms]
    by unfold_locales (auto simp: iso_verts_tail iso_verts_head dest: inj_onD no_loops)
qed

lemma (in nomulti_digraph) nomulti_digraphI_app_iso:
  assumes "digraph_isomorphism hom"
  shows "nomulti_digraph (app_iso hom G)"
proof -
  interpret iG: wf_digraph "app_iso hom G" using assms by (rule wf_digraphI_app_iso)
  show ?thesis
    using assms 
    by unfold_locales (auto simp: iso_verts_tail iso_verts_head arc_to_ends_def no_multi_arcs dest: inj_onD)
qed

lemma (in pre_digraph) symmetricI_app_iso:
  assumes "digraph_isomorphism hom"
  assumes "symmetric G"
  shows "symmetric (app_iso hom G)"
proof -
  let ?G = "app_iso hom G"
  have "sym (arcs_ends ?G)"
  proof (rule symI)
    fix u v assume "u ?Gv"
    then obtain a where a: "a  arcs ?G" "tail ?G a = u" "head ?G a = v" by auto
    then obtain a0 where a0: "a0  arcs G" "a = iso_arcs hom a0" by auto
    with symmetric G obtain b0 where "b0  arcs G" "tail G b0 = head G a0" "head G b0 = tail G a0"
      by (auto simp: symmetric_def arcs_ends_conv elim: symE)
    moreover
    define b where "b = iso_arcs hom b0"
    ultimately
    have "b  iso_arcs hom ` arcs G" "tail ?G b = v" "head ?G b = u"
      using a a0 assms by (auto simp: iso_verts_tail iso_verts_head)
    then show "v ?Gu" by (auto simp: arcs_ends_conv)
  qed
  then show ?thesis by (simp add: symmetric_def)
qed

lemma (in sym_digraph) sym_digraphI_app_iso:
  assumes "digraph_isomorphism hom"
  shows "sym_digraph (app_iso hom G)"
proof -
  interpret iG: wf_digraph "app_iso hom G" using assms by (rule wf_digraphI_app_iso)
  show ?thesis using assms by unfold_locales (intro symmetricI_app_iso sym_arcs) 
qed

lemma (in graph) graphI_app_iso:
  assumes "digraph_isomorphism hom"
  shows "graph (app_iso hom G)"
proof -
  interpret iG: fin_digraph "app_iso hom G"
    using assms by (rule fin_digraphI_app_iso)
  interpret iG: loopfree_digraph "app_iso hom G"
    using assms by (rule loopfree_digraphI_app_iso)
  interpret iG: nomulti_digraph "app_iso hom G"
    using assms by (rule nomulti_digraphI_app_iso)
  interpret iG: sym_digraph "app_iso hom G"
    using assms by (rule sym_digraphI_app_iso)
  show ?thesis by intro_locales
qed

lemma (in wf_digraph) graph_app_iso_eq:
  assumes "digraph_isomorphism hom"
  shows "graph (app_iso hom G)  graph G"
  using assms by (metis app_iso_inv digraph_isomorphism_invI graph.graphI_app_iso)

lemma (in pre_digraph) arcs_ends_iso:
  assumes "digraph_isomorphism hom"
  shows "arcs_ends (app_iso hom G) = (λ(u,v). (iso_verts hom u, iso_verts hom v)) ` arcs_ends G"
  using assms
  by (auto simp: arcs_ends_conv image_image iso_verts_tail iso_verts_head cong: image_cong)

lemma inj_onI_pair:
  assumes "inj_on f S" "T  S × S"
  shows "inj_on (λ(u,v). (f u, f v)) T"
  using assms by (intro inj_onI) (auto dest: inj_onD)

lemma (in wf_digraph) complete_digraph_iso:
  assumes "digraph_isomorphism hom"
  shows "K⇘n(app_iso hom G)  K⇘nG" (is "?L  ?R")
proof 
  assume "?L"
  then interpret iG: graph "app_iso hom G" by (simp add: complete_digraph_def)
  { have "{(u, v). u  iso_verts hom ` verts G  v  iso_verts hom ` verts G  u  v}
        = (λ(u,v). (iso_verts hom u, iso_verts hom v)) ` {(u,v). u  verts G  v  verts G  iso_verts hom u  iso_verts hom v}" (is "?L = _")
      by auto
    also have " = (λ(u,v). (iso_verts hom u, iso_verts hom v)) ` {(u,v). u  verts G  v  verts G  u  v}"
      using digraph_isomorphism_inj_on_verts[OF assms] by (auto dest: inj_onD)
    finally have "?L = " .
  } note X = this

  { fix A assume A: "A  verts G × verts G"
    then have "inj_on (λ(u, v). (iso_verts hom u, iso_verts hom v)) A"
      using A digraph_isomorphism_inj_on_verts[OF assms] by (intro inj_onI_pair)
  } note Y = this
  have "(arcs_ends G  {(u, v). u  verts G  v  verts G  u  v})  verts G × verts G"
    by auto
  note Y' = Y[OF this]

  show ?R using assms ?L
    by (simp add: complete_digraph_def X arcs_ends_iso graph_app_iso_eq inj_on_Un_image_eq_iff Y')
next
  assume "?R" then show ?L using assms
    by (fastforce simp add: complete_digraph_def arcs_ends_iso graph_app_iso_eq)
qed


subsubsection ‹Conclusion›

definition (in pre_digraph)
  mk_iso :: "('a  'c)  ('b  'd)  ('a, 'b, 'c, 'd) digraph_isomorphism"
where
  "mk_iso fv fa   iso_verts = fv, iso_arcs = fa,
    iso_head = fv o head G o the_inv_into (arcs G) fa,
    iso_tail = fv o tail G o the_inv_into (arcs G) fa "

lemma (in pre_digraph) mk_iso_simps[simp]:
  "iso_verts (mk_iso fv fa) = fv"
  "iso_arcs (mk_iso fv fa) = fa"
  by (auto simp: mk_iso_def)

lemma (in wf_digraph) digraph_isomorphism_mk_iso:
  assumes "inj_on fv (verts G)" "inj_on fa (arcs G)"
  shows "digraph_isomorphism (mk_iso fv fa)"
  using assms by (auto simp: digraph_isomorphism_def mk_iso_def the_inv_into_f_f wf_digraph)

definition "pairself f  λx. case x of (u,v)  (f u, f v)"

lemma inj_on_pairself:
  assumes "inj_on f S" and "T  S × S"
  shows "inj_on (pairself f) T"
  using assms unfolding pairself_def by (rule inj_onI_pair)

definition
  mk_iso_nomulti :: "('a,'b) pre_digraph  ('c,'d) pre_digraph  ('a  'c)  ('a, 'b, 'c, 'd) digraph_isomorphism"
where
  "mk_iso_nomulti G H fv  
    iso_verts = fv,
    iso_arcs = the_inv_into (arcs H) (arc_to_ends H) o pairself fv o arc_to_ends G,
    iso_head = head H,
    iso_tail = tail H
  "

lemma (in pre_digraph) mk_iso_simps_nomulti[simp]:
  "iso_verts (mk_iso_nomulti G H fv) = fv"
  "iso_head (mk_iso_nomulti G H fv) = head H"
  "iso_tail (mk_iso_nomulti G H fv) = tail H"
  by (auto simp: mk_iso_nomulti_def)

lemma (in nomulti_digraph)  
  assumes "nomulti_digraph H"
  assumes fv: "inj_on fv (verts G)" "verts H = fv ` verts G" and arcs_ends: "arcs_ends H = pairself fv ` arcs_ends G"
  shows digraph_isomorphism_mk_iso_nomulti: "digraph_isomorphism (mk_iso_nomulti G H fv)" (is "?t_multi")
    and ap_iso_mk_iso_nomulti_eq: "app_iso (mk_iso_nomulti G H fv) G = H" (is "?t_app")
    and digraph_iso_mk_iso_nomulti: "digraph_iso G H" (is "?t_iso")
  using assms
proof -
  interpret H: nomulti_digraph H by fact
  let ?fa = "iso_arcs (mk_iso_nomulti G H fv)"

  have fa: "bij_betw ?fa (arcs G) (arcs H)"
  proof -
    have "bij_betw (arc_to_ends G) (arcs G) (arcs_ends G)"
      by (auto simp: bij_betw_def inj_on_arc_to_ends arcs_ends_def)
    also have "bij_betw (pairself fv) (arcs_ends G) (arcs_ends H)"
      using arcs_ends by (auto simp: bij_betw_def arcs_ends_def arc_to_ends_def intro: fv inj_on_pairself)
    also (bij_betw_trans) have "bij_betw (the_inv_into (arcs H) (arc_to_ends H)) (arcs_ends H) (arcs H)"
      by (auto simp: bij_betw_def the_inv_into_into H.inj_on_arc_to_ends arcs_ends_def inj_on_the_inv_into)
    finally (bij_betw_trans) show ?thesis
      by (simp add: mk_iso_nomulti_def o_assoc)
  qed
  moreover
  { fix a assume "a  arcs G"
    then have "pairself fv (arc_to_ends G a)  arcs_ends H"
      using arcs_ends by (auto simp: arcs_ends_def)
    then obtain b where "(pairself fv (arc_to_ends G a)) = arc_to_ends H b" "b  arcs H"
      by (auto simp: arcs_ends_def)
    then have "fv (tail G a) = tail H (?fa a)" "fv (head G a) = head H (?fa a)"
      by (auto simp: mk_iso_nomulti_def the_inv_into_f_f H.inj_on_arc_to_ends)
        (auto simp: pairself_def arc_to_ends_def)
  }
  ultimately
  show ?t_multi ?t_app using fv by (auto simp: digraph_isomorphism_def bij_betw_def wf_digraph)
  then show ?t_iso by (auto simp: digraph_iso_def)
qed

lemma complete_digraph_are_iso:
  assumes "K⇘nG" "K⇘nH" shows "digraph_iso G H"
proof -
  interpret G: graph G using assms by (simp add: complete_digraph_def)
  interpret H: graph H using assms by (simp add: complete_digraph_def)

  from assms have "card (verts G) = n" "card (verts H) = n"
    by (auto simp: complete_digraph_def)
  with G.finite_verts H.finite_verts obtain fv where "bij_betw fv (verts G) (verts H)"
    by (metis finite_same_card_bij)
  then have fv: "inj_on fv (verts G)" "verts H = fv ` verts G" by (auto simp: bij_betw_def)

  have "arcs_ends H = {(u,v). u  verts H  v  verts H  u  v}"
    using ‹K⇘nH by (auto simp: complete_digraph_def)
  also have " = pairself fv ` {(u,v). u  verts G  v  verts G  u  v}" (is "?L = ?R")
  proof (intro set_eqI iffI)
    fix x assume "x  ?L"
    then have "fst x  fv ` verts G" "snd x  fv ` verts G" "fst x  snd x"
      using fv by auto
    then obtain u v where "fst x = fv u" "snd x = fv v" "u  verts G" "v  verts G" by auto
    then have "(fst x, snd x)  ?R" using x  ?L by (auto simp: pairself_def)
    then show "x  ?R" by auto
  next
    fix x assume "x  ?R" then show "x  ?L"
    using fv by (auto simp: pairself_def dest: inj_onD)
  qed
  also have " = pairself fv ` arcs_ends G"
    using ‹K⇘nG by (auto simp: complete_digraph_def)
  finally  have arcs_ends: "arcs_ends H = pairself fv ` arcs_ends G" .

  show ?thesis using H.nomulti_digraph fv arcs_ends by (rule G.digraph_iso_mk_iso_nomulti)
qed

lemma pairself_image_prod:
  "pairself f ` (A × B) = f ` A × f ` B"
  by (auto simp: pairself_def)

lemma complete_bipartite_digraph_are_iso:
  assumes "K⇘m,nG" "K⇘m,nH" shows "digraph_iso G H"
proof -
  interpret G: graph G using assms by (simp add: complete_bipartite_digraph_def)
  interpret H: graph H using assms by (simp add: complete_bipartite_digraph_def)

  from assms obtain GU GV where G_parts: "verts G = GU  GV" "GU  GV = {}"
      "card GU = m" "card GV = n" "arcs_ends G = GU × GV  GV × GU"
    by (auto simp: complete_bipartite_digraph_def)
  from assms obtain HU HV where H_parts: "verts H = HU  HV" "HU  HV = {}"
      "card HU = m" "card HV = n" "arcs_ends H = HU × HV  HV × HU"
    by (auto simp: complete_bipartite_digraph_def)

  have fin: "finite GU" "finite GV" "finite HU" "finite HV"
    using G_parts H_parts G.finite_verts H.finite_verts by simp_all

  obtain fv_U where fv_U: "bij_betw fv_U GU HU"
    using card GU = _ card HU = _ finite GU finite HU by (metis finite_same_card_bij)
  obtain fv_V where fv_V: "bij_betw fv_V GV HV"
    using card GV = _ card HV = _ finite GV finite HV by (metis finite_same_card_bij)

  define fv where "fv x = (if x  GU then fv_U x else fv_V x)" for x
  have "x. x  GV  x  GU" using GU  GV = {} by blast
  then have bij_fv_UV: "bij_betw fv GU HU" "bij_betw fv GV HV"
    using fv_U fv_V by (auto simp: fv_def cong: bij_betw_cong)
  then have "bij_betw fv (verts G) (verts H)"
    unfolding verts G = _ verts H = _ using HU  _ = {} by (rule bij_betw_combine)
  then have fv: "inj_on fv (verts G)" "verts H = fv ` verts G" by (auto simp: bij_betw_def)

  have "arcs_ends H = HU × HV  HV × HU"
    using ‹K⇘m,nH H_parts by (auto simp: complete_digraph_def)
  also have " = pairself fv ` (GU × GV  GV × GU)" (is "?L = ?R")
  proof (intro set_eqI iffI)
    fix x assume "x  ?L"
    then have "(fst x  fv ` GU  snd x  fv ` GV)  (fst x  fv ` GV  snd x  fv ` GU)"
      using bij_fv_UV by (auto simp: bij_betw_def)
    then show "x  ?R"
      by (cases x) (auto simp: pairself_image_prod image_Un)
  next
    fix x assume "x  ?R" then show "x  ?L"
      using bij_fv_UV by (auto simp: pairself_image_prod image_Un bij_betw_def)
  qed
  also have " = pairself fv ` arcs_ends G"
    using ‹K⇘m,nG G_parts by (auto simp: complete_bipartite_digraph_def)
  finally have arcs_ends: "arcs_ends H = pairself fv ` arcs_ends G" .

  show ?thesis using H.nomulti_digraph fv arcs_ends by (rule G.digraph_iso_mk_iso_nomulti)
qed

lemma K5_not_comb_planar:
  assumes "K⇘5G" shows "¬comb_planar G"
proof -
  interpret graph G using assms by (auto simp: complete_digraph_def)
  have "digraph_iso G c_K5"
    using assms complete_c_K5 by (rule complete_digraph_are_iso)
  then obtain hom where hom: "digraph_isomorphism hom" "app_iso hom G = c_K5"
    by (auto simp: digraph_iso_def)
  then show ?thesis using c_K5_not_comb_planar comb_planar_iso by fastforce
qed

lemma K33_not_comb_planar:
  assumes "K⇘3,3G" shows "¬comb_planar G"
proof -
  interpret graph G using assms by (auto simp: complete_bipartite_digraph_def)
  have "digraph_iso G c_K33"
    using assms complete_c_K33 by (rule complete_bipartite_digraph_are_iso)
  then obtain hom where hom: "digraph_isomorphism hom" "app_iso hom G = c_K33"
    by (auto simp: digraph_iso_def)
  then show ?thesis using c_K33_not_comb_planar comb_planar_iso by fastforce 
qed

end