|
| 1 | +/- |
| 2 | +Copyright (c) 2021 Gabriel Moise. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Gabriel Moise, Yaël Dillies, Kyle Miller |
| 5 | +-/ |
| 6 | +import combinatorics.simple_graph.basic |
| 7 | +import data.matrix.basic |
| 8 | + |
| 9 | +/-! |
| 10 | +# Incidence matrix of a simple graph |
| 11 | +
|
| 12 | +This file defines the unoriented incidence matrix of a simple graph. |
| 13 | +
|
| 14 | +## Main definitions |
| 15 | +
|
| 16 | +* `simple_graph.inc_matrix`: `G.inc_matrix R` is the incidence matrix of `G` over the ring `R`. |
| 17 | +
|
| 18 | +## Main results |
| 19 | +
|
| 20 | +* `simple_graph.inc_matrix_mul_transpose_diag`: The diagonal entries of the product of |
| 21 | + `G.inc_matrix R` and its transpose are the degrees of the vertices. |
| 22 | +* `simple_graph.inc_matrix_mul_transpose`: Gives a complete description of the product of |
| 23 | + `G.inc_matrix R` and its transpose; the diagonal is the degrees of each vertex, and the |
| 24 | + off-diagonals are 1 or 0 depending on whether or not the vertices are adjacent. |
| 25 | +* `simple_graph.inc_matrix_transpose_mul_diag`: The diagonal entries of the product of the |
| 26 | + transpose of `G.inc_matrix R` and `G.inc_matrix R` are `2` or `0` depending on whether or |
| 27 | + not the unordered pair is an edge of `G`. |
| 28 | +
|
| 29 | +## Implementation notes |
| 30 | +
|
| 31 | +The usual definition of an incidence matrix has one row per vertex and one column per edge. |
| 32 | +However, this definition has columns indexed by all of `sym2 α`, where `α` is the vertex type. |
| 33 | +This appears not to change the theory, and for simple graphs it has the nice effect that every |
| 34 | +incidence matrix for each `simple_graph α` has the same type. |
| 35 | +
|
| 36 | +## TODO |
| 37 | +
|
| 38 | +* Define the oriented incidence matrices for oriented graphs. |
| 39 | +* Define the graph Laplacian of a simple graph using the oriented incidence matrix from an |
| 40 | + arbitrary orientation of a simple graph. |
| 41 | +-/ |
| 42 | + |
| 43 | +noncomputable theory |
| 44 | + |
| 45 | +open finset matrix simple_graph sym2 |
| 46 | +open_locale big_operators matrix |
| 47 | + |
| 48 | +namespace simple_graph |
| 49 | +variables (R : Type*) {α : Type*} (G : simple_graph α) |
| 50 | + |
| 51 | +/-- `G.inc_matrix R` is the `α × sym2 α` matrix whose `(a, e)`-entry is `1` if `e` is incident to |
| 52 | +`a` and `0` otherwise. -/ |
| 53 | +def inc_matrix [has_zero R] [has_one R] : matrix α (sym2 α) R := |
| 54 | +λ a, (G.incidence_set a).indicator 1 |
| 55 | + |
| 56 | +variables {R} |
| 57 | + |
| 58 | +lemma inc_matrix_apply [has_zero R] [has_one R] {a : α} {e : sym2 α} : |
| 59 | + G.inc_matrix R a e = (G.incidence_set a).indicator 1 e := rfl |
| 60 | + |
| 61 | +/-- Entries of the incidence matrix can be computed given additional decidable instances. -/ |
| 62 | +lemma inc_matrix_apply' [has_zero R] [has_one R] [decidable_eq α] [decidable_rel G.adj] |
| 63 | + {a : α} {e : sym2 α} : |
| 64 | + G.inc_matrix R a e = if e ∈ G.incidence_set a then 1 else 0 := |
| 65 | +by convert rfl |
| 66 | + |
| 67 | +section mul_zero_one_class |
| 68 | +variables [mul_zero_one_class R] {a b : α} {e : sym2 α} |
| 69 | + |
| 70 | +lemma inc_matrix_apply_mul_inc_matrix_apply : |
| 71 | + G.inc_matrix R a e * G.inc_matrix R b e = (G.incidence_set a ∩ G.incidence_set b).indicator 1 e := |
| 72 | +begin |
| 73 | + simp only [inc_matrix, set.indicator_apply, ←ite_and_mul_zero, |
| 74 | + pi.one_apply, mul_one, set.mem_inter_eq], |
| 75 | + congr, |
| 76 | +end |
| 77 | + |
| 78 | +lemma inc_matrix_apply_mul_inc_matrix_apply_of_not_adj (hab : a ≠ b) (h : ¬ G.adj a b) : |
| 79 | + G.inc_matrix R a e * G.inc_matrix R b e = 0 := |
| 80 | +begin |
| 81 | + rw [inc_matrix_apply_mul_inc_matrix_apply, set.indicator_of_not_mem], |
| 82 | + rw [G.incidence_set_inter_incidence_set_of_not_adj h hab], |
| 83 | + exact set.not_mem_empty e, |
| 84 | +end |
| 85 | + |
| 86 | +lemma inc_matrix_of_not_mem_incidence_set (h : e ∉ G.incidence_set a) : |
| 87 | + G.inc_matrix R a e = 0 := |
| 88 | +by rw [inc_matrix_apply, set.indicator_of_not_mem h] |
| 89 | + |
| 90 | +lemma inc_matrix_of_mem_incidence_set (h : e ∈ G.incidence_set a) : G.inc_matrix R a e = 1 := |
| 91 | +by rw [inc_matrix_apply, set.indicator_of_mem h, pi.one_apply] |
| 92 | + |
| 93 | +variables [nontrivial R] |
| 94 | + |
| 95 | +lemma inc_matrix_apply_eq_zero_iff : G.inc_matrix R a e = 0 ↔ e ∉ G.incidence_set a := |
| 96 | +begin |
| 97 | + simp only [inc_matrix_apply, set.indicator_apply_eq_zero, pi.one_apply, one_ne_zero], |
| 98 | + exact iff.rfl, |
| 99 | +end |
| 100 | + |
| 101 | +lemma inc_matrix_apply_eq_one_iff : G.inc_matrix R a e = 1 ↔ e ∈ G.incidence_set a := |
| 102 | +by { convert one_ne_zero.ite_eq_left_iff, assumption } |
| 103 | + |
| 104 | +end mul_zero_one_class |
| 105 | + |
| 106 | +section non_assoc_semiring |
| 107 | +variables [fintype α] [non_assoc_semiring R] {a b : α} {e : sym2 α} |
| 108 | + |
| 109 | +lemma sum_inc_matrix_apply [decidable_eq α] [decidable_rel G.adj] : |
| 110 | + ∑ e, G.inc_matrix R a e = G.degree a := |
| 111 | +by simp [inc_matrix_apply', sum_boole, set.filter_mem_univ_eq_to_finset] |
| 112 | + |
| 113 | +lemma inc_matrix_mul_transpose_diag [decidable_eq α] [decidable_rel G.adj] : |
| 114 | + (G.inc_matrix R ⬝ (G.inc_matrix R)ᵀ) a a = G.degree a := |
| 115 | +begin |
| 116 | + rw ←sum_inc_matrix_apply, |
| 117 | + simp [matrix.mul_apply, inc_matrix_apply', ←ite_and_mul_zero], |
| 118 | +end |
| 119 | + |
| 120 | +lemma sum_inc_matrix_apply_of_mem_edge_set : e ∈ G.edge_set → ∑ a, G.inc_matrix R a e = 2 := |
| 121 | +begin |
| 122 | + classical, |
| 123 | + refine e.ind _, |
| 124 | + intros a b h, |
| 125 | + rw mem_edge_set at h, |
| 126 | + rw [←nat.cast_two, ←card_doubleton h.ne], |
| 127 | + simp only [inc_matrix_apply', sum_boole, mk_mem_incidence_set_iff, h, true_and], |
| 128 | + congr' 2, |
| 129 | + ext e, |
| 130 | + simp only [mem_filter, mem_univ, true_and, mem_insert, mem_singleton], |
| 131 | +end |
| 132 | + |
| 133 | +lemma sum_inc_matrix_apply_of_not_mem_edge_set (h : e ∉ G.edge_set) : ∑ a, G.inc_matrix R a e = 0 := |
| 134 | +sum_eq_zero $ λ a _, G.inc_matrix_of_not_mem_incidence_set $ λ he, h he.1 |
| 135 | + |
| 136 | +lemma inc_matrix_transpose_mul_diag [decidable_rel G.adj] : |
| 137 | + ((G.inc_matrix R)ᵀ ⬝ G.inc_matrix R) e e = if e ∈ G.edge_set then 2 else 0 := |
| 138 | +begin |
| 139 | + classical, |
| 140 | + simp only [matrix.mul_apply, inc_matrix_apply', transpose_apply, ←ite_and_mul_zero, |
| 141 | + one_mul, sum_boole, and_self], |
| 142 | + split_ifs with h, |
| 143 | + { revert h, |
| 144 | + refine e.ind _, |
| 145 | + intros v w h, |
| 146 | + rw [←nat.cast_two, ←card_doubleton (G.ne_of_adj h)], |
| 147 | + simp [mk_mem_incidence_set_iff, G.mem_edge_set.mp h], |
| 148 | + congr' 2, |
| 149 | + ext u, |
| 150 | + simp, }, |
| 151 | + { revert h, |
| 152 | + refine e.ind _, |
| 153 | + intros v w h, |
| 154 | + simp [mk_mem_incidence_set_iff, G.mem_edge_set.not.mp h], }, |
| 155 | +end |
| 156 | + |
| 157 | +end non_assoc_semiring |
| 158 | + |
| 159 | +section semiring |
| 160 | +variables [fintype (sym2 α)] [semiring R] {a b : α} {e : sym2 α} |
| 161 | + |
| 162 | +lemma inc_matrix_mul_transpose_apply_of_adj (h : G.adj a b) : |
| 163 | + (G.inc_matrix R ⬝ (G.inc_matrix R)ᵀ) a b = (1 : R) := |
| 164 | +begin |
| 165 | + simp_rw [matrix.mul_apply, matrix.transpose_apply, inc_matrix_apply_mul_inc_matrix_apply, |
| 166 | + set.indicator_apply, pi.one_apply, sum_boole], |
| 167 | + convert nat.cast_one, |
| 168 | + convert card_singleton ⟦(a, b)⟧, |
| 169 | + rw [←coe_eq_singleton, coe_filter_univ], |
| 170 | + exact G.incidence_set_inter_incidence_set_of_adj h, |
| 171 | +end |
| 172 | + |
| 173 | +lemma inc_matrix_mul_transpose [fintype α] [decidable_eq α] [decidable_rel G.adj] : |
| 174 | + G.inc_matrix R ⬝ (G.inc_matrix R)ᵀ = λ a b, |
| 175 | + if a = b then G.degree a else if G.adj a b then 1 else 0 := |
| 176 | +begin |
| 177 | + ext a b, |
| 178 | + split_ifs with h h', |
| 179 | + { subst b, |
| 180 | + convert G.inc_matrix_mul_transpose_diag }, |
| 181 | + { exact G.inc_matrix_mul_transpose_apply_of_adj h' }, |
| 182 | + { simp only [matrix.mul_apply, matrix.transpose_apply, |
| 183 | + G.inc_matrix_apply_mul_inc_matrix_apply_of_not_adj h h', sum_const_zero] } |
| 184 | +end |
| 185 | + |
| 186 | +end semiring |
| 187 | +end simple_graph |
0 commit comments