TorchLean API

NN.IR.OpContracts

Operation Contracts #

Shared operation contracts for NN.IR.Graph.

Several IR passes need to agree on the same small set of “shape contracts”:

The point of this file is to keep shape arithmetic out of individual passes. If an op has nontrivial shape behavior (concat, matmul, pooling, convolution, LayerNorm flattening, axis moves), define the contract here first and call it from inference/semantics instead of copying the formula.

Small shape utilities #

These helpers are used by multiple IR passes, especially Infer and Semantics.

The output shape of flattening a tensor of shape s to a 1D vector.

Shape inference and the reference semantics both use this definition. It is a simp lemma so that proofs about either pass see the concrete one-axis shape.

Instances For

    Generic contract helpers #

    These functions live outside any particular pass (Infer/Check/Semantics) so they can be reused without introducing import cycles.

    Check that an axis is in-bounds for a given shape.

    Instances For

      Validate the axis of an axis-dropping reduction (reduceSum, reduceMean).

      The typed reductions Tensor.reduceSum and Tensor.reduceMean require the reduced axis to have positive extent, so the shared IR rule is Spec.Shape.nonemptyAxis? rather than a bare rank check: an in-bounds axis of extent zero is rejected by both inference and evaluation. The result carries the evidence needed by the typed operation.

      This is a simp definition so proofs that already know the nonemptyAxis? verdict can reduce it.

      Instances For

        Check that a natural-number op parameter is nonzero.

        Instances For
          def NN.IR.OpContracts.transposePerm (rank axis₁ axis₂ : ℕ) :

          Axis permutation that swaps axis₁ and axis₂ and leaves every other axis fixed.

          Instances For

            Infer the shape obtained by swapping two arbitrary axes.

            Instances For

              Compute the matrix dimensions used to interpret layernorm axis.

              TorchLean’s IR stores LayerNorm as an axis : Nat instead of a full normalized_shape tuple. We interpret this in the same way the PyTorch exporter does:

              normalized_shape = dims.drop axis

              That is, we normalize over the suffix of dimensions starting at axis. To reuse the current spec primitive (Spec.layerNorm), we flatten the input shape s into a matrix:

              • the row count is the product of dimensions before axis (dims.take axis);
              • the column count is the product of dimensions from axis onward (dims.drop axis).

              LayerNorm then runs over each row and the result is reshaped to s. This construction works for every nonempty tensor rank. The normalized suffix must be nonempty; the leading batch may be empty.

              Instances For

                Compute the inverse of a permutation array.

                If perm is a permutation of [0,1,...,r-1] (where r = perm.length), then the inverse inv satisfies $\mathrm{inv}[\mathrm{perm}[i]]=i$.

                Instances For

                  Permutation (0-based axes) that moves axis to the last position, preserving the relative order of the other axes.

                  Example: rank four with axis set to 1 yields [0,2,3,1].

                  Instances For

                    Permutation (0-based axes) that moves axis to the first position, preserving the relative order of the other axes.

                    Example: rank four with axis set to 2 yields [2,0,1,3].

                    Instances For

                      Geometry of a matrix product after broadcasting batch axes and promoting vectors.

                      A left vector is viewed as a one-row matrix and a right vector as a one-column matrix. Their inserted axes are removed from the output; the original operand shapes are retained for validation and flat indexing.

                      • leading : Spec.Shape

                        Broadcast batch shape of the output.

                      • rows : ℕ

                        Row count of the left operand.

                      • inner : ℕ

                        Contracted extent shared by both operands.

                      • cols : ℕ

                        Column count of the right operand.

                      • leftShape : Spec.Shape

                        Original left operand shape.

                      • rightShape : Spec.Shape

                        Original right operand shape.

                      • leftLeading : Spec.Shape

                        Batch axes of the left operand, before broadcasting.

                      • rightLeading : Spec.Shape

                        Batch axes of the right operand, before broadcasting.

                      • leftVector : Bool

                        Whether the left operand was promoted from a vector.

                      • rightVector : Bool

                        Whether the right operand was promoted from a vector.

                      Instances For

                        Shape of the matmul result.

                        Instances For

                          Project a flat output batch coordinate to one operand's unbroadcast batch coordinate.

                          Instances For

                            Left scalar used by one output coordinate and one contraction coordinate.

                            Instances For

                              Right scalar used by one output coordinate and one contraction coordinate.

                              Instances For

                                Broadcast reversed batch dimensions, aligning from the trailing axis. Singleton axes also broadcast to zero; using max here would incorrectly turn zero into one.

                                Instances For

                                  Infer vector promotion and trailing-axis batch broadcasting for non-scalar operands.

                                  Instances For

                                    Infer the output shape for matmul from the two parent shapes (see matmulDims).

                                    Instances For

                                      A successful decomposition determines the operand shapes it was computed from.

                                      Merge one concat input into the accumulated dimensions.

                                      Instances For

                                        Fold compatible concat inputs into the accumulated output dimensions.

                                        Instances For

                                          Infer the output shape for concat from an array of parent shapes.

                                          Every parent must have the same rank, the selected axis must exist, and all dimensions other than that axis must agree. The selected dimensions are summed. Both the axis and the tensor rank are arbitrary.

                                          Instances For

                                            Sliding-window shape arithmetic #

                                            Convolution and pooling preserve a leading channel axis, but their admissible padding domains are not identical. The contracts below share validation and traversal while retaining the correct output formula for each operation family.

                                            def NN.IR.OpContracts.inferConvDims (tag : String) (axisNames : List String) (inputs kernels strides dilations paddingBefore paddingAfter : List ℕ) :

                                            Infer dilated convolution dimensions from one parameter per spatial axis.

                                            Instances For
                                              def NN.IR.OpContracts.inferPoolingDims (tag : String) (axisNames : List String) (inputs kernels strides paddings : List ℕ) :

                                              Infer pooling output lengths while enforcing the same basic window checks as graph validation.

                                              Pooling uses poolOutDim, which assigns an empty output to an empty input axis, an oversized window, or padding outside the pooling domain. Kernels and strides must still be positive.

                                              Instances For
                                                structure NN.IR.OpContracts.PoolPlan (config : WindowConfig) (parent : Spec.Shape) :

                                                Validated shape information for pooling over a tensor suffix.

                                                The plan is the common boundary between shape inference, denotational evaluation, and executable lowering. It carries the exact split and positivity evidence required by the typed pooling operators, so those passes cannot silently disagree about which axes are spatial.

                                                Instances For
                                                  def NN.IR.OpContracts.PoolPlan.outShape {config : WindowConfig} {parent : Spec.Shape} (plan : PoolPlan config parent) :

                                                  Output shape computed by a validated pooling plan.

                                                  Instances For
                                                    def NN.IR.OpContracts.planPool (tag : String) (config : WindowConfig) (parent : Spec.Shape) :
                                                    Except String (PoolPlan config parent)

                                                    Validate and plan pooling over a spatial suffix of arbitrary rank.

                                                    Every preceding axis is preserved, so one operation handles unbatched tensors, ordinary batches, and tensors with several leading batch dimensions.

                                                    Instances For

                                                      Infer the output shape of an arbitrary-rank pooling operation from its window geometry.

                                                      This is the shape rule shared by Infer.nodeOutShape and the reference semantics: both call planPool on the same configuration, so the evaluator's pooled tensor has exactly this shape.

                                                      Instances For
                                                        def NN.IR.OpContracts.inferPoolOutShape (tag : String) {spatialRank : ℕ} (kernels strides paddings : TorchLean.Tensor ℕ [spatialRank]) (parent : Spec.Shape) :

                                                        Infer the output shape of an arbitrary-rank pooling operation.

                                                        Instances For

                                                          Infer the output shape for the full parameterized convolution configuration.

                                                          Instances For
                                                            def NN.IR.OpContracts.inferConvOutShape (tag : String) (channelAxis inChannels outChannels : ℕ) {spatialRank : ℕ} (kernels strides paddings : TorchLean.Tensor ℕ [spatialRank]) (parent : Spec.Shape) :

                                                            Infer dense, unit-dilation convolution output geometry for an arbitrary spatial rank.

                                                            This is the ordinary convolution specialization of inferConvConfigOutShape; keeping one checker prevents the default and parameterized APIs from assigning different shapes to the same operation.

                                                            Instances For

                                                              Check eval-mode BatchNorm metadata against an arbitrary channel axis.

                                                              Instances For