TorchLean API

NN.Spec.Layers.SelectiveScan

Selective scan specs #

This file contains the small proof layer core behind state-space sequence models such as S4 and Mamba.

The key observation, used by Mamba's hardware-aware parallel scan, is that each per-token recurrent update can be viewed as an affine map

h ↦ A_t h + b_t.

Affine maps compose associatively. A recurrent scan can therefore be implemented either by a left-to-right recurrence or by a parallel prefix scan over affine summaries. The scalar definitions below are kept compact so that NN/MLTheory/Proofs/StateSpace/Scan.lean can prove the algebra without depending on a particular runtime backend. The diagonal tensor definitions are the direct TorchLean spec analogue used by the model and CUDA contracts.

References:

def Spec.scanArrayFrom {State Input Output : Type} (step : StateInputState × Output) (initial : State) (initialOutputs : Array Output) (xs : Array Input) :
State × Array Output

Run a stateful step over an array, appending each emitted value to initialOutputs.

The initial output buffer makes this suitable for chunked execution without changing the state transition being specified.

Instances For
    def Spec.scanArray {State Input Output : Type} (step : StateInputState × Output) (initial : State) (xs : Array Input) :
    State × Array Output

    Run a stateful step over an array and return the final state and emitted values.

    Instances For
      @[simp]
      theorem Spec.scanArray_empty {State Input Output : Type} (step : StateInputState × Output) (initial : State) :
      scanArray step initial #[] = (initial, #[])

      Scanning an empty array returns the initial state and no outputs.

      @[simp]
      theorem Spec.scanArray_outputs_size {State Input Output : Type} (step : StateInputState × Output) (initial : State) (xs : Array Input) :
      (scanArray step initial xs).2.size = xs.size

      A stateful scan emits exactly one value for each input.

      A scalar affine transition h ↦ a*h + b.

      • a : α

        Linear multiplier. In diagonal SSMs this is one channel of the discretized state matrix.

      • b : α

        Additive input contribution for the current token.

      Instances For
        @[instance_reducible]
        def Spec.ScalarAffineTransition.apply {α : Type} [Mul α] [Add α] (tr : ScalarAffineTransition α) (h : α) :
        α

        Apply a scalar affine transition.

        Instances For

          Identity affine transition.

          Instances For

            Compose two affine transitions.

            compose t₂ t₁ means "first apply t₁, then apply t₂".

            Instances For
              def Spec.runScalarAffine {α : Type} [Mul α] [Add α] (h0 : α) (transitions : Array (ScalarAffineTransition α)) :
              α

              Sequentially run scalar affine transitions from an initial state.

              Instances For

                Summarize an array of transitions as one affine transition.

                This is the algebraic payload used by parallel selective scan: prefix summaries can be produced by any associative scan algorithm, and applying the summary to h0 is equivalent to recurrence.

                Instances For
                  def Spec.scalarAffineScan {α : Type} [Mul α] [Add α] (h0 : α) :

                  Return every recurrent state after each scalar affine transition.

                  Instances For
                    @[simp]
                    theorem Spec.scalarAffineScan_size {α : Type} [Mul α] [Add α] (h0 : α) (transitions : Array (ScalarAffineTransition α)) :
                    (scalarAffineScan h0 transitions).size = transitions.size

                    The scalar affine scan has one state per transition.

                    structure Spec.DiagonalTransition (α : Type) [TorchLean.Storage α] (stateDim : ) :

                    A diagonal vector affine transition h ↦ a ⊙ h + b.

                    Instances For
                      def Spec.DiagonalTransition.apply {α : Type} [TorchLean.Storage α] [Add α] [Mul α] {stateDim : } (tr : DiagonalTransition α stateDim) (h : TorchLean.Tensor α [stateDim]) :
                      TorchLean.Tensor α [stateDim]

                      Apply one diagonal affine state update.

                      Instances For
                        def Spec.DiagonalTransition.compose {α : Type} [TorchLean.Storage α] [Add α] [Mul α] {stateDim : } (t₂ t₁ : DiagonalTransition α stateDim) :
                        DiagonalTransition α stateDim

                        Compose diagonal affine transitions channelwise.

                        The order is the same as ScalarAffineTransition.compose: compose t₂ t₁ is first t₁, then t₂.

                        Instances For
                          def Spec.runDiagonalTransitions {α : Type} [TorchLean.Storage α] [Add α] [Mul α] {stateDim : } (h0 : TorchLean.Tensor α [stateDim]) (transitions : Array (DiagonalTransition α stateDim)) :
                          TorchLean.Tensor α [stateDim]

                          Sequentially run diagonal transitions and return the final state.

                          Instances For
                            def Spec.diagonalSelectiveScan {α : Type} [TorchLean.Storage α] [Add α] [Mul α] {stateDim : } (h0 : TorchLean.Tensor α [stateDim]) :
                            Array (DiagonalTransition α stateDim)Array (TorchLean.Tensor α [stateDim])

                            Return every hidden state from a diagonal selective scan.

                            Instances For
                              @[simp]
                              theorem Spec.diagonalSelectiveScan_size {α : Type} [TorchLean.Storage α] [Add α] [Mul α] {stateDim : } (h0 : TorchLean.Tensor α [stateDim]) (transitions : Array (DiagonalTransition α stateDim)) :
                              (diagonalSelectiveScan h0 transitions).size = transitions.size

                              The diagonal selective scan has one state per transition.