pseudoinverse

\begin{theorem} Let $V$ be a finite-dimensional vector space over a field. Let $A: V \rightarrow V$ be a linear map.

$\exists$ linear map $B: V \rightarrow V$ such that $A B A=A$ and $BAB=B$. \end{theorem} \begin{proof} To show that there exists a linear map $B: V \to V$ such that $A B A = A$, proceed as follows.

Since $V$ is finite-dimensional, the kernel $\operatorname{Ker} A$ has a complement $U$ in $V$, so $V = \operatorname{Ker} A \oplus U$. The restriction $A|_U: U \to \operatorname{Im} A$ is an isomorphism. Let $R: \operatorname{Im} A \to U$ be the inverse of $A|_U$, so $A R = \operatorname{Id}_{\operatorname{Im} A}$.

The image $\operatorname{Im} A$ also has a complement $S$ in $V$, so $V = \operatorname{Im} A \oplus S$.

Define $B: V \to V$ by setting $B|_{\operatorname{Im} A} = R$ and $B|_S = 0$.

To verify $A B A = A$, note that for any $v \in V$, $A B A v = A (B (A v))$. Since $A v \in \operatorname{Im} A$, $B (A v) = R (A v)$, and $A (R (A v)) = (A R) (A v) = A v$. Thus, $A B A = A$.

Next, verify $B A B = B$. For any $v \in V$, write $v = w + s$ with $w \in \operatorname{Im} A$ and $s \in S$. Then $B v = B w + B s = R w + 0 = R w$.

Now, $A (B v) = A (R w) = w$ (since $A R = \operatorname{Id}_{\operatorname{Im} A}$).

Then $B (A (B v)) = B w = R w$.

But $R w =Bv$, so $B A Bv =Bv$ for all $v$, hence $BAB =B$. \end{proof}

import Mathlib.LinearAlgebra.FiniteDimensional.Defs
variable {K V : Type u} [Field K] [AddCommGroup V] [Module K V]
variable (A : V →ₗ[K] V)

open LinearMap Submodule

theorem exists_ABA_eq_A : ∃ (B : V →ₗ[K] V), A.comp (B.comp A) = A := by
  -- 1. Decompose V into ker(A) and a complement W.
  obtain ⟨W, hW⟩ := Submodule.exists_isCompl (ker A)

  -- 2. Define the isomorphism from W to range(A).
  let A_on_W := A.domRestrict W
  let A_W_iso_range := LinearEquiv.ofInjective A_on_W (by
    rw [← ker_eq_bot, ker_domRestrict, eq_bot_iff]
    intro x hx
    apply Subtype.ext
    have : x.val ∈ ker A ⊓ W := ⟨hx, x.prop⟩
    rwa [hW.inf_eq_bot, mem_bot] at this)

  -- 3. Prove that the range of (A restricted to W) is the entire range of A.
  have h_range_eq : range A_on_W = range A := by
    calc
      range A_on_W = map A W := by simp [A_on_W]
      _ = ⊥ ⊔ map A W := by rw [bot_sup_eq]
      _ = map A (ker A) ⊔ map A W := by
          congr; ext y; constructor
          · rintro rfl; use 0; simp
          · rintro ⟨x, hx, rfl⟩; exact hx
      _ = map A (ker A ⊔ W) := by rw [Submodule.map_sup]
      _ = map A ⊤ := by rw [hW.sup_eq_top]
      _ = range A := Submodule.map_top A

  -- 4. Define the pseudo-inverse map B.
  obtain ⟨R_comp, hR_comp⟩ := Submodule.exists_isCompl (range A)

  -- Define the inverse map `f` from range(A) back to W (and then into V).
  let f : range A →ₗ[K] V :=
    (Submodule.subtype W).comp <| (A_W_iso_range.symm.toLinearMap).comp <|
      ((LinearEquiv.ofEq _ _ h_range_eq).symm : range A →ₗ[K] range A_on_W)

  -- Define B by specifying its behavior on `range A` and its complement `R_comp`.
  let B := (ofIsComplProdEquiv hR_comp) (f, 0)

  -- 5. Prove this B satisfies the equation.
  use B
  ext v

  -- Decompose v using projection maps. This version returns elements of the submodule types.
  let v_ker := Submodule.linearProjOfIsCompl (ker A) W hW v
  let v_W := Submodule.linearProjOfIsCompl W (ker A) hW.symm v

  have hv_decomp : v = v_ker + v_W := symm (linear_proj_add_linearProjOfIsCompl_eq_self hW v)
  simp [hv_decomp]

  -- The goal is `A (B (A ↑v_W)) = A ↑v_W`, which is true if `B (A ↑v_W) = ↑v_W`.
  suffices B (A ↑v_W) = ↑v_W by rw [this]

  let y := A ↑v_W
  have hy : y ∈ range A := mem_range_self A ↑v_W
  -- By construction, B applied to an element of `range A` is just our inverse map `f`.
  have B_y_eq_f_y : B y = f ⟨y, hy⟩ := by
    rw [← ofIsCompl_left_apply hR_comp _]
    rfl
  rw [B_y_eq_f_y]

  -- The final goal is to show f(A(v_W)) = v_W.
  -- We apply A_W_iso_range to both sides to simplify the inverses.
  simp [f, A_W_iso_range, A_on_W]
  exact
    LinearEquiv.symm_apply_apply
      (LinearEquiv.ofInjective (A.domRestrict W)
        (Eq.mpr (_root_.id (congrArg (fun _a => _a) (Eq.symm (propext ker_eq_bot))))
          (Eq.mpr (_root_.id (congrArg (fun _a => _a = ⊥) (ker_domRestrict W A)))
            (Eq.mpr (_root_.id (congrArg (fun _a => _a) (propext eq_bot_iff))) fun ⦃x⦄ hx =>
              Subtype.ext
                (have this := ⟨hx, Subtype.prop x⟩;
                Eq.mp (congrArg (fun _a => _a) (propext (mem_bot K)))
                  (Eq.mp (congrArg (fun _a => ↑x ∈ _a) (IsCompl.inf_eq_bot hW)) this))))))
      ((W.linearProjOfIsCompl (ker A) (IsCompl.symm hW)) v)