Skip to content

Commit bf4bf08

Browse files
committed
feat(Combinatorics/SimpleGraph/AdjMatrix): adjacency matrix API (leanprover-community#34601)
1 parent 433f0a4 commit bf4bf08

File tree

1 file changed

+118
-19
lines changed

1 file changed

+118
-19
lines changed

Mathlib/Combinatorics/SimpleGraph/AdjMatrix.lean

Lines changed: 118 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public import Mathlib.LinearAlgebra.Matrix.Trace
1111
public import Mathlib.LinearAlgebra.Matrix.Hadamard
1212

1313
import Mathlib.Algebra.GroupWithZero.Idempotent
14+
import Mathlib.Combinatorics.SimpleGraph.DegreeSum
1415

1516
/-!
1617
# Adjacency Matrices
@@ -46,7 +47,7 @@ open Matrix
4647

4748
open Finset SimpleGraph
4849

49-
variable {V α : Type*}
50+
variable {α V : Type*}
5051

5152
namespace Matrix
5253

@@ -63,6 +64,8 @@ namespace IsAdjMatrix
6364

6465
variable {A : Matrix V V α}
6566

67+
@[simp] protected theorem zero [Zero α] [One α] : (0 : Matrix V V α).IsAdjMatrix where
68+
6669
@[simp]
6770
theorem apply_diag_ne [MulZeroOneClass α] [Nontrivial α] (h : IsAdjMatrix A) (i : V) :
6871
¬A i i = 1 := by simp [h.apply_diag i]
@@ -88,19 +91,22 @@ instance [MulZeroOneClass α] [Nontrivial α] [DecidableEq α] (h : IsAdjMatrix
8891
simp only [toGraph]
8992
infer_instance
9093

94+
@[simp] theorem hadamard_self [MulZeroOneClass α] {A : Matrix V V α} (hA : A.IsAdjMatrix) :
95+
A ⊙ A = A := by ext i j; have := hA.zero_or_one i j; aesop
96+
9197
end IsAdjMatrix
9298

9399
theorem isAdjMatrix_iff_hadamard [DecidableEq V] [MonoidWithZero α]
94100
[IsLeftCancelMulZero α] {A : Matrix V V α} :
95101
A.IsAdjMatrix ↔ (A ⊙ A = A ∧ A.IsSymm ∧ 1 ⊙ A = 0) := by
96102
simp only [hadamard_self_eq_self_iff, IsIdempotentElem.iff_eq_zero_or_one,
97-
one_hadamard_eq_zero_iff, funext_iff, diag]
98-
exact ⟨fun ⟨h1, h2, h3⟩ ↦ ⟨h1, h2, h3⟩, fun ⟨h1, h2, h3⟩ ↦ ⟨h1, h2, h3⟩⟩
103+
one_hadamard_eq_zero_iff, funext_iff, diag, Pi.zero_apply]
104+
grind [IsAdjMatrix]
99105

100106
/-- For `A : Matrix V V α`, `A.compl` is supposed to be the adjacency matrix of
101107
the complement graph of the graph induced by `A.adjMatrix`. -/
102108
def compl [Zero α] [One α] [DecidableEq α] [DecidableEq V] (A : Matrix V V α) : Matrix V V α :=
103-
fun i j => ite (i = j) 0 (ite (A i j = 0) 1 0)
109+
of fun i j if i = j then 0 else if A i j = 0 then 1 else 0
104110

105111
section Compl
106112

@@ -111,8 +117,7 @@ theorem compl_apply_diag [Zero α] [One α] (i : V) : A.compl i i = 0 := by simp
111117

112118
@[simp]
113119
theorem compl_apply [Zero α] [One α] (i j : V) : A.compl i j = 0 ∨ A.compl i j = 1 := by
114-
unfold compl
115-
split_ifs <;> simp
120+
grind [compl, of]
116121

117122
@[simp]
118123
theorem isSymm_compl [Zero α] [One α] (h : A.IsSymm) : A.compl.IsSymm := by
@@ -123,6 +128,13 @@ theorem isSymm_compl [Zero α] [One α] (h : A.IsSymm) : A.compl.IsSymm := by
123128
theorem isAdjMatrix_compl [Zero α] [One α] (h : A.IsSymm) : IsAdjMatrix A.compl :=
124129
{ symm := by simp [h] }
125130

131+
theorem IsAdjMatrix.compl_inj [Zero α] [One α] {A B : Matrix V V α}
132+
(hA : A.IsAdjMatrix) (hB : B.IsAdjMatrix) : A.compl = B.compl ↔ A = B :=
133+
fun h ↦ ext fun i j ↦ by grind [of, congr($h i j), compl, IsAdjMatrix], fun h ↦ h ▸ rfl⟩
134+
135+
@[simp] theorem IsAdjMatrix.compl_compl [Zero α] [One α] {A : Matrix V V α} (hA : A.IsAdjMatrix) :
136+
A.compl.compl = A := by ext; grind [of, compl, IsAdjMatrix]
137+
126138
namespace IsAdjMatrix
127139

128140
variable {A}
@@ -169,10 +181,12 @@ theorem isSymm_adjMatrix [Zero α] [One α] : (G.adjMatrix α).IsSymm :=
169181

170182
variable (α)
171183

184+
@[simp] theorem diag_adjMatrix [Zero α] [One α] : (G.adjMatrix α).diag = 0 := by ext; simp
185+
172186
/-- The adjacency matrix of `G` is an adjacency matrix. -/
173187
@[simp]
174-
theorem isAdjMatrix_adjMatrix [Zero α] [One α] : (G.adjMatrix α).IsAdjMatrix :=
175-
{ zero_or_one := fun i j => by by_cases h : G.Adj i j <;> simp [h] }
188+
theorem isAdjMatrix_adjMatrix [Zero α] [One α] : (G.adjMatrix α).IsAdjMatrix where
189+
zero_or_one := by grind [adjMatrix_apply]
176190

177191
/-- The graph induced by the adjacency matrix of `G` is `G` itself. -/
178192
theorem toGraph_adjMatrix_eq [MulZeroOneClass α] [Nontrivial α] :
@@ -181,18 +195,58 @@ theorem toGraph_adjMatrix_eq [MulZeroOneClass α] [Nontrivial α] :
181195
simp only [IsAdjMatrix.toGraph_adj, adjMatrix_apply, ite_eq_left_iff, zero_ne_one]
182196
apply Classical.not_not
183197

184-
variable {α}
198+
theorem compl_adjMatrix_eq_adjMatrix_compl [DecidableEq V] [DecidableEq α] [Zero α] [One α] :
199+
(G.adjMatrix α).compl = Gᶜ.adjMatrix α := by aesop (add simp [Matrix.compl])
200+
201+
set_option backward.isDefEq.respectTransparency false in
202+
variable {G} in
203+
theorem IsCompl.adjMatrix_add_adjMatrix_eq_adjMatrix_completeGraph [DecidableEq V] [AddZeroClass α]
204+
[One α] {H : SimpleGraph V} [DecidableRel H.Adj] (h : IsCompl G H) :
205+
G.adjMatrix α + H.adjMatrix α = (completeGraph V).adjMatrix α := calc
206+
_ = G.adjMatrix α + Gᶜ.adjMatrix α := by have := h.compl_eq; subst this; congr
207+
_ = _ := by aesop (add simp Matrix.compl)
208+
209+
@[simp] theorem adjMatrix_add_compl_adjMatrix_eq_adjMatrix_completeGraph [DecidableEq V]
210+
[DecidableEq α] [AddZeroClass α] [One α] :
211+
G.adjMatrix α + (G.adjMatrix α).compl = (completeGraph V).adjMatrix α :=
212+
G.compl_adjMatrix_eq_adjMatrix_compl α ▸
213+
isCompl_compl.adjMatrix_add_adjMatrix_eq_adjMatrix_completeGraph α
185214

186215
/-- The sum of the identity, the adjacency matrix, and its complement is the all-ones matrix. -/
187-
theorem one_add_adjMatrix_add_compl_adjMatrix_eq_allOnes [DecidableEq V] [DecidableEq α]
188-
[AddMonoidWithOne α] : 1 + G.adjMatrix α + (G.adjMatrix α).compl = Matrix.of fun _ _ ↦ 1 := by
189-
ext i j
190-
unfold Matrix.compl
191-
rw [of_apply, add_apply, adjMatrix_apply, add_apply, adjMatrix_apply, one_apply]
192-
by_cases h : G.Adj i j
193-
· aesop
194-
· split_ifs <;> simp_all
216+
theorem one_add_adjMatrix_add_compl_adjMatrix_eq_of_one [DecidableEq V] [DecidableEq α]
217+
[AddMonoid α] [One α] : 1 + G.adjMatrix α + (G.adjMatrix α).compl = of 1 := by
218+
aesop (add simp [add_assoc])
219+
220+
@[deprecated (since := "2026-01-30")] alias one_add_adjMatrix_add_compl_adjMatrix_eq_allOnes :=
221+
one_add_adjMatrix_add_compl_adjMatrix_eq_of_one
222+
223+
variable (V)
224+
225+
@[simp] theorem compl_adjMatrix_completeGraph [Zero α] [One α] [DecidableEq α] [DecidableEq V] :
226+
((completeGraph V).adjMatrix α).compl = 0 := by aesop (add simp Matrix.compl)
227+
228+
@[simp] theorem _root_.Matrix.compl_zero [Zero α] [One α] [DecidableEq α] [DecidableEq V] :
229+
(0 : Matrix V V α).compl = (completeGraph V).adjMatrix α := by simp [← IsAdjMatrix.compl_inj]
230+
231+
theorem adjMatrix_completeGraph_eq_of_one_sub_one [AddGroup α] [One α] [DecidableEq V] :
232+
(completeGraph V).adjMatrix α = of 1 - 1 := by ext; simp [one_apply, sub_ite]
233+
234+
theorem _root_.Matrix.compl_zero_eq_of_one_sub_one [AddGroup α] [One α] [DecidableEq V]
235+
[DecidableEq α] : (0 : Matrix V V α).compl = of 1 - 1 := by
236+
simp [adjMatrix_completeGraph_eq_of_one_sub_one]
237+
238+
@[simp] theorem _root_.Matrix.compl_of_one_sub_one [AddGroup α] [One α] [DecidableEq V]
239+
[DecidableEq α] : (of 1 - 1 : Matrix V V α).compl = 0 := by
240+
simp [← adjMatrix_completeGraph_eq_of_one_sub_one]
241+
242+
variable {V}
243+
244+
theorem adjMatrix_hadamard_self [MulZeroOneClass α] :
245+
G.adjMatrix α ⊙ G.adjMatrix α = G.adjMatrix α := by simp
195246

247+
variable {α}
248+
249+
section fintype
196250
variable [Fintype V]
197251

198252
@[simp]
@@ -235,6 +289,13 @@ theorem trace_adjMatrix [AddCommMonoid α] [One α] : Matrix.trace (G.adjMatrix
235289
theorem adjMatrix_mul_self_apply_self [NonAssocSemiring α] (i : V) :
236290
(G.adjMatrix α * G.adjMatrix α) i i = degree G i := by simp [filter_true_of_mem]
237291

292+
variable (R) in
293+
/-- The number of all darts in a simple finite graph is equal to the dot product of
294+
`G.adjMatrix α *ᵥ 1` and `1`. -/
295+
theorem natCast_card_dart_eq_dotProduct [NonAssocSemiring α] :
296+
(Fintype.card G.Dart : α) = adjMatrix α G *ᵥ 1 ⬝ᵥ 1 := by
297+
simp [G.dart_card_eq_sum_degrees, dotProduct_one]
298+
238299
variable {G}
239300

240301
theorem adjMatrix_mulVec_const_apply [NonAssocSemiring α] {a : α} {v : V} :
@@ -266,8 +327,46 @@ theorem adjMatrix_pow_apply_eq_card_walk [DecidableEq V] [Semiring α] (n : ℕ)
266327

267328
theorem dotProduct_mulVec_adjMatrix [NonAssocSemiring α] (x y : V → α) :
268329
x ⬝ᵥ G.adjMatrix α *ᵥ y = ∑ i : V, ∑ j : V, if G.Adj i j then x i * y j else 0 := by
269-
simp only [dotProduct, mulVec, adjMatrix_apply, ite_mul, one_mul, zero_mul, mul_sum, mul_ite,
270-
mul_zero]
330+
simp [dotProduct, mulVec, mul_sum]
331+
332+
end fintype
333+
334+
section hadamard
335+
variable (α) [DecidableEq V] [MulZeroOneClass α]
336+
337+
open Matrix
338+
339+
@[simp] theorem adjMatrix_hadamard_diagonal (d : V → α) :
340+
G.adjMatrix α ⊙ diagonal d = 0 := by simp [hadamard_diagonal]
341+
342+
@[simp] theorem diagonal_hadamard_adjMatrix (d : V → α) :
343+
diagonal d ⊙ G.adjMatrix α = 0 := by simp [diagonal_hadamard]
344+
345+
@[simp] theorem adjMatrix_hadamard_natCast [NatCast α] (a : ℕ) :
346+
G.adjMatrix α ⊙ a.cast = 0 := adjMatrix_hadamard_diagonal _ _ _
347+
348+
@[simp] theorem natCast_hadamard_adjMatrix [NatCast α] (a : ℕ) :
349+
a.cast ⊙ G.adjMatrix α = 0 := diagonal_hadamard_adjMatrix _ _ _
350+
351+
@[simp] theorem adjMatrix_hadamard_ofNat [NatCast α] (a : ℕ) [a.AtLeastTwo] :
352+
G.adjMatrix α ⊙ ofNat(a) = 0 := adjMatrix_hadamard_diagonal _ _ _
353+
354+
@[simp] theorem ofNat_hadamard_adjMatrix [NatCast α] (a : ℕ) [a.AtLeastTwo] :
355+
ofNat(a) ⊙ G.adjMatrix α = 0 := diagonal_hadamard_adjMatrix _ _ _
356+
357+
@[simp] theorem adjMatrix_hadamard_intCast [IntCast α] (a : ℤ) :
358+
G.adjMatrix α ⊙ a.cast = 0 := adjMatrix_hadamard_diagonal _ _ _
359+
360+
@[simp] theorem intCast_hadamard_adjMatrix [IntCast α] (a : ℤ) :
361+
a.cast ⊙ G.adjMatrix α = 0 := diagonal_hadamard_adjMatrix _ _ _
362+
363+
@[simp] theorem adjMatrix_hadamard_one :
364+
G.adjMatrix α ⊙ 1 = 0 := adjMatrix_hadamard_diagonal _ _ _
365+
366+
@[simp] theorem one_hadamard_adjMatrix :
367+
1 ⊙ G.adjMatrix α = 0 := diagonal_hadamard_adjMatrix _ _ _
368+
369+
end hadamard
271370

272371
end SimpleGraph
273372

0 commit comments

Comments
 (0)