Skip to content

Commit c465194

Browse files
committed
feat: notation for vectors in Euclidean space (#17732)
This adds `!₂[1, 2, 3]` notation for `(WithLp.equiv 2 (∀ _ : Fin 3, _)).symm ![1, 2, 3]`, which is a term of type `EuclideanSpace 𝕜 (Fin 3)`; and more generally for other Lp norms, using the `subscript` parser. This reduces the temptation to write the type-incorrect `![1, 2, 3]` that has the wrong norm. The (parser for the) `subscript` parser relies on `initialize`rs running, and so a missing `Lean.enableInitializersExecution` has to be inserted in `checkYaml.lean`. It has already been inserted in the necessary places in upstream repos. [Notation Zulip poll](https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Notation.20for.20vectors.20in.20euclidean.20space/near/476796192). Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
1 parent de7196a commit c465194

File tree

5 files changed

+73
-3
lines changed

5 files changed

+73
-3
lines changed

Mathlib/Analysis/InnerProductSpace/PiL2.lean

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Mathlib.Analysis.InnerProductSpace.Projection
77
import Mathlib.Analysis.Normed.Lp.PiLp
88
import Mathlib.LinearAlgebra.FiniteDimensional
99
import Mathlib.LinearAlgebra.UnitaryGroup
10+
import Mathlib.Util.Superscript
1011

1112
/-!
1213
# `L²` inner product space structure on finite products of inner product spaces
@@ -30,7 +31,8 @@ the last section, various properties of matrices are explored.
3031
3132
- `EuclideanSpace 𝕜 n`: defined to be `PiLp 2 (n → 𝕜)` for any `Fintype n`, i.e., the space
3233
from functions to `n` to `𝕜` with the `L²` norm. We register several instances on it (notably
33-
that it is a finite-dimensional inner product space).
34+
that it is a finite-dimensional inner product space), and provide a `!ₚ[]` notation (for numeric
35+
subscripts like `₂`) for the case when the indexing type is `Fin n`.
3436
3537
- `OrthonormalBasis 𝕜 ι`: defined to be an isometry to Euclidean space from a given
3638
finite-dimensional inner product space, `E ≃ₗᵢ[𝕜] EuclideanSpace 𝕜 ι`.
@@ -95,10 +97,43 @@ theorem PiLp.inner_apply {ι : Type*} [Fintype ι] {f : ι → Type*} [∀ i, No
9597
rfl
9698

9799
/-- The standard real/complex Euclidean space, functions on a finite type. For an `n`-dimensional
98-
space use `EuclideanSpace 𝕜 (Fin n)`. -/
100+
space use `EuclideanSpace 𝕜 (Fin n)`.
101+
102+
For the case when `n = Fin _`, there is `!₂[x, y, ...]` notation for building elements of this type,
103+
analogous to `![x, y, ...]` notation. -/
99104
abbrev EuclideanSpace (𝕜 : Type*) (n : Type*) : Type _ :=
100105
PiLp 2 fun _ : n => 𝕜
101106

107+
section Notation
108+
open Lean Meta Elab Term Macro TSyntax PrettyPrinter.Delaborator SubExpr
109+
110+
/-- Notation for vectors in Lp space. `!₂[x, y, ...]` is a shorthand for
111+
`(WithLp.equiv 2 _ _).symm ![x, y, ...]`, of type `EuclideanSpace _ (Fin _)`.
112+
113+
This also works for other subscripts. -/
114+
syntax (name := PiLp.vecNotation) "!" noWs subscript(term) noWs "[" term,* "]" : term
115+
macro_rules | `(!$p:subscript[$e:term,*]) => do
116+
-- override the `Fin n.succ` to a literal
117+
let n := e.getElems.size
118+
`((WithLp.equiv $p <| ∀ _ : Fin $(quote n), _).symm ![$e,*])
119+
120+
set_option trace.debug true in
121+
/-- Unexpander for the `!₂[x, y, ...]` notation. -/
122+
@[delab app.DFunLike.coe]
123+
def EuclideanSpace.delabVecNotation : Delab :=
124+
whenNotPPOption getPPExplicit <| whenPPOption getPPNotation <| withOverApp 6 do
125+
-- check that the `(WithLp.equiv _ _).symm` is present
126+
let p : Term ← withAppFn <| withAppArg do
127+
let_expr Equiv.symm _ _ e := ← getExpr | failure
128+
let_expr WithLp.equiv _ _ := e | failure
129+
withNaryArg 2 <| withNaryArg 0 <| delab
130+
-- to be conservative, only allow subscripts which are numerals
131+
guard <| p matches `($_:num)
132+
let `(![$elems,*]) := ← withAppArg delab | failure
133+
`(!$p[$elems,*])
134+
135+
end Notation
136+
102137
theorem EuclideanSpace.nnnorm_eq {𝕜 : Type*} [RCLike 𝕜] {n : Type*} [Fintype n]
103138
(x : EuclideanSpace 𝕜 n) : ‖x‖₊ = NNReal.sqrt (∑ i, ‖x i‖₊ ^ 2) :=
104139
PiLp.nnnorm_eq_of_L2 x

Mathlib/Analysis/Quaternion.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ theorem norm_piLp_equiv_symm_equivTuple (x : ℍ) :
165165
noncomputable def linearIsometryEquivTuple : ℍ ≃ₗᵢ[ℝ] EuclideanSpace ℝ (Fin 4) :=
166166
{ (QuaternionAlgebra.linearEquivTuple (-1 : ℝ) (-1 : ℝ)).trans
167167
(WithLp.linearEquiv 2 ℝ (Fin 4 → ℝ)).symm with
168-
toFun := fun a => (WithLp.equiv _ (Fin 4 → _)).symm ![a.1, a.2, a.3, a.4]
168+
toFun := fun a => !₂[a.1, a.2, a.3, a.4]
169169
invFun := fun a => ⟨a 0, a 1, a 2, a 3
170170
norm_map' := norm_piLp_equiv_symm_equivTuple }
171171

MathlibTest/EuclideanSpace.lean

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import Mathlib.Analysis.InnerProductSpace.PiL2
2+
3+
#guard_expr !₂[] = (WithLp.equiv 2 (∀ _ : Fin 0, _)).symm ![]
4+
#guard_expr !₂[1, 2, 3] = (WithLp.equiv 2 (∀ _ : Fin 3, ℕ)).symm ![1, 2, 3]
5+
#guard_expr !₁[1, 2, (3 : ℝ)] = (WithLp.equiv 1 (∀ _ : Fin 3, ℝ)).symm ![1, 2, 3]
6+
7+
section delaborator
8+
9+
/-- info: !₂[1, 2, 3] : WithLp 2 (Fin 3 → ℕ) -/
10+
#guard_msgs in
11+
#check !₂[1, 2, 3]
12+
13+
set_option pp.mvars false in
14+
/-- info: !₀[] : WithLp 0 (Fin 0 → ?_) -/
15+
#guard_msgs in
16+
#check !₀[]
17+
18+
section var
19+
variable {p : ENNReal}
20+
/-- info: (WithLp.equiv p (Fin 3 → ℕ)).symm ![1, 2, 3] : WithLp p (Fin 3 → ℕ) -/
21+
#guard_msgs in#check !ₚ[1, 2, 3]
22+
end var
23+
24+
section tombstoned_var
25+
/- Here the `p` in the subscript is shadowed by a later p; so even if we do
26+
make the delaborator less conservative, it should not fire here since `✝` cannot
27+
be subscripted. -/
28+
variable {p : ENNReal} {x} (hx : x = !ₚ[1, 2, 3]) (p : True)
29+
/-- info: hx : x = (WithLp.equiv p✝ (Fin 3 → ℕ)).symm ![1, 2, 3] -/
30+
#guard_msgs in #check hx
31+
end tombstoned_var
32+
33+
end delaborator

scripts/check-yaml.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def processDb (decls : ConstMap) : String → IO Bool
4040
return false
4141

4242
unsafe def main : IO Unit := do
43+
Lean.enableInitializersExecution
4344
CoreM.withImportModules #[`Mathlib, `Archive]
4445
(searchPath := compile_time_search_path%) (trustLevel := 1024) do
4546
let decls := (← getEnv).constants

scripts/noshake.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@
424424
["Mathlib.Tactic.CategoryTheory.Bicategory.Basic"],
425425
"Mathlib.Analysis.Normed.Operator.LinearIsometry":
426426
["Mathlib.Algebra.Star.Basic"],
427+
"Mathlib.Analysis.InnerProductSpace.PiL2": ["Mathlib.Util.Superscript"],
427428
"Mathlib.Analysis.InnerProductSpace.Basic":
428429
["Mathlib.Algebra.Module.LinearMap.Basic"],
429430
"Mathlib.Analysis.Distribution.SchwartzSpace": ["Mathlib.Tactic.MoveAdd"],

0 commit comments

Comments
 (0)