1-- Finite dimensional real linear algebra2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.LinearAlgebra.FiniteDimensional8import Real.FiniteSum9import Real.Squares1011-- Vectors are real sequences observed only below the dimension n. This12-- representation permits the same sequence to be reused at several sizes.13def dotProduct (u v : RealSequence, n : Nat) : Real:=14 realPartialSum(mulSequence(u, v), n)1516theorem dotProduct.real (u v : Set, n : Nat)17requires sequenceU : RealSequence(u)18requires sequenceV : RealSequence(v)19showsReal(dotProduct(u, v, n))20proof21have product := mulSequence.sequence with sequenceU, sequenceV22unfold dotProduct23exact realPartialSum.real with product2425theorem dotProduct.zero (u v : Set)26shows dotProduct(u, v, 0) = (0:R)27proof28unfold dotProduct29exact realPartialSum.zero3031theorem dotProduct.succ (u v : Set, n : Nat)32requires sequenceU : RealSequence(u)33requires sequenceV : RealSequence(v)34shows dotProduct(u, v, succ(n)) =35 (dotProduct(u, v, n):R) + (u[n]:R) * (v[n]:R)36proof37have un := RealSequence.value with sequenceU38have vn := RealSequence.value with sequenceV39have value := mulSequence.value with sequenceU, sequenceV, un, vn40unfold dotProduct41rw [realPartialSum.succ, value]42unfold realAddValue43unfold call244rfl4546theorem dotProduct.symmetric (u v : Set, n : Nat)47requires sequenceU : RealSequence(u)48requires sequenceV : RealSequence(v)49shows dotProduct(u, v, n) = dotProduct(v, u, n)50proof51induction n52| zero =>53rw [dotProduct.zero, dotProduct.zero]54rfl55| succ(k) using ih =>56have uk := RealSequence.value with sequenceU57have vk := RealSequence.value with sequenceV58rw [dotProduct.succ, dotProduct.succ, ih]59ring6061-- Only the first n coordinates are observed by an n-dimensional dot product.62theorem dotProduct.eq_prefix (u v w z : Set, n : Nat)63requires sequenceU : RealSequence(u)64requires sequenceV : RealSequence(v)65requires sequenceW : RealSequence(w)66requires sequenceZ : RealSequence(z)67requires equalLeft : ∀ k ∈ ℕ, k < n → u[k] = w[k]68requires equalRight : ∀ k ∈ ℕ, k < n → v[k] = z[k]69shows dotProduct(u, v, n) = dotProduct(w, z, n)70proof71have first := mulSequence.sequence with sequenceU, sequenceV72have second := mulSequence.sequence with sequenceW, sequenceZ73have equal : ∀ k ∈ ℕ, k < n →74 mulSequence(u, v)[k] = mulSequence(w, z)[k]75intros k naturalK before76have typedK := nat.omega.backward with naturalK77have uk := RealSequence.value at u, k with sequenceU78have vk := RealSequence.value at v, k with sequenceV79have wk := RealSequence.value at w, k with sequenceW80have zk := RealSequence.value at z, k with sequenceZ81have firstValue := mulSequence.value with sequenceU, sequenceV, uk, vk82have secondValue := mulSequence.value with sequenceW, sequenceZ, wk, zk83haveleft:= equalLeft with k, naturalK, before84haveright:= equalRight with k, naturalK, before85rw [firstValue, secondValue, left, right]86rfl87unfold dotProduct88exact realPartialSum.eq_prefix with first, second, equal8990theorem dotProduct.add_right (u v w : Set, n : Nat)91requires sequenceU : RealSequence(u)92requires sequenceV : RealSequence(v)93requires sequenceW : RealSequence(w)94shows dotProduct(u, addSequence(v, w), n) =95 (dotProduct(u, v, n):R) + (dotProduct(u, w, n):R)96proof97induction n98| zero =>99rw [dotProduct.zero, dotProduct.zero, dotProduct.zero]100ring101| succ(k) using ih =>102have combined := addSequence.sequence with sequenceV, sequenceW103have uk := RealSequence.value with sequenceU104have vk := RealSequence.value with sequenceV105have wk := RealSequence.value with sequenceW106have vkPlusWk := RealSequence.value with combined107have value := addSequence.value with sequenceV, sequenceW, vk, wk108rw [dotProduct.succ, dotProduct.succ, dotProduct.succ, ih, value]109ring110111theorem dotProduct.add_left (u v w : Set, n : Nat)112requires sequenceU : RealSequence(u)113requires sequenceV : RealSequence(v)114requires sequenceW : RealSequence(w)115shows dotProduct(addSequence(u, v), w, n) =116 (dotProduct(u, w, n):R) + (dotProduct(v, w, n):R)117proof118have combined := addSequence.sequence with sequenceU, sequenceV119have symmetryCombined := dotProduct.symmetric with combined, sequenceW120have distributive := dotProduct.add_right with sequenceW, sequenceU, sequenceV121have symmetryU := dotProduct.symmetric with sequenceW, sequenceU122have symmetryV := dotProduct.symmetric with sequenceW, sequenceV123rw [symmetryCombined, distributive, symmetryU, symmetryV]124rfl125126theorem dotProduct.scale_right (u v : Set, C : Real, n : Nat)127requires sequenceU : RealSequence(u)128requires sequenceV : RealSequence(v)129shows dotProduct(u, mulSequence(constantSequence(C), v), n) =130 C * (dotProduct(u, v, n):R)131proof132induction n133| zero =>134rw [dotProduct.zero, dotProduct.zero]135ring136| succ(k) using ih =>137have constants := constantSequence.sequence at C138have scaled := mulSequence.sequence with constants, sequenceV139have uk := RealSequence.value with sequenceU140have vk := RealSequence.value with sequenceV141have constantK := RealSequence.value with constants142have scaledK := RealSequence.value with scaled143have value := mulSequence.value with constants, sequenceV, constantK, vk144have constant := constantSequence.value at C, k with*145rw [dotProduct.succ, dotProduct.succ, ih, value, constant]146ring147148theorem dotProduct.scale_left (u v : Set, C : Real, n : Nat)149requires sequenceU : RealSequence(u)150requires sequenceV : RealSequence(v)151shows dotProduct(mulSequence(constantSequence(C), u), v, n) =152 C * (dotProduct(u, v, n):R)153proof154have constants := constantSequence.sequence at C155have scaled := mulSequence.sequence with constants, sequenceU156have symmetricScaled := dotProduct.symmetric with scaled, sequenceV157haveright:= dotProduct.scale_right with sequenceV, sequenceU158have symmetric := dotProduct.symmetric with sequenceV, sequenceU159rw [symmetricScaled, right, symmetric]160rfl161162theorem dotProduct.sub_left (u v w : Set, n : Nat)163requires sequenceU : RealSequence(u)164requires sequenceV : RealSequence(v)165requires sequenceW : RealSequence(w)166shows dotProduct(subSequence(u, v), w, n) =167 (dotProduct(u, w, n):R) - (dotProduct(v, w, n):R)168proof169induction n170| zero =>171simp [dotProduct.zero]172ring173| succ(k) using ih =>174have difference := subSequence.sequence at u, v with*175have uk := RealSequence.value at u, k with*176have vk := RealSequence.value at v, k with*177have wk := RealSequence.value at w, k with*178have dk := RealSequence.value at subSequence(u, v), k with*179simp [dotProduct.succ, subSequence.value]180ring181182def squaredNorm (u : RealSequence, n : Nat) : Real:= dotProduct(u, u, n)183184predicate Orthogonal (u v : Set, n : Nat) := dotProduct(u, v, n) = (0:R)185186theorem Orthogonal.symmetric (u v : Set, n : Nat)187requires sequenceU : RealSequence(u)188requires sequenceV : RealSequence(v)189requires orthogonal : Orthogonal(u, v, n)190shows Orthogonal(v, u, n)191proof192unfold Orthogonal at orthogonal193unfold Orthogonal194have symmetry := dotProduct.symmetric with sequenceU, sequenceV195 rwa symmetry at orthogonal196197theorem squaredNorm.real (u : Set, n : Nat)198requires sequence : RealSequence(u)199showsReal(squaredNorm(u, n))200proof201unfold squaredNorm202exact dotProduct.real with sequence, sequence203204theorem squaredNorm.succ (u : Set, n : Nat)205requires sequence : RealSequence(u)206shows squaredNorm(u, succ(n)) =207 (squaredNorm(u, n):R) + (u[n]:R) * (u[n]:R)208proof209unfold squaredNorm210exact dotProduct.succ with sequence, sequence211212theorem squaredNorm.nonnegative (u : Set, n : Nat)213requires sequence : RealSequence(u)214shows (0:R) ≤ (squaredNorm(u, n):R)215proof216induction n217| zero =>218unfold squaredNorm219rw dotProduct.zero220exact realLe.reflexive with realZero.real221| succ(k) using ih =>222have uk := RealSequence.value with sequence223haveprefix:= squaredNorm.real with sequence224have term := realMulValue.real with uk, uk225have nonnegative := realMulValue.square_nonnegative with uk226have added := realLe.add with realZero.real, prefix, realZero.real, term, ih, nonnegative227have zero := realAddValue.zero_right with realZero.real228rw zero at added229unfold squaredNorm at added230unfold squaredNorm231 rwa dotProduct.succ232233theorem squaredNorm.scale (u : Set, C : Real, n : Nat)234requires sequence : RealSequence(u)235shows squaredNorm(mulSequence(constantSequence(C), u), n) =236 (C * C) * (squaredNorm(u, n):R)237proof238have constants := constantSequence.sequence at C239have scaled := mulSequence.sequence with constants, sequence240have first := dotProduct.scale_left with sequence, scaled241have second := dotProduct.scale_right with sequence, sequence242simp [squaredNorm]243ring244245theorem squaredNorm.add (u v : Set, n : Nat)246requires sequenceU : RealSequence(u)247requires sequenceV : RealSequence(v)248shows squaredNorm(addSequence(u, v), n) =249 (squaredNorm(u, n):R) +250 (2:R) * (dotProduct(u, v, n):R) +251 (squaredNorm(v, n):R)252proof253have combined := addSequence.sequence with sequenceU, sequenceV254have first := dotProduct.add_left with sequenceU, sequenceV, combined255have second := dotProduct.add_right with sequenceU, sequenceU, sequenceV256have third := dotProduct.add_right with sequenceV, sequenceU, sequenceV257have symmetry := dotProduct.symmetric with sequenceV, sequenceU258simp [squaredNorm]259ring260261theorem squaredNorm.sub (u v : Set, n : Nat)262requires sequenceU : RealSequence(u)263requires sequenceV : RealSequence(v)264shows squaredNorm(subSequence(u, v), n) =265 ((squaredNorm(u, n):R) -266 (2:R) * (dotProduct(u, v, n):R)) +267 (squaredNorm(v, n):R)268proof269induction n270| zero =>271unfold squaredNorm272rw [dotProduct.zero, dotProduct.zero, dotProduct.zero, dotProduct.zero]273ring274| succ(k) using ih =>275have difference := subSequence.sequence with sequenceU, sequenceV276have uk := RealSequence.value with sequenceU277have vk := RealSequence.value with sequenceV278have differenceK := RealSequence.value with difference279have value := subSequence.value with sequenceU, sequenceV, uk, vk280rw [squaredNorm.succ, squaredNorm.succ, squaredNorm.succ, dotProduct.succ, value, ih]281ring282283theorem squaredNorm.parallelogram (u v : Set, n : Nat)284requires sequenceU : RealSequence(u)285requires sequenceV : RealSequence(v)286shows (squaredNorm(addSequence(u, v), n):R) +287 (squaredNorm(subSequence(u, v), n):R) =288 (2:R) * (squaredNorm(u, n):R) +289 (2:R) * (squaredNorm(v, n):R)290proof291have combined := addSequence.sequence with sequenceU, sequenceV292have difference := subSequence.sequence with sequenceU, sequenceV293have normU := squaredNorm.real with sequenceU294have normV := squaredNorm.real with sequenceV295have cross := dotProduct.real with sequenceU, sequenceV296have plus := squaredNorm.add with sequenceU, sequenceV297have minus := squaredNorm.sub with sequenceU, sequenceV298have algebra : ∀ A ∈ ℝ, ∀ B ∈ ℝ, ∀ C ∈ ℝ,299 ((A:R) + B + C) + ((A - B) + C) =300 (2:R) * A + (2:R) * C301intros A realA B realB C realC302ring303have memberNormU : squaredNorm(u, n) ∈ ℝ byexact normU304have memberNormV : squaredNorm(v, n) ∈ ℝ byexact normV305have memberCross : (2:R) * dotProduct(u, v, n) ∈ ℝ bytypecheck306have combinedAlgebra := algebra with squaredNorm(u, n), memberNormU,307 (2:R) * dotProduct(u, v, n), memberCross,308 squaredNorm(v, n), memberNormV309calc310 (squaredNorm(addSequence(u, v), n):R) +311 (squaredNorm(subSequence(u, v), n):R) =312 ((squaredNorm(u, n):R) +313 (2:R) * (dotProduct(u, v, n):R) +314 (squaredNorm(v, n):R)) +315 (((squaredNorm(u, n):R) -316 (2:R) * (dotProduct(u, v, n):R)) +317 (squaredNorm(v, n):R)) :=bycc318 _ = (2:R) * (squaredNorm(u, n):R) +319 (2:R) * (squaredNorm(v, n):R) := combinedAlgebra320321theorem squaredNorm.pythagorean (u v : Set, n : Nat)322requires sequenceU : RealSequence(u)323requires sequenceV : RealSequence(v)324requires orthogonal : Orthogonal(u, v, n)325shows squaredNorm(addSequence(u, v), n) =326 (squaredNorm(u, n):R) + (squaredNorm(v, n):R)327proof328have expansion := squaredNorm.add with sequenceU, sequenceV329unfold Orthogonal at orthogonal330rw orthogonal at expansion331calc332 squaredNorm(addSequence(u, v), n) =333 (squaredNorm(u, n):R) + (2:R) * (0:R) +334 (squaredNorm(v, n):R) := expansion335 _ = (squaredNorm(u, n):R) + (squaredNorm(v, n):R) :=byring336