File: Mathlib/LinearAlgebra/Matrix/Adjugate.lean

full_name: Matrix.cramerMap
code: /-- `cramerMap A b i` is the determinant of the matrix `A` with column `i` replaced with `b`,
  and thus `cramerMap A b` is the vector output by Cramer's rule on `A` and `b`.

  If `A * x = b` has a unique solution in `x`, `cramerMap A` sends the vector `b` to `A.det • x`.
  Otherwise, the outcome of `cramerMap` is well-defined but not necessarily useful.
-/
def cramerMap (i : n) : α 
goal: α

full_name: Matrix.cramerMap_is_linear
code: theorem cramerMap_is_linear (i : n) : IsLinearMap α fun b => cramerMap A b i 
goal: IsLinearMap α fun b => A.cramerMap b i

full_name: Matrix.cramer_is_linear
code: theorem cramer_is_linear : IsLinearMap α (cramerMap A) 
goal: IsLinearMap α A.cramerMap

full_name: Matrix.cramer
code: /-- `cramer A b i` is the determinant of the matrix `A` with column `i` replaced with `b`,
  and thus `cramer A b` is the vector output by Cramer's rule on `A` and `b`.

  If `A * x = b` has a unique solution in `x`, `cramer A` sends the vector `b` to `A.det • x`.
  Otherwise, the outcome of `cramer` is well-defined but not necessarily useful.
 -/
def cramer (A : Matrix n n α) : (n → α) →ₗ[α] (n → α) 
goal: (n → α) →ₗ[α] n → α

full_name: Matrix.cramer_apply
code: theorem cramer_apply (i : n) : cramer A b i = (A.updateColumn i b).det 
goal: A.cramer b i = (A.updateColumn i b).det

full_name: Matrix.cramer_transpose_apply
code: theorem cramer_transpose_apply (i : n) : cramer Aᵀ b i = (A.updateRow i b).det 
goal: A.transpose.cramer b i = (A.updateRow i b).det

full_name: Matrix.cramer_transpose_row_self
code: theorem cramer_transpose_row_self (i : n) : Aᵀ.cramer (A i) = Pi.single i A.det 
goal: A.transpose.cramer (A i) = Pi.single i A.det

full_name: Matrix.cramer_row_self
code: theorem cramer_row_self (i : n) (h : ∀ j, b j = A j i) : A.cramer b = Pi.single i A.det 
goal: A.cramer b = Pi.single i A.det

full_name: Matrix.cramer_one
code: @[simp]
theorem cramer_one : cramer (1 : Matrix n n α) = 1 
goal: Matrix.cramer 1 = 1

full_name: Matrix.cramer_smul
code: theorem cramer_smul (r : α) (A : Matrix n n α) :
    cramer (r • A) = r ^ (Fintype.card n - 1) • cramer A 
goal: (r • A).cramer = r ^ (Fintype.card n - 1) • A.cramer

full_name: Matrix.cramer_subsingleton_apply
code: @[simp]
theorem cramer_subsingleton_apply [Subsingleton n] (A : Matrix n n α) (b : n → α) (i : n) :
    cramer A b i = b i 
goal: A.cramer b i = b i

full_name: Matrix.cramer_zero
code: theorem cramer_zero [Nontrivial n] : cramer (0 : Matrix n n α) = 0 
goal: Matrix.cramer 0 = 0

full_name: Matrix.sum_cramer
code: /-- Use linearity of `cramer` to take it out of a summation. -/
theorem sum_cramer {β} (s : Finset β) (f : β → n → α) :
    (∑ x ∈ s, cramer A (f x)) = cramer A (∑ x ∈ s, f x) 
goal: ∑ x ∈ s, A.cramer (f x) = A.cramer (∑ x ∈ s, f x)

full_name: Matrix.sum_cramer_apply
code: /-- Use linearity of `cramer` and vector evaluation to take `cramer A _ i` out of a summation. -/
theorem sum_cramer_apply {β} (s : Finset β) (f : n → β → α) (i : n) :
    (∑ x ∈ s, cramer A (fun j => f j x) i) = cramer A (fun j : n => ∑ x ∈ s, f j x) i 
goal: ∑ x ∈ s, A.cramer (fun j => f j x) i = A.cramer (fun j => ∑ x ∈ s, f j x) i

full_name: Matrix.cramer_submatrix_equiv
code: theorem cramer_submatrix_equiv (A : Matrix m m α) (e : n ≃ m) (b : n → α) :
    cramer (A.submatrix e e) b = cramer A (b ∘ e.symm) ∘ e 
goal: (A.submatrix ⇑e ⇑e).cramer b = A.cramer (b ∘ ⇑e.symm) ∘ ⇑e

full_name: Matrix.cramer_reindex
code: theorem cramer_reindex (e : m ≃ n) (A : Matrix m m α) (b : n → α) :
    cramer (reindex e e A) b = cramer A (b ∘ e) ∘ e.symm 
goal: ((Matrix.reindex e e) A).cramer b = A.cramer (b ∘ ⇑e) ∘ ⇑e.symm

full_name: Matrix.adjugate
code: /-- The adjugate matrix is the transpose of the cofactor matrix.

  Typically, the cofactor matrix is defined by taking minors,
  i.e. the determinant of the matrix with a row and column removed.
  However, the proof of `mul_adjugate` becomes a lot easier if we use the
  matrix replacing a column with a basis vector, since it allows us to use
  facts about the `cramer` map.
-/
def adjugate (A : Matrix n n α) : Matrix n n α 
goal: Matrix n n α

full_name: Matrix.adjugate_def
code: theorem adjugate_def (A : Matrix n n α) : adjugate A = of fun i => cramer Aᵀ (Pi.single i 1) 
goal: A.adjugate = Matrix.of fun i => A.transpose.cramer (Pi.single i 1)

full_name: Matrix.adjugate_apply
code: theorem adjugate_apply (A : Matrix n n α) (i j : n) :
    adjugate A i j = (A.updateRow j (Pi.single i 1)).det 
goal: A.adjugate i j = (A.updateRow j (Pi.single i 1)).det

full_name: Matrix.adjugate_transpose
code: theorem adjugate_transpose (A : Matrix n n α) : (adjugate A)ᵀ = adjugate Aᵀ 
goal: A.adjugate.transpose = A.transpose.adjugate

full_name: Matrix.adjugate_submatrix_equiv_self
code: @[simp]
theorem adjugate_submatrix_equiv_self (e : n ≃ m) (A : Matrix m m α) :
    adjugate (A.submatrix e e) = (adjugate A).submatrix e e 
goal: (A.submatrix ⇑e ⇑e).adjugate = A.adjugate.submatrix ⇑e ⇑e

full_name: Matrix.adjugate_reindex
code: theorem adjugate_reindex (e : m ≃ n) (A : Matrix m m α) :
    adjugate (reindex e e A) = reindex e e (adjugate A) 
goal: ((Matrix.reindex e e) A).adjugate = (Matrix.reindex e e) A.adjugate

full_name: Matrix.cramer_eq_adjugate_mulVec
code: /-- Since the map `b ↦ cramer A b` is linear in `b`, it must be multiplication by some matrix. This
matrix is `A.adjugate`. -/
theorem cramer_eq_adjugate_mulVec (A : Matrix n n α) (b : n → α) :
    cramer A b = A.adjugate *ᵥ b 
goal: A.cramer b = A.adjugate.mulVec b

full_name: Matrix.mul_adjugate_apply
code: theorem mul_adjugate_apply (A : Matrix n n α) (i j k) :
    A i k * adjugate A k j = cramer Aᵀ (Pi.single k (A i k)) j 
goal: A i k * A.adjugate k j = A.transpose.cramer (Pi.single k (A i k)) j

full_name: Matrix.mul_adjugate
code: theorem mul_adjugate (A : Matrix n n α) : A * adjugate A = A.det • (1 : Matrix n n α) 
goal: A * A.adjugate = A.det • 1

full_name: Matrix.adjugate_mul
code: theorem adjugate_mul (A : Matrix n n α) : adjugate A * A = A.det • (1 : Matrix n n α) 
goal: A.adjugate * A = A.det • 1

full_name: Matrix.adjugate_smul
code: theorem adjugate_smul (r : α) (A : Matrix n n α) :
    adjugate (r • A) = r ^ (Fintype.card n - 1) • adjugate A 
goal: (r • A).adjugate = r ^ (Fintype.card n - 1) • A.adjugate

full_name: Matrix.mulVec_cramer
code: /-- A stronger form of **Cramer's rule** that allows us to solve some instances of `A * x = b` even
if the determinant is not a unit. A sufficient (but still not necessary) condition is that `A.det`
divides `b`. -/
@[simp]
theorem mulVec_cramer (A : Matrix n n α) (b : n → α) : A *ᵥ cramer A b = A.det • b 
goal: A.mulVec (A.cramer b) = A.det • b

full_name: Matrix.adjugate_subsingleton
code: theorem adjugate_subsingleton [Subsingleton n] (A : Matrix n n α) : adjugate A = 1 
goal: A.adjugate = 1

full_name: Matrix.adjugate_eq_one_of_card_eq_one
code: theorem adjugate_eq_one_of_card_eq_one {A : Matrix n n α} (h : Fintype.card n = 1) :
    adjugate A = 1 
goal: A.adjugate = 1

full_name: Matrix.adjugate_zero
code: @[simp]
theorem adjugate_zero [Nontrivial n] : adjugate (0 : Matrix n n α) = 0 
goal: Matrix.adjugate 0 = 0

full_name: Matrix.adjugate_one
code: @[simp]
theorem adjugate_one : adjugate (1 : Matrix n n α) = 1 
goal: Matrix.adjugate 1 = 1

full_name: Matrix.adjugate_diagonal
code: @[simp]
theorem adjugate_diagonal (v : n → α) :
    adjugate (diagonal v) = diagonal fun i => ∏ j ∈ Finset.univ.erase i, v j 
goal: (Matrix.diagonal v).adjugate = Matrix.diagonal fun i => ∏ j ∈ Finset.univ.erase i, v j

full_name: RingHom.map_adjugate
code: theorem _root_.RingHom.map_adjugate {R S : Type*} [CommRing R] [CommRing S] (f : R →+* S)
    (M : Matrix n n R) : f.mapMatrix M.adjugate = Matrix.adjugate (f.mapMatrix M) 
goal: f.mapMatrix M.adjugate = (f.mapMatrix M).adjugate

full_name: AlgHom.map_adjugate
code: theorem _root_.AlgHom.map_adjugate {R A B : Type*} [CommSemiring R] [CommRing A] [CommRing B]
    [Algebra R A] [Algebra R B] (f : A →ₐ[R] B) (M : Matrix n n A) :
    f.mapMatrix M.adjugate = Matrix.adjugate (f.mapMatrix M) 
goal: f.mapMatrix M.adjugate = (f.mapMatrix M).adjugate

full_name: Matrix.det_adjugate
code: theorem det_adjugate (A : Matrix n n α) : (adjugate A).det = A.det ^ (Fintype.card n - 1) 
goal: A.adjugate.det = A.det ^ (Fintype.card n - 1)

full_name: Matrix.adjugate_fin_zero
code: @[simp]
theorem adjugate_fin_zero (A : Matrix (Fin 0) (Fin 0) α) : adjugate A = 0 
goal: A.adjugate = 0

full_name: Matrix.adjugate_fin_one
code: @[simp]
theorem adjugate_fin_one (A : Matrix (Fin 1) (Fin 1) α) : adjugate A = 1 
goal: A.adjugate = 1

full_name: Matrix.adjugate_fin_succ_eq_det_submatrix
code: theorem adjugate_fin_succ_eq_det_submatrix {n : ℕ} (A : Matrix (Fin n.succ) (Fin n.succ) α) (i j) :
    adjugate A i j = (-1) ^ (j + i : ℕ) * det (A.submatrix j.succAbove i.succAbove) 
goal: A.adjugate i j = (-1) ^ (↑j + ↑i) * (A.submatrix j.succAbove i.succAbove).det

full_name: Matrix.adjugate_fin_two
code: theorem adjugate_fin_two (A : Matrix (Fin 2) (Fin 2) α) :
    adjugate A = !![A 1 1, -A 0 1; -A 1 0, A 0 0] 
goal: A.adjugate = !![A 1 1, -A 0 1; -A 1 0, A 0 0]

full_name: Matrix.adjugate_fin_two_of
code: @[simp]
theorem adjugate_fin_two_of (a b c d : α) : adjugate !![a, b; c, d] = !![d, -b; -c, a] 
goal: !![a, b; c, d].adjugate = !![d, -b; -c, a]

full_name: Matrix.adjugate_fin_three
code: theorem adjugate_fin_three (A : Matrix (Fin 3) (Fin 3) α) :
    adjugate A =
    !![A 1 1 * A 2 2 - A 1 2 * A 2 1,
      -(A 0 1 * A 2 2) + A 0 2 * A 2 1,
      A 0 1 * A 1 2 - A 0 2 * A 1 1;
      -(A 1 0 * A 2 2) + A 1 2 * A 2 0,
      A 0 0 * A 2 2 - A 0 2 * A 2 0,
      -(A 0 0 * A 1 2) + A 0 2 * A 1 0;
      A 1 0 * A 2 1 - A 1 1 * A 2 0,
      -(A 0 0 * A 2 1) + A 0 1 * A 2 0,
      A 0 0 * A 1 1 - A 0 1 * A 1 0] 
goal: A.adjugate =
  !![A 1 1 * A 2 2 - A 1 2 * A 2 1, -(A 0 1 * A 2 2) + A 0 2 * A 2 1, A 0 1 * A 1 2 - A 0 2 * A 1 1;
    -(A 1 0 * A 2 2) + A 1 2 * A 2 0, A 0 0 * A 2 2 - A 0 2 * A 2 0, -(A 0 0 * A 1 2) + A 0 2 * A 1 0;
    A 1 0 * A 2 1 - A 1 1 * A 2 0, -(A 0 0 * A 2 1) + A 0 1 * A 2 0, A 0 0 * A 1 1 - A 0 1 * A 1 0]

full_name: Matrix.adjugate_fin_three_of
code: @[simp]
theorem adjugate_fin_three_of (a b c d e f g h i : α) :
    adjugate !![a, b, c; d, e, f; g, h, i] =
      !![  e * i  - f * h, -(b * i) + c * h,   b * f  - c * e;
         -(d * i) + f * g,   a * i  - c * g, -(a * f) + c * d;
           d * h  - e * g, -(a * h) + b * g,   a * e  - b * d] 
goal: !![a, b, c; d, e, f; g, h, i].adjugate =
  !![e * i - f * h, -(b * i) + c * h, b * f - c * e;
    -(d * i) + f * g, a * i - c * g, -(a * f) + c * d;
    d * h - e * g, -(a * h) + b * g, a * e - b * d]

full_name: Matrix.det_eq_sum_mul_adjugate_row
code: theorem det_eq_sum_mul_adjugate_row (A : Matrix n n α) (i : n) :
    det A = ∑ j : n, A i j * adjugate A j i 
goal: A.det = ∑ j : n, A i j * A.adjugate j i

full_name: Matrix.det_eq_sum_mul_adjugate_col
code: theorem det_eq_sum_mul_adjugate_col (A : Matrix n n α) (j : n) :
    det A = ∑ i : n, A i j * adjugate A j i 
goal: A.det = ∑ i : n, A i j * A.adjugate j i

full_name: Matrix.adjugate_conjTranspose
code: theorem adjugate_conjTranspose [StarRing α] (A : Matrix n n α) : A.adjugateᴴ = adjugate Aᴴ 
goal: A.adjugate.conjTranspose = A.conjTranspose.adjugate

full_name: Matrix.isRegular_of_isLeftRegular_det
code: theorem isRegular_of_isLeftRegular_det {A : Matrix n n α} (hA : IsLeftRegular A.det) :
    IsRegular A 
goal: IsRegular A

full_name: Matrix.adjugate_mul_distrib_aux
code: theorem adjugate_mul_distrib_aux (A B : Matrix n n α) (hA : IsLeftRegular A.det)
    (hB : IsLeftRegular B.det) : adjugate (A * B) = adjugate B * adjugate A 
goal: (A * B).adjugate = B.adjugate * A.adjugate

full_name: Matrix.adjugate_mul_distrib
code: /-- Proof follows from "The trace Cayley-Hamilton theorem" by Darij Grinberg, Section 5.3
-/
theorem adjugate_mul_distrib (A B : Matrix n n α) : adjugate (A * B) = adjugate B * adjugate A 
goal: (A * B).adjugate = B.adjugate * A.adjugate

full_name: Matrix.adjugate_pow
code: @[simp]
theorem adjugate_pow (A : Matrix n n α) (k : ℕ) : adjugate (A ^ k) = adjugate A ^ k 
goal: (A ^ k).adjugate = A.adjugate ^ k

full_name: Matrix.det_smul_adjugate_adjugate
code: theorem det_smul_adjugate_adjugate (A : Matrix n n α) :
    det A • adjugate (adjugate A) = det A ^ (Fintype.card n - 1) • A 
goal: A.det • A.adjugate.adjugate = A.det ^ (Fintype.card n - 1) • A

full_name: Matrix.adjugate_adjugate
code: /-- Note that this is not true for `Fintype.card n = 1` since `1 - 2 = 0` and not `-1`. -/
theorem adjugate_adjugate (A : Matrix n n α) (h : Fintype.card n ≠ 1) :
    adjugate (adjugate A) = det A ^ (Fintype.card n - 2) • A 
goal: A.adjugate.adjugate = A.det ^ (Fintype.card n - 2) • A

full_name: Matrix.adjugate_adjugate'
code: /-- A weaker version of `Matrix.adjugate_adjugate` that uses `Nontrivial`. -/
theorem adjugate_adjugate' (A : Matrix n n α) [Nontrivial n] :
    adjugate (adjugate A) = det A ^ (Fintype.card n - 2) • A 
goal: A.adjugate.adjugate = A.det ^ (Fintype.card n - 2) • A