TorchLean API

NN.Proofs.Autograd.Tape.Ops.Conv.Index

Convolution Index Arithmetic #

The forward and transpose convolution loops describe the same integer relation from opposite directions. This file proves that relation once for an arbitrary list of spatial axes. The only geometric hypothesis is the standard one that every stride is positive.

Finite spatial indices #

@[reducible, inline]

A shape-indexed spatial coordinate, represented without partial list indexing.

Instances For
    @[instance_reducible]
    @[instance_reducible]

    Convert a bounded spatial coordinate to the runtime list representation.

    Instances For

      Read a tensor at a bounded spatial coordinate.

      Instances For
        @[simp]
        theorem Spec.Conv.Internal.MultiIndex.get_dim {α : Type} [TorchLean.Storage α] (n : ) (dims : List ) (values : Fin nTorchLean.Tensor α (Shape.ofList dims)) (head : Fin n) (tail : MultiIndex dims) :
        get (TorchLean.Tensor.dim values) (head, tail) = get (values head) tail

        Reading a dim tensor peels the leading coordinate and recurses into that slice.

        @[simp]

        Reading the sole scalar coordinate below a vector index agrees with the vector view.

        @[simp]
        theorem Spec.Conv.Internal.getAtOrZero_dim_nil {α : Type} [TorchLean.Storage α] [Zero α] (n : ) (dims : List ) (values : Fin nTorchLean.Tensor α (Shape.ofList dims)) :

        An index that runs out too early reads zero.

        theorem Spec.Conv.Internal.getAtOrZero_dim_cons {α : Type} [TorchLean.Storage α] [Zero α] (n : ) (dims : List ) (values : Fin nTorchLean.Tensor α (Shape.ofList dims)) (j : ) (js : List ) :
        getAtOrZero (TorchLean.Tensor.dim values) (j :: js) = if h : j < n then getAtOrZero (values j, h) js else 0

        Otherwise the leading coordinate is bounds-checked and the lookup recurses, reading zero when it falls outside. This total lookup is what lets padding be expressed without a separate case split at every use site: an out-of-range index simply contributes nothing.

        theorem Spec.Conv.Internal.MultiIndex.sum_cons {α : Type} [AddCommMonoid α] (n : ) (dims : List ) (f : MultiIndex (n :: dims)α) :
        i : MultiIndex (n :: dims), f i = head : Fin n, tail : MultiIndex dims, f (head, tail)

        Split a finite sum over a nonempty multi-index into its leading coordinate and tail.

        @[simp]

        Reading a generated tensor applies the generating function to the index's coordinate list.

        theorem Spec.Conv.Internal.MultiIndex.get_addSpec {α : Type} [TorchLean.Storage α] [Context α] {dims : List } (x y : TorchLean.Tensor α (Shape.ofList dims)) (i : MultiIndex dims) :
        get (x.addSpec y) i = get x i + get y i

        Bounded-coordinate lookup commutes with pointwise tensor addition.

        @[simp]

        On an in-range index the total lookup agrees with the bounded one.

        This is the lemma that connects the two indexing styles in the file: implementations use unbounded List Nat coordinates, specifications use MultiIndex, and inside the bounds they coincide.

        theorem Spec.Conv.Internal.getAtOrZero_eq_sum_indicator {α : Type} [TorchLean.Storage α] [AddCommMonoid α] (dims : List ) (x : TorchLean.Tensor α (Shape.ofList dims)) (indices : List ) :
        getAtOrZero x indices = i : MultiIndex dims, if indices = i.toList then MultiIndex.get x i else 0

        A total lookup is the finite coordinate sum selected by equality of index lists.

        This formulation handles valid indices, padding, and malformed or out-of-range lists uniformly.

        theorem Spec.Conv.Internal.foldlIndices_add {α : Type} [AddCommMonoid α] (dims : List ) (init : α) (f : List α) :
        (foldlIndices dims init fun (acc : α) (i : List ) => acc + f i) = init + i : MultiIndex dims, f i.toList

        The executable nested index fold is the finite sum over bounded coordinates.

        Recursive tensor dot product as a finite sum over bounded multi-indices.

        Every stride in a runtime list is positive.

        Instances For
          theorem Spec.Conv.Internal.mkTransposeInputIdx?_of_mkInputIdx?_eq_some {outIdx kIdx stride padding inIdx : List } (hStride : PositiveStrides stride) (hForward : mkInputIdx? outIdx kIdx stride padding = some inIdx) :
          mkTransposeInputIdx? inIdx kIdx stride padding = some outIdx

          Solving a forward convolution index and then solving backwards recovers the output index.

          theorem Spec.Conv.Internal.mkInputIdx?_of_mkTransposeInputIdx?_eq_some {inIdx kIdx stride padding outIdx : List } (hStride : PositiveStrides stride) (hTranspose : mkTransposeInputIdx? inIdx kIdx stride padding = some outIdx) :
          mkInputIdx? outIdx kIdx stride padding = some inIdx

          Solving a transpose convolution index and then solving forwards recovers the input index.

          theorem Spec.Conv.Internal.mkInputIdx?_eq_some_iff {outIdx kIdx stride padding inIdx : List } (hStride : PositiveStrides stride) :
          mkInputIdx? outIdx kIdx stride padding = some inIdx mkTransposeInputIdx? inIdx kIdx stride padding = some outIdx

          The two index solvers define the same relation when strides are positive.