PhysLean/HepLean/SpaceTime/LorentzTensor/IndexNotation/Basic.lean
2024-08-26 15:23:38 -04:00

172 lines
5.3 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2024 Joseph Tooby-Smith. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joseph Tooby-Smith
-/
import Mathlib.Data.Set.Finite
import Mathlib.Logic.Equiv.Fin
import Mathlib.Data.Finset.Sort
import Mathlib.Tactic.FinCases
/-!
# Index notation for a type
In this file we will define an index of a Lorentz tensor as a
string satisfying certain properties.
For example, the string `ᵘ¹²` is an index of a real Lorentz tensors.
The first character `ᵘ` specifies the color of the index, and the subsequent characters
`¹²` specify the id of the index.
Strings of indices e.g. `ᵘ¹²ᵤ₄₃`` are defined elsewhere.
-/
open Lean
open String
/-- The class defining index notation on a type `X`.
Normally `X` will be taken as the type of colors of a `TensorStructure`. -/
class IndexNotation (X : Type) where
/-- The list of characters describing the index notation e.g.
`{'ᵘ', 'ᵤ'}` for real tensors. -/
charList : Finset Char
/-- An equivalence between `X` (colors of indices) and `charList`.
This takes every color of index to its notation character. -/
notaEquiv : X ≃ charList
namespace IndexNotation
variable (X : Type) [IndexNotation X]
variable [Fintype X] [DecidableEq X]
/-!
## Lists of characters forming an index
Here we define `listCharIndex` and properties thereof.
-/
/-- The map taking a color to its notation character. -/
def nota {X : Type} [IndexNotation X] (x : X) : Char :=
(IndexNotation.notaEquiv).toFun x
/-- A character is a `notation character` if it is in `charList`. -/
def isNotationChar (c : Char) : Bool :=
if c ∈ charList X then true else false
/-- A character is a numeric superscript if it is e.g. `⁰`, `¹`, etc. -/
def isNumericSupscript (c : Char) : Bool :=
c = '¹' c = '²' c = '³' c = '⁴' c = '⁵' c = '⁶' c = '⁷' c = '⁸' c = '⁹' c = '⁰'
/-- Given a character `f` which is a notation character, this is true if `c`
is a subscript when `f` is a subscript or `c` is a superscript when `f` is a
superscript. -/
def IsIndexId (f : Char) (c : Char) : Bool :=
(isSubScriptAlnum f ∧ isNumericSubscript c)
(¬ isSubScriptAlnum f ∧ isNumericSupscript c)
/-- The proposition for a list of characters to be the tail of an index
e.g. `['¹', '⁷', ...]` -/
def listCharIndexTail (f : Char) (l : List Char) : Prop :=
l ≠ [] ∧ List.all l (fun c => IsIndexId f c)
instance : Decidable (listCharIndexTail f l) := instDecidableAnd
/-- The proposition for a list of characters to be the characters of an index
e.g. `['ᵘ', '¹', '⁷', ...]` -/
def listCharIndex (l : List Char) : Prop :=
if h : l = [] then True
else
let sfst := l.head h
if ¬ isNotationChar X sfst then False
else
listCharIndexTail sfst l.tail
/-- An auxillary rewrite lemma to prove that `listCharIndex` is decidable. -/
lemma listCharIndex_iff (l : List Char) : listCharIndex X l
↔ (if h : l = [] then True else
let sfst := l.head h
if ¬ isNotationChar X sfst then False
else listCharIndexTail sfst l.tail) := by
rw [listCharIndex]
instance : Decidable (listCharIndex X l) :=
@decidable_of_decidable_of_iff _ _
(@instDecidableDite _ _ _ _ _ <|
fun _ => @instDecidableDite _ _ _ _ _ <|
fun _ => instDecidableListCharIndexTail)
(listCharIndex_iff X l).symm
/-!
## The definition of an index and its properties
-/
/-- An index is a non-empty string satisfying the condtion `listCharIndex`,
e.g. `ᵘ¹²` or `ᵤ₄₃` etc. -/
def Index : Type := {s : String // listCharIndex X s.toList ∧ s.toList ≠ []}
instance : DecidableEq (Index X) := Subtype.instDecidableEq
namespace Index
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
/-- Creats an index from a non-empty list of characters satisfying `listCharIndex`. -/
def ofCharList (l : List Char) (h : listCharIndex X l ∧ l ≠ []) : Index X := ⟨l.asString, h⟩
instance : ToString (Index X) := ⟨fun i => i.val⟩
/-- Gets the first character in an index e.g. `ᵘ` as an element of `charList X`. -/
def head (s : Index X) : charList X :=
⟨s.val.toList.head (s.prop.2), by
have h := s.prop.1
have h2 := s.prop.2
simp [listCharIndex] at h
simp_all only [toList, ne_eq, Bool.not_eq_true, ↓reduceDIte]
simpa [isNotationChar] using h.1⟩
/-- The color associated to an index. -/
def toColor (s : Index X) : X := (IndexNotation.notaEquiv).invFun s.head
/-- A map from super and subscript numerical characters to the natural numbers,
returning `0` on all other characters. -/
def charToNat (c : Char) : Nat :=
match c with
| '₀' => 0
| '₁' => 1
| '₂' => 2
| '₃' => 3
| '₄' => 4
| '₅' => 5
| '₆' => 6
| '₇' => 7
| '₈' => 8
| '₉' => 9
| '⁰' => 0
| '¹' => 1
| '²' => 2
| '³' => 3
| '⁴' => 4
| '⁵' => 5
| '⁶' => 6
| '⁷' => 7
| '⁸' => 8
| '⁹' => 9
| _ => 0
/-- The numerical characters associated with an index. -/
def tail (s : Index X) : List Char := s.val.toList.tail
/-- The natural numbers assocaited with an index. -/
def tailNat (s : Index X) : List Nat := s.tail.map charToNat
/-- The id of an index, as a natural number. -/
def id (s : Index X) : Nat := s.tailNat.foldl (fun a b => 10 * a + b) 0
end Index
end IndexNotation