1-- Finite windows of coefficient functions and their indexed list values (ZF).2-- 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.Algebra.CoefficientLists8import Coefficients9import Nat.Order1011def listHeadOr {A : Set} (z : Set) (xs : List(A)) →Set12| z, List.nil => z13| z, List.cons(a, tail) => a1415def listTail {A : Set} (xs : List(A)) →Set16| List.nil => []17| List.cons(a, tail) => tail1819def listCoefficient {A : Set} (z : Set) (xs : List(A)) (n : Nat) →Set20| z, xs, zero => listHeadOr{A}(z, xs)21| z, xs, succ(k) => listCoefficient{A}(z, listTail{A}(xs), k)22descends n2324def coefficientWindow (f : Set, start n : Nat) →Set25| f, start, zero => []26| f, start, succ(k) => f(start) :: coefficientWindow(f, succ(start), k)27descends n2829def listMap {A : Set} (f : Set) (xs : List(A)) →Set30| f, List.nil => []31| f, List.cons(a, tail) => f(a) :: listMap(f, tail)32descends xs3334theorem listTail.closed (A : Set) (xs : List(A))35shows List(A, listTail{A}(xs))36proof37induction xs38| List.nil =>39rw listTail40typecheck41| List.cons(a, tail) using ih =>42 rwa listTail4344theorem listCoefficient.nil (A z : Set, n : Nat)45shows listCoefficient{A}(z, [], n) = z46proof47induction n48| zero =>49rw [listCoefficient, listHeadOr]50rfl51| succ(k) using ih =>52rw [listCoefficient, listTail]53exact ih5455theorem listCoefficient.zero (A z a : Set) (xs : List(A))56requires element : a ∈ A57shows listCoefficient{A}(z, a :: xs, 0) = a58proof59rw [listCoefficient, listHeadOr]60rfl6162theorem listCoefficient.succ (A z a : Set) (xs : List(A)) (n : Nat)63requires element : a ∈ A64shows listCoefficient{A}(z, a :: xs, succ(n)) = listCoefficient{A}(z, xs, n)65proof66rw [listCoefficient, listTail]67rfl6869theorem listMap.closed (A B f : Set) (xs : List(A))70requires function : f : A → B71shows List(B, listMap{A}(f, xs))72proof73induction xs74| List.nil =>75rw listMap76typecheck77| List.cons(a, tail) using ih =>78have element : a ∈ A byassumption79have image := FunctionBetween.apply_closed with function, element80rw listMap81typecheck8283theorem listMap.compose (A B C f g : Set) (xs : List(A))84requires first : f : A → B85requires second : g : B → C86shows listMap{B}(g, listMap{A}(f, xs)) = listMap{A}(compose(g, f, A, B, C), xs)87proof88induction xs89| List.nil =>simp [listMap]90| List.cons(a, tail) using ih =>91have member : a ∈ A byassumption92have image := FunctionBetween.apply_closed with first, member93have value := compose.apply at g, f, A, B, C, a with*94simp [listMap, ih, value]9596theorem listMap.length (A B f : Set) (xs : List(A))97requires function : f : A → B98shows length{B}(listMap{A}(f, xs)) = length{A}(xs)99proof100induction xs101| List.nil =>102rw [listMap, length.nil, length.nil]103rfl104| List.cons(a, tail) using ih =>105have element : a ∈ A byassumption106have image := FunctionBetween.apply_closed with function, element107have mapped := listMap.closed with*108rw [listMap, length.cons, length.cons, ih]109rfl110111theorem listCoefficient.map (A B f z : Set) (xs : List(A)) (n : Nat)112requires function : f : A → B113requires default : z ∈ A114shows listCoefficient{B}(f(z), listMap{A}(f, xs), n) = f(listCoefficient{A}(z, xs, n))115proof116induction xs generalizing n117| List.nil =>118intros n natural119rw [listMap, listCoefficient.nil, listCoefficient.nil]120rfl121| List.cons(a, tail) using ih =>122intros n natural123have element : a ∈ A byassumption124have mapped := FunctionBetween.apply_closed with function, element125have tailList := listMap.closed with*126have shape := natural.zero_or_successor with*127cases shape with zero | successor128 . rw [zero, listMap, listCoefficient.zero, listCoefficient.zero]129rfl130 . obtain⟨k, kNat, equal⟩:= successor131rw [equal, listMap, listCoefficient.succ, listCoefficient.succ]132exact ih with k, kNat133134theorem listMap.congr_coefficients (A z f g : Set) (xs : List(A))135requires agreement : ∀ n, Nat(n) → f(listCoefficient{A}(z, xs, n)) = g(listCoefficient{A}(z, xs, n))136shows listMap{A}(f, xs) = listMap{A}(g, xs)137proof138induction xs139| List.nil =>140intro agreement141rw [listMap, listMap]142rfl143| List.cons(a, tail) using ih =>144intro agreement145have element : a ∈ A byassumption146have head := agreement with0, Naturals.constructor.zero147rw listCoefficient.zero at head148have rest : ∀ n, Nat(n) → f(listCoefficient{A}(z, tail, n)) = g(listCoefficient{A}(z, tail, n))149intros n natural150have value := agreement with succ(n)151 rwa listCoefficient.succ at value152have equal := ih with rest153rw [listMap, listMap]154cc155156theorem coefficientWindow.closed (A f : Set, start n : Nat)157requires function : f : ℕ → A158shows List(A, coefficientWindow(f, start, n))159proof160induction n generalizing start161| zero =>162intros start startNat163rw coefficientWindow164typecheck165| succ(k) using ih =>166intros start startNat167have startIn := nat.omega.forward at start with*168have head := FunctionBetween.apply_closed with function, startIn169have tail := ih with succ(start)170rw coefficientWindow171typecheck172173theorem coefficientWindow.length (A f : Set, start n : Nat)174requires function : f : ℕ → A175shows length{A}(coefficientWindow(f, start, n)) = n176proof177induction n generalizing start178| zero =>179intros start startNat180rw [coefficientWindow, length.nil]181rfl182| succ(k) using ih =>183intros start startNat184have startIn := nat.omega.forward at start with*185have head := FunctionBetween.apply_closed with function, startIn186have tail := coefficientWindow.closed at A, f, succ(start), k with*187have length := ih with succ(start)188rw [coefficientWindow, length.cons, length]189rfl190191theorem coefficientWindow.coefficient (A z f : Set, start n k : Nat)192requires function : f : ℕ → A193requires bound : k < n194shows listCoefficient{A}(z, coefficientWindow(f, start, n), k) = f(start + k)195proof196induction n generalizing start k197| zero =>198intros start k startNat kNat bound199have impossible : 0 < 0byarith200exfalso201have irreflexive := Less.irreflexive with Naturals.constructor.zero202exact irreflexive with impossible203| succ(t) using ih =>204intros start k startNat kNat bound205have startIn := nat.omega.forward at start with*206have head := FunctionBetween.apply_closed with function, startIn207have tail := coefficientWindow.closed at A, f, succ(start), t with*208have shape := natural.zero_or_successor at k with*209cases shape with zero | successor210 . rw [zero, coefficientWindow, listCoefficient.zero, add.right_unit]211rfl212 . obtain⟨r, rNat, equal⟩:= successor213have smaller : r < t byarith214have result := ih with succ(start), r, rNat, smaller215have shift : succ(start) + r = start + succ(r) bysimp [add, add.succ_right]216rw [equal, coefficientWindow, listCoefficient.succ, result, shift]217rfl218219theorem listCoefficient.outside (A z : Set) (xs : List(A)) (n : Nat)220requires bound : length{A}(xs) ≤ n221shows listCoefficient{A}(z, xs, n) = z222proof223induction xs generalizing n224| List.nil =>225intros n nNat bound226exact listCoefficient.nil with*227| List.cons(a, tail) using ih =>228intros n nNat bound229have element : a ∈ A byassumption230rw length.cons at bound231have shape := natural.zero_or_successor with*232cases shape with zero | successor233 . have impossible : 0 < 0234arith235exfalso236have irreflexive := Less.irreflexive with Naturals.constructor.zero237exact irreflexive with impossible238 . obtain⟨r, rNat, equal⟩:= successor239have smaller : length{A}(tail) ≤ r byarith240have result := ih with r, rNat, smaller241 rwa [equal, listCoefficient.succ]242243-- Every finitely supported natural-indexed function is represented by a finite list.244theorem CoefficientMap.list_representation (A z f : Set)245requires map : CoefficientMap(f, ℕ, A, z)246shows∃ cs, List(A, cs) ∧ (∀ k, Nat(k) → listCoefficient{A}(z, cs, k) = f(k))247proof248have function := CoefficientMap.function with map249have finite := CoefficientMap.finite_support with map250have domain := functionSupport.subset at f, ℕ, z251obtain⟨b, bNat, bound⟩:= Finite.naturals_bounded with domain, finite252have list := coefficientWindow.closed at A, f, 0, succ(b) with*253refine⟨coefficientWindow(f, 0, succ(b)), list, ?_⟩254intros k kNat255have alternatives : k < succ(b) ∨¬(k < succ(b)) bytauto256cases alternatives with inside | outside257 . have value := coefficientWindow.coefficient at A, z, f, 0, succ(b), k with*258have equal := add.left_unit at k with*259 rwa equal at value260 . have absent : ¬(k ∈ functionSupport(f, ℕ, z))261intro supported262have member := bound with k, supported263have smaller := Less.of_membership at k, succ(b) with*264have less := smaller with member265exact outside with less266have kIn := nat.omega.forward at k with*267have vanishes := functionSupport.outside at f, ℕ, z, k with*268have length := coefficientWindow.length at A, f, 0, succ(b) with*269have enough : length{A}(coefficientWindow(f, 0, succ(b))) ≤ k270rw length271exact LessEqual.of_not_Less with*272have value := listCoefficient.outside at A, z, coefficientWindow(f, 0, succ(b)), k with*273cc274