Imports
/- Copyright (c) 2026 Terence Rokop. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Terence Rokop -/ module import Geb.Mathlib.Data.Vector.OfFn

Writing a list of index-value pairs into a vector

Vector.scatter writes a list of index-value pairs into a vector in one left-to-right pass, each pair overwriting the entry at its index. Repeated indices are allowed, the last pair carrying an index being the one whose value survives, so the entry at an index is determined by the pairs whenever they all carry the same value there.

Main definitions

    Vector.scatter — the pass.

Main statements

    Vector.get_scatter_of_not_mem — an index no pair carries keeps its entry.

    Vector.get_scatter_of_mem — an index carried with one value takes that value.

Implementation notes

The determinacy condition covers a list of constant value and a list of distinct indices alike, neither paying for the other's hypothesis. Both lemmas quantify over the starting vector, so they apply part-way through a pass as well as at its start.

Tags

vector, scatter, fold, choice-free

@[expose] public sectionuniverse unamespace Vector

One pass writing each pair's value into the vector at the pair's index.

def scatter {α : Type u} {n : Nat} (P : List (Fin n × α)) (v : Vector α n) : Vector α n := P.foldl (fun w p w.set p.1.val p.2 p.1.isLt) v

The pass leaves untouched every index no pair carries.

theorem get_scatter_of_not_mem {α : Type u} {n : Nat} (P : List (Fin n × α)) (v : Vector α n) (j : Fin n) (hj : j P.map Prod.fst) : (scatter P v).get j = v.get j := P.rec (motive := fun P (v : Vector α n), j P.map Prod.fst (scatter P v).get j = v.get j) (fun _ _ rfl) (fun p P ih v hj α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin nhj✝:¬j List.map Prod.fst P✝p:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), ¬j List.map Prod.fst P (scatter P v).get j = v.get jv:Vector α nhj:¬j List.map Prod.fst (p :: P)(scatter (p :: P) v).get j = v.get j α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin nhj✝:¬j List.map Prod.fst P✝p:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), ¬j List.map Prod.fst P (scatter P v).get j = v.get jv:Vector α nhj:¬j = p.fst ¬j List.map Prod.fst P(scatter (p :: P) v).get j = v.get j α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin nhj✝:¬j List.map Prod.fst P✝p:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), ¬j List.map Prod.fst P (scatter P v).get j = v.get jv:Vector α nhj:¬j = p.fst ¬j List.map Prod.fst P(v.set (↑p.fst) p.snd ).get j = v.get j α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin nhj✝:¬j List.map Prod.fst P✝p:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), ¬j List.map Prod.fst P (scatter P v).get j = v.get jv:Vector α nhj:¬j = p.fst ¬j List.map Prod.fst P(v.set (↑p.fst) p.snd )[j] = v[j] All goals completed! 🐙) v hj

The pass writes the value of a pair whose index no other pair carries with a different value.

theorem get_scatter_of_mem {α : Type u} {n : Nat} (P : List (Fin n × α)) (v : Vector α n) (j : Fin n) (a : α) (hm : (j, a) P) (hu : b, (j, b) P b = a) : (scatter P v).get j = a := P.rec (motive := fun P (v : Vector α n), (j, a) P ( b, (j, b) P b = a) (scatter P v).get j = a) (fun _ hm _ absurd hm List.not_mem_nil) (fun p P ih v hm hu α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = a(scatter (p :: P) v).get j = a α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = ahjP:j List.map Prod.fst P(scatter (p :: P) v).get j = aα:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = ahjP:¬j List.map Prod.fst P(scatter (p :: P) v).get j = a α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = ahjP:j List.map Prod.fst P(scatter (p :: P) v).get j = a α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = ahjP:j List.map Prod.fst Pq:Fin n × αhq:q Phqj:q.fst = j(scatter (p :: P) v).get j = a α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = ahjP:j List.map Prod.fst Pq:Fin n × αhq:q Phqj:q.fst = jhq':(j, q.snd) P(scatter (p :: P) v).get j = a All goals completed! 🐙 α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = ahjP:¬j List.map Prod.fst P(scatter (p :: P) v).get j = a α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = ahjP:¬j List.map Prod.fst Phe:(j, a) = p(scatter (p :: P) v).get j = aα:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = ahjP:¬j List.map Prod.fst PhmP:(j, a) P(scatter (p :: P) v).get j = a α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = ahjP:¬j List.map Prod.fst Phe:(j, a) = p(scatter (p :: P) v).get j = a α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = aP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhjP:¬j List.map Prod.fst Phm:(j, a) (j, a) :: Phu: (b : α), (j, b) (j, a) :: P b = a(scatter ((j, a) :: P) v).get j = a α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = aP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhjP:¬j List.map Prod.fst Phm:(j, a) (j, a) :: Phu: (b : α), (j, b) (j, a) :: P b = a(v.set (↑j) a ).get j = a α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = aP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhjP:¬j List.map Prod.fst Phm:(j, a) (j, a) :: Phu: (b : α), (j, b) (j, a) :: P b = a(v.set (↑j) a )[j] = a All goals completed! 🐙 α:Type un:NatP✝:List (Fin n × α)v✝:Vector α nj:Fin na:αhm✝:(j, a) P✝hu✝: (b : α), (j, b) P✝ b = ap:Fin n × αP:List (Fin n × α)ih: (v : Vector α n), (j, a) P (∀ (b : α), (j, b) P b = a) (scatter P v).get j = av:Vector α nhm:(j, a) p :: Phu: (b : α), (j, b) p :: P b = ahjP:¬j List.map Prod.fst PhmP:(j, a) P(scatter (p :: P) v).get j = a All goals completed! 🐙) v hm hu
end Vector