|
| 1 | +/- |
| 2 | +Copyright (c) 2022 George Peter Banyard, Yaël Dillies, Kyle Miller. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: George Peter Banyard, Yaël Dillies, Kyle Miller |
| 5 | +-/ |
| 6 | +import combinatorics.simple_graph.connectivity |
| 7 | + |
| 8 | +/-! |
| 9 | +# Graph products |
| 10 | +
|
| 11 | +This file defines the box product of graphs and other product constructions. The box product of `G` |
| 12 | +and `H` is the graph on the product of the vertices such that `x` and `y` are related iff they agree |
| 13 | +on one component and the other one is related via either `G` or `H`. For example, the box product of |
| 14 | +two edges is a square. |
| 15 | +
|
| 16 | +## Main declarations |
| 17 | +
|
| 18 | +* `simple_graph.box_prod`: The box product. |
| 19 | +
|
| 20 | +## Notation |
| 21 | +
|
| 22 | +* `G □ H`: The box product of `G` and `H`. |
| 23 | +
|
| 24 | +## TODO |
| 25 | +
|
| 26 | +Define all other graph products! |
| 27 | +-/ |
| 28 | + |
| 29 | +variables {α β γ : Type*} |
| 30 | + |
| 31 | +namespace simple_graph |
| 32 | +variables {G : simple_graph α} {H : simple_graph β} {I : simple_graph γ} {a a₁ a₂ : α} {b b₁ b₂ : β} |
| 33 | + {x y : α × β} |
| 34 | + |
| 35 | +/-- Box product of simple graphs. It relates `(a₁, b)` and `(a₂, b)` if `G` relates `a₁` and `a₂`, |
| 36 | +and `(a, b₁)` and `(a, b₂)` if `H` relates `b₁` and `b₂`. -/ |
| 37 | +def box_prod (G : simple_graph α) (H : simple_graph β) : simple_graph (α × β) := |
| 38 | +{ adj := λ x y, G.adj x.1 y.1 ∧ x.2 = y.2 ∨ H.adj x.2 y.2 ∧ x.1 = y.1, |
| 39 | + symm := λ x y, by simp [and_comm, or_comm, eq_comm, adj_comm], |
| 40 | + loopless := λ x, by simp } |
| 41 | + |
| 42 | +infix ` □ `:70 := box_prod |
| 43 | + |
| 44 | +lemma box_prod_adj : (G □ H).adj x y ↔ G.adj x.1 y.1 ∧ x.2 = y.2 ∨ H.adj x.2 y.2 ∧ x.1 = y.1 := |
| 45 | +iff.rfl |
| 46 | + |
| 47 | +@[simp] lemma box_prod_adj_left : (G □ H).adj (a₁, b) (a₂, b) ↔ G.adj a₁ a₂ := |
| 48 | +by rw [box_prod_adj, and_iff_left rfl, or_iff_left (λ h : H.adj b b ∧ _, h.1.ne rfl)] |
| 49 | + |
| 50 | +@[simp] lemma box_prod_adj_right : (G □ H).adj (a, b₁) (a, b₂) ↔ H.adj b₁ b₂ := |
| 51 | +by rw [box_prod_adj, and_iff_left rfl, or_iff_right (λ h : G.adj a a ∧ _, h.1.ne rfl)] |
| 52 | + |
| 53 | +variables (G H I) |
| 54 | + |
| 55 | +/-- The box product is commutative up to isomorphism. `equiv.prod_comm` as a graph isomorphism. -/ |
| 56 | +@[simps] def box_prod_comm : G □ H ≃g H □ G := ⟨equiv.prod_comm _ _, λ x y, or_comm _ _⟩ |
| 57 | + |
| 58 | +/-- The box product is associative up to isomorphism. `equiv.prod_assoc` as a graph isomorphism. -/ |
| 59 | +@[simps] def box_prod_assoc : (G □ H) □ I ≃g G □ (H □ I) := |
| 60 | +⟨equiv.prod_assoc _ _ _, λ x y, by simp only [box_prod_adj, equiv.prod_assoc_apply, |
| 61 | + or_and_distrib_right, or_assoc, prod.ext_iff, and_assoc, @and.comm (x.1.1 = _)]⟩ |
| 62 | + |
| 63 | +/-- The embedding of `G` into `G □ H` given by `b`. -/ |
| 64 | +@[simps] def box_prod_left (b : β) : G ↪g G □ H := |
| 65 | +{ to_fun := λ a, (a , b), |
| 66 | + inj' := λ a₁ a₂, congr_arg prod.fst, |
| 67 | + map_rel_iff' := λ a₁ a₂, box_prod_adj_left } |
| 68 | + |
| 69 | +/-- The embedding of `H` into `G □ H` given by `a`. -/ |
| 70 | +@[simps] def box_prod_right (a : α) : H ↪g G □ H := |
| 71 | +{ to_fun := prod.mk a, |
| 72 | + inj' := λ b₁ b₂, congr_arg prod.snd, |
| 73 | + map_rel_iff' := λ b₁ b₂, box_prod_adj_right } |
| 74 | + |
| 75 | +namespace walk |
| 76 | +variables {G} |
| 77 | + |
| 78 | +/-- Turn a walk on `G` into a walk on `G □ H`. -/ |
| 79 | +protected def box_prod_left (b : β) : G.walk a₁ a₂ → (G □ H).walk (a₁, b) (a₂, b) := |
| 80 | +walk.map (G.box_prod_left H b).to_hom |
| 81 | + |
| 82 | +variables (G) {H} |
| 83 | + |
| 84 | +/-- Turn a walk on `H` into a walk on `G □ H`. -/ |
| 85 | +protected def box_prod_right (a : α) : H.walk b₁ b₂ → (G □ H).walk (a, b₁) (a, b₂) := |
| 86 | +walk.map (G.box_prod_right H a).to_hom |
| 87 | + |
| 88 | +variables {G} [decidable_eq α] [decidable_eq β] [decidable_rel G.adj] [decidable_rel H.adj] |
| 89 | + |
| 90 | +/-- Project a walk on `G □ H` to a walk on `G` by discarding the moves in the direction of `H`. -/ |
| 91 | +def of_box_prod_left : Π {x y : α × β}, (G □ H).walk x y → G.walk x.1 y.1 |
| 92 | +| _ _ nil := nil |
| 93 | +| x z (cons h w) := or.by_cases h (λ hG, w.of_box_prod_left.cons hG.1) |
| 94 | + (λ hH, show G.walk x.1 z.1, by rw hH.2; exact w.of_box_prod_left) |
| 95 | + |
| 96 | +/-- Project a walk on `G □ H` to a walk on `H` by discarding the moves in the direction of `G`. -/ |
| 97 | +def of_box_prod_right : Π {x y : α × β}, (G □ H).walk x y → H.walk x.2 y.2 |
| 98 | +| _ _ nil := nil |
| 99 | +| x z (cons h w) := (or.symm h).by_cases (λ hH, w.of_box_prod_right.cons hH.1) |
| 100 | + (λ hG, show H.walk x.2 z.2, by rw hG.2; exact w.of_box_prod_right) |
| 101 | + |
| 102 | +@[simp] lemma of_box_prod_left_box_prod_left : |
| 103 | + ∀ {a₁ a₂ : α} (w : G.walk a₁ a₂), (w.box_prod_left H b).of_box_prod_left = w |
| 104 | +| _ _ nil := rfl |
| 105 | +| _ _ (cons' x y z h w) := begin |
| 106 | + rw [walk.box_prod_left, map_cons, of_box_prod_left, or.by_cases, dif_pos, ←walk.box_prod_left, |
| 107 | + of_box_prod_left_box_prod_left], |
| 108 | + exacts [rfl, ⟨h, rfl⟩], |
| 109 | +end |
| 110 | + |
| 111 | +@[simp] lemma of_box_prod_left_box_prod_right : |
| 112 | + ∀ {b₁ b₂ : α} (w : G.walk b₁ b₂), (w.box_prod_right G a).of_box_prod_right = w |
| 113 | +| _ _ nil := rfl |
| 114 | +| _ _ (cons' x y z h w) := begin |
| 115 | + rw [walk.box_prod_right, map_cons, of_box_prod_right, or.by_cases, dif_pos, ←walk.box_prod_right, |
| 116 | + of_box_prod_left_box_prod_right], |
| 117 | + exacts [rfl, ⟨h, rfl⟩], |
| 118 | +end |
| 119 | + |
| 120 | +end walk |
| 121 | + |
| 122 | +variables {G H} |
| 123 | + |
| 124 | +protected lemma preconnected.box_prod (hG : G.preconnected) (hH : H.preconnected) : |
| 125 | + (G □ H).preconnected := |
| 126 | +begin |
| 127 | + rintro x y, |
| 128 | + obtain ⟨w₁⟩ := hG x.1 y.1, |
| 129 | + obtain ⟨w₂⟩ := hH x.2 y.2, |
| 130 | + rw [←@prod.mk.eta _ _ x, ←@prod.mk.eta _ _ y], |
| 131 | + exact ⟨(w₁.box_prod_left _ _).append (w₂.box_prod_right _ _)⟩, |
| 132 | +end |
| 133 | + |
| 134 | +protected lemma preconnected.of_box_prod_left [nonempty β] (h : (G □ H).preconnected) : |
| 135 | + G.preconnected := |
| 136 | +begin |
| 137 | + classical, |
| 138 | + rintro a₁ a₂, |
| 139 | + obtain ⟨w⟩ := h (a₁, classical.arbitrary _) (a₂, classical.arbitrary _), |
| 140 | + exact ⟨w.of_box_prod_left⟩, |
| 141 | +end |
| 142 | + |
| 143 | +protected lemma preconnected.of_box_prod_right [nonempty α] (h : (G □ H).preconnected) : |
| 144 | + H.preconnected := |
| 145 | +begin |
| 146 | + classical, |
| 147 | + rintro b₁ b₂, |
| 148 | + obtain ⟨w⟩ := h (classical.arbitrary _, b₁) (classical.arbitrary _, b₂), |
| 149 | + exact ⟨w.of_box_prod_right⟩, |
| 150 | +end |
| 151 | + |
| 152 | +protected lemma connected.box_prod (hG : G.connected) (hH : H.connected) : (G □ H).connected := |
| 153 | +by { haveI := hG.nonempty, haveI := hH.nonempty, exact ⟨hG.preconnected.box_prod hH.preconnected⟩ } |
| 154 | + |
| 155 | +protected lemma connected.of_box_prod_left (h : (G □ H).connected) : G.connected := |
| 156 | +by { haveI := (nonempty_prod.1 h.nonempty).1, haveI := (nonempty_prod.1 h.nonempty).2, |
| 157 | + exact ⟨h.preconnected.of_box_prod_left⟩ } |
| 158 | + |
| 159 | +protected lemma connected.of_box_prod_right (h : (G □ H).connected) : H.connected := |
| 160 | +by { haveI := (nonempty_prod.1 h.nonempty).1, haveI := (nonempty_prod.1 h.nonempty).2, |
| 161 | + exact ⟨h.preconnected.of_box_prod_right⟩ } |
| 162 | + |
| 163 | +@[simp] lemma box_prod_connected : (G □ H).connected ↔ G.connected ∧ H.connected := |
| 164 | +⟨λ h, ⟨h.of_box_prod_left, h.of_box_prod_right⟩, λ h, h.1.box_prod h.2⟩ |
| 165 | + |
| 166 | +end simple_graph |
0 commit comments