Imports
/- Copyright (c) 2026 Juan Jose Fernandez Morales. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Juan Jose Fernandez Morales -/ module public import Mathlib.Algebra.BigOperators.Fin

Multi-indices

i. Overview

This module defines the basic type of multi-indices used to index iterated partial derivatives.

A multi-index on d source coordinates is represented as a structure with an underlying function Fin d → ℕ, together with the first basic operations needed later in the local Classical Field Theory development.

ii. Key results

    Physlib.MultiIndex : multi-indices on d coordinates.

    MultiIndex.order : the order |I| of a multi-index.

    MultiIndex.increment : increment a single coordinate of a multi-index.

    MultiIndex.toList : the canonical ordered list of directions encoded by a multi-index.

iii. Table of contents

    A. The basic type of multi-indices

      A.1. Basic operations

      A.2. Basic lemmas

      A.3. Canonical ordered lists of directions

iv. References

@[expose] public section

A. The basic type of multi-indices

A multi-index on d source coordinates.

The coordinates of the multi-index.

structure MultiIndex (d : ) where toFun : Fin d deriving DecidableEq
instance : CoeFun (MultiIndex d) (fun _ => Fin d ) := MultiIndex.toFuninstance : Zero (MultiIndex d) := 0instance : Add (MultiIndex d) := fun I J => I.toFun + J.toFun

A.1. Basic operations

The order |I| of a multi-index I, defined as the sum of its components.

def order (I : MultiIndex d) : Nat := i, I i

Increment the i-th coordinate of a multi-index by one.

def increment (I : MultiIndex d) (i : Fin d) : MultiIndex d := I.toFun + Pi.single i 1

A.2. Basic lemmas

@[ext] lemma ext {I J : MultiIndex d} (h : i, I i = J i) : I = J := d:I:MultiIndex dJ:MultiIndex dh: (i : Fin d), I.toFun i = J.toFun iI = J d:J:MultiIndex dtoFun✝:Fin d h: (i : Fin d), { toFun := toFun✝ }.toFun i = J.toFun i{ toFun := toFun✝ } = J d:toFun✝¹:Fin d toFun✝:Fin d h: (i : Fin d), { toFun := toFun✝¹ }.toFun i = { toFun := toFun✝ }.toFun i{ toFun := toFun✝¹ } = { toFun := toFun✝ } d:toFun✝¹:Fin d toFun✝:Fin d h: (i : Fin d), toFun✝¹ i = toFun✝ i{ toFun := toFun✝¹ } = { toFun := toFun✝ } d:toFun✝¹:Fin d toFun✝:Fin d h: (i : Fin d), toFun✝¹ i = toFun✝ itoFun✝¹ = toFun✝ d:toFun✝¹:Fin d toFun✝:Fin d h: (i : Fin d), toFun✝¹ i = toFun✝ ii:Fin dtoFun✝¹ i = toFun✝ i All goals completed! 🐙@[simp] lemma zero_apply (i : Fin d) : (0 : MultiIndex d) i = 0 := rfl@[simp] lemma add_apply (I J : MultiIndex d) (i : Fin d) : (I + J) i = I i + J i := rfl@[simp] lemma increment_apply_same (I : MultiIndex d) (i : Fin d) : increment I i i = I i + 1 := d:I:MultiIndex di:Fin d(I.increment i).toFun i = I.toFun i + 1 All goals completed! 🐙@[simp] lemma increment_apply_ne (I : MultiIndex d) {i j : Fin d} (h : j i) : increment I i j = I j := d:I:MultiIndex di:Fin dj:Fin dh:j i(I.increment i).toFun j = I.toFun j All goals completed! 🐙@[simp] lemma order_zero : order (0 : MultiIndex d) = 0 := d:order 0 = 0 All goals completed! 🐙lemma order_add (I J : MultiIndex d) : order (I + J) = order I + order J := d:I:MultiIndex dJ:MultiIndex d(I + J).order = I.order + J.order All goals completed! 🐙d:i:Fin d{ toFun := Pi.single i 1 }.toFun i = 1d:i:Fin d b Finset.univ, b i { toFun := Pi.single i 1 }.toFun b = 0d:i:Fin di Finset.univ { toFun := Pi.single i 1 }.toFun i = 0 d:i:Fin d{ toFun := Pi.single i 1 }.toFun i = 1 All goals completed! 🐙 d:i:Fin d b Finset.univ, b i { toFun := Pi.single i 1 }.toFun b = 0 d:i:Fin dj:Fin da✝:j Finset.univhj:j i{ toFun := Pi.single i 1 }.toFun j = 0 All goals completed! 🐙 d:i:Fin di Finset.univ { toFun := Pi.single i 1 }.toFun i = 0 d:i:Fin dhi:i Finset.univ{ toFun := Pi.single i 1 }.toFun i = 0 All goals completed! 🐙@[simp] lemma order_increment (I : MultiIndex d) (i : Fin d) : order (increment I i) = order I + 1 := d:I:MultiIndex di:Fin d(I.increment i).order = I.order + 1 All goals completed! 🐙

A.3. Canonical ordered lists of directions

The tail of a multi-index on d + 1 coordinates, dropping the 0-th coordinate.

def tail (I : MultiIndex d.succ) : MultiIndex d := fun i => I i.succ

The canonical ordered list of coordinate directions encoded by a multi-index.

def toList : {d : } MultiIndex d List (Fin d) | 0, _ => [] | _ + 1, I => List.replicate (I 0) 0 ++ (toList (tail I)).map Fin.succ
@[simp] lemma tail_zero : tail (0 : MultiIndex d.succ) = 0 := d:tail 0 = 0 d:i:Fin d(tail 0).toFun i = toFun 0 i All goals completed! 🐙@[simp] lemma tail_increment_zero (I : MultiIndex d.succ) : tail (increment I 0) = tail I := d:I:MultiIndex d.succ(I.increment 0).tail = I.tail d:I:MultiIndex d.succi:Fin d(I.increment 0).tail.toFun i = I.tail.toFun i All goals completed! 🐙@[simp] lemma tail_increment_succ (I : MultiIndex d.succ) (i : Fin d) : tail (increment I i.succ) = increment (tail I) i := d:I:MultiIndex d.succi:Fin d(I.increment i.succ).tail = I.tail.increment i d:I:MultiIndex d.succi:Fin dj:Fin d(I.increment i.succ).tail.toFun j = (I.tail.increment i).toFun j d:I:MultiIndex d.succi:Fin dj:Fin dh:j = i(I.increment i.succ).tail.toFun j = (I.tail.increment i).toFun jd:I:MultiIndex d.succi:Fin dj:Fin dh:¬j = i(I.increment i.succ).tail.toFun j = (I.tail.increment i).toFun j d:I:MultiIndex d.succi:Fin dj:Fin dh:j = i(I.increment i.succ).tail.toFun j = (I.tail.increment i).toFun j d:I:MultiIndex d.succj:Fin d(I.increment j.succ).tail.toFun j = (I.tail.increment j).toFun j All goals completed! 🐙 d:I:MultiIndex d.succi:Fin dj:Fin dh:¬j = i(I.increment i.succ).tail.toFun j = (I.tail.increment i).toFun j All goals completed! 🐙@[simp] lemma toList_zero : toList (0 : MultiIndex d) = [] := d:toList 0 = [] induction d with d:toList 0 = [] All goals completed! 🐙 d✝:d:ih:toList 0 = []toList 0 = [] All goals completed! 🐙lemma length_toList (I : MultiIndex d) : I.toList.length = I.order := d:I:MultiIndex dI.toList.length = I.order induction d with d:I:MultiIndex 0I.toList.length = I.order All goals completed! 🐙 d✝:d:ih: (I : MultiIndex d), I.toList.length = I.orderI:MultiIndex (d + 1)I.toList.length = I.order All goals completed! 🐙d:I:MultiIndex d.succList.replicate 1 0 ++ List.replicate (I.toFun 0) 0 ++ List.map Fin.succ I.tail.toList = 0 :: (List.replicate (I.toFun 0) 0 ++ List.map Fin.succ I.tail.toList) All goals completed! 🐙d✝:d:ih: (i : Fin d), (increment 0 i).toList = [i]i:Fin (d + 1)j:Fin dhtail:(increment 0 j.succ).tail = increment 0 jhzero:(increment 0 j.succ).toFun 0 = 0(increment 0 j.succ).toList = [j.succ] All goals completed! 🐙