Appearance
C10 — Linear Algebra: Summary Notes
Table of Contents
- Part I — Vector Spaces, Linear Maps, and Products (S01)
- Part II — Submodules, Linear Maps, and Quotient Spaces (S02)
- Part III — Endomorphisms (S03)
- Part IV — Bases (S04)
Merged notes for Chapter 10 of Mathematics in Lean, generated from the comments in C10-S01.lean–C10-S04.lean. The individual section notes (S10-1.md, S10-2.md, S10-3.md, S10-4.md) remain available alongside this file.
Part I — Vector Spaces, Linear Maps, and Products (S01)
Summary generated from the comments in C10-S01.lean.
Vector Spaces as Modules
A vector space V over a field K is a special case of a module, instantiated as Module K V:
lean
variable {K : Type*} [Field K] {V : Type*} [AddCommGroup V] [Module K V]Class in Module | Instantiated by (vector space) |
|---|---|
AddCommMonoid (the object) | AddCommGroup V |
Semiring (the scalars) | Field K |
NOTE
Semiring is a Ring without the inverse property for + in AddCommMonoid. Upgrading the scalars from Semiring to Field and the object from AddCommMonoid to AddCommGroup is exactly what turns a module into a vector space.
Distribution property
Scalar multiplication • distributes over + on both sides — the operator • defined in Module describes the interaction between the AddCommMonoid object and the Semiring scalars:
| Lemma | Statement |
|---|---|
smul_add | a • (u + v) = a • u + a • v |
add_smul | (a + b) • u = a • u + b • u |
Commutativity property
Since Field is commutative, scalar multiplication is commutative in the scalars:
smul_comm:a • b • u = b • a • u
Module over ideals/submodules
The following somewhat surprising instance holds:
lean
example {R M : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] :
Module (Ideal R) (Submodule R M) :=
inferInstanceModule (Ideal R) (Submodule R M) holds because:
Submodule R Mis itself aModule, instantiating theAddCommMonoidthatModuleextends.Ideal Ris aCommSemiring, instantiating the scalarSemiring(sinceCommSemiringextendsSemiring).
Module over Ring vs. Semiring
| Scalars | Object required | Why |
|---|---|---|
Ring R | AddCommGroup M | the object of a Ring is an AddCommGroup |
Semiring R | AddCommMonoid M | the object of a Semiring is an AddCommMonoid |
Over a Ring the module automatically has additive inverses; over a Semiring it does not.
Linear Maps
Let W be another vector space over the same field K. A linear map φ : V →ₗ[K] W satisfies two properties:
| Property | Lemma | Statement |
|---|---|---|
| Homogeneity | map_smul | φ (a • v) = a • φ v |
| Additivity | map_add | φ (v + w) = φ v + φ w |
Linear maps form a vector space
V →ₗ[K] W is itself a vector space, satisfying:
0 ∈ V →ₗ[K] W— the zero map sending everything inVto0inW.∀ x y ∈ V →ₗ[K] W, x + y ∈ V →ₗ[K] W— addition closure.∀ a ∈ K, x ∈ V →ₗ[K] W, a • x ∈ V →ₗ[K] W— scalar multiplication closure.
For example, linear combinations of linear maps are linear maps:
lean
#check (2 • φ + ψ : V →ₗ[K] W)Composition
∘ₗ composes linear maps into another linear map. The two spellings are equivalent:
lean
variable (θ : W →ₗ[K] V)
#check (φ.comp θ : W →ₗ[K] W)
#check (φ ∘ₗ θ : W →ₗ[K] W)Constructing a linear map from scratch
Example: the homothety toFun v := 3 • v as a term of V →ₗ[K] V:
lean
example : V →ₗ[K] V where
toFun v := 3 • v
map_add' _ _ := smul_add ..
map_smul' _ _ := smul_comm ..The two proof obligations are:
map_add':toFun (a + b) = toFun a + toFun b, i.e.3 • (a + b) = 3 • a + 3 • b, proved bysmul_add ...map_smul':toFun (a • b) = a • toFun b, i.e.3 • (a • b) = a • (3 • b), proved bysmul_comm ...
Internal vs. user-facing lemmas
| Lemma | Kind | Statement |
|---|---|---|
φ.map_add' | internal proposition | ∀ x y : V, φ.toFun (x + y) = φ.toFun x + φ.toFun y |
φ.map_add | derived, user-facing | ∀ x y : V, φ (x + y) = φ x + φ y |
map_add φ is the same as φ.map_add — dot notation and first-argument application coincide.
lsmul
LinearMap.lsmul K V : K →ₗ[K] V →ₗ[K] V turns scalar multiplication into a bilinear map; partially applied, LinearMap.lsmul K V 3 : V →ₗ[K] V is the homothety v ↦ 3 • v.
lean
#check (LinearMap.lsmul K V : K →ₗ[K] V →ₗ[K] V)
#check (LinearMap.lsmul K V 3 : V →ₗ[K] V)Linear Equivalence
A linear equivalence f : V ≃ₗ[K] W is a bijective linear map bundled with its (also linear) inverse.
- Composing with the inverse gives the identity:lean
example (f : V ≃ₗ[K] W) : f ≪≫ₗ f.symm = LinearEquiv.refl K V := f.self_trans_symm - A bijective linear map upgrades to a linear equivalence:lean
noncomputable example (f : V →ₗ[K] W) (h : Function.Bijective f) : V ≃ₗ[K] W := .ofBijective f h
Binary Products
Throughout this section, V, W, U, T are vector spaces over the same field K.
Projection maps
lean
example : V × W →ₗ[K] V := LinearMap.fst K V W -- first projection
example : V × W →ₗ[K] W := LinearMap.snd K V W -- second projectionUniversal property of the product
Given φ : U →ₗ[K] V and ψ : U →ₗ[K] W, LinearMap.prod φ ψ : U →ₗ[K] V × W is the unique map such that:
lean
example (φ : U →ₗ[K] V) (ψ : U →ₗ[K] W) : U →ₗ[K] V × W := LinearMap.prod φ ψ
example (φ : U →ₗ[K] V) (ψ : U →ₗ[K] W) : LinearMap.fst K V W ∘ₗ LinearMap.prod φ ψ = φ := rfl
example (φ : U →ₗ[K] V) (ψ : U →ₗ[K] W) : LinearMap.snd K V W ∘ₗ LinearMap.prod φ ψ = ψ := rflBoth equations hold by rfl — the product map does the expected thing on each component, definitionally.
Parallel combination (prodMap)
φ.prodMap ψ : (V × W) →ₗ[K] (U × T) combines φ : V →ₗ[K] U and ψ : W →ₗ[K] T in parallel:
lean
example (φ : V →ₗ[K] U) (ψ : W →ₗ[K] T) :
φ.prodMap ψ = (φ ∘ₗ .fst K V W).prod (ψ ∘ₗ .snd K V W) := rflInclusion maps
lean
example : V →ₗ[K] V × W := LinearMap.inl K V W -- first inclusion
example : W →ₗ[K] V × W := LinearMap.inr K V W -- second inclusionUniversal property of the sum (coproduct)
Given φ : V →ₗ[K] U and ψ : W →ₗ[K] U, φ.coprod ψ : V × W →ₗ[K] U is the unique map such that:
| Lemma | Statement |
|---|---|
LinearMap.coprod_inl | φ.coprod ψ ∘ₗ LinearMap.inl K V W = φ |
LinearMap.coprod_inr | φ.coprod ψ ∘ₗ LinearMap.inr K V W = ψ |
Concretely, the coproduct map adds the two images:
lean
example (φ : V →ₗ[K] U) (ψ : W →ₗ[K] U) (v : V) (w : W) :
φ.coprod ψ (v, w) = φ v + ψ w := rflTIP
In the category of vector spaces, the binary product and coproduct coincide: the same object V × W is universal in both directions, which is why this section can discuss projections and inclusions side by side.
Vector Families (DirectSum)
V : ι → Type* is a family of vector spaces over K indexed by ι (with DecidableEq ι):
lean
variable {ι : Type*} [DecidableEq ι]
(V : ι → Type*) [∀ i, AddCommGroup (V i)] [∀ i, Module K (V i)]Direct sum (finite support)
Given a family of linear maps φ : Π i, (V i →ₗ[K] W), assemble them into a single map from the direct sum:
lean
example (φ : Π i, (V i →ₗ[K] W)) : (⨁ i, V i) →ₗ[K] W :=
DirectSum.toModule K ι W φThis is the universal coproduct of a family of linear maps — the infinitary generalization of coprod.
Product (infinite support)
Given a family of linear maps φ : Π i, (W →ₗ[K] V i), assemble them into a single map into the product:
lean
example (φ : Π i, (W →ₗ[K] V i)) : W →ₗ[K] (Π i, V i) :=
LinearMap.pi φThis is the universal product of a family of linear maps — the infinitary generalization of prod.
Projection, inclusion, and single
| Map | Type | Role |
|---|---|---|
LinearMap.proj i | (Π j, V j) →ₗ[K] V i | universal projection out of the product |
DirectSum.lof K ι V i | V i →ₗ[K] (⨁ i, V i) | universal inclusion into the direct sum |
LinearMap.single K V i | V i →ₗ[K] (Π i, V i) | inclusion into the product: x ↦ (fun j => if j = i then x else 0) |
Sum vs. product
There is always a linear map (Π j, V j) →ₗ[K] (⨁ i, V i), since (Π j, V j) →ₗ[K] V i →ₗ[K] (⨁ i, V i).
IMPORTANT
Elements of ⨁ i, V i are finitely supported tuples, while elements of Π i, V i may have infinite support — so in general only one direction exists. When ι is a Fintype, every tuple is finitely supported, and the two coincide:
lean
example [Fintype ι] : (⨁ i, V i) ≃ₗ[K] (Π i, V i) :=
linearEquivFunOnFintype K ι VPart II — Submodules, Linear Maps, and Quotient Spaces (S02)
Summary generated from the comments in C10-S02.lean.
Throughout, V is a vector space over a field K:
lean
variable {K : Type*} [Field K] {V : Type*} [AddCommGroup V] [Module K V]Submodules (Subspaces)
Closure properties
A submodule U : Submodule K V is closed under the two vector-space operations:
| Closure | Lemma | Statement |
|---|---|---|
| addition | U.add_mem | x ∈ U → y ∈ U → x + y ∈ U |
| scalar multiplication | U.smul_mem | a ∈ K → x ∈ U → a • x ∈ U |
Example: ℝ as a submodule of ℂ
Submodule ℝ ℂ instantiates the scalar Semiring with ℝ (a field) and the Module object with ℂ (a vector space over ℝ). It is built from four fields:
lean
noncomputable example : Submodule ℝ ℂ where
carrier := Set.range ((↑) : ℝ → ℂ)
add_mem' := by
rintro _ _ ⟨n, rfl⟩ ⟨m, rfl⟩
use n + m
simp
zero_mem' := by
use 0
simp
smul_mem' := by
rintro c - ⟨a, rfl⟩
use c*a
simp| Field | Role | Proof idea |
|---|---|---|
carrier | the underlying set, here Set.range ((↑) : ℝ → ℂ) — the image of the coercion ℝ → ℂ | since the ambient module is ℂ, the carrier must be a subset of ℂ, hence the coercion |
add_mem' | closure under + | destruct x, y ∈ carrier as ⟨n, rfl⟩, ⟨m, rfl⟩ (i.e. x = ↑n, y = ↑m), witness x + y = ↑(n + m), close with simp since (↑) preserves addition |
zero_mem' | 0 ∈ carrier | witness 0 = ↑0, since (↑) preserves zero |
smul_mem' | closure under • | destruct x ∈ carrier as ⟨a, rfl⟩, witness c • ↑a = ↑(c * a), since (↑) preserves scalar multiplication |
NOTE
The coercion (↑) : ℝ → ℂ behaves like a linear map ℝ →ₗ[ℝ] ℂ here — it preserves +, 0, and • — which is exactly why simp can close each obligation.
Preimage of a submodule under a linear map
Given φ : V →ₗ[K] W and H : Submodule K W, the preimage φ ⁻¹' H is a submodule of V:
Full definition (click to expand)
lean
def preimage {W : Type*} [AddCommGroup W] [Module K W] (φ : V →ₗ[K] W) (H : Submodule K W) :
Submodule K V where
carrier := φ ⁻¹' H
zero_mem' := by
rw [Set.mem_preimage, LinearMap.map_zero]
exact Submodule.zero_mem H
add_mem' := by
rintro a b ha hb
rw [Set.mem_preimage, LinearMap.map_add] at *
exact Submodule.add_mem H ha hb
smul_mem' := by
rintro c x hx
rw [Set.mem_preimage, LinearMap.map_smul] at *
exact Submodule.smul_mem H c hxEach obligation follows the same pattern: rewrite membership in the preimage via Set.mem_preimage (x ∈ φ⁻¹' H ↔ φ x ∈ H), push φ through +/0/• because φ is linear, then close using the corresponding closure lemma for H.
A submodule is itself a vector space
A submodule U of V is a vector space over the same field K, in two equivalent phrasings:
lean
example (U : Submodule K V) : Module K U := inferInstance
example (U : Submodule K V) : Module K {x : V // x ∈ U} := inferInstanceU (as a Submodule K V) and the subtype {x : V // x ∈ U} carry the same Module K instance.
Lattice Operations on Submodules
Intersection (⊓)
The intersection of two submodules is literally the intersection of their underlying sets:
lean
example (H H' : Submodule K V) :
((H ⊓ H' : Submodule K V) : Set V) = (H : Set V) ∩ (H' : Set V) := rflUnion / span (⊔)
WARNING
Unlike ⊓, the set-theoretic union of two submodules is not generally closed under +/•.
So ⊔ is instead defined as the span of the set union:
lean
example (H H' : Submodule K V) :
((H ⊔ H' : Submodule K V) : Set V) = Submodule.span K ((H : Set V) ∪ (H' : Set V)) := by
simp [Submodule.span_union]Top (⊤) and bottom (⊥)
⊤ : Submodule K Vis the whole space:x ∈ (⊤ : Submodule K V)holds trivially for everyx.⊥ : Submodule K Vis the zero subspace:x ∈ (⊥ : Submodule K V) ↔ x = 0(Submodule.mem_bot).
Complementary submodules (IsCompl)
If U and V' are complementary (IsCompl U V'), they decompose the ambient space: they span it, and they only meet at 0.
lean
example (U V' : Submodule K V) (h : IsCompl U V') : U ⊔ V' = ⊤ := h.sup_eq_top
example (U V' : Submodule K V) (h : IsCompl U V') : U ⊓ V' = ⊥ := h.inf_eq_botInternal direct sum (DirectSum.IsInternal)
DirectSum.IsInternal U (for a family U : ι → Submodule K V, with DecidableEq ι) says V decomposes as the internal direct sum of the U i, i.e. (⨁ i, U i) ≃ₗ[K] V. Concretely this means:
⊔ i, U i = ⊤— the subspaces together span the whole space, andU i ⊓ U j = ⊥fori ≠ j— the subspaces pairwise intersect only at zero.
lean
example (U : ι → Submodule K V) (h : DirectSum.IsInternal U) :
⨆ i, U i = ⊤ := h.submodule_iSup_eq_top
example (U : ι → Submodule K V) (h : DirectSum.IsInternal U) {i j : ι} (hij : i ≠ j) :
U i ⊓ U j = ⊥ :=
(h.submodule_iSupIndep.pairwiseDisjoint hij).eq_bot
noncomputable example (U : ι → Submodule K V) (h : DirectSum.IsInternal U) :
(⨁ i, U i) ≃ₗ[K] V :=
LinearEquiv.ofBijective (coeLinearMap U) hDirectSum.isInternal_submodule_iff_iSupIndep_and_iSup_eq_top packages both conditions above as an iff characterization of IsInternal.
Span as the smallest containing submodule
lean
example {s : Set V} (E : Submodule K V) : Submodule.span K s ≤ E ↔ s ⊆ E :=
Submodule.span_le
example : GaloisInsertion (Submodule.span K) ((↑) : Submodule K V → Set V) :=
Submodule.gi K VSubmodule.span_le says span K s is the smallest submodule containing s. Submodule.gi packages span and the coercion Submodule K V → Set V as a Galois insertion.
Decomposing an element of S ⊔ T
Every element of S ⊔ T splits as a sum of an element of S and an element of T:
The key idea: rewrite the problem of S ⊔ T as the problem of Submodule.span K (↑S ∪ ↑T) (via Submodule.span_eq and Submodule.span_union), then induct with Submodule.span_induction.
Proof walkthrough (click to expand)
lean
example {S T : Submodule K V} {x : V} (h : x ∈ S ⊔ T) :
∃ s ∈ S, ∃ t ∈ T, x = s + t := by
rw [← S.span_eq, ← T.span_eq, ← Submodule.span_union] at h
induction h using Submodule.span_induction with
| mem y h =>
rcases h with (y_in_S | y_in_T)
· use y, y_in_S, 0, T.zero_mem; simp
· use 0, S.zero_mem, y, y_in_T; simp
| zero =>
use 0, S.zero_mem, 0, T.zero_mem; simp
| add x y hx hy hx' hy' =>
rcases hx' with ⟨sx, sx_in_S, tx, tx_in_T, rfl⟩
rcases hy' with ⟨sy, sy_in_S, ty, ty_in_T, rfl⟩
use sx + sy, S.add_mem sx_in_S sy_in_S, tx + ty, T.add_mem tx_in_T ty_in_T
module
| smul a x hx hx' =>
rcases hx' with ⟨sx, sx_in_S, tx, tx_in_T, rfl⟩
use a • sx, S.smul_mem a sx_in_S, a • tx, T.smul_mem a tx_in_T
simp- Rewrite.
← S.span_eqand← T.span_eqturnS,Tinto spans of their carrier sets, and← Submodule.span_unionmerges them:h : x ∈ Submodule.span K (↑S ∪ ↑T). Notespan_eqexplicitly uses the coercion(↑) : Submodule K V → Set V. - Induct over the span with
Submodule.span_induction, which has four cases:mem:y ∈ ↑S ∪ ↑Tdirectly — pick(y, 0)or(0, y)depending on the side.zero: pick(0, 0).add: from decompositions ofxandy, build the decomposition ofx + y; themoduletactic discharges the algebra.smul: from a decomposition ofx, build one fora • x.
Linear Maps Between Vector Spaces
Let φ : V →ₗ[K] W be a linear map between vector spaces V, W over K.
Image (map) and preimage (comap) of a submodule
lean
variable (E : Submodule K V) in
#check (Submodule.map φ E : Submodule K W)
variable (F : Submodule K W) in
#check (Submodule.comap φ F : Submodule K V)Submodule.map φ E— the image of a subspaceE ≤ Vunderφ.Submodule.comap φ F— the preimage of a subspaceF ≤ Wunderφ.
Range and kernel, expressed via map/comap
Conceptually, range/kernel and image/preimage are the same idea, but in Lean they are defined differently:
lean
example : LinearMap.range φ = .map φ ⊤ := LinearMap.range_eq_map φ
example : LinearMap.ker φ = .comap φ ⊥ := Submodule.comap_bot φ -- or `rfl`- range = image of the top subspace
⊤underφ. - kernel = preimage of the bottom subspace
⊥underφ.
Injectivity and surjectivity criteria
lean
example : Injective φ ↔ ker φ = ⊥ := ker_eq_bot.symm
example : Surjective φ ↔ range φ = ⊤ := range_eq_top.symmMembership lemmas
| Lemma | Statement |
|---|---|
Submodule.mem_map_of_mem | if x ∈ E ≤ V then φ x ∈ Submodule.map φ E |
Submodule.mem_map | y ∈ Submodule.map φ E ↔ ∃ x ∈ E, φ x = y |
Submodule.mem_comap | x ∈ Submodule.comap φ F ↔ φ x ∈ F |
Galois connection: map φ E ≤ F ↔ E ≤ comap φ F
The image of E lands inside F exactly when E lands inside the preimage of F:
Proof walkthrough (click to expand)
lean
example (E : Submodule K V) (F : Submodule K W) :
Submodule.map φ E ≤ F ↔ E ≤ Submodule.comap φ F := by
constructor
· rintro h x x_in_E
specialize h ⟨x, x_in_E, rfl⟩
exact h
· rintro h _ ⟨x, x_in_E, rfl⟩
rcases h x_in_E with h1
exact h1- (
→) anyx ∈ Egivesφ x ∈ Submodule.map φ E, sohforcesφ x ∈ F, i.e.x ∈ comap φ F. - (
←) anyy ∈ Submodule.map φ Eisφ xfor somex ∈ E, andh : E ≤ comap φ Fgivesφ x ∈ F.
Quotient Spaces
Let E : Submodule K V be a subspace of V.
The quotient is a vector space
lean
example : Module K (V ⧸ E) := inferInstanceCanonical projection (mkQ)
Submodule.mkQ is the canonical linear projection onto the quotient, mkQ : V →ₗ[K] V ⧸ E:
| Fact | Lemma | Statement |
|---|---|---|
| the projection itself | Submodule.mkQ | V →ₗ[K] V ⧸ E |
| its kernel | E.ker_mkQ | ker E.mkQ = E |
| its range | E.range_mkQ | range E.mkQ = ⊤ |
Universal properties: liftQ and mapQ
Submodule.liftQ(lifting): ifhφ : E ≤ ker φ, there's a uniqueV ⧸ E →ₗ[K] WfactoringφthroughmkQ, i.e.φ = liftQ φ hφ ∘ mkQ.leanexample (hφ : E ≤ ker φ) : V ⧸ E →ₗ[K] W := E.liftQ φ hφSubmodule.mapQ(mapping quotients): ifhφ : E ≤ .comap φ F, there's a uniqueV ⧸ E →ₗ[K] W ⧸ Fmaking the square commute:V → W ↓mkQ φ ↓mkQ V ⧸ E → W ⧸ F mapQleanexample (F : Submodule K W) (hφ : E ≤ .comap φ F) : V ⧸ E →ₗ[K] W ⧸ F := E.mapQ F φ hφFirst isomorphism theorem: the quotient by the kernel is linearly isomorphic to the range:
leannoncomputable example : (V ⧸ LinearMap.ker φ) ≃ₗ[K] range φ := φ.quotKerEquivRange
map_comap_eq and comap_map_eq
| Lemma | Statement | Intuition |
|---|---|---|
Submodule.map_comap_eq | Submodule.map φ (Submodule.comap φ F) = F ⊓ range φ | some elements of F may have no preimage under φ, so mapping the preimage back only recovers F ⊓ range φ, not all of F |
Submodule.comap_map_eq | Submodule.comap φ (Submodule.map φ E) = E ⊔ ker φ | everything in ker φ maps into φ E (since 0 ∈ φ E), so the preimage of the image picks up all of ker φ in addition to E |
Open exercise: submodules of the quotient
NOTE
The correspondence theorem — submodules of V ⧸ E correspond to submodules of V containing E — is stated but left unproved (sorry) in the source:
lean
example : Submodule K (V ⧸ E) ≃ { F : Submodule K V // E ≤ F } where
toFun := sorry
invFun := sorry
left_inv := sorry
right_inv := sorryPart III — Endomorphisms (S03)
Summary generated from the comments in C10-S03.lean.
Throughout, V is a vector space over a field K:
lean
variable {K : Type*} [Field K] {V : Type*} [AddCommGroup V] [Module K V]
open Polynomial Module LinearMap EndEndomorphisms
An endomorphism is a linear map from a vector space to itself. In Mathlib this has its own notation:
lean
End K V -- abbreviation for `V →ₗ[K] V`Unlike general linear maps, endomorphisms can be multiplied, which makes End K V a (non-commutative) ring — and even a K-algebra.
Multiplication is composition
Multiplication of endomorphisms is composition of linear maps, i.e. * ↔ ∘ₗ:
lean
example (φ ψ : End K V) : φ * ψ = φ ∘ₗ ψ :=
End.mul_eq_comp φ ψ -- `rfl` would also workNOTE
The multiplication φ * ψ applies ψ first: (φ * ψ) x = φ (ψ x), as witnessed by End.mul_apply.
Polynomial Evaluation on Endomorphisms (aeval)
Evaluating a polynomial P : K[X] at an endomorphism φ yields another endomorphism. This is a special kind of evaluation, called algebra evaluation (aeval):
lean
example (P : K[X]) (φ : End K V) : V →ₗ[K] V :=
aeval φ PEvaluating the simplest polynomial X gives the endomorphism back:
lean
example (φ : End K V) : aeval φ (X : K[X]) = φ :=
aeval_X φaeval is an algebra homomorphism
aeval φ : K[X] →ₐ[K] End K V is an AlgHom — it maps polynomials to endomorphisms and preserves the whole algebra structure. This is what justifies rewriting with:
| Rewrite | Meaning |
|---|---|
map_add | aeval φ (P + Q) = aeval φ P + aeval φ Q |
map_mul | aeval φ (P * Q) = aeval φ P * aeval φ Q |
map_one | aeval φ 1 = 1 (the identity endomorphism) |
IMPORTANT
Even though both K[X] and End K V are vector spaces, aeval φ is not treated as a bare linear map in Lean — it is an algebra homomorphism, so multiplicative lemmas like map_mul apply directly.
Toolbox: Subspace Lemmas
The two theorems below rely on the following characterizations:
| Lemma | Statement |
|---|---|
Submodule.eq_bot_iff | S = ⊥ ↔ ∀ x ∈ S, x = 0 — a subspace is trivial iff it only contains 0 |
Submodule.mem_inf | x ∈ S ⊓ T ↔ x ∈ S ∧ x ∈ T — intersection membership |
LinearMap.mem_ker | x ∈ ker φ ↔ φ x = 0 — kernel membership |
Submodule.add_mem_sup | x ∈ S → y ∈ T → x + y ∈ S ⊔ T — sums land in the supremum |
LinearMap.ker_le_ker_comp | ker f ≤ ker (g ∘ f) — kernels grow under pre-composition |
End.mul_apply | (φ * ψ) x = φ (ψ x) — multiplication is composition, pointwise |
map_mul | aeval φ (P * Q) = aeval φ P * aeval φ Q — aeval preserves * |
Theorem 1: Coprime evaluations have trivially intersecting kernels
Statement. If P and Q are coprime polynomials, then the kernels of their evaluations on an endomorphism φ intersect trivially:
lean
example (P Q : K[X]) (h : IsCoprime P Q) (φ : End K V) :
ker (aeval φ P) ⊓ ker (aeval φ Q) = ⊥ := by
rw [Submodule.eq_bot_iff]
rintro x h1
rw [Submodule.mem_inf, LinearMap.mem_ker, LinearMap.mem_ker] at h1
rcases h1 with ⟨h2, h3⟩
rcases h with ⟨a, b, bezout_identy⟩
have := congr((aeval φ) $bezout_identy.symm x)
rwa [map_add, map_mul, map_mul, map_one, LinearMap.add_apply, End.mul_apply, End.mul_apply,
h2, h3, LinearMap.map_zero, LinearMap.map_zero, add_zero, End.one_apply] at thisProof walkthrough
- Unfold the goal.
Submodule.eq_bot_iffturnsS = ⊥into∀ x ∈ S, x = 0. Afterrintro x h1and unfolding⊓/kermembership,h1becomes the pairh2 : aeval φ P x = 0, andh3 : aeval φ Q x = 0.
- Invoke Bézout.
IsCoprime P Qdestructs into polynomialsa, bwith the Bézout identitya * P + b * Q = 1. - Apply
aeval φto both sides, then evaluate atx(viacongr((aeval φ) $ bezout_identy.symm x)). This is legitimate becauseaeval φis anAlgHom. - Rewrite to
x = 0. The longrwa [...]chain pushesaeval φthrough the algebra operations:map_add,map_mul,map_mul,map_onesplit the evaluation into(aeval φ a * aeval φ P + aeval φ b * aeval φ Q) x = (1 : End K V) x;LinearMap.add_applyandEnd.mul_apply(twice) turn this intoaeval φ a (aeval φ P x) + aeval φ b (aeval φ Q x) = x;h2,h3kill both terms;map_zero,add_zero, andEnd.one_applyfinish withx = 0.
Theorem 2: Supremum of kernels is the kernel of the product
Statement. For coprime P and Q, the sum of the kernels of the evaluations equals the kernel of the evaluation of the product:
lean
example (P Q : K[X]) (h : IsCoprime P Q) (φ : End K V) :
ker (aeval φ P) ⊔ ker (aeval φ Q) = ker (aeval φ (P*Q)) := by
apply le_antisymm
· apply sup_le
· rw [mul_comm, map_mul]
apply LinearMap.ker_le_ker_comp
· rw [map_mul]
apply LinearMap.ker_le_ker_comp
· rintro x h1
rcases h with ⟨U, W, h2⟩
have key : x = aeval φ (U*P) x + aeval φ (W*Q) x := by simpa using congr((aeval φ) $h2.symm x)
rw [key, add_comm]
apply Submodule.add_mem_sup <;> rw [mem_ker] at *
· rw [← End.mul_apply, ← map_mul, show P*(W*Q) = W*(P*Q) by ring, map_mul, End.mul_apply, h1,
map_zero]
· rw [← End.mul_apply, ← map_mul, show Q*(U*P) = U*(P*Q) by ring, map_mul, mul_apply, h1,
map_zero]Proof walkthrough
The equality is proved by mutual inclusion via le_antisymm (a = b ↔ a ≤ b ∧ b ≤ a).
Direction ≤: each kernel sits inside the kernel of the product.
sup_lereducesS ⊔ T ≤ Cto the two goalsS ≤ CandT ≤ C.- For
ker (aeval φ P) ≤ ker (aeval φ (P*Q)): rewriteP*Q = Q*P(mul_comm) and split the evaluation (map_mul), so the goal becomesker (aeval φ P) ≤ ker (aeval φ Q * aeval φ P)— which is exactlyLinearMap.ker_le_ker_comp, since the right-hand kernel contains everything killed by the first applied factor. - The
Qcase is symmetric, without needingmul_comm.
Direction ≥: anything killed by the product splits across the two kernels.
- Take
xwithh1 : aeval φ (P*Q) x = 0and destruct the Bézout identity asU*P + W*Q = 1. - Key decomposition (
key): applyingaeval φto Bézout and evaluating atxgivesx = aeval φ (U*P) x + aeval φ (W*Q) x(proved bysimpaoff the samecongrtrick as Theorem 1). - After
rw [key, add_comm],Submodule.add_mem_supreduces the goal to showing each summand lies in the appropriate kernel;rw [mem_ker] at *unfolds all kernel memberships. - For the first summand,
aeval φ P (aeval φ (W*Q) x) = 0:← End.mul_applymerges the two applications into one multiplication(aeval φ P * aeval φ (W*Q)) x;← map_mulfolds it into a single evaluationaeval φ (P * (W * Q)) x;show P*(W*Q) = W*(P*Q) by ringre-associates inside the polynomial ring (which is commutative);map_mul, End.mul_applysplit again to expose the factoraeval φ (P*Q) x, whichh1rewrites to0, andmap_zerocloses the goal.
- The second summand is identical with the roles of
P/QandU/Wswapped.
TIP
The recurring pattern in both proofs: End.mul_apply (pointwise multiplication ⇔ composition) and map_mul (aeval ⇔ polynomial multiplication) let you move freely between evaluating a product and composing evaluations — with ring handling commutativity at the polynomial level.
Part IV — Bases (S04)
Summary generated from the comments in C10-S04.lean.
Throughout, V is a vector space over a field K:
lean
variable {K : Type*} [Field K] {V : Type*} [AddCommGroup V] [Module K V]
open ModuleBases and Coordinates
Fix a basis B : Basis ι K V indexed by a type ι, a vector v : V, and an index i : ι:
lean
variable {ι : Type*} (B : Basis ι K V) (v : V) (i : ι)| Expression | Type | Meaning |
|---|---|---|
B i | V | the basis vector with index i |
B.repr | V ≃ₗ[K] ι →₀ K | the linear isomorphism between V and finitely supported functions ι →₀ K |
B.repr v | ι →₀ K | the coordinate of v with respect to B |
B.repr v i | K | the i-th entry of the coordinate of v |
NOTE
ι →₀ K (Finsupp) is the type of functions ι → K that are nonzero on only finitely many inputs. Every vector in V has a unique coordinate representation of this form via the basis B.
Constructing a basis
Given a linearly independent family of vectors b that spans V, we can assemble it into a basis:
lean
noncomputable example (b : ι → V) (b_indep : LinearIndependent K b)
(b_spans : ∀ v, v ∈ Submodule.span K (Set.range b)) : Basis ι K V :=
Basis.mk b_indep (fun v _ ↦ b_spans v)A basis is exactly the conjunction of two conditions:
- the family
bis linearly independent, and - the family
bspans the whole vector space.
The constructed basis retrieves the original family pointwise:
lean
example (b : ι → V) (b_indep : LinearIndependent K b)
(b_spans : ∀ v, v ∈ Submodule.span K (Set.range b)) (i : ι) :
Basis.mk b_indep (fun v _ ↦ b_spans v) i = b i :=
Basis.mk_apply b_indep (fun v _ ↦ b_spans v) iCanonical bases
lean
variable [DecidableEq ι]
-- The basis of `ι →₀ K` given by the single vectors
example : Finsupp.basisSingleOne.repr = LinearEquiv.refl K (ι →₀ K) := rfl
example (i : ι) : Finsupp.basisSingleOne i = Finsupp.single i 1 := rfl
-- Coordinates of a function `ι → K` with respect to the Pi basis
example [Finite ι] (x : ι → K) (i : ι) : (Pi.basisFun K ι).repr x i = x i := by simpFinsupp.basisSingleOne— the basis ofι →₀ Kwhosei-th vector isFinsupp.single i 1; itsrepris definitionally the identity.DecidableEq ιis needed to decide equality of indices.Pi.basisFun K ι— the basis ofι → K(for finiteι) that recovers each function entry as its own coordinate.
Reconstructing a vector from its coordinates
The vector v is the linear combination of the basis vectors B i with coefficients B.repr v i:
lean
example [Fintype ι] : ∑ i : ι, B.repr v i • (B i) = v :=
B.sum_repr vLinear Combinations
Linear combination with general vectors
For a coefficient function c : ι →₀ K and any family of vectors f : ι → V, the linear combination over the support of c can be computed as a sum over any finset s containing that support — the extra terms contribute zero coefficients:
lean
example (c : ι →₀ K) (f : ι → V) (s : Finset ι) (h : c.support ⊆ s) :
Finsupp.linearCombination K f c = ∑ i ∈ s, c i • f i :=
Finsupp.linearCombination_apply_of_mem_supported K hTaking linear combinations is itself linear in the coefficients:
lean
variable (f : ι → V) in
#check (Finsupp.linearCombination K f : (ι →₀ K) →ₗ[K] V)Linear combination with a basis
Combining the basis vectors with their coordinates gives back the vector:
lean
example : Finsupp.linearCombination K B (B.repr v) = v :=
B.linearCombination_repr vLinear Maps Constructed from a Basis
Let W be another vector space over K, φ : V →ₗ[K] W, and u : ι → W a family of vectors in W.
Extension by linearity (B.constr)
A linear map out of V is completely determined by its values on a basis. This is packaged as a linear equivalence:
lean
#check (B.constr K : (ι → W) ≃ₗ[K] (V →ₗ[K] W))
#check (B.constr K u : V →ₗ[K] W)In other words, given a basis B of V:
- (a) once we specify the images
uof the basis vectors, the linear map is completely determined; - (b) conversely, once the linear map is specified on the basis vectors, the images
uare determined.
The constructed map does what it should on basis vectors:
lean
example (i : ι) : B.constr K u (B i) = u i :=
B.constr_basis K u iMaps agreeing on a basis are equal (B.ext)
Two linear maps that agree on all basis vectors are equal:
lean
example (φ ψ : V →ₗ[K] W) (h : ∀ i, φ (B i) = ψ (B i)) : φ = ψ :=
B.ext hMatrices Representing Linear Maps
The matrix representing a linear map is determined by three things:
- the choice of basis
Bfor the sourceV— onceBis fixed,Vis coordinatized; - the choice of basis
B'for the targetW; - the action of the linear map on the basis vectors of
V.
IMPORTANT
The basis vectors B i need not be mapped to basis vectors of W — they can land anywhere in W, and different actions give different matrices. Moreover, even when B is mapped onto B', the map on indices need not be bijective, since the index types ι and ι' may have different sizes.
The matrix of a linear map (toMatrix)
With bases B of V (indexed by ι) and B' of W (indexed by ι'), both finite with decidable equality:
lean
variable {ι' : Type*} (B' : Basis ι' K W)
[Fintype ι] [DecidableEq ι] [Fintype ι'] [DecidableEq ι']
open LinearMap Matrix -- `*ᵥ` is matrix–vector multiplication
#check (toMatrix B B' : (V →ₗ[K] W) ≃ₗ[K] Matrix ι' ι K)This is a two-way correspondence:
- (a) given the linear map, the matrix
Matrix ι' ι Kwith respect to these bases is determined; - (b) given the matrix, the linear map is determined.
The matrix acts on coordinate vectors as expected — the coordinate of v multiplied by the matrix of φ gives the coordinate of φ v:
lean
example (φ : V →ₗ[K] W) (v : V) : (toMatrix B B' φ) *ᵥ (B.repr v) = B'.repr (φ v) :=
toMatrix_mulVec_repr B B' φ vChange of basis
Let B'' be another basis of W (indexed by ι''). The matrix of φ with respect to B, B'' is obtained by multiplying the matrix of the identity map from B' to B'' with the matrix of φ from B to B':
lean
example (φ : V →ₗ[K] W) : (toMatrix B B'' φ) = (toMatrix B' B'' .id) * (toMatrix B B' φ) := by
simpComposition corresponds to matrix multiplication
| Lemma | Statement |
|---|---|
toMatrix_comp | toMatrix v₁ v₃ (f.comp g) = toMatrix v₂ v₃ f * toMatrix v₁ v₂ g |
id_comp | LinearMap.id ∘ₗ f = f |
comp_id | f ∘ₗ LinearMap.id = f |
toMatrix_id | the identity map is represented by the identity matrix |
Matrix.det_mul | det (A * B) = det A * det B |
Matrix.det_one | det 1 = 1 |
The determinant of an endomorphism is basis-independent
If B and B' are both bases of the same space V and φ : End K V, then the determinant of the representing matrix does not depend on the chosen basis:
Two aspects are at play:
- the matrix of an endomorphism is unchanged when the target basis varies together with the source basis;
- once source and target bases are fixed, the matrix is uniquely determined by the map itself.
That is, toMatrix B B φ is determined by φ, not by the particular choice between B and B'.
Proof walkthrough (click to expand)
lean
example [Fintype ι] (B' : Basis ι K V) (φ : End K V) :
(toMatrix B B φ).det = (toMatrix B' B' φ).det := by
set M := toMatrix B B φ
set M' := toMatrix B' B' φ
set P := (toMatrix B B') LinearMap.id
set P' := (toMatrix B' B) LinearMap.id
have F : M = P' * M' * P := by
rw [← toMatrix_comp, ← toMatrix_comp, id_comp, comp_id]
have F' : P' * P = 1 := by
rw [← toMatrix_comp, id_comp, toMatrix_id]
rw [F, Matrix.det_mul, Matrix.det_mul,
show P'.det * M'.det * P.det = P'.det * P.det * M'.det by ring, ← Matrix.det_mul, F',
Matrix.det_one, one_mul]- Name the players.
M,M'are the matrices ofφin the two bases;PandP'are the change-of-basis matrices (the identity map read in the two pairs of bases). - Similarity (
F).M = P' * M' * P: fold matrix products back into compositions with← toMatrix_comp(twice), then simplifyid ∘ₗ φ ∘ₗ idtoφviaid_comp/comp_id. - Inverse change of basis (
F').P' * P = 1, since the two identity readings compose to the identity map, whose matrix is1(toMatrix_id). - Determinant computation. Expand
det MviaMatrix.det_multwice, commute the scalar determinants withring, refoldP'.det * P.detintodet (P' * P) = det 1 = 1(← Matrix.det_mul,F',Matrix.det_one), and finish withone_mul.
Finite Rank of Vector Spaces
The finite rank (dimension) of V over K is a natural number:
lean
#check (Module.finrank K V : ℕ)The archetypical n-dimensional space
Fin n → K is the canonical space of dimension n over K:
lean
example (n : ℕ) : Module.finrank K (Fin n → K) = n :=
Module.finrank_fin_fun KThe scalar field matters
Different scalar fields give different dimensions, even when the underlying additive group is the same. When computing a dimension, always keep the scalar field in mind:
ℂas a vector space over itself has dimension one:Module.finrank ℂ ℂ = 1(Module.finrank_self).ℂas a vector space overℝhas dimension two:Module.finrank ℝ ℂ = 2(Complex.finrank_real_complex).
Positivity of rank
For a finite-dimensional space, the rank is positive iff the space is nontrivial:
lean
example [FiniteDimensional K V] : 0 < Module.finrank K V ↔ Nontrivial V :=
Module.finrank_pos_iffThe forward direction alone is often useful on its own:
lean
example [FiniteDimensional K V] (h : 0 < Module.finrank K V) : Nontrivial V := by
apply (Module.finrank_pos_iff (R := K)).1
exact hFinite basis ⇔ finite-dimensional
A basis B : Basis ι K V relates finiteness of the index type ι to finite-dimensionality of V:
lean
variable {ι : Type*} (B : Module.Basis ι K V)
example [Finite ι] : FiniteDimensional K V := Module.Basis.finiteDimensional_of_finite B
example [FiniteDimensional K V] : Finite ι := (FiniteDimensional.fintypeBasisIndex B).finiteFinite Rank of Submodules
Let E F : Submodule K V with V finite-dimensional.
Dimension formula. The rank of the supremum plus the rank of the infimum equals the sum of the ranks:
lean
example : finrank K (E ⊔ F : Submodule K V) + finrank K (E ⊓ F : Submodule K V) =
finrank K E + finrank K F :=
Submodule.finrank_sup_add_finrank_inf_eq E FMonotonicity. The rank of a submodule is at most the rank of the whole space:
lean
example : finrank K E ≤ finrank K V := Submodule.finrank_le EPigeonhole for subspaces. If the ranks of E and F add up to more than the rank of V, their intersection is nontrivial:
lean
example (h : finrank K V < finrank K E + finrank K F) :
Nontrivial (E ⊓ F : Submodule K V) := by
rw [← Module.finrank_pos_iff (R := K)]
rw [← Submodule.finrank_sup_add_finrank_inf_eq E F] at h
have : finrank K (E ⊔ F : Submodule K V) ≤ finrank K V := Submodule.finrank_le (E ⊔ F : Submodule K V)
linarithThe proof rewrites the goal into positivity of finrank K (E ⊓ F) (← Module.finrank_pos_iff), rewrites the hypothesis with the dimension formula, notes that finrank K (E ⊔ F) ≤ finrank K V by monotonicity, and lets linarith close the arithmetic.