TorchLean API

NN.Spec.Models.Hopfield

Hopfield networks (spec-level) #

This file gives a Hopfield network model as a set of explicit mathematical definitions.

Intended use: mathematical scalars (, , etc.) and theorem statements/proofs. For computation, instantiate α := ℚ (or Rat) and evaluate seqStates / energy via #eval in an example file.

Note: we also provide Tensor-shaped wrappers (StateT, ParamsT) so users can work with Tensor _ (.dim n .scalar) instead of raw Fin n → _.

References #

Relationship to the Hopfield formalization case study #

This file provides the definitions (update rule, energy, trajectories). The global-dynamics results (energy monotonicity, fixed-point convergence bounds, tie-handling lemmas, etc.) are proved in NN/MLTheory/Proofs/Hopfield/* against these definitions.

If you’re reading this alongside “Formalized Hopfield Networks and Boltzmann Machines” (2025), the correspondence is:

Core data #

def Spec.Hopfield.act {α : Type} [One α] [Neg α] :
Boolα

Boolean activations interpreted as ±1.

We intentionally store Hopfield states as Bool (instead of α) because many proofs are simpler when the only possible activations are +1 and -1. The embedding into a numeric scalar α is explicit via act.

Instances For
    @[simp]
    theorem Spec.Hopfield.act_true {α : Type} [One α] [Neg α] :
    @[simp]
    theorem Spec.Hopfield.act_false {α : Type} [One α] [Neg α] :
    @[reducible, inline]

    Hopfield state as a Boolean activation vector.

    Instances For
      @[reducible, inline]

      Hopfield state as a vector tensor Tensor Bool (.dim n .scalar).

      This is a convenience wrapper so Hopfield models can interoperate with the rest of TorchLean's tensor-shaped spec APIs.

      Instances For

        Convert a tensor state to the underlying function representation.

        Instances For

          Convert a function state to a tensor state.

          Instances For
            @[simp]
            theorem Spec.Hopfield.StateT.toFun_ofFun {n : } (s : State n) :
            (ofFun s).toFun = s
            @[simp]
            def Spec.Hopfield.actVec {α : Type} [One α] [Neg α] {n : } (s : State n) :
            Fin nα

            The ±1 activation vector associated to a Boolean state.

            Instances For
              def Spec.Hopfield.dot {α : Type} [AddCommMonoid α] [Mul α] {n : } (x y : Fin nα) :
              α

              Dot product on vectors indexed by Fin n.

              We define this directly as a Fin-indexed sum. This keeps the model independent from any concrete matrix representation.

              Instances For
                def Spec.Hopfield.mulVec {α : Type} [AddCommMonoid α] [Mul α] {n : } (W : Fin nFin nα) (x : Fin nα) :
                Fin nα

                Matrix-vector product (as a function, not an array-backed matrix).

                Instances For
                  structure Spec.Hopfield.Params (α : Type) (n : ) :

                  Hopfield parameters:

                  • W is the weight matrix
                  • θ is the per-unit threshold / bias

                  Classic convergence results typically assume W is symmetric and has a zero diagonal. Those assumptions are not baked into this structure; they are stated and proved where needed.

                  • W : Fin nFin nα

                    W.

                  • θ : Fin nα
                  Instances For
                    structure Spec.Hopfield.ParamsT (α : Type) (n : ) :

                    Hopfield parameters as tensor-shaped weights and thresholds.

                    Instances For
                      def Spec.Hopfield.ParamsT.toFun {α : Type} {n : } (p : ParamsT α n) :
                      Params α n

                      Convert tensor-shaped parameters to the function representation.

                      Instances For

                        Hopfield update dynamics #

                        def Spec.Hopfield.net {α : Type} [AddCommMonoid α] [Mul α] [One α] [Neg α] {n : } (p : Params α n) (s : State n) (u : Fin n) :
                        α

                        Net input to unit u: (W * x)_u, where x = actVec s is the ±1 encoding of the state.

                        Instances For
                          def Spec.Hopfield.netT {α : Type} [AddCommMonoid α] [Mul α] [One α] [Neg α] {n : } (p : ParamsT α n) (s : StateT n) (u : Fin n) :
                          α

                          Tensor-shaped wrapper for net (useful for interop with TorchLean tensor APIs).

                          Instances For
                            def Spec.Hopfield.updateAt {α : Type} [AddCommMonoid α] [Mul α] [One α] [Neg α] [LE α] [DecidableRel fun (x1 x2 : α) => x1 x2] {n : } (p : Params α n) (s : State n) (u : Fin n) :

                            Asynchronous update at a single coordinate u.

                            We implement the standard thresholded sign rule:

                            s[u] := (θ_u ≤ net_u)

                            Interpreting true ↦ +1 and false ↦ -1, this corresponds to:

                            x_u := +1 if net_u ≥ θ_u, otherwise x_u := -1.

                            Tie-handling (net_u = θ_u) matters for formal convergence arguments; we pick the convention "ties go to +1" via .

                            Instances For
                              def Spec.Hopfield.updateAtT {α : Type} [AddCommMonoid α] [Mul α] [One α] [Neg α] [LE α] [DecidableRel fun (x1 x2 : α) => x1 x2] {n : } (p : ParamsT α n) (s : StateT n) (u : Fin n) :

                              Tensor-shaped wrapper for updateAt.

                              Instances For
                                def Spec.Hopfield.IsStable {α : Type} [AddCommMonoid α] [Mul α] [One α] [Neg α] [LE α] [DecidableRel fun (x1 x2 : α) => x1 x2] {n : } (p : Params α n) (s : State n) :

                                A state is stable (a fixed point) if updating any single coordinate does nothing.

                                Instances For
                                  def Spec.Hopfield.pluses {n : } (s : State n) :

                                  Count how many units are in the true (+1) state.

                                  Instances For

                                    Hopfield energy #

                                    def Spec.Hopfield.energy {α : Type} [Field α] {n : } (p : Params α n) (s : State n) :
                                    α

                                    The classical Hopfield energy for a state s (quadratic term + linear threshold term).

                                    With x = actVec s the ±1 encoding, the energy is:

                                    E(s) = -1/2 * Σ_i Σ_j W_ij x_i x_j + Σ_i θ_i x_i.

                                    When W is symmetric and has a zero diagonal, asynchronous updates are known to monotonically decrease (or not increase) E, which is the classic Lyapunov-style argument for convergence.

                                    Instances For
                                      def Spec.Hopfield.energyT {α : Type} [Field α] {n : } (p : ParamsT α n) (s : StateT n) :
                                      α

                                      Tensor-shaped wrapper for energy.

                                      Instances For
                                        def Spec.Hopfield.seqStates {α : Type} [AddCommMonoid α] [Mul α] [One α] [Neg α] [LE α] [DecidableRel fun (x1 x2 : α) => x1 x2] {n : } (p : Params α n) (useq : Fin n) (s0 : State n) :
                                        State n

                                        State sequence induced by an asynchronous update schedule useq.

                                        useq : NatFin n picks which coordinate to update at each discrete time step.

                                        PyTorch analogy: there is no direct equivalent in typical NN libraries, but you can think of it as an explicit, deterministic "update schedule" for coordinate descent.

                                        Instances For
                                          def Spec.Hopfield.seqStatesT {α : Type} [AddCommMonoid α] [Mul α] [One α] [Neg α] [LE α] [DecidableRel fun (x1 x2 : α) => x1 x2] {n : } (p : ParamsT α n) (useq : Fin n) (s0 : StateT n) :
                                          StateT n

                                          Tensor-shaped wrapper for seqStates.

                                          Instances For
                                            def Spec.Hopfield.cyclicUseq (n : ) (hn : 0 < n) :
                                            Fin n

                                            A cyclic update schedule (0,1,2,...,n-1,0,1,...) for n > 0.

                                            Instances For

                                              Executable Hopfield (backend-friendly) #

                                              The definitions above (net, energy, …) are written in a math-first style using over Fin n. That is the right presentation for proofs, but it bakes in algebraic typeclasses like AddCommMonoid and uses Finset sums.

                                              When we execute Hopfield over IEEE-like scalars (e.g. Float, IEEE32Exec), we do not want to pretend those algebraic laws hold exactly: NaNs and rounding make addition non-associative and non-commutative in general. So for runtime execution we provide a “plain loop” variant that:

                                              This is the same model, just written in a way that stays honest about runtime arithmetic.

                                              References:

                                              @[inline]
                                              def Spec.Hopfield.Exec.act {α : Type} [Context α] :
                                              Boolα
                                              Instances For
                                                @[inline]
                                                def Spec.Hopfield.Exec.theta {α : Type} {n : } (p : ParamsT α n) (i : Fin n) :
                                                α
                                                Instances For
                                                  @[inline]
                                                  def Spec.Hopfield.Exec.weight {α : Type} {n : } (p : ParamsT α n) (i j : Fin n) :
                                                  α
                                                  Instances For
                                                    def Spec.Hopfield.Exec.net {α : Type} [Context α] {n : } (p : ParamsT α n) (s : StateT n) (u : Fin n) :
                                                    α

                                                    Net input to unit u computed by explicit iteration.

                                                    This matches Hopfield.netT, but avoids Finset sums so it can execute over IEEE-like scalars.

                                                    Instances For
                                                      def Spec.Hopfield.Exec.updateAt {α : Type} [Context α] [DecidableRel fun (x1 x2 : α) => x1 x2] {n : } (p : ParamsT α n) (s : StateT n) (u : Fin n) :

                                                      Asynchronous update of a single coordinate u, using the same “ties go to +1” convention as the spec definition (θ_u ≤ net_u).

                                                      Instances For
                                                        def Spec.Hopfield.Exec.seqStates {α : Type} [Context α] [DecidableRel fun (x1 x2 : α) => x1 x2] {n : } (p : ParamsT α n) (useq : Fin n) (s0 : StateT n) :
                                                        StateT n

                                                        State sequence induced by an update schedule useq : NatFin n (loop-based).

                                                        Instances For
                                                          def Spec.Hopfield.Exec.energy {α : Type} [Context α] {n : } (p : ParamsT α n) (s : StateT n) :
                                                          α

                                                          Hopfield energy computed by explicit iteration.

                                                          This matches the standard formula: E(s) = -1/2 * Σ_i Σ_j W_ij x_i x_j + Σ_i θ_i x_i, with x_i ∈ {+1,-1} obtained from the Boolean state.

                                                          Instances For